From 4dd84ee030b401a28ad366d708f22a78e0907d70 Mon Sep 17 00:00:00 2001 From: Metabox Date: Mon, 13 May 2019 08:52:54 +1000 Subject: [PATCH] ... --- dbLifeLog/DBD-SQLite2-0.33.tar.gz | Bin 363277 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/Changes | 148 - dbLifeLog/DBD-SQLite2-0.33/MANIFEST | 79 - dbLifeLog/DBD-SQLite2-0.33/MANIFEST.SKIP | 20 - dbLifeLog/DBD-SQLite2-0.33/META.yml | 11 - dbLifeLog/DBD-SQLite2-0.33/MYMETA.json | 41 - dbLifeLog/DBD-SQLite2-0.33/MYMETA.yml | 22 - dbLifeLog/DBD-SQLite2-0.33/Makefile | 1122 --- dbLifeLog/DBD-SQLite2-0.33/Makefile.PL | 29 - dbLifeLog/DBD-SQLite2-0.33/README | 36 - dbLifeLog/DBD-SQLite2-0.33/SQLite2.bs | 0 dbLifeLog/DBD-SQLite2-0.33/SQLite2.c | 1630 ---- dbLifeLog/DBD-SQLite2-0.33/SQLite2.o | Bin 56064 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/SQLite2.xs | 69 - dbLifeLog/DBD-SQLite2-0.33/SQLite2.xsi | 804 -- dbLifeLog/DBD-SQLite2-0.33/SQLiteXS.h | 15 - dbLifeLog/DBD-SQLite2-0.33/attach.c | 311 - dbLifeLog/DBD-SQLite2-0.33/attach.o | Bin 7536 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/auth.c | 219 - dbLifeLog/DBD-SQLite2-0.33/auth.o | Bin 3472 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/blib/arch/.exists | 0 .../blib/arch/auto/DBD/SQLite2/.exists | 0 .../blib/arch/auto/DBD/SQLite2/SQLite2.so | Bin 415248 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/blib/bin/.exists | 0 .../DBD-SQLite2-0.33/blib/lib/DBD/.exists | 0 .../DBD-SQLite2-0.33/blib/lib/DBD/SQLite2.pm | 542 -- .../blib/lib/DBD/getsqlite.pl | 52 - .../blib/lib/auto/DBD/SQLite2/.exists | 0 dbLifeLog/DBD-SQLite2-0.33/blib/man1/.exists | 0 dbLifeLog/DBD-SQLite2-0.33/blib/man3/.exists | 0 .../blib/man3/DBD::SQLite2.3pm | 326 - .../DBD-SQLite2-0.33/blib/script/.exists | 0 dbLifeLog/DBD-SQLite2-0.33/btree.c | 3584 ------- dbLifeLog/DBD-SQLite2-0.33/btree.h | 156 - dbLifeLog/DBD-SQLite2-0.33/btree.o | Bin 43248 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/btree_rb.c | 1488 --- dbLifeLog/DBD-SQLite2-0.33/btree_rb.o | Bin 16752 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/build.c | 2156 ----- dbLifeLog/DBD-SQLite2-0.33/build.o | Bin 37824 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/copy.c | 110 - dbLifeLog/DBD-SQLite2-0.33/copy.o | Bin 4360 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/date.c | 875 -- dbLifeLog/DBD-SQLite2-0.33/date.o | Bin 22952 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/dbdimp.c | 990 -- dbLifeLog/DBD-SQLite2-0.33/dbdimp.h | 104 - dbLifeLog/DBD-SQLite2-0.33/dbdimp.o | Bin 55512 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/delete.c | 393 - dbLifeLog/DBD-SQLite2-0.33/delete.o | Bin 8848 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/encode.c | 254 - dbLifeLog/DBD-SQLite2-0.33/encode.o | Bin 2096 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/expr.c | 1662 ---- dbLifeLog/DBD-SQLite2-0.33/expr.o | Bin 35232 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/func.c | 658 -- dbLifeLog/DBD-SQLite2-0.33/func.o | Bin 14088 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/getsqlite.pl | 52 - dbLifeLog/DBD-SQLite2-0.33/hash.c | 356 - dbLifeLog/DBD-SQLite2-0.33/hash.h | 109 - dbLifeLog/DBD-SQLite2-0.33/hash.o | Bin 4808 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/insert.c | 919 -- dbLifeLog/DBD-SQLite2-0.33/insert.o | Bin 16792 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/lib/DBD/SQLite2.pm | 542 -- dbLifeLog/DBD-SQLite2-0.33/main.c | 1143 --- dbLifeLog/DBD-SQLite2-0.33/main.o | Bin 21184 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/opcodes.c | 140 - dbLifeLog/DBD-SQLite2-0.33/opcodes.h | 138 - dbLifeLog/DBD-SQLite2-0.33/opcodes.o | Bin 6808 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/os.c | 1845 ---- dbLifeLog/DBD-SQLite2-0.33/os.h | 191 - dbLifeLog/DBD-SQLite2-0.33/os.o | Bin 11920 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/pager.c | 2220 ----- dbLifeLog/DBD-SQLite2-0.33/pager.h | 107 - dbLifeLog/DBD-SQLite2-0.33/pager.o | Bin 19384 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/parse.c | 4035 -------- dbLifeLog/DBD-SQLite2-0.33/parse.h | 130 - dbLifeLog/DBD-SQLite2-0.33/parse.o | Bin 41056 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/pm_to_blib | 0 dbLifeLog/DBD-SQLite2-0.33/pragma.c | 712 -- dbLifeLog/DBD-SQLite2-0.33/pragma.o | Bin 17896 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/printf.c | 858 -- dbLifeLog/DBD-SQLite2-0.33/printf.o | Bin 15128 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/random.c | 97 - dbLifeLog/DBD-SQLite2-0.33/random.o | Bin 2456 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/select.c | 2434 ----- dbLifeLog/DBD-SQLite2-0.33/select.o | Bin 36376 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/sqlite.h | 868 -- dbLifeLog/DBD-SQLite2-0.33/sqliteInt.h | 1270 --- dbLifeLog/DBD-SQLite2-0.33/t/00basic.t | 8 - dbLifeLog/DBD-SQLite2-0.33/t/01logon.t | 10 - dbLifeLog/DBD-SQLite2-0.33/t/02cr_table.t | 16 - dbLifeLog/DBD-SQLite2-0.33/t/03insert.t | 15 - dbLifeLog/DBD-SQLite2-0.33/t/04select.t | 17 - dbLifeLog/DBD-SQLite2-0.33/t/05tran.t | 34 - dbLifeLog/DBD-SQLite2-0.33/t/06error.t | 20 - .../DBD-SQLite2-0.33/t/08create_function.t | 112 - .../DBD-SQLite2-0.33/t/09create_aggregate.t | 129 - dbLifeLog/DBD-SQLite2-0.33/t/10dsnlist.t | 82 - dbLifeLog/DBD-SQLite2-0.33/t/20createdrop.t | 82 - dbLifeLog/DBD-SQLite2-0.33/t/30insertfetch.t | 141 - dbLifeLog/DBD-SQLite2-0.33/t/40bindparam.t | 197 - dbLifeLog/DBD-SQLite2-0.33/t/40blobs.t | 168 - dbLifeLog/DBD-SQLite2-0.33/t/40listfields.t | 127 - dbLifeLog/DBD-SQLite2-0.33/t/40nulls.t | 104 - dbLifeLog/DBD-SQLite2-0.33/t/40numrows.t | 152 - dbLifeLog/DBD-SQLite2-0.33/t/50chopblanks.t | 149 - dbLifeLog/DBD-SQLite2-0.33/t/50commit.t | 219 - dbLifeLog/DBD-SQLite2-0.33/t/60metadata.t | 46 - dbLifeLog/DBD-SQLite2-0.33/t/90cppcomments.t | 23 - dbLifeLog/DBD-SQLite2-0.33/t/99cleanup.t | 6 - dbLifeLog/DBD-SQLite2-0.33/t/SQLite2.dbtest | 134 - dbLifeLog/DBD-SQLite2-0.33/t/ak-dbd.t | 354 - dbLifeLog/DBD-SQLite2-0.33/t/dbdadmin.t | 211 - dbLifeLog/DBD-SQLite2-0.33/t/lib.pl | 255 - dbLifeLog/DBD-SQLite2-0.33/table.c | 203 - dbLifeLog/DBD-SQLite2-0.33/table.o | Bin 4032 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/tokenize.c | 679 -- dbLifeLog/DBD-SQLite2-0.33/tokenize.o | Bin 19272 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/trigger.c | 764 -- dbLifeLog/DBD-SQLite2-0.33/trigger.o | Bin 15368 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/update.c | 459 - dbLifeLog/DBD-SQLite2-0.33/update.o | Bin 9952 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/util.c | 1135 --- dbLifeLog/DBD-SQLite2-0.33/util.o | Bin 15320 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/vacuum.c | 327 - dbLifeLog/DBD-SQLite2-0.33/vacuum.o | Bin 8768 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/vdbe.c | 4917 ---------- dbLifeLog/DBD-SQLite2-0.33/vdbe.h | 112 - dbLifeLog/DBD-SQLite2-0.33/vdbe.o | Bin 42768 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/vdbeInt.h | 303 - dbLifeLog/DBD-SQLite2-0.33/vdbeaux.c | 1061 --- dbLifeLog/DBD-SQLite2-0.33/vdbeaux.o | Bin 15944 -> 0 bytes dbLifeLog/DBD-SQLite2-0.33/where.c | 1235 --- dbLifeLog/DBD-SQLite2-0.33/where.o | Bin 18600 -> 0 bytes dbLifeLog/DBI-1.641.readme | 93 - dbLifeLog/DBI-1.641.tar.gz | Bin 603947 -> 0 bytes dbLifeLog/DBI-1.641/Changes | 2584 ----- dbLifeLog/DBI-1.641/DBI.bs | 0 dbLifeLog/DBI-1.641/DBI.c | 6692 ------------- dbLifeLog/DBI-1.641/DBI.o | Bin 755272 -> 0 bytes dbLifeLog/DBI-1.641/DBI.pm | 8435 ----------------- dbLifeLog/DBI-1.641/DBI.xs | 5706 ----------- dbLifeLog/DBI-1.641/DBIXS.h | 573 -- dbLifeLog/DBI-1.641/Driver.xst | 804 -- dbLifeLog/DBI-1.641/Driver_xst.h | 122 - dbLifeLog/DBI-1.641/INSTALL | 46 - dbLifeLog/DBI-1.641/LICENSE | 412 - dbLifeLog/DBI-1.641/MANIFEST | 125 - dbLifeLog/DBI-1.641/META.json | 71 - dbLifeLog/DBI-1.641/META.yml | 45 - dbLifeLog/DBI-1.641/MYMETA.json | 71 - dbLifeLog/DBI-1.641/MYMETA.yml | 45 - dbLifeLog/DBI-1.641/Makefile | 1594 ---- dbLifeLog/DBI-1.641/Makefile.PL | 361 - dbLifeLog/DBI-1.641/Perl.c | 1541 --- dbLifeLog/DBI-1.641/Perl.o | Bin 215968 -> 0 bytes dbLifeLog/DBI-1.641/Perl.xs | 54 - dbLifeLog/DBI-1.641/Perl.xsi | 804 -- dbLifeLog/DBI-1.641/README.md | 93 - dbLifeLog/DBI-1.641/blib/arch/.exists | 0 .../DBI-1.641/blib/arch/auto/DBI/.exists | 0 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/DBI.so | Bin 499344 -> 0 bytes .../DBI-1.641/blib/arch/auto/DBI/DBIXS.h | 573 -- .../DBI-1.641/blib/arch/auto/DBI/Driver.xst | 804 -- .../DBI-1.641/blib/arch/auto/DBI/Driver_xst.h | 122 - .../DBI-1.641/blib/arch/auto/DBI/dbd_xsh.h | 61 - .../DBI-1.641/blib/arch/auto/DBI/dbi_sql.h | 96 - .../DBI-1.641/blib/arch/auto/DBI/dbipport.h | 7748 --------------- .../DBI-1.641/blib/arch/auto/DBI/dbivport.h | 52 - .../DBI-1.641/blib/arch/auto/DBI/dbixs_rev.h | 3 - dbLifeLog/DBI-1.641/blib/bin/.exists | 0 dbLifeLog/DBI-1.641/blib/lib/.exists | 0 dbLifeLog/DBI-1.641/blib/lib/Bundle/DBI.pm | 52 - dbLifeLog/DBI-1.641/blib/lib/DBD/DBM.pm | 1454 --- dbLifeLog/DBI-1.641/blib/lib/DBD/ExampleP.pm | 435 - dbLifeLog/DBI-1.641/blib/lib/DBD/File.pm | 1449 --- .../blib/lib/DBD/File/Developers.pod | 665 -- .../DBI-1.641/blib/lib/DBD/File/HowTo.pod | 191 - .../DBI-1.641/blib/lib/DBD/File/Roadmap.pod | 176 - dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer.pm | 1292 --- .../blib/lib/DBD/Gofer/Policy/Base.pm | 162 - .../blib/lib/DBD/Gofer/Policy/classic.pm | 79 - .../blib/lib/DBD/Gofer/Policy/pedantic.pm | 53 - .../blib/lib/DBD/Gofer/Policy/rush.pm | 90 - .../blib/lib/DBD/Gofer/Transport/Base.pm | 410 - .../lib/DBD/Gofer/Transport/corostream.pm | 144 - .../blib/lib/DBD/Gofer/Transport/null.pm | 111 - .../blib/lib/DBD/Gofer/Transport/pipeone.pm | 253 - .../blib/lib/DBD/Gofer/Transport/stream.pm | 292 - dbLifeLog/DBI-1.641/blib/lib/DBD/Mem.pm | 376 - dbLifeLog/DBI-1.641/blib/lib/DBD/NullP.pm | 206 - dbLifeLog/DBI-1.641/blib/lib/DBD/Proxy.pm | 1004 -- dbLifeLog/DBI-1.641/blib/lib/DBD/Sponge.pm | 305 - dbLifeLog/DBI-1.641/blib/lib/DBI.pm | 8435 ----------------- dbLifeLog/DBI-1.641/blib/lib/DBI/Changes.pm | 2584 ----- .../blib/lib/DBI/Const/GetInfo/ANSI.pm | 238 - .../blib/lib/DBI/Const/GetInfo/ODBC.pm | 1363 --- .../blib/lib/DBI/Const/GetInfoReturn.pm | 104 - .../blib/lib/DBI/Const/GetInfoType.pm | 53 - dbLifeLog/DBI-1.641/blib/lib/DBI/DBD.pm | 3500 ------- .../DBI-1.641/blib/lib/DBI/DBD/Metadata.pm | 492 - .../DBI-1.641/blib/lib/DBI/DBD/SqlEngine.pm | 2233 ----- .../blib/lib/DBI/DBD/SqlEngine/Developers.pod | 851 -- .../blib/lib/DBI/DBD/SqlEngine/HowTo.pod | 333 - .../DBI-1.641/blib/lib/DBI/Gofer/Execute.pm | 900 -- .../DBI-1.641/blib/lib/DBI/Gofer/Request.pm | 200 - .../DBI-1.641/blib/lib/DBI/Gofer/Response.pm | 218 - .../blib/lib/DBI/Gofer/Serializer/Base.pm | 64 - .../lib/DBI/Gofer/Serializer/DataDumper.pm | 53 - .../blib/lib/DBI/Gofer/Serializer/Storable.pm | 60 - .../blib/lib/DBI/Gofer/Transport/Base.pm | 174 - .../blib/lib/DBI/Gofer/Transport/pipeone.pm | 64 - .../blib/lib/DBI/Gofer/Transport/stream.pm | 76 - dbLifeLog/DBI-1.641/blib/lib/DBI/Profile.pm | 954 -- .../DBI-1.641/blib/lib/DBI/ProfileData.pm | 736 -- .../DBI-1.641/blib/lib/DBI/ProfileDumper.pm | 351 - .../blib/lib/DBI/ProfileDumper/Apache.pm | 219 - .../DBI-1.641/blib/lib/DBI/ProfileSubs.pm | 50 - .../DBI-1.641/blib/lib/DBI/ProxyServer.pm | 897 -- dbLifeLog/DBI-1.641/blib/lib/DBI/PurePerl.pm | 1279 --- dbLifeLog/DBI-1.641/blib/lib/DBI/SQL/Nano.pm | 1014 -- .../blib/lib/DBI/Util/CacheMemory.pm | 117 - .../DBI-1.641/blib/lib/DBI/Util/_accessor.pm | 65 - dbLifeLog/DBI-1.641/blib/lib/DBI/W32ODBC.pm | 181 - dbLifeLog/DBI-1.641/blib/lib/Win32/DBIODBC.pm | 248 - dbLifeLog/DBI-1.641/blib/lib/auto/DBI/.exists | 0 dbLifeLog/DBI-1.641/blib/lib/dbixs_rev.pl | 51 - dbLifeLog/DBI-1.641/blib/man1/.exists | 0 dbLifeLog/DBI-1.641/blib/man1/dbilogstrip.1p | 115 - dbLifeLog/DBI-1.641/blib/man1/dbiprof.1p | 225 - dbLifeLog/DBI-1.641/blib/man1/dbiproxy.1p | 213 - dbLifeLog/DBI-1.641/blib/man3/.exists | 0 dbLifeLog/DBI-1.641/blib/man3/Bundle::DBI.3pm | 114 - dbLifeLog/DBI-1.641/blib/man3/DBD::DBM.3pm | 924 -- dbLifeLog/DBI-1.641/blib/man3/DBD::File.3pm | 605 -- .../blib/man3/DBD::File::Developers.3pm | 720 -- .../DBI-1.641/blib/man3/DBD::File::HowTo.3pm | 267 - .../blib/man3/DBD::File::Roadmap.3pm | 224 - dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer.3pm | 557 -- .../blib/man3/DBD::Gofer::Policy::Base.3pm | 146 - .../blib/man3/DBD::Gofer::Policy::classic.3pm | 101 - .../man3/DBD::Gofer::Policy::pedantic.3pm | 105 - .../blib/man3/DBD::Gofer::Policy::rush.3pm | 102 - .../blib/man3/DBD::Gofer::Transport::Base.3pm | 187 - .../DBD::Gofer::Transport::corostream.3pm | 194 - .../blib/man3/DBD::Gofer::Transport::null.3pm | 122 - .../man3/DBD::Gofer::Transport::pipeone.3pm | 117 - .../man3/DBD::Gofer::Transport::stream.3pm | 155 - dbLifeLog/DBI-1.641/blib/man3/DBD::Mem.3pm | 164 - dbLifeLog/DBI-1.641/blib/man3/DBD::Proxy.3pm | 353 - dbLifeLog/DBI-1.641/blib/man3/DBD::Sponge.3pm | 147 - dbLifeLog/DBI-1.641/blib/man3/DBI.3pm | 6991 -------------- .../blib/man3/DBI::Const::GetInfo::ANSI.3pm | 119 - .../blib/man3/DBI::Const::GetInfo::ODBC.3pm | 121 - .../blib/man3/DBI::Const::GetInfoReturn.3pm | 86 - .../blib/man3/DBI::Const::GetInfoType.3pm | 96 - dbLifeLog/DBI-1.641/blib/man3/DBI::DBD.3pm | 3453 ------- .../blib/man3/DBI::DBD::Metadata.3pm | 199 - .../blib/man3/DBI::DBD::SqlEngine.3pm | 701 -- .../man3/DBI::DBD::SqlEngine::Developers.3pm | 896 -- .../blib/man3/DBI::DBD::SqlEngine::HowTo.3pm | 424 - .../blib/man3/DBI::Gofer::Execute.3pm | 242 - .../blib/man3/DBI::Gofer::Request.3pm | 92 - .../blib/man3/DBI::Gofer::Response.3pm | 92 - .../man3/DBI::Gofer::Serializer::Base.3pm | 96 - .../DBI::Gofer::Serializer::DataDumper.3pm | 93 - .../man3/DBI::Gofer::Serializer::Storable.3pm | 98 - .../blib/man3/DBI::Gofer::Transport::Base.3pm | 96 - .../man3/DBI::Gofer::Transport::pipeone.3pm | 92 - .../man3/DBI::Gofer::Transport::stream.3pm | 92 - .../DBI-1.641/blib/man3/DBI::Profile.3pm | 791 -- .../DBI-1.641/blib/man3/DBI::ProfileData.3pm | 337 - .../blib/man3/DBI::ProfileDumper.3pm | 256 - .../blib/man3/DBI::ProfileDumper::Apache.3pm | 250 - .../DBI-1.641/blib/man3/DBI::ProfileSubs.3pm | 90 - .../DBI-1.641/blib/man3/DBI::ProxyServer.3pm | 591 -- .../DBI-1.641/blib/man3/DBI::PurePerl.3pm | 243 - .../DBI-1.641/blib/man3/DBI::SQL::Nano.3pm | 279 - .../blib/man3/DBI::Util::CacheMemory.3pm | 117 - .../DBI-1.641/blib/man3/DBI::W32ODBC.3pm | 103 - .../DBI-1.641/blib/man3/Win32::DBIODBC.3pm | 112 - dbLifeLog/DBI-1.641/blib/script/.exists | 0 dbLifeLog/DBI-1.641/blib/script/dbilogstrip | 50 - dbLifeLog/DBI-1.641/blib/script/dbiprof | 263 - dbLifeLog/DBI-1.641/blib/script/dbiproxy | 184 - dbLifeLog/DBI-1.641/dbd_xsh.h | 61 - dbLifeLog/DBI-1.641/dbi_sql.h | 96 - dbLifeLog/DBI-1.641/dbilogstrip | 50 - dbLifeLog/DBI-1.641/dbilogstrip.PL | 71 - dbLifeLog/DBI-1.641/dbipport.h | 7748 --------------- dbLifeLog/DBI-1.641/dbiprof | 263 - dbLifeLog/DBI-1.641/dbiprof.PL | 287 - dbLifeLog/DBI-1.641/dbiproxy | 184 - dbLifeLog/DBI-1.641/dbiproxy.PL | 208 - dbLifeLog/DBI-1.641/dbivport.h | 52 - dbLifeLog/DBI-1.641/dbixs_rev.h | 3 - dbLifeLog/DBI-1.641/dbixs_rev.pl | 51 - dbLifeLog/DBI-1.641/ex/corogofer.pl | 32 - dbLifeLog/DBI-1.641/ex/perl_dbi_nulls_test.pl | 176 - dbLifeLog/DBI-1.641/ex/profile.pl | 25 - dbLifeLog/DBI-1.641/lib/Bundle/DBI.pm | 52 - dbLifeLog/DBI-1.641/lib/DBD/DBM.pm | 1454 --- dbLifeLog/DBI-1.641/lib/DBD/ExampleP.pm | 435 - dbLifeLog/DBI-1.641/lib/DBD/File.pm | 1449 --- .../DBI-1.641/lib/DBD/File/Developers.pod | 665 -- dbLifeLog/DBI-1.641/lib/DBD/File/HowTo.pod | 191 - dbLifeLog/DBI-1.641/lib/DBD/File/Roadmap.pod | 176 - dbLifeLog/DBI-1.641/lib/DBD/Gofer.pm | 1292 --- .../DBI-1.641/lib/DBD/Gofer/Policy/Base.pm | 162 - .../DBI-1.641/lib/DBD/Gofer/Policy/classic.pm | 79 - .../lib/DBD/Gofer/Policy/pedantic.pm | 53 - .../DBI-1.641/lib/DBD/Gofer/Policy/rush.pm | 90 - .../DBI-1.641/lib/DBD/Gofer/Transport/Base.pm | 410 - .../lib/DBD/Gofer/Transport/corostream.pm | 144 - .../DBI-1.641/lib/DBD/Gofer/Transport/null.pm | 111 - .../lib/DBD/Gofer/Transport/pipeone.pm | 253 - .../lib/DBD/Gofer/Transport/stream.pm | 292 - dbLifeLog/DBI-1.641/lib/DBD/Mem.pm | 376 - dbLifeLog/DBI-1.641/lib/DBD/NullP.pm | 206 - dbLifeLog/DBI-1.641/lib/DBD/Proxy.pm | 1004 -- dbLifeLog/DBI-1.641/lib/DBD/Sponge.pm | 305 - .../DBI-1.641/lib/DBI/Const/GetInfo/ANSI.pm | 238 - .../DBI-1.641/lib/DBI/Const/GetInfo/ODBC.pm | 1363 --- .../DBI-1.641/lib/DBI/Const/GetInfoReturn.pm | 104 - .../DBI-1.641/lib/DBI/Const/GetInfoType.pm | 53 - dbLifeLog/DBI-1.641/lib/DBI/DBD.pm | 3500 ------- dbLifeLog/DBI-1.641/lib/DBI/DBD/Metadata.pm | 492 - dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine.pm | 2233 ----- .../lib/DBI/DBD/SqlEngine/Developers.pod | 851 -- .../DBI-1.641/lib/DBI/DBD/SqlEngine/HowTo.pod | 333 - dbLifeLog/DBI-1.641/lib/DBI/Gofer/Execute.pm | 900 -- dbLifeLog/DBI-1.641/lib/DBI/Gofer/Request.pm | 200 - dbLifeLog/DBI-1.641/lib/DBI/Gofer/Response.pm | 218 - .../lib/DBI/Gofer/Serializer/Base.pm | 64 - .../lib/DBI/Gofer/Serializer/DataDumper.pm | 53 - .../lib/DBI/Gofer/Serializer/Storable.pm | 60 - .../DBI-1.641/lib/DBI/Gofer/Transport/Base.pm | 174 - .../lib/DBI/Gofer/Transport/pipeone.pm | 64 - .../lib/DBI/Gofer/Transport/stream.pm | 76 - dbLifeLog/DBI-1.641/lib/DBI/Profile.pm | 954 -- dbLifeLog/DBI-1.641/lib/DBI/ProfileData.pm | 736 -- dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper.pm | 351 - .../DBI-1.641/lib/DBI/ProfileDumper/Apache.pm | 219 - dbLifeLog/DBI-1.641/lib/DBI/ProfileSubs.pm | 50 - dbLifeLog/DBI-1.641/lib/DBI/ProxyServer.pm | 897 -- dbLifeLog/DBI-1.641/lib/DBI/PurePerl.pm | 1279 --- dbLifeLog/DBI-1.641/lib/DBI/SQL/Nano.pm | 1014 -- .../DBI-1.641/lib/DBI/Util/CacheMemory.pm | 117 - dbLifeLog/DBI-1.641/lib/DBI/Util/_accessor.pm | 65 - dbLifeLog/DBI-1.641/lib/DBI/W32ODBC.pm | 181 - dbLifeLog/DBI-1.641/lib/Win32/DBIODBC.pm | 248 - dbLifeLog/DBI-1.641/pm_to_blib | 0 dbLifeLog/DBI-1.641/t/01basics.t | 340 - dbLifeLog/DBI-1.641/t/02dbidrv.t | 254 - dbLifeLog/DBI-1.641/t/03handle.t | 410 - dbLifeLog/DBI-1.641/t/04mods.t | 59 - dbLifeLog/DBI-1.641/t/05concathash.t | 190 - dbLifeLog/DBI-1.641/t/06attrs.t | 331 - dbLifeLog/DBI-1.641/t/07kids.t | 102 - dbLifeLog/DBI-1.641/t/08keeperr.t | 348 - dbLifeLog/DBI-1.641/t/09trace.t | 137 - dbLifeLog/DBI-1.641/t/10examp.t | 640 -- dbLifeLog/DBI-1.641/t/11fetch.t | 124 - dbLifeLog/DBI-1.641/t/12quote.t | 48 - dbLifeLog/DBI-1.641/t/13taint.t | 133 - dbLifeLog/DBI-1.641/t/14utf8.t | 76 - dbLifeLog/DBI-1.641/t/15array.t | 254 - dbLifeLog/DBI-1.641/t/16destroy.t | 148 - dbLifeLog/DBI-1.641/t/19fhtrace.t | 306 - dbLifeLog/DBI-1.641/t/20meta.t | 32 - dbLifeLog/DBI-1.641/t/30subclass.t | 182 - dbLifeLog/DBI-1.641/t/31methcache.t | 157 - dbLifeLog/DBI-1.641/t/35thrclone.t | 86 - dbLifeLog/DBI-1.641/t/40profile.t | 485 - dbLifeLog/DBI-1.641/t/41prof_dump.t | 105 - dbLifeLog/DBI-1.641/t/42prof_data.t | 156 - dbLifeLog/DBI-1.641/t/43prof_env.t | 52 - dbLifeLog/DBI-1.641/t/48dbi_dbd_sqlengine.t | 91 - dbLifeLog/DBI-1.641/t/49dbd_file.t | 266 - dbLifeLog/DBI-1.641/t/50dbm_simple.t | 270 - dbLifeLog/DBI-1.641/t/51dbm_file.t | 186 - dbLifeLog/DBI-1.641/t/52dbm_complex.t | 359 - dbLifeLog/DBI-1.641/t/53sqlengine_adv.t | 49 - dbLifeLog/DBI-1.641/t/54_dbd_mem.t | 41 - dbLifeLog/DBI-1.641/t/60preparse.t | 148 - dbLifeLog/DBI-1.641/t/65transact.t | 35 - dbLifeLog/DBI-1.641/t/70callbacks.t | 252 - dbLifeLog/DBI-1.641/t/72childhandles.t | 149 - dbLifeLog/DBI-1.641/t/73cachedkids.t | 81 - dbLifeLog/DBI-1.641/t/80proxy.t | 473 - dbLifeLog/DBI-1.641/t/85gofer.t | 265 - dbLifeLog/DBI-1.641/t/86gofer_fail.t | 168 - dbLifeLog/DBI-1.641/t/87gofer_cache.t | 108 - dbLifeLog/DBI-1.641/t/90sql_type_cast.t | 153 - dbLifeLog/DBI-1.641/t/91_store_warning.t | 37 - dbLifeLog/DBI-1.641/t/lib.pl | 33 - dbLifeLog/DBI-1.641/t/pod-coverage.t | 8 - dbLifeLog/DBI-1.641/t/pod.t | 8 - dbLifeLog/DBI-1.641/t/zvg_01basics.t | 4 - dbLifeLog/DBI-1.641/t/zvg_02dbidrv.t | 4 - dbLifeLog/DBI-1.641/t/zvg_03handle.t | 4 - dbLifeLog/DBI-1.641/t/zvg_04mods.t | 4 - dbLifeLog/DBI-1.641/t/zvg_05concathash.t | 4 - dbLifeLog/DBI-1.641/t/zvg_06attrs.t | 4 - dbLifeLog/DBI-1.641/t/zvg_07kids.t | 4 - dbLifeLog/DBI-1.641/t/zvg_08keeperr.t | 4 - dbLifeLog/DBI-1.641/t/zvg_09trace.t | 4 - dbLifeLog/DBI-1.641/t/zvg_10examp.t | 4 - dbLifeLog/DBI-1.641/t/zvg_11fetch.t | 4 - dbLifeLog/DBI-1.641/t/zvg_12quote.t | 4 - dbLifeLog/DBI-1.641/t/zvg_13taint.t | 4 - dbLifeLog/DBI-1.641/t/zvg_14utf8.t | 4 - dbLifeLog/DBI-1.641/t/zvg_15array.t | 4 - dbLifeLog/DBI-1.641/t/zvg_16destroy.t | 4 - dbLifeLog/DBI-1.641/t/zvg_19fhtrace.t | 4 - dbLifeLog/DBI-1.641/t/zvg_20meta.t | 4 - dbLifeLog/DBI-1.641/t/zvg_30subclass.t | 4 - dbLifeLog/DBI-1.641/t/zvg_31methcache.t | 4 - dbLifeLog/DBI-1.641/t/zvg_35thrclone.t | 5 - dbLifeLog/DBI-1.641/t/zvg_40profile.t | 4 - dbLifeLog/DBI-1.641/t/zvg_41prof_dump.t | 4 - dbLifeLog/DBI-1.641/t/zvg_42prof_data.t | 4 - dbLifeLog/DBI-1.641/t/zvg_43prof_env.t | 4 - .../DBI-1.641/t/zvg_48dbi_dbd_sqlengine.t | 4 - dbLifeLog/DBI-1.641/t/zvg_49dbd_file.t | 4 - dbLifeLog/DBI-1.641/t/zvg_50dbm_simple.t | 4 - dbLifeLog/DBI-1.641/t/zvg_51dbm_file.t | 4 - dbLifeLog/DBI-1.641/t/zvg_52dbm_complex.t | 4 - dbLifeLog/DBI-1.641/t/zvg_53sqlengine_adv.t | 4 - dbLifeLog/DBI-1.641/t/zvg_54_dbd_mem.t | 4 - dbLifeLog/DBI-1.641/t/zvg_60preparse.t | 4 - dbLifeLog/DBI-1.641/t/zvg_65transact.t | 4 - dbLifeLog/DBI-1.641/t/zvg_70callbacks.t | 4 - dbLifeLog/DBI-1.641/t/zvg_72childhandles.t | 4 - dbLifeLog/DBI-1.641/t/zvg_73cachedkids.t | 4 - dbLifeLog/DBI-1.641/t/zvg_80proxy.t | 4 - dbLifeLog/DBI-1.641/t/zvg_85gofer.t | 4 - dbLifeLog/DBI-1.641/t/zvg_86gofer_fail.t | 4 - dbLifeLog/DBI-1.641/t/zvg_87gofer_cache.t | 4 - dbLifeLog/DBI-1.641/t/zvg_90sql_type_cast.t | 4 - dbLifeLog/DBI-1.641/t/zvg_91_store_warning.t | 4 - .../DBI-1.641/t/zvn_48dbi_dbd_sqlengine.t | 4 - dbLifeLog/DBI-1.641/t/zvn_49dbd_file.t | 4 - dbLifeLog/DBI-1.641/t/zvn_50dbm_simple.t | 4 - dbLifeLog/DBI-1.641/t/zvn_51dbm_file.t | 4 - dbLifeLog/DBI-1.641/t/zvn_52dbm_complex.t | 4 - dbLifeLog/DBI-1.641/t/zvn_85gofer.t | 4 - dbLifeLog/DBI-1.641/t/zvp_01basics.t | 4 - dbLifeLog/DBI-1.641/t/zvp_02dbidrv.t | 4 - dbLifeLog/DBI-1.641/t/zvp_03handle.t | 4 - dbLifeLog/DBI-1.641/t/zvp_04mods.t | 4 - dbLifeLog/DBI-1.641/t/zvp_05concathash.t | 4 - dbLifeLog/DBI-1.641/t/zvp_06attrs.t | 4 - dbLifeLog/DBI-1.641/t/zvp_07kids.t | 4 - dbLifeLog/DBI-1.641/t/zvp_08keeperr.t | 4 - dbLifeLog/DBI-1.641/t/zvp_09trace.t | 4 - dbLifeLog/DBI-1.641/t/zvp_10examp.t | 4 - dbLifeLog/DBI-1.641/t/zvp_11fetch.t | 4 - dbLifeLog/DBI-1.641/t/zvp_12quote.t | 4 - dbLifeLog/DBI-1.641/t/zvp_13taint.t | 4 - dbLifeLog/DBI-1.641/t/zvp_14utf8.t | 4 - dbLifeLog/DBI-1.641/t/zvp_15array.t | 4 - dbLifeLog/DBI-1.641/t/zvp_16destroy.t | 4 - dbLifeLog/DBI-1.641/t/zvp_19fhtrace.t | 4 - dbLifeLog/DBI-1.641/t/zvp_20meta.t | 4 - dbLifeLog/DBI-1.641/t/zvp_30subclass.t | 4 - dbLifeLog/DBI-1.641/t/zvp_31methcache.t | 4 - dbLifeLog/DBI-1.641/t/zvp_35thrclone.t | 5 - dbLifeLog/DBI-1.641/t/zvp_40profile.t | 4 - dbLifeLog/DBI-1.641/t/zvp_41prof_dump.t | 4 - dbLifeLog/DBI-1.641/t/zvp_42prof_data.t | 4 - dbLifeLog/DBI-1.641/t/zvp_43prof_env.t | 4 - .../DBI-1.641/t/zvp_48dbi_dbd_sqlengine.t | 4 - dbLifeLog/DBI-1.641/t/zvp_49dbd_file.t | 4 - dbLifeLog/DBI-1.641/t/zvp_50dbm_simple.t | 4 - dbLifeLog/DBI-1.641/t/zvp_51dbm_file.t | 4 - dbLifeLog/DBI-1.641/t/zvp_52dbm_complex.t | 4 - dbLifeLog/DBI-1.641/t/zvp_53sqlengine_adv.t | 4 - dbLifeLog/DBI-1.641/t/zvp_54_dbd_mem.t | 4 - dbLifeLog/DBI-1.641/t/zvp_60preparse.t | 4 - dbLifeLog/DBI-1.641/t/zvp_65transact.t | 4 - dbLifeLog/DBI-1.641/t/zvp_70callbacks.t | 4 - dbLifeLog/DBI-1.641/t/zvp_72childhandles.t | 4 - dbLifeLog/DBI-1.641/t/zvp_73cachedkids.t | 4 - dbLifeLog/DBI-1.641/t/zvp_80proxy.t | 4 - dbLifeLog/DBI-1.641/t/zvp_85gofer.t | 4 - dbLifeLog/DBI-1.641/t/zvp_86gofer_fail.t | 4 - dbLifeLog/DBI-1.641/t/zvp_87gofer_cache.t | 4 - dbLifeLog/DBI-1.641/t/zvp_90sql_type_cast.t | 4 - dbLifeLog/DBI-1.641/t/zvp_91_store_warning.t | 4 - .../DBI-1.641/t/zvxgn_48dbi_dbd_sqlengine.t | 6 - dbLifeLog/DBI-1.641/t/zvxgn_49dbd_file.t | 6 - dbLifeLog/DBI-1.641/t/zvxgn_50dbm_simple.t | 6 - dbLifeLog/DBI-1.641/t/zvxgn_51dbm_file.t | 6 - dbLifeLog/DBI-1.641/t/zvxgn_52dbm_complex.t | 6 - dbLifeLog/DBI-1.641/t/zvxgn_85gofer.t | 6 - .../DBI-1.641/t/zvxgnp_48dbi_dbd_sqlengine.t | 8 - dbLifeLog/DBI-1.641/t/zvxgnp_49dbd_file.t | 8 - dbLifeLog/DBI-1.641/t/zvxgnp_50dbm_simple.t | 8 - dbLifeLog/DBI-1.641/t/zvxgnp_51dbm_file.t | 8 - dbLifeLog/DBI-1.641/t/zvxgnp_52dbm_complex.t | 8 - dbLifeLog/DBI-1.641/t/zvxgnp_85gofer.t | 8 - dbLifeLog/DBI-1.641/t/zvxgp_01basics.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_02dbidrv.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_03handle.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_04mods.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_05concathash.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_06attrs.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_07kids.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_08keeperr.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_09trace.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_10examp.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_11fetch.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_12quote.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_13taint.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_14utf8.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_15array.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_16destroy.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_19fhtrace.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_20meta.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_30subclass.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_31methcache.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_35thrclone.t | 7 - dbLifeLog/DBI-1.641/t/zvxgp_40profile.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_41prof_dump.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_42prof_data.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_43prof_env.t | 6 - .../DBI-1.641/t/zvxgp_48dbi_dbd_sqlengine.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_49dbd_file.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_50dbm_simple.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_51dbm_file.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_52dbm_complex.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_53sqlengine_adv.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_54_dbd_mem.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_60preparse.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_65transact.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_70callbacks.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_72childhandles.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_73cachedkids.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_80proxy.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_85gofer.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_86gofer_fail.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_87gofer_cache.t | 6 - dbLifeLog/DBI-1.641/t/zvxgp_90sql_type_cast.t | 6 - .../DBI-1.641/t/zvxgp_91_store_warning.t | 6 - .../DBI-1.641/t/zvxnp_48dbi_dbd_sqlengine.t | 6 - dbLifeLog/DBI-1.641/t/zvxnp_49dbd_file.t | 6 - dbLifeLog/DBI-1.641/t/zvxnp_50dbm_simple.t | 6 - dbLifeLog/DBI-1.641/t/zvxnp_51dbm_file.t | 6 - dbLifeLog/DBI-1.641/t/zvxnp_52dbm_complex.t | 6 - dbLifeLog/DBI-1.641/t/zvxnp_85gofer.t | 6 - dbLifeLog/DBI-1.641/test.pl | 201 - dbLifeLog/DBI-1.641/typemap | 3 - dbLifeLog/cat | 1 - dbLifeLog/data_config_test_log.db | Bin 24576 -> 0 bytes dbLifeLog/data_log.db | Bin 32768 -> 0 bytes dbLifeLog/echo | 1 - dbLifeLog/ps_system.sh | 3 - dbLifeLog/readme.txt | 20 - 557 files changed, 195672 deletions(-) delete mode 100644 dbLifeLog/DBD-SQLite2-0.33.tar.gz delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/Changes delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/MANIFEST delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/MANIFEST.SKIP delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/META.yml delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/MYMETA.json delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/MYMETA.yml delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/Makefile delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/Makefile.PL delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/README delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/SQLite2.bs delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/SQLite2.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/SQLite2.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/SQLite2.xs delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/SQLite2.xsi delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/SQLiteXS.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/attach.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/attach.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/auth.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/auth.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/arch/.exists delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/arch/auto/DBD/SQLite2/.exists delete mode 100755 dbLifeLog/DBD-SQLite2-0.33/blib/arch/auto/DBD/SQLite2/SQLite2.so delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/bin/.exists delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/.exists delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/SQLite2.pm delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/getsqlite.pl delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/lib/auto/DBD/SQLite2/.exists delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/man1/.exists delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/man3/.exists delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/man3/DBD::SQLite2.3pm delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/blib/script/.exists delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/btree.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/btree.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/btree.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/btree_rb.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/btree_rb.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/build.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/build.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/copy.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/copy.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/date.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/date.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/dbdimp.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/dbdimp.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/dbdimp.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/delete.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/delete.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/encode.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/encode.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/expr.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/expr.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/func.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/func.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/getsqlite.pl delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/hash.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/hash.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/hash.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/insert.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/insert.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/lib/DBD/SQLite2.pm delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/main.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/main.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/opcodes.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/opcodes.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/opcodes.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/os.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/os.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/os.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/pager.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/pager.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/pager.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/parse.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/parse.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/parse.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/pm_to_blib delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/pragma.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/pragma.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/printf.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/printf.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/random.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/random.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/select.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/select.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/sqlite.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/sqliteInt.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/00basic.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/01logon.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/02cr_table.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/03insert.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/04select.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/05tran.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/06error.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/08create_function.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/09create_aggregate.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/10dsnlist.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/20createdrop.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/30insertfetch.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/40bindparam.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/40blobs.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/40listfields.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/40nulls.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/40numrows.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/50chopblanks.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/50commit.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/60metadata.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/90cppcomments.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/99cleanup.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/SQLite2.dbtest delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/ak-dbd.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/dbdadmin.t delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/t/lib.pl delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/table.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/table.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/tokenize.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/tokenize.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/trigger.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/trigger.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/update.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/update.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/util.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/util.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/vacuum.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/vacuum.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/vdbe.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/vdbe.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/vdbe.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/vdbeInt.h delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/vdbeaux.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/vdbeaux.o delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/where.c delete mode 100644 dbLifeLog/DBD-SQLite2-0.33/where.o delete mode 100644 dbLifeLog/DBI-1.641.readme delete mode 100644 dbLifeLog/DBI-1.641.tar.gz delete mode 100644 dbLifeLog/DBI-1.641/Changes delete mode 100644 dbLifeLog/DBI-1.641/DBI.bs delete mode 100644 dbLifeLog/DBI-1.641/DBI.c delete mode 100644 dbLifeLog/DBI-1.641/DBI.o delete mode 100644 dbLifeLog/DBI-1.641/DBI.pm delete mode 100644 dbLifeLog/DBI-1.641/DBI.xs delete mode 100644 dbLifeLog/DBI-1.641/DBIXS.h delete mode 100644 dbLifeLog/DBI-1.641/Driver.xst delete mode 100644 dbLifeLog/DBI-1.641/Driver_xst.h delete mode 100644 dbLifeLog/DBI-1.641/INSTALL delete mode 100644 dbLifeLog/DBI-1.641/LICENSE delete mode 100644 dbLifeLog/DBI-1.641/MANIFEST delete mode 100644 dbLifeLog/DBI-1.641/META.json delete mode 100644 dbLifeLog/DBI-1.641/META.yml delete mode 100644 dbLifeLog/DBI-1.641/MYMETA.json delete mode 100644 dbLifeLog/DBI-1.641/MYMETA.yml delete mode 100644 dbLifeLog/DBI-1.641/Makefile delete mode 100644 dbLifeLog/DBI-1.641/Makefile.PL delete mode 100644 dbLifeLog/DBI-1.641/Perl.c delete mode 100644 dbLifeLog/DBI-1.641/Perl.o delete mode 100644 dbLifeLog/DBI-1.641/Perl.xs delete mode 100644 dbLifeLog/DBI-1.641/Perl.xsi delete mode 100644 dbLifeLog/DBI-1.641/README.md delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/.exists delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/.exists delete mode 100755 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/DBI.so delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/DBIXS.h delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/Driver.xst delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/Driver_xst.h delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbd_xsh.h delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbi_sql.h delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbipport.h delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbivport.h delete mode 100644 dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbixs_rev.h delete mode 100644 dbLifeLog/DBI-1.641/blib/bin/.exists delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/.exists delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/Bundle/DBI.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/DBM.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/ExampleP.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/File.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/File/Developers.pod delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/File/HowTo.pod delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/File/Roadmap.pod delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/Base.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/classic.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/pedantic.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/rush.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/Base.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/corostream.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/null.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/pipeone.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/stream.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Mem.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/NullP.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Proxy.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBD/Sponge.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Changes.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Const/GetInfo/ANSI.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Const/GetInfo/ODBC.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Const/GetInfoReturn.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Const/GetInfoType.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/DBD.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/Metadata.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine/Developers.pod delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine/HowTo.pod delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Execute.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Request.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Response.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/Base.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/DataDumper.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/Storable.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/Base.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/pipeone.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/stream.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Profile.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileData.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileDumper.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileDumper/Apache.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileSubs.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/ProxyServer.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/PurePerl.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/SQL/Nano.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Util/CacheMemory.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/Util/_accessor.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/DBI/W32ODBC.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/Win32/DBIODBC.pm delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/auto/DBI/.exists delete mode 100644 dbLifeLog/DBI-1.641/blib/lib/dbixs_rev.pl delete mode 100644 dbLifeLog/DBI-1.641/blib/man1/.exists delete mode 100644 dbLifeLog/DBI-1.641/blib/man1/dbilogstrip.1p delete mode 100644 dbLifeLog/DBI-1.641/blib/man1/dbiprof.1p delete mode 100644 dbLifeLog/DBI-1.641/blib/man1/dbiproxy.1p delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/.exists delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/Bundle::DBI.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::DBM.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::File.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::File::Developers.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::File::HowTo.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::File::Roadmap.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::Base.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::classic.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::pedantic.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::rush.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::Base.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::corostream.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::null.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::pipeone.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::stream.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Mem.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Proxy.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBD::Sponge.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfo::ANSI.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfo::ODBC.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfoReturn.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfoType.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::DBD.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::Metadata.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine::Developers.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine::HowTo.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Execute.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Request.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Response.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::Base.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::DataDumper.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::Storable.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::Base.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::pipeone.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::stream.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Profile.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileData.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileDumper.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileDumper::Apache.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileSubs.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::ProxyServer.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::PurePerl.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::SQL::Nano.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::Util::CacheMemory.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/DBI::W32ODBC.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/man3/Win32::DBIODBC.3pm delete mode 100644 dbLifeLog/DBI-1.641/blib/script/.exists delete mode 100755 dbLifeLog/DBI-1.641/blib/script/dbilogstrip delete mode 100755 dbLifeLog/DBI-1.641/blib/script/dbiprof delete mode 100755 dbLifeLog/DBI-1.641/blib/script/dbiproxy delete mode 100644 dbLifeLog/DBI-1.641/dbd_xsh.h delete mode 100644 dbLifeLog/DBI-1.641/dbi_sql.h delete mode 100755 dbLifeLog/DBI-1.641/dbilogstrip delete mode 100644 dbLifeLog/DBI-1.641/dbilogstrip.PL delete mode 100644 dbLifeLog/DBI-1.641/dbipport.h delete mode 100755 dbLifeLog/DBI-1.641/dbiprof delete mode 100644 dbLifeLog/DBI-1.641/dbiprof.PL delete mode 100755 dbLifeLog/DBI-1.641/dbiproxy delete mode 100644 dbLifeLog/DBI-1.641/dbiproxy.PL delete mode 100644 dbLifeLog/DBI-1.641/dbivport.h delete mode 100644 dbLifeLog/DBI-1.641/dbixs_rev.h delete mode 100644 dbLifeLog/DBI-1.641/dbixs_rev.pl delete mode 100644 dbLifeLog/DBI-1.641/ex/corogofer.pl delete mode 100644 dbLifeLog/DBI-1.641/ex/perl_dbi_nulls_test.pl delete mode 100644 dbLifeLog/DBI-1.641/ex/profile.pl delete mode 100644 dbLifeLog/DBI-1.641/lib/Bundle/DBI.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/DBM.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/ExampleP.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/File.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/File/Developers.pod delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/File/HowTo.pod delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/File/Roadmap.pod delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/Base.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/classic.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/pedantic.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/rush.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/Base.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/corostream.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/null.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/pipeone.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/stream.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Mem.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/NullP.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Proxy.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBD/Sponge.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Const/GetInfo/ANSI.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Const/GetInfo/ODBC.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Const/GetInfoReturn.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Const/GetInfoType.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/DBD.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/DBD/Metadata.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine/Developers.pod delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine/HowTo.pod delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Execute.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Request.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Response.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/Base.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/DataDumper.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/Storable.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/Base.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/pipeone.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/stream.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Profile.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/ProfileData.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper/Apache.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/ProfileSubs.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/ProxyServer.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/PurePerl.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/SQL/Nano.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Util/CacheMemory.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/Util/_accessor.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/DBI/W32ODBC.pm delete mode 100644 dbLifeLog/DBI-1.641/lib/Win32/DBIODBC.pm delete mode 100644 dbLifeLog/DBI-1.641/pm_to_blib delete mode 100755 dbLifeLog/DBI-1.641/t/01basics.t delete mode 100755 dbLifeLog/DBI-1.641/t/02dbidrv.t delete mode 100644 dbLifeLog/DBI-1.641/t/03handle.t delete mode 100644 dbLifeLog/DBI-1.641/t/04mods.t delete mode 100644 dbLifeLog/DBI-1.641/t/05concathash.t delete mode 100644 dbLifeLog/DBI-1.641/t/06attrs.t delete mode 100644 dbLifeLog/DBI-1.641/t/07kids.t delete mode 100644 dbLifeLog/DBI-1.641/t/08keeperr.t delete mode 100644 dbLifeLog/DBI-1.641/t/09trace.t delete mode 100644 dbLifeLog/DBI-1.641/t/10examp.t delete mode 100644 dbLifeLog/DBI-1.641/t/11fetch.t delete mode 100644 dbLifeLog/DBI-1.641/t/12quote.t delete mode 100644 dbLifeLog/DBI-1.641/t/13taint.t delete mode 100644 dbLifeLog/DBI-1.641/t/14utf8.t delete mode 100644 dbLifeLog/DBI-1.641/t/15array.t delete mode 100644 dbLifeLog/DBI-1.641/t/16destroy.t delete mode 100644 dbLifeLog/DBI-1.641/t/19fhtrace.t delete mode 100644 dbLifeLog/DBI-1.641/t/20meta.t delete mode 100644 dbLifeLog/DBI-1.641/t/30subclass.t delete mode 100644 dbLifeLog/DBI-1.641/t/31methcache.t delete mode 100644 dbLifeLog/DBI-1.641/t/35thrclone.t delete mode 100644 dbLifeLog/DBI-1.641/t/40profile.t delete mode 100644 dbLifeLog/DBI-1.641/t/41prof_dump.t delete mode 100644 dbLifeLog/DBI-1.641/t/42prof_data.t delete mode 100644 dbLifeLog/DBI-1.641/t/43prof_env.t delete mode 100644 dbLifeLog/DBI-1.641/t/48dbi_dbd_sqlengine.t delete mode 100644 dbLifeLog/DBI-1.641/t/49dbd_file.t delete mode 100755 dbLifeLog/DBI-1.641/t/50dbm_simple.t delete mode 100644 dbLifeLog/DBI-1.641/t/51dbm_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/52dbm_complex.t delete mode 100644 dbLifeLog/DBI-1.641/t/53sqlengine_adv.t delete mode 100644 dbLifeLog/DBI-1.641/t/54_dbd_mem.t delete mode 100755 dbLifeLog/DBI-1.641/t/60preparse.t delete mode 100644 dbLifeLog/DBI-1.641/t/65transact.t delete mode 100644 dbLifeLog/DBI-1.641/t/70callbacks.t delete mode 100644 dbLifeLog/DBI-1.641/t/72childhandles.t delete mode 100644 dbLifeLog/DBI-1.641/t/73cachedkids.t delete mode 100644 dbLifeLog/DBI-1.641/t/80proxy.t delete mode 100644 dbLifeLog/DBI-1.641/t/85gofer.t delete mode 100644 dbLifeLog/DBI-1.641/t/86gofer_fail.t delete mode 100644 dbLifeLog/DBI-1.641/t/87gofer_cache.t delete mode 100644 dbLifeLog/DBI-1.641/t/90sql_type_cast.t delete mode 100644 dbLifeLog/DBI-1.641/t/91_store_warning.t delete mode 100644 dbLifeLog/DBI-1.641/t/lib.pl delete mode 100644 dbLifeLog/DBI-1.641/t/pod-coverage.t delete mode 100644 dbLifeLog/DBI-1.641/t/pod.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_01basics.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_02dbidrv.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_03handle.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_04mods.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_05concathash.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_06attrs.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_07kids.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_08keeperr.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_09trace.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_10examp.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_11fetch.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_12quote.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_13taint.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_14utf8.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_15array.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_16destroy.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_19fhtrace.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_20meta.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_30subclass.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_31methcache.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_35thrclone.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_40profile.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_41prof_dump.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_42prof_data.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_43prof_env.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_48dbi_dbd_sqlengine.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_49dbd_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_50dbm_simple.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_51dbm_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_52dbm_complex.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_53sqlengine_adv.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_54_dbd_mem.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_60preparse.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_65transact.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_70callbacks.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_72childhandles.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_73cachedkids.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_80proxy.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_85gofer.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_86gofer_fail.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_87gofer_cache.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_90sql_type_cast.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvg_91_store_warning.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvn_48dbi_dbd_sqlengine.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvn_49dbd_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvn_50dbm_simple.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvn_51dbm_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvn_52dbm_complex.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvn_85gofer.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_01basics.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_02dbidrv.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_03handle.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_04mods.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_05concathash.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_06attrs.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_07kids.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_08keeperr.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_09trace.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_10examp.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_11fetch.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_12quote.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_13taint.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_14utf8.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_15array.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_16destroy.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_19fhtrace.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_20meta.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_30subclass.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_31methcache.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_35thrclone.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_40profile.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_41prof_dump.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_42prof_data.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_43prof_env.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_48dbi_dbd_sqlengine.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_49dbd_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_50dbm_simple.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_51dbm_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_52dbm_complex.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_53sqlengine_adv.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_54_dbd_mem.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_60preparse.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_65transact.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_70callbacks.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_72childhandles.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_73cachedkids.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_80proxy.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_85gofer.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_86gofer_fail.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_87gofer_cache.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_90sql_type_cast.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvp_91_store_warning.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgn_48dbi_dbd_sqlengine.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgn_49dbd_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgn_50dbm_simple.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgn_51dbm_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgn_52dbm_complex.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgn_85gofer.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgnp_48dbi_dbd_sqlengine.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgnp_49dbd_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgnp_50dbm_simple.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgnp_51dbm_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgnp_52dbm_complex.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgnp_85gofer.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_01basics.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_02dbidrv.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_03handle.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_04mods.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_05concathash.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_06attrs.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_07kids.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_08keeperr.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_09trace.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_10examp.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_11fetch.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_12quote.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_13taint.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_14utf8.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_15array.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_16destroy.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_19fhtrace.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_20meta.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_30subclass.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_31methcache.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_35thrclone.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_40profile.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_41prof_dump.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_42prof_data.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_43prof_env.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_48dbi_dbd_sqlengine.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_49dbd_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_50dbm_simple.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_51dbm_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_52dbm_complex.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_53sqlengine_adv.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_54_dbd_mem.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_60preparse.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_65transact.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_70callbacks.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_72childhandles.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_73cachedkids.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_80proxy.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_85gofer.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_86gofer_fail.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_87gofer_cache.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_90sql_type_cast.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxgp_91_store_warning.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxnp_48dbi_dbd_sqlengine.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxnp_49dbd_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxnp_50dbm_simple.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxnp_51dbm_file.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxnp_52dbm_complex.t delete mode 100644 dbLifeLog/DBI-1.641/t/zvxnp_85gofer.t delete mode 100755 dbLifeLog/DBI-1.641/test.pl delete mode 100644 dbLifeLog/DBI-1.641/typemap delete mode 100644 dbLifeLog/cat delete mode 100644 dbLifeLog/data_config_test_log.db delete mode 100644 dbLifeLog/data_log.db delete mode 100644 dbLifeLog/echo delete mode 100755 dbLifeLog/ps_system.sh delete mode 100644 dbLifeLog/readme.txt diff --git a/dbLifeLog/DBD-SQLite2-0.33.tar.gz b/dbLifeLog/DBD-SQLite2-0.33.tar.gz deleted file mode 100644 index 58dc97d725de5295c0c3422e3c9ed1859c3bef87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 363277 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"EorFI zL|JL{IVV|S;WhCdr^G{bmiFXbK~M;F1vPC!T}zO})C7*ku;ry1f&|LcHBkr-?3G}x zfVvBKubDe3Ugf=RU{dN^uiv-jR+eA6);fvLyXp-^G#lPZ;YV#n_&V~G&}$1H4?9(7 zjTWBMDwG^pXxI`*@c#s&9*oL!2utQ&WdR*47Pbjg@&AwHxgzm}YLfqY5{&3_>dnz3 zIV!zDxD!=I5i2&S6$|z=frEb%;p^i;Bbd}XkhH@?Vs`-fyTS2LQMRM#2=@;~hWh)O zu(3$ZT@&@ic9qX`KvhA4HHrVQObDUK)*5S%VQdGRq=dA0kGeEB{=L3-`L=C9^HPDY zxHLCCpf;Q)Qyl5FoQjQzm2y>*jVH64Xbqx+aNR(mAF~g*4#9{4yb;xJ!C+uF{w{;T z8-`hUl;r@PmM7I~?eXt8b)$58sb?-kr2O51VFQ2Bv$4WV@THlWOhq5!NByeu{S06EfH#M&m!b)l%`RJ&l2o80igH5d6RsQHUl?N`1 zs&-U>ix)3oSb5bjloj8A<x#gBqRs|N8U@c9v zPQ^<~|Goo8-)ZFTj9t9%l887i5wJmp4!)&QS}ou?YWxU>&f2UA!zx1!*ct&5&lXf> z{Q*oZtiC~dW9(sX+!vrAhjW0!3LVTlk(XITiEYB_P?u@SK~)jZcT%G;SUYNnL7kJD z4hSAnN=Wkq22zgHkzRmJCl!p~;Do{O#dA7bpn`DF6vj=qjtg%b(-T0pD|K`9se~#w8vhZy9$n z?BEvi?uzCv$ol!bVm&F6hFykFy%qkpJK<_K!iD!i?>6|ez69zkAiSCQZ|v>sXYbPG zU%7tvZd%LkS*zc&WJxjoGlVt+>Z4(`kn4b)3pY`OU?$umfU}=#d4<|r$#>=Tn#4K} zITZ$_`@)neSLHR>3T_CTSih_#IgTa)!yzbP)1~ zv+I)TlFvK3a3ECRSLFBStc$2BG0*UtC@Owa&RRl(0ySP`8<3!Sq^_S8;1&MiMV{XJ{7kXuo;K^_%rD+B1pi+A0>pch&cG=I%)HHG_`B^@Q-B9APV|-nV;1pm|B5qbzedg+cces;yDud@bB%Tts=G0O6 zS3haBY)$RI+Fu{K3iamwIf8Lz#hITm%Jb)1=s3hNMcxHwtYEm%t$2MJ58|(P>+c`l zjkIH%38$6i!d0zAy0oH3oXa-<;+eaC4nl<%kWeUvZb`*_8=&ZB8(RKzhqJ5^v^B_| z^&@SI53HQypgT6pu)VWSF?~9#2i6>73n~gE`WcI_FMt&_qAnyAz99fp&^PkkKT9vx z9UNd3L5hsu0w5NPbZ%P@i!{enJ$bd|pLh;6CJ|d$trp)FwnwMDS|J6LtU19l_o@TX zcvuf(9wEC`H9PDrPOjACRvbe~tvd%d`NtJ8zhH%b8tU(20I1Eli_M6pA04LC0(`^; zAf&1SWt#ETl5y<2xcBm^hlJ;T5I-rBn025Q-MOk)G#G0ZI7Z*zIeM9cv~M(7=pqb6zyd$SY6ZvIKU2?Cgb%bTvD|f7SevN_%(s&SIW87e!x- zELH+>62|*CYAxyFdodq5h&r?ol5nA50Zie>sRyC@kDw3h*7Um&2-Fs)U;X_kWEm;Yy>I1pM5W?y zqy=3^(y4c6IW?$Kw;+eTQCUf-VbnldmvC*2u})LFDALV_$_3M+*LP7Ao#XF#;MwYI zqTB>Ocg-+kwrb2fecxcAPQOSPpX;mR?OJ<8QMk7t=5MnZpgzPP4-gK5CR*Gu@sXrL zuy7F_F+rNo+UBSfwZQ8qXD0^-ub&^B?IySD)ys*IinCjEtkxs$>2K*6qg8N%CU9T@ zWDXCog2Ot;S;okio+G}^H@|69FL_w-n9e)Nrc-jdxG3j^k@00?Kvv+%C@s9?bdn@4 zC(uU%2}#QHS(+Du;^|q3+gr&Ci6b_*l9RF|#P@=JgWw>HdLH_5hs3y4EW_yMnGC8jTooe-gW?*HKhm42mMK-&6mc7eH7NTeJ zglBaGkK4DZ@=11?7pR8xI_P-kQcsX1;xch?a&mm)1qjE%pR6S|q7RMXPc6B?vrk%@ zjPl~GA@vdDE-<^oQ*~OrlS#Ng(%(w3%moFA&%wRg5>qU(bxv?(L?n@D^iU)`yz-P$s!Zh z`)n|0*TRMt50PR(cof#j z0nW7fbj#s6@NYZ(!U8gQF6hu+Eu$YiB>RZ(6du@0T(}`N+<;Dz#32*85j3nQn+`K> zTcLUd&nzm1`rI!;iiEn0heu?L0+8GtVB9a&HK`%a@C$aU=TaPQ&aZr1SIpTxh_d_l zoiq-msLz={Po5Wx?HhQ=U|@WtVs;$G)mU*Z3C-xCZ{^acWzOr)jd{goIyrvvFw#lO zmu^#aEigBdY0N)q-MmJQVMT&LYzM!IANt5txIAw76;5zrK9K`sHJ%>le>8KAr}qjU z{kK2H8|B@-x0BiJ#oYi2^;U9kFl;OLE-FSdu#$-Ez)){B86;TTYBrh>SRKZ|V))gj zfjU^#W(?Uz0&9k0T}*e2I^@cHTp~Z!ZYa0X6iS<)N|SmOqK@l-Ad~oG_Vj8uzCY&| zhNsKJvxC#KxM?cA%=YKwN#y!Hxh%>Ki){lBsP4}CURp@TaX%h~t6RUFu8Jf@=|@d% z4XTjSlYh=9pXzE}EMTflD1=5sS`g zUJSG82m?K=tr~D_^%Yx#8Ef65;2LXvM%(KL!%?75AwSe`cMf1jbpug!P2+Y5_iH6K-<}lYpPZ(uQXAeCEajJre!7R zL|Rr#_{mD`0%KjR*;PtvcHJ~le$`GE{=LfU;#L}7rLgnxY$}ca|3o;H-!Xi)(iqra zuu@s4#^>T_T?#%32jc6RMr}wpp*=bf@gZzxD_Y?}(ihn+g8**ANc6ri#M;p?+)C z!r=P0YFUsvS1l`kE~}PjSB3?}X_C;M>VMZ+eH~-XGRE(!9TlVct$T_(nB_#Hth6ia zjiz2Y$;a*v+#d8h!t<~Y^!)J59Iww0o*$q5wEqOo(m(yT{$Pt-B!3#Gv)Q6@%ijN+{v!!>yW8z0r`cqdVK__gONE(`&SzIfEFI?6V3g+L z3PoAWBt%}Lm>*(39Z=8;c$^jqg>{zbo+^3AjjWpw%mqk;&7A+aDmISYi41H zDeg^MT(erGgmkaT+3u5P2l5P*rv4Kyb$GOY@S|7CdolpA6WTo7N3&@qFP22Zv0lh!?qWg{cpP}`K-TM!} z{2EYSX34?(N%9|X*ZOl_3`X-I#Cf5-W8}WAt9AGI(E#$KY+XHemptVaor_a6Ee)Z> z;Z%aY0h3B%Vp4NSC>(~xIj<=!89R2ANd-tU9PMnbN#oRB676*tFzImCDC82M2W)N! zKQ9gJ3VZxLf8nL8p$&3)0Z>^Gp2-f~SREJ@&8(nRizWnbI4_{PE&MMf)~r~=fzBa$ z0p=#Wf6_O}#!!-^RoUj_;kj6^a>Rq-$Na4+sA^#cwAS!^^D%&?RLNa?o3*&`!!`r} z-MyPYDFA-mI-gfJeP@b9mCL}|S}+gL@Vt}Um9{?|OsCJ;*Mj4E2Y31|eT#E{;t#O4 z>0l>#T$p+&nTqp-0%wxE-`z>_N6^1w|J?j~?;cmVe~x#g7aSaj-O4-3{*%{$N@0fP zx^xFVPxsG%$zN^p?bdayxt_hUe4A%MrU2XFAJQo)$UZKiXaR`fq-H)E$CK8(PICO>^>^uLhUUp`Tc=W62&pJOrSH%;QEeQxVV@p8J4iNW zQxGTmNo@B+PtM>ycJi-gDTfd<{7`i0uD@6c`is@I!`FZ(10XOrP(*KwPRN)9KXBD7(>gXc!wzLiO>nzA?-8TXSJDcJbyPCxo&$Dsu znd*amwtIP5dsgQZ&mhTJ7HBSAb|>5v!>k%i^K-LjNhpM@PWfOyGL^Zs2k5;>i4-vS z$xIED#+?d*;gnU)FqBp~0Y(5&lWkj6cC^!(Zis9}`J}i7!%bMLEV1GsVxohiY-V!` ze%QA;%POF3(1uIRBw%@9Yb-*!E;=|Y#FN7w2%;lx06gehMHK{@%2TCQHUk+Bvmtyu zuVj*T&(3!DzQZ(>shbkWOqq_VlD7=4Ihn)T$fPKH%m!PXjQ~k69cSwJSp|XcgGVyu zNaI}JLqc~`=Hhz(F!`+7`m9=)+PN_eEvy8Ch286FsiV1hqQ<|ke^&i{-I~-2 zN6qwRU3qoYhaUw!USXu`!SMdDy=mqtdmn5`yC3l-e!{0tY!^~dt7)K)nC~?1@xS;q zq(R;0G^8*7t53r()(){B>ZHR5w>#<1k+Qj_-|viD^@ux`Kz`pxzHM5CcD-RY|zlDt%HY5`=b?+QjY~SGT#@&SzAuFq(P6 z{{HqmV#IdJ00Tt)%-vu(o>@lWt$gJ#W7{JY<$pZ01QEd`fcc_BWg>e!S9X@67TRJ@`c7mWz@ z-09oLeRdAsh;@MG4d@zMQkB(2IY|RTZlrcrQsr8d1 zTyqC9cUZ<@xMq>j=1rP(X$Vb=W)-#S3M|;w0SOf<0PSWJUc8BMEyMZLM}S2pB?-VV z#}<#q96rS*e(@~Y$BY^z6RGcqY7Br}eCmQ9VgFV*qDF_KWp19))fBkC>I z^|-&itgZ{h8y($<=)melv{H!6RZSUo0@WRIO{Z9qw+rw%<)c=`xWEqy_e*Bkc+&I! z+O{WgCwb$sOdJaGD3~BVn2Bd9)l@(Ezjf8LJJfSL%i}s=$bJagn!8TLON5NQ#3UK# zHXgve*|u+{`K5amX1w=`_^Iws&rS}HzU^4={90HIew#iGozlY+%!=EJ4Zv(i;)S5w z5Ic#Bk%Xlvh7umO?N&cCJx4#niTqZNrNl3MG*sI4{7Fl`jd;%&xaF`z=;P`@rr#|ik5mLENW-`O23m@@8Ru;P z?Z;$NPG@sN0XG_InXdae=o%!S#2XjgI7Gf^b07j+BW|b94Za?6+Lj^aYO(2@#+Zu} z@tbjCctj;W!-`8$*Z?ccxKTA+jX`qIvQ!bjRW-@o)YapcXT+*R!EJ?7J}JM_&P zG6R03uu5}W>Dv;TOj2??J1LR|Gbtr%SP467pH_^`ztqI!7vQsE zMfm`@sm~gckBwUeA?CBCYtvaFIYHo z))k{-h^7#Ai-L+w0yCb>lr}QZU_rgz})u*P-U}oLq`S(Ltq)B;|#t* zFC3@`o7tadJUk{ee_?YyU~*5LGK7%AKzmVBBCn=3&XvX6DvTGXh3%d)6$2-N+zI&W zgc_v1+(WIQ?A{*!$54JxZBb=4Db7mhqwJR+?Uv*oL1MtJ+FoGa$Yo7;fAhnZzQb)}KlFvchrg;)hd)+x0?YY@_Qce*Zj#Le*#e{NA7i2gERW+g0bVFI}*c5t> z-6oo0$3#}sR%fOS<;xhl7-HmI24TxsQkX=%Ff{eIsd<4n>}^e$=(y}WL`icF{@FB` zX*PkIV=*J0zbQ&mw?Y5yN=7cj+L+5W5@ZF(JG>^uDQNXXY{$G zSmCZABG(b`z1a7>Ab8K=be3jjGe3 z)5`#AfIc{7KTXdvlY z%2Ny4f+Ybv)M@I-jB{rW7x$&3uB->nuZerW-czo5$X9GdO1Ie@R%AGXA+tb&q*lx> z4;-UVX2sv9sHlSr4@#%PuJP-RONnVW1W~wGmc$S$dnB$iazMSyp`Rs1sYuR9%dR>u z@1~`AqQ;c`FLb6!{OSj&Z^2hT93K1)%6ozt{`9VS+ui~0AE0$zYn;Tq4~p6~wn`o-?I2d5opD52_?2RAi2K+X&DZeo#CPmVp6*X^pW6Wobm zqHyHLW@Wv-C~m50qeNBgK@?OtKMHI%IvES6W0eU3F)vN7LFA;gzviS{SL&N}6ou;3 z1#`5npyTwA{aaU<_1Hf|@p5F<*MrjBbcUis0IX&s?So4t5-DA}%Be5O9ahym=4x%@ z0g-k$s0x>hc$#g3Hcm`3HsZ(KPK;bKNX@m6?tf%npjt?wkHQj(;O1U3P78Z2vAEMl zjsr6%4wA=K;oztqHNyISC0{(67a5)1hIF(>{G~ldWIV44dh%~z$e ze)WzQoY?jaLQVe7pPgB)Cyo?ck0)_mn&y1IDINj*L3Z%Q>om7^ylv{gB47N>s)Rpb z6gKLcN0AoFn|E0ErCw=3!RiGmr%6Ybw0G+2`Co6_hBFXbX-jKAZH$ysEr!qX7opb*mDbfFP&YWk*o#&hE8qr&8Pf&@?& zcJp>c<)TB7L(y=F&IZqHbJV@2yJ$zDz{bA>STM9VWBa{`+ft}adKYvvUaz75lWYL+ zd)?64EiAe}pR7>obOxf$3I$)x!3dA)-fqOgZ;J9EXb!mfxR8`=Lk1{qbUsPY zCe#zoYa;cS2BbyGE{2cpN=@9xs~zW(HNn=qHX}>eD7;r9fO}Mx)7de`9NFvb>GA8M zmzZ!?26JyYr~+Fkc>kh($0|MZAwaZ{cR3UwjdkNb-A&eyj?XZdYn}N-niDhw8AUKj zqxnxsu0y!r0uS{{GR7F8`3O)qQL#&0g5&~RSjUwR{?gO)MYiw}RTjewDGMak<}G}S zJ<5hkn0k`6@UHzBOQ}sGL+eZ9|I$@LZvB)Qrc$~i4<+jWKBd|#!z?hK6;zX?;`c%Z z>7=-sh(6hI(#30pXyB0ZlUv99pV$DO2fA@n`XvSuqORLhD%(mEbOhqyy?V$YbWukq zavw1ucUDRuq^rU70B!t0OiA=WfVWMD0wMR=KVhJ80_(6_CD@16dC@U)*5t!)JTc)74Y_sB*vg6&T2=^aP9#oSfcHbG4Z^&Obk$6$yRuQzg8ltwR4YV+ z)ViX4M_IMRf=;T-CM~+BlbMZ9HM8-Cx=fqKA)0?Y0$E#VSXfDhFI(HHJ#5y=(UwNJ67#Dx=evl#92EgzoPtCG| zL;7_JiVCo`nxptUA3<;m>U_%)uofHF-jT2p4qI^nf{7^U4QEZ>fm?_f59=XJzX73< zfDn5SX@APWdt}E(jTT+}veD3A-a2n%y@`u|b)pK-jyJPTFm-J~kI<>VOg4Ki!jZ;P zl(Bk(wR=mIur4@KzT*>t8AooUpEavBmkmYqcT~C%a#09DiAcp&ghRd{;)9&N0e?Ik z;tr!^P|YGTg@V;spps$W4D`SSNYdCeY%14^QDT~xrI}jZ60gk=UuW<0nJ%{Z*z7Lo zHaeCr)cLN7;X?y-K!BD5*9_grsk@AjQ~7uB8L&o`v~ z{DQ{e0WLOj}{01qW7Hf)XtDMVNwg9x=Bmx+8ms9t+RQ=N4T3wUf! zV%~u3S{p&liyA&>QC^0YpMxO`ej9w=_DJ!_qeU2YC%NzI=lp~mJlo;+qq-MVZN~Z=s-7*X8rJZ( zRoBxG$%X1)tN+?Ne)bH#y#^yRJb#kvi|+he?w0sl)nA%cBPuYUe@m+WA|05%0!#az z54YKx^9j2VpmAbq|p#!qQc3g!h#m);&NLv;BYWZ<}^cOLHar9Af#?3$Q4c^UJGR zBrSG`%#vO-4SQF5LBJ|xw%>0IuVv0UFW>?XH)S}zrrL~nf*TI-?OQ#_tf}I!RTC=w zyw=9OWa{Euob%K_`$;@ci3AnJ) zXIXJMyYdAOD`^x~rEGft|3a%G0)qHafcUZTVJ9i>-RmSDJX7Ds2Xi?8{qxTuj>o*- zaW(XNJK;eKN?`kbV_R`=H0PtEjh!H~1K6yr{Jlv`B&9p>${|h+&XZn*RMw#ubB6W5 zn9o{PZw|voFXfI*%OR9;QdlQ>({bIF6U#a_!wiv{8Nd7G&8r;%Qc!brC$G|xS?HE6 zfg+gw>rVgk*Pn*~b9yCoQS@lat6_eb&!occt9B&%(v%|-|DL==_R3+#Uzj1a@AS{U ze|@+w2d-?a23+U`(GN?^VNoo6$lC@EO5s=Nv}$ES$BP(dWf41XWsPM%IGhTb z?hpzDZ1SQc#XMDqrVCE9U~LEmdjvU{4G9y~kPJA=R0Yt9+UJxZV*eUE!I-yoPV zyKq)u4ThVIBo@KiYxz6G!@R*FYTkDeo|+AT9|%-GiHMjyKaQoE?xm#KTH%R4YK zucUii_y6V*2+ZF{e?5E$VY4p1g?tI};*=K(x^CUu_oU$EN5CHKbIVS#QH0aN?@vq1 zAn;})d<+nrh(RRD!Fx!~GGpVXDLR1|6uQt+Ej~l{KwofhW`mxY@??_)%PINA2DNB7 z89a^nRynl@%+ASp@7w}QwKcu@^C?D#&BrrnzF+H6up)Hd=G`+wR}gs z$eUd4L*REw|E4|6{h4$ujgA4H8;7zZYiU^I;B62EWShWP+@G9HmC6~LWjrrz& z)PlXaTqN9kfycWB`JfGAgI@8kMsIkx+27T-Ir0FD1LG;fF*EoyyQEkK7wGHjL5?T) zSqq}`D$UdV~*|^_y;zNVabu!qS_i|iuxE3X?L;5`e=j> zEp_dV8WjYeayp) z=EQnX!&UJE=BT1OO53HW(#?}5?gfqx4E5H9t-&?hBM*Bn842KyJCvw#at<_aJZHgr z5ct*y1&On$Yte6AcRwzeSjx8rT&a_M`6B(?^fs%C9Pk&)JwLT z?CWJAE()Whr%MNkySDvW0-=RFXGF%6v)9a9da@I`kujUakH-0U5(5OIxI@-n$^`X1 zz(@&C98W0oW0*xIjc0ocfT%pgJr;#l%}ii{rWQe{EkU8u0Z-U)ySB;teR{FO!MPwr zlY$CG3l^u%;ReyTs=sZ=yz4>E3Zt$8o-Tl(bC>~jge!{(r#G~&fQmO^(s^)n9_F0G zy;>zjL%afh;2%zrP{pn?df+pO5nsui5%}^p2T2)mgA&N-OC^X$fRzv$gYZ2-Hbn7B zEb@q0tfMd`7R@Br4Jf!^)09(ye@*Y62O9(pb(s5>=8R-%wLtjRiQ zm=Bo!%g5ZJDfTJdQjh{Eru7!`0DI9iYoLK)cERvgL`QtRLscWvhgs_Zp?yM;gZGo^ z7D2mxAXBV_&<<}5N#?K*`6ggPToZFNp@R^32~Ntqn7Km;Zfaz#G6Kx?RX(^)TObhC0*gKw8HnBQx6Cwy{Z5DZBfEHh7(#2|LkkN{VTalvQigXZEf_qNJ z00p)_{L+0Ti4oo3pYMEb$AV8$2@b#69YB8xGlyTeb1X;@iuZug4vWWxsqo>K zVzURPubt1yY)2s`^tjzdqv_`6j%yP=`|0(L?nh7bRS?xw1GZuaEz2yK{$e+7nmxY) zS-86uD)hQ>KfbdF-YSC{AW9eFnGqINg#tcQ`XG$?Ra^-CyPcYSBYApq{2VIYi5G_^YsF0+ zJF1CYL&C5t7!lD@=pda#Zf$cfd6$>-3bqXd71E}?D9yogP3SPy%+mm-qw5qf*^Qvi z-bWIdLFAqjhTjOlND)GwjxO*LYFzk7-DPknNKT)j;%tyl5e>uim=4wu54~$r%(rPF%+(R$Km^ibePcbzC{=t#JPra?C~b>gKpDKbs?G$11By{C;(i9` z%H=e_L>s7)IWO|dIbDoNXuuE~G?ZP#vcFTJk~>Ci1wbpvu$&Naz~0|56=p&#JJWw# z`9k;}N*D*$0bJA&QeJzt`_;Jm6~*YwDPKvkZy)P0HjGYlTce5BOZbv|7ZO%zD)AeS z*-Lyxoj=}a0yhgYP@DEhXQox~JeUaSWr0aX;DD=YF{TlCpd@klW*-B&@nvxiH*Y(c z0X;aWQWm=%AtJZ>;vHt%Gs~}BdLgG%?XYlm6x_*^Go2n{X%ZLb&+nmTg0a0Eg5Mb- zjh=~IG6AX>ik@FpKF)!M53>nKwL^0Q8Gx~xV50dih8RZk09TI2cuu#(o(QGK{Opjy z{fLGwp$rur5yX&gEQ~5xOORs@8vxc}$uW70mTDH{ln4XJ{e2;MFMXzIwYThy(!sdp zzTOd06n-ifMdNoc77=iLdf9-y?}E@5;q6;U{Y5}nZbz&{l|W-RM3>qeln>u8Tbtd{ zsGbdQ_&&%6XkF{??4N%Jkz_jG8F(;;8$A*dUrX<1A>N1YtuE3Wrn&iFnB^^R2inhQ zez#ofB9X5(sik9-8DxI@xYm%~EjC>35GVmfa4YP9B={D>15)b|fjKBVXtQZ+?CnyPZ}-PTn_Hy0Zhb2}~6h zw>O9?TL}-D(W9H7g@I~siH3}ytb&ESa?`6LA=5XXj)Ux76C-%Y@rhk=t!`Vn!&LSz z#GolThP=M3;hchl<_(@2j*T>2h+~++b)`F#QC+-Rfz5(TrDB8_fJUJ9+}VX!b=`|Q zjonze52PZoU0@Z$3O%5!cP*=kONbi!QfbFdPJUWAM=rQHF7%~APZ~Qc63@tA18*rq zIRt(Ie`}$pU%?`Nl3nK@DZoENZ@c^ZC#`SV=I`#ujxHxY8C>OPa$)voqIu@vZWUR4~4~}*+`A~(6vI!D|C2wx&s>c)6}6HjXwyzM1nvSc7jD)M4Bbw@fsa~PyizXmUxk{*dPs*>>44uz#dcjrQF zx_x^DINIfsd1jhjkWlSrp69v|K(#Io;9aX9da%GohVr}9X?k;-f5=*PR~s^PzlSb8 z+IAqi*5%q|zWdZzlp- zoM=}k=X}m)2?x(4fEnOE?F{GV*`>MlT0VI27% z{^5{!xBFfkgFTEfLM10RD}i57@RjfKDVU7R91gC)hnxJNU7gTX3~-_J1PtUQaj%@c z*Mm*wiV67%<0fs!Aedl>OUC7m2*;sRjBAnr?gF_QIq)>yB@3xCD5sP%jNI}|1*=J2 zsglo&&!a73)YAJ|v@NK{H3yZ#0CTC>2N0B;=V8b4CEFu(>p+_AH#HRS_(JTT%cuHLN8E^>J6@ zxBT?tz#ORGxBGn`)WsbEI1Y*wHdGSvIMxM<&wVW;y(?^(@d77j!ksB<`Z3lyub{;8 zT=rC!R52LX{D?~+I47XlfeE#6BNaOuv3G#tF5*ta+h4mXsU9$DBG(H<0XtEJ^;vK_ z{#L_?3V(y1ot1&=&Bqo+IcSQrL8YyWfrL~^IwI;lnr%?4XDVg|o>*t~1md_Vs+Eom z3jt+jpQghB0;lICV>Ez0b(9Z)SyyH-^mcSvnuGXiT#?@cm~hmD9v>y5fiSs1sMIxd(9)^I1NsxgzOETfHa@hKP8B&z~RcAHqyAR1HHpm;?8m z;F~E4C8wPfBd8&kr&J+85VqO=#&9ka30j)fczSSha5VTuXuTdpzJpHCHb}h2_7;-+ zR?XkF(f1Vmn4a9sG9Ug4p0fQ=xy33U`H0_BX-~LjhgQN^ymB?s1D}ZP z6tR(fUE^!IfvS^ToHFz%EC2*hCx}3lFM-GpLJZ&|o4SFV{Uwuvd26PJV9Om!Crw?u zj;-lt(g)Y1rX9wD6m)2rD%3&b5ZNAnqA04$?G6mC=tqcH;w4}zU`q5e3BsUlVPjRm z>(oZ}!NXt3{Zvf~l;F_k%KZ5}oouw(1@@kuTE9ShLpXqoq>zjh=DLay8XcNu`AHJh zhhOLqD~Vwn^z2?Q91m97RZp1~3Wa|k;Sm0UZ{==U9Jh!gsfGv}#BJVaEdpZYym4?G zZpBGIN0r*kMn9@u06>#Rhc-dSvK*a5txfvCZkV%TGoewV~!24iUG_ru{6HNrC8zagSwV$#Q}cZYr0oa-s2f=5 z_YlZ=4h*yb0KCm|UdvJpxeOsSggS}XZgGETFD-q)c5vt^qP@Bl1BZf$9(st-Cj#K; z;v5=0NjPsOd6eL{cn5xB#Bp-eBTQHH5#snVjrdPJqc){3Swgr2nY(IrVeV#73#SEi z*^>CePF=*_(x|`{p8#rrc5CyFW2F8^^9XK5-aKHeWM_rg(?l`X?F(;C{lDgX((< zv2!#b%<8i7WOkDr?$c^vy-ZBig$(46%B$h|zNVVz|7=!}V2%{ScGaBVuz^Aj^OK7Ce z%JMA)cUb=dYmrkoBd@_AUIJ>2YK=YyKBNtLp2pQC8R571Yw<)k=kaJ*NZmfVKyCw# z1VDP-TlWYd7$j>io>&9l? zCXIhA4ZJl@BXl-37$z~PDvi6$zWA1L>|F$+uq7CV6<`aH%2jaJ8Q5IG zjw2GR_@)H{CUwJ06YtGe49!u^NXJjmBw6bSs=Q>lc1(c?Q|_Z-+5PIn7t&l&sbQ8P zP%UHX2eMU65dB+5l#KGlJDAmS&K(9l0VVd(>bspef0H#saZAyjJnLR~s~Nyl>t>HpRX4Y^6l^OI6U+^UtaP5i`hGpDgUy zM{SyocF%cf+_HOir`uhwVmybO+V@r+Rhn%(?bHhtp*}pBU;J{vD~Qw%a7{?doN<#K z2W10)_L+ws(iSTK$(+h1{2ucI!KcvJs#yA?g+xm|ayTfB|fmc(Qp$gPgf_rPt(gwDd}1hIWQ zEanypHI{R9VJbcc$Z1_BE}$8_(tvIxAJ0dGFp^jP*%Cw_(`^YMHk8MS^GVt4d7&a) zT&awuf*@6v)<*7vd3*?Qx_7Cx4u!M*S$oyf5koAfXw9CNosKy?XjWQpXD}M4LQN3wjxfXs)(rCdayhESs$M0Z9PITBZi}hPLV)hP z1Jf&ULWlm5j~nCh7+NEF$vbwLRo>~VK4DCYlc~*4UUNxm^c%}_`|5MC*b6%cvD?{+ z4&9>YC+M9T5qpJ@kMaH(t3`r$u!J-R{xbT3?Wi|SOOCF3{ZVY&+tJhu`aST*^T(p4 z*HO`vMTqE34iQ*%zT1(@&ocb;X1sD6iKy%o|-WY2{R8g_@U(0AqN z9jIu`=w%`~pR&UMS2`k0DVI~CA98Ebnk=ia@O^U8=dhSnT2*rv@48JYI0rZa%Jzrw zS;_=LrVFaZu!XVd(^e9r7BY$}z={gCeZfAdR6*PvQd#QKQhtzbLq=A|V1cyK zQy%2+u=!2Ml^MVqulPQ34c`65=Pq-HVN#O2Bh+x&pmzWAV$)!|WDjXzJ7kqrM9D>3 zxyFp1r;m38Ru|HwkB%YE%k$Cs$Q-ifzuWFv?tV2V*Ywu#^vm>LwQap(U?*S6ca}xRdF2+x zm>ogD(4Z*2Ftg?O?bc@W32^bg)N>2WcrBAI`b-(4)ueU8>lMbO)o}a+{@M-KEEac% z8Rp(8*HsH$Z{vUYr(eXvktY`MHZ0-;ko&dx(BVL*^)Sd~2>D=M#&ZTN!_I%R5r-Z> zz$Z(w=b=NL#D4KFMVxP5t2i9IsM6wy@Q$=#IZiSNKi`(GTwG<1I1}V5-lD+xo`F!> zdbb36UIOj6i8tvgdyVVNdwE;;L0?{d1%U4;7(_VLZf855Bd5yL-tXsu3+2Le4!Q1J zEzr6#7?$Js&Cqi3hl_i5HWLGU62AX`N@_Vu(jPNV-M}sh#!@ z8$32GFrepiVEs9*uR#=mDgsaJfySDf?+_#M3z8`@6(8z%#Qb~~>9eyZ95A-BE4lD<%ZG`T#Y!TINUR4v()@CbfGfqaz(3F>dNh*xB|c@WqtA? z|9sv0QaCQH5mYvorI26lyY_Db@QNA1{MquDvC`qU8^NW~Zvyxv2QqjIl%(1&YX;q^6}=7W49SQcM>ng1?!+(3!9M-t zz-E?$yQph)<6QoZkS?A-*C&CjsPkSg!>ZPdfHysC65&`_vmzQ9$2lg0QPD+@jG5Tk z*W3taUib!kpyvo6fJn*b7Vvr3D^alw1ll!otV@KzSW>css8pd8CtmFl<9*=pt{_^o zf{>CU&IP_RKxl%;8rwK!KnVFZKZv zbX??cReWX>h$snsi$c>m(9gDwAx#275+t#(+I?2b`Q^OEZJeJhL;4F7BU#H}h+tl- zBNk#qoNEd&G6=b4%$S+naw`v}3nsS>vrMJ-T}EE`-s^<^EbM|mfvUyM8rf5@q^u+x zJ)|-Vv0~S>VCQN89;-U=3FhHY307nECsbz1Z`6u_y6_K|h|z^N=9EShISCSQAd^5FA|OMIe9LEBq%NW!%W8 zon^h)S!QZ%ILwq5CA*H*xM4GnLW%gXRZ}Ti7zi52y`<$;y4h<~YvwyS2%ERNkvd=l|)G{rsWJIA-s3y??n zNX>KPwNmOrMp(iB{^+NBg*?V7U@+xrsUbXvR)IT&#Kf{GW(}wItJ2aK|P@F+{btHn!tv^{dJ{+pJ(aqi(`SdC; zUN6-l%?7Cgf-A45mbDg)#goN*eCd3xH2e!2QQNEZUlMaV$1!O9(?7>wrRaS2|N zM%V_FIqL}>-!e=ti&({N=q2DGO$6haR#u>^<|1yV)HxQa@7?yc&j3^7Y-(;vIVfe? zA>;Q`kOkjHv}%5SSzX>s@aqzX#flymUa|U>Sqi=cz`n-KrZ*L8LP7M0p{5MK>(Ky~ zICHOK;3sUh##wTrW28Jv>@xRcEa#rwqL7bb&Z8D;l#ZbgA*C8gGB${I5q7QLLo6?$%Ql2kOtbN)w0S zbe_>L4|T}wmE&*g?%_(K?`1$k0vqn;BHPcFa1kkCmv8etaCMMNZpRwpCn zMey%MQ76aGo;}&!`~DB6si{o+%2bswS=_=b8h1eBmKC4+t<<_Qv00n&5BpCJ*f5Nt z{oobzE}P~THwvD>6aWJmg`5!VE{T&?{RBQ>RSil_B^U7~=K-WjUn=fDJ^lCvuupvKF=%FD{Lnit?vk%QUgCX=0<9S|d%a zxQLT!Hc6)(A~Y;Hn8*d`Kq2@(z(;o4#AvEiJgh6R2pdp2nNOwhzG<%06w2hgkU)l)_PS! zIHxypPyOCrBTzz0pdQ>iLR%xxe;hd4UeNyz12;Jp2TVRB;Rx*tXbHhkuXhBb?qa@V z7%2z$h&sGBy@C^C=2z$l0eGAm-)u?w8lX$u8`~{tf^sX}kTn}r>RW8XAxpl>G%*Ga zi8bols(N)>5Zr|e$4Qg03dC5hcLwtP1|L)7k9%I?39I~1()s(`+^cj9<%;9nirp{* zX(PfsJ@WVY=_;;+#PgaN-Ln$t$3J+NA9^uq;f}}q^4KLIWT0o76?pFE&1{l8tZ#(1 zGsw=L=Pwq|rL^d75zKwB9m5;(`P0JjdJB2$;l@q{cOV%406LDWs-FXh?1VwDj7lVI zZRpH5UYb5>k*n?i}*$rc2PM2v%Y5hL4SK?bv=?&g!p;zFZSe5~fJER8H>v`*;DY&@xOD1;Utxuu%Y}-Xx|n5-jii)MAj;0viCtT> z_)almXeZ}$se-v5a+CAS=H4NO49e-U@gmWdKGQ-~Dm7E1V{yHf`aNKECLm8B-QDR7 z4k5dR!Rsg&ry^Fa&m`gA7oW@$mMaesf(bPcXot_H4R|5mGz=2i~_3nr1Ot!fBN5l|DFHsKiS_j)MQq3d$YTB|Na;3 zmiBwL(d~7+Up;v6r>^<;^;chdKjGIe@8ADZuiM-1-hc4r*F96NcYphSmSPlhqh7L{A}{@?W9N%k&B_G!4)tYoNy7uj@VxWX(e@RgyFhYyKJw$|2wN{|U` zCgz+?zT5rb;PuPXX9ou_l5{dL$LB23hKKI@HWTh?Ypd6lT^rs1Zt-P zg4HXNn{qx)s43GdwYJTzon&-}hMY96N84=6EUy!|3tXquA%OplCx*wL8|iX(!=E2Y zEDA{Y^XlgHEFWiZr`UaQ$VI?hn4@!M3Jx)a4YLR5anuk@5#+_3Q`oZ}e+Tfd;QDm| z`f)hoF2Sn!x4f`@KQ-5V2x2zf13*~H%8>!Y``nCy3%x|h`Jp@blI^W;wtCyxR(EkB z>B??$VQ!n_yfB?L{Qz$w(>JJL`!5S?_}W(BvWWy0e8WYMJiavFblEe0n2bt5xy{T) zdVqDGzB~T@b$M~oYD=|XKj9m;IeD@moZNBy}0g@HiWT&)f6{?{nBQ z>HHo8MVckW`jLYX}N308DpB>GTr9@hc4lH)~=#zTVX9>cwHy-JI0-DOBXasohj=;>G9h=T!tDU&6FT5_Hja6K}# zQ*Jn=^dc8g!kiveAd zF=5u_b@Oph#$J>%}t|W>F%Mz-F2 zcKUpRI8YY?toj;&$zK}^XtfDRo)8gUzs+v&6>kyv_CKoG)#l@0k9MCQe3Y)+mn_b; zL@unlFau_W8!8YQjMiWYG^pZ`c>WOX zKxW>DnPDlHz&>jQh`*ZsI~=+9tuZKJp6?$01b2_(EuImujI3CNE&$XzWJ1cSJMD$+ zq>DuQz$4NzQpsSNR#(Wj(~Ap3QZSI`=>TZ&M|=1XqXVW5dkYE5T)T{5e?Dg*32ORs znht}uzc#E4+P?3#Juh;)ahfVCd@rZP^9(o+!Kk`A9$*<^^v7j6smxC^6PMtYYqmBe z>a1vsQxDD59X>rcJ;P7s2zdeYY5K=&2X$|IJ%gFZ3-WR>3>P^Y1x}cIjX9zX1#B`o znhgw83-$N@;?IHC#8+GQG4UOG5nt1RT`AR*DSKT`-x^V1T2?~z!~6o1RsjmjFb7AT z>EO!L#~@qS=r@sxx2=A;^%b5yBSduJTkz0GJgjDk z7+e2(aqIqqYvznEpoXs&*MLOZ`*KmC2j<*>LJyo2V@e#AFVCKS^VA#>?2X+?YDbet6|EO(pZckmY0$^2!Gr7`cHuFns1%pJ+| z@Z;&$74eboR`)MZyc-cB?VR1;x=&-p0pg)PfSC6Aq_Rk+NPt;d<%pw)cpw181+qBy zrz`vUS?av9K;knMy%k}UO6->)IUuwY`1HM|EKIM>S(qagbicOj6nPiafE83p3#Y#n2Wid0lZ&5tR9ou@B-PAJV+8s%ECeCSfA3zi8=yi%i1bMqE zM?>JxrVcFW^G#b;$Q`;)dAjB7>G}tl+DA0Hp4k|tXHTS3?@@WFPn-L)SY z9%clSbR@#ij+J@OZ<4F+_f^s}Cn&K*VyKn%g5TUtHh)Yuy_@pd+P|m%XHZUVwg!Lt zSL%Q6fBhBcf4W~jc+kCn|4Y#S^txaDum0y>@sCU(W*^*7cFoOXlzgSK4HF(Yh`EDN znvX%RGP#+exfkuAU|TkvU_ho51f`?>Z0!gmbB!Eu8&pSdAGkrLG`gVZe0oV2wkrI-x&lcMWZThA zhm5!8vi8kjY5 zZw;f-;C`glX~Y6wl-2BVngQ%3p7>!H5oUbHV{S+Rci08WpNTujZ$|#& zT)v)|53xDfX@jSYL>@mK7|cbXGOghX!~CE?N#BEPdk!1G%iiWyvoBM{iOOD9oSHn< zQ{^T!Oq1p%=>8juCy2TV$lMy21_NKCiO95%x-t+7eq$%$Y^vU;%o|Vq7B6 z=Pz&!6xc`D@~>I+^gxO1!iC60gaETV1(o%I4^l`mpQuhaFO>HgyBS8iCKD0l!Vt2c zXchNYp@KIgRt2kQhvP&b2;Wz2S#FD4<*D%D_6SL4%_1u=sRTGwh(rUU@BwL}6ZR=C zl8YQJdJ20`5|)KHjt)ry*Xvq1MM6BF< z<-C}kfVyZ^$VDMN$_^fCacdEJjjXh=2)`L&%K|F(2824j8eF zEQ<13$F{WPIVjQnSwtZ5n${o^au{!K{qM7N-z%qv#rU`$`xu)ELH1OGFn?1GDT8nr{ETvXBMF7M(9t)-< zvys7+B=QCh60eEysJfBS#c(kl!)PG&vYbRvl$JnD{#LF^#9~jw7{I6ICYxr~*3lkC zLLmbDt%@YNmx_mffaeMSzork&hYK+-tuUi;F0C-(a4!GX|EH$^0k!VGRR8m3@BV{s zsQ>BS|N4LRKmTI=&+%YZ!r^nj_rEHj{|Xfl>UxwX1|>1Js-R&iK?M02on&1}7&`lB zA+``N9?di>`$2n78vLZX8K0LUve8K|Ht90WRXQi$6LY};w8DMU`k86?sWb{$Q4j%d zePPPk%*ZmVDL}`MHOjWeP7|n10l!piuQGI$dD<*uJh#whk+<{l*}b*%bsDfSj-Zkr7%#v zOwBbShe)WKES-w0xgne>%qOSxc(6IlFY_7C1JuLFSPl@ZBZg68#N(Uw*T_+3Rlhz7%FgR$fP67P4ck?d~?%)5*SDRn; z2#N#${mop!#%WP(KFI)@&WP&v)rq0YaS52YKjh{xDDpIEy*%A*`>OD=0v&jRYTQ14 zG??8OmUZ=5J*sBIQGV_}BUP3E49(l-NfbO9vVWZ&K0kQ<^ySgssfDgl>F8kb!9+?9 zb8Pzb&I8m0L;s+12CNj8ZGYKW3*Ug`KP=~<>zw}Q{*HI+t?fCdTK%b$Jntl2-W31I zFpG{kHjCL+hdJ$yD{Y>Qchr^oJMi&^Qscas10~y%vkyC-x)%EQf%1D_U=U;Bf5Tm` zbnU0+B3%r*0BT;%)jJ>l^c=ejl}_Ozeqjdjyt9vljs?OGzI%Qed~nqncdF(Oc>dG} zW=es%L`$Fj9G0Ga@Cttfjj&)Pz!se)0B6GLcbt?dNh++KfHTb8rE;<|n0{W)5qaNY z6`I+*oR;9kU^v2;z{~3f7W40jf2v~+*nK5iottwXm?e>)`FK7i&TO~^sXT0I_VBCp zz5KkzSKutN2dW*+%>~n$4lpYp=H`ojGWo&G2Bx6P$RUDrt+}!lH7Zn2!|yrEqXY1c&W#na%cb>RY}Y zAqDK}t*tG*xW7wZW1_=!B1Q=_82R-`elcrfe@)-ZuQ&?%V*@5i{umT9v0<17Fkr2f zPC7(_c!?gCq&7G*Ue(Bl{WYP30ec$wo7P#RhE@k*`gI~VGcU>>v;L+x0 zE%gUdbBm_2t+jm&f@FpsCjEHF&5kyD-Q*rGff1QM?|v>t@sUO$V|9HxdIS^k&ws+N zk73||A%Ua3LxK1Fd#yuZcc{`0I|n1qfvy`ih3VIiJOMPFO6x)ODL^c+$$}veHIW~F zd4-&Lz#Ip84LF*YxJM92p`wA*_yqHJ4P1;a%tNZ-n=a8BlhDQ&-{0siLYX;lC)8Cd3 za7#U}h2&nJFv4Z5rkfir^QGZ4rpk@4NDI2+gw+QVYyi5`DiThRUO|??Uml*G>fg7X zntyg1eD|G^`<|18XUbvv-z+uPFT5kB7>cpYo8MiiFQ(*(XV_N7vKiDWktJG^;ZK=l z8Fa75*cGBT0$Kz*CX$D~bkQM@_EwZ~zq@)qKCM=zTaZ^fNwwnyOmiXXgA42uV%WCC za21lmcy&VX$oHWoUysi(=!CQgmX2QSH0kNH#J0PwAWo&_trm8>XqQYpd3p9NMPNFZ%pZ05!l2L8JAW z?Z;BQJe4QrA|No!=Fye;{fd8w9FAlD9V)9#*TYvQN&F9ZI_xIh-HHWpkwUJj7n;XrgbWX|x>!GVEK;Wh(g_P53*nP=r zgog>;>&;NjIrUXfZ9Q~K0=F@9p8e;3E4Iz}64^<1JIRwy@?+2Z|F*;2a_dn;(&AU< zN+&e*6HVSv{~vq*-q6O8ER4hZZ}=2rZDJ%WumrY~1>-CR+2+K658!08i68w2X@IfC zj8-FYahCV9zjf>G>bXe5_Gb5-6K~em%yd`Zs;jH2>%!~2$4`3_4uYR{a&#Z7pr&lY zq%%&^03q7wBu$w#)~Eefn4s!P?)>%)Mlg6U2KU}mx6^-KUN&8VZPs2j<+h;G&kx%z zTIuK56Y{)#5Y)FGJ|cquH_XGh_T=%(>f@#Q&kr7b+kV3DG3Dc0YvoC+)n2OaJ>cs& z7~hC67pgtLG7q3%4*>FV(0;u7Xyx%n9>qQ6!*Q!qR%5=2aLo z;E*!Ev&O^ko;+&V{i(qLio1xu79Qa|K=AA3w_o8k?Uz<*&|g03SV^W%I>oD%>>WJm zrhKmYRD3VZ{AAfXaU8W7t?gcL`W?;K5%Xt{Gx}ssK!AaElg4C_xwkO5iUxya93jUd zAw7E8Dfsiv&CTA$PJiBW&~DHqIjg*8A7GD~ttP64 zn*h0a|L5jvv)yd3^3xtYt+k=Z{T(>j)@Gii?baRmCQGk{Q?S%pg~dbj!3Zt4*c6f` z>tQL=*;2bEkHbaIvpxF=;{9p1EK)9<&hLZepM&+_XL*e@X-|G*@typ3cKgo}=3yfj z0$86nTVssEL>GN5!niou1_xO_RQD3-% zDt2=afH>xD(qISvtUxjQB1x}YS`5CoLcJ0;OwoBP2xYlr?0AjQvSn}S(o8s9Co$F$ zObt6!Yj6&Duezx~VFmaKsa}&2=n7ICuVw6AmSv$$9G{F_tm)b{(=78?$PLV#z)^4J zhT^qdN?{QF4@O8w=Aki?mtm+=Fu znqZQ`@#fPL9%S1b$bv?Gf7I}j1lY5Alt07VL0py2!Xpv6zV2qc*XlkyZJX0N5}pQQ zP*c{vH!BOeWgW5?sRlETr19T#8h_mT)|jnub+A&w8UkS}2O zuxXlYwDVzEJ@Z1bZ$d2d$CYs7#G`=ZCt19ZZL9wsnX2!ee7o9y0?b+CAuwscVXdkn zf5-gg@c%6+X&E}^^N`0wj*Q=+qO(p++Un{`n?PAWJC6U`<~JQGy}SeEnE&I~%qa>- z*zrb%pm*T^e`|X~?>uckg43h3+=k-={$AVAGlhkot-|+hsEK?h6q28h^GB6Em`afZ zFM0q;NU0@S1EF?z#}qh1t1u-i!}5;37I;cZ)%Zx;CoofvZF7Q!=5qt$ZzCiC1(jMSl$kK4bTNGNe``7j?yk7bFY5OnVw(<4= zem~n>ZLNK0NF2QIDBSgmB5>C$JNn_=iA~ol7y3czxNZYFYg~R3{DvhIE#wL|u=`uN}Ny+XD#Kb#ZFJp4(-p-{%XW8=43B z2qNW0m)I4cwtwMixuHohA1_i=u(tWbj{X2x#Ba~l+jF2~{PseZrV+~=F&ZMkSZvYFrLW<{y0N6Hhe8GL*`IsIj=^^Sa`pb9>lj4BCwMkG&#@y0KW zWs2mD&Hj?SgOAox;v+mm^>Ip3vFcL7%8v4xPrR#m+&izsyVg4^Z(!L895-3iQYM9zQQ3qDwJU$&`Nak_sAZ6$26*ncOGVX{0 z7|g(%OKWH$1ISx9stFXXjV&F~3K0{SiZYt$2ml|H@p98=+V+=c8Z+n=*mqB);U5p( zIbjcvPnu{aP^mtRdxdqEt<`I9%s_=+JD83IG7{hkJz!J1?63=fFHZ%2Cp5aMMk7ZQ zi)gfmQ9UHGj}3;NQJ!1ensSv+AzkP)dPHGLG%{J}!fLfPH;*O>ylDpQ%}tOf=_f~# zK{_=)=c{fE9&Uk9>!gz5c=*z;ia%-EY1%lvVUVQD>97hZ6N3S!gSBSxoxw|MuyFt5 zFWNW(nSFk^gKZy*@TQ^ zPdy5V=;5HyC3J$(T}H%A%tRF1FTj+)uwR)T9iF%_VSm|J$S<^-rIJfVd40~yc9FaM zP+WR7ij*UWN9k%b)&i;1>X12UW(_B+>a6rfn^(SkYKyRNg$D10Z4VaL)zh-~)bgI% z-qWi0wB|iM@}3@hPfxt3Z@s7Qyr;jYeSr2VmhzyT)2N}>GI?4=Il7_&ZpJR=YR!c^4P65yAXmCC`!MKfM5UU;eWtPC^aB!M^;{BV3<8K88y$qaT;g8j>mL-aS+}sd#I=NB!uK&T`q~>kW@oi#%9rLb!^z z`5#xE?SV@+JigXy?eTS^;Y0DX)T^+zP$a*Yo}4$nRuIP5E5b*#G(pE>YZG-L&=&k1n~*vGk!mL5*H9gRwD z9_DG!n_*V8k#@Tkd{4^Xz2$b}VS6=LH&3hh=)w3IVO;0H!Y;aA$`!l=M|Kl<-NGrj zxwkpeL-i~!M!<93G?vyptEbyJ5NF28TsCJv=jQA#Bg@4fa7qf@-)f3cIIAVxkvkA` zCDc9Ds8^!xB9X*e;#-FZI7Q(1CF&xi4@s zE42GCx87{}K}wAHBARLfGIUvnre@Hz!28lCn0yu(X4ta6Q# z&A^Mbyd=SG_2rU|3L>ZZ3t#zKV&cYOINBJ71A*rg7gNR918cQm@~s4D!DK;&Fmnqg zso1hyM77Is6sMESccF6rv|@j4G9JJL3vl?uN)90E^#Fagj*bs^_g^-Hy@MV33;i;D z1!3tumtn!E3yzx-9~=FtzgZi3>&?_fzHdT~~(inY&OPuMJej5J({apeBB zrW*wXzEN;@f!XOYns-@EQn&q}Q$L?D%byqn^mm>Y1VKvHc8j&F zRhKw0VZ#yhfHkckJ$}=A)L;IlwaR}5_}9AqtJb_;`59+$5C7W1zs~Wmi>B5(5TjSW zUdbAjYr-ZTZcVsx376t8%iWfwY90Qg)?oVl`xEY_nCBIz^$W}@;^n6xdKrHIC*k&- zcun)FF!@VNDHJ_rWPNdPxVLrOoO^mhWAema%qJY&m!VjdHaq^6U3q=eXA#T4gZk!_ z1kVyThXBOXBV#-I&8vVUZ(>7 z_*Qwj7l`<+U7CtD$th6?>($AmLQdSt#e-*(zZcTw>#2Hn>WDLal>>M5*9IjZdHsoM(c5aRQ6l*6_ zW4r8M<65(9b>pjKvyav|aF1e)LiIq!3j3H(K6qPZ!BNiTFv7pbn`MpdMMS^nBl^c* z-amMNS{GBR82vAH29)AzD~EeNeYmj65%*qH z@8$O;6OwFr_g(;CzbqzBI~#k)n}V%~HEKhy^=J#`FYZI`?!XxDc&`e!F>Z%$2BHOJ zLm6*DJtF+mqOXkMVPEwnB1FsHQ?@scCs9T}f!zq6$X%vCR5&3qylCC<>(KOr*2?2X zBlt#NvQ?l=tyxbVe7k(rZ#?|A;g^1|ocBsqFr^?70h0&qGFTq%yqzBd|EmlGSK3d` z5CusJL?ra_yBr}err`44bX?w>QuShb)hvhPc__FDw0JX&)*4@KQy*21#)^H6L{kTb z*ZhvU);$z#8x(9n=h4%$^0X}J$Rn0f=U>=wyq>`0Mw#CK)>;(3cNRsng#{}q&^Ere ziKm_)D49b*I%#6z&loW26nFDIIGE!k>es7-@-zac1mehTF1`oHN0Xc>qSfK-CpwrL z$P)nG3)@DwSr`?7)AXG19X5r|61|llqK)#>VJxa^m!a}Qcvi@TULCT{#U6*bnIjYt z-Mu4+E=H@eMTB!Up|#DSur)eUj~EgE_-1HIQ2**n*Vvhc=I@u9n8Dkzm2TGH+}UOqEpke{ZR5r(R2YGKLNyj79v7rf}l!W{C9HXeG9c$21?G+7!> ze$zF`N@>)kLM&m`JzbRhhIpXM(vtf@zH=Y*5om3zU5sc|+O&FM5Y3Ag%e(uJ2(OyvLEJ!yT5@n6@zee_5C*WV}pt3=t&)vp`$RKIS%dEHIIhS|fmI%N#zY-+Z?dIuG68Y;K2dRq=EyY#_imw6EK##NW% zOr}=5bOl#GZ(d)YH%GnZ)p1YQ4YxBFuEb*I~H2Ho!K-F^Cnie{)1K%IapEztSB zU~0xmJO;8Cur2`TWXz*IMI zy!;p}L3aQFy3j9dP<}SW+Po=eK6h64fqr6rfDfk<`W-*t?R7hcheyYUbpd0vzL&_v z#g}zc#C~rE_1zyEqn=lAcv)wlGD-GZFNANW_G7L7O}~L*XurugfiJS_)M*|kzH3NN zf#bv0kCvZND%#)~$UF_j`eSPA-Gi=hyHN7=!OItKnkFWs1fBV&FY)>#*g4Ru*Y>YT ztvNIJy;=EOANc@-C4}ZJHuO)rgY+y;>Nw5)6Im$uVHS$s@dEWvIOPsMVbW9cdl+U} z5q)TRqp^)9#${oY7a98NqYCPCXO0d1q5r`2XNy7IL>v7kYr3?--(-!#yqU5135@Nt zscWarcC#*%f_ZhUuB)34BV=O|6UhEPj}kTl!{ zE|?tU^}=`2?7i4}ebmu*4zwM1_ud?Jjxo)uv|&-!3?>GCXcVFrLqV`#le9Y-pMKZH zF#i=roHT*~1g^GztT%EcRO0WdBFJ`vbOPUj>~~REICy)^W&DDa$~o$C2J>z*84NPl zFU@M6OtPDDz}w_fgT1sJ~I#z>7lNiKlhIM`RnhKt{n zzYSK{kM}mMg!BWy^^7Wmt8kRmYm%l((rpe$;n_uqqydrIA_^XxU%7$LMlv4g7s9kp zm_GEJ=^}rPeE7e0+OXPJ|GsIX9lEuBy!&IPWQR(%cK#!97Ux(ikrRD(*l9x zlcm>{nvB!!^x`5O6P2cg(T9%e-6-YVUDw_6&jusf4$>^rvyvxqbZV%h zFTCtdkZr6NDQRO0iLGzJBsHeOarAa7B`!e9W1Po5;!;HzVf*He>tq*#*UGL_#f&?A zD4+Af(dI3E5x?vT-mTM9I2eUs`BPMnX-=Yec<}o5^R4Y4CqTB>rW$}`HFLhg_<0XV$U5&DoaifU>K)qn|nE~hOG__ub`qOZ1oY^O?I3Debzb-B|g4~@e?lwDr`LCu! zQB3J&Bz&_JZlV`ol=Z@4l)sBLkZtp5=S^nw>basvc5|4rzEzAWAXKE^6ve-Euk6W&QQRQ?>_-OioN)LYA>dY z*=cEP~|sP zx0C^ews24-Uo6vPxf(6cmY>bu0anhF@Feh4jZnxsm<@Vb{tb&#ntN9Z61G)uz=%An-;p=$~G{OS~<>w2JqkkS}Fai z8pO6s{S^R&P9xd@y-3~s$nH<;V$pl!v(+<=;e^PEkHq(P-nR+Y+lGgOSAtI9Oq zY(8$woWKB_A9mMPgJG&z5MPs2Dsflwm=0oG)KdAAC?m2ASfy4K;g)GtVOCD#BnDns z&qqOv?Xwxcg&qBvUDmfQw+;`te)ibt#xF1p4<5X07{&sFUe;rdZx9DhHTz6PV5(EX z6HPF=2e9ZATdkgB5OcWC#errWT^{_vPmMgr+t~t|M|Zyj$zq#2thoM0UVwMUBFPD* zlBFrbMN0XWeew%(ba~i$vAutcOn{m5GU1IH%VbKYB3mhi>Com7{nJK%t=$~iO=EG#??DNjc-Ti-sR<@{DHOg7q=6U5Tz5G(j+2z$aHM2!!cTu3@E2yd| zMb8Ti)8gOZ`)kam7y6)XxXGM)Yy8<0H|OoInXp@B(*T1lvM)*tVY^LETt&)`R6QI3 z@9c9Z_bd81dys`Q`3sKL9)vG;JFj;4ZIo&lmfOl2B)9t`X*TMk4Hd%hISgja zobp1mQ=+MWlWXqz)rzfrHx15GlD(|tI=I3z$DPMz+ztXSpHSa=z(MhthamkBER%Uz zdX+UR<_Nx3PubKSdjT_Y+!(ev7b{jiOOWZk!N@3~(;OYb&`5ddX)`pE63r5B1t^axfXAo}nKIlZg3tR95U-`9X&@ z$SlxZjVK~Wpc*B7j*s?c#As)SW>DhdKo=F}(^LMmbMW^0YtJkKxiw5#pXb)F)!iSZ z3z&8QbNc}Em|WJ6F86;l9r1>hV^Hn@+VT}~(yM#C7MVDrO@l^2qN{UZAl3{or;7u^ z-oJ>WLEq!bQY_>KRcGV{ z(V)Pz$3t>Jp#(lyFq4*@B6faH@^gU;?>hXoFo&%!dqTvyYh2r%FtNi*Kg*!F3 z5z4NzgyRb@Bap6&uwAe|R9*+q@U%t_9ZLR!`bkk^1&fWUdorcPoPJFzAm5cJ>hi^9 ztoGQ?D?DkYfgf`U{o;k0k$A$(28E;&nEDpLo@3!@gp5~R$~2}=vMtWjStvW-J!A2H z(eH6le4PKD52ipV7|aaZfAhMViA`HUWaPi6aLpb|f_uHllQ5~6>r8N)iR)C{hRvai zDXNO9Y#4pYRjT`&kN=-0KsXa710!Io*?W0A*-sKPXA2Tv!Wigww$&mmw`a9D?|Pd` zpT6L8D&GpK66mI#NY;OB%qrw5&B|;exxwO2I2oiTU5s^pM~)i#lT$pWnv~QnNGWW* zJkXU48CKyOUdmg1;9@zBzg1@DcXWJk*y%Dy9!&R8!H*xJo9t3?_t|Ap!^;~GO3GcU zaLH7)F-@K8DP`HjXVm#`tk?`{+R!hr8#=l~oUEH3l~7hOA4FBj_jxjUM_tu)Rn?ca zB%E7!HC>0LEDXP#iQ!$SOQmJzbRJ>41>&@Wkd_leIajVHN;p2=Of?|&?*BAq%JB8s zULy`$7urwX9>4hR1$`@8x4N$w(zG89M^P`tWRCp_WobZ{MobTaY(a1p#iM=_W!bOZ zo%kFZp~~6FUyZ5E#2o%gK8#P8$&x$OJMQ@zPE2!;cRpvRxd-hZu|SNEv&)0FS#Q?57ny?M*;~aI%s6}JIB}<=9(1ONdb2xohxWz5D!cS=A(Z;X zN=n}4d~rnxiht2DRXeUFgRMN7HcsBa_Mx|{)}>BIAy+l$T7SxlPHF%6=QlYtBaH8oS?H!QNcg?c5BEzPEa}K& zK1Ol}za&~>fS3OzXc;Wa{ColYL`t~z{B`Hwgq}y+TmQDUkyanP5OQ5OdP`bj)}qlU zb7GS-As0JCF;*`4SVe4FKA*5a(_A~T9oBS{;%viLZmW7)Lt(6rO$)xtu^1qY#j?Qm zE~6?zK|m=uw*~jea)-hAl4)faHrEV`m&miH*vo43d4F>HMKaOR;U6IkjO>(l`M5D1I*fgr*hDc{n;^XhBf$aIHK4 zep0wz`ldeH>F|aV%enBFCPTYStbyIlgh?RNReU3GjWbwDOoe7(YFdAvOJ&KEAFHP+ zrI2a?HXH@SdBrht8$^k4(SqMDytRyX>0h&SbEhVR%Aspf^sMnxo4Nnq0K>leC6r(xu4iPmcyr>*L+YM3<5k3+E z{}?IEwK*uEVvP~EKOsA46TT!JEoNA#-dHD`o{PFW6;L3D*{7aMiox-Y>%u_PSw+3g z9aL!|X~*3;H3taXX(!80Ogbns)fnUpUflkVVl2rB?@HjV_6}^@ybfI&OMmQ(Nja5?!j;LN)Z^ zCnLMBXTae{IscZ&AOFjA;-jWYooBa!B|bO@3i|!~B@{x1KP?cOyAzy-KJolbS;6|D zXf3l@+@u~FMq&1ox=7Nrz2;*Qfj_=H@$-o(NjI-46)UW7A#VN+RpQx^>wBf>v9^zi9#1Z z;{^RFPS7W42z!I$fSMX409T@l*L0)g%td3^8RNDfnutH%4U%WUr`wuEcFJd{oMM!= zqKc|To<;+2KUphePmepOg{TiK27jVz$hKOp8!`>Ri8j2+$sG8;QcL6lX7bWHAXAh@ zY6?C>TNKQYC_V{B2~#l_oWj_BjQliBm0PqgsHy_2z@Tlg_ar~asIpI|7bm4 zUHdkl|Km~X@gMm={tfv*&hL`{gL7$g0flz=-gIBt^ceOH?DTe3q7e6%X~k|bru-q$ zp|zG|qqPyTPi{;&8f@Ao4{_n)p$`19Uog^2_s!PZqfQt8za2b=ZwPs36k}+WS7ePD zPzG93hMS|*RQFM_4Z3vEdu))$%gPV9=xqYIOZsP)&TC+F3^Wn7VEmUZvrxvm6vb%D(tjf-UNLsRABeK@(T1VU!xKq+_!uc=PgyNV!!1pRU%RD zTfSZ;66L;4YtKW4!nbKH=4(ztA`_FLY`Nsyg3cpZYC&)(0|MaoE8u;q>`B5La2}ja z47~}uX=1grWRngOBfck%xER?rmGvEq;3jP+hYh%I;cg=*9 zeY4&TI-i^AMA!)Gn8eMbOcU4S$?$9x_9OGzrB<`)SRMEHhh+HgkpH4VG>(49{Eutx zCy!QH{(JPOwYK({@;^TL_7C~*_mTfFr7(zl?cgXH0vnHM+}n@gCFeShf^afEM}0pq zY=bbq$O2R>jpDO&3dT#x6tZ+O>O}#17p?@sZW0U!Av~w22qOdvbrzyP0^|^gIt8&vI3QgF5|&UuFNS$<~dDAXCTv|J0q#l;ln74 z2B%b0J_adf2*~pFvvcI9(Cc)7p;jp9<~aO-w;C7e2(vMV2^B;bE8NE~^vC6qMz;x6 zNr!Qg1=}=*Ci`=SJ-`Ey^HTziK4BFqMZz8-3|Igb=z^Wj>&|f}cyV~J=Um}4>9vUX zva?CVr~f%I|2tUo_14<@<8PIik9no5#dL)GI!!+WlVN~!cOy;{)M*$R9^rk|`45jq zJwyv!6H_SWU`nUyBKh#F^0SYf(P%F_qh(cYaRL{FD}tL5 zC|p$n?5sYEbg*W9riqj}UtM8jfKc+GJR#=0Oysf8ogHkMIJ1 zQQBguJA{8txKVrgq*5?r`Q>K`{H>EMYnJCDL*Rm;O?A9cEVz>|XY>wSR=UEYd7Yvo zFmB!ip$5~>Ab4)ZdOt`0uX zilCaVNgXU>5_Kxw@4*w)D$d3Xqz|Z7k?4{%YzPJj-M~aCIJo#Cc_dB{NmSb0|3zl@Smx zOnCYeoistd^`BmK4m$yyWiU}Id>X)-Q5<=wO*8&uAKoloZWJ?kAb`twG@ihLX7e*d z$r-Y^)V9K|jbhcpI5>?gY?K(9hemlceTJ3W^cxNqd1Q-8ox>AU=Zbkr=8Eq80 z{Nv8^P5@sr0G3RM&q0R4&6rZG=Bn<&>Fnm(TDGVbvmarn<*OZ!CS<7~xeKuOn1PBB zmXLsVD8tzTK5N?;&&ZDrUNGXo;*UIqYTHQbqx7l^^8VQwFge}mI?mW)$nOIly;3IN zGPd_85llp6L2Q(bVN9C|kJjg%7YDF%7MKMSo&qwIKq&{a_2Rg5SONtQ84!Tuh~}42 zRu7jAm;K=Njx0UkK@lD7h3Z*Tvy9$%BLmnVo#65DM z^N?(@PSDZ{2={O@CQFON(o~1A=6uLfrXOUHGC8pf=as-PlX{TRD~&9o!~fD{wN)$7y%*$3JxW%xvOM-Y@j? z@ZcvCl-A!Y|DvX8Pvl!Jr55?AfDMt`&N#J1<%B)7Ov=4YyQd1QmmWYf-$=u3uUVT( z@0{gl@y^N9KKz>i8%zUYei&bcJ14)`LW+NOeIp`^tgG#s32P~{rg$X^RgGNoeEsAt z3_L1fEbLBTAqT)fGL3I4Mj5y>+_NW9lqdu1zD0TLuFN%udxehU)5~bQoem}!3HC1Y zCihN#+(Hs3)|yOFCz)hn9;d>{0~uafqBD;zdJSduI$45Bjo%nMEg83T7J6y&gK#$v zqbwa3C<3L|qZpe@0^Bx*e$HDEy0;7=d~ zMh8P`GfixNi)h(&w8I{@uv4#?6&a6iDtR-xmY~aQ(rnO#0;7`3`4%8=mySZC|5&M> zWfAI@hC)W=Ory6uc%Esp+R*pi{L10SkJPiH!{hETw0_KTG@>};jEj8kH9>=`Q)O@Q zcAb+4??q8OFU2IVFyh&&<|#j*<3^L?}*`0FCGX?5sJl_(Md2s+BMvhDlJ! z#FPX;>mah=@j1Fb*5SpK8&An}0 z5>&i%rc|;+P2gWgjKm#x6jr@PcQMs31M#rf> zS7w~7y(G<_LY0NnE4<^HxA>dM7$)Hdj1!jMOLv^h(z8DvJ7WX4djR=a` zA-p#YSs`hJ<#t1$LQzcOy7V0gRxR-uxM6fwFZL`+3!PIPG1EcGxS_j1{8PLGOwmax zB`kS%&r89{P03219lO)MHm{ zJfg@HUCyV|w_DZ!9dl8~_+eW&iUGcU!kx}?D*9nv>e*-pg>3+APT`E4f{BDRghFPe z$LFMjyG%dWBLF+-Unbn;9H^i!YzfeA29?}!{NO=z8cRF}g#t8-HG5p1#_?`+?o-H| zsGWaLDkqF!$!?g+YPv(`O2-a6jho{E6mAv`(i2%61 zP^R-uhjpv!Rg)^0Zbp5mFWZ~~+k9nJxHCUi7A16m$yK8@H^}&2o@@?i_UYtD*&Hnc z2TZ|Xc|wFBuf)#Gmrb3)A_2TW4Hv1~(E2MJjpN>A5RTY@#T=2UKPcRgk==@b$wb7% z<0|^c1egi3sB^Z8XpyvqmpuK4D0W#+g-p#vpUfoCaaLmKC-NAMO>7e3k2jvC9f0s5 zAl&sl+l3lRaJ3cNomJ@0VZJlW*%903EGFoFN`nXBt{Z+U*vNy}@`v&A_#8n+*RJ6; zx{Z!R3!-+EIqAKDxrRlhm=0ar=0+N6zgtnYO2c%RnQC5X4n}g3UYZqCeIc7b))FKN z?-=E5wUZQv=2l7|Sgsexyr49qgsZgFENq8ksggI0Dl#^nsYx?uA!KFq9IC`@9P`jw zCpCTB2-6Oa3oj@b!D%<-O_Q3c(F(-OEt_Xt(=4;fP&PFsHaVQ&pMkvFKH`@-utM@z5i$;|TD{!(R3d75A+#Gx$xe2Gr8dANgUMl*rM;LezsRDa zKzTi~`+tzo;#&X92`x4{ z7S+E-UxJDNqaKA_A)oK@m7RI~C4Pr*H0dHsaBbVTu<*I8I)Z)gbnBIUS#H1MivXOj zIGIG#n8#9u9QN})TCl%=%H2qqm4z49h+T%s)*e(SjJeb=@84;y8x+};vBqzHh;C-9 z-$)bs-jhiESd-J(Z8H{Vw&ZrGQjHmYh+q(;JoJWKa-R_ofUPFm)@PfKV48)c?)Mo0 zCaplI2xcnZ4&U{`@*sBH`|ZN-?El5NLw`sAuhsUW)uR8`<3Hkm{J#EQtHIWA6c2*c zKYYLbExupp(O?Lju%@`?>Jh_wWCJ`YIc5jjSaA&f>1ji9+YtsH_wuF^<*0&ftXpvjfz-)1P+r}?)%<%wH4 zf2Q8CsUf}-_WKoZ8nk#FYHSqzl#V`RYRABYkpXsw%wT%OYbc9MqeAW??4f)UUH78l zIA~q3ejC&mX;lzP>$=r42Hps!N0+W~cFr?1$>g3j%6j22Qt;4piF(CQ04lCCfEGcf#X)rvHL$dikUa1?)xSeA%nk#9aKS$`X~FWdz|D&HvF(3c)gNKX^vBij1Tx)l7)7PEl$E~rW4ywJ zkK`SNJ#Pjl>=MueTt+lRGZnOh--Xd>?2LCMuOMG+ft5;O)jkP`x>teDSMfYX;gk&e`X9%0HJTb7&;atbbL^BNzz{EB#lZ0}~t~9ut0tV%Hv^^nX6Ei;s zlv4sK6fmP6i#-aADT$aso|rA&XCx!UGI%ES5NpwY?2@z!qA?I)X#0X>5-)`{1|l5S zgQlK_3*ur&g5hgi_GN-IYW#?jED{`EF&nPB@orCaC3 zA1U^qTtecpno>p6PTf&Jx^YY6EcjIdk6}KEyfC(C>=9LvOwq~Y^c2m4Fqy^4O%8ez zkrvWuRQ#@H#0n$t@3p^%?elfJltgu5Qs~HVFv%3zz==iId=eD=ZV=jF|6FB>c~E|i zD^|k?w0mmFBe&SL08c=$zb(??h>A|f0O;~Q9IA{cQdN1)n~_I2BX7t6ozTbd<)|AR z3%2xqd^YuWB0(c)GCjGB(}|BukKJO+(WTH?SV@ORcI|n`1^%cQ6L1$sx>5l!tUQ{! z80KGVFL|}xX^?PQh;L!%z}E97B`OZvnPhxM46FEi}k% z>f^@^!tpJ;r1(95n6Z6&KTQ_L_L#=i0-7WoWZ8Thp1W@{bGR1Trtc4+5BS%kR^!tk zt;#?U$QnUvH%Mr7GeQI06_Fo=OI~@OH6>I+jSFu(!eyY~ZU&_%O?RaWCyPOOt~7{} zv+;Q;&p;O*BFJ})*dkgL*|xPfsbO8(ISFw%8S`eyfsd`ahEOr}WEhP=i@z=|BJZ&H zYpc~-lsR>(0Y+qBZ$p^QT$16mtW0IG8NToCA9W6oX=O&i+c!H~#~l@wBM9E2T{ru( zGwqjHul0s-Lqr{AHwk>w1reDJIJgdP2*bm<>C5?xxk00>@7}Oz!5Q?;Y!^(3*#Oe& z0txV90we+cT{ChQtFhR4-U7#!V_HLO%Bp)Sk{lF2k3zn#tXrx%9FEfK_yWcYG_06p5=#E?lW!~pU-d~~rtPA29$o^Na6EP%P?j%HJ(J3cT;Mj_%v-pvkhOg(^4 zecn1_E}oZ9Z;zJ^uo;yLb8npftQ^gi(l|XF+l;X$XOi#`#{^a_mH6v0=qzI(~?xYGpqj z4Qy->3uo_Ws%H-}LfU2wKdfBJAynMF+6^f{YBVfs%w}W;0NG9#M@M+aHji|Ph8hm1eB%=XNOM~8$5)gaVhI8m|%>U zBqvfVzDN>5Pedep+QxE+m8VPoaau{2rW2&7NQx-uHg1@udYk|T6D2apbaftMlJa`b zeQ(_JDHMl3Fet1F0`9l-s2elt_F#8Mx#(Xp$BE_Ox}E*)gPqP{_qcO(>|K)d;}q{h z9@<6F@ncv$$2QDkVoqJuLUzFmW20e>G%fM6%jZ!q$q{5aqU z`TimTv7r^U~_)UL3sKGJ# zz*rL_NDwdj!0CMx)ZKeJ0={XtT8hN-NIz&l-S?Xx*w7mQiB2gC%x)4ffg2bgRME4Xh*86dfZj0e7ba7gL@MH&; z{0XqOz~!z!Sw+r#ZNo!IYUG>#@-rBI{UW@E-;EmeQw{n-8@80fN$=CMi^}oHK*lMa zif1!=Yte|$YI2ACDTI~e| z@TW8Wm_kaJLwwyJ2QdaX9_12Lpsvgj=U{JLp828_z+727{pK4Bt#0Zs3&h3}5WSVw z!#ZDYHq2{0=UlvTeTw|w3prl2|GFNIzNq!r4EwM4qqT3>9_8)7+U@oq_FsR*|NcK_ z1Lhllv6eL)+N8Cf^lY!k-P zWHAx7Jv2XrPQ}Jb?t&NJ2D7FX04)-^JwJ=a8Q}|?&U2Vy=K@D!MLKMn_`|QG)3JRx z#0}GgWAQ_jpiw*iOJ}ou-;XE{75;0P2pNS@7GX)rph$sUps3>L;UxPB6?+`Ol=3uY zbiFc&!VkzC!2IzPQOEcyhk9i=cozhkPj_r!`56UvN{1Wv1y|o>FzPkK+7zHJ6eo>X zI_X09;oIeB{hNe_AlxJY8dHT$GfDbWHVkuLln7yAJ18qY{IU`sXMET7X*@J~4Ajlz z&4qQrH9CS`))7WCxKG8o2%_|foJS_bk)se0in%uGObLK&+}GFQ3SgB1dC8bBpP2u5(ftj@+6u&b|K4qi`bD00^>gpzZv(<6AhbY%1$x8 zx@YFrzQ%g?Ee5(yF&QuccNROO#qP6V6<$5Ww0AAqyU5JAUR2et*YdNE^uWvVQL9np zouG`WVUWnK5`yGqTKQ-;0sz}6`JUJfvHT3>C-UgBT|o^EzY!3nNRexgtLiB8Bru{FHHI;e2_Tp9EIv%O3+*fv;#7G9|sQ~2CtE{(K9=mY1%gj zRXhHn`{M2X_VMn)z9w%R5tsh`qEt++sz-s$n!4VVQ-Jb)e;A=77;IGMo)r2U9S*Fr z%`4L>%jMD^u%h00Z_7);KNzWXb9n)9>y*rDsbRiuVUrS@d^;$ZrrHdPOY>~N`coNU^Q%)uG(XhV({AiNqGarM#06d2=JtPvc?)nr>n zyBq^{P~F`zzsPKWBZI2MEyhlsAokcORr$BoPcUl%Mf^u>?2DQ^9uZRmu#oLtSy_>> zHf(nrWalSgGNaQ|ENYB7DKr$v>k4b($dQ ze7e{>1Ea(4Plkh-?O)3XBX(KuAfNaZ_7iXP5}J4zURkmTph}3M2LW|G!y92ThD}!! zUNnk(@T1ZM-sTcu^`0^~sFYJi<(51M5OT%6G$4inl z|0b#Xcs^^B@DeAqCCy=)Q0#MjlrOGeNbalH$$YD(?2Tqo(`7>AV3fDDhMy?TJDIEqYtwj_efpQdEMDQ1~#Aa z5n0!Pe#B-jkqSpgLOX?!N81$g+O@_rV!DK8W(oN}kP;zQxoL6{$=t@iZ^rKgId7gk zRk@~zSVS((d=NadUK$51lbe01TArE2TYCz~UP8=W8Zp0omX5{;b|( zEBHRhZ{8*QdAZ#P*2Uwx>TG8C^HCfCSx#^;`&)6}=W@ac-IVDtWD|f1ZMrYy3RYud zN(I0rTS1pLkN|0Hy81lgNL^K=QK(#sajv4qIag_G5Qo{6TJ*h8?L9JOH$!aBl{GK( zg;k;lTUOrXi|U+x-ur5eYMu*j+!6=_uLFs@-Xn5%Ez z^Y*e&h28auOzItu;N5=te%S5%$8VuAE;Qxb<*LPob6X4=D(*0zk@+{6Uw)4L^(k9K z!e}_u?O#_BR>>xj$5ESQf~l%``d5o2JZW*Z6QlnC?Vh22R!nziDvRDJ@aRNN3&+Qh zKk1U3!=+40aAE1B=u4F2pWjsWLcZ%Nufj{cQ8jq}qzltYIt9LbS5-(QHN<}vm^Y-{ zEEiAcn*xx$jxS=FcmA!u9k7Kxf8+=E^`j+tdMORK<+gfh;qcqMPD*qpTjUB$ddPvq z_)4|=ldqu?t`Acu5oU0PPsxllxFLNnd)tC7+-6{pH-{< zb=NMrxee_#g}Y`TJ|Bs`f6$bPz;teyInbSZ@IVd{u^6Y)+Gd>VHyY)_pA!q2RIA=N zE$Ddvh)i8UvQcMIlZ&(3fPW>$SnE5{KPD+IK=BmIUr_NJDsyM6on{xWvi+M=QY(FK zZtME-wft?SwAW>;2Fp~}Q*Q2ia+{`+zngM3+@@g!YUFtiRo3G?3TSLlASaA#1%fJ~ z6K|CkDyXvMFtv;DQ#klgc0mxBsJLy3MXXCu<_B_h8XNQ478WCO^h=D9oCTNRC??ga zQMSI2$ZEsM2)*tkSu5H+$YoL!$T(YOEfY$)*fr7hdQb~bdbNh!)MM*09GK`AWm_U= z72`5m24WFFEH>mg3GEPacHKDZyV>m3~*?(Vwz|sG%8riMpZgZR!N&<12qIz+D-+*+S@5GUV9O))sEL8uMMAHwe3`B z_UggpH)2VrT$tt}}zD$2|mrm@41&Y#04806HE z*d75fh)o7~vE@g-)=h)t|yS#lN zlrtRJ7n? zyncJ+CQa&>VT#$tm|>Byq!irV?!JbHQ+&BmK$0rR_b)3(ynOiyW3<%UeyJcKa=ITM zzU`O;p2>*|oDyOj)#bRaldohj>;}vWkw~?TcX@xX2pj9p2sP)*7C^ zpuJI9fy&Qc{GhyW$@pKgDU)0fa9m>N0sUM|Gtei@y}j7HmrdLed*$WhKHfJ}5aVAY94GpA;(VJ&u4E=HU!0uw*x zZh)P>2sxlRwV-Tj#egW@IZ@XQ#$1d8^~+3cQ4 zs%bL>St=hEoG$sPPaVscE6j|S`GY14npZ~#nv4|4=pnW_B62X8^|~VrZTB(UIbm&x z@kl>&X*kMiY)aoGpdXDMH?scHl6IXzprpt!%Gm|2@_01 z6uimBMv#rbd2cIw$;iZA{MmL9L2)kyAaxNaq8@NK$WnGq4@^RD)ezSpNhp`}l}2OI z=E^|-E`cgAD!bfBNAbCplAc@Bu$n-Mx)e;efWeq8L~+auUU!iqd5}Y!H$XkO-Lz#@xU40l1Tuh z1A-6X73Y7ZG$InpTl8u&#Z6OTzYM8#Y;R6%3ye?lRKeX&%C9C5fnJ(sUDQ@tCqJ(_0a9v=j)9{A>6`LAwA$8D%|Q{hr5D_MkB=D) zQ2MtwhkUO1e$b@pjqD+BB9+TozQY${4q(|5nK<-+Ltk|{GF9aCkLFsf6o|>De9ZgO zL6AdN1A^752IL)zwZGR?%=c#Sek1VX%~OVA$t;nnv=qr$511RV;VsBD&f$<=MyXsJ zYOyk7q^j$}>8o_~{gaJiRDFzBqcl(oTS<~s&txjJVF3KyO{=3F4*N;CHuMew$!}$E z#F&t?Dssh|s!rnRtc-r}qvYgO7DfiUv?^MWR_us-)P3Pu&UMBs+VrbdbP0+yD$LiQ zZ_0-Eqq-T!t_mjRdf-ogGq)az(#6>xK#7LW&gShpe)GeJF!Cx5H%=^(avDv!!dt7W zv6!(z=~xXZd7}GFnz_=^Dixu1^BO5w#kQ^I?nPBP2V-c(H}L#fcs8QQ8!mI@PENv$u8hgR8I95M>G1fps;JWI28v=I*(1 zysP1B3VmCBAkKj2|r9uSL3C^vNA>TR{8mahNDIchA&7D>u2tF z^64cNj!RBUdW}R%KW-LlmXWlUx^~m`0Ux8Q-TrlO4=HSMAJ*V=P4;oH32>%tnKHO$ z9UMvY3Q_M|#zi5&#WKqCsB8?Jx3h8#@cGlmz;M6p82sZyrLk3cbNmy>?olEnQea`8 zoooo*Mj?zz@HD6*N5OAXPL-JysX&uHg#>&)5y+8&vh(0pXWe`gjn2bi<_X84+sH;h zAq}A3)ougxTw}B&i-1NUN%Le?_{7wU^0Y8D%l-#7emC0vw|g7;{^z4sX${8TgE~?= z5o3t)ZZL7Pqy0NWVK);Sn;s-~HcVbdEn!SjxBwnU*g6WXgBOPfdm_Ftyz8fJ zB6FtFt|Su(2C>MUE>bcJrxL75n}>UKA3ZW{29Yy`u;P{Wrp?pJ`i>uw0M5praJT zl43NUdzu{-w=;&4O@_lk9Q7MEKE1s`{kvo*q0IH9aaXnvnWSPMAb)4lC^s`W`cXKL z>(hQ3Wf%aMv% zK2>T>t))B-y;~MzHR}^bzT4UG5^ZDJP&+kZb82)Y+Rc#huPW>7RXF&NmDq5}b;_&8y*yIDnJ zVNuai)NLds>9A)a63{M5s3Vk5hKxD<%Q3D@6$5T(*)pwb>`U%3^EhKi9AB-ryw1l&_(B4~5aox*KqXxvRtnk2exg&~T9pDqrIJ34_>4M=F{X|i_0 zSF9)|{O-z%7nYmz5zvkxHazJMnExZ=bILtKjHBF(bJTgkDNeFX;rcmcg3NmcNW%fC zE_8Bc=>ROLiIg3%t>QSk7^axvE}wN-(E*x8yqM!j&Uzu{U1pGSDT$nnNulErj1{?J z1dam3XyKCGP};C!esqpJoHGVP+XT8vvN?!CqoD3ZgMsPq+vG!%UM2SC6H$#X%7&x# zGX0>=Uombl0ZJ-Ej#KFjTE}$C#v&{$Tz%qQrcvAAAq0m~iILbLQ@P!KR&lMVZZ)BK z?^3hmM(_*W2Y!j$z=wtK4V-3+1B&4tdM-z?He@&V1v0Sd?p2j{1XjTCZUa_CRr*ZW z#?p^Z&C(@S^K+{W_UuvXV#Vx~SQ2O2l$bVyNv#m~(FXlArs(>o3*tXKOf!lG2FQ4T ztm0Li5$2=r@`4gLW(G2+uyTgS287qJ7$Ap~rjNX(eV#sB;c5@3TKU;!vDR?RTyqRw zPYDC_@PZQpjwbG;A!B6*ABzn(2^giu*V36=Gp}1fVlZvHov^&Eg*ol}rGwes@du&| z3Cuog(SP^#5FK0849vDLR=K~;X(bofak!zlt60e_qu6jt8-*N@S;_-E#?4i1Q|h{E z>r&j-cvvv~wj=k=4K{LbiLJ@MbSg$2K~Ap5g207a)4Zr>JuOkD(&6SNV}Oo!yK|zw zUIMv3rOP|T6MON;sF;=QZ7?&hMDDiB5BFvJ0(0Z36sR*Z8g~5?SaWx`vX-w)>SyrM@IOVi!{nAS(IvQ5VLB|Mq=9LU*XPZR5sJ@V z0h5;*-Jga-DN2T%JXJ0*ybwobiW8m*%%oszKdinoRA-x3IF?6@-!)XTX zf{sjj;R%>_nVP}T;c*v){{o;^6aLrmcCfe1c^3?`$gAsBOn3PbZyVpuj13@-kAbOY zl8nX1s0R%tS6w`=Mxhkc zv_}HchJ)dnPzIR3-2`DUqT^yM1T+8W=9>B`DYWex75k+()HHUfP&RiLm`Ah{KeOCM zK>P#JuhDNxhctyO&cj`McU$S-Ref~xk>-Z;aLHWTWk%HUMRFi&g+oqApo?InL~JB` z=BV?fYf<#s1ig}a#{!WM)AQ4=bIEB9?wERVdlmu9~Y-^8r@XSZ#9C-2ty42Q~` zmvxS`mJ{oFsPxw8%(>lHpPzS~3IO|w$J6aBr%P6+ur-nmsty>%iH@A6id=s{p!^Ug zl-x=}NlL&@AObhZIP9Szy{$sGQp}um~KH#ttHzVH6=}$K7_oVE*6%s353URv2nyKM> z)QaFA&4l>!^}+K}h-ZWJQV!Q?!*bi*+kiMrV#p$l3appA5i2aI!nv1(w_ zSfe`pW_)fuA1~r8bG|TT3TLCyMo*z#iisya&X~tlF8kvw=L3!5)z8jG(HWlkdQaDB z-!cJMY6KL&{JKtue?tt1SpE$$9s^3cOWbOS4x735obKA&Uc`aotport`--4h{cplI z*sYDc7T8z&&fJ28#l@X6W1CthWqm|_ACw3I7^ZI{=VxJ&z_Bz0Fzw>)Vi%`9=hJdL znvf>cT+>^mjIJq~u?OdBlqP3gK!+|glsQNW4izawOCM64bwi4!*z%lHG^8q=$pP}b zyD_#|$sccyd}{4&LI>J&>dirw>ja<1yQ)aqccN2NTSli=N13Pjf{ynAIQ$JAcP5=! zdDA+ICw&`m-nqv#1FDzMUz*8hZ(n?`&C>ijh#6&x|c7#Tm;&0 zg-)A>q1hUVZWnUQIQBs7v2qD-m}Sffr2{3v^%(TjLU< zP%@CsO{utb`0^-E?J62L?)>ezRB%hmW8};jybX|J`@)0Bi(zw*xl}=Od-o{;pq<0r z?UG$Ks}H&LnpR6s=Iu1DJFjX8K4BwLz!1l|P1#avWH~n zAq13IucOljS|`9+7L8Em=BpIcnPrsQNym05RkAcxJ`OiC4VC8vRcKohErp`;+Jt&2QPGOJ^x@iir|whDgrToHWHPECGs!m{(z1NGFN|=^ zK6|JN?(*n-z=Az&|?;QWs>EvEc6BUDsrJflQuQ*`aXo(~?4X7J^MY>TZa+JkY%XQYp81t_8todDUG8&=JG8y>5JCm5z1!2oY19O26 zm8+T@u;Y}nk7eleS{5*u?og|hfi(Nh(#U8+hWN^41>gYW*3O6mN95Fjb14Hk>>mCh zDfi$_cdKu-N{Vyx&thHtXmT<}wbe#haXP0x=zE;b@TR;t9pbw9PJ9{nqmA;;;Mp4Z zeNU$J{Xn|niXV(Ng397>nBXEW#}v2E=_u(_~!`c#B(^{!JJvnOlUMDyjiu6}iIi1W-7 z`!9-hT7GhJe$55TDhG0#JgV5J3AO)zjofom0>CqiT6PARmFvUA>bHeE53UlTm1Sl? z{ZWFZPreljv;4$(pGeD9Z9hl|zXRpdgLUsR0nirk?P9{4`9^|mcy`*`EcHVxqxvN#qg>-{N1pO+28%F*S)OjXc4woX`3z0jI7#JfLc5^6K~T97ifxO%D6S@|EsD;=!8zL%rZUUcy~4f_Q<@VT~j&N@u{PyDNPaKY2U-@((H7qtWL zON8{`(To~zaL=z6J3H6eP+s(9I!>t|b>K&Dx*PkM?~1cs*Y~ws1w~JE%*pFSm|9 zZE33caR1%~Xa*|OyHV2b4#JaYpwEN%lZ)YQ;vX`a!q`J+!#BG0DY%~AJaw;^*{*&Q zta5P7eCe{n&s4EQC-*Biq3{RmkukKvevNMx5u0Y5a+l>O7@);Z&1KPM{9yGCP|MTc z&Fbsaz1sGDWCOeI-t>4>Jj(5?8RWY?gWI3k;O;3L97Q;Hp0x+o54Y+ zdzcOel;P-~|6KSgC@-^hg2qf!3cLv80ZzbI<-G2zaDZ-ztRLJy*grakA@3g-7}15P zUa~V(!C%dz2fih5#ejO6)3x{`+C59qRw@tIjmd7?0ww?`s{CKD@1_o^R^NTOe{k5L z9f}s-c_ik))g?{E#Wp#l4JX;T1hKL{tI=gNy0ICb)6>ceZu0g|jY5_0vI7@j*U2=& z=^#Ag&|(unX$}UJaO5lOfs2x9;;flGC6ts2`xN%hU6&FGg=bm~!qYJu*Gcp@v63ry z1Tr3YH1>Xe041I|T7IjHFZHG@V@@GYby-9wnnw0D#)avt3@CaIxhf`p6OUsvKbbKq z;JLuGj3y}5l+48&F3Sq-d$A^{%)-k8`qa24iOR@qxEf?BsJ%^>N!qhpZgTAXlH9sJ z!B+{ARe}g_h8n+35uG*JZz?U2mR12sQfYX?@dr=Rl!9t%TTyhd;J9!^1aQA#(l|-PNpb9meXOA(s#cx|7xK8bF;IPm^Pt%byvzgsfbitbGMThg!bTS0Np3kI4d)IxQSw0ilCe>GT zMMg5cC!aBt>Pz_Y+lm=8e&=TXmAB^qvRlUg*z5R;OB1&sx!aS^yEXa(cUbMYJ2X?* z{cq7ifV7_KTl2VgSxZg`E!=^U#*BPpp2&n9(!lZ zzgFQ~xsPYu_EadUwL%I9*{s|acgFJB@iwN-&a82r&QH>A|2_Oaao(RP00UK9$ZbNR=2lOZ~Hl2D35!Bj54C=^VU zA&Nr5EEDmZP*5sEd=a7Gvw6?i06v*X)~x&|2rtt({yAiqPaDkV2``mm!KX+s|66Qn zOIY?^dNB+~afYGKgj;9ZSh9;Pd|c5{TPZ48HjaicbHfPp4u}TwH0+ICzAg_`tQrbO zkp?G0)t>}s6k3+DZ4kV8!~vtSVVY2mhGOS6oMKlW7D8APS$gn<6!xSP?EFJpBN{2E zRBZYE%x(XWhyJh2L(uatC=$&H?SHpabQi=yD;`g3`qv;&iH!86#Icv-yO5DDEB%l) z#3u+qI~WSSAHlhz51>;@2A9i{rQ-b2omf3dljV=mC~Zi1Kg#!kfeAU~MK2uaRFf~Z zULSRAv3`7ti99LtA;zG+DZK^69@(H4TULU2uG6o`X5UhAk&Ki4a|!>Yyw#o;i`iWD z3xMpPwfe z>erG2ASj$a+}`?&YQu2G;nvyNFYjQ7k0kr0xn&(^oK#K6uBCGdBLeiH)^2i|`q}^+ zp~hN&Clm)QXkCA+^Q{t?i?I%_jpZH$-|@7-0~3XiBfRkx9Y*Z_qI=#%I7?alF-lLp z4{(k()crQT@?xyXC{6ZbMoSFDM#wOW@Zh3RldvtamAd%-QFmZM@46*)g-n{E#-tuhI zqcnOjxY0e5mdh|C5T2H$81hMmn-4#iRIbQS+bOXYR+IL*El43773hs1=sD(QiSC$u^5fr-2BzIoS`n=GMMJhO##r!7+ZJga+ z&b0YIC|u*GOkTBPz$Zsze4X|<5!D2fdfGU@%z}h2Jz!WGYF^oghMY?QPjqG#j0+;0 zPh#AAFKYxPW>-=0n|M1VeWZ)7IG2b4v%OQ4d5TP)yE3D6w9yN+Y%{&Hrm|uuOMGzs zWDq7F8m4m#oTXCwhlzy=4oBa|xb%G&>!8*@sp-Nn4-|nv<*e$&pP9Y_J98PQlMMJB z>MiCN4SvFIsE$hiBrPv<8kiacs3^?(n6pcw&W-v{%#%vB!FQLvUNjtM4C1CVdNZYL zK8a*%p(AeM{J!vICiaASq1ztYOu(1nAntp~3r!e96Tnh4H2Y z!SMSC72uRUfHe=qTUqbb5=v^5hzCpPU8-UxQ!bFiW~pSwwddr@$uuw;d`YGcN(0V0 z43=T?FXDtS!P*fgTzig~@-~-r#5D!L$D=%+7IL z>i6+>CB(1IKqi>;lvqicLSd`U!z0eeQ!9|!n59UIU6^utwo1BMH$5T+f^-MfIkuf4(^;=?T6a+bbm}OpwIHTA zx138Y>{{4#uGD67?4ssj&c@>e`>*>Z=XE&{%y4$J#Ig4|EUdy9zS~2T3dtn?X}jE)}Mmb zpMHlwlWYuhGWZi5Xya++W_|x3`iD89)mCdYcoCh9CYTd-bxj3}4kzPtIJEk4)*FQJ z1?Ghx-i+A5N1{1r>15Pn<0EwA0qh%uJv?hTm;C@(y8%+=xCa;ubUEUzTBxx>&zE&+ zEx>$1H^EIh0XiO>r75!{#Qt2ylv7@p!MydzdJ@|PkVq8-AAo%voKj8s$cI6eub-Wx zhU9bf-PXfX!6-G4fR~qTn0E~4ZyzM?XL$+b()t!dxido z82RX7>pS=_Xg^+Wt*t-)7I{u`NeaG3hUw4Z785+}p)=FU`7`wjik|y#vT=V9pZM?i z81dfKc;LGUysoL&X@<`tKFOpdggMsjYL{ zoHJ!f{J|uB)99?1%aaDLF6m_Q*uCc%>n8B-mEcEx=~`43jk+toq#-UfOyP?#`>-M0 zR*QBOj|G0Tu21C;zo(JGc;tY^Ugk~L5E}AQ09n|mE{a`UJOk@8MrxY6j%p4V*DtMi zhLxh%d7#qRB*9)aBXUpcRXaN4*QnO0h7zis~X9ju-aWHXFao z_eib*uB}Fhi#56bjsJ(!(0Ho!@!oLbcfQ;z6O~2dE{Ff^vYTVwA_Y|!XVZL|0WzTx z|4007xa~qxJ}i`;eg^6pK8zP$!gI~;yewV5`{mne5G7~hbG3u=qu>HxY6F>FFu=HE zg(0?ih#yPv)W?WF$EP6m8}{z)@r&;Sw*W4xN}!?OBdSLjZ(7&A*8QcA$ZlSLhj5_S zg9pg&{~2)>>cR`gRro<+z5W~}{rI$WzM=navZ4I!Ne)l4DKiXTzvT3O;*`ou-tfzd zq-Dzb@mV~se*|no`Q#&~Uz%h4%!hl~TZM-t88;-bJ6u{>pMlfA% zGUDbZd2Rkl9=5R%MzfP``n~+S&MMa7s`q_WzOVB4>39zlzqW3YZ+|vS5Ij=xKU>2o z#?ou<&$}vG7eY@Aw>((Dx-e2x`SC)i9JeMytV*W7GMD0VPLlh4dv= z%zAu^YWmM4U-5>20vQqKK~ciVN5z=AUh%tWLC~j8^av(3y{I>wZDuI%u-EA7N3)wF z=TzV`CuHQv+9AP1Rg%#Fk6^j)S5ZEX$sWxi$AlP1g%rBoQF;~kbM%g}Lz&@lTpfvN zLs%5bZ|+MOz^ymC4q!o0DpZ&{Z&lOguA=NYQX$gMn6%1q^iLYI=d(vXo?T9&{h3qA zu(DYb=r#EtF?XipbIlk{G>(Tpb!Sc>LK0dv7cS;OXLBKBMTe$O@2r%x_RsH#!o}gw zw<__6sBHRCH*0T{P0h^M=bfNNb~#Q0jJ1rHz$0J@M}qi#s#v1{xy;x1(~?e7f@hhl z_$-2f^?hpsG=L1p<7kAvI!ftwoH}cVn<)i8+Ol$&p36&sVSA581{n`{tNFZ9#0U5? zo1Rya^8#P(cxm68cKVvCJGj@-A*0a~#c7V0F`P;TLQbjFem4hloDI^G&p-|g&HW#S z9Mq+16E( z&Me4!=7A{NBn^hEMgN$D1IlZMq4wyyr?7U&xyGNPXjaR2k1z2(<-V0+&Frab`@2gU zGi8DwJBLTR2mAG<854gQjWW4UlbU=_2ZZiqgg31wYT;;-Bq$){=S={7#>CAYy_Arq z^0Is9Z*Mw>yL+Ae90u@=$_9l*G8co&WL&;t*-T|i1r z@x+g~DVZ57c_TxKr$fViH3bwc6hf+D!5Y9gFlJ570<0+M4bqH^_hd8y1trZWt}D@V zdb><-gDC5T!>FiZp|796QBf&SdSNFTf_b+lkGvVMPps3+$}MfiCS_*(H$G#}yQ@JC zZu!0`>SLw)FrqWv;0Oe#d(eZV8^Xn37Z*|QW;C#@4e>ME#1E1OYk_jy`B=PJ#48V| zh~PZuwr21i^RyN^Vs03JdH>+SJE!rtw~RqWPo1f*t?JtJqr{dJfLHIF8hx%SnD-4` zSS73>3hZmoj}G4M?{xkqWC`j1L{g|`sMd|HaR;R2?2iV9!Bsly7qDB3e$IUjse2D; zNWXkX6YA#_NmP8)_ry?e`z42c5TlFiFF0#F^{wWe{`((Nr%ib-*3@r)ze@i-Y6g$# zKdHkdp7?cIrrPSiv7OuMyUX3gzgTms$=yV*O76iiHyECWb$->5y=pF#q@e6UgJ3OB z%PSQv383Bo{wYQF;Ey@iRy3f+Lv&LxjSJmxU4MJ(kpe9A%u9J`Iv~58pgaf`TcyN6 zE`_isj`;WhY|UG5e0QW6T+2HR<~~TiZ?#(PAX%_CQ#mqo+&MZH8sl>cXA)y8b1|o_ z;!@c{!y)|^PhnUegdw#kLN(fZpnhScOp$ps9(^i@S503&9*ufLUU*Sz;YkmMdUhVa z|1h{n(&0ZqE|^?iUEh4HNr|oJ+dG{XFJJBc*AK7v_7C3t_uTa##G%l-U!~`M4x3b?&6mT zUXqW#sZ*N|f;O=K2-un$8&a4&^#@X_QBU}4u#vle@SKDQ73i9V5LX_*F+IkYFe8n3 zrUO(Uc{l%MGG9)zIgHu<#uXVb7Isq7b3PI&aA;S!bDaasc{=Dbb8e!wr{WTmO)l6( zF1$R$OHFGB*dtCQwE9o9x$0XNq2Oq8u|2+)e>N8Ux4*f&W`Mt8Tp-{pbut=VWXe?{ zu|d{+XA2v*9$;LscLyA0#$=4$l`~EO0aAQVb5__84hd-3SybevCKqVI|A}-<#<(=x zs1_TXX@1wvXjfWL60Eb=_Z%>US}6N{9MFSlm)}$hX3|(Z+~x=TB2K~qv{yRl;5UBeP>-@gK0P^aW&)$|4 z8h~n#@Ssfk;iw<vP{^L5CeqUcv#1OmfJwp8U<$kq4i5CqXQqJXowD` zn9U?Trj+-N+#5UKS#n>Wclwcc6N)1 zcE+Ngv5jmOKa~#W0HHu$ zzlcUzH4^1LJV<$53{+EwO~6G1PmP1LzbrnvZ&uxew&IHZBle%5Fqx&nX(-OJPL^8z z?%jqQE<@D7lLoy9gxci!I;FEPMV79D7xa)d@5oX$#-dNlXP~T`1>p~WA19Vle}=s7 z+MG57TQYai4H;?g&AI)r^H7=FqsEK|E6BFxpUa}R`t-xWQGqf|KPF%|rmffcD>}-~ zp7)2b9v8|znXtK4utOs?u}bmI8YRyyxUeKcQhy8y8skhT}!Q|8K7`SYM~-G?{SUwdOwYUg=D+hsO!&2OvE<_ylpjj+SB3snXmON*J#b zW`fC^(nR?3JSfd28w@QPVGyxFoP01svkEM)Ju1iAqtclqX|0|d3W91Xq=TT4)}%SF zbnmrsHkVJ6?+}ydMa~`pDdjraqT)Smdp+o%1i|WhP+x90Y(Qih2@qoJcSGaZQWLgt zQ&D0j#kT>ut!L_z)d$JYkNpJva-#NRfdhCTH_0~$;bB;=? zUU-tZ@s+nHu3!H6$dSU-EU#yMEh_7+&R>u2KZ@nECS z&8TOryS#dAHZ*m7&az1F2hXIX)@(KXm4|xDvc}aTW*PXloyStX{nUj#LSrev* zuBCLVr4Z#ZO(w;Z{Q2Gg6ym>~MPpvkmEqubiT~DW ze_M$E_GqpB_>cH+zt8a5(7Xq`8h^k3>CO835o!N}e_YiO8^-AfDI0!$0fcUV?|bL{ zcqA`7*WJX*zwLyF0(MsRNvq>JzlIgd(hCVPnxH`kEauk;?zgYIxBS|UvNyyot*kt(@nv3g9gpjHvA2*-PE0WY zJ4i8~&(}>DBeKPEL(i-A*DkLWzC!#RMR>_At^BoXdAy)bp8y#QDg*`{T;br9Fasv# z`N$T&Re&;Fo^J0WTm$NbMO%31%!Px5H&C0XIuSVRlnEF@7_R`l%KQnXfTl9 z03A@7e_!+;!>@&T>Hj&f5Wj2u&(+6|zg;cF|9t!h{r`RAf3}08Xb8xQrbVl(e*^&i zeFA`rt5;m`UL(VCkn(XmE{`d@4OW_nhnK|r)FCu^<9=EQ&5Ed(DnRA}8XlmF+R0?_ z0h0rzXhnu`;zMdVpgsoa$$Lytb%NjGag4$h*}k*Q&1oE=p`P5sp|IkNcg$F7Npw|X z{Ky5@SIro|NzU?Po8n0Cc=&7&pz9p})LIUb!X!jPSW&^e+B$mG-Q7QKdN1A_z^l$- z6CvsM&v*B?4u7VQ{rdIM@!{_NOYwVT|2=5Wb^)REBaW?(zIfR24~V#2C_gZYTn~#3 z@M^fveu!>xGRU0}gPe=wuBssylyuZ%3M*hk@Ibp{+vDMlG~^N{h3rEIg-zY}6Z9O& zjLq+GIEVquWcF9kB!@b}x1ZP$^(TvxjFXKQr-OE1aq{RjVm%p6*!)c#A{J+(hjS)g ziR#jnLt(?IPAIbk7{V4LW|o`c>O$T00#icKdnPitd1q=p+sxqs-Z-0&Pd7`tPhbG# z@-w@>o3@7iCjB6{8UA(uenIhGH`O*bOQsK4`5!a7X30L1ztxppF&G{Jh4Y^nR zNcZN!A?#*M5H)bAuTDqlg}1XQG7lX9RE`M%?Y3>suC7vFAvYWiB1*BLX#?%#QIthv z?}JJ|4@}YchE1-@aA127g(E?N;VW8beCPn}43^N$-LsQ=0Syk)bV#l`NZe_F#u#3R z0(Z@~{u#cqID^Ge^YKcinv5o1<>sBt6<*P-Har6bde<;@&TR#L(yJo67-~+`F>YkY z0C%M)_|NjQ#A;zo+YZ&F$Pk~(OlREZMp4yfOUO5A)%L(99C+nnnzg^6wZUDk@^Csk ziz|~@;{yH3;sPPgCEkPoBRnzo68$Cgo40#n_PR;(f&>14K^^~n`t-Yo`TgwKciKE& z02`~MJnXgrZyU2R_i0r=t$MAZ6>Gu?2-)%)Ewm4ggSSVW9cNno8S^6NQEqOAn=J1^gLv z%49Y-rP+K_DjjlEX+PZ#GaCbh%@DaB)!7LADb2pnlqT(an~9pPWOX^wGnPxUS?FH7 zS$MVDOuXO^pE1LHP~~R$Bu?g;VSG3@l+p99#tQ@ef_km!CxTdB4xR~bz$#yO|#wC-=WxnBP+3kGLu5A&fC+_L4U$~qMehocmDK4kgmSk0xh z!ZMb-T2Z3ic97kG%yI2Z*=*t|%vcrM7#(OjoScRi@gSsDv-Bb&))pE*8-*7aAYS2R zesC4xtIN0_<(zeNdd+JP4-=Af)>UVclKe!7RW%%vxlX8=AV#?W9xlFxN+ne@JXFmK z20UVMsqp;2ti2k($rFFxcV*j!F49tCErw!J4F8?6e- zR4hYrz#!OCjW%Tsz|~ahPV&Z~m-!5~^(C)Anssh86jGCg0-GPo<)Gzrb&k#4slBfA z%ifnmo7o3A3kx;mJX^Ol1c{CW}wj*dmXffg_Tj@#GL#6IE``k-rt&)A&WEqV2*?AQ9Da*zMne3-r z%VcCL^(jw;IZeST~)l|C6^yjJJJ8L!41Si@o!ark+8Jr(T*Ic0F- z7u0!lv2ZOone;wHl4Vf6zCaNj6B+{oUa|Avst`2=`+~G`sCf=Vs2Xt};#1!|oz>Gt zzl~9Z(5!?dN0{_N?2^fLstfI)91j0(CENw}HapT8@*|Y+2 z)5*qY{J?9Q7a^5}12Jc2>YZHLG*T`ygt<9&S3*@1@wFY}FX!)8fKSwc7p|R1?CJ&9 zf7850%876Jmv+~XS1`@;%YrcCF+<5BmBLmj40Ne$+mL(fd6sxx^mGtf^k>iw_qzma zZeTW9b9vWpWsg~|}Z-?RpcU*;%+(O{{MG^D)$U7kxSkU}efQhks>MGfbu z4f)Tifhua}h#g6NO(J`e{L|`L0ymqo_BB7=dAm+d2e2l=~5GUVZAs3H8C&j)aK)HX7`ZbZ5%RFQM} z*4w1ccGnwAIn&MjfijP>Y$K1wTXs+4ky65cZv-XVMGxNAo53GXV~}~}#S@q@M02i; zBJ(kuhS#Rj_Ik!+ARY1473zx1y|14<23=@q=^+n`U_m!YRhWaKba({kd% z$z@7U0+!;1Q_4zXOQThvHa@VO0W)vCbOfUPFiprd66&I^v&Q|&op$ODw~XdUis^ai zO;g@t*B$K{g;xdga~O)8ZB?xXhupzi#(moUsu~w*e=I8%JE06};3Qj~GpD=}osIdN z)7X%jM8h==m+(e7izD7QCPkFUH)XPoqnEb}MU@wN zJ!%=JSX#AjKUQH-xdyB-j+So{BYLslN)%)H?v!@5To_`EEQ&k2n(JAP1Zi3PKh*z+ z%t+6FNBi&Aw~xMU745&j{lotI5Bu-`EB4=Ve@l^sjMk}W0dCF2!?9$QnPm=sen)fg z(*y%AboFiMtM0;|>DDI8Nmh_Iiki7*sCp$EP=veaRWU>-NYpJRU{8@c%V)}rr zzk8$9n)>v@WO3|1ePC1G+z4n2MG@>4-v&3d=F^@aSg_EyX8D2K=)(`O%69P&g^S+E z-HC|dyt0O8Jw{5ngDRP+R~r6Zh8Rd2r9tThH!~?YJvQ?fIbCEp8iiUYCT4G=x_L1V zFm@sNyKHs4{9Bc1t%^^%#wi`NsApi<1W91HaWglnVZ3oy2Qq%TZ72hD8!X|qG>4-M zI_NN{?gfjQm8m;l^4H1k4=5|Iy@sOeHS`MYBMR7y5QZ_Gfw;+L14{ccWkWne4C^rj&3p#pC`~WV=BbR}W zOiGDna`HkGc2&C#IIbb@#$o=DP-*5@ZhCR^(>%#HaYb1v1tv6yZ_1|tOXdM4t{n~- zU8`km4k#H#j9(K0Jh{Q^@j=Qtz^eb$*m!B$gHGOHZe_Gno({_m z0`bP(vu5RE5(->4rW0r$b~*__x#6q?(>o!Cunjxi5{f*e5YIQZFV!0AJ9#CM-KVG0 z_SLe+`v{@8B@eY>iONy0jTEe`h(oB=yzyFDafdQ%rQhB3Ke7??nFTRi0$wE;Z=9w% z?LyYj8wamx&Q?p-(F*xA-_L4enl5>19!2sHsZ9x-+&$P-Sf+ZJmk`Fzl6l!9+DeEq z)h8(D^F%yjKgK-dbhC%y?TDB;>O<@dFtYZ6Y4lLutgMLKf#y=fO+83B59{~O8ymq8 z{!?F&nAeAm#&2eu9Hkd%$S>y(Pn#F>1z$jo4O0PdtIt;2lz5(LFjeCcw;G4@U3%33 zngV}|N~BRzkb2l@An}2JSV2=(j{2p_(ak|gIao(7Cgtezx4axONLW@Hrh>A@rCgft zX;wCBia4%DP5cl5Wp5Ka(Q<+hZrA^{@n4ume9;I1Q}sXa?a`yhdHv6$)j#w<|33Xs z`|%(8pWjFSLmD43Z_13(zZLO`9mGzevkA)xoN^n6I1&qQ=wu&Y?Cu|R4v$sd?FzM! z+1_6wPJoWNZG&QG)LGRtOb1?&&oG;UP7N-c3E4v&Z#{qA3F^B$uXm4*8xmE&-uc^` zLwYg02CRS78!Hs%52|@55RumrV&mW{ya5hi$WBUZ1CUul39(N6-_DFay*`}A%*J!Z3oJAY{jzSHUUxAr-6N^GH=TWFrWeVNxN|kUt^~n z&&uhL%!FAV5|Y1h;>~g}&akK~Xv4wLn=B$7(L9=NK*wIlKqVDC!fHzE%pOs9b9D2k6L|0S6kY2^NK;7(Yix^PqI(~7 zMQ&?s)0N}EN3f)$K5r*!TUY4;Pn}GLz7308!8mhUd~{*QCqxNko&!6eqt5Hj_OYY$7q8|53*C3M;k{#@xx4XGm8e70HRNML`FqQVkL6$Nmg=qReviesB%S_AIc9;ko`Cp>a@sc81AX0{W ze{d1?$>C2N6jD|ustuJ1>*FRfPZHuO^x%IoO3p;2vAKltCUFX086*!Cf``cr7&-Lb z`SgwAPwn(p1I!tfWT#NrATOS_B{);Hry`++6)Ta`)QGxeAqd_eM;I&(>EEW-zZ0uy z(;|}Y_Gr|jBYSCh9G>8>rcwAC4{X=RtMj;bZd_7$WpTq19AFPe0?0xkIIo3Al1VT@ znq-f19~d*1gimNH!)4j&iYmzF%iPWvfrCKp_N5cdH91hiMIncm6%8htqgruyFKN;l zjnYxh8z8+>tSo7v;J`=YS}dDcmw;o|uH%eu6dZCaozOh1yR};S=-2X=;yjvnIlMp# zI|g757S7%YI=mu}Xs`Nm-jJBNz8S>*Ykh_F8aD!`njDEA=8t_?*QLwiCBjQNh>Z`k zkrOZD(Rc!);6;e0$Y%X80RT+hZvWb!x`I2XY|ldI9`TIg_1>ts!!pcztc>_=U7V7_ zt=o?~&pW|36N`l5APL4bR&%utTMH)ZIk^H$&F9fsoFsC!N}F1`?5IgL>RC80_0LAp zo9hD2i|n$w+b7!tyg+44-^7q99`4&XX~gXxcV2c5gExn}d#E-3q4To?0)0F<#U=KZ zJUod8&I`s3LohE*ct92kY|~>n;b=3sJg9Uy%C0u&V_ZhT9Uz{ajgqS=;L{CLVEMX~ zQkn``2j1e@W=ky)Qy4Wiq%!^fh;Hgn8AW-XOc1_I^P_5|nFxFLn+gyK336f*P*;-) z_47g6`>;__6Aok}LK|^NsD+QI@pdxa^IZ1;)*grB>qQ(qu5Z_D1msKhtOAk!7)MtX zm*is2AVg9VtPr+ubY(m{01g1}jz{s?84!dn8SrzAcm-{2FZW&?90r}O?N`C!!B2sy zr8Z!ML1Hbqjgp=@SkF5Ety2Pp7?mQBawuCb@Fu1RB#Ewo6xq$Bfe0}$v%BB<$%`LG zhKF?GEjX_fS zPR8fk=TYy2?U!izS!!)c8xrfk)kNTpnO)=s>m=EPHHhPNockcChYepxWMtcAH1VMX zxmfC?A+$)m$;_@J?bE@&k*F=!(zY|Jo7+To6^`Xa2Mc?vu>5Q&ADhAP4|e3!(gf*0 zP=)s*)rOsIQX~5t@sm4phknp*&Ud4fLgi-((^&d+1JQ(Nr0fOg93LY0Hd{Up?PiCt zga@#K-e{WnMjCUVwzm<=3o>%;p7JImXCE@XVkBvD5KzKAK%Vn3W7l^tJZj+5lgb$H z-L--q4vbxh z>!ZjNu%5+rZ#s(6F!Si026$4MD$O8tW5DB3b}iCJna@G4)8nHQz3FB#b} zMMKt$7`0i(P&k~Y@a~1Q)dlH{Was2E{Xj0|mWyFnP@T*WfzP1`@HorD@GvL164Z~4 zPGohZVa6nS27=+~i8ImCM7cn~C3+y`ILB}thh;QEIK)0(NRfU9K&e8c)X56nQ5z9ZOb?6HIdznVHfu$T9JLU8xVIN zu%8FR`eidXc+-8E;%v2CUVFtedzFCyLF+7vC3)Gf;4O3O72X44L=uE8I_f#bfEvi} zT{wadkGn^94VoTw>>~V6c{%|=bS(ZXmMgG~{fyqvm^%YSN?S&SM+Qeohtw1%fQ=Q| zas_Z0*TWIfC>Eb0U#>z_I6i#aF-lZXu6g=Qw`UkXmQ)&B)ParZRA5zU9)qbt`1E4y z^$|6K8`pqQ``4)JIkC8bY7Cm4vQPRa4yX*rfZNj4)r7dx8e;y!n|m_slWyN^-js+8 z!O;oRL`0Im;*6>rN;CHsNDa5kHg=c*X9gXze_ zJ~V)`CgK8@Ku0gR6<OM4%l&rofJJEewaTsOk;L?y1pP)60#WiU`5_Cw{a!o@o z9Eq-~v>#nTodjqScX4)&HkTg0bcpx@5>0+BOSVxl$|eONQ3v2iy>^?!IwH+GeO#E(T zh{YS4=vMMMj^_G}`AU!iaM`_gYT{N&HhWemW$W|`g}hwp5Dw^YZ(L!)>~>Qtcd2CA z4a;XZ&YPzjrAs)lWb*IHfrXEL2qL-!+RM)DgqTs+m^Jw3h$QQ8`nD^0Ck>Bs+jSKw zDa~bEc6V(pbB<%%ma+?4&C(B;-si@`KLF%zf5vEPuBW)u+%RhDkkRmFbhZTQ`)=#f0iQL{Jk^{SV+}YX*4qm9c7Z2mZ>HBp&5cR0BG4Id2Bh@K~t zc+fYO_xd6SQ3*pArsK%oz*m4=jmJ4Lg9Hdc zoFhYsVGVDhaYMpAIJXAq#0dEV+{M;+2WzwR zcIj{~{a)!>R32!PZ2TM@fxN@-)^0SVdqZOs;a!9>TWry+y5hp~ijgAgf`8s?jx)z^ zYWCif0elAE1CI;zo>=qE%{XYx!$}(f283~Bs!POhe+CbRYchXFb&rm>j(4{k-XN!JjCr@l`^H9409n`-^X!Y|_seQ86qaGuet4hX2e*ZcgwwR* zT8}cF|5CbZ&0QL7eGxmeGN8F7=aQyx+yssY7)UW&v13zaG_9t#kYPT`PL1gX&Yzeb zH{BVhgse(QB`24VPmE_5#8GR>^qp*IPfHoh3V~u}%1qZ#9u7F;J43NIhS3-4n#3u>iQG>w1~=9+!isSc9U1Qx%|#1C ziLQImaO_gz&8b(yFb2#zFc{K?7sn&IatewZW?B)o66i(BEr)j&KhwnX^GQhlbp32f zQhmbSnW|KtvbXL6N<;;{B+hv*7ke2wC3Ur??h&2wjN{w1$WEHpDc42+zQf+#6XI_B z8??iKV?|f=vW*zDbl_@(DagT&aqa>q{@R z^%T{yb1r7-V8sH0?*0V$#g6Cabkk*OjOf01Iq>eD|o<#Qg0$u6yb%Xa>inYMjh68OJQ@~3rhD>-*v^K3C1v$ zA#7X7bTwMWp3sWvvvn?8?aS{%>lFIScIXjScF0u5Y^&wBujVyUEAj@Fr1o`+%w&$# zR?aId`w6k&ZAF#+eZOw!OsuVTD8OL7=-9<3Q;G-BrTwC2mv|Q9rYJwD#bU2-^Vy1` zHeqvtY3QSBT{&a-|~xR9VW7jdEEE_8(S)YVy&IvmO)DF|%_ z3@dP^0Ez(+IaAQ2U&MWO)hChBg_(gr`z0+7!aFv2ED5G~sM$Hj{RuOvRBt!fM6_h; z0UJPk%9!6Wxx5I<_Bk#FEDNr`DM3n~kz^s{Wnw<}G{l1i-clqU!r3eb%T%>40y$-p zq($}cVvlpxl06pA9xW4`Oqfmz znOaJBDbFCK!7Dd=YMy+zs%p6fFB}h!S=EFI{*0z3C=6JV`Q?m?Eld(g2LCz zKLiRD;ocw9d-fGQrwA|mKj3nB{1I0pv=*>nK;Ztd1?C`!dp45fo0vk8cwuUKeSdPXvHKAgK|pF@>FN z_Q03}6q?^)FcJ<J)Kt*zRl6Kyf>}QD(R>@o>W0q zUv>u+^3^hh&SN%_n=(?s8Qz*01)c!pGtnrVZY4R0y^DK_fpbQ2pN&YpeCMkV^boEk<)QH+6V*@%u1Tf~6)1_S5M*LX$kqBX*46YQ^XwYWgtD!pC(%Xk;z(%* zotg#`lOuz3*aIO5bc!$%} zZrChOe4%ch&%^BaDy3^`3|3RO8|MCfx2miLoEpZ&cnV%xCqqA8k*Kja*QaxZ^kM>q z!H>J0pLjXQKVwswIhoKU#}N_qfn$EORB7~&IiEv)$35+a+rNe7O9_KNo4ISsgpC$l zNCtgS?qfLSMh+eo(wKTrpQ*MJu0gMG!Iaa+%CcwlEO;eV@=(i8`w~d-b?YP@jrBz3 zs~gNjU-{w%uXme09q@Hyo0R>78O_Z5P1_yud+;&|d16m~EI7HxE&%LL9 z=3l-D|8KB_J>#6RT0A04dK<7LRGHp zxLIa+vESzDF3UfP=o*^)5YsyZ$Io{H{PED4XBtPBa(h4>yDR7SwV(qXI3=lzkZw}G z0pm&+c`Jd>l*h`;(`x)hB=@Y<fv-{aSgF*sbZPN7c+4t85NM zHkvs1e#!(+^vK$n-G0fFs*Ik^I*+Cp;?%S~pbcxFY-_Bs0YCm)`M`Bv~YUG$ItkmHsA zHWJCqaBJm9nBA{U3rU4Zn?{++ptK86z6dQVU;5j!qIW;P>$DEhZNw6%NwU? z6cO=!yI?C;8;UjPPlkh-;yM}#qIL=gs5LO>C&PiR=Z@Sgun7!AJ3treXQ@3MS>Iy< z5|I1_i@4dkoAnD+@dP!aqd+0TslTAqI}Vv?1uPC2_aPnvjgi#g+)*Kx)ID@*&UtBt zbo`UGwaNh9#)(52y);3)OD$Dr!dQ;cbgo_Mvo!l)M*k%kB)KAaQ=-Bz=J*^;64qt2>t~yftc46fWkAO_ z!w8`xIM1mGBeqY*>BuQN65?M>lN8myYL>XWUqC1MzH` zO#<{rt6&ahvzEKrTWYTS#7o6DV}0H>J4w|@-assp0$JTgPQS$sRiriA*d-9BO%f=9u1aGtgDQEy~U z?wc7)+V7eHaL+ZbG7bE}X0Tcn7YCsy?FY%~v*IASO8MP8h(>`$4QF}&1lj7=85?`Xe?_}L z496sX%Ff1E^l+&$Hn-{Ou0p*04M$>t85*M=$*Ma2PS%=Evf&M>9K9n|vJcO<$WOo1pIbV5m z(y{5+({i`$T{ZvSH^0cIVMp$$I>0K(uHD+(Uwng!jN)e`g)cA9)GOqb3e)1B^{?Md z#)eOS(AFW_J|%hw@o2QX&t`cL(&5&g<;*f)sfyqr)5f8y&^9IL_8>>ZJ3<2deQW*T z&5PGtFT4BOueSDIb{fGyxv1F#uEgst;GPbC+TDRNfxO#3l4=_Zx$|FJCd}bkrk1A4 zMaDXF7gA-)si8ux$|=HDQz|K6IJN;pkDZl~%S>&8K6?gcNM5wnoPn^bh?6*=r3rby zN5Gn*83*^yoE*wCYn+ZT=HybI`Qu;^g&A3awu8Fqi94Md!Ei9iI4``_ zI$A5ZhYMtgQW@SPcYJuqgQ4_3P0HE12#LBI1)34%$wut=z2JNXA4fw@afStSDF|}c z?EYm26Q4VJ{aHbCR?n%H>iNvR$KoT%HKq6TyR`SX?~P?T`jq|YfA622=R3)XeV;ony4+b90N^5;+OR(rLz_UQ4qPrm&V{CvFj;G?Ee|fnwy!ia}Z?{@c z9zCj9|FuW0wKco`Pady9`A6TjR{s>V{#gHi`JX=rU+?zU1Gn1E%b>lo8mz*mec1ZT z!*(lZKVE;dw!ZckOv^CFtlz=c3kyTwZbK0209Dr4rS`_cgi{p9y)lSP_^|VQm)~Au zaQS~+)xVBLqX7ScV!_uG_aXSYKROS-{;_j-w0p20{B`$e3r=DCycsMaVlEnpH%W*N z?a`@K?3i+E4a?Y`OC{$cB7r`uhAc9N!Jl=+8s0~Cu;tDC_Dn37X?1imup zk7A5t#7u}V08|WQNBoz0jfpoU0=hBj&K$yVE3R zhamb#u*fhM^DqgQas#>af!umebX8b{@#o<9VCP^RjUUO&g*uc~z|l9{xurgVRT-pb zae~u_YpD9>uW!SdeT@vBna$^+-pN$lIuYC&j-nw-h8nl111gU9Uu9SYoXW;NPQkNO zcQbWlqkAJ_IjH`I@q3qz0ig7(j;&PmXU?er05laeV3I?-7=Nue=IwC&V>o~xN4<0Y zaeOk6A2&nzVP=4r9{T%m`}J;6-#t2bxZBwd{_A)kl7ZU0tp8&X=#EQ4)<-`q4v{(bE1& z@8S9QVxXS8-}P4T)t|$5`&+w8fBlJU6M(umEaCn7=pO^OWBED(T?Feg1r1b;$Zy(4 z-z=KBh7YzdPZJmB-&A-pC@aiU$%Xkh7j6W>Z!qq|2?+D;zl7f2!G1!|pFTwj4o8>7 zIU?oi@z(R#o$mG)C+`fJ`t8y7tIl4@`~9uGPRZ-zpWpbe4?BBXhd&%GK&xuc0u9Jd zSH%o`v#4(k^(<7(Z)N%FSyPjCGWVphk8A17sZYh}Qy&X+sJ;~@Qk+_+&!!r!>@pfH z{Vti#JJ09caQ2f{p!d6>?RW+Fju~kC;_zTEsPiXjdy%Rv2IFzjy!P!ra6W!%RH2s_ zE-U@|V0#Pt+Sz+^aJY5&Gge$^1mlH+!=27y@cd`p-vSckkJXCFTcS}d)Qjjm9iz*U zdVDhICWc8YPO_gCeF|zT?3QmpjthY;;2*svG6K_wW-u8Jfe**{9u3tR!J-OO*XHBR z#+1k{2!49i!Tbdn7G!rHcG4o9ZHvuCOk=*-SfG^(wqCz3Z?(8=v)aboBcI)YMQgeYq=u#l~s=Gwfj{TYnS9Nmnj&K|BKZBo|mo&t{5`Z#xlB`281}`7D&7kJ+ zDhOWh{?G{)rT$`V8mpOWk;!0Hi+GqbOM}bM#i%?Rr3DQjV9T?I|L@oA!NZ4h6ohhL zR~1CwVr*MAta(s}N=r@n|3k+%l>^Z7fEz!t(&E<-XH~W1 zRnXu=Mm0od+KIou%{SVpEqwLW zS15o_#g^M5DFzXIQFi(wOa^!TSCpK$_IGFm%wRTfrhZLoxF-B+qZC*zC^;6Inn*Vl zMFxP{u*FFo$g(d#vqAy@ZxqD#^$cv)|llc^goS zvunW4ugF(Pg1>Qj*yHt;rSBU+W5h8C$Q1Msp6lPQ|60d?<@>LV#`h1i7{Ks)SSqE7 z)GDUCUj$a;D`}<7IQP^QeV~iA-fbWfp!qpl>s+CwNXS_<7rwe(`0CGBAs~3|<-swm zl$l+(r*3(Gw6$)xV}E_yyFM zehQete#pk7niIkQimQcG;2&3Y%f4zVsEA;or^QTzj9LlxLKt~yjy8&UGt)ArCpE31 zp@66`cfSM|;ShwHUxL5>_I3C6H}2tW@GiKu3m&|4O2PfNd)fDAnS#L za3mvBkTEEOeYxTB|J$dV>|U`F=0F4aYifi6^ywBIJmQQyhVo` zzG%Y>SHUha2xx?9J`hr7?; z9@CefyI>XnVW+yL*5t76^`P zZ|iUVOB@)m-d#Oe?Z@tA=XiGy2K4qhynaIC-Q&I;Ztc+2w7(U^a{FN%!;1VOc=)x4 zmA?dwFb{`|WYV+x_%ZDDUtzbKzc0e;U=Sr|<8v+n|6#9*Wq{AEMfpo!`2V#17t-Q8 z)iiYec?TO`ga5wE*I$H<+l%pbqKP{y;x15o*a_FV?gD@QjzF4zv`U)ZIe3fmPZJhD zfcdQ)!Hnkof4-a1CM+LR{R@2li$BpN?N!aOd(oaf!9Nn3)AFujr&b>=;a^{Ll~>Dq zLI1w$N(wOTp^Ob;E)?`g#B0&C%`=9(4BNFn0l@j=TOzY_;xu*|6C^K|i@#vxfg6 z&nb|1I!D`wyKjzB`Ln=vm&c4EF6XuiI4c%F#A9dIC}mVDZBK7n4qRja_aiVJzL;>RTaFi~59!6dpa7Z?3JPE*- zk>f1#Q_%C#!Y~>QFvsb8yv)O~5W{|BGq;*?5r2P?_9uAmpq=3Jr*QgU=bkN~!feGZ zKsFf;)6qD~MZ`V@W^^*bnAi)O=-(GSf*(-+BG^RXbw%}(msady{-N2PVm$2@hd8H^ro}D`(hV( zVInkW{<`&Mm-Z42EC!heb0pnRS>7Tfx2^rBML#ZzFa%t z+5y!@`tpxSifMT`_B#$C;!wTN`17ax2gjZDXKd)qUKn)9ASu92mkmM?htW9%_B+l!_jZ9|2lMw8 z?hOXlBG<4y?L4Kk1$zn9i3FK2p^&x<;gAD2(2+(!Z1f|O#uzg@V-5pvdCiQ|9La}% zq&_&B)f7~s-f`&GxKE@j1lVVeSe4`dUg!AL!Hz?ImJAVkeGzjEbR~lZrA-FWe1WF| zrZ4T=DAYC~fepP&#aA$X6dk)m;IB__N@7SYV1OCV6UyY0OL&%T&UKFH#L;P~gn4C9 zXl3C5=lm+pIC83#K9BqT2-qa_P_VI&@x&!ZEavElF6R!`!gR1egGM2vvmX3|FS{dT zM{BH%>Y6pF1-W@5JT`|4tPA?0nZm}M%DAj&k$76+HeL9~Btnlhq{<8nP8;i%KxERe z9A@KEFPVRNsv~ow}SFs3qQb|3x#$~ z?{Zi#mC<1t&Cp!;nyNSUnH+x z)T#Vtgqd*+Yjg{eQ4Y%%(OY6+OQPw<86kboOahV@vud!S(wz9D!6rNa5rzF?>M|-T zdQ8Ro;fFKV70XR6&V%ue_sUHmt+^yD?Jrnd`vO>BY_e&U`4<0CnjA@2a1CAWWKV{d zKorWY#guuN&Y+y$p3uB1uyO z>@siTo`n1XhU$dmIqo=bdrPR$B+#z81deAvUYz`K+#`nn41|^8iufBxLqL8^ECKxu z2l2-U9;LVWzD$O~ygLFToAl&{$QajiOcVnDYj=(TTHh?wUk`gNK-b0DAd&kig$6PQ zu+bnEW5^`r6VR=BYzXMcd7~9~&tfJ~@mDCd)PjzjUfNbubvfV55lVFn91fiDz+u=c z6Wm9x*s5uVWTcD5WD!x zJ0QsC@#%QOTxVbjTw4EX4M-)5TWB^*2^YM}Nq3Rs74lLFBUm$A`CB{GPi+QYckwQ2 z!TXe8GgLr*_;c{149cWyFc*4u#aLWLaUGqDF~34CJqVjjn|r_nuk5ffij?5>;9}xO z$JJH_moP2dyMjRl)_dSv0lUj^{P++)Cb_n<7%xsgsX49+E!Mxj4wkWn#?sPiY2&69 z`SB2{P;T#r>W#ez!6M!|>eI7kkgLW@SM#{&xJHZGH9CTiOE;c7BMqgqXS!J95KR-) z8`DZXL)p8*CPk9Yg6h0HJb3#C4FX&(r+7pO3fZBUke>07 zIj!}$x!^)D*i@zUN3B+~)oMK;s@yRz!%zw~#Y_mW)__1Dm80S%x=53Iu+h$gn9z2+5L^?OEJPid2rmVgRVN_v&Nt zW_NdYg~g~742LObKxfd2i4YCa*aWr(N%rS`;K*<^gm{@zqo9h9aTRvZBzdgGZEmNlBZa4 zk&?A=5CMEyCn~mp7>=5os{|u)EUP^f4mjWdig#y8d>R9#foE zVHhEs3{S8<`Z6@6oWntQgALkzM?E;vqAo`K5@R7pMV`NX3Do&DY#zV>R(qi^(KH%o zTxP+o(Rigd3=_nzhs0uzBGjB?ODB`F%)#7xd;IF)aACpov1*dz++QA5T6lUo;9q|Q^yHo(%x8pgKc$1yvk*FV z1h~7Q{py~+50v)B6{e=7Zd@ycfRTTQ+u-Y2C)8m|)&G`38CVL)7J`yN+HF6K)Q7yc~94na+le#7Z`UQ@5r%zJ*?LqTZe{Fw=Hw8cTuBA56o z8;>SEy5N+Ie54ZtzI~GLfVWedV$w#b>X&rAvOeO;N&SXrdKtR|5l=rzElAVP~ zTI!!{=%8iCS{gJN7bycBa4UTsylrVHQ8YKCDhI0tkuXEOix?cxzJgk}0d@*6UpLG& zyokv-BeGxAG;p@lB#1nik`SCPJTn`c(34<^B_53?!!eB<@1NsdK%w;H{Sn!M*KMmy zL;R=7aotTI*$xJ$Y`BSX*?g$<^0T3hAzHf#2b{Oq^@8oqYhpvi&@cqj{rmFpOAGTf zQ@qn1b}sWQA=QLYLsNZ|BM^9V?*$g1s{j=$_0WOdSNt2zX%* zqveumE7UVPr$ce3O!GFsyl*w5>M2r++UrXgJo<*<7GLH1~ zH%cir4^A85@I{ABk z)&CS|kwcQPNhw<#BN%z!-QVf_&2`C#^N6OTUE>Z!7r+tIO)!!{z_Av8Afqs|glI%S zQ$uDMg#@b9m&tWJh!K!e@gPKANwYmvpfF83>a=T?hWL&{g7Gzx?0@XGd%!Tk81R7h zOm1(X@x6Jq)F5~^t|9Cq*7&JtVc5*(=HtKyn8T(x0H7%5S{qDr_UObvr>Ry)ecavN;tbnI9IP#Ixq<`E(oD=cYxIMP%|L(vy4&SWmbj3eL}@tTPe#vyQFc?HXHl>hvv!7?wo z+l+DN$F3ErwgK1x7^#tes;Mv$-9w@BayK1x1BQ-cUa>#`v7b-I)*ulh z;UisJIhkY>KpoBP&_V@`%7Y(wo_Cl4!WWy@RKud1VDet-OJZ8pJ2K$FbgGkh&=;MU za2^zZR>84{l_YRQjS+~*kyfD){h-xE7fv;#hxsgYunjf}p{4zysztFM;vHQ5aGb_< zS>MJKFi`p#A42-oQ+!AOP+0>>baf1r(Q9P&T`vB!PN0tAq6HaDvNekT-SC4$m*O3j zD~5mWA~$>yUDR{mZ>#2`Rgp^Lp-st)1l!o6z-kY|Df6PbY&@WOBklg@G0rDhqS*&@c&nsdZs+IZqp>gwcRbA|QRHH>}`_lx7)w zmIIAAFNxnYAT)(Ytso>3bNQCF?2Hs%49>?gw5FJmJ11_jZ0tx1x9DzK=E7iyxE1)y zU~MEyOfo`m96Dm?d8`=jocsbnBn?0gkr|8-On%_NjQ2Kk;rLCgT)ccpd%elXrJAO6 zJqmkBkBV;L!dI}`(Sd@gKMz%k^+e)FiH{^A*-8SE|e6RW4Pz~DSU`M<_zZHdllCI){n!P5ZNwp=b>YcX(RS0BWJ;Y z8!Hh(EYyK%5rQ^v;gw_hqAH;kHyX@jnb>n@h7WPU%2jM~B~YTfDKg|eN+&)Uf@t1H zyC?7VPh#FeIcwwEMsl`_5X_r3Ay7!g(OSdCix=&R7ae^BIAre@PQ%_<3}4bhpl>2y zlz%-PlE&Ob_obZSDL#6Pv6r`=!+DcrY`W?9nfECQr6g=MfQ0J|oV1f*`c$EHCg!vpGg;e{aLA{mcIyW1DTx)*m>z%=aEA?k{)3l*ha z+Egt=>HUU$)9__DqliqUZLV|)8p9ousdHIY^?q6X~0Vfo|rttu`V% zp90Uv+Z?uj33eSS@692Bx638R1VLj>=Ti7_YjpO@lXv$0$DNb?$;B^gocs%+puX!D z8R>ra`SD?=)7|SFZ@t^lCsu4#yM6;7_b6@<3waeEO)@SytvFg0pH_g4v=hlvmYPvsN3E(TT||jrcB8O~4sMml60ERJSp&SM$_$UO1)tuSrb`1ss?OwR}zemN>S; zTN@Co@CAh_lBL9y*!zg_IIxC$*T5eexsj-tOjCwaIK))7|CoU-%pv6Q8RH=n(Vvfq zfJePiJRB1XDT*MX@Ww_%@P=oJ(Mgl8jJeiKfDD0M2iAaW^MtDSmmwyZtJFp^qVTxP z@j^OaB_ykZ6xt+5fIqs;k|o~I*%<1NI?SVOm;F=9_UPXc~CO-+g4zq zQgT~lQpImv{LW4hH0 zYTxv0O`KTOHtE&5fP4A)ozW5*(zQZrRMwx`cZ%b&mtA(Oo~Hc1snZM|%gqfSN`qQ6 zr+x*SfW%(SLZz0X$U)=rj|cPtTKS3Ws#aglc|*Mq_Bwlh`WRWQgcobU&%G}~z6`)2E9=V-&Ia{#ikncK9?4S&iAkGlh4?*^uYN2&#S@#NhzI$Px7DKLJb2PaZX z*VW$Li2upJeey1!KR4e4M*fn1t=den3!+~O)O6ulpaQ9{uC!NLE9C`O{er7dkn)0y z>%8PA^E@$8DO~|=&4=~`p}mN&0~7&nmKptoMJJEbQXr3fAm5gCDZ}_lNL-T1MKl6l z2HkQDwBjGSPsMGB>`5l=KJ=#D>w;Q3qwQl6&L-crdm8oka)txtq=7n3U=fWUJECzH@kZaH!Ojw!5&4?*VoJy4Q0(zqct{ z6!qP?Z%-dJ^73g}+V9*pTlFs(r;M`~CX`=pJVt8*UIep3>p{&0yec^m3v=NqlBYBp zC+G_ggq-~S-0YGf)e3$!*LF>JX|A4>lIFs(&~W5Szjl{b{@Rjf!LfgQ6Lc8mHd4kT zbiyj0JwD}B3AIdR<^f(KiK;ldaoC zOS#DfYoO$eOi;Nb-l%>@tOtnZzln;7K*|2-M(@i3G05u3hQYDOk-^YY^eaTxXry3> z%Yp$Cv#vuhs%G2tSji$pnVWqPIF*qCEeR6eaAeeg zY@10Tf213Dsb81}^nul*CU?eQ1kF+4g+2yfxr&U2jsyK%ppPuOAmlDPGr5}+B{6)C zM|^34@$dRppwq?|sO_o$gkb|PdZ%flAE7q@_Ey_vq$98X@!{@EJam-_C1ZlIT^OGO zEePyYP8RgzK0_dLQoJ}MCFx2d$n)18-CeC>BJZODMdjG8nK0FGhBgECA2WhFF`5)K z*UC?W8msBam?tNmJAspW(gj|wVk{2$XnQ@)lDvu&bm2aCkyEH-McsC5d$_k zrqfBA9_^e!Z{CdXj&XcLl}InT^SsM&D8W*{9Pz4}H97)MAFgh4cb#e*shn>-7c9Fx zoZgqFby-9h=Gv9z2X}MHM-jVXQJes0Yw5Q`H=$zK!A?_K$H!aSuN0+qn(5GLn~lLc z-pNqDYj-V!@nlA9IGr=CB@1G!WHuM8CjNwPU#kp)n_3m_CXF(uo^Y5J)XK>ja5@Oj z&{Q0w;2O?=Ro+&Gi{>fR>rgHsC^S!B0=n5n@w$Ym$x{>BgcR^9r>cpwa7r<&>VQNb z6=aqo8zT!bm|4)q82Z$cQwjFV2f#Inp(k~vtI{&})^ZpW;3GeS#zZ}rrIpNZ^(8=+ z?mupdK(7u6#X^;;UJSd%G61c_{gRb)H%xjzGYG#K(KvBZ)z(IC^P(EpC~-Gb7FF!- z&dIAV^LKP{Kch$zlZG^x^;ywVb8#Xdau=7rzGWs!@Ju|I**q|z7H|Q1vF)W0vj${+ zrS!o~KoO4<<>TFGlSwJ>E~t#b$bg1SQI?t}V3Jpqp$Kn_!Jte$D;ukVt~5D#2C;;> z-g>I%!b-_HJtHCUUU7NaCCekzTCp1K&s>dmel_yA*V>qNW;h)G=Vl3#>yv4l+@nnw zw#kenGY6`=;4V@@D;}_cjNESvl$cm%rgWU42(65p;@x#1{~8bx=V#K z0~vb&SdXsPjhsc{9J67F-b_B)kTqY(-r!BXszuvN@7QA$9Ckp9VUAw z)@X&nnze$?S)Q={U&&?R%u7bQm>1z$tmx6+*2~@P?!lYRz5!EIkf5qNZo9 zKw&J$CRkg0-g&vZzhTTc=%%NbPe$>Wo5Cw@SeCVDGGx9u*3Z097O$1K9!yh1xAID8 zinSq1AFJB(KyWVi*--Ke^{42P)v-dZ*~oz2-GJqZUa1*5yaWV;_kV>HAFJ|yYY z3j5ieqR*Q23m|`2G6EAXlP85^WNs|{8RdYPrA-)3EDyBz)C?I@v`bX8e4x=l-Gu@N zC?0?{ZE0iz$}NZ~E@zWXB{-gAT5WtxwCmOWfEe(?vcrZEPv&5V<7Am-vw{f@Sv4VR zTe!+&mIB6w+L%~6DZH}NS~#_uar4X+D;y=J*U=Ea^pPh)3$O{WZ37+skyt6Rk0Lqm!$jYOqd?q3q1OZuGa({dWPqV)L|EjUYI(UPfE&eUP$V&yo<{YiQwYOSj=Q3IWUkz?VwWN+v z|J;ynQA%ika@H3Tnm4qetc{?&3rTt0I1)8S-*KDlc4Bo!M z94qLzNgOcS_A6KN)MaE~S5gVR9GT!@CJeZQfFMP#G~AyM0mF++bzx>aQfY$3pj(1x zhGJ@!?`x_Z0ro8 zi(n}>EZKWQmoVa2cbsxXqf>PBh;KNy&!gT4qztGOEM9$>y$)MfECOpgfbshW$HDgN zgCop(*w_e8PY09iyq=Bwu+thF#^OU#S1Ed4N-7D^j$vosBRlinu`}--JHx^Oa9T@4 zVz=xW`CgeM!6)GBo{y^yN9v}CJ-Tcit5do4>;a}Mq#ojZC$BTf7UbL60V^nb{GEtxuOXnPQaBX3X(MHayk7vrl^ydGM~?Fmy9 z1dsg2AYJ}!7TL40WIK^EyfF>c{jwH;G-sR~qYKWbq0+;p+{nt5rxf(X%vMLzg|gc< zT~AdzRLDKnLvfj4f51K|Mk%D;v>Pmuf727m^<+F6nXBPY&}=W@4u7^6H=?(IGlIAB z7bnL~3fV83ULDrioNV-6qOlqcz_m3KR?+3j85JWX!?1>1qcgmbqIjxST&7zviS>=$ zQ(#y}Y+r0rd=lzYl3L$Wk<;VkGW|eG-b?AT1n$hAv2^l!@^iCbl$VbXWFs}3Ns@z1 z+>Jc>oo>7fpeS?-tC7qZs90aCB6WjpvO=Cl#p;SeARGc9ZkS|%T`~-!VO8^68s{hv z;U~gF4+%3H??}1n3N-HiIWt1tyeLEER4fQJSe@Yd=*30zA3-P@#7e;b+ zk9-BH70d!)mLVv48O6zvqX7%4pjf#uFMzywiQ)`Gi{9mq-NcB~mh&V(aBp9qmKygNMDZ=aYv{l*YS}?H(18u` ztKA0@u*&TV-b~!KbeDnqu@Q^{-Nc5cF1NhE9zITPJwG@+E{p47XY;{>ijW?;;p`mj zcd*a4BA|n6)|$Zj*Wde-!N62#OTl#NBNq(3#ejZ!i!%3!-i10!nibk*+? zzjc$8H^<>kZ~iER_Pc2KjNy;{lV~$PZbx=Jd8=gAJc=bc8FuXR=pFwNQWR&j?dn2- z0Hvso9+TJa+p>5Ja;sv57ba59`P7MUoSu()hA_B{N8?F20LB1gEc@IEMI@Zcpv=vk z5F=8;pnMW{;)};Zj{jp$Z(S9}att%oR89Sbk3C&yY5dD%RMwYK_<@T!n`DtGd@pCdgT$A$!xmQkRGLhUj6fMjZlChUw_7cMO$s z1G6=Ms!ZPDu#`dYqn710gfp~+rJBOLD!If;*O^01?d&v#;7OK}lF4_7|5SgFJJ^8T zV=k=3GQZ@A@c1DL)`3j{p#vGRexElEC%%&FGkU`r$N9Im+7QWdlF*lt1Hcr>TO8Aw zYY=9EV?*1e(yfHVib@cVXD($WO0C4gcR3QpC25Z`FHtBOJ^(O+L^v9&(;yJ>6%GB-`k`^9o{Z^ z#Vpn{{T*Kn`Rup5dVgm!tcwA(uDBdn^Jde&R8~9Htv6E|`bngQ%c@?>@k6x!aS%$`ffhIwv|SSSHbi%vV3SFMl^oAlVQG<&QTjcZ;2H{eXV8B zmKxF;oeRz`f(b$(EFcmAwc$&dB|aT1xFtE@?8ty0Qzh0H$`AOG)BA1XyNCpXsI$d?Ej2AYnQX0jOCR5a`` zHch_qW1MEDHCA-uK9`FyA(usoYO5d-5fBuY#$-ZWp}iI1i0G|}qB0|(V4Lxn90o8QVs_4s50bknFQi$a zzo6=CmI!Hu6_4Fxva))u-4fZ9+Pf%;h_+$bDpq zw$LUF-lD3?)9#8iLh>`yzBdygWCn6X}vjvhtVD?3OwsXIh#gJu*=CkSU17+c%eB@~?O zzX6rt(Xom|;4O&K5Gj1`G=_So)h7~@4SJ$$N-aY>ObSu|enf&U&5deRk4$ztdB?Kp zIom!99R-92#E4@a*;)%ZIAKaTBO$!79!lT|gwgNJ71y_-!au_7CE=lZ_d>t}A#|L= z)isN;YAHtyo-StR)K-RIuDfOMPI{+@FXVi=svl&H zg<&ZW!(^hC!k>EqJTwx^`PyrrK(d=!u2?R zef;id&*0BgiQrV(u%EBe#l)X|0le2r8Y!f|tHpR+G~=TA?i`(iKc5+2fwv?YktFP* z{d;A6^v=L6q`#xH^V1!*O@mER%EMI7y~djFz&PfWUPP zk*gFO(#HU4z!%lkrdUO_frqTA`L7Yc#Hg^=v-5T|h6r3NrRt_f4|>#uGqG~yg>#{? z#;zpiG!pL$>ahQDbi25X`nTx%2_{vH_*RE%e?+%fQc&cK-xVpu2a>+CdXESN5HLdW zEzMu)9T^lr&zVS#iowYmh7w6XA6?nqe{^wn(CeLC9G-1&$0EU~9jsD$`}Y~dN|EjG zXNc;pVTQxFs{T{|*3`eXCjCc$HLLQkxLWs$^L@>9%pB;;R(@F zdy92Y-UHDNm!CM1uj2AEELfcz?eY=8H@N{|lwX*UWe|Rd@iz_=qk!w^%*Kg{m{R~k zxv6b??cZmL{Za#m?MR1d=^7qs9si>^otDT+HxM8M_o;r=-Yfp1QGXJ@9C)>71=$2wX+{%Pn#hMDgN zv%ljFm-cszsMh)9cnZlt$VJ1)y@peO|42L6DHvigPWUTckTSOOR{#hYzI*9}UYT!U zJ@n7^!eXKy!JxPCd;4;#U&>{38Hd+HwGeW(5G?PePbMTbc<4jq?syDGK1&?5YZ#6C zQWZ>cocIC_tj6|IaA=!S4zOWC!Kj9J3-f_oy7b%3p#D}MKD5!`lfo0f67k9sTT)cVzd3K*E{Xf%oZwkYas|*FKW=W#0@;ZiC7%sKbGykKyx&@D={!9rp zb6Q{-&09A0U9?3BC}9CC&p0zREq!(83=1Y1{#uVP{JDNBki?0rA!r|p{%(*w zDDcGkguWlc<`?=c5tPw<@nwbvvFn9WUG2FfkjNnV*NS~!tDgvl`Bt^nZ_MYKQcwD1 zm+ez!(T^DaVtmonR-ngc5Ks?2e$*E-rcp*401M)54>ZYmQAM zYc@S$g((&t^AY@cEV#pZ_;-{M?Zaq5i7fge1Or@bVJ~jPvPvI1x1h0XVoS*&#X>HB z#c^pe?7?Z~Q;BR2%_>vHt=8h;4pvbOX`89-Ij*&HPM029i<~bZ&UZL;*2oloHWHEA z1(Sr{<$W(HgCQw=Yf2H0-PsOyUqU1sT5GOno5~SF(HZR-=%g&tqZGM z2|7&coBP>+==`a4UiD}k{|(T&`S~&Qu0;THLDl(f&^C?=C`f=tT%ywQtXIOh$Cc3e zIJ{A^TmnggZ}BYFiTm)b10m{6J~on1izS;kriN5e`E=JIgdto2TsQAyeqW&>O3mtA zwe@JLAaWMg&&kljkQ{O-i)gT^3H#c3sk;I@6#vMsfzaJl1li{Oo4A~qzNx3=6=3Og zTwD3%#n?yTD3N>^rHgC~F_iQnh}7_*?=%6W7%4XrNlPwtDI`o%e2Iy$O{hHvY^Yb0 z4fuM^cyyvpBJw`;1p{M^KwB8N#1ML&po>9&a1+jLL>xnxVM6Cix!js5p)Y2@&Qq=k z`vR^J|9U(gayX9hy2bi7F1jqK*M4iAqYN_?b zO`5)69t%UcSNa_K0`2pMojIt~%9!XdWAninQh@=QK7`a@NHCAvi$o1r?{`E5s&icG zGbF#%l(AB-H9e8WJ{u1jc^@rV_@J#v$0?(pX{rNRK>+uNLE5WxrM{wWf?10wP}wBp z@e5@2ZQ5ksUVQ0=GCSp20i}RlwnCsNSpzp0Xna|kmnW1p!hW%NH zR!}2nH{NJ{a(O`9mNXZ0ssZDQarbw6@cIIh`YT6N$1$O+&1AT7ImT-~wcy|@HWp~D z5Ike?B6z4&Wm+!8+GS_w$EQ6Vd$EBxXSe;qETs!WE(hu6toqQOji_$5()7~VP{dAH z7g}JO^B0UE`Xl-aWWs_!2ap#|=U~j?)I!=Yf4pA{9{GRPoPsx1k0*fQD*xz|d-hN4 zvk~vX1HP!aztXC$_@=t5m)fJpReQp?YAePS`lh}D$NC#7o;g|2jIJY&l>gV<0Lwh^ zxO;$gp?zoZkrFZAjnu1ZKxwk6$^x3x$oj`<$77U40{rz{rEYW;ou9tz z5lb4TXaoHlHDozckyT%g?r{AVTP#YX9i4cX)jI{oX4-NuG$lP^c&gF0c*oWQF)0 zN<_NQfp&o5q2L62uWSsCV~@n~K?1*0wc@UXMyJLHhvP+@uFM|~YIE+Rnlr>RbTM^V ztHV7N-+T@(Y2aOPi&t~t(5!@AGjdqvvF3E!feL7Ulp}cIHQ){Y(Gsz1rKLo0i%}b+cZ74j$xKG5X}-*XpAhSF5c?<9Ai{r`>8g|EfQ6qh9-6 zT#akhdac!Lwp9CiTRn=ZzXbvopj1ZD@05TxU)FBb`+w6vi4qkJJ^y_%!tJ@gq^tvT7!+>`#66$AC0pYFMzt> zzZt#QO($2QYx)^3$Od!8^)Nz0lVJ(_{1WQqerZq1?U&J)YCtbuFzJ3t0i$2?04^X; z{Fl^hJi2_Ynm*^2o73AbE79j*XdJ3x^9S_x$!YJj_g@z$hhOSWepb_hf8)(s{0Tlw zHm^4;(P27VjFT5H$m$2LV}fw}>QBAh^DpHve_uMjc)fqnJ1gr!?jP-nsbHgx{oj{V zSL$#*JKs6oeS5LDe`?wvpPcU>?*B#4U$tM~IIeLb)-U&ZulJ97vdi_2y`#O}t9Ng< z<7i_~`xu{}UYz}9`}c(LpQrN~IBI=bk2co|oD)mB?eJoOzJ;G4t-FHwcIVH%i+AYK zwjD!~_x1HM4`wh<`jao^)P9a|@;FPq1Rt{z2wMvF=FOMUr^*`08dIg=fQWPW{nlEx zxQwQ$+L*U+H~KSJ!!!-Pcrm;jUYM7q|8s%4;@}Il(iv!DM9sHKtD{7|8@L-=V|+)G zZxR2mHXDsx|Nj<$IFaC*UUu`t=Giy3)Sc9;Z!`_K_!S%)dAE@5SsA9xX=Wq52mB{nbBE0t5cJ9FA_M_J^A_vXZDLRP_LU z_&A-Zf5333{<%)(d>b$wuif-B=obIES)-)7>i0bNUxS>{>W%hPvp?OerT8oS1lksK zMgPL@5C%Qqf7S1^{`GAi9$*$!^#c`7R6i)5qtq<;fv+mobSjv+`g#7mT2~ILI3@Rq8@yw z{_PKMM}!1L1wbQ&+`-yBeVZMJyC3=+Km7aq!P&_WQMTF`q8x0Or3pKVSQAh-!Ym_TR+y)DQf6?Z4-@Q}y>H@Z`1s)+fvF z?T>%m#J;~$kEXYfsT!L8e(nGM{{JVk*#8XqkD1tSC;wHOR{w9Se_;RD;^u$$|8Mc< z^XO(ipT2nh{1y+T4HC|>bTJ!%kN9=6IZ5V76dT}GzIijh9j|@<9sMy?75mm}pyaQu4M$*zxLg=_krxr6M#-BKa3@cO7nk=hLN*Ok6|4o2 z{!RD4k&Az`{a)GUk_ksIMkglF2Qq1zc_?cHPi9E?sW8F zG)&BFK%E?#ace&n{`J*pzB3uxUyjZEZbnyg$j~c)KOJ4)h|%od-fF0+;>HR=W59>g`I?zwv=qGOyi(>O3qzV+z&FAp5c>YE_H*o9(&Fqdq(Hwm+EiSV^ zgF}LTo6app>@P>DS=aq5^MifApB>pnR*%JRl=TK&6vTu5;m2>1d-1^jwm%un>~HA$ ziGFDO;M_V?8A1UaRj+yK5D}!?*-g{;BZH`9?)?7eWH!3GcOJn-5qu|pMXR^?{T!-S z*c|W%e&??-XNIOJ`}2PGZZi72T%aBlp~=j0 z-YM)(QnSGzi=D-v`d!h3{e2JZHWC?&iGih>?PTCtYLIznzf`}7SG0Q#mhAvutChDO z0Uf9hHNp2Yvrfs~$V~BMmV7YN`Dkcr_)(4C{^AT>{Vsb|zaE_1pWn!zd-i9CO!p`~ zlv%c=AchDUO^aFYteFMbu1gI^sQIZSTP z;O5-^3Kg{NZ?Nq(OS-<69jRX-DX;wv__+8j9V{~Y>zVxSjr>JU4{|+%4bA>8x19Rb z+mO%zQYVN87TTZD8fCbzLfKw2o!`g@WiIqQO}h?Mb=DNGK-F!U-4r)s zII9KmQN?3*SBr)9a8qZsv>+dD>Z}$C`9%Zhxb(^@K(MK^TE>e#xCxxqBF&*_zra#qWz9l@scTvOCYLQVbEQo2gf0G!p*noPK_1e-dm)%*LB{ZeyQ>nK^) z)LE^ACA=l7JF9iD3~JrwgiE11tMz6n)VjyBijh!ncuk9uQ1>}uF%s%6ziBblw%4>6 z3H6TOv>2+hTE)8sjsj=3igyb%ja_mfO*Y)rSuL&QhMPL8r6j*4188`gySR0u=|Wv{ z#5A1M+P_+cfwtRp$!HtSYLV(w)U@kiptx<*SuLyFhnmKIQ&RgwO>2JBa64#PcSQ%Z z78EpfR?C_aLQS335=MqV)0TU1VuVw{0G!n_#WI6Uy>m<3EkaG5)iM^1pg`oTmNa(c zn>wqdjUZt$tL8VQ#L1zib-yXtPQp+dep9lmgqk|5Mb&wWL_+u6LW4|E)3)FAyhwy@ zxiTRebHYviy@h&ZSSGEy$MK?=ZMI`~bCZoI+_dHmfb2)XrY=bO; z^qP`ID%jLnEwcC&VW6Gc1z^ewHg#6ZSh<2tyY7y?D`YNFr|LB=f~lGYB={nzp1xIt ze`s2F-16O`X*OlU=c5)N;oPwyvV4uD&%(J`_XsWWtY22H>m~84Qaw zv#Qs$n7F#J*R*&Qx;3xq!Fi!-SofN~DQ?>EoAwHuHod0B=X}@OTWI|(fZBHXYtk>2 z%DT>K3Cn4qX*b{WJgA|^)oRW@K(^LEQ)jh|5jLoD*ZihMG#gjz`KIC1Fs?T8O(8rq z)U@e0EmHjBYAe^YK!S{`ZBLWemf}FuPN-=Ja9nkz3^Fbk*e9xfQa3PFwg;iQ zwhT7JhwHSKs!3y-e2=1cH&8xge9RlTN#VqxssGQ=fDplQvAip55QQ0qR_!fCm-47wI6 zK$dUI(3d8mrmbAl0@{k}?f+HYi23`UU)A+z_5DxWXtd(GcmGpsHsk-?|NJ)hKM=oP zQ|l0&sm+mKQZRMY*b-(`3;^<4495M@ZH5IJXJ{DKiCoBC5Gyf3?vP0|9b*m9E6mUo zjg#yC7%q`UgQP-n=jbyCnF}E~qsSg{*uRhN(*=ajU#BUhB*ELK52Nv>*9JoPFp&u4 zmx3Tf$oZjO%pmHEszcICN(_+s-)A?FfD@8{j_)hc1hSGw^FG$wxP^mle$$^|Lx90K zKz_|X2FE%zfGN;n%fJD0DVgs8unkpFM+3~0$+>MO*O&*1@|EgDPm9?U%oQeo7H1a$ z0J9V?Hu}+GGJ!@2Qi~TuecTA#nh?!Y;ll4Ox z)=OPs8tMyDqSJhJipYT^VrAAb0YP+pcJc0L|GTx%Bi-n02)N(8c_|+yv)Lr|o~bEj z^C3T^Oa{jn2Ro;4dJvPS9_m!~;%TJL!ieI$;Ukg#U~m6y=hZ>);^6fed;n`el)t)o z5))rM?0tAJ0H*^*<5FmX1sm7e39e`(gUTIb>=-gKC{4i%(jr@ z-k;u_oan3!P-yqVXqHYe$J01X-)CwcXY=uWG#^6Rz>;*ykoF-IJhGY5bR{2?X&Fo3 zA{AjCJDiI8?$v@aRPP<1MH^}>LY1}A5ZO@jQE`I#A8F?yWnNt1XBQW?Dg%vlr}C<@ zTL#K-aCQg@e=rxrkP0nQZDdTPg6WGC1BJ1vcMy?1zkzhi%vCsB}xOVDC#c3+{W4cWN@PvWb_kO`lEz>CuuhNs6iu_W~krRYX)ct9Pv2`ae`+RZiOnst(Hq;dODS-oDu$1F6)|l!CHGSlaRiURUxf3M zr&m`R^;KEyW!%r^7nr*SGgDq%j3#3>l#2^R`q}6jK84ip^cQ?^a|hg=lToilMa@1! zB=^NdKfArSD6P+i^K9_f$zSK|BAR{uHvJI&;Sb4BZF}|4;G^H*#rpQndQ|#Ymengh zVmLWXprG&T3rs|~m1_nslW~6vC3LkualU`pJH3Fger=26&$oG|Wv^-PXwQt0fSHyX z{Hgiktk?Ud^j%r#CkEf!>bZq{y0hDhWy>oHTrH^sQXQQYziqAbUFG|7L0k34ZC!`f zmA{k=TB|p1`v$eI?34@It2gc!P5njXRk`2`^@a;9fV#e7v?6l z!(wv7Sg|pzu&}=Q900}Z6(xwB?tOdukK>D7#gES`5$L*#qj+D|yf16ZzQn^8#A9^| zb4Peo@~3#Z&JyCkdeW40@G==d84METS4pubF?r$$sg=Zj!_d1gw>PBTsTBb-5 z6(d?UsF?auohliqP=IJ4M1=yKL=q}hC^apa=UcKSp=OQcC7`MVF1h;26muYPCZR;w zRG5T%q2%>YxX%_#Q1iWmD3!N_&@!E7Q?{c<5C@m(ER(Mmx3@Z- zC#*(4dmr6m=1z*WyPQGzI*5w>p;~|Q>prLJHyh;+H8wy32y?_iX!=kM#Yj?&KQ2Gf zzfDQ51*tmWD&r)pajraX8%wwt^M@rwuDH~<*AsU_sh$Zc zYRSbga%0eXbV^$qua!_5xGum;={X_sC@{V|K-zAjtxzA;`X>BG3k%)FP(OR|I*!WX_vJuBGP_?AWV*@z-z^Du->U(=h|)#k%WU+hi#MLE+AF_-L@0p&+1TRvzL^QGTCt zapw-UQD#pzOo5)`ciNInt0Z|3Wz5~3%zgT?OeEJpGZ8Fq&76dc#KORJOV0J0`DSP> zHvFOwqTDs{Mux8s7g!A52UsI~h{p&o!i2$9m_%pB6hvo*?hJ>PPJGs8P!61WggQJd z5+S}%g$#9PrLqtv?W&V0N(q5#$+(cNT3$YTS(*g(Xj30PIrI_dgWWPBb9zoNq}mBo zMvZGLQYLUt&JFfM_*RYOu0MtyhRM{iUq}~j@`!`>Zv=4C+VnPjO`{leap#@wd_o2VqClW3VbIHec0;G*woNa zumB4#N#(w%NXaFzTm=YRbF!gUv@Rnzvv)A7563PZ?8ZedPUvNE-^?NPhKy_EX#`#i zoPwhpSX}0(jCC&{bv2ZKn9Oq%gzroHU*0O*T#qIbla(EnI-(U1oXhW2>lAq&k}Gt? z1;@>W5g#2~_Y2Rz8!mRNtF!<*_9s`Va}sF*TN@);2FIC>Fx&o=3wXd${az_fLS5C8 zxKNG^hVcv{u~PvVvM(%~%b^#+SHy6*b|BDV!H`BM>ciJ!G=?9r-9rnVRJW071+#mD z{3w{X)mDJHAxkAKl(42ydYz`A8f964`tDF18V_0fy2Q$m0@X-pxk;kPV;QVq>tK&% zlhV$FDv6p!mKpp7zLMF8B-7Op03&c!z#A7+P{URdmyl*?76w)OAyJGZR45iHl~S!K zgqCD~Pf`hwLcutm;H`^AFp9uVWwb0RB_Cf9Qp=SG^D?eZ4#UUkfS(u^`Aj}sfN1_< zi!LN%gNJ^DRHifAxh_JT~GNn3$hc3rI$^x%nc(C8Q^| zZop}BwN+TmjWLv2-wcDtr%>FZIYOQZ=NZB|uMOL{Q5xu5{RU8~R4phiX-*))A7Gtt zp@hLut`GG4D{kF?#@5ug!oFY#mum0xH0fv%639MO^C7tgdL`KzPR484C2Y`;9waRM znnRZ5UkxE3-U_)E^b{zvMpZEac1^w%XMvR^JY6&aQ;d4c1mq!hkzP64Ma#BPj`ANv z`V8Vg&8&F$C=C>r+NuiT%M+T?Rzc@HVJ$ic+1P-1*7spxO%os+P@1RUGo=-ktKpYw zZK1L^U14arhBhM>;4()%yX{YTpOIWDxj4!RAz{K{w^*%>%(S$YP6tXsW5*sy_(t}7 zAQ1I`(UKNp@&;T2w4<4+qefm}B>OwmUBP*kC?H3Z2$ zxAcWZSta^{KT&%CDrf(cq*o>TsH`iXN3zg14Zek zsgCI^@|wP>tc3lkO@&sM`=c`vU&|P7o!cDGrbwB(_L3M}V2A3;M9vX`bfv&>(1Qyk zPuCg-(iY5XhP8k5l3TnLJc?@KG2gKC=a-ACt0zYlS<#}CLtS#%ZR@fyX2@0rs=*t&U6)ceEo}0K~sFHo;Rt1YKVj)%TnmVEr z_q2ak(tw$FN6aEz=+2rL<_@I3ZRp40`Rcj*5UvBbE^icZdCA8zew=$Hvix0h((&*! zivv;0OTF0Mriq&xO~HdglroCFB1=E}Q~T;GU5A!8G?cj1#7|q(E->$c{Q3&EPK1`D zGIL1e*H`QcBEU0kc}T^iSxD{|4t3rmbJSdjYKzZ@wXpX7>9`INabpQD=9lx#ujK?PxE6wJ*^dPi_>+%l?PU(6y*c4vBV!*P-^(ehS_!m=2 zG{(z~hqHg&gGMEAz5DAL(?Jo0GBsJ+Xk&xQ>6L#*32CevsQ2nP(QCG|6@7AKN2l4( zrg(680({b=s}o(xEe zB0Unp{}#N(Y*jn8uXCQyP@f55LZc;3AGjf#LL*XQIQ+my5Bk~2%o^AMP?Z2ih5$VkviK6X@>YO<9UUL` z4)p+`9eZE#usK3u9f?@|`NKwi82uspD`ZR7gOq1*YeWIUO?1R^bhmvx2Fm;H-TloID5Nu+S9GX6WQ?S-N6C>2=lwxIrw(x z`!fk;=luM1|J6Ih)9K;Pfrj<^VCT)nsT%O{;lD&cXiP z1l28N z&g9o;XVYX5U1jjkmWkRWzJaAzfkI!Oy_<~A=CfL}84a&MD%iqrK})~N;9`lF{o+Cg zx=McZ1%XF7Zjvfh!d5yjMQ@1?O4MfagMxOnxUKMzHmCg=xJ>bH1P^MV?tiHStG#rv z02c=6Nvct+ezEo7ev7c8x@nro3jwL`d%hO+JwN77)x$5N-Z;hB7mYGnTPR7R*%J=z% zqv_LHv2q6&eMZ5v!2}!>h5q2=+O5Ny?1dXz8ZQ&6FfGv#&(o+6rZ(;V4Q`~P{upA~ z7Leo4x{u!_+F2K@=66=jQlr*BVd9Dy6-RVfI)aoi7`2iA@DhxkI@l1sPLyK5X`Sp9 zhF_2S*XaKE(A2wx4p*C5q2DQo6gZ-bOa0N`2kJiJW6HW2lQxNPYPiNccefL}FY+L%?UqQW6 zW6TQ1Y~HJRdCJIn@9^aK6jIR?>Lbxw(5FDQ-|HRpV7x~cy9dW-Jx`~|b)WA;Bk`B3 zq1C*WiG<&CwK6lNr)iL@ckBOfb?IS3<3CLlEXLozr(X0BxvglRj}+wpMQifU5}H?` zMoXI^LGS@WAag>RMO4y9wGl1>U3X>$0zDJUaCBuWq*30G-*uXEF%2R zkb*$$KURZUEd>2~Chp}{<9}B{@ zQFhD!g=gn)d2;^qY%&ix!2UOyOO{@R3rAyp`>f7_WH1M3FLbQ7(P26^MaS9r03Z$x z9H%)<zf#=tz z%=0=+7xU31F^L%{P zPY*A5@2=kDuie*z?kv8j0KsG&+dgIYK#KXnc~14U_GVO_bu5Ij(Qj8KnI( zjVuI1@`WRkhV<;DFjRQEZ(uDw2%~^?0`B{LxdNdn(SnEYK)NU=s5U2MpBR}`F2>WzE{E~p#0;u>jkFzAGl6W*IYof`q_aL#GdYq;s$mB`Xm(-2 zA;;5>S2~`<1w~_1JmsfXiz~Ia;U5!3bve3L%$>3ZU?@F=f5F}ZhuXRIEId3p+Bxi9 zobCUmhvQM~CYj~E-JtFj5Hy~(Ozo<>9BH#Rrkr0NRxSJCM~Jm@CA9VDY9*e}p&Ge< zu*kdz@|R8g>C=|&$K=Pvu7288e`8Ph!FvC4pyZzGo6+Cik8daG^zXB5zW8wW@%|^u z)w#a&YIm>q`pw(@KYep>cyxU7U#Dm1@BaMlci;bo8&u<3z0qv7JKc3{%^Fprzxfdy z9KGT50ySebW_ZImsQzg5IB&h7kz$*r(ROt!8hy>q)%02Ux$~=nQdVug`byjx@te_) z6juNz*J!dx?8Q9BhnQCCsD==cV9U?WF3{(u#4#4PN;nF)WRtOgT5acBG9pYXdWx>K zngEqBWsY#nsbW z$cIphn`*w$;D^8c$ZZ6w<0c|gt*XH&Z6(zjLJnX#%S>5OspL>xSwsCpiI<2PmN(*Z z^rQ4@umI@_OR*WH%^0gYOqlKMVQon7tKXc=eVWE+I0|41V2Ai2#7lnEXF-tK#l?b> z<29gC2+&5oTCsgO%cqy#zKljMtB}9gj%~CNt3C1MU;p~0dbzPt{+XAw#o(c{MWz!Zzbp@xA?D!(}*1((pmp?1pXw_rgm!i;XwSMUc-mG zV5~WL1*M}#>Zj8LtxQVAuE!BKm7#FlMn=Q&qp}Q{Go!(Vp%ImrZZ;8yvyy^=*hzg> zDgdR@FTFpWoMGa(J*9F~qW9-o2%-1q_fsVjM(^23gU^gI{e_;xmKR)s^{68;n? zuM{8K?a!gb87O~xar4u_E1z_Ff6~te{V`R9KTmf{JcWv(Dih|Ux)6LJ|5ninB+D#) zQ4(zJtN6#VV4RgG$1Mc}^=>e|my{Oh#^ae^zW7qV6Fd?X5Yy6f2j|SUT;x;42VwCF zd}PcyxRGagkWRq#)svw#lOf1uK_yYl~z~Z7dZp-xjibz^+g+R zC?$%yA%S=^t*qZeig8X4Mv1I2wHT#Hncu*7I#=bslEsvsUxBnK2AGE9=1uY9JjwK< zbyU~)h4ZU`zl(Fndr`bWv#RzVakMOqpx1|w4`HdARx3XVCN zFe)z{l>Av#{I8#xb93$l;Q}-#2A7tsAKfBg9o>Rqe`;p$gZUYGnhtl%htFCBJ}N@ol9MvtOKx3|e~q)y=Ry&ib(vWKFP+=yCpqr}!! zC;7(1u9&!p!8$rua5#Xt5z1WyZ9L{02>HQVv@7CpZk`H`#7w=dwHf*|$jM7a^4Dj( z24TjAU37cGjq!d#Sl)%vKM$_#8{9o3x9h^=T>s`XjO1T`dL&*%_#-6Ng!0drx4y6Q zXQEl`asg@E6#F>!;9!Cf%5!>oKTk5sRF7%J*dlzj0PZ48w)@Au(^E<;a*tJxqU)55 zu6MIk@hJZ+fPs~yI~xZ1KAYl^3l00X^WgRFbvj4M+l$bZ!ywAFWjx?l^_kkAFa>kt zN_{~;wteqt&yaniw2t0BCJLsl{u?^?p{8z1g^R8rD69=aE^KPo12w4L!CuOvPzOF` zccM4j+iDD9V=64E!$sWJINOlk#nH9j9-r<#9AUiGan3wXGe7Ih4GV|YwYXyi7L|0P zx&q%qBb=pkCzL}^w}b;L|LU`5Ht-lCSuy7#27yR$`2$>-?aUARv-haWm0qchgWI)? zxFIyzr_aiOEy+{}TdMJv>B0d|*qxGu=`x#NnTQPcpnBDkeGtpg4218^a_l2DH%FNF zV1`*ZIqM^39U5@bNxsd=u?LEMl>C8=RS)G7caUdH6W?Qbg*M>b&dKCd($LTsCcr<+ zFO4_?tFW<6{j*R6ru%KB5TgwLtc)x812*{4cyNZ85Be7V66S-_5>6sW7q8zP96U6T znM0s8DV-EQ(G%4bN&EkhZB_SE;4gw zmX{lg%l&w*bNr9ii(x4Q!m<${*112)Kx9fB2ky?{xaw z(WFSRK1-7K4zo;P8K+v9kjq$xS%uj*bu73Q(M;b2vhsxG%UF`q$V4wIIgU9NpT!gA__ge7UW=bi>2Ut?z6xfz*Vh zky-1n;-YSsbZpFhg)D|#wy;3_>^&6n1dk1m$-GwL#TgVS)MIg@+XUADXaGwAdNd5f zGL|7yngl|E6l?bRt!tcqAQvufU3NbZiH@mg7N)1ZrF6u;!_PY`wLoQO`{T@YCgQxt z)|DWcKrRmLD+Fl8tFVNGjaEoU>dW3_czk8`uJU6voMqI?VgL&~1;;mGM!Faq66WK-cl_G< z-2396MOJ&J_PH#=1$0Dygt|HrT1`Xw(s15+(t0*Up)c=om-9ngc>oY|2bVAtSpxoG zpB2UX3ceHZI20+dgILBA>%+u;lF|iX8EO1MBbS;0XT>vQaw91gTbrSlN+m>M*}nh! z>w2xMR2--OUrM=e3MhAK&qtx+ zO_&Fc3VnS$njD>1;GfzzV7^m7e0Q=b0A2OLnWRKeuBb(~iC=U(75?O~r)64Qo0^Me z&NyjldI^O>&^P`?d#KBZ5E9S4_LbW2?-M>{9`T+4~C%@kB6fswZn-hN`m zVqM@uXTMXQMOb(b5+GzG;ZDAsbLm64NSzpT;Fz9wJI~czqG*TOkk9ShbIjMi!KNCk z_Uyh%sRo;Xr4WSXRY3Fe+BeU?I{|4%S2}VETB6NV;S&T*J-@#C$8vJ{7Ztp7S8*%q~eD>$w>Dm7A z(f-lv<0ykmN50HLM~~s1YM{g-wZ7;)L;IB_3v9yYjoKsJPEFto`Nj-WLp)I|L=oKW z{&0I+b$)Sjuyg+U`1BBnyxpw^25Xa;P~uECh%{aqRGx`V0^~dc`|Wm!BI>=p4CAO8DAAE z)#!uLt-z}ts#4=EF?55WAiA$oS?55sy7bFL}fha2_LwW%aPp$)nW7o%0zWM>ut)q1(A43o1`EUAbm(Enx`XGj*X zYl!SHsgCu^P?!n3@F$a@sjtI{J*a*fRcIZ(PiVDJlSAHfg;l|^z7>@tMK=z*+~le_ zrr4@g*-S|#jKR4CWtr4!Jt|X4ZH68{zPeOvJ@Qg`I;2DYwo2CLT zwU-^K31c`6!bV1F@YMD$wB^liyIES)qTfkT?Y5x2TWYE!>2 z2Ji2=>T{~qD^s)=hqmb<$CjWf#13f2c$3UEA8_hASO# z`)gZg8fu4H6tfv4OK$rU#e1>-Hm-rV2Z!BRf{Fn!PF;ZM%I+Ckzuu0rV$L(;#*Kw_niHsxpp@mD zlDRsJL-Cp0DV3k*N>8_=Aw-h_pj*`dMGw{MRHKV)boXc1m^A>|?uhJZ&J`h{PK1X! zXDYh3Dh}i@Wa!i5$Uymq$6|(CS*Vuz)FRV6jqLI>n{hCX1+rqx`ZQx@fBxiJbxuHbl3s`hK zi}kTcM46?F*#N^8-^@`}3YIOJ~!* z(`SaP@Y`Xk4X_f*xy#73B#BX7hHCIa&mkg=V+43Z_OyW$owCNy(>n;~L>ZMvvRngK;-=n!qNr5;Sgls^-Y41+ zkW4oFWnbzWquiHL))RTosmi-^Y>0yE(fVk(Zqkwg;hE~~`(9pY%NTi^o65Vx#UQa2 z3M0dngJ29Jb)nGdm1G<`Y->BZ6`MlN7t%lL)w{FrrNag1_@*%1@#qpG4`CQw>4L*{ zmE?QPW7JHebnyDDj6$9IfkisxbcWIyjiC7OO!^`T1%D+%d-I-Q$krc}=VPUhuPLTu z-2(7}U&N)``!VMO?Y`>8u*dSLbRpL5KZ#4qoaxsLjN$#`A6~Ed+BH{5JY%kxLzBqDhaOx$KWuY5j` z`Wx=w+ssYNe-I4)D~%fVE>Zn#Y-n$t1n9*mnryUl88zN4#OSc&cyOPMlVnpJbiIjkb5=_VJ(mk2 zcpkD&Uya|}rSiASs&(+cELcuwPmWFOP-x#5G6umrTx(B$(^=opf=$Pa*yb>STf;|h zMRM&5Y{n)%D7u0BXKd2qTRpyoV~`KI&^vuy(Do$F4#AgmTi)Olw=LLHg#-EfE>}TX z#duC$0ZE^Nbm!bOmOtC}LiFD4Pv-R+B;o3h&qqp4)1EGfHlxOqzL6t7{H@?Up4hr ztMglNo=*X#14TL3JXpDyh@{Tx%r!)jaPL&4Ss~x|{|zL3Yq|NAMSKt{6dy17Ph(&d zcG=Z~^3!GPZ%_XtWB+m)d*fd!WPkl|A$yr%{jU&%i?oGeDfbtO&N&HE^Z!*)l_X*Z znwKXnaeNX}bLRR$X?5A?gVJyHw~%RV3W9%)O#AgOk!hbU$Nop^{5Oy~ovryO;mf5l zU|)`Eswl2lJlo#RWy^Syr2JS}`Jn=9kXQ7trufBCIzMpG_37V9%>5@aBO~V0a8WRX z>c$g4=-#g@X`}I#RI2YUL}tl=McumFaGJ~i!BQ?Kv3OXvYG39Gx_A`{!ZOdJ6|z3t zu0}(fj$x1LHWsvO}DbIVjbgweLY6RetZOllzJa7^FCbS%`fj$r2azv_z42qV}!F+ zLe8Vftt+K^=!J=7NH>e^R7TwRR@BXvfBP=4~&V8A*U62+eIJx z3H?kn9yqffI~TCWs_$lyCkY|m z_TQ6hnszTF2#blG!7$3E{ej8Vta<~H(hP-$9L>Q|RZa6wjp?3%U``AL87Fkw$1_@u zX@X8~Nd=r()pFiuks8fNy+dDJ2YG8IpO-qy$5aN7TsJeQM4$$xhfx6s*aZ-hj7@;E(Ht*gz#ws-l!0`%3_Jmu!*S%6gyTV?}lc9 zAn_Ub6Af*8+OzYr39tgvo{pF~fHP;Q1b<)5pOr+58$ekhfV5d@MhQo27r z2}$_?BL|=`?K@jA!HKKqbm+ccV>1t8qAdR zGe{@HtW?V~AVjXZ7;)W|g9C zjnQce>_~k;yNRq+2*9&c*&$(~loB<1)~uGF*UR~{?TkWDbeewQOgO)x1Y_z@y_uzx z(NBGfuztQK!d6BT6pFbbECp*Z;lNT}oWF%sPG>gOWlCT#ZsD^FwfOw`3AMa9e0Sda z?qdIF|9pSvVE->YC*o2-|F&Ms1K&MWpY84(C=V4~i-xrD| zIbR)nsYjR6c@@)2h0H5IFDEjWy3pS91^!%q3>i_N*1kGTwSdS5=g;`5xvT7x<2P&J zZW`Bp7&gh7`x7=Ql*l9kH=st@-8b@sCcCo)CBM=a18WO4hj(zm%#FmR=49CaWI_k51ESJE}!x;AQ+JM88 z??=hloN#j5b{w@W)0%Q)yE|CT+WFmJ)k5&}{=*Xodkn^fQi zZAtk|vq-WV7=9VUvFgyd+>k#@Gh!IPDu(Osg~jC2y8*}ZOX)`;^5bZ}6pw*Z=^V~4 z@XZFQ`v5U)RD;nZx?3n&RzI}DM_=b=;=)Z-l1MbAN-+?T!&-ugUqbbUR^pHn;+9P; zKu#q?Gcyzif}A20NpLkw5{e}N&P%XC;vdaf|C^-9DAXwqxii>4EvwRa)h3-{5T}fY zoXJ`jV}wbHO2y^_%+CGg^Dhm{!miGgtcuCdm81xtR_q6rh!bv+h$PqyrQrv`vZ*Ab zAGemm(|N#A+Sf_2L3S-yqV?zNvcsS&r8@{K(;)b;g^f{hl+NE}WI+(f(Rtl4F9H05 zKX70>qaEw*2t-uLc~e6yYfnCnZHHPIpfT`cBdQR?L&wEg(j6y)US z8!9aYgj5(44Cz~4$rdF?`7OwWL(CQf7mI&dj7LgR*z4bG8w6Fmoz9NZI~`@MH<>*Q zVjb}Bg5%P30{A=il;gc*K#0)li`IxQ=9~!w2euu}pLbe~YIU=! zI7h9~s5U$8&1RT+ftxv)3Zknyrztj1=r(7;p{G%+v2i(?6G?!bMG-k%8}7Eo z!CuvkNq@rT1d6y;pX%y^f9g*ba6ubaqPSI!qtbTtr@g3FS3`~Kn@zP!+I+*Pn51`G zzOiEmZ&VRsN)??G51b$dN{qtt)qHb!2QK-0Y7LM8qGwT~)@^iK?OM0BS;g{n26H9& z{HqARI!N!#M}$!RLwMC=Ef7kOn4O9(4mmS>F&zimgcmVnF{y$`_q%_^pS@Rm8>G9{ zHmaNT`tvl~y!n;;s47}&H5$JI)VEtr=ih2It~YC~-^Hp?Qz5BdSI^^Gv)TAvRQ)Xw zuz)-2DEi%Pe?DKXq;U4F|pnVqM1!Bd<0e_FcQ4r-ardetQr)&VH#bh zDHSEh#DX72<4v#46<#i+Gjve_3pgB3>cuQe##i_yzocvP%>O>Sf!hTTzsL6#P7ye# zYXS_FMiV|X1Q=}R_%;8?y0AACG>td=rFnWy*<#S)Wken@{R!v~yNv4%w3p~Ck?U&H z4%W*$lL5*Amx}xM2Xrrjxq!y^n5kz9*Gw2mj%-+`tI;9DY{xPFHxR{r2cg%h^Gk)t z=;Zip|2ww7a5-8E&e!t51k)~Q8}Ql1+Y1v>>^@~7;B7LVLjBttb;P_-;zr5|2}bBw z&(1&4{o9l0@4lm|DjRzj`$xM6@Ai5ZIG&5M<9DaKJ)ykucQZ`SiM3Tss171=|>g~uqy5{tkP#naGG0ZspB(DfkX~YIX5Ouwlp#= z;o?u{U76!pd5D(@IZT=0`GdSi6qh#k3;fvd3#zhOMZf=E-71}e&$9XaVqdKPT zq2xK%*u#7M`0UFpLdPl0#^6@?6*Y(Zd}lpO#>pHl@*}GBq-bfblLe5d2y1tVmLE8D zhePU5;Q3UCx+whC_@n4`cAwj#ID5Htr!y}3y|K{K3mLaY(_&BmTzZEgGZo<@AJ zoYP2p^jC~?)PuhV>J->@!|f_8?Y+-&tDy%9_$?L z?G}!_8XkGPYUG%eE+)PAJSV`Qs`tbUZ_LzYb7H+2bW@{X}y6` z7=47jXN!qCnuqW(iU1VMjGb3`81#>*0nX2VE_QU)nWZ5?A!o9~yhS+U;g=clERcXE zaM-&(vtzE+reJ}8>sAgFIRXbkfEDR#xD~K_KG!*gf<^BzUY*?D0^fnWFuKy+!QnMX zFcpzVWFr7!hV8Au0A72Y>jdjwrtVK$mh6Is>y?s;WcVNt4NIT;j!5wce06bnhMUaW z9l>VRYM!ix_3U#)Pb_L9mC1*Y74PX(_Es?}B}v@`R_CqQR2TxR1$12M73&L0K3_z1 zF$d1FU#s6_Lb;dfcbm=4u8w5RhiAJNf9{6CJ|KbeE*N;%ivrQXA;T}r2Tj?EeYb( z$)c8nP!cJ?$}5@66R3|ljH#ly735U1){1wRV3-_ys?Lp}iY5}xA~ zYG}H$va$b8RJwddWiFrD+I3rnRqvk3l6Qq)h{{jTys}SQMTJFjvvW%x7&veP86X6a z!v2|;zkX|3BDZIu$u4>C#LwlB>Ux^{uN`O4trhoe@Ntm?7^cqND)gJ-*AH^5fNsdwtJ2fx|NW5Fr(Uc5=lmM<&;8Fo_5R1) z`*7-3)WvKy+p)u~fkmk7;!B(bwc1>Z-aK`Y*vV zQv(k|Nl4e9;o+Lyq$y$`ijE+l4a#z`|BwwiJ#r}M-%#y{C~9I+dEgH z@SEOg>AN!dSeS<7`X;|qZOn(e2dBj!!ZY{Ns`(JBn#K5)4oBv%Z2NL_HC1?+UzL=C zm&|4r(J@y=`>yhR`4Qi%)-HrPK&bqs{0IoDwKnSououKke%7IRghyty58-bnI1xHl zQIr}+6JXTWXo5RS*Kg3?X&8K{$RWuri#IOE5WE>#gShB|V+7chMv31g5k2=u z@`C`+(Xj``0I)jtO)^G%=53L#q~0}v#4?DItrl~i7bhRepDwVs1i^N zSQH*Xw@~avI}nJh7q~dGDuf9iCaFY6O=ARcZVPiI5+x&rSHTXrtf@f`Rtr@eNhM#A z=%rrRszHcI(~ZCviY~b==B2P6W$-x)`+D!}@Rl!w@uN!BH z4oTBohT6~=h_TyIV3tpWNZ{Bn1IvZcY9UlZb?E1Ub2L}|6lzZ5<2{TON(A){p2qQ0NhwY=(+3wL3VbGr zdunHEJtw4YGck<>0Og$a(PA@d7EeuwquKmE zx*GSdN%xskRoW1tm_^in=N18!9f&@)dLON;OaP(x_tN>}ZuhPraIp0E)|&I|XUv3x zk~#^aTSZrpw3)y)3t6YxjS53>sgsdy{p5P06gBnNR`A#qu=L#n-6m>a3*RXb^nD>d$f4 zZ%%q2m7rli9jA&}dEX`ip!)jL)|&MZxdn594G|hmKBVupU=Qc$z$t@>=LaAt_IC@mPf$Fw^3OeV9M19D}9eL~I&D*`xi}T})y`A%&(n(o~v3S?;tX%p+ z{R$CpRu6|Z&=x-`?Lp%&N+leDYQI-5|FEIj=VAB0QyM$~*Ra)BbWveD`N5|X1xR~f ztL42MU9;>$`CD#)!(tv5r$`hzIa@&w>61#%Nv`hIkve$;tNS*pRT~}CDRj`6AIWd% z?1Vv-PL2?1>Yp!42GmAeE?eqD4;@#t!~(VK^WvK&Y+%$TC8eMP5f8YZMMNZ|-cg$E zmVaXKC3DWuKzoY64)Ry;YsZKxKQ?!oTREn{E;m?G%=8WfD1kBmV;2KRt@yXAybsB1 zKaU_5HVeU&&<4}Txd|0#_B?OP=U?FC?{?+LW#=`zTWJ!lOO zHM)6d7{FV(9=JgY#3tf+AlL%Gyg=Qi#BLLGi3-pElmjW?8Bsh0gJqVYBg;pOcd)vr zX}zX8$QHMdt03>j@n4I6Hrn7UO%xZ{M@M9?vwBa9r@nWwbrcw#GcrY`>1?=C5W$(^ z$rB`jogo*#y9Gsxt0}6Hxw@u3RPk=N^z7qaLR&hWm6;!67Uo?n`7E=~qQtG^?}faD z;{twAARVQ1xX&`P_1NKR$0Ilx6Cl;}2KNs}NJr@&+rv-;U5UNUrS%r|+Uv5ylm2&JNP?^ksZk=x&~mtV*cw+B6XDCTiK8f&*JG zKQ-UmGq~L_>_ri~1hqeTmnB7xqwFLPp1l&D{C;OKPg8$5>U+!?3k^)~xX<8{!yivF zG;(@cAf>~pm!hQ`uTx4^+NY((+*jA)D zNJCmBvPLrnN*KvBsAM)f>}T(Td-s^GPBLJ*YA{N09^wc&5-SgafF8upLPM6kii8NVg{0)Uh|IPWXFLVP!NZaJ)-U?AVBm7epE6aAiH2x3R0@!KLd(@AUNI^}B-u zGO2&8#yA!(^bJJT#~k*-?+$y1k^ZiR-`#R1p{1W06TbSafuAAA(CE`{6w_HcPY3BZ z3}pBC^z_}yIRfdB4X z#51M6%tjxQKSoYSu6sIz4HWXG(*k-zrE|+nDRxbj`2nQM1D6kSPm*~sbkG?(1`D`U zmm3z@!sE=U=m=DY2vHEzCnji&8b$Srt`dxJocwvL8iV_a7NxVGg;sTZO5fWbx7PA+ ze_m~54Ov;Oa@hxW^1LyC<5iCJ-2$6_W_-871}D2={^V$zsK11+cW(RFqd~;pC1mH< zMiaZqP61y`|LP0p#vi<}jW)YXd96zJI3s<|&p^j@<%2KtBW@U`; zjN)wWwV*AER*ZTLQ>1{A=NgQ`OlqKdY$)s#`_PpnbU-p(K__>TY6zeO16I`0^#+)m z`V-Y$u}&-j&EqgxbFp-WdQNaE7$1FSlPyDyIp%8UUvDC#jX}w^s6c#Ug11}(xeh?Ubj3Zf2RdM%*{8YdvY5gdY_E%^}QbF z*9KlWq1@!Q1_;Y3$Q~f=5#H2r*o@gz0LU4~0IQDxzXkqrnWcCVN(5A_^abY??Id=I z;8g6KEfsc0e9S4z zn}aXf1g}5Q!2%fwN3^320M8#5+2Ej?&PKO=yYxiWKwI~4Wz%1b{nYYWopOw%k}jGg@jynX))aeKN1 zx633TFDJhMks5w2sZU;R*UQgp&-l%vUK2NT8otswCHUOIRSehxtG%bl#oNYZQWYpj z;PjrHq-M#Bg0<%o0C-;psWsH8e!(u|oXyiDVjd0Mb|tNpyIHAiiAa%?`mjp4oQw;~%P>kK`8dhv8o*>n7RfbmJxH7!^uA?_Qct z%N2MJUtx33mZ^sL)mN;xoTayk+Vm7N034tnT`E??+bm_f=O?=rAYaJQ>tl2WcX9Gv z+21y{t+!!LQ3&^x1{?TLR66f$u5YCH6XP$*&cLw4o=s1Y6P|h{6~G{d$0bb{QVoG$ z80KbJ(}h*Ybqxb^G+wS#yedkqqw0Rn1j;+K2GGsq56 z{R4lC)o*c2|5j7Kb>J8EbNxr1))*(NzUFC)B19%rETu`!5vcK@DC+yVL1h%@CEi+Yp3DR+Kqzh(c&_2#`Z~8Vnu$6sb1BP!^rQ4bp<4u|Z1-bPU(= z#K$wsv3*eAvGG<7rpOg^jN@ZM_K8=CD@3|sDguIZ&+o5oDF9x4H~1Kd`vb_+4U-ES zDGf+YJ%9NU2<{7zBCodSU2NY0`8n@u_Fcz&RfkvVjd)r(BG?2lo(B;ryN9qKLTZ`4 z(8s)0TCLHM8kn#Uv`tG3>@&pFJ+ zG4Op}eO~d3v5Qk!I0t;^>EKy^K*&~@{-RWJUOvm6m*pP_&}zz&tVz;}O@O_OWR?@n zQnD!`oKHX*o<|m%;6`&}jw4UijhAeUXIhznay?6@5Pc}}I%80(w-4#WSD(YnlH>o1 zc%d`Hum5Hvwrtm5_~!VsUpwyP^!WUE_xRu;5YURAgRpAj@9#re6H^i%FgHfwCIEa4-dF{O>Whe)!W?&PNtoa#F38mKnn%-RbB@FN|nFrLzVg7o)Be;ysnfpo}z53|K2I()bLHoEF(^F;VZ zskY$5Oo6A#OqacZ0fFO-W^E5ipft=@a%-)&*bjp>|~6)&*kSwz3X^rnxEg!?hvh zL-#`kNuPFZU-(XZM%_x_=3_ZCuD6myAkpjv5Nk0ONpmW|lfj`KK2I-?q|kKLXaQR5$QrvDE`~s5BD|@{e(vzF$n;L#bk~ z{AhFX2ZE&OGF-ULV&fl0392b>Khm>5+r}F`y_*0IV-I62+&UD~tzcz%$59j`Sy=Mc z?ri99rkN#kLA>rr=9!3P6Uh!{Cd35|h$Aw5qveo)#$YMbN6>o+?$V$vwin))F-Jsq zF1+x*QkD;AjBly|bcRN&@#w}!ha$UANf`O8AhoOD>lsrLl z@4%-d_i)G7hvABx4(&OWlI067n9PsRtun;lkr-ZX=b{Xq@6lI>pi;0#WXH`2zEym2Cu?ym9+nX z>LaETlZ~E4D1fblFil=Luv&baLbB%%iPiYS%E4lSs6s+2QV_PBjU6QDuk-XAsFE5L zN|1uWC2Z{p>h2Dmz043kxayk|)%#Kuu$GVoA+G@bw;XKwtuY>Z`RjCB9UoE7@i2R& z8UMS;>qxvY{jB1pl5d*QP%H`Lfbkm&@ARLV_)xd@Ur4TEexjWmxu&~*ZvBFd9Q-L{ zr#uL8v%H1UlZ`z#r~Oks8Swcto4^}2iW|71#sbrQljQ(2;`gIhy*K+u74n3DM3R|_ zoyAHxpo>8|Yv(K2^}EN1hx_N~KSlTAeB@_|+R19$;r-fTGWw|D;D%-QwF+0TK-Pq( zGPs9qQq$+lW^5VzrvmkJH@%%M<|M()bRj@Bf~N|h zRP7scINj=*qh9DZ66o*?_JnW+%x@EN!%*y0aok}lM#*j&lFyUhkntNpag*JL=4l#b z5VkG249A>AUy-AlT>yL~)_^ZjxLB-f0LUE| zeE;WKtnn7&3S_~PasQrER#B9paTN*qiCG^6?{3&!OrjwVOa`}bwJk2V@hHU$PHTT& zaHV-UaDA(z&eHpYVg$p-&6G!ep$3iVApB*}=HkDB5!GIT6rV=?(5%wat52kxFEU>lOgI>gGQ#ISUYCUAnhq}(RVR1Kq5JZ%9dVDfR0Oy|adSqm01b8WKT4!ODX z1wwVj=EwK+EDfhWm}5>zA%r*vE}i%Rg}rOCxnSvT=R(-Kwo$tKL-1qNZ!i3tzE?`P z(N{6DQd-nJdA2~Br6_rG{)Yys=TwR6ilM5+-(CvGvt$HZA5JS8BI)% zhJ@+?sr9FHJ38@$+HJ!8?+6g~s79#>v;Vw^Z0=F@SBLKPs78$fb!?N`xvoRCdh`J! zu``{%-sTGHU#1@tSB411d!r7`0tE^V#y^t&@HZr@aGf9BCnlRoCYyHT4H|jgS;JDi zTji5Z2^m;nyLLUi^rgG;sZ&3|bsha-ePF<%G~dc_k#r{*)dXKU!HQTkH ztTQC-wuXAjHC%@mMujBl|XsLiN6qASSR=BB5sxc+CLz=OPFKPwSJ~WjCL{KnS;M}IG)v)#T zKHaG4fB|0Ujk*GCg@4@ND@x_(m7u0{`h11k4@GB+8=vi=nq={cPjp)6a# z2EdV+Y=$n57=c5JEKV8x6IAij6H@9j=G|3LU#Hej4~7Y@LauKzt}no5E;$LLmSgWF z*-SE1n2$(Gh|O%-M?Gd-t=zCR!!lq|AvH|k(}A`HEBp;jU$iB=uT+NiC{HW!*7n^Oj? z53$bTKR@oi}cQ^Os%m9An8K!qbM9BP{I<}eI=516N`Me7nl17ox-GQ-A-6iAk z1^}T!d6~NtFUnY6eA(?u=@mJM$<(~edw-w{SEgfTJ%16MD#`T?p~a<4(j;n(sO}c{ zwq_MQME4GnKFF*lx!kPcTT`HgwZ3A-i=R#Qmh7iLElCBF$Mb~G$K}aeoSYx0ZYXOm zDaxoI>A*pnPRTi3$8@53?)D?X zs!+|Vw5D!~+wu!VG(}b^(qpev%;i2bG`S^=2K!0qKJAeSb>*`(FW4NTw14@b0NCpugn4qLMzu0qF$7_zx+ zPW+y=2AB!>&Q6%~Z4wM6si8kH=%>0Ql+gIuDh>fZbpEqB3mJv+d=iE&wLsC=+L%aW zTK>uj(s;;1p|u+Q5e=fet%2IDl~Fqb|MC1S;NqmQ!Gn zS7PCmIlq2#JGh;ebdPRyT5bfwYG@*ne2bpBf?5f`_7wQFhr^Gb0zdYy(4L6bRrbyz zqE$*)T}BaE^CU15y$hTyIdmwm;3fR9ae-?)#iF8gLzhj4*^HEw zY~Vms6q4a%kVW24IFY31D~;YcDTTUI>~5x1NiiZ+Bw*;!`83TaDYO~qkpineHsEa% z>C4eI1lR~btY2b)sZv*|TbvXpZ{)Vm`G?>d(kd3)q}|O5%k-@L1&9T{g}MOx!{C0A zyKZ|Rcz6$^QN(UlkAM8b6NxNgp#;1gm4F;K{204>x%}J>i>sG|*Wyc|)N)X23`HN{ z@cA>p$yYfr+uH!&y-Z(?NsyqPbbjXr44aeCyY81SP-4qV7p8!lV>9>dG1>tC3kIEY zbplxMl8(7uyql1D#xs=B0%x6@mfK53&HD&^Ge+A=JRN;avhnDvujHXrbO)-%b$7A& z=2Mb-VCp#!3AnDYFQb5izungng%1X9cdWy>RoMzMFal$ws#25>jwAuj44ux6MyoH4 z#~|EmHgwy!C`j9pi!;K!>#%;A8XC6+?dFj&#%%Fm7)rJP?KdxFmhw^}Os7ize zC06I;2_hqp$_kdRlig@467fp<4ljgCtw2f;eH{Ym%nefshYeilD;l8tHk zEN4rwN9@e?An7iUb}=XD1*{tKcC8SOxh=_9j3YobytM<{3goWT7l_#i{k-SoNeX*g z7kt3W5cLwP4{9*y8$P1hD@uO8H zm&M%Aj&5RgAwlY$Ta(HAny=jZkm3yP@yrD<_Jpa_t#j`t->mU-Ok8}8q5kB6PWh=# zsV6L5OVzRX&E@?RRwdK5=g?;D)NC(1#c$P7l|{F3PtEbb=&H%U(h22}qf2_!<|teR zidRq_;K8h)-C(Ih>mCR(@Rz{ym=lU?{YpUWy5)ol(KxxH@HV`Jr-XkPCP$G+P#198 zAI8Xv`qJ85jewuB2(KTQYgUo(>>n>s${pJJo&U$g~a4vM){GG|V_RO!JZaMntz8-+z%@+^-x0jthOPmp7z* zWyfcFanZSd<{xX9_jF0D&o#SQFt>TB%psFp$4L7>_}M^By-@2BKTbXzARQ0L^ar{`Dqbuwn9$_-W#f0wA zD>)d%!Cz6~rbFT&nK)KvCEc*TGU$bugBA26gA~)!M~S>f=XVKvI?V6#HGpyBl*#)5 zoO`QV)TP_PE#ydoSjEvW$#PJjuNnHQ8Nu0H&B8q? zS3xw+7rdl7IGpP23fG^q$c89DdlgEbLd;L7COjLlXAF4AX6ayrm&H1(bH==%)EmVa zwzuO7Z`18sMLTx@!EDzz3y%l5uASdsAgc+T5cmSwY>rdYJMg0xR&{wW7_E;BL8x!| zlRD^BpM}18+)-k9J1S&;p@q$e(-~3DDO>1?oi5Z``~>x%06+Gl#}X1` zf1xP6uel#NY|+MYi%wY9f+CR)5q69ik~qMX2|$!Y`7N2_&4fBpZo-b6+-;cttg`}c zY`Br9=e*j0?-GJ73prJ{f(7mAs?sIy9c1&E3~ro7LBW5CiA+2hxhTWUF1lPOO2Kre zqKvxQD$~WhAY%lVF@rRKM2DLu?JBv)BTIlrL(=YmOJH=DDJp9{z`%A0^`4D) zMrCrXm`ck)MW-=9h_jkuqyz?Qo6@QPW(?FiWnnp3Ra#pxv8uH2UUQ0-U}g+tmVFM1 z9N%xi%b`zDBa^>e^BVMUWZ$j`vs1q|bd5Fh>#jemOCWfluAkQh-c(f125 zA2f4_Oa#t2P0CIQa(CzG{P?7IWK2s$h%l%5ObtH(!q5(NbV!9>w2zOr-A7+(SkLO< z@Wbf=tgs^dl)U^52K$eiiG!T8-Z`4fPvw=9$=o0om8*=hG3$r;N2j5!R=I8MU6#Um zf?s)G*<=h~NvxSfON;G;|l}33np3z49<7eAnKL3&} zfSR`8i*nHiHZ!w3q(AAarNHQyEhfYH!Uv?W^y31xg?86K4FD= zBdXf173UYpUv79WWLBLO33&7sObGU$LNAX?dba@3yjYNbsK)S=J9%ke8Ef8z4c+qzok({ezGgVP@C`H*lUJD(+UHYe$N zo^B~^PDBkdE=Z9Tzp=@)MClq>|M#=3JM~Lu30g0spORUs>lImm15QQEHIc!Matz+q zi>YI`;Hy8bH<(;wiXsxB5-UV`sVTgH!=z~NRQQN1ihRQo$Gm@{9R(HIz)wl8onG6G(XbnIH#y$*1!OJMKVE>In^Q zLbn}H&5|L}EIRuIE)ayc2c?s;q#|!eLMD&1o5g&X-c3An2E^$ZMHcgxf2QG~Aq;F-9o3fs!ek=oRt<}#Y;af7a^rlQkNiXvU4 z;o_t%=fdNMtf+i)X(JGqm;!ie*>IRTvQ5O{QNUY44oZKc(5djy43wD~*Wkuu8hYt5 zkk?OO_af4l(5q51O5LO&C1WUCT0WIx&?DC!p3ZLOk8WwtIf#63Wr3LD!x)NWVgho` z!T;n`o&_2Bcq$J;AQ)j3jdIyAygv_^ag8hT@fpXI2_9&qO`HZ^KNRKmb5wWL@{{%@ z**!STE0(eo^XX^XIo;AvB@9#Ja^(|>@SPg#n1{;HxWY{e(-P)YId6GHtMUrLR)|5e z44#g^raZ&8v;k~$Jm>s#i@qyy-E@pp8h*E~ELEm>lMThf2sM+?pXcRh~Ej_f_cx z64sa0KgNCej~C+Q3q(!Xy#MN}vXiq{w9V)3cATQiB3q)Fa`Ale@`dNJsVS0yZg0B@ zwWTg*9DJM%&zemDg=ya9C3QABWBF$%oil#o`bQTifm6u{-PGiGY`Zx#&2!OD!B`y! z^}q;XNwsQCslH1#@u( zx^$KZv-9)f=!1f$k#aRT)=KC+)4B1mE+%R`o2wN50##$HpqLIP=k!>Ib|a#ls@>ae zAxv2$-~*~b2OVy}u8(d3fIZLY~!`?!q`?nO{8glU}83yFm*QfzS6>z%)qc3Zc>zAsW2Ip1@e5&dUk=a z?q)bU`w4O)!ry;8`^m9vX=Jw4))i z!C+<>)K@r@?QI1u67g(YXwt%V$NF-+E+g)qKa+k(GQp8|kW%6;;>I~_LzIv+pPW0D z=#qmR}rm zDZ2lm1a-;BGzmF6f>1H@KPNMiTl^;TME6k&;MN3#v90Yqqp=Yy_FWROj>uS{<+j{mj;-I`l0rLK zc1>&j@H|&piyCu8z3T!QO6kn7ACS{|MM_|tb|n%3D^ZI-)RFLK=f|f#69;cwhP;&m zS);=}{#t{ruE-niVAf_&#znA;gcRxBi-Z*BUATl8%$ZUNDCgtHlBe_pw*klBn9>xU ztLO~}Od@Mwv(t`=J?_sqYae!(VBYKrhZ9i=drHJbIj{@skzFVA3$-aOa9Bw5*%Fbz z!rK7Jm=RPprLKHVr2fA>&G8`IA%>6*GuJ5AC^tuvUI*78uPvO^)W+mc#UpKPVQpzg zls`)SD`@b8y@X^*GA|`L&}u^<*HKckx7EFDJ*6xf&eG{rejaq5wW9&7Q~pCb4mgxk z8;Y;d4R%J^jH=ccA;UcM&?#-w%w|5CK@GGF2x5xPqj*S7Qns()you=gLtWKCS0&Nc zU$iyO$&X;$OyU0*D3V9d=XPQD?OzI zrJP=zw3WW9xSeAaZ%(O8IcWN*Rjc-xz($>qW^9;L6yz9vby@Yxk$GjtHcSmcv7Dnh zt%7T{GYrp89Q#XffuuLC?77}e0vAXyj=K#XXEl7&0*uVh7kp^lo zNQoS*9u@nvn8#T4ksoSO4V2-trG5Wz$*nA0_B~;WoFAN|mNqC*a7?PVXiR6o>_h=N z5^&SWl7v!@0mr?fd06$VrP0;i@&D;zWwo?=gPseH!i|9$V9}l3>*OLpc@%ynlpHxL z;cEHC7mh8WhtTpjmO?uh1f}f*ZxF}D6$ICEHkiCjc2IPYz6_a>>m3!ijxYMm7ANEE zp?a&r;qjTYU-$*HkIs9bR|_+PH6sL+dGoShjg9YvgHbg3dC3e-J}#^c;74G+dUy7H zWUM-9Gb5v#wb!RPpcqzWKM^123S5NJWN`2gXT8CLSb)eSj7AJ|tk0P8#(EZ5wjn9j zn+ZUYv~+stnE;8b>&B$zzca-P1Po493%VLrZ*;SEc!hB`S5T~uc>wR)fQNP19<`i~ z9r#Q9N}L1@+kTW-6sjczq)|+du1j{jRq)Vt7!uv^WwY#>4ft`?I1jHO{?8jQP^v_q3%tHH>?=0>Z6kQxXAf4Ju?^q6332i15%OW?E@mIf= zUg|ja@>bp{!0}Ocy$z@kvZKnb<&EZ8FImo4JZC2Z4d^V0oqrH@% z9^#^z-#`1uYJ-KYU_$HX({8X1T3N2Iy{ejq5)_auqLWsm6{rYRIU~_(^R?Yxdwy|W z=fv_%yi}1ckM9D>^;gAv5VJV(9BQSq&$1v4K%(zfZwcym#q^l3_sR-!A*YT|ne${ePXxt)I*>&)Dae(F2bW@bso$;j{~!`x|a zT5#;lqt$!nJNUsRmlQVB)>CwbY(beT_gTVbBgn=Qjme${h6t0-yw46;wA*3tf(I8E z;GBHoI5xO{5B9A2im2*i(?i};-35kqnG~)M-HlOY^9fvK6z>S{!@vpTwGaa3CqYU| zz8y`-N&{vVw=nM&W(#5yHQA#3*$ox5DP(KQJsuz6^Y}!s$Kt!b!d$okx5vjjKIU@s zhA+*~A2bSxJxkpqLxaw{NIu?4a`m9WSF(7_OFSuk`6h=xF|_JdaCQ(&7@i%xVG!6z z!h{FQmpTkrzmc79dwmvQ?ZzA=urW%Z%+EezF;Mb{n;#2ts~Z%LVJ(D}94bNr<>dIo z)!2xQ!sQjLnA@g?w=3fI_b0+eMd`X#!>_lO<>{uQVHdJ(9-`&Blm|yj*z?XqVniZW zdLK<}gmM7#4+QwfNR2oC`s)(>`bE23E-TS#YlYiD&V5++wesr__IBS-=LM+KvCggz z25r6Xm(57ro`FYie>l9Drral{f5CtK0$6_dixp*MDXg217S}1-^Mkq4 zbmwmxyI%qn?d}N|sJm0P)>bhRN3sgB6Gwnt!E}n&o7Cc$Vo{!w>^u+G1~;ybYg`r8 z7zN^l^LgA|kD?_(kOijn!062mD8`ORBVU}?-l1a~47$n};z3RjE9(M0C{zB{np-1a zMTLMT6k}egpOCxX75g>1O3l(J<}dU&(q`{liT?2q1N!AQjO$s>uvDlkt)#fHNzgxi zpGZ7;rR!79uo$-e72EyHCVo4bYd)6?ulVHL$>j&VA_T+rX|TGpuH6*AAqKN=N>xB9 z5t5w(%K02faa!Pfg3becL0Z*WYCT&h^|R~-9J7t-L<^%U9o}N|HM(UVu~1YlS=opc zEB+Nd{OJbSIC8M%dT0ujCI(jpx8rvF?q#;DK8d-@mP{RRgGF|64ExWI*?&Oabc_2e z4tuAo;((7p(d}~XI{A@T!B4yUHJJ#WKP$eAg%DBMUIv0b#QrYrVGf|8@TAbj5iytO zWaByh=z6>+7l8?}%G?+$ydWV@6dMq-#-(_0vkiwPIcIcm`c6A!VdZO3`CZ7y2!Ldb zb{cX5s>lp!p8rkg;+BKMNL&l&P9UyY90{g95B8E(F={4&-Cf6`II^5A@Fi27c|f@u zUGb0x^Q{TGDOj7n$k+l*eZawGT$;e9A;BQ4;V@@$w4tSrS3y4NGw04JT{P{LfiJ4M zs%%chbyQ|oeid5u)-R363@R^q14A(AQrb^N`YYGjS85qWKGlUnu}l|}10!AvqT=NB z+L)}j7g^MZ8szF$c<;)~N<84!L~X&Gmr0a6zYVblgE_8VS`A@|bBez9nk6=OQaR|i z81x*~H+;^e2HtU=a5^N)=*|8TwtTa`pI_5AxgqbGWhpf@zs#kS9dQ5|W=Ig?!bG~t z(dkS4m)WN9M1d1>LIB7;>uv^#ZiAlJ;2Ci7x5CIXEAjhlgf1QCF5Y-_L=VoO;I|PD zIwC>a65T6cHSv=Gx=PXWPV`k2=Z|R%Adm!biO17Q52h7a0hgr9UG85|@x$qsSMLZU zU9eO3=Hei;y7f;)g`etCBEqDE2xb?|xtc6->saQ|u{uLs&a&@k+8Zo!`THfwjRFS0 z?Lexmd?4F)Vfou-ApukZxu6iS^SJDI`)vok{T>(_Mj@Mjj6})Q7sij})2d!*Ca0L- z7|KADyfk^XgzJ*Jt`8op|KTU6BJzqQs6A~7YT+fQ(Gmy&M03&=!-%5?1c&5@5ibn~ z{Io39)dP`B^c>6+28Pm|#XLn1I!qE?)Qyv}3CyclG$E9Othko<3KyDHG|$gLzYB^W zGpPL*vNB+Q8zDJ@HF+KOz)A@U7CH$6cmnFI_$k!zfn%R^U|V?PnR}i>f`Acg`c@vv zw-Z;*D_U~y#8u5WQ=)B#KAIC9W#%OhlTinzun=h*u1w_^QxG9jo$yB_vd9-#LlKG7 zH9)1<#oQ`28*KE!%#^oE3Z%SY(1A4%xh5PxKRGH&8Teu9pd$3*ju z7T>WnMH2_vN_6p+d8mHE>y&bDIL|p7hIR`L1d*ew2&jiMFVnp(j6~rr+BKHsPd7Z; zGYZIz9(wYY^vQeOU)M>xk%sfK(f)o?Iu=LH&Fh?@1Pe=a@1SIy%M%&QCTVzy7L;-^ zh+z@6h>!nsUGs(8wv)&ZZmVQ&a~m&vi-jm8hR!FZ(2W=Fk2_aegJHwbhG1g$qjYpB5}h=blX3Lla}g=c zc#Q2u@;ed9Q=F7h*FK{%4jK8Xt_eSMf;EcU~Nb?fc15p6X#gK(wGV6Z@F4fxgH9CBXrr=JzPp%L8Ev$$KQBt$YFEN z{Pem@A1JgmV?N38xWYVevb002@PwY>pnF4Ms@vOSh|zAcNDxMrW{b-VEEf46VdQfbbJh?JLv+MT}wm zH-1kH6B+rHEQniJOSt$@&uJg5c$mFVtaJEU|D$YdPF^Kx`4EO>X;aJTImPE_s9x^M z!O9^({`?}lUI7WNncLvd`c2Y1v4$p)GjO8O`sO37oKj*sFPFT%kli|kdzYQ~l0AKv z--hpqAiq{XZ;^LK*&pd24I>|J|X*8odV~;qV^5nkx!0AP7lVj z(J1f{!O1)5XonqGLZ*~2N}P6=Q24_}4|CsN8lGgWDnXZ(Piy&fP})6YnL72E>xhWlR_E65h}F##CQRCo+hJtWldjXPPAR4;LylJC&LnnBL+-p z6r7x6k#UyKY;-#vk0@)k+MiL4)6n!GZvqJ|07NlRo&SUL>se=`9FaB0*qaa3OKp zQX8$Ml_rfRtzNLaJ8j-z;SjhI1Y8I&Lq{B6Gd+YkKa@2uW6XnTA!p7XAzt34-EU6L zH!Q0TIvGBcEiYl24`G-OW|vECJg|^Qf>{PwCD4N4lTTwr%bAegwC^wltZOaAJePFi z4f6=nu;cY=B&wo{8>YpwsvCUqj-?i*OByAUXP>wJ?0SI?K6hy6O+Jj$MFusj0gXD_ zPF|-j2a-C^-2O=7Oy4sMHh$o?PA6DQUgQf3s_&!B*tedh#G48|S`l@yGadH_xdHWc z5od~+(-}+y#hjEPIiq4AjKXk%&=1LsP_`-?jGY_*uB)nu+#NYp?b-qCoK6GlND#_)%*@z`NsWw zFmm>3>|#21+F41IcU`lw%A)QAT;xpPDo2=lXE=<^G44?Pu`D&?7RCWIfCzI2I`rz1 zC!m{VH%d=6i6x!z%!>L#eUBTSx5b(X?4-5zqdPB?ae7z5tR9qYY?v-CDe4-EI}v|T zGasuhltlYSXT8&N8&^%5^4}Nz;cPLLU)fLgdI!Dpo=I{2?Xn6$I)XJ2x{8aB88g8v z*;+Jt!P2FZ)KROLhXg$#G4=77ZJd;ySy9YL(b|lck1xDr_$mdA_u;Nhq3D(i)L9>H z#5r1web-V`QiBV*r&teT2JDQA1W3aGiiG+WHdj+agV5ox0EXAdrdkou=upE8#w)HL z&S%1OF`K4nmH(CsDYLDYZUutluM~NjF%0TRo3JB)9YWth=zT687`T0ZG@<$=I(gO* zx!9dffhh9jVB)P2?j5II6r2Oul&>1}_VvaD0|^(^!K5G1epXQ-5KuP*e6n;C}+;szQPJ&+}@y);so&kIu;gY_tv;)f5UFBxU$% z62Vp8X&yO8SX9821L@4l?fC=}!8UCO1B&W5>T+=L1EMbDS;3Byr- z{j02{B_gfCUR=xguCOe5QIz2u(c(tR}E2!9i`X6dH`B!P|A^|g8HB+8f>(byH51zxixVG^w=jqxSGs@aj zy_8PY3FOfwA~6Tc(8RL2Zt^0dti7-09w6ONVk>zbf5Q@%`5;&ek}lPk`N?|{N8sLi zd)qbB6snbB!_Skv5DV(3{>tT8SFyq1eY--#@u`NQ9fx+04-faxwa<_vTIp*;H-%j9 zqgvCXuQbP~1hPK3@(ojc;({B^h7w%4$c5?AeXIfCTJ$l?7thk&GC%P&$KVGL)=t`0LMgKCL%|&H4Gx|^(^IQ$e>i{`< ziJ&Y)=4|o6`urk4B4evtXT!~QDpIxv=O8@9RxU%qB8Vj*i{+mdw^K?a6b`#_1aD$J zoR^agnR1XX)*i?PmfNO07Eoy6G|bd;ZXG&o=o@u-ZQ?;kRV;)K)xeAwlb+;ADqmq=y;07Q^TdVs5U949Osm(Qg0^IY9ZA)L~E^=^#we6(93wH z=wy(Nqms73ogSYb?;anZ-&79%n$4=J{RDAsXOOHSTpUOP-aS4&eRpyWZ~+Q~27|>2 zGPhE|QW@u^G~|+u7XoYXj-NA~N)ZgX_^e5su8W_Q5X}+x`D9O1$%X@rC{}6{~{rsyl$>NhvXyfK-_+-wVZ7&PYwx}pUYg`VT z#t(K`d(??)3!E>@7#pu}P7;iSY1c)3@Y+eV{PZ9uy6n2e%V21n-VGPB;gPR*4$gXO z=Ja-4%}b;-LV;o2vFPv{zAypE060MF<}$?fArvz>_snm`t~XcOF`5NYK<$t3GnfmE zUys5`PylNkDhVQDH~T+yF+)%Phw6_aFburX>2d5l)>k3@A8PVBCBmf_^&f))X8j); z@&%G1J#WhAObhg;<@Eh_G^fXH=P{(}rRN>zIi$@JB+{3KQP~1*ueE~*1jp)HzX0bz z7{6S1StXsWF*~h=Kkd(bL+Jbk?hjN#@KVMNzH}-Q;8i=gL^U1lvFfH-cP{sTUBl zbT!|z zB_YisL{Fr3O7!LFR!Z0Qh9w{8_dtwIuz9UCm6t>4s1vG zg9h;BY6IK zEYub2af8ivX4h*tT$6MLA1mz950dMfFJN8u&o~`*^uoz&q?ogFp5e(1|7aB(|bS#|pfwLhKoM_=P*4_G}$lLhApoWf+TO6#CM zMSrMcR;Af?_2VC^osSV_y5Wn6H7AWOIx6AyKw{X=Z3R;|X08&Bt$-ad+(vVP)Xexo?^aFh+k{n4$` zD%0sb1pw;H`AkX517hRkDN4?k+9PS4Tw_esd^AWZk%`HVF2Sa#xT4Mb5FPgKwJXGR zno?m!u#6@jM&nJd4b}xwd=Bs1!8!>Ch0D;iLak`n(+det-BPVxCd? z5XGDLKOm^a^J+)^UlG%bYW+pC9l;KYdLO6J@8M)KRw(P(LauB$B6#(^LOmEQj4!dm z7sXs-)(ouy0IKRV8j^Op_que@&8t=aG z=)EEn0CCmNz*$cFJZo&Ii6yfUcm_+qN_OYdGmNXX29gu4@+FkMFs_kTcn^Ggn?ga} zzP;QaFG!mml?Yw`K1bjg5yRjH+@G3pt)f<-(Wyj@YPSU?G{HAXeKo(S;1%>}GP*Uf zA8Jb~oO}QoN_&wa%Jnsnoxv>07UMalyM-H(+bP_8jG-Vb{L-I~p!|cbJxgjcN-^3p z;kym5eNHr=FFgf_G6lnlQjSa>NGc?Ic|RwU6;+fSQ}LpqE)=J}#kPkFRym>_#W{AMCX|`Do4Ek{AI~Nw-dMhiTWO~(2ueN5*9&-`2`X;O}b|x7a(Ut z=7?8*>ad&B)uB3P2D8zWm&eTuMUHc5C(m94<1N&Lv?|02v}ct_Dyv5Atb{Fp0C7UG z4frGG+NYmw6tq%Jf~u%ZGE0MaM$sLmXRLgdi$25?8Ys?u2kOyQ-V%Xns$5-f>lalY z-g-ic>3okmpYXH5JDY77-Xat~HzsX|LI^gIN9e5|ClqS)&^VmXw>EhvtxcfGTwC{e z^-jWAvMHZJK%{*#^xicN`KlM{AT)pqh3}2%j^G*|LFg}js73)%|@vDCQ57t z5kQAH9rO;5k0PXpS)`aY1Zt(T%_rIg;P`&7GvTCHR~6&)s)Xe6VhGW3BP`hqhd=2@ z>-=h6NeQYG3KSD197dDrVs3pJKi81H&gR2Wx_R?*?ej5+aP@k$PIP_0zGj=P)7IKo zs^ZPMcuY;zBOQt`@x&sSn#r1orLdiVLz9^iK0eq#+&_=h=piZzFWAp|2ff{M^p8kP zBq>W$2Oxm{S&8!co&hD&Em3@g;Gx=~1jLQlI)I`R8GXPJ#~9>#r5Mtd{r>p%>$BcD z$(GKS6D%0~X{&J7GGV8kKFM#FtkFU!B}LXEnVjywdDA;povruRbvzI?0SU5#Lc3~w z{>{a^lf9kuUIl)n$Usy^)o&E^R{{SvdUxL2*|YA^1Z|YrA+-vRFX9#7~ zs;9|dbVUt5^k)!O9=#tyC=#p-%vJ%PC$n4dsLaYToCctgiy=%A@~LKzLrJOHxq`e5WE^eBwea`R2 zm$5!Tc`H$16gto{?-)k7HnS01CfK4!oDD8hlwbt&(kSW!-sXmQE#?U=+G6?r_mHFE z{QHxh)mt(fy<~My49iq&f~FhBlGzHmKV)2;7<7_Y4rZryqez0hv(7a}!hf)1!%EPk zn%q%j)+DMmt7ahCgGYixP`hj0sK2T92DKhEalawAow0En_hfNj7)=1))EjtbPOOS?XkFIC+82W|j?`o;0k!T8=*Jwh&TV#X27=qJgO4)>3aPbE_-9ts>QayXmC1JQOn1%S^T z$ePO5p<4*A0??V39f|=FtpYy|;f`%_>L8z)0%_PyF+i9IdPOiwt-Wsj{=T|y5p#B~ zcI960Aat@kyB9^BtgPt4&T07iuoB`}1d zWH28b5~&YP9S~|A&gB8YF)g^|#6dxuQ5-C%?+$vA_noLhh1=VeIn1{h9d`Ep;j7~V zXX#Pb5ogm4hefamL-MTRgG)B35Rlm90Y_G@tjI$TaP;G?uw zi^W61g3Wh|^UrYkOuH~+I)@!1tkOVAKd%+BF|~UzC_|kS*U9W`o=lZ6eSaT!v96A% z7^&wqOq6(*j1|YihHY%w`#7D^hn<@K9e%AfY66fI;MJQhb&N+5{E8VH&t?M<=;70P zwGB^5!p8@-ss?Qz)pXt-^-Ej!^)o!gQ*R63--6TmC)KP$aOs;yBi>s3BpK?KSO&pN z;%YUBcgrB~ceHk@f42%7)4s1btqU8|K6Khf+jhHQaQU+Di7DjTlk2Sf(CpY|t1chn zcC2;fGr7&;dhEVY&-cy=ui}M~mgK{WqvH#rbJ}DjJ%+Ei->+(A*?ebrSFMEkB;P!C zn&U8S2f5~WuSJSs-=v)Yo^GYZVM5{xm`C6~ne)1&;Hi+{aWvGKWWkZ2Q)N&le2{m* zw%@;@j1TWIV1RT!?gqNmT|q*>M05A6#biKfd3aRs;qsi|G9Pon+id7M76Ok_9xz<4 zQ-v~J4RkSuOE}8W-V1F=3Ak+H@@42Uo z`6@s)3Fs(g_XLU>iK4wk9e0UNbM;_^lfJ~K@BRG+!TaGys~j2oBySazkw8`hD+jP; zO5|k%T`0E{H3NhHP=ZCN;0?;ow3ufe*?(8@XcR8|7jsRaW?mL1{Fng|UZhvq{D-q2 zqpzaxq95J70!njBK5Bm!ul-lwp}lK?cD5P%#!#JEGQOx!0Fe61jPi#(h#z&#Y4Ud{ zi=v42JBH%7<*RAaPVu#~xBIWpFW#N?F7{p@oQHC&TYPYqQq&>(>>onT1ARFBE)=)y zFUE)mU$0c_r3P<##yQ*f7UMqHSU=#hve(RXG1vYo-1nX4A9k@wt;-pZtTj@gZQ%P9sjJ#^y!im?t-yKj+6|JEaaR@UswTkb=p*fh7Ic1<`J<6QHIB1Tr<`DITTbyeRq1{|-D%=H( zs%RVtRN5hIe=Z^X+Wko)WzsZsX@;P8nO?p<`aQD!h!M%sn~okJ$zU4<`sXyZs?s;q zKebk)5-BOQRe_&t@N?XSziV~;xs5-^_%}YUNtW%EifADUqh-JNUKLvYqSw|8~eoh z#uidTL#iSq8UeM!@x@Jq-NJD+@i}3!)nZ&~NKFlCC1#6osUfvAq}*H@ILA7UrWSW_ zO%WbqwBDk>?U>pOsotj9wJm-hfVq0RZ6I|RQU`IMTByI9ExUGg@M(gq4$ycv0IGaJVrGnL*oy`Zy_&;n~&xN z5#lWFA|6_1-^GT;tI$V;kRtv9F^8k9R}oJ*jvDpWZt|*VNSelJUFtZ;I#B^)zty0X zptp!?oVD60__v|VxMLvUm})SBCaxo|e}~q*iz9<4wXWq@YRL_xt~;hK;-if_2k{=Y zXdPo56VU?p6JyJ&!Bb7sxW;4ri1nux*N_Y!f5Q4Z+_zSH1oy3XaCSH^+6}Fa;dC`k z<8|6)F<}|`Ne8hdRzfv4yf302EEUumF2)Tf)Vzt!Q<>gvyNF4*| zF)J_ET0=5?ykOkO%GX*|619gGtPY_$z1u3P?8*EAkAJNA9I ziCD&;aW!kmb7)mM)vmKD8dA+b>RKwm^RrI77O`I=j(}89Z_sM$k!eVp#%tB48B>ea z4o4Otew%e#d89L>lnzm8!|c0y}KbxY&eUk53-)5?uQ{EX*CljH&` z`!+O<*XWEx*)8hS?FqSZO*JIT#~&jz$u-rG3?F}#%mhrT?Q-9Srtua@rgTQry5Jhs zXb*~g$5N=j?;4uMoAs{0{&*rZ8ukQl(B7nzxK5Irot>ufTBlZd+MdynEFXXTnMoMc zkPIJxfXviD*bSN~(hFczLo%`oVz$Pd331SE82mOmh(+W{HKev0;w)+#8gCd`g(Oy# zOydr5H`JeyLq@1a))<~ku?(qccbn?sJ(qBUsX`Zi;; zqgs~6n}&}I$+XtBl1UwTRTEdffn#lvoM~iH4XI_$U@Mu%xc&{Aosmpo_towCxAczE zkPMAKVf|^vH6$aeJYoH5#Wf_u$LUPMk+*9ttIY{5k97wji#A(k?OIj$L?C&h-9gSo zn8m+4O>>^KaE?usZJJgqYiSy<5l54}tXY4|iO{P3S|>uQ{=^fZgQq-j5Dlqe&b!)@ z6SslX9d)f;B9AA-$8opRYGnIp8>sczhw7ZiRyS{1yNcysHNxrRPJ~wb*E$heod=x= zH5?7;PeiMoxaFP*t*)bO#LZ5?N&zPY?f}F%VX=v8(6A>$+sG=|UmYzLHPnXaiyF?l zfjo!yQiMFSMRaRVgm(OEoe1sPuXQ4{>!A~&O0qlg&)C{ZX@BF-WJ!&zOxHFv-m>^@ z;y4=EwodYCo6csWRUC1>5i>?Lq^7YyAx=p)B8w&Bx4|bxY_RWRR70{f{&>3@VN^ph zH2ws;8jA4-lBV%GOUo$rlJytIU+*@I={kD6Ln+O7;=)EwW*e zTtKG{&aP>>Z^zJh+uC~N7xZ&PyOwCbZEa%p*w|G%hQ?_|ovxjoluu%k>FjfDmo!w+ zX}I>MxMgI)dadKx#CTq8%OOj(#gma$T6AVEvx(J+H}g5@*~B_6!=G?nkjIfuQX?uQ zy}#WwngZWAp#7m)wN%hHnqtGOh_>mV+>N*)9i~B+O5}+R92xwqAsL;Mt;0<#7a*0= zIoPOLX+x>0rVZd-L+YB@bv!wQW$+rETLRma97iKhxwDR4%dl8BKFx%XE{Y3 z=U8uBJQ+UD7C+)~B$IT#HE82lS&BAz*N~bHo*Fr<@DrL*5bqjN%f)yR-ih~BJN8Ml z?ool^<4uy+n?YPVqa>N0br?gLU3&*q6SPN|5Kp?K@#8p97a<)+j>*tC>YO#=Lp7om z{xI=bC%Wr8jLwNt1!)z?4;xi_(ljGzR6D{7K{r@U14+|(r`8bi zIDLl}RkmB;h{>Lf)KSATxDhuDB%^b7sV(W_hzZmJYA7jmkkfVQbWWpuL_Jq6o-~bj z2+O1eAV+92RUv(LXb+OUO=msXqAi{*A4eRJ6or=;PK zu0j$aQ4;@*cIKY5V>QAW;-FI}D=Cf!C9x**_eP6kY^1rSq0HFc0pad!5>9bm$c;KNeMcMt zXNUW$fos~V+1WLXEt)V$To&n?){FKrLT%t0M7W!qbjr6a#x;%C5knomqr}wlq$ipYae0!>sx|YZUbSQD7)`M$ z-ghhRlNQQdtrqP7g_}=X*2&6*Xn4MI0WT}EIPt6qKg1P?tG4a!chqjM{hj9Tds)%? zMJzdV4gZT!b|D_g_eMl(Y)$FpysYTvHDWotVYGMBi|MA>9}V^Ids#hbG<^FN^PMH# z=K5Y%ywgZiZdsisYBfDsIBHoL1aRqlS*^xw5iWf%tH4}HyCcc5+F)uo7$upZ+st`c zkrk{)wou0JYRn1E)_7Twwxew>a_!pYgwVI;E=GMXtB2w@k5S*t>Y@0}&(Zg?idhSe z&Hm+`!&+L~?4p=%=VOgg-^)r{a$}+OwOOJwc;XxU*jPLwYge?=2U*9+YD#Mt#BUy> zzL(WQ@mt6Xg!J)HUO;wU@`{P9Poj}Nm?x1v&Csu=ShBxIC_lz*i_@!;_p+*+^`g58 zxyVDYdUPl6Wkq|c(=j)4yuWhurB&e_C1%%kXGiBBS+fLewtkV`OFIB% z48Vr(WySV#lKmgJ{)!A z-HvCfl|CM|@^Yw3^ra?`cAOwtvq|FNm}6bZ85d^URGrL;oZ~} zcYD>g*x6z~@|{#C=VcX=nIs<VV2+s31nW#3v&aNnwM2?jVbu4sdWse$ZFttpD!`M-mfRHFhJ4xhE~D-GLs%~>$uW!! zY0hr`uA0*k+Bq+)zzP%JXb8ErRudj0dPn(QRskF^)eER~Ys0g$XwJ(@N~WZ9(0Yl} zEi8rlURF<8e_CoyHlX+Q4R zO1;#Z@Ix{>r`(ss%Q~IMoCwCt>KC5~t@=|>1fnf_JKyp>!ow#n&5^hlQ)~`TO;<;V ztxZQmZTnEA{$@|9R?Fj0Pd*V^?O*FeXmuWTA`ljZJi~ahCxZ2|BCK>nRtirZtJMU@ zZ{)nJr2ZTUKBV;)A@9(0l5OpY(2jqt6QN!EwN8X~J#Zpu{@*n>#w@3^rP6Bgv9&+7 zJ)M&|u7Jm9b4Ta}LU%CseCuVUaayz1x@Obd_E9_@Vc*B7?`8EAyPE4mW@VMf+ttY4 z>U&vn6kRN|LzaeHKK6;;8!cCtGG11U)0#ZHV}aSW(eenF9M59UJL6>)@$G2a-xb6| z$irC32->%-n)9;awc|)(>t!8rRBKDXs9Kv?GvH-KkeYSx3;i8gf;)B(vgA?Eds*=p z0!CZvL>=oPL1T@(-s~E#{YhFnT0Si}V>Plv&dW+l6-72NvdVNiA)8pI<;;#Cu};#p zrzri+nnJ^ssC_RhmcE+y9AX<`wI!somhb|rxn42G%Zl!PXhldaV2@y;ba5L)<7U~x z+77Lk6?-cQIfVJE@R@2<18b1;vZ}WHl^1JNxCYk#WWB7IuL)UDu6BO?8&!Ahx-N}t zO0NYeopDnWW3A=Atmp)Cc7lXmtNEiLc-F4cwS3(Fn*Ww|$(pqq<*Xsr%PKdQhvGfw zWhHlh9`8aH@bRAavg(9aYUwD24a0a@1^Sav^FP--n|-$%8q;#TOYYn3&dZAZ zvTHdCq#Z)ory0@6T6O0h!FpM7PZG;w95r#HM=;12*zyAFWyN>+8^{Nk+=`6TkJ>1@?gEJ^uDW^92?wsUDzDSL$V`$SS=Npd(KGeq%|S? zQY5&DjL{g?-mt!x6-%Rp8vh{XFDo5;ASC#x>%pMdEawD_ zyE!i_xm)B4GTk_HtXUsH%T;2Rk4s4GS<5@5t)4lyKNuiZRi?cvd zx3(j<99hMBS@G;z0$VwrPWO6zTDO}X#@p`NHM>Dcr&hCf{KR)_o=j)GtmsWmjKg^n z$Ijp2WhF9ly4lg9(nhOO)?QeY+}6(z7VyBLj0#QU_8Ta>x8ZL%lJ%1qZ~tQQFh`H- zxEAN~T*b7L+o-P-q~(9pdTq4w9$5Ld=u;WfInF=F;yIn1!rO@{S{-xNixs21m4JYM zGe2zGS;uzVwQ4@kl^k;y(U5r$tN;w$yEMlZo<{hyLR`~ePRuTLV;m$l$@jct#}UU3Ln$$N zL>{o&Y?Ul z$aS=R`W{#txw&*=EBkg)FGMeEwFSFDNL}adi01|4h$(`HVriSzn&l+cJ4Nm0Zq5UX zTea%8Ro8yax1>bfc&CsXllA}Z*j+}kJ7Ror2~!DSKN|5R%1BhzgAVH%q#0=frR1J+OG?JF%5a1ZFuVuIuAZ_?p&TKHjRfgBYTW6qM(J zTQ)serCuzn$nWIO)C0x(NJw=Dk~phSdhjT$-Yk|2j0aY$+4aX%Z7#uenYi0Pn8+#H}T(dT8o9Bw!c05^&_bz3Y(Q+&P z?Vskx1FH+CSj?6LLo0>~fPcnuP@eTYupAt4c8HdVIpiBIL17$M)oKJhu-YbalE<{6 z<8I-B9V>DTCF773Rr5Wtlp@)+=YI`lL5`F3SFMY)?vh*($aAGvr@n-nGsV{95T1+& zR=3%*$tZth)N!R2K3lG z7juMujICn)qHQI@syN9SwT4Si+5<~{(ezI9nC8{-pI7TuA#Jwv9$1Wnwm46kIuAxn z)>?ws?Ybwl=YbW+oR0x}rCV2~J*0ig0Z?n%(X{K{?7BvNlC+0AxYNu%F?kr(tlKUm zB3B7&NYcTG5Ppt3DQUqaZO~WY89M!o=w8f z?OxhY+C|kvFRpdCmx z3CV3+wd3n{tM+GL*81mW*EdV>8w&XAf&pGaB~#yqHsaz|>9jcIl4q9SRumZDu#m`v z<%|`Lf_mKfz_8_5QA$k%#~OO;nI#nTj`wv<%m@`6cfP>X97t`)k)mtoqUf-tlP9T_ z#|^+_OL)hv(#!{jbsJqfmwNMIw4i!!`DO`?!A8rUW5@PDiLkqP=%S%g&Q6;pV!S$Z zdqp*^)o%NA))DI{QaHz}){fwH>h|ZZecrC-0>kthnjQVzls|Xv&#jvHITskF-?T-4 z?Yj86DSkFRsL8c+W{Eb@lc5rg<+hktyVDRqYuLV7qTOwqRu~d%ey)Xj$kVtsOE}|b zb!!5W8BXRn-z;I?Sj=L&3jLf-4L%k-maD{F4^npp zRxEd@xwF$|3Aa_NTflLBe$lb%BWtlUCcKu^+sHjZC8QgBe7xq+xZ*?pcePqmU@J$N)&x*TKCJ#AV z^0PB$iH@M+ZoTycNFI$hVq1XzkZ}V47N;*3 zMN&O@nqt$_IXiR#i@c{!mrN}mTiqa65oQTABM~QTTW*AjE(-ab2$yJjG~Tj($F+^oBd6DJ8;Yj)Nn{J05>(whGP`Cn1en^~;tI z3)mg#+J^r|Q%DC*mh?AipZqiGn)a=qkVbxodr$q1sdM-VCeUfp=%_! zp@dhII!nS{_P3vq<{{rTDR~f@Ut5%hsME^1LlDn#=2&fVl68o&k#nafINy3J=MK@T zTP(LI86lk=_@qrqwirf-wN^S+eRl}ms_TucjZjhdQ<^Pa!iXMP)(CIx4$i#LoY$ff zJZOYPseqH4wki1)n#SAKb>G+>+LSJ-T@`qeKgZ%{x&-vsu4^E*?Tq4%KgViK{M0d#ZIWT|%DPQ1CYTVm-4J7Kh}CTPkTi|An-(kW zW-NXd^J><`&kYZfxhigoxyV^G#h996Oih1G4F^wclxNy_X^u7z^IVKZaEi7l*46YN ziP5ygXv`I}d1C0rcZWb5iuyYa?%j4C@|OV8s`SO%4}DueJhucCXZ9paP*UE z-QcD}9I)zf72^)kLaeaUSsrR9&W*;SabtJjw(XX-^tzDRc7oj3xI?rW;^c2MmT*g6!G=Gkpsd1e^H18vJhR>@=5$q}2*gmMD@IIG znYJtV?hq}MvYNTw((L%>RSLJ zs%&WcJGxie5hHbU@(F1kD#sU(sqqL%t!85hq~;1pt!Dj!V`_y?^IG`pcCC@aWt_J= zIPYr@#8W$OcQ7!jPsVun*IGN{4k6`&hvM3W6x2CM3aH1Af@Ju3v;GTbw}i%PwMRi( zN#nJmIeMpgv-zmCt2;1UNSel*D91M`tu;vgUWmqDE_Qa$&v#x$rEK(5l3tZe+41so z|H%*4AIs&nwdYjfev*8gb7A@0{xpl`>HB1oQBn1){&;-ZAH3&>n^ClX74@M2eKwyh z26L#CJ|4YKup0YSIv%HYqsjFPcx+0r|G@y+-;2JBzK{L_1=itpe>zS2Gw2Gxzn=AP zZ<868cAr4w%Vdz=CYkEc9S2rk|E>~!UqL97p#m92->R>Y56LV_Cr}w4LGoO%ZKOW> zOEiM+ri(dLyoVN3HGl-`#b2t2qj@w;RgaT&PH(8r{QQ3Ef&?&woBrfF83G_RRy7I$ zVn9NRSu&rEREx_*4LDIvqGUExqfoErH?#C^f;HnmA6=<+REzj}=iuPg&h9tbo`hI- z(;UBMJZPH|=H!XAX$k-QKH7c>vO`IDUQcdjFtT+(`Y|KRD>U**RF+ zCW_8Zc6OJ*d3UsXaD3L=yEr>P-9LJ>6xisP(k$EUrb*SiYx&R+5BgLh}e zL)$$*dVR3JyJTXj$;tNxulIHoG3=Zb^}W}7-8(()?FC=&^$zwGP4`aEmh`>XTY@#k z4wqp~ZHMKrU+?T6EL$;!^d+y~92~zYe7*nXsBp#h6_eZB=Y1Aa!(v67!~LU`ZD2#KqUW=N zowK(qad_H0TqPMD?e46Y*Sm*|`Q7TdtEE`EzaAjw{^@xC=;E7im&@Kq=RIaP;WldC zsw*XTE+3CNf_L7nq}A64$2%)&W942xIo&_pIsJacS{&{F*Sl5wYxiw$nW%aSaz*cG zw|BNeoj5pHEzSb(UBNe$sM1>n=iSNP%D&Xe-8)^)H~0h%w;`D-EP@L-ATTN+WK~~# zr^l;gY_(vkm858ADQy5XpPu!0SIoWl-EQw>)&5dzu^i6c{@MBd(e7$I@2x&7U!NWy zu4)6@c@+-NR`CQ70QP#TWq|0_iv1P6IX!;2Vol%f{CV|wP&!}H=G(Wu)0O*6E&lQH zHhY(W~?tW^R1hnW1gX8pfjjT>Uo6qH*#e8EYFD zb>f5h&>t^6Ga2{190;MTv_FXyvQ(FM>1>#h;cfl4|F?9uPS7^Xxq&CQ{Rx=LsO#0e z!DnCr%uKiNZX|HE$iQHCkI%_k8qLzhd^Aa1J7s@nhrT}tlU|nICi4;4D+m4Y7z~3r zfziZH0L*=~veEth8H}hmna}Rgk~dQ8i3>4Fx0ukFD)8wBFAowMv_;Hp8TPA_5twIEe4RSJKt-DOx6RmRoud3Wu|eY%!gV!TO2s z0z)bs1`jnrPP~o491AAX5Gv&_TV`Vsg)=OsY%t-bx6^SlPsaCPY@PSjD#JDbOYLZ) zzL^Z*BW>3W?M}I%Cj?h7=KcL>_;D*VM>VMZ$uRkd14^f6JC7!eWwXfl_sMKFn9R3A zFwP+35|H`TT$`8`rRrIdsTm<U1pnP{_S7l<_Qx$ljV@OzT0O>_{z0wU=cB6$G*Mji z)w?(9SK?gJ*V%kHN;hv_Y7;q{vY*}GpU>2|$*vt$jYH<(rav=pPiAVd=k(t4Vd?>S zu-EBxy23bL%qE&*6fy>|{E8TT1=o%G=oXcZ~mk@c@}e{fH*71RI}Ri;-+hpOM({(E?pjF4HH#X%{Z8RS0P za3G(LzFv%9;=kk3OSQm&qi15M*sr1*xDm;2(#05VD{%O81I6Qs~a(_&EnoI6Zb~(oF)xFA0rUL#Zfv* zkOzNAM?+^ebLKt3n-d9jf6oVk zmm;zWUV}If&UW4D&|QZ_EM0Gi>F|w)#UtNghzERaA#ieh^1U--eK%oNRNqF32l@sA z9f4_mf%ozzRsJn~N7A6skhA)RszW4VIn6#Yf zkOfN&7CE^Df~G0w@H#p_c1J>HC&_Zy%4CIroimrmg6+r!a_&3PD5Yy&Q!YE+3rEAu!-E0>!l?Ns8(k~KL5@U0^`-;EmrInTvw1ojCVC}d zMP|;>l-@7q3qU~EV~kM~C6y<$i)?W@821+$A($G8!JvjXmuMMHM)M2&Rteu1Q}|0G zRb$y=%pW)pOHhtC3Ii*hN%FvvWa;=rVirLWP$E_lVBIdp^ASB$a1hK;^`=yJJ0$g5 zEvz7oE2Y%9=)O}*Z6ZnadX_Gxm-pt;`b{77ZrfxX7sIpwAmh>PXfAAZ;_fTcMq>s%J{?31 z`ba#9VlzV`MtC3x#81XV>Iem1J2P5LMt@%ClQ^yx5M+X{F=q@I613Eh0L`bcj-}ne)1iui+8BqXQ2>eT+!;)-LjHL+4#n z_wiAW!@O$IXABnJ8vR`tSo2$$HysTYzas}vbGkr85?_!ild*K)tzSGIht?NaM~Cj(tN|F(@=^CQ9xeck7xm$#yDbfLIsI} zeNDyWXi4xLq5$n2{I27?GmpEuZg3d*{lQ6O<&;QDDAB0_Ofd=t5O&TYeFAc8rhW?+ zQDT23hg2==@JF@ck4&4oXd~W_hUA!TB_VF#5bZ~_G8U6HS~7kPmK}cH;^&$FqV2rU zx*NYF+)r-(kGk@?`wazb=yyi*b6c1b^Fn__yNnfIsG4C#4xVu6FRXkxR7wfLnK* z)+~4MFZ9V=a`tw2NqeVdr_Tzcm{v8fm1InchcG+Hvyo2S`;eK_(r+66 zkdRd&pYmEZy_VV|Ge4}A>?;ZyXtz91Fq}603KpOi5x2t zeLz9XY*3Pry0P~H0wF>GG*dNi9F@d0s|TC$H6^!c1l!O>9ye(Qo9KHxZqy17Nnej~ ztG1&Wp~J1O)pT8TQYt_gH=?K_r)G4!dAQt|n{fUm)5Q5ct`g$uA-)&3JZ@6+oA8gW zjW6&at%BE#x0q3C<7#7RvuMX0G;y_A)KuJKaMM;%Q+>n1?b=MkiI^aJ7i)`UWG$5u z*eD}omW+fwGP0(~NEjg_VSeN;X`KypTsU*5!fm?wHUbfBFp#g!D_+sTc&ZmmkDYJw zxn0d^XCBw}YU{5M2(&`>*3V4KMqx|3N#thD!e)w~!TH*0P0Q9dTD7HPR{Hss)t_S4 z`1_eN4?-X=mw3!dynalc-O}32%@~Qs=&Mo5?ILac<>s|ObMw+*RDX=HY+Ho}upKMZ zMr1OMgq@gSG*-X>UDdNC!1p@QSoHxqxgS(2r@E^)GA*;p>NpuN@+B3&ud= zFpw2r)y!AekPW`}ecik#J(HNku6f@GyeDrSZqUp(Fz>XyOoNke+WwooCK$89KpqGZ zL^t%7qcqea*xM0m&&C3AqzGVaA8=pla1MztwhovR$N^H%zvE~ReGkeF8!H;>a9{7U z=Bm%6Rn2_Wa^)FPa*<1GHYx4|`5Rgudnn6UcJl8yUd2I_D@L)#%;Ko-80Sd0X!${~ ztw6sg-YEBs0?_*}r_)xP`y|lFwd316I|``LV{@7_G-eBcc`ePBoWs+;bPT>RYXGl6P`~`i>ARt>3RHqqeq;yoLO)Jpm;M{G~4zzjWwdsW5xD2b)4Z(5SbgO|jM_!va z(8gmy-CCdx2dz8p>fv@Cnz|u;bL_g)E`;*aK)Vpy$tl5Y7eYPQ4MS}^e0bp-I=Q|v z^v6oKcuT&$_?C0Qdi|i0U-VF`h7eB%ey3Ro_ej7_s}SZXvfgPH!aRi5JB>nU=kR)` zT?p;kiRZ!|DI*=g0uw=(a#_MM)tCtGng=v*7~+OD7@nt75OxpMI*weTlS8@qxb)v#7? zHhwxWY$Lk-K!|23_TQ-9&&Fhx)nr3AUG^Sa* zpqY+u;bxtJW;!m0n{}5qg9LQa8<{?0HQhtAme#Bdm_iPWXIsq8sS^i3^I&`OC#5b_)8W*Qb~3&#!n8F0w8l;-K57(vL}^Gv zUo;E8z%-Yk4_bknY0K5*QQmP+Oiowod9dTbgBN#^@nh%DiAeaVxbP4M5Zg6G8~ui@ z8Gdg#W)tJfP2-}brbW#&GY4maGcWSKe~t+SFq_KNV#2v$639J32}`p3+skx38lcmC z)X%bXFzU~fVRSc|-$Z@NVFDm13kta2OP_luAAydEFF_U%{P6sKnv{R`LjWkFfNAiu z8h!DF{q<{`4BS8z>A-E|JtPE=%9K!=rWDE72H=m7ncx%X5Ki0mca!&%^lq|_uNC%G zgEjkhT_beu)0)Yv;h?cU9;X9^E68y)N$xn|#wImPlrTQNx0xhl$RQVzOC4{&$hf0*Pz={+=^TjpQE2 zG)Wa)2i0QAIh;JY(`kY1ZstH5Tn()MM=5U7S;l5i(oHpP z6}H~06N^&V!-2>-ra0h7r*!GRPdJYcNE`}JoL0%h!-n~N1b${}sOdc?^nlDr3W+z6 zpMRo1M_>X)NZzW!kQ`)8j;(08z^pH(Uk*!Bz49B%Of*##mSh>`ftm48MQSGf^<@Gr z%=mPoqY<)!tI=eX-KeMVooctqU+IsJ(s}a242VZUfl8$yH znYClPVx3>IV$BE4tliL^)oZoziWSezUA5Lj=GHXbH3I~4HX9W7R&BezJ!Eo*_8XmF zK#uK)Ow3S7quKpscx*ppW@e)`T8*dAtn-kWnT^({$G>c5od?XU6I+68{Ic%4513u2 zZn|r9e-S};A2K<++nVt&=?yCAt?tdzWUcySBB@s&GBHb!wdOBikWkNWb!V0$tJPn? zAnWl1X4Z`@`PY9DJ=SXvm|M4IyK6pu&1w&snIXn@{L5GtR6JbWUDGn-U)tS6W@m`M z86y7wkG+5YYvaiF1e1G;WknO9SgNaEg9p9 z@85oFJ*sL|b#+SuoXkFFeD;|jsoszEsjkSeZc}X*cbuY`5-y0cH?J+ATA)&2~W0qHa#fW_L19h8{6-X~_)o zNV{d`w%M9%-xMpWFQ3cqHfEWhxdNLj>-U{swN%0x>7VH@8H@HpsVtGzRyFQ%K1{ml zMVj=K3YEEN*I!6`2Nn2jHWaA32J1B&bQ5E9L0yS7*I0JM$jSxX-Xi{@R`rNLfrIKM zgMxxBMJa{4$78ZJj6FnT58#+JS!!2m@C3bkrhYi1X`NwT3k5q0YUV}de%r^%Rr>un z%cGs>u`rMjbgpYLdB6S0HLURW-vjI?TTlSNHe>~qsGyG@dks7X;83z7Tnv>yJVpbc zfjX^yo2!i+!Ulhv{{x{1@Sg)dD!w$PL7dpqbDZ}3y0-tJu`eZdj zoNKE?el;175$4pwNcSj@UnTBt(bVYL2`%!jF)$fy+bBC{U}`-01>@gxNiT8HoH#uSZk_D=#cwsJ6)7 z2wyDLb>){+#;@84TQ^;k=Fl@$5`-=tA^1s=n0~Slx-LN)pl?1@m1F0@+n)`Ee3=f| zP&XWoGIjazbkfv-6dAMEW%`kAY}z)5`8Bib!%}>e#66vR^0oSA7rt-_Y@lSWh|}Q_ zkS9$iuM*6n8RZF}3rm=L!c$gbO@`|J+VldVS;AsQ+gn3lLfb-v@cVDl9PRG>`!Bzo z9Uh$#T1|k)UZ@Vw5Q&(RlP-jIv=Kg21}EJvN#Fn$mPH>Nthw!C@2j&jjYKbNnEpp# zrBt0%lWVyE+idnrktFiGvx|KEE4TSxAJ%kd2hzHN@9WvSlg`=x%h#uc7n(C>=uYh~ zx&^Z)&=j2luLWmlx@z=vN7OarQB(T;_b7e7<7AsvU#Vfh3gZI*n!f*LM{EW?Sb6D9 zVF0-FI-BXXw`nikY_Du6b?5ZGd6Lkj#lx0KliGY=muUtRS6nc?;ue^aw&nNrZ-`eG zn5-U!WVF1XWqdVKjMZfN_%?@>AP#>GFjl-iHRtH;Vs9=pa2%{4XVhOw)J{6-4d0v;S_d^S_&_J@EB-n~Wd@ z4J4C*Ysv>H^r(oxyGKK*gWll?%U)Pj%U*Qs4wIV`7;_^my1`RCrA~pHf+I@@vi=*A z+RH>gse2V#@ZUe*V4fJ!!dn(*Gs+tw^T>FOu^3oTxJc7*PwmsEHV=a@^T{+OhO+zF zQ(ksX_kLiS>o)=FNr-KfbBz*Z45tzueN^Y7pWS=|9K+!fn&`VUpGDc?#L9$OQ&P95 z-f@g{9|~?AdD}ezuD2 z8>_=wRaO0B&hTvNd0~@`er~97`RTy3|81{uEE;y~_39R2J)VURm7+uo=}v1~QO6yB zlc@nhYlh<)2qW8 zkJ*%jXNvs-@EISOmZZ0woyfEA^sjO!<<<#Vkk~H(GBGV(q4y3v_zM>SI;)cb$3dgR z*I=X@12;3WOsOiP^zur!qJ0!N`Iv6)OGFs0kmpTfv_}7eH-$#jioP`X(@G<1JD0(~2|q zRcG$2&Wu)_IjpsuPwnzgtIe4|Z8@Xf@_$=(KCRpSoVl+#JH6)22tKvTJ~jPMb}Vaa zawXQBQvjdZGk;pC_;ja|>;9(|=hJFM$+e1-t&)1{&bq8SYqs9@KdsF6$=R{ur&igg zmeWehskiEkbJhP%+yLhmuR5!{?yUTJ;WsfBca_%V`CNC_dfnM0_|y^ub;!oLOE#SA z0iQ%O&TsI^4rar-WOx1Kk+%&w!QyY?;;#FjY{?CWP;5BIr}&%rq_%p?esT^)@snMb zP3MTfC;QumLkKsVBLbi7_1JXAx#^4yK8ZHh{7<6Zs{cuhb49K$eA=*|9J1(rT6bD; zj^w6uT#KLFk}J+9F?WXr!6(t*rc=^6$s1e#C)>kTOJ0vH=TdLEjAf(xlkH(^#s4IB z(v!<1A^V-E8}x#I8vCf}fi9Q_I;ghv#fLJZEdwDOvdB zsv0fvA}lRA5;30m8QhLq6bF5 zOf_hiJa^pQf<0uAg$&Tvq+;wQ=eIURGfzoAf!y9+X5%cFvfEn3Kk*BR9E4hza4n}A zuU^6UP2F+|b+_JYH`0U$-3w&mR*QC>54Qt-LxyoD^SR8&t!DsFr==6$z0M{BN?Og% zUZQ@fc^n5cyCHTqn<;HK7_=XWM_v8BeH7N|i^QX_$!OGkU$1h7f+yQ!Ivl@#o4;QM zBWsx-lxb6sz;%K00!U?K7oS@khbr~LB*jKYISNDK{l-%RzJmEO`1p)(hiNwkGkgr$ z>mQ-jo$gxxj6ShzVN-u3@4)Zjf7Rke-(Qa6>+5)Qk@l14x(1Mt<>lq*i`@I~qIYoL zIG=M5p9MF^q9=i#Kw9tw(08Q<2eW~<=a zI(-4E2Vx?RHdX=y!Aptb;Nd9V>yBt+-Vt%8vFcHYFt*u7)pSPHS_zD**o$$7-w62m zV<)GO?#uBQX&_No6m%Kc)$;A_%0^rGA8)lb=UowkW101o+C*rTE4cNnie$`6fMlMv zY9iFSUyGG>2G>(MxBl^g$d|qB`Z^sKcT#TJ%IdtE#>wR#c-LAc%4>7=ZZlb(n?ykV zyN8~JjUNca1|4VQa5ZHjbKfHaD)P{?S(}x^%6xt^v#3IDz3Rajg1zNL3q3Nf1xh3y zjZdLDO|l*n&01QqM60R46ojn3waL_NsqK)rMiZTR_0Fu%eZ(m1NAaSv&1t+Ysq^w=Jt+@~L?#YxH%`A}5 zzpjL3G~dQe8EyO712(oYS7T{!c2W&FhGw3(PTyEPSi__se@uZ(?e=u|Oit~70j_d7JJv(0d&Ri!|z7>T>J-mJJgfS6Tzf2QB6)s5N4 zyJAPwnr}o>E(#B+DF?LH{))Vo-Q%i_C6;ilugp2swfUyH^@mRN0a@Qn>u3q_`utQw zeJxgMeRH-`YDw|>jC5nERn})v+^k#`fGMnA5=*()ok;U2B>TqWEGn+Z$^^y1h?PG(Q2J-W27}oSjx{?z5v4W>=5a zQpb(;2ORDC*BPxPtQ#8-H`;dl>x|Zt*^SKy9PQ=M6TK2gWrWJ2T>2*B1 z{V}<%Fm3v?n%ml~Q^L}idHX$<;`0GLbQhuAP0k9^2shlvt%(E9yQvW z`^s{v`|1&I%qpM$(3#`CNh`-L^bh#OJ@(#R45GobC$F~;dkrn~-dZi&sh8O(QQEb0 zZXXxljl^q`&|p{E(+~O9{4alI#7Yuh;=s**Q!f_{hlKc76dEA^iTSiT|A8%*`s^?4IuZ@L*0E>xQMbTg@5g z8MlzvA3E&vW(MH|*S3XQ6>72}-qc67wq|kfrG11lRRVJBPIy z=dgd#AImwcx4-5bX3~Dwx9l`#Vn=&%-i><>MPHx$`D1VQWN&wW$_?3Q+M#XC!ztz1 zHrD1Bk|4F<-jsC{p#H6`Y0fV}dTqzJ+4`C~*ggn-$J0HFHmrouZr*oBcQJmrdg}&702t!Bp-DnI0;Bomuak(+`Nev8D`d^V!{-d%)3-r@y3ZY<;bv&d~Yhtj}t* zwAK2f9>M~BTe`TiKBI*y;2t_%pgu6R&%&098Yl+wMjW3z45G;t=SjRvv#el zuHN6;^@pv^>ijmea>H0_PQ%zN)~-#d2b$1h^5|^SVyysES9Kmy} zv`LlNzpa@klvrTOnn9}FgI9U@r#(yAyzhLoSjvr)~2gcVH=L55Ihd_7gi*|G}Q+QuE%ZfiDc zpUuhxIlb?@c3X4X^p1|FEQJ*U*0yHSMKg_9ZHBelTzQC4oxtEMdtGnNGPvFIY&3R8 zHn;LZNrtP3WmT#5)-1z%8K=_3v)Y>b3Sc7R>Oom%w%(p)PzRUl3u*3HZO^T)bHeB9 zfmzz?daIUOJ1}>rGqR2OjU8`a@9s?-nkC!o0jHt;Q8t_shXcG_N@ybW*31S1NIpF) zeVZYW%BFaNwC|ya8j@*#N|PHSO$6M7g)q|&3Nvm{jge(mOGT2^`5j$;I_Ug7^Wsbk z%(2<1+HP2}S((C)N8v4pAZRhKwbobNbbk>-@w}F!Z8n2bqo}BI@e#N1pq5UJ zD7OjLR+`NjMz#C;wH(vty~k8dY^J@Vw3;@BY_m1P_zwChdJROwK0w2)rjZWP(uN^_%8L|b-5D|0C9YxB#n(=T$XX$P}9*I;I(zb%nUxGLbh-464Ywy+

(hoP*I;FH#x=0{joTZ(F)q}Jo7Ho72&rloLT0wmEwy*o_m%o< zP~v;mbnfBm+KiL3ENrD&NzA6t$)ho%>;f@AE3J{lW`{d}#Nx^6?(wt}VcDCTZ&;Or zQALZxV*v7Zrd1f~wk`cSxhNJs*w}yr;P|lqyB?a2(9V-E)M&1 zylv02{+5BSR_WCh;fs-&&elW2Ahax^hj_QR^8hzyy>gb9t*%w~x;!A)I@`&N2GN#9 z@K~ve##S+JdoG%o{*r*`&q63$mo76$`9+Q@;Io~-^!x|n9!U5W=Xs?HXK=QNb zUr`|&c(78PYJDj)J*>2wfA9p~?BMXQb1X#c_4)DoW-(7#c%;?V%ALkFKbXq@ z98E*9ZLPHIu%^cY(DD8sC4z>Kds*yEVrq0 zcBkP9I=a!E5nNR?r8vCo#jEQ zDKrDW`FioYfaD8b4qyauAt1v42qXMU9=4xOF_UbptbYxDziJul>dIZ$wfS&s*nEhk zn)Ov-)$-*kZ_`xJI=`NAS-vK56yD9wbi?>+4_uch!y~Ab!~0-&fXpVC_39{&)AveGHX-)sqc+m zAP2bdRj>#ciowfS9JUL7C3d;4%)%_2*!Rsv@h#J8;( zDV)W3TCIf1oPok^Hs^lV_+j@aPkajv(GubH3ZE(C;{jNZE#FXJ-8|fd+HB4!jjdU- zywRL(6k#9p8OJq0cF5}kFHJ^h7M6x@wC9C`J`!$1pfoo+Uv77U|j2E$2<^j|QC6cjRd~2#EKeuA)ElAljmROO^dn=07 z-lu_@#odr*|W-vBH zguiZH0qq0b^}t+h5Dk|@iuZ_VmzWwEi=DiLUW>-tu6MrSdLTD4Z~2|mNS#a3(e z&-5s;C|7IKpJ1fhM8!F5PE8lH)oy)_V`x#a)}}wJ1ST`fz-Kh{Svae;m9^O<^MY57 zy(lNcc(72YS@~@1CX2BznOiF}S`RJM)!NEb-NNuK4|%Eo-7 zDLAK>jb(M#m9c!K>h0@(W0`ebEGH>EU6IHBIJq9S?&h&?8<=k}Gi{+(L&cWQm}Yld3P zu&b8queIj9m4~ODSDoV-ujZ^V4jWcVSZmKWpqHeK-yZ>YiVdMukJOM`JpFYO`VGs2dds& zgZt9C&s^q*cAuJb-9o#qZOkd!yt?09=Dz%|rp?8ox~*-@DHR>wYc6YZ-~Gd>bFm`K z#+)Km=Wq9#%hrRxL|BNqwW>$$&|F>|oZgek%>S}NeNLN`6*V^2=AP62Sk3%zBG~1$ z8Cf}CV@^5X^~nzhFYiUA=XdL(KBvveN&_2nN(0CDp3~<1polZg$w~zU*9dL-1~3Kq zPpL(`eEh1F%DVVt>9WkC@*7#3o0?mjsz%wGDy0W4B+zcI$_LFK`bS4@pVgJkVhpai zo*I9~ey#lb?bi&<`3Ub}VIMtUy7?3{yW=x%c&oW_&tw*%!(m0qt<@PoxLzOp*s&z0 z)moX~RqMy8qK6d;x7KDD)2r7M^w~yy4o`oXiQ5iQa>Zx7uqDpF+HC z;SSff=44EmLG(ToT4{ZSRO4+6rnt7XIj;?H_xN5D+IV<$qqc=aT-%ycVLf@hd-B75 zCbT;DwZ<-|&BzFN>&-dU*5l5bd(CHSeqV<-(`K_~XEUebx_5NAw|gJa?hbi^sn2P1 zTDNm*&uzCpIHAYUFxc50xMgcLZt0jaTkErVQnW41<9c)bzH@Egd#>%f%ynaKAD)A$ zWYh=*>#gS8%c2C1e}^-$*_!bTY}v`K-g~lt(jnN~dT_C@Z2>3OTbuV@n3a1k%*tIB zW`2LLgV{YXXIMicVy(B^cUi+yPH>+~)SOk_Xg6oW&1_p>&h_^Eg!IM1>7PH<8AH$8 z79wwS)GwZT9D86)s=f%k4mg{vzw2acd#BIk?EZN-02*Kq5#|zInU1V zsPVsZ?bGT#j6m)Ak#u?Tv*XH7dwXbGT-Eip=Kn2cV(n|3i9gb|xOSgowZ8r}6Xkw| zBWTr>wfTwm!Pg-LVPN#HKpI?9zA?X?dw9o)qtH%R9cq2$Pv40LWT$u9i_NV+b1y6! z^ZNR|ZpGRkaV!1}iKDZbE6uN(J^Vp8-s+kgtAF~&Prro!_FF%H#yu>hNQKv$Wa1D<+?Lrc4Emv-as zV2pq6GOqvm%V_L68?E-eAa_>6NyMw&cwe7%rVVh@4sd05(4m!;Ssw%~y7)$G?Vc;J zIpd>(MGoI+t^xI1!KSS_u26SA5dwv=;#}(%~?{i(;h^2wkyp$WY_)MyJ;N8qL**1wq_X^oJwb0 zvr>J_%2u~#2Xa|io%P|)qL^>2HSY)HqB>pw6Mw+5*zX{?Z0C5I6)B?dQ^ zkOuj76klG)6^C;H zzTSS$4@dXl6SWeL`$Bc^iME`HZvN>LwepmkB(!RxE3=@2yIVRxq{N&veMsTmCJ5Nr zY|pqT&ACtc{1HpVB?%4Q%3PZ(_sWK-hB&tjH0)3Evurq?Hb^UZY_8sOkn;x?%@Uhu z(eyVe!Q#Us6pHBD`i$DIg{R-BM30}L#~BrRz^i|#=uAMCulU*Grf+Qd*16N{Lo$fs zejlo+|15tFW(aOBf7S&ccWyBujw%o>g)7#hr-3C~9#|9E%XE)Y6OO zG9CC!SY~Goq?X=j2c3Ghn#*z759f^tCesMV%7>u4H`^suPcV6UeDLbk9BJ^5 zrtW0h?&SJZyB@j+zdSnb2+Q8u{NY5@#G*pY3_GP2#5r;s?-j%>X-w=9coOdHs$ z9oXh913Nf8IqmH3TiUtax&t~pwlPOin`yIHv$NQ`)5fp2W_*>g$mg4tDS+_~QfHKx zWjj#d9L>IB6!V++i%DNXgWj-%UY%{w1W-TQpf|q;`hDA?pl?>@1r~#*Gi5WrX%n}6vRy@} zluY7Nq4gOfSuGIzW_xXF7s0oD(d+#A+<%_#qGR#dH`~Q@zP?1++FE)(JWM_X)3mh$ zp4jT1?gZNr;@tY?-1p_A^X6dM#4Ph%sbZcuLT7h3XWd=P=~lL;^*}N>i{F&V>tvh^ z7s|x>5=i5)-&cu=Ud(B0<`kQ)OdHMS z|D|b~+7@bkvnto}O#9HD;nX&#XK7k3--fM+Psh}@=8Tdm7EOM0ZLXV0p7J>V(0)pav(cW>Gt9!jZ?0|3?FoLodvMYb!SYe4*3$EI zFY8aP2jpRMaH)Pt=JViQna6{BW2N;Ky;}}m9Zoj_Sm5~0_4fT%wJexmmZd(<`u+2` z`(eJtUYl#NSKD9HmFVd8>leFwKR#qG*tP|z-(27L^EStGLwxw1S^JvVx^`b29iKkz zwpdYk<4?RZFXOcTHFstGYr5XO+&y^xu$yAV_>HYnUoFq9{lLyz8yo9i)mbZGoDQvo zRW~+QgDbH+9>?9Qf^EO-rC`<&J-ZH@a|FDi?n*6+&(&zS2-2R)6Yp+p}|O(q6HW&J-@w8d!M4E9j-~g#vB)ariR%&8zsF-H#v)SS|qO9 zpaF@P2&ndb^vf@YXf2ECn1&vj$*&3VJdz9fCMnYPKD9oyzp`1APP zYxt`rdWgH-WGK3zhSWYj`fl;j;$n1qm8jM3_p_UHa2a*8UJ@mrlI~=jl;?`k19X=mLK|gI|;00xlDE6)l=xBm3_=>T}3NzI#-+hmZ>I z9=|$!**V?&Vf)cv(u;vQ6Vc&*=f%5MW<5_waW{E+@Y*cp#c-4k#up3Xr$+7D9GLqz z{}|L7{QcWec0C;P68uH+sq{kqd2^*kzEIfv=Q~Y|S2-JILz?60OwGLe!COof5o?p1V?_WRMfS=An{YVuLdU9GIDuJ(Y}0@s(0xxXAIr}(I)x;mK* zhodA{n-h-)ux0UiHW^2g!6a90f17+7kK(g0Z_ZDhN=io{9ERf^lISm(fD?lMA-$N zOB&x8eI~G>Uw(OWp!BuVU*2}0LAW`ghVc7}hANLF(WvP3=*P|>dR`d0PbXuO22eh; zI&ItM&S>-|zubYdMMoEY#kQ6|D{`y9H3BINOjR(1xi(1RQS^`6x2ON8J#+S{rl>YH zR43Yx)M8p|>7c8w1lU=klfS)=U}qCJIW^q~UKK<1y=*9d;4xJf%eg_8E{!6haUs&g z)bHPlDDC2y{`Zh2Ufr)unD~aL1KsU#lwFSE>t%BkkP4Xw)QsY2n5hMZA!k6dP>7hQ zDQD;7n8XORuu#9|3|k$kZjF~g$sXNNdafuRoF_%$M$kB315F!fJZ2nu(#-}vXCPxs zoRESHCfDbxMug?ZSLvvyN;=a@L&6OI7-WAot1eWF| z9;p3Th}AIiVbV=6QZ?6&s zym$wL;bfdYgFnBY^q=E@`|0y&SFX3Xerh0U@bNz!0VW2mldJSIM@4z1c;Eb24>jO!{Lle*mPq)3^`%f<5L9=xmU56^V;Sx4LD` zO3(+B{$8xBudVFwQt$5_zRzPvX&@RU>f#KxS#bCC5SVxI7d6T502XDb75Ejo0;q6E z&IVaYBc>RwBNzHYFVbfBLBJth9lj!M$Zjk9pz>sd8>G)E9^IFFB5{ho%?s=kKEbs( zRLA*O9?N@|r>ehunbwS4RSp%gkS2%iurOpaukU?Tu2PvJ3h`L3W_{aKD{SY|lKzqU z6RZ6AaabJqm(h&%Z7^Hy$$_$jn#9rG(SFAiv|?jeZ?!t6oHl8}{=AoTEh&xqy6aiz z`1t7fY zR_b}t1!whI4%b5WXC*HThad_87*K+OM9iX=T85FBIczeDKmFuV@hr7^ zc(;VAmfv2VXZ;3zGoT-x+J3>3QJy5S&2FYfN3zW*Nh&8sGBHZIAcR5x@L`bL(B|Z7 zR}M4$jBPuEQ<5!k5vYJtI36Be8SI+dP$%o7lGT!A;8e%n6qCy*U1;WF((m6E2m76K zSqenvdyi_kN_>F;HiE?Kiy;EnpOBUoxQb7$n8~;V?)uZtj&s$b-+z}pUkx-!2P!E+ zDJ|Gf^KJ|hIZ{-*O2kecIYQHn%*CS|VnwZ4bD^3CRMKRZc(YRYNDkAJ6rL;6uNZ|> zL~YMEJ1#kMi!98@51l6Jb?8jfdDEJ+3Dfmd_b7#>CdGuBbSSL6rdZ!=hqpWl&2?c*}QIr_CleW$q;_}_hjK)^4WH!giFdL06r@IDe`!Z=DnN_qgyNTkPn6y`M zflFxh!G&KCM*82(HDK?pd>?9JH&@hG>0AIvF*(l@rQxdeb4He<_L8&hL#+*xaoYsZ zb1?!z)g211$@=oF1bpXVDfpCgGW-212(9iYr`$WiQVMrZkXVN-mc4RR-C?wA8Vehi zflEw9O66>*tJSnGkN)dF|L*>8|Hb~&$=_Zp6|ue4TwYoEj&9-AL-x^ZHJj_JtN+zh z|2Edwoc}hPt(BFH)_=8Bp|#c3=E{otzO~X`UHPx5`A00kL@~or6#dtAJRVn-oA&$v z(tqX|<;Szm;r`jt%QKYVLjPKiMB#(iuRE`HUq@yC+OqJ;+uglRRQ_*87JhfQ_xk9h zvwwDSdJOIZ{=ZdO7@TP!=%MW2nk@WMHH{i>$-i~C<=5}t9F~uHLl)kB^{TS~|H)Xe?u(N{)`_(NwJ4kMZ<%OLcq$t?(!fWmX_bP|s>>&G5l@{J`4?l(pmlk$* za8He6cfYiB+u6ar*Y8d$rnu5{H|6l<>w~?r)m!m)@a->EbkW&CWz{Wg(7A$z*WALDTe!0B7OvdE6=w%KRYg@{X9v;evZAoFgAjIC@o&}HLCj-b zQP|~!j1JicOr&JMoW zJ+0c6Rc8l(?EF%>&dv@Vy{x22t6Og2mk?}K%IBROWKf#Y!p;t&3v>A})|?$Y?kIL# zF3YT~xP?K4DJ2DK9v}RC%nrmYp4ZRk_U3hD$}Omu|z^!Piq-c6RXfl$MU6DrfO3* zJ#FG}Z?}9kHeG$NdWM_M4!)~iyUjIkyQ@gY=DNFdL2c9&c6RW8jt&mbek`Spo8BEf z?Nrd`%`I=~)JT*@7#{al(-Q)B-<993EoTQ`zCNnhlW5D?!AeS}3a_~A_~6a%aj9gm zk3tK%avrRsp!_0Cv11Bbl7Io zJ<$7=8gH}ZiGiI8#jVwJ%`%-zvfF9~G>TH4y476uB<_xqjmz71bqWX^sv602+5s+^;eov|KCAi(je@FRq#9)$!50w^gN`z5HSK zr>cRsTtf{i%oT0BmYSb`=p0v>qC8U#1oKywUU4OM1XU<6z3P@eKB%yZwOnh>-fop@ zq)M-Qv#dNPuD#}TT4`r5F|AQm=`D8!0SLarT-p53t5Mne4Sn{+QF?jB?pbLb z<=JG^rRav`C^{HK!+zWapM7W}X2-EXHcq=qBLeR-iWoTWljqel?oIuB6W>O+*#tZn zF0-tMt_I+)kbF%0%U&7qjR7z0%k*P1fM5sk$W}j$@}z%(HTlOV1Gm21ub*FmyTHXL zN&2^qh~q8d58w)RosGcVI38d@XoLOnAL!pB?G<>D_F>%y5F?S3Q#yudsFh726bRkI z!7qZXS>5dVTFp#H2mJRz?^&cTYvW_oTE_neTe;&UGx(DK`aar;{uR}3lf2f5YS{q( zcdUM>QIsjPnQFIg2-T8a+vK_fzodCDy-ddoP@)b#OAA!?$)lphVcbeN#`aMLTW)}-I()xGKN9ahEdHPg1mUBq{cyzFLJzV(Q;F9V4 zx-;sQ?#j;M%dCr^#}~=?R$a7@NnhQ-V{U=51z$Fxjh04t#e}BEZ+2hf9cdGIfl}pc zMJfu8Ki5Omtoj>+RR*J^n_Ujne0!#M4qea(@-Q3Y#i4=XS;%=p5DEbCK#DoTy)Tr4 z&(K7El}-9R2!|TR=*6QpJJUeEV|80klJN=7_ccs+q0W&z>NfRM;~3hLp%)N%F9Gf8 z-eNo*lP8QD66<9yoa&JeF_JBae&|C+9SBN-n5%0=H_%@QD^To6ZWkGA=tT}(06FH+ z@yB~XemxN#9_On3oQ-9*i+>dp+Z8b-i0qc08pU3PJSU&`+; z;(nf}Z{>G%-;``5>kgOJTWYxuZ}neZP#$ z?%q@VlimV*V_S3F*s;1=QSUtJXWf`Wbey{fd;yvP1R*$`s&qDjP!}DDpEvmCLi5K- zZ|OxJT)M~P;TBydiiO$I`an0~oI}tV2H0iSL)FdFIK5859}trF1icA@7-E2Q z>ur6$^Q4Je1s}fOdD4F3?GlF5E=8)88$0i>yE;Z{NVU4~Ds{+XMMau&sA}6(b-r$T z(f913h)w`{;ee`S!(`Biy8R43j&U8YSyb<`T9bAOlAmJBWvy;1RHvViV#(V`A5 zc6N@-oGSiKn+PICu1JWp*-kMVLliCc05MmGQ1{OD9qyekJ%?j@mP7TO9o3?_GK%^h zoOaHRew2md{d0AnmxnLL-?#zT@Z&{4zRaV?y5_;)bQCKAX=*^Wy(l>iKkCK<5Fpi} z(<=2Mi;z)+nAGSdRYEKT+K-_Ra7aCkqzPAsc4Uvd#u-yt!?FYra$^_Od=q zCYLppKs6eNt8&c~C}FBPHE+&<#DOl5J0s?ro%Y#G!i&S@_9x5m! z{DU2h7C%a#Y;`ERrgc8K(4^v^3m*->+N)#?b(y-=>)*I;=A2MXl{gx%EPQN4M{myv zO$~;KU~H}8&>PX)6?7dq*b}h|)7olbb2XNaYttIpQ=&Gv0(9*XB6b%fT^FN*>jhJT z9v+pO>tH~<={%f@!p*u9vx93cbWmP#xtMlvzwh{?D~bOR^Vy01e`R%CHqw$v9zj*_ zEd``mvTR^LAh>Xm%b*xQ`qTy4VAP?%7KW5aTMW{kI!{QLgiR;ysrDdFe-vF4Ur+=Z zcx22%D(gu^(9l>z-(&Cxv|?Lm0HcU4&Vmx7uG7IJf2o!R0U4C8z)>D!(IlCMI07G8 z&yAXql9;9;?74ms9b%kJ2lkiaDOsfz=1D4SJEv1H4u{5e)7+W(yobUn5OMg^I>+! zt}82@`S1jHaN+T1UXa>S4Q~=H5OvFc4vg?&kGyHv8*`v`U3P88O_xrKG?v!xPR3U# zt{5?n2>@t7m%lxo;6}tmSdY7DE-q(CQnHs=758h~X(WRB)c_D-fUs5cRbd@SaUCUt zodK(u_WRD^BaTvXfKlKss@{M#x>zQ|WR$1*7-3D4F@~wK6roXGP-5+Zi9$8++(KhT zF(4=mAICumU_m#+51Pf9dD5@GL z6r(7Cez)wc8ZWGD2&~Gcf$L-(FVPs$0l~Ys*dUVFp1F(*334CT zPC%iNg+bN4;DNwW1Efx#POX9gcLdK-BEHm$2iH-PSzadYkBPVxuiS&OC#t9rU_n4r zeE2wtdwW^-Ayrou#Dcbw@0wp4vf%D{{u7Lx>`^E}gbOM{Vr9gtf<~H{R`4(pLZ>RV zey0{u*k7~pfB*93A{Mf=J}DO1?Zt{NU`Y#&`-?U1#l7Chf?OB^yR)PDgB4t$s3FO) zfxEpP?IDO?yQ5Kj3wyXAH?-bx_Sc9?LVQEH{cQ`{fF7Q%HKI4We?NP>`>JyiLNtR> zGo&Ng<0RSTgQAHW zVpBZ4rhX?g4CocLj4QY@rR*V7hnX5y+&nmPwu%gT!9_I1KybAuRZZ3XLhaIDX?vn) zQDB$Y25%0KF?lr6y3z2Oli+o5W*!ANZyCqEJEsNe-Jgfax)r+d0PS??#YKYcA$l3} z2!{g}xFpK54*Qb)kJ`XzzjO=_m45(_AM5E=Fn18#$2L5iGVR9)2MDP}yyH2(nB zpRvn&5msXaudCbuylswi!}Mw921Za?UeV@CkHDh@%&-)a4ew0inMm--ly2vAj`%>F z@awXIX~bVpUH8gu&q;XiN=fg+XC9PqXmhbcyuw8bMDLHGY+CdZQrpx5J4c7VAH96} zJH68W4sWwn#1BYD?vo`g*W&jz(RfYMI8Du}sFi-VU~&`?ZRyz-n^J}FWmJM!79LU% zl>y&>GgV}i_Im2xqq3hT0Dm`T3h54+ZN)|UrVZ5I>{(NxrkJva#-0h21isNp&E(+1 zm$l(3Jt9XbODf|rSmvS6+vox+ET{u`tHuGYGU~49hU#6%9{`?WM5}@XF1x-?$76bb z2KuR{h`bxtikLT9dDL2|*5iEKpw`YOW2AdG3{?z`0?+Cv@IdV@`~Y6^0b6!pbWboT zEtk$xxCof(A{Fl;a+W(uoTC~(wN{+sd4kwVBbequOcNowfMcjL+Ra9z3BgMCfP->l zdV-1zFt-Ekj3HE&I@M1vQvlP1#TaCRrO(MIBLh_7wy6qmjT#XmF6t>TRv3(mfYWg0 z0;3uOd{jK5wxF8^b_y>?YLqv)V`{_TNXCOM{5^>K<6EAl=5%`Kw6wFUZSpEiw1*5?BSeO33*` zmCI6XF~P23@Y<#n^W|dV`!yQ@CQ%V_^eUz|x z3^fOk0~URzJo%Pd5Nc{AbN{oL`opQ8bKW83V{>VeLDo{HKi-i!JS1KFgZ0jbz1cx1 z=%6!1ZA>Z0&On2^Qhf1jtnP<%h^M``$Nii5Ha`Q8+%w&py84qLK_3?OxvG5ApNa*T zhG7VYBF*ld_e3))#vm8v>!jP@+xVrr)u5f`sOMSeadg=yj~`7TD;5s0|IgCFMdqy5 zDJ5SRs{hhl;4dR9yi5l@EP*~@_7POvQYdb(Wr2WTw~%D%?MRWgu4~6Cp(Tba)VgWU zl8{hoNknSkUsPSZEsKL=QFZYZr}b<+05{{x8mqEK??Ne1NX@G&tqJm38-B2bzeqte zotb?3Yp&>6;VZAPG`V>NQiL8=ZVoJLuqiFPo8bGU=L1zmdNIvFn^RA&3V8pVu)hbL z1?nkQJqbsmxtfsPI$mqwJ{J8o`0X>b=acJXly+-n{RJoJwxx~@IE_8ri1#l*k*oHB znqgdN{&tjJ|Crp)GB?Y(*Jbf9MG>u>04Y+Ed@2&41Nd4Ipo8A0?GlP~fO!urMZzlO z6bXudHHwrc{~Tm<(4?sptSv9UOTog|p9wTfbLsgISL>@#26@-9uK|tQzwYP+t}coh zQ_Oi))hXM)H&F?!&Pw z{l~=ZqqQ00XrvFiY4P!6@8;p5r93UAcM<0df8F&iKD2aTui|8o{&V79##wKfKdXA9 zFj2F-1U(EZ_cb{v-piR!v*j3AFB?$4jGd#-86-}+$AyTZr%zM+L7y!mWrs?+z0=JB zWbX8GaP}d&E#9A(ip8nh^76+&=k~n((Ow=HO6lEE1^>XSGnZUF^`5z6HLTwpay582 zOcko_y&PwM)SZ0!qsQfbvnLmr<8QzmfBRmQ({k`{4r8469#1X*TY34?n-7Ege45Q& zv%BjybXB9^_WG1)ad!;|9 zL#W?;YrpGw*5B!1%xf(dt$qb#xwey2TX!**OFKEw%VGymzNulB=P4)4r17TbBeJ=P zz-3BDnH#48b}LC3nZ)|Kd{=FnGwU_o8h?5{+&_Pv&1aDp9sG#~c{_@Ejq!TYWRN$X z0>;{6G_oCY;cW}#2kmMg}Zp|2OO>%LObjK!n z*gQ`~{|;B6xT1gbRq&lX*6!kQamU+o&qM#P9_(%;KHZvm-=Np#dxO5)QxNA8qljjC zTGYu;)GaII_QlZV1xPQl*x+b8q1jcv85LW}$GvP~NAWDGmG6wK*9Nui7vj~50w?MRkh?e@~IHs)z8ejJsKhV3i_n}d?LK|Kk-%+siY-tg`xcs&3L#J|@&iK4My^6&tiBM;p{CX%s&?%T&)_(#XDjoNdP8%QS;8dM+Nbk)z;4V^c%A>dI!ob=8As649;C$?msel0)mK7R z8TlUmNMPmYkN};$TJgTL%h@^+kp~cZk{&wTD+NkqQ2x#t3Y@c_l2Lkb%OFWwv`(D| z(@#5891hJ(2$WfPEXF!M@52xE?dX&GKT#BT;KHZ6FdmC{3Ug$js-(4N7TyQ7 zK-kZ+;b}HB%VFOe^gCYI$o3G=PgWXf>1Wk3zS+{>0Shr3)alJ>$9ZkUueSLI`&85@ znA`R1KXq0%yBS}-(*5&UY}j_Dzdda?ME4c1ZeM0y>EWoI-OIN8_MgRXxqgc{saQOdgqwGd0jI~gO zhkzM2GJFDR3OQb5p ztEC-SEvb|ohsstD#%l7R!EDSj+v=rvsJrD3H=|6khQEOFppFzkV1jBN<`Pv6h2rx{ z`NWj9a5%**tYTK-Yi1<~Pdw;A^hYIyuxd~n>DmnRM3*LvnOU1(ovZoPLa5wy70TC) zX!f&G*j94}600fXmq<7x&AKmayHFdW|Jr^u<0=;$u{dv_rTpv5qY_-T5USdj|71}4 zzcl}gk_|8Z!2B;8tE+3PBLB-eeiRd|=pedE;e9y;{}u$g zP6k~7GkKFKIZlJ3B!epeYryf;gx#4i_YnbGb%B6JY}CG(3=kbW?t`@vKq#^sicJLo z=@?K{;z2JS^&(ovh5Ey$jad{BuCy(btfn{VCkWjEDLZIZfS80?co1(}yAPP{%_rw0 zH9J5qga$7_8`0n|W)gea-GFz|b}5$*b_erzP{xg<=b+F&jUvUwQd%{$fVqZp(OrQn zhT0c1K2y*%g!(F;mz-C(5nbp%a{b3g^N0D30c-WYk6hM3^5g0ObEH>UGf8I}WR6r! za6q-ArKRZSZ1f>lO9bXk-5DIptC%(dkw$ca6t^Ys-_2Fpy)qy>V4CMMdOiXCF@c`4 z92(TM9aD6YUZ?#SAx-Q=@!dZ+?Kx&XzgD7X)(!UlN%Rg9D}V*- z?PI)`A*4=FQ=$O`TM_FT9cEmT)>9%J86Y(D9f-T*WRzDHhkA>vZGj()$lyy`S2$M(86mDNX&kBQqYtc`W-m-ryqKo7P-6RG%d++f1 z14{$K6AiL4I%**O3tuliSft%MHS|-87IJ$CYD+Z;V^#E#7SNu7^Q16VNRp619s-L5 z6%U7_OwC$R-2N?|O?4vDq~BXE8^*WiRDiq6%@d82fnbW8-c& zffPJ30z{{|g=ICzfV(TqDTVw)!vx+DVZ+@+1nyG|9;Mq=*GB!Ny3Wgo_JoIaV=2J5 zT{^7b2$lmY0Ejy~IC!JEV*D3k{|(%BI>^UKY~E6#PN5-_gei(%Dng%pih+eH zRgt++?c3#z%_ndW=$ky+*d*ZS;%QAU2YJKcX-+HMTI0#mle&MHe+KkE_DSn;PLo%A zd*s1!@^<%luR+de`aS`OFJ1W583aIF5gz!!@pt3Gz{gJB9Y#kd(du%maHaZ!!{DWX zqzSib|3RgXb(X5q39)8 zwVV>dSM^c<&g7>|#>cz+2Rc1vi(Y2wl3=H5FTd?IqHjN`|DPcf14%^9e|!}=&B%<+ zZD{6YKZ}uk46_u^#J3l2jn3a~KGYSc(fKsY1_0-dJlfpM=v(sl{kG%Qf7Lnc93SkF zrQ7Kd4TD39UywQq2v# z=0uY2b!d((HEKz}&E1mwzZ{yv8~C7nJBY7AYE-8NIUbUY+|>W<)_>bM-s^A@?oFuw zHW_shVD0w$JnO3p-?|m{e%L+Md%lJK6J}z|K=Istf?P8?<1iF{r!xb>`zeUP1ITlx zB!{khVxbvEGXQ67ya|@kG|*vn0AvQHX+%FQvKB}Dnv&eM@RWj3Yx)u z<#;RLAhCRm*A~*l9a0LsZ~x|w=Je=Couamdr#;q9Q1TqgGC*(G@W|~><#_M)!3nM2 zTA=dDsEej$RY_By-GS0f#xHKiNsT4?&871cyo!M~tKr%Ni?G+=r)hpde@d#nt=sE> z)5ZBD?W-Fq4~k_xDBA$BebRdZi&*=%r&tA~(@P-r-8tz(fYCTWc7zCbhFfVuXI4Ot zjFayqV~jbE{-s?|h{>U7a}G)tdWJCPBi4$>Q=HGm^%$Cy8F&m2NtI%Fq&XSD(iW#t^$pp zkVxq)`|V&(_Cw%tUOO;^l#^#+Zo6!t$eOrOuIh@Rk=RcXkGfZ?r+y09j*tU3&)DxC zbI+<_Y4(+=`e~9o=9bBw)HG?5plbfa#HDG5XW!fl*>IeypPv{cMZp0ZvsC@3)2k-a zGgbXtu&NANEv?#>Rgr^=ho0)H8C2cms=*Z&xv6T+ny5PA&1ufRIiH~FdUe(KysJ(( zq_zE|x;0h*K10>r7km4imr(WZvg*YXD@2gz&XQ8XqAtD)xCZztFqYGn62vY?g#NyUUd{?W4r);YbGzWaYm15*k;uj3CCS!kKx!_xqVIPiC=z|Ic4N8u z$VQT(nI!L~DTyE^R4c*MpAqJ+g%Lw-ngsHbiIT{Miji=~O1^@235%Gdb4X6WDsG2# z`e$0*O$UlKJtLz83~DD@S#GVi*0yv3vW7ep1zOASJ1W`QX2t2pcA_UMPlRb1BTYbx z>JHep-yNZ?S8+U))WB>4(Qp?~N|#PPb(5rr+I(w0T5t_5z|_+VrM0LQaY0Dfh}Kt8 zxW$dELwZ=984Lm6Og;oZOQhnem&us20>3^we6@e{?#1iQ+37DzwQ zJEmX0r&DPyVELy{qvty?1Cza!lh)Ec?nDc!wfZ7w|Apjgre!MebVt|VgL#eMfQ7Hip!KM?#oMDAz{ly6XKEl0af{lP8dT7^)` z6E-j5vxKT&LmBuQ5-Kfwt+c&X$S_1NIl?kPDZER}fYAcPR{_9%%V}MlX5>qs zU9e+*g;;8lRTD!^!fEfbQIBlhv`_J5oLwX7!i#v`XV>>$((T7!YDaYupU@IW8lW=; z#L;2#2<2Ou41AjTksoRn6#c=l%!NgmTYUjO zEH-Rv+{Fe^xQ5VDbFg6|@d1-HDwx>9qT0AdsksF#gM|Y~iO0D`3P@HzC}pYx2C81t zYlK@uy_2k1@M8S!lH~NH@`~KP>fDyJ^HLsPo=S}HA^NPAOvRj0sARZGce||op=;ge zOL9@{o<^)_`Ea~lZ04;?_JqP|sXq8EQ-Xyq02`QluP(>cjpd2U%x3^34>rr!!PP@5h4=w!W+$ z%}_n=qZwqJz%ko)s{dt%>cEVKac?^+44$96a2>Uo3m)$w>lRvN(TY@D%xrME?e3=@ zPrqb5#+C_n@qdt%^Ijk_y|MV1#}caQ3wEOT3RKM7a0cL5rWfzE~+>taI#j=IASC1cyn@1db&9C&K?c`A74~va<=uqi~rK z$IRaZa8kg4Nwo=z!O*Qt+)MGPXt|uhbosdh&JV?E__a>3i54_6AfE2&_ksdh*U8+W z-Fz5#lN@bmwP@~tHL0DRyxraFpoFazRBF7w)T&qLibQJQEo(bS@$@4XP#ZjFM7nq` ztXGcU$t4;2C+(eH5Bwb?RUG|R+guCRtXDX+dWV&WkzND&#rig78YFfvnz_$LOrc>vzSU&eES#a|gS=P5Rt~GwN|Qnl zbbf>B0FurENGr8kgTgHcPGN_cp2iVJHmpBD7{PY5(A`-8fdccdZ%0p`!rvC=y!*}0 zlW(7R=~J!^h@x(Afw3+w>`$tcg*(@XchntqQm3XLKZZ`gms{0%`c#+K;v38gdugbj zjfXK!PwAp!EI3^93O`qe^Mj9rD7$tN+)Fyr3iV(6w$^C5ecOQ+`a;2QfDR(4e9#*U z%ES&YhzcxO_3yA*{n_wM^#%1>`IBVRaFu2B@RF5D!uPk#`15 zeBYFZB6twYue!-4l1aTxHLzqfkpNnap7iq_Fowa^|9kRg+8F z=oIcl;wp+sMbE9NX{psLE{gosyTW?at>+Z4xnAUDF=|`L>_uphq5W|yhj)oXUvxRl z_91I6S>>o|iQIt18MeY5oB6wBQ$l@;NDvz`|2n-+{l$gXNXViJvW1e6F8DbUM9ue6 zZ-V-y{|a1KnCEssSN%1TKLrk^vz)Dxv*0_TTxUISr5pK2qc2v`XbSQURo)R3uqaspfj<@P{8W{A?_|B}p3 z3&N|ZVO4h7#)M*I!!u)9SSz$aa=5@VuB)2}av*EDJAT(ejRe@0&V|o`|3vkt zRn;ZI4p(22)j_EuM+MtX)j!F9ZemPPiFwTYVQ5BLG7C7V)X2GNU_c6XvoIGp|HXf@ z5q5@w+qRJO`*l_^liqC8@h-I0KfRGynWSt}qLNLaS%&{%cmTWN_T<~2@h6v-p=ijD(a#(LW{+k)vep}iZ^O5OaRXs@h8eC!++Hc>QR|Uw&Xso6 zZ~yYCAsmZ7^CqL=TWuD2c!2X`t@){0TQ=>$3m6c%!3QF9m=1X|Onb{Rh8L!1#ztCH zP^ebq^Dh`pDTet59K~{Qz*J=OSwsM&7Z;kvgLwydRMrJ+=YnAMwPv$cZ^)5?lex|E zD=J?lpQ^{JBpBum;Q6+*vspO<)SMjvhyX8Q=dJ<*%;Ey{yjXv12Jn5;2aJ&Wyi}~< zVm$CXcYs36Ur;WvC(rPQx~%flsp8hK#LKA?6|0osuG-XwCr12#hd` zRBvg4Dk{yVUM_(aiUuVBHc32o%#=$lA&bcNN6BT1PWkMWXk8M?W@QSHH=rVoNzaXa zH!Xl|1l=*ENDMBFMrzSMkD>s&Y3|6QD}PnW`y3`fW4Xk)D015H!t@sxmX>gZ>Z(&1 z+^^#FN2zsLQ{s6u3hs@uMin-P2IXR0fM{yAe@Q>zsBfQ>z`C^L zoD^qjpqWftD`b*z9>p4c@l`H3&2_i!Qd9PBuZK1}pH2nHkfm0-kAFGM04)dGck@%t z-9qE~+K4`FyZ6K%BOakowr~dDz?%NreD4!1SaJ2sj@v}E@M&iOx?}sG`b((>?s_;K zeYw}RJK{U@VKh-cbHD5S{jK*6yUAI8ZQe&5MoTto;3^=-NH0BNg}s}?K< zReEZxTu*IzB-BjkdvK(xyF|>+b;&*qJ(|X03K&H}R#R+aW|ng&rc=UpLhKp@x1Aju zv?Dpob7yInmTXh}LILfA!xD&HO)1YD>lX?U0r%o$Ke_=AJ^jRwkA%(T)vc{95UJp~ z2VzmvWYqgc?tFogHFWu<($)cGG04e3AH*(vcL3k;=JMLiU9U~; zw@gOTi%zjwb#eNh?wHpfIpRa@?7wMUS${M`sTG!|?1!x-4CrJTCm-vKi2VY~^c^tynt&S+vrSDub zIGw#u`p~Nu-D8Nqd}FUem@bEIhJTFdV9j=zz7)qG>7X+T{rIV-@lC*yqIeR%Us~mZ z@Z7Q{?=%R5qFj+6?p@G|94+BHb4jDPm?bC2??B8i$S>Tpgt6qXo@OMq2r@kDFmf3} zj>ZTW5`~ota;VWj%xu8el4Vg}$rkJ|1we&`bzk|6cEE& z*l06L9NhCA^&e=H6qFr&kgEGbFFzrb9;)ONXJ3lX@oSm0FUszpE(DF zXp;7lL1KZtM$=>WEPc(Z8oZ>lA06S>O8)-gLr`&};F_1;qlZ1+yvZ|fU_YKRukhja zPq;eZe7gVdKGlZ0o3jajSJ5@s&h=|EfV9iZ;$PnJQEDlR`Ag_q^##U=Y9xTss2{wg z7W$*#l+sR}1+fyYlCYXZWM8K?Q2FmvvHH`H2??Pun@{r4A<~Mxlh5 zEj3tSmt{TrEqyz!rEo)Ef>IMlOQBSq^t78YMojU;JP>z$g%A-Y(Gdwy>DYOKaAOFZ zwrqF>h87Tl1H2H7IPe1$McJ12juqaN&f9=dN9ejZiiM+X$jP3-qZc4Q#Ch@zVZBU@ z8{PF(N974iHaq#s!GXaS*5xL__hXm~Jj_P)GMl>A5Xx-!udD3yYK= zDlaX8j~=!5^y&MeJY+V|@i2mpJgY>=UI^l`H3Kd#IInDrbu@gVNB*O5cP?!W^}rFX z&*Y&3i|P(U!fsb9wx+LEbsvmO@~rr+c$4f>>(uvxQ630~<*(lRV)TrCPRjg>p8Gx* z+J4j`{}2&^K^`L5H@JDgk_PuL;FwfU-*n;D_N>N%;I3nwzqec_{{LB_LAy2>6y&W5 zvt4gJj0L3TzlJ%wo5kI6Y8wv}&*mMlljq}+`kQEb)owWtXR^;h-<1ss>F^i;h+ ze8VGE`w|#qT@A9W##aR57cT;3RyT8c2-E8g;y0<9QN2Wlq&IvH7+h*iG0_C?nLF3t ze4!J%s-CeS^S?2fS1VfFlv%dKX{Nhfv0ddQzdY#J`N#MEs+imNTR?TY&(-}>d5IDK z;F-9egxs_^r2oqMM?c9MD4pFSs|B|6IVS`x8xeK7QugZqQ}t3((~BK{-Lvdf8ZVY@I93pz<7MZ3k|7N+1DAq zUl?Bc`W^{G}@f& zE_#aj$3KmWo@$YHA|)WZ^V_I~RHB9of%WLC(Sp}xyeIfhXdq(YXsKGP;a?D>y`Mc2 zwr3rYFYL-l)e7o^IgyU1$^aw6^s>+=<74CM3&^6dz;j0;GAr-4Wo3P;vm@itO0Ne6 zs5L}c=N9k)mv&@yTiNTd9c-uz`n6sbIzV%mGcCpml3X|2;(vDJemlalkC!W% zay8&jGTkv>X>iuUaBTll%iwgDjx0I)D*zxo)A}LWpgNT5(?BLL^cs2T+VEI*0YGGG z%&88Mo#cAzf&ns$1%O^B7Oa|cDCatWyMIfdmD%M8km3pK0NGo9`G(rFI28YQFte_L# z&u9}c4fQk5gn&A5P0b$L1LiRnz?6{~7`OszwZ;nqyF!9S=xzu+NRJ8cRN-VT4&Q*D z<$u3eSFOTT8@^F85`h;0t>Lyb(h&ZN6Mkyv4l2@f`U$r<5<#Z$t=>6D={B`@B3X4w zbg`rjDQ-BAExZ#P&te-!B*`h1!V|T#gMY%6a>BIq@7$suFyvde-T6YJsRYuZ8HYo1 z)dB1dZx>8aY7YBv*gB!)I<6X5IzX>wZ=jagetF~%TI`WtILU8#+e16z9v?lNP>Wht{PO6FMT8Pp4FPy=Mv$p_6vgOmq0##n>N-dL$BaCu)IF(l zJ`IW4qJ%7Qrx?3LZN%9}4_&5&)-;R*84jsHW|pHj@hvzOAXu*ih&f=4&qly%k7!03 z1JuQa!Qk~t;!t?Vf&5}}(Fi>NaDHUPUWfrfZjy$6kf$^VhC3piC~eGv?b3bz`o4%( z^O-1*L9CR7Q{c5E}bAdg*V^HFk+ zaAOzW0;1_~%(Pei-{nBb00w1I1BrpY1z@oWChf^>cq(W`*$BPhF>eVb*i(`Ox=}_q z*ob}rM^JM1QIDfqqo$!TU5`7^cp+&4=E_>Gv3zEuQPmmGv+IP%6gc5#b||_ujCKrb zS9$8iIhPk;o-sc!*DkYEC~)e z9-w45+zw4+F&T}n^UILR&_U!g^`ptIhFJ))vO4tDu3@`I$ab=J@oFp^(c9$}uw$cc z;nGAjNILdi^MFaasxJ@hrPvg)oU~SYqE(j(`uba{>b=P#vzuAA15zDB$cT@L?&RmFg_{ z3!Fk+r`f3B{}cJYM@lfxuK&RN-_5nP_4Pvj@7C&n@_+wv`M;G?-cs7maGW5GXswBq zAn{~;rS5z$&Aa_Ly@vD=!`l&NF~HjlFTF}3>n4~31+s!$O%?UrsGnR?a>=xtG>BlJ zJri)mayQ*FyZ}Hhf?h_6xIjw-B{}(+_Lsdf7b!huU#1^1WjNAj^}{Gn`WIM}e~dDS zc+LI#`4#2~RrehdfDJGY0;je>jSe%BLcvP}@_NW@-u4+)sf@skzzUXg=Jiadv~e`d zlSwaIqHD>q0Z^Ub)yHbe3vZ7PU)6=7L93O=vJR=0_`s`81^h^DI3s31AM`Np0HY1? z1t`;9DGikx)FB2Rl3QBzF+sv%K0Pb}(;CFrHj(asAM~C@nzS@NMy+N1e{k?tziV!) z|5JzVS##yt+GYed4HA<^|6P%=)qb7jn81}S1pr4FM{ugt!czJ~9uox(n?Ak$AbK{|DwamRddKjaTR}rfyH3( zz^vYQZTLb0uXoM>Pu7k=kJKna*DtPEk6XhBnG^dTiKNxm04);BMe3)cDn@ zY3Lj*366;kh?o%^R?W}7L9GHf_5unyZpO|r$~Tnc0u$=Qy_^Y?ImIR80_V2HkgJVM zbwG|be9_&i0%4t>3F#@z9blTn3tt$?U&24Klbu(&5&h z8o=zj3HhNgQ3q;}jqOcDMx{2kn}{GN?tXNOG$sS?mn)J3xqAoQ(Jk8&M>Y!((h;~m zO6z;XSeq0_hCd^%(AqXmak@q&1(T_=k-=C&16>nZl$P0Xo8Pfgg@WjcN41=t32;VJn*r-Ym$ zpt$hDr|R}IF^{91c;boLq=gT4f%J-=_1~-ZTnBq>CZ`auR61cyt@InXZ`kTj)o4@W zU5#!i^cxj6zqsEVqoZUSIo<{`W`i|FdU&03Pj#e~%t9lR#B1ho^Z; zIR+|X4^XPX3}$qPWN?Wx@gvzFm1RNCD@twvaiq#ey^+$eMv#R0krFFF<+_Pc`57gB z6xWpcXsT;14@AD-lJ2;HxTw8s@MQc5tAPRq5M*k=F=Ngg@4t9+!g41u&o{R)eAU$3 zEFWKv67{L^2%(ak30#v$8p`&VuL1@KEMCo&a{D>OS^CP9L@VCXMUe*Ot;c0~q>Hqd zKP`VUF2iKWWWjuy;>=l^vu(;{)~l?4U5OUdyoOm0kh8aH1<;57B04~QI6+_9$*>oX z6DuXum)UtD=_jzrlmeb;By1C=V1v1<4@%`o9-S*u!#=X|daJ@2sVRAEHSxlNS=%zslL=uw%U3mka7;1yT*i=j}B-SF(*h>ql7pA zSc!7iL$yXqY<>j0q0cW1{ctJh45GUUE^PjtT9HIe^}F769~=l!MpWZMe9Jhx>}Tid zO!u?y2fboyf76jw#%VtqQFi_@%_e#Ow(*EEM}h#Q6*K6NlgXkYGt#Qna&!U^O*cxu z#1r($+@83fXMpXM#3p;C$fVP!>CkzBOZLdw2@qGi8NgR8M@MQ2ctSBqv*${lySk1? zAJjSPDQ0^U=Z|O+Kvq;7;0)54qSYF2zGHb7Z=zD+?>e}CfhPY5Dmblrr`G4n^1Q6UJ7<;wV|px z!a_7B8lW6-?~+v}s8uVrwbEXs!9 zJgb_2B>z`aQbhHSv;VeN)>hPS1^aLNKm7kc_TT@F-d9#hN7DInPLRIR(}4WbKKF*nBv^)E497D7q<;t z{MGT%ySLGcUkWu;=^xO(>kspX-JbwLqoju;u-!X793Ag>j{P3coRaUWI%>7X;_-T{ zGykcY`v)hd2Z!opeMoL^vQe*)wG+JwF>6u7OB{Rf=HQe}WQr&(wW4dq4Rh_)E8^M) zM;8|W4CK^4dinCCW2-k!ZAhK~rS+q+J}yIbM$pip{#!tTVBb(IRF6!E0eloORa8eW zGE{a>e7nDCrB4iADy3}0sR}EkHW9AHXn!57U%#}Ho^N%RtFpRgfqm^J8@(5 zm02R)*zOSC6fk1Ke7|t|yEuit=`ge(;WS=Eq@~90{D;fH7*ML zfPXkY@oK=2{HOCXEe8Bbe>p$$GQh9=r~KKTbTH+a53&fRXi`%qS}K2`0}k;n_=oco zpWYpPj-5_*J&iHKUz<8ht!+0DgpRQ>cfA7M7PWx(tVC%Klmtksg?F&4)KGeqN}~Tc zIylrE{^#`U;P9|>EIuE-J9R!E?w-Co-hC~;dEI$=Dn1?`y!zpk+uV&V0Fp#; zM>S%Yih1qGuFnBsjrDDA1^JF{LNmbw%zc~oNhSe>ZD5o^YEwff=SebP^kj8ZAh9~G z8i_QfBx!ySy=znI63-dF1vc$5H|xjrKdOaO)xZK3TcqL*15L7P|9oNp+%xINVFZi_ zj3#a_5f2qN{&nTO_zL~GLN7gz*Y}Tfc(#qDePH7bDN%P1uj&_l%qSTzwe+v3HUJ$y z?$;X8Mnmju^rfLoK#+e8nZ#;C@6qr2Oo(zQTVlbrhS|SRK{ySe21_g8$q_C4zo&zN z^E;ki@q2fa<$3t`FWO}Z-@Me{v=IpTG2FFZAlk?9h5e$9U+n3mv;3y80x_{vAbl@i z7l1^W@6AiZZ&2&E@0rc%4XS_VeW8X^SLM9?bwfqOc6Lme-`;cRpNO_lgJIS;9vvR+ zT@M$Ah=C(3=@Znz2K^*;=D7a8Q^mi&|ReK*_&Kn1JC*wL`XF099dVmVG9#p zt1|~5+VsIDG#$R6WmbOxj1RW89dWhhwphI3o-VoPmTb$CTIL=fo}g>q!eb&!YO_0| z(Hn3EtW5^+>^&%@ozGyjHdbf2OK3^zKM?t$hK3Pk!x!}R3;lJQzTTs+_wZ{iZ|Fe` z)F3q8n4o`pGmQL0$HmzOqzRs&2h>{4X+e`-9&(M!0{3_ck;p_PfWzh{XvZQ^m=(~F zYGnhnJYJV5K5J2^TQ5OtaLfu#gs;e`gjn9K_8#p&m>*5I!QPXP=cy@ehF0V z06JSZ#TcZ;q57{E3$&N@4aZ468U@86{yghT0)?TnnpP00z;dxFr)btPqb^~~4h&oB ztrCbvW_mQfUbnGzwBpW%1F~57R>NktBOe6%Em*kS5ZQIW ziYZHz=BU@An1u9;oh)^>hF zPYrBs8G^)MwYJSS1B>p6$HV^8yEWN^p>Icd0VU;N9|O$P{}E-YQ_1#>CGCK4Cm01R zI4~~C9kkBx(m{Ln4%+9l&b8Gol-xf$ZA7$5v|~-(YH8UvmTil&g_51WVRKz9*wqE$ zSH(Bpj^OoWe5=&vM$~zG_HvY6gQROzZhb8E13G{7JJ~(lZ|EPPBi)TqZ*A3K$Ai8& z;he-`0PtFfBZK#rn4$cQCW9tKar{MKUbqpBXp{++D3&eYol5$B4WfYxiRC2FQkSfs zQ9rv(yCNn4uOygR;?Y=yFCv3gtt-Y%u6j21lS$aoAu#24C&DzO?WZxehE8lWW3+IR zUryh#SCP+8Zr(Zo`Xc)XQ~hWXh@#u0v~h6~>fd;c^vpmtx=D;n)F`J4T|SQj30B%OYzQ6~rY(4)*hRwtu@{bI@l-}mW02kLwNg~H91a)lY32UL0S{5(N5k&aJa?(3aM^p#Pj6`?^Zf zg-2qn?d%#hwH!ibA{LxWIC4Om2Z1RE$1MP!QVg)?3l(&U-_laRn)=$UvDT68PMTtU z1xj0w$d2U89tMhXsU@Y4Fw7+|Y6)|xRi|+2Bg~H^i$86>XFPNirJ*@BDn-dbfcgFR zh^pAH>L`Py14uKcvy=a<^P}l4DjHN9h=^6(BAB=aH%#!&S&K0mGF}KT@H!6{30})h ze&Fx?!Mnn-9+J_Vgs9=bK=I6v1~_Z}^bYU3(Dh2h>sss_PxP$-+Jqyn$=LpyBBezl zP-{5oz$_-VeEdxqG%{MVOS**6l%?$Yn**qe*qA~#mV4WXge?0T%d+(XG`J%l25L|< zjmT~K@lcyaLvU8CsXj8vf^zc7KtGHi1xbY`2CR39+<5w4#93_ zt!y+FfZE+hJ4G$3s+RR-$k_+RE$!l#yuknUo5Viz=y3gRJ-Q~aUyjcD_?)dKVFY51K`0xLt{{BC@`f&m(yRg_^pcgbx z92m1=*;XELhG+*-(6#X*1m<6Q=Df>x&|_|BA5z%Xt3PN=W|sk4H0Ggxi;*3K$RCtb z)em}8$)6>ojfktomiB$$G>l*QCv=qH<2vXw88|!T=;@|^ zEBHlIWqvkvMKL^<(jH?Sq5bDZ{pMGE+!MFfbK&rn@B@4gQ!gbML@tGj~#9-Jg8mo$=t&1;=y+qqi1K%lnX1+DEIzXqrh=a})9jkq;k)(M8uVBMT ze#Jf&T@YWHm5c#R*h1}$0bRrR`Q>0B9TjE`O&zH+C-}3kD*V(_1a$FZBjDNKM2oA+ z`1Q6lQ`)Z!z5u!rFeiiN2;i&6JYnnkcR?y2ZVQg}699R+TU!h?j^$hqluD8j*u1b= zyZ!>T@fbXK4o*8~Cr4+ezr5|d***EOzOy5~?EGD1Rb{KQ`?C*YIBU~~@7`3jtbX+y z)`zO6#9eS}I-`5=d}p=Lj=iw>0_rUknsw>{;M$5&RIS|p!Es@ByC)(KEU1~3n4hMuP;)NQ&wb z9Sv6&)HOPKdj_@M#2=C$liP-W4+x>lwA+Z@uAJ@va=82EV6X1Brv&q(p=j|fV0t!5 zE)Cm86w|~ou@wh}2Pgw39mJSc4s#_!L*QoQJ`5puV26{nV+=r`$OMMio}^>~*B~8e zS$TWL(*<3UKOOWw;TPDSj)*ll--BFHnw(u11t#^A@e^p{$>0e`-$HRk`);lhG#9Af zK;mEsGH}_31~6NJvDPS!pXEXwQLQNd6~@1wLvGLnzln1&xg?{sOV%;;hgZV8z#|j$ z0`?!87}V`$-HC~KB@0xqmvTHs5PTgLnem9oj>-<>HZVbLKJ|k)w=ROA9Z5qK(`7<* zoa6`numoy2NO0PRNYhn;%P#4LN$*3|o@(-~X+P5OQ@og^B%JF?(v4N@YTNTJRqIz*9gja&Q9B*Uo3J zPz(K!6mM1in|+Y)K_)QJvU{{a|MZ5PCAE;)@KPW8mQ0Qbg=U0nU%JP3Fpc2#Ka=Yr zc>seq<%e|WL@TpMVXMD@S9;-@=u}TwgTzb*)|>EcHY~xtfv8^8%!aB6i6}RqUH+z8 zl{hr4-?NvNFz=*9daO)=yGesr`!rhkSXbgi+wyT34CZx!TKeTWOiAA)*9U{{s3Cer zd!XiovN_i}=8;kSg(R6*R)W( za`h|?R}3KSndejV&cWU0cMNS$7rtHjs0-#leD+|f0>%f_{veGc+Y?YGC&xwmWRq)D z&IDZ9^n(P+6NrK_HbE-}xdEa{z~%iyclW%>FFu4gh1T5(I&Tw5upJ-wZ(ox7x1t-Q z->Lx+Fmm5EQ!u;ZEj@tsd99WQZo4N;``Nt7g&fTnCQn51u6xN&f%-rgmsUYbuYTB1 zo4kVIYqfXeEyz{TG=+vcbB$@C3NTo2!2ytVfOIQ(FSAeIf}1o-0kpK6xHd^r@PhY% zUUa1$(Z~}ED+f1^b z<$KbjV!gTZnGHOZ52iHoj$x2Cim?G;}4~pi(+{x;G z`1HIm45tlr%mN?J;=m_Kp&*no`mwoohbg4(1(7j5!A0BB-XP)qAiQEX0(Pp{AB^J|F zOQX+_PN+xZ#{9)X*7K%uhUc@sL*>7bt<|-|sFf%b%^x=8snE=tAL@B6@WRrW{HMC` zaL4)nIdBh#dg`vKWwkOEq_4iF9;rmzx4K(}!09Ub&aZ*~i&|SzRFqDJ@_ZDJ9vl~a z_DaslBlDoG0L=4F5yfD(rCrYK1gLm!}qlZvj&aXFI&T|BE_)K=RIZU;n)O z%gLD@d4(`=kRPg@SMsg1hK*9W>FI`AD3QRpM8q)4tJ`Wz2uW3Th@y7#QMXmE63%Rp zj3wu#Gg+x@3gt3q_)l9_P@79cD^qU#)3bL2CFY9 zVA0AK8t77MwxUX?9*6hjOV!@&Vg5GoEs3>KYu*CniKgfgKu<_w24KQdoKu_=`?1n0 z&_I{1)a+r-@LTW0r+^9CM zOsPfBFtc78#e5lf3mv2Asz5Ln+Q$Y_4HUxY;4oTX-V13EYUF|oJK7KnJYYG`N@NDK z4Sk6;7zUUcl$Q82r8N}q*jUOwlO)>f7v<;k>~ca^I=p2kNnpQP6}E|OuWZ|YR_49i z*%435r8~v^y+ym!nz~KM_?&BpV<+5 zCmV?&F1Zh|d8C=^j8R(1a~xAiG&F?9VMV~Y`tiy_GXf|L*8AxJ+b4YT1;2iodu0^l+x$t#feFo`z3+;yv_$XO46DPCo2 zY3PWB?m44KXN4>&26MaJaCc+a3Kq|n(D`l4RtanSs-P7ZPSFbw9ykW!1NSnA2 zC5mVrrLdxm9=a6(LR#u27nE0wZx@F$qr)N^m6MALs1Iy8(TcK~gBgo`6N|fJh!e6q z&&(QuG~~9cK4Vp+NaVy_&?_|yvkdHaAZ#(E_>U;{VlwoRXv})-j*E`R%Zi>eMrA*Sq&C?h3J?OboB+#JO@p;l` z8IlXNrxwx*1du#&2Z&S!Jk3IUN=RXqItY|K#9W)IJWK(r6m1pI2o`8-ejl_+6dCXo zg&6v;WMAIZeJDk|LIa*z|D9j^EuV~|mE2RYm}+91UDuc*&fU4EuVLZ2o76nFj5}pX z%pIDt-yspl0yR&!wE#2pkDu1s#`63#qjfz9K- zEq9#cS^uM^qeP}EyszBhS2oj{;>3mSrbRa{m%&*tPzY_b`3SUbLyy($JLSHzvW-%8 z5)3%Q*Kf<%iJg)ZQ+s>7`|8au7+G%4OfNgxpoZxf_3H;EX)yTgb~rJmbJX5xs>lZ!A^KSQ^2&>_e*g>wAFg9HohI8^B;W3}A5Lz4L~Nbs)q^)dJVl)ryb( zqPmPlt?5!V4k*-yag!sOo#9b{)<`y94-v}7=m#cV-i>{7@3^yj+KEngU%c*kk&1F* zwY^M6;O9}2qBk76L8{*m-@WM^AMDZkIb)#VA0PdEuuoocQ2XHUv;z`bpjz${N|60#2b#f-I1c5D$LI=e*-#f9=I1o*M=Zh^A8{kw~7lFVro>0 zot>o?gf=d~2YxumCTzT5-L+Hc4lFm*J5l4)Tq{w(bvX%-q5kLnGXCI2h{&oIVZ(YT zR(OSr5y21BhEwA^TMNPPgq(`$6j1a_8a?%&W}C*pvFW>k&CXm5S!J5|$cCf|#-c3_ z!n0LdAHeBvlzmKlhTdu-&W=djnkM~IND$2S{|XXh^CpUty>nd*5Vmlx4Pd`Y!Ggch z%|+jukL>y4zP+n$!lD4gpsv$Lj+53&#nFNH?1J(oOEoZ5pHo?wp{Oqw@NK^zU*^`) z|E2nUkE;RP63)(yxuntw6!2@!L6&Xs2I45CJ3CGdgZfuNzN;yvi;;4MU3#7mhaL3T;_`KUs<9yo*o^^)w*#JU_1_b(#oVTKN z8gxx#WT6jRZMjBpS!Iurvs`O0n5XhJpt?P8AYc3_u;~ZqVUNvhhsF)uf-S~{`E{lF z-oLj<-@Xy_4WTY*-*+^#!=5<}EiZA6WRq`uYP-^>Av4Q7^!JM^D!DLX2y=j7r;KXQ zux~6B(XP&49$#_f743YY5R5KoUMa>Fk|8qYCD8S%uEu_d0J+pP3%$b8Wj|YBAOs`_B$Zm$wzfd&y^E z<#?HmZs1X-mvs9v@SpDdcfu@I0zK1x~Ktd7Qy#dBKF1s4_}i;GiL5+gSaU{ zPLg*=={Xq`Jh2Y9UX?Kc58pjv4$B#@u&5#-M;A0AKbqE(H9BYJ?Stc-5$nz6*-}pQ zB~ti~ooE+hxac0u5Eixo?{$2h3xAr(r`nOsVHgCoDS#+*bNeaEgL&H{aJ6MSt~~ zU>8{+1<^C!UnDWy zg<)%;sC8!qkFEjQ)M4Bo)8r;^$c8Qu5yBk@a~6DDjxkw`7F-I!45B5nVC(o+8XEKm zz6I0>c!$R}8W4Vbl5?A~CHrijXKYjgyUu_!y?~2(dVvAqJ&oTHkHdq4Ilzm-O*W$3 ztmG7O&G3d3ie3ewQ%#=&SUG-!WeD4p7`5Efw%St!x06YLW zrzZEFT$6=K*le)`}X(2`m!2aIi_L^a&@@Suw!d;{&^Am@|P8_>fJYYo9`D zi!~#xMtlYEg<*M7Ky!&!4lYzf=n9;C8e+~ohz5XW7`s>E;Hd%9XFSES8K|lI30I_F zb;fj-BrsL=qzfp96x~UFzVKY56HPawJ|y+DAW|%HvuTpi|3&H>aJGRE)a98(%QDDB zEtEB)4~>Xm5etUJGJ(yJ?HKeq*07mb{dU%NS3e!b!w2eq~9)hnc?(L3N2)wR}ijGk* zf<5~pXz9NxQw^vcRUnk?NtWiPkUud6-TR!9z#+@&B(@K z1r@~x(UgcH%)3{~b-ZkkIm<+11$GR`qZH&Q4p|K{9oR?}mNxL=Cv>r#US>TzuW{vY zz4fUH-SNVg`<$Zju7^Pv2l7e8TvP(*KH#mu-Y7NRg?aMQuuZrLSpoK9DAXSu~ z)Gx1+v3#SFx1;W=CRH$Z6kt$Jq0%uYqc1% zu6@?+PDb{Hlq9DG2v9M8g4Agp`vZ zirxgq2<3l9k(L_6&a;6*x7EUT`3hn^F%tAjLbq!i1%e0U4sd{$U4cDFNt_oMr;YLv z4GiI*gn;$|1hfzSW9SFp_SA8nAwLvfIXlKU1dCFac3kgwFdiXNfwmO6pJY3aq;(04 z0DQai!4yB(m%XAfxT{}(UYbUq?sBr_53)lj($>kND66a7$f+o7Q#|wVB#u1!D(u2eaRp97UttBw@c`SEu z+w3jt5tLZ5X;BiUoeSq=_$NZ{`8WDZJbvs5q2gCK5um1+GobYr=TPW|>K=zh?Es{e zv^#-7IpMShnYmFG3hhFOJva#_z3hqbTSH9M3)R8ofAO!JIFLL9tQiWcc~673DfgAq zmX+UoPkMUdu8UqwBmms+YD|1<1elaS7I|C&$u#Yelsr<)h$rBCi5aA9LK+OzZxOZ@ zxe;E+V?~y7*@AwM!1=m(Fz7R*NZ^1Uy{HYJLx-saUVev1Qx|5(Q2c{$APEF!w^2%q zr4(oql?>WlQqf#9Bsa~Z&lWr+yqD$F^*eB1rM16DNZXM$2nCPI^Ig#&e{H_!WMGbV zsNQBz9}kVu34ShYM7evHsA@YzE4VVQ1VE&WTBa$|0Tu3%e#n& z0^d}0{*S_zI4kD74RG!UxnSw@COv}4-2)mB%*VjbBZZZ7@wvU02y40|Gl50haC0#< zq73qsn#?6y@GwrnUK<8zgCpE29k{rm<=f?Mn6oULTpCf(%Vvj&<}=L?C&E@}DJSz> zUE^kPevC8D*!X%KinCt6+q7A%DNpX?KE*K2Gn}vPrb?7;+NZRgsBnY*Lh?PSfP?NA z7FoE$bSC6=Q`{h;(X-DStc{@@QIxWZZYT{jRF`;#s#3aaJR)b^ctVv0<=SbYRaqgp zenlJF0#KI4#rk6$wtW$^kN4yfkm70|$22)D}*Q3C2 zPTD^>iqDmAr3JK_WZ#+dG@v1E9Lzy+4)3yuG9C%>}LxqkKutcOE z;Tdl-=%<4ZqkPmd#rz+BTDs_7#sUZly-ykD`My>C8%VqLy?ekYEA8hJDIq z_%Q+m@Hh;HWHQLvNXq8B!jR|-j5ne_v<;T9B*$`|>QAutVwkU;amERsxPCB>%GT5X za(=!DX~~UZXyB)V&d(0g>15E$&{lAsqA`FTCbjuSNA(X9uqXlamTKcX>C$WE6~yTC zVY@~ar}U})i1zbjo zHwY)*csGElEd(C)w*6#i?rWRxm=(&^5loKezoIQ@ZNnr&!<9op)6EH8Fy0s9HR)!P zHND9O=EBR4+mEF7*o*kNXc-SIU9mzil}ZT;y^eg(P5d3ug+X+5yx%#FUi=~zWi-Qq z^ytMh>X18ji9owdpnikw)P!kI0g;>~W2v90+pNxYk8UgC0iof+dYtOld-jN@7?sLq z;1QWX8BpTYDVzvsz%+NNpT~8B)vaMuRLKTO3b1AQD4tq)4>m{R65Q%HbIgs{BV#4{ zbf8H<)8>I%$WcE{OdI3)LxNzK-K3Wcx(Q{UjH7-$Hih&^b`_<94ZUUBrVTpS15T$O zUtSWjzJ9G|12QcT!%1^`L!|F;tMD2Zj}f+icytP6L5&Y`Kw~sz+)qCfB>>*H43Ul) zQf0{!uXo_MXuOMSb+S@A*d`N$1=)u-u7O>hCz{Gz#0yKk@R9Lj+5^xMAFDa1m|5^! zKoSYAs)M+H`;rNK<2gy-UgC0`-=1c4 zEvCR+?-Ei8TIA7F!}W~zFt6zkiE{r2j}N9TMeC}->Of{KpYjCAoX*3v#0RoxU zjb*&j4_Naf`$C2ZF$Hd@^Uw%oodFi{e#7Z?{Ddeyuxy*u^~w<^m0~oC4Rsm8nzClkp8u4@%k& z{+?0+!-y59bD{gdLDz{Hyx0OST*^JQ1tSl1v$Q0Ah>XpVW4azc2J55ySRxIOuEVyr zB9gtZBj2$2*@M40IXyl&d{q|Q)KLFL90)tbV#wfc#dimTZf+HRv1-($be%mUuW{*M zY(5lYytFqhwNu}&aJSa6P*k#Lx8}qA+cbsM?deM~G#Z5c!>Y3GEfc z^yDmAs$1xZTc9>N4Ab+ycJEs`oEencjv^T>4q&<%5q{zLP`jxtloZ4HPGhB?-QfGD zQpt_7sufM+wn^R%4c#wj<48r=yHm>x)~6Fi6AG`UHB%#lkAYl$RYBM$s{n04p^%H? zic?y!0orxXX7aJjWMV8Eu24#l8yWc(82n(XVHiL-PbJch7y4&blT;%{hQs`SYO^Lo zQ22w4v#y%?0mXXnT^n2|FgRZ-Lpdh49A)rEs}vL-0?tQYmQixSMw>XY3R@5&zy&c; zE0xoGr3;^ciir-l8xbI6Pb40N(?DMdoupTs_6`t z!R<-A6XS#Jz_`+57t||iEKW8mVJOl43iSicJWJ=d-m`FF8B{}B|KU8p`7`S=?!v^V zTec8u_?AX=jsP&~jE2gNZ?c7M^waL~-VeLS3v2a8)QeueKH8=7x(cu8IW&fje{hj0 z(2#%XHKH#41Zjs2d1^Hv0h5KyQL5=R_!VNZ7QoHM(+Vn!o59OkumEPKrWRe_1xD@R zZc~$;#y6;#wt*+%we4C@zJ4$>KnA{#4B+$Ho z2#cSRo6!&#;S$>mPn^*5;p?lx-N;9HF(M%lc6fK46!l5 z;D|Mn_b9mpKkpHXaR@m^Y;!`d9~v{KD^|I0TF=Q_o5Y3WR$0Nc)+r3` zLN+Pk(K!a4M+glpO!5gjYXijxI?v>Msa0oFDMJ>UlwmfF=3;b2li`uVRfFWBoQ$xk zb41ZB^-co1FFr1f5}qq_Cli}*U0%^w7<+{|sH=^+B-9b;CN}bXVzY_mpf38mFM5u< zqb$#f$PLN9TmX7rE+(hMlZ8_})=gE1K7F?sJ3*}{?K57Ne>OZcg#43_yARm2}U7A*k2pQy+ z(!-gSxCb8nybxOL}Q9+`q?MbxP2?PnM~goNZWVw2#OHn}%@+F(v0%vhD;9ysb{Dh0F;Ylt~HrF1|c>=FUV@iROCME#2HmuPrt%-m|&#I;CEH~jr z(2lMai99-%o1;oZgn;BKrhxc874G5{!HmY3s|D^iy87eKtZLm{rI2Vd&J*`hUOy@q zU*?x1A(MMB@#Ac)BmwF^<_w1kCb$|W140akM`=jDWnzY*Du_u0NR6*>7NeAN_&ADL z)Or?S&Y`r2uVffOzNE;EouMO(EEg56m{qBkt7NhAHEz3KYsG6ta&0T>kh3+&5R)Mg zRtlDI)W<+WBq;uF{`&te!N2EGVJtGhH}Y%Qe^g&IVCE>cD;^=SX3?#e#+PcLf!Kab zY&5syb3ktc!U-cf$wYoe{|eFeMae(m^^1@9c!f>`=VAe_LapjEhK1TxXgMNCBJ<CjZF?56UAMC8kQ_9sF66)T-*Bf0A+!ws}uM>*N<}AT52q)o(`=p0Ux@}_&DI8L( z@z>W$55zahx|>Z#G#?4|zwPzz;Z=HA|Bv|9Q0H?MlCiZ;s6F=6fy%dY6#td@_sFEf z=*LzGH;Omhfc@THCiWd#zLp8nG3+$BSGHsYbj>7Rz1MB7J{nvgQb ziITx3Nc|D#6>d;YGGV(m`&cPh6jRiics@3UBXP4_rkEK{n8@YP5m_5dMuO@r;77w` z07VNR_r%S1Y{mn*Q0~>z27bJe2%&(UWC5*$hpMs4h){;$%A7|wdz!t7PWN2Vb)dhu zi)D;FWyLdF3SGFQ2a|m*W}}a$d%Q{o*Jl_h08~o1NHYfWM(y~|N|9C%GxdirB|%fj zAO29RfrJ1W%6T_un(p+O%Gp@rGkq0;Z?zo5YW3db!LNdOII!)=HA91RR7hbzST zJf${5g9LFh$Ytd=gbe0rxb394aawR1AbzCTzSELcxb$g9maM2+Pg`fy`0UBSB=`2b zn3js>-R+{Mj1IhDO5hLxVzzj4Xlir^MQrI`EtQF$*|e|H_mC-@Zh?@iyd2nOF5jDv zG#QU7psrbslp?=_W2%OqbogY8nRx)^aYCT>|h24 zwb;a&I#s9fG1=+%)OtTAx4StYMwC@7`0dZ$e=~?2UHYIz$$tiaG}D)YM^o=`scs zL7+wmX}^T+PsnlQKi}hCl6i4L)k{ z2+X6V0jGQ^7tAeSLWNg*;4Rk{%O+)WFyqD1IaM4HsOYjep7dXzjeKL+h*CrJl6|v7 z+1Nb5Y|NEz^Q5OI<9IXho4^x8=Jawl$}rP8!mo* zrVjjJmZS{pXRy9uhUp6-!AoP(Lk=m0s=p)78kgeul;ulvp|GX)py-p@K=r?EFE>It ztq2L^f+m`d@clErxJZ!knn-4}hUJj1yo=uZqvW5HbR^Nez~t^x(A+p~r37~ao>?GN zq6spJUZ~q9fXmJeUYX8R!jWM&LPTBmc|WX0sW1skRQjX8#Z$z~VMAUa+yYmuECckK zCb7|OPRq0>Bt=`HRG4!_I8HU{v9}sDQ(K;2zB7`L9?8QwCdyO`GIZlS4mYa^6A)lzACMFY6OQt=o}PU5C4uhJd35>uJQC0x@(&H|&zF5l zC7)U4o+_z_H`$eVW|nsVe zDd~k1l_4Mq9vXO9P$cc!T=S%w&IXU~HO4>48gkuuz*=LDx2r&|c1GQ1i}Y0@-LldD zQHfQ@357C}vpG7uqYyUE$m318yCaX~v2wsj0EwMFESD&}nSy7*%N&@pN)Le|h;RQPt=B}=_Jmg(hyOr}r(TRA#5t#A)HFRLFed##zJc}Js2 z1nt6@F^GuowGHzkeka;m)gC&v_;ehmuDjy;hrMX z3y&p;Q6qXxHC$}MvN`~RWU9ai=|FGKzP-nC3vI-*BN!J8Gu~EpX^OxWOCPKNZite? zJPMO4K;uh|r%)xS(SagJA#@F}M3CpjveMG$pl3|bPsz%c96M4Ayu4DL=o zOcHcJr(EWgc>G|@CU`3{4h(HHp7jXqqZrOu2lI5Z0lb(1 z>#!9Ym?sV$3C9xW7@9!N@~qT(aDhL5dU_k}o(PvhN@()=`&P4A=MVAoHQ|M)UFg9@ zO^wF*D;xiK&ai;1$eG?Xr#F0&0+wKM`B)=QXm3nJZt+YJ*82`}MOa*M;aCb{f?LV3 zeKwbY9!yE(bA;gj$m<4#6fj~YBVg9o=#nc#%)DlGDtonum?D7TQ`}TAS#gw*p9h_k zaKDFRr7wOi!7Y&oag=}us&T|6sVF9Ic=CM&+YJeqfP>g4v5h6&M$}I~kauk0FjVb+ zw0pSkZ9N(r?DIH1_=7j8It1wjBufBE7(#u8vp#JrhOkXI`h&r@bDhKn-+|zOGvc@b zDxu|Na4NcO2)QkDl#G>DB#n)-fQ9X9WGh@DAX;|KUs~}t&1q=7@_^4nxZYY4 zHW=dQ89bUKb~!QI)2S5u^sSZK&zcIx@uB0v<>d$hY7&v$2XhQLEiv$znv*H7bMnZ> zbumQJ6z#2)v}gS^(6IzVMIampqhYaKh8i6SXWen2p>&K+EZni`@igszP$KSMR+{T| zJC4Dh%!RF}C>Q~j_Irq<%R#~gHa(h{OeUfsv=#uL6kCQ2o7+7I)i<4bH3bsc zg+p}llxmt=gjS4Ifu(FHa&zTTb2-?OrQBl|hmr*{13_kqx-j1$m{p!K$P(cOs;^Dd zwLDoIdg#p8AZW?1Cxg6@L5#+H!u3jVvDn8Boc{@601-1hula`S^Uf9ERRJuK;2`)z;WOb3!aWnw#bnSWpGeb`d$!!B zDvp=i6e%5F~lJB z4xT)~7jllGJ48f2a()LBkr@L3X?s(`qktotoQEbxzgtT>eL>9?mx$m&v8goQPa#x5 zoplJS!0$|?MIFW!EjS|sgfAGfeLVM5GE?h?ru}xOEs*!P&oeiV7ot2JsN*Cbk5YQK zTzO`YRwNsXSt`AjfjdqK9TGdHuy|IJijwX?NV&_A0ZoD5Zmw>Tj8jvZMS=96^qz@) zK1M2T6-0uCahv`auhc~i%1EOP3r2rypo;~Dv_N2Zv4@2~7h@%|a2KKm#X}mlN|}hX zB8FLN-P zptHhxtu8LWVE~bN0b~o9TY|DNCXdN49qI43Un^-ln+Q!x50wdvIP2P zp+wosv|$Z!&#n^$!8NV8d|gLi7*rD}Bgg?pDT4>Fyujht{7JXUZeJe}h={PVm3(6{ z!NDA)Q?{v+XnB$8(>UQUWf|tC#S3D($fBVpF)d+cE;p)?!Eczzs>sLZ(HG&MwW-f!) zj~P$b8qxV;tLZ&zEUutgyAjbnt&bRQYeVyN`|LKH29{RxyeFI&1ddrK-8bRya{d|rDX^{+>Npt` z3he}ta-GyZPRgFT>n>$ANdINhtkNq0Wk9&;(sgnkG}SLZ#2@joue`<=AXX4zMpPAE)A-DweYr$F2Z_AsGo26^_aK91B0h>Pr z7j;7--Nm85LcC9|Fkb<0iTT^G#|O=ki`0w950_p<`iA!<>{6kN&agkuk#u`0SxIhL z|F`K7j7P@2$2v>Wv+p-OZG1^Dq9iqLWMsXRs*LyUqw6h4npC^CoSkSGHXGURv`GfV z&I|6CP~`*zGT|wPHOkir8k^LcLp; zpVS{(YdyH&=uCQ&GwvXu8`2wm9*@%;(wcGFM&q@hy857x5Q>_p!b9R7W3)@*eWJmS zF9YL>z#cLNjl^dBu*(>=Gzg}!{h&`l#e^6S)0!dp35n|52J4{2mIvJ~cu-I)uCqi+ z4r=c2sMvd=D>VluicM-CF}R-SKc-sAcPulemD{fmZZ`j!9I5J1@OuM4F@A;5!-r znNi}PMZ&RgB75ot29{8lcXbw!Kyop9u3H=)^gij5pu%qpSS_+PIVqpGQyovJn*-H#zb$qL5=il%-fBb(D5MDi_zh_c=1`*yioMO z9ri-6AOeIU8upDvCMDSiPXY%~>hz@~?v0Zn;tPLBheL8kWXXCsK`MBenKYT4=X!(* zP!Kb`n;0--%WR_o#A51%a%xt+TSCgV4xP-4HQKdi!gmF>GlZlfWb_WPpW-3NT@wP$ zCYIh=!-Z{yNJ;XFG_st`B4P3 z24bQ|u1&tv8g>sbCuKlY)P+}+fw=wlwJ1me;0KQeL_c<*Q25ID1HDQjOefh7-bVJ{qow zZ9i6*r-38Z)y9L#wf@^l_Wk7%<(RJwJa$M*>0pT&>VBKPxog_=kiyM5y{9c*ktc|M z^90|noSmHRo*wK83ki*JXU7Nt{)3f2KFXu+z0{Q8Wvf-g0O=W`qYnn%5ten^72*WE z-=1d0$Fb5Sf7+S`=&cs#IOz_uS<7>r?`(x>yx#7s|Btfx@_;2Dd_2?dLq<%OZ$suw zdKaSV@B;VPk?Q$-BSC4A2z7$;SaE8^pd*Chy}KCD-PO_9<$=|KA|Nl_NPd0WBQV12uG13&h1(14IILT0UZ&@FYT~ag1EAzg9|3%mK=L`ky;DRdNyL7 zoQbI+4(}tl_dzyTvQFCMKW0DMaD|uINW1pLxlYI~*Q6hlFBh$UEFvHpFfy`EvsqK) z8wAoWP~L7jnZ^m4y$}jX)2%&r(S*l2K7gMZl!R$vQQK;*Po}o$hFuGclR&|%;5+M3 zz(nOA(VhO8`eBEJY5oY`m4HKVqJ)b;?2b+sZ+8<4H}v&GLd4218w>U)Bdr8;<`S_l zqG=8b!RXJzP(*GIG`*<%)OUSDm-UbmTUcM+hC4QCP${_M*?>^tyy_($wElHYY7cT< zwbukpNj9Pfx@LoVD_Ve3?Lp6q5OLI8V)Hkoz=&@Fy5qY?Xx5cB?eY}sBACQxU#*BG zvCz~0Q_*>%724ji4H94h&uicZB~JhyO!Hx8og6hgbV3%c3zc`p`k*WKIpwb*K0|FP zR;UVGWj#Nc1XJ0lB%cJFUh=)E26|46J-g1N@vI z8!%60)eRUwjctGY{JvIRo%YVW!3WL@TmTd0%DDxRFLLS|(@f8AgqqP9;u5XhxEUDS zcgp92%A|KGNms#`bkwp~GzR087JtY;+8X=Mt`Sx84E)g5EymOz3jY7SUWdvY0`{0qBCgwpvyk?q5Y}b22Un%$5%DTBo&!ln;YvE@j9?tL= z$H~dM@|63I=#}0j;7|vnDYuHHd6oA3-aTIi_TNQlCo=uzj;)Xlz%skwKE?PZpvrUn zCmc`X7XWGmYW-woW#eW6t;2f*hjhw|DiMZ~<%I_~ zrPJ~&2pb;Mz%Q-c9WJ~!SvzhL{2+2o6qp_moS80&=K!#JC^99!IZ4KK0)>*PbX(JK z?c6c&5zv}6thq+Di)uFO1p5eSP&OyRqQ(Zp;G)wi8MX&<&gDRzZ|VvThD+G3k%e1Gf(kd`-ZJbE3+ z$vGyb{ZiP&_x>}|ewZXP%sv6vj~2g@ZmjMjNAd2*zWf+jT%w-lJR~93%yY%ebDV7n z*+cmLYp9)q?{*YCPw`n3yh}HznbW8H6FJEFJ#1mvfx)Zxkdnh66ugL@2s=T%QnA0_ zdd*Ik9hn@fY&1ouZF{p+hY)`w^QQ}J<2&qg$H7GpZb(@N{`GHYaEIpI+dRl2+v!+Q z#|3X_)Az>9-BfnJTnJ&C*N|i`bRi_ ztF?!~?d6~5zP+a2zs2nhjOIVL_m8{1HNz+WZ7;8P@hoHix4pY0L}S7asULx6JhyLG znL6hAypecZ;`4S*_VIgqzM&37dacl8%DlR&9nai61^%_HSEoM(L0{XC87H*F(jmzu z_rX!*f?DFyhG#5AAwOfvMzn&F)!v4igE|A~8cK3Bzggkbv`%D9I76ZRKOIbx?XuG7 z-{S;H7KS0xx_mB-E(-nzRRaB(d>w`9Xm=Jb<}6sSS#;#_jdH;ip~N1><1dtrz^lk! zX=vq3jQ}j-+>67rfkxqFDcNKW*bZ9#%1kOwqBH9xp;)8%j-4IcFIiz1gRMw|$3rVM zC6*f#tIdh_mXR~GHd5!qq?>}tG}aLDW$_~Cw+uv$dC0A)a$zu)azrszg4r2TAThqt-W{FJAHokO6b1nmBp+1~gWVGdZ%-Xpmwd-$Vw zkU_}h#{*3yfVRi!Adfz#$xTjvGU|VB8OtSOb0~WaVQ3o)r9C`6Ce@dcw>|)9im-Rl zT29pZ_BF`X&E0sd=j2_*YyZ7ny!XkWMI%Q7T{3UDA)_BZY3VZXe5*J`GWI1cx;XGO z=4o3dmO(#3sB$8TT0i{q6`RGz=!@|jCu+u+SJ(n)S1P^~jApj#tQzDTBMqo&$%W!J@Ru|oEZ{dnVvSX0TmksLuG5CVho$GAUIK7d`q`C#!@lyW znS((}!&ai;0*LI3b!-T|0H9E%{!rF2OE70A5<8FoLf*Va{B}^V}Pe`1BY?RZezpie^ zY4s7&@=|NNplxdudW>!XfHd=%kKQ{*=SBe@tArS%eYB`dmS%|SU!!L9EPCu@dZT9; z=(JLgf2UpCAoB$11B5rx&$1y4QUs_rR;)Ni&sT6IWzodY9Jw3cI23?_M9Oo`b!7a2 z1&y&gKw^1t9r!HKEHQSI6kYKZ_h_>P$y9cl>e)V-xs-GLM(c|(xVP`Lu*g)c#e zB~`~YtyC>LRvUU|z0xV1Fmp^Rw#E;i5tDV`=k7dVZL@ch8cS=vWx?uy1*odkr#R9Cv{dc@4av); zq9*z!D;9QnIfZhdA2qmn#hUc$Po=3^RX3C>R4q02p>eGE5-BmoQN;o-1d=oyT)d1G zFDSmS>yg;($Y1^_E^52x8P253gxBkpsz5P_+-N~K^of_Vs$~gqv!Nqu78bu*G$pV% z=)m^}W+pBVX*L>5hjkWlAOS`~m*rXq3Ybv3Y>Xm;arC&tkfUzm!XgVeWPgAmD`vnjVtn!$*4##1@Hr_d9RF%ciU*TnMmbBU?0s^v$?*y`d>};Z)1JU`ERq;YHzHr z|5r;DT3cOhuB@!9@++&Wt^bOef5ZYzfPX~Me<|%@Tvcw`@Bd5xQ8;^B?Smo>!!bg^ zM=hD4FP@CAz=)WNz@Gt4bKn*K8;|Q4_&K~`RhUt98x<~YVKJLY%%jK)* zI=bgjNj@UB6YHk>A?jm%*2mbW?=-B!8;Mc{+CrBcp5cs*Cl?pQ|M#9gUFOl@;Lf_k z{v?P0|42#DiK6?py;}6IM}Gkbg$tXNRZ0Bn7;xvsC8aibdOW+II>#rVo*B2A_VVU( zYpoV)G)GG%9&HGgfCt8uVy$)7dFscc0FU){=}6;l5v|K?zpA{r9MehBsp%G%ulNfV zq)g-}U=;GWa9X@B!VQE&skqRu@3-ZYc=qp3U&4v#jxw2lo!w_OVxZkf{AHAR?uOR0mh{3>Ktk<2xSEoNL)bY!ccP~y(kA(+AUVR4i zIK(07K#UbWd{P;!#G{WnQyvPTMIbp?->w$3p#{78*)UeZyA}CyF!1yXmzS|1xflA6 z8O5&k!BD3wBMbf@x$y@D_D_=w&@nlfJdu>-6`}4hc8jH40$)|Hq@?!fGc#7*RBPMihfLcCLwfuo`MI9I5KA3 zFj^ce!#2QLh#*M{z31i#ycptd(xLI4KysW6uHdjUwvSRz=rk_!b%IV8q{AJM=mEl8 zfn5kXZSXIPw1f4M6W;|mBIls#Ro*jv(Uhkr1ewJ%7HT#{EyWnu`w?)4`Y1xs5djVj zj8#sc9@#YEY729vvLUT9Ye~*8w=_s1$(X*K8^Ny^^wQKF_JTP<$lJm~1{q*LK^N&Yr39=YalzN!4ItZU6Q=({W7Tp&z7~+rvcn1NE-(X@I zVr53A=>mbN01~c+mooR=qUxS!BXehSo2kiN5WIM>s_f;Y507RsY6qlCokZ(l2EO~^ z==fApkyUk`-4wL|BYvKak-eI8ZlW0h$K??jF~S?6PCq!o5x`Udo8^=-GHjQn4W%B; z5Xx^1Uyu&M+vRV&*SLm49}pY|>^jRPD70u9gH6`vfKac?;U)9OU){bwz~p5O*hy{& zCSiMFIj$}0K!f6@VSIc$0A`9D02m%c4~0{ZBY%TKI*xt=zkCgE8-t6!vpm|{j<1Ti zu7*uwj@=x@w7$)A3u{HTLLsR|3+EF=_<>Yha)3swXTih3#z^?Z=uvO< zU>Jl)dcLgCfT{@hl~DtTh|p+vc5tJO%%bgtaw$-k*6?5s{2dY{A~oc`%D4aMN0$Ca z+8e-Nbk2G4?vL{P&t^ua57&OBC zq-R_vg@}Rr7}0dK*GSSw(fK65HL{ds+L{jXD!h1i@(U)sXJD@L%n6F^5#KTXB3V+S}<~<{1IfSY%-SmfofX`>plh$QEg*!U2K%VLSa5k6t&DM zu#2sgfm9QXLN&OD>Zr>V70-f(;TJ3J6=)E}n}GaLHcY730>NBlqUeU(afGu_I~_Xk z>PLO)@eBgAjuAnQ#etLA0yHla+X61a3-y3ft8Rt;*W^XBCUbT{FV^cEA0Hj-dM&%y zOeNLOQ+iF68|Jlv&$@@Zud$7`*=OXsfEd`%F4L~I^bfT5TWsfT=lG48!wR>9QxJ-V zx{-sFw%@CcVu7x{>TSOT|5LX#$G4yX2`qt@;BuLPtXU8p|LW>{TWsO=(cX`peQsf0 zgGxD2BvM5xZRhalO~5a8Ss@ZfFA*o zM_~CtdoKZ5NzZacqj$mEA7Wh6#%Zn~&jLKdg{HcDczX1cc=PsDUys&$c%@8}eB>3QS4ZzQ(Avq~ z51lu=+}cK93vX5Ji}yxBe7`vK`;(=IZJ4~mdo$740N zV8wSQ9hyqJrJ>8nN;o0#Pfp#?zYU(@*Dp_aXWD#*-+|fW=p?#GVo>i%n$9P~A?j)% z*IZ?JhzRb!JN-c);I^j5_`;KZriqtQ;+IFqYW`exRagC#_EVUMJ)-D|S9;ElcMo56 z^Z@v%7St{+t{~}<5wF1;zPtZ|+v9Wl5^f0_sI-1axtXS2q~oKX4U1?so7kGeq%kRY z%-DZ$@(B2;*pedD9otf?q$PL`$*>p?Vg8WZ zlKhwuRLBOCJAV(O03DQSpw(5aXHE! zjuPodMJNfEm=qGV><9ae=m`EtotiWJe5RF8jZS4O%FOnySZ^QAcoFnWuQSAw?h<|` z&}pAhJGi}4!_U)eHAtgHU*D?TJEJzv(w+lt47%N$TQVUz0yLyF&~?;dQPo(KmiDla zKH#DlTl-~pV*rRo29_3@SwJZ)C;uG8+5&fyUR~RqccQ}tlD*nQvfL4Lr6S4)8tFUGBKt!rA^hj^m;`Hz+7C;??%LFey z4msQkp}Rs=Jx0E<#`c}FMfLg`#Q)lU=XK|_BeJs9uz4VPu>($t%HXYC84AlZ3nx>d zq4J1w5nSJkIA<%_fC3GPAgCL3c|}N5a8M|Tc`yB#_9g%Zt_O?w&9?Eng{&o`7b>&a zP-&FRJsM(VXz2)rEI3g#=RDHMxWJod)B~3QeR&0pw_QDb_H{n`zRnhcRQeZudrO+^5D84I=h!?szTHcFR4PUwx#rH2dpM|e>z4;bnij;%Hlg{yJBYO9C zfA_S51d|60=2%p1t%2g!y%0pjM^1Y`y+QcR$$+uF0i7KT@%pvWZY8tP$*>2Pm&fH9 z#xu?;idmrKKF(=j_w9lDZXbR+dH3Rf zz+Lq8DBAl0<#O$wRFq=O!4K0qZ7ua)A6%q&?Reo^f(`HvIb4u42)m0~qp6?iA+~-U z2ztT(H|V254dvZYI#m0!p!T9Oxa=!YyUu2D2d`fa1}VE|xx}jr`pg;iq1uC(axL*2 zNS~9jHS&q#r0}VO)K$Vc!^>iz{Qx}-$Zd|qeve<^sm>AaRePZrW|3KIO~y7amY;Y! zp!cZB69_Q?WutbeWb$z#xdS|C-3}>Tn0}|B2XKB|piB$oBoOnnCTa%+6pgmT+8(@$ z_iM~z_Qs?B(w^FmgcGNdhe3?5r%^vsHORE?Oynx2WHl0O!hc$}hA43ai;HKNtw6e_ z3_a-pLjQSlfa8snN`r?_KKz5n zdUV9q@_B6GWknt;bs(^XF}jh`iNv93h85~l3qZD0e3^3k)g0e>d1dYlNnrHzLvHiE zaLAH*n9$G5;KauiN)FDvtt+ZH>e0iySJQA3c&PWptPqb_WnKr`=OENFa!bU!lGab2wT<$CW^cO)csx|HhI1tu_P4lkm>@(8K;)K! zkEcsuVTl2TCeQ4a^9vfjZDWKHyMuA+4pg}hj6|%)5<~t6IL5a?LvHZ75bnq=l01RW z(oh|YMe=h3Yi_W-kg3)|pqY%rW1-&IElB!gsTGIpWm@jChAv8*<1~aq4u|FFHmt8u zjwUy(r=;#=#DK%vK4o*sV>9eAb*}d4R%Go0<~&Mzlj~uDd^<0c=4mm-Y!U3*V+j|! z`P3Wuw6|D7!14rHiZex|HhDiuhB%10SLuMtq$|x&hWmqr^i~}kR_(NPM{)Hl4RXq|~^?1yMwDJuL2kzCh zi4^2*6kcO=K*Z{i-`Kzskv;`N#+Xku`6r0ps#WbKM8n7~F3=xHu6Z8bY5m+RcRISx zy}cZO1SiB1MfpL9Mwbw^ccXYX1b#EZcbS6a3f^Eq0EYEL0!(;JAaN{#RlE-t?W*i_ zRt0SM!sa!`MC2v;>}-ZQ6d!`_9u7CpWh|-&Y`-9F2!}!UOB#obN5U@oI1sFVgY5lm ziddv!(p^ddWtY{TtM@zb8- zvbXl9mg{2yu2JUvp(6D-{!Ez*+5JYZP(i%Ii>S-ut!2C_Ds61WK;yi1(A9ozzK?dI z8Z1j~JM?=Ce^(0?{<%#*!@7hEtYCrFmGG~t_^VpG@Xu@bb9*!V>pK35s~aw`LDgIM zD-<}yI2;pLU|nY*>5e|&$PsuUjYkw(=YSkAPbYIq{Z4OT%v!3$? zV|{5fDNy1e`&A;Fizz}}Uo%`J;cqM4r_S)+p*X0hXpep;A_FWVDL7|=YcA1?CFDic zqJc#r;g|NpHhuzEKokdgBRn;Oa;vlU#mucu{a#9Mj;cF&-wlr+96Fg3H&f5H4a99h;$qudchnhwskndikTi`dj>K3$1YO#?L z2d5c5o2>J>-baYL))_A4sV?kV-6qy3NDJcJ@%U&SuJ3r^6_D)5EFt7U5yAKn7KX!8 zA9>5z=o<~5jF(+^12eLbEk+a3Ccm6cGly&WIvu|vihP4ym|L?V4@8BjO}<#DFXiLg zzJ5^0@sq`Z3|r^Yo7FwMAY*DZQ}GzkcbCQ^ife~;=PaH~h!1;?N_@GF7*^_@fd19lnP>fUs2@o>9)PRs=sLLU~ zB-Wk5DN+mzTEC@65s&}`L}-+=m~xbtnuOY~c&Inr{(`BTVE4feu*kqxz@Ovx8zVFPOwpK> zt1{(AjZcDn6bW}EZsQrB?%sJr^@#5*;E!;``q)pquite}7M^_j&nI;Xz%&1}{NBG=70_)uG9B%|p!Y2N*rb7TIWkh~lByo^(~xN3(#{%4E-owm5- zGS9lj&Rg|0Z>=<=t0UwW`xq*x2V%9ZpVL7PmMgzi%=$XloV;7A1quz&gs5?tv2kqC zacHm@)@K0B-%bqj4ZpEzj}?$E_A$}>OPz62sZBX(7)pdTVeOz!7@G%-iJq2>!6T%4 zLc|-9^vkf@MG-IQ+8A-=LqKa|1Xk*t=jM-JULG0-%Lq z%C&^rpm3Io+3)LmGGKfHK;LE6!}thMN>A7!w5n?_4Hse}i0W_#W#r#xkQx{`pwq*U z5N!cp-AcLyII~2Lw3l@!W}t4qS?_rq+db3GREr`qkixn$z?h`3@Q4#g7`u^7w{wW0 z|ALf=cU`9;LxKkC$~Qtou~bMtBQLc$Y8L!N*nVoIl!e7lh)KR6c7TKD?X_R5H%Qzu zh;U}(rNA>(J2t|Y2bV$_f9{WIEUy6U+Zpf&D zbCxjK)?l8P+}&gJc(=8B!xd6BcEFgt%r2mk2oQYW9h`Q7@x7b8qx5SuM#&gPp#8;z zH=C_;z736oV67J!#oe>-mC(IQxo3ir|pG8-Eb@s-GfIoD;wFi0nE*f(7wKaz>|5}R09YSjx7 zaj;SRZ(*rj_#OAc{Jv6`R&(^dvy0#{b-dWZIn!R}i)=D7OqqR(&3l#=dD4-Fv|ZMj zl9-~I)u@UbuQ#OXzxZnCy& zaZG`bvh{*U?-`qoPK&cWAw2p|qreQ9?vzaE9_lhw{?&tl?Im z@5<}oshT!AK|rkBP{5Zd5v%=Iw}PZsw|7%(A(}M1dz0&TBO|16&n_J+kZJv%&rYWl z0KtmiVnM!fge$8@8MJt-^-Zdz9(}qA`c&XtgT6Y>Mtqgh5xtr?^b%a99F>|U-nAlP zEMQG6lzl_v;+gJ1lZI?OgBQ2sBp1Gh`1aaBVFp2+%pJpL!=r(Oc!GZOXn`#^R!lK# zqH+J~_8DK_l3X@>TG%Xev1D`hjY&$1hD1Qv#PtN?fe2Jm&>b#hCWs;TBT&}k$vC@K zU7~M05Oy*p6iv!wZ{;ThF{c;W<)NR2JIpy3=tilEFl2=5Z}lFu99KH4*C$cD4lY3 zFn8zh7ac+X&hqq>?LK{4h*CyOGoF>i!4a90u`*sA9vye^QeMb>h_;C_Ax&a<8c7W{ zI7Mt75cHU%_mh#-omoIt>LWz=JCJ#T%+K(5y;0O1AGtT6MEEj0N*?8!4}7Pi0R+)BI?h7vI!*_*MpT2Fq5hkUyUTSv z&fxdjvcwj272{lWL}r`O^e~cz9!4ZPdHXH&m~W&Q$CD3~m-| zjU}O#WM+uVfonx+#2s(V>Hl^|mrE<&=ha6cJdn4)6l*i02cf}O7g@xT5FWFE=8ikN zh^VvQ`MYhdrNLo($tO|YZ@#p-)7=-ZJGQxYcyxyXkEXi0&YQPlh%5IU9W-Z$xcU&I zJ3T&l1*jAjoQV&hZg9TQ{dCaz*+FXh2@bK?$=OF|1||WU?mRj>Fp1+d|L8a#)cdz} z*R9w;K6>jPVuR!~|3Sg#yhCi!obEO{?+_bAr@M~MJ;Vmk={}pCSe{}4W61M@-aS0or3`Ymx%OR~W1t3abSrnA z?C$C5?%of6bE_7kX&?eoW}$bX=6tj>9#5b-DY6#5(vvbd)e7bA!$UE>065!y2XV*& z6h}NU-+>z~xDJynWH1q8rL&`Y>cqa+gKKd3ixn;i#H@f$?I|9CD~I}rmMQkL!ILqm zJUlWAQS9OO+S$-)&p=$Vxh5`#3$x7vpf)~Iny`B*zPOSx2V*{ro~yCHV0pElg9Z-oe@tYeGp*>FxY%72 zX8ZA)T{k%?Lw5cfWD>(xO^wwJ0@vXm%M=Y7;1{jN?_)(^tOSob7kxO#gzKVzx)@?Vxfs*mip*VFQEM<@72h!jkm3%wz;^Jsen0?gK)Ek7+KW4UPA`-VwB! zGv5^UM8^PrWUxE%2w>ZUU!KcH$O4Q<+Mn{|E#8}_IBL>;3?OjZ8}Cx2ViSCmUC+p) zcc;(9)s4XC3N{e>bDXRd4_L<^I#6fp$OlN{b6DnloeRgz&j_a~=0II&Lcz5LyUc zG2j?_F6dMUS=!X55jpW6X9{sw4yiPGN9aXX2Fbwd4Tk+FdIb$#W=@d!a#R#k^#Not zRN#y@1o{R-e>Y_Ge?x$qN=F!ir4^W92DVh>V6fN^;Y=tLyFz#~6Y_!$j=GVpW-;gt!qTn34(To0Y*>@Fih35it{AV^`%ZU+^dI@W+tBaD8ss7I+y z_dH^IKEV-88JT>?y;@kC4cqhaR!2>n$^B64~%FNcOi3nwnnReii7|1lJ&{>8h3|(}BGPd?FmvMTk;xaiB1K(+anX?h`N~ zP2YN)%0aUN23LW%+Rza~vf29>v*YR5K8N3U%fcAwPAtHM*QB)?2tf4ZLddJC2MQp* zgL`8#Ko1_NLC}ggM|3%SbS41+!d0@7c~LLIbDOb>CDG=J@?mK6i-dK@w5NEydU|k# z#XwXSJpu~S4`%JrC!X;j2^fu(a0_)x0xET@b1AyH->h(B^R>yBWEi?Ds}&?QEofFq zX*P;xc-Sb5jYIkDFu<-Ie`QDTG^fAew!%h8yfNWg`mhIT1sJ$1C;AwPd^*P_r+snH z=wx}S3UW^kpcNABT;D{_qa4&FgwueP!Hi|g$@z|?&1Ow9J&6m*@)6)C#1uZDAJk1+ zEQ8T z;tj|qfcKsxNgxXh0M#7~3`{1$Lg%bj6Zge+K+cWA)=2TixT~Fx0WB2A^_)ZS{!|d7M}d|N!_zFux6=^o=PrA zFHPz(B$XLDP;u|lbJF+JM^m^@bb_{T`%oj(XV%i*r|q zQZrJ%?VOY}W6F*P7oC&TBEV2v!Q7gD+7r7Znr-MoaP`%o#}!H_Y>qq!$4@=vk0gn> zzVRBC20nv>JbV1=AWwMlD}NQ zv6t*Ahtn-w86lY=YPLpsVI>}4g1}oX9TNaGswMWQ@U?FQf{qPoa*u$<^+)3_zw9i# zpo6gKwSF@2c3`Qck!i=HJ_aF+n{~kl6M;yQ!R7d>R1VNev{q>ZW-bYd{xx!+K{aWF z9XL-e0FWA3jBzD)RF1Di58)a*rEb~M9Na<7T1yCGF+}C+R8U$jARFR#KizwoS&2{N!v3(n) zrPHWby!)oiaKa%B7UmYVP!L9ucM`$T1|qMV&K@O{ie-Uc&VB=skO0uSF&Y5x-bkt) zVld)cEhbab=#H*c7X3C21wSUsGRTdw1@X9f0xYMbc|fWx!?^SY1VOZ2B<&({w(!{r zVEtzz!M1?;NA*A~n2t-zuCGC-*Y5Sh-O;5JXsE9?XLj)tk}u1kkN{$QA(Mj#9j}wt z7%X)~`94alSlm$ElX*O+!)bl{DTjr=Yu2#b!1Nh7r-JPShi)Hr=?U5WSuQrQ0xV_v z?WMU^1>7Zh&?B>Gr3|%BXIEMFA&j|RJSj&*HslPtquU|F&81@}u0}2B@W7Z|oc)qZU9$kH2*>SRgT>g_e+IgUAw&&f(Nu94dVj7OUab{TVX=3-^Ko zDpB#(+^eRo7XjE;%AceMlMTp^OgJ5gJIs_`rod%hXx6de3-XGN@{i=!0f*}_xzUG< z{%rV(4+yc7+x*Ih$*~ovMVRiJ;rOQNpmSBzb+3@8N1qL8aR>6t2f*$}XMi(|L0g6l ztQ-SbOO-}r!aw;C<(WZL)y4>DVvw0A!`urhN03al>=f*+adOf543-aTyJ)NhWf6nd z3@|BDP&_l_@y+TE`y5MuEb*kPHdf8?jAlr-S|;+wGDhulwl&ypNJ6L0QB={zqt=ga zjy)RQf)X1($`jQ~sy^0`G$3rDYd`hoL@@fNk`f{_?+FV4`llYv{y|tFx-_lX~|Fie*4^3R#;`sSh{)#cR zCBcA6cxa(`ih!0|1TSEF`mtWVlVpIYA(N9y1oU|R_V0S_=j;hV(e~UcEt1Uaz4m+U z^+5uh()ACU*X&0V z6SXa7qdGgt$S8BQTqqnzfdqLbmMW>stkAF219;Wtqch?HB9C-~k@oFv%V&Jtm#D&w ziBsW};g9zQ8Zn1_D`7OILpt#Jradd?o|IpdkA={9DnV1truAHRQFJS0hYm*85h0D0 zFVY!;k@49ZR$PqnBt$2GqIlmKu1VWID!Z7XL@hh97SS@8+wm+XIeqg*0vLyry~|ZX z-LGQ^tN{6iZPIj6T0=UzmIo*5DI8l_$A4YIcZfie@sL4h@OsdTJB3@p#aE>ZA71fq z(i60tK0fZ?ImX|a4;(kp*y_$Emza`0s%%zfqc){>NBe%%o}A3cU#xO0oXAhd`2KID zKU+_>=J|qa%{LYn7az!%h0FYJxAoI#HX18SOMiot-FUdN?EHnFR&%NGwe~TJ_`vN~>%u4a5zaxheL0BkkrT)_EC7cy#b9l5t&MKR`8wcC4 zv!Cy8z1-c7)+5+%tE|kB{zAs+diw!AgIG%kPELq}uqU3datg zexQH%Umm@9d9>=4ox$@xQ_SQ&b(34iK!F}Z397PI>`G~}aH%){xZ9qpqew>1_;FYO zKs{of23Ye>ojA~9&lwYumpOh-DZ}k)N0-A|r99h$BQ>cZn zZr*FGb%S1;_M>12tZrjdGmaS>)sQdi4eYDwDcv&sYR2x2w+C9TVO(T`-sbmnhgfBw=xh5Mg3;tnukXJ6$0Z?3>~FZch_Qe$y( z1GpuXJ~N7fJR1)? ziLzVU5!zU?amT3(NrJ^hKTnSz~xHBrR5KUNYC6`}OlPR8ONF7%Jsi(mjePbs**cB^Cw?A`DwF z`{_R{4M0L3CWb_WCpcl`rJJ&O)CoIkSnBm3tKZa^ShLP3QET*{q1Yb50`D;J}n#R{pBOPX|_vMVAq*UvCI6+h<~(aKBu z`NltvU%(A_NUr{khJHaI8PuC)c;OlY8K2(sxHHTwnV&TN^Dm zP0++6iK_8=M#2|LC7I--q+5$Ps|@C3q63b`Xvt*<5CpZlzq!4;e`KZq1GwL}$jySJ zt*K?;G!k*sS%wjW$f-t*S`facS}dQzhBbpccX0Zx`66o+Z@QdGa#k3j9B=IYy7AlL zu`d4EmXmBUl^qnPs3&DCNwqOS-$jN|#VGG_ECFkk&kUu~g#r9GngwB)6J_}&!Zuu) z7g;_6x)m0o9_|@q+;*u7|z9ZJH=cN2#1AMWyA(@@_x1hDbS-n!;WI9q@H-VcB z?U)&MU`BWPC}c`6RnRuL8;5UM7$hU~_LAB}$4~bUj-|`Z$p{QEbKE(z)JeJOh!!tv ziLxJ1mS$W+KRB3J+Llm^UJxIv5pb~DE|3`7U7mXZ zFS(4ZYFegtj^*Rcy@+PF&8#Fx&=dC1RP*K1~hE)rV=fi|N#_qKZVGK?ujx zbcJiTRBgGhZdQBI>!M0FjJNqoALWH~D;*wTM8R(&`=+92unm=TP*Pf)QTq3kz05?V zOIiiknO)R9sALyB$Dh(NFsaJO6Kk@}fI? z&$plNAN;oUM1r`L7yV^p^X1FuR=l_JqNw3I+IhZx{PgAC=HbMmz>q&X*giZw-rU&T zeFB^|msU3u$Ec?%d(%ftP@I}vhe(v*8-PNHK4+5|Mt;N2S&DH2aK??lN|h-3H+Gv*jt{7t>!*Nr$&x~cv$0})LUCwjH<+Ie1v;H* zc7E&S&fd|Bql06VOstbZAN>QA@+{^;vUfigU2IWFv;D1y22-IJPmY3Jxw#UkEDud( zpjn2a5Qq>23qWZ-Y~@j)(Tt?L0;^;5UL z1z>XfYH=Q|74p4JHvj>UmI9dAeLdTQ(a;yI`YCq0dK_`^6YjH%II|kO_g`OV8QFx4H80;lmb*q@>L%jHa65n?ciSUBg*y0k9M=TA6${V-9~EZbnf-FJe~&rp(ptC{xM zwm3OC0WJvnZJbES&)iN=If8TttvFcmj$8xlkx@(r=K=u@k_^qpB_%`Jf5SEoG26eM zk9(tZ{yaI2>D+5@(6{}cSpkl+EXp`0aegE}^+@wQl4zK%vh)cPyHyCV}tTLnF6Hd+l0Ratozn1(069c>>Tzt}z?Z+ob;^l16vicL}#OX&ew)YOS0 zZpH8i%`$=dfsJ|2Q+|S5vTjYLq(;*e%lsD8i^p5rPhLJ-Z^}FLi0%uugvpuXemX)t zk#ydOlcN(~i8IuZ9}F*Pg4VBOj7QxAE)c_>P2G)_ydxWGI0O>65P2$PXk_J9MEkF9 zJXB$cl-C|EOGz(ruZh)$&Yu+buHK35G?MVq#;-p|7*l|wVi?X%N7{o`4;6p78;2^$07(Rf;6aX-opR^xY zkFfgnl@Ai>fBmzJdtIPvcdt9#nZ+JN$02RM>mu+TXlDW|$_(jK3l z%FT@8E4~V^Sd>NiD^vF<6iKM!X({%)&%1jqWMAwYshapo1;^gUExs1EQnrr8L>MVI z^c3cAO+vt8q%f}&ihLwWNBg^3CQdxpO#Tce>z74Y1mCG_C>$3Ele@7YCxyv? zi^xR9=j%NljfQD^ELUC32@5DgO;Psb-BpK2aQ*CUJXb+=D|$0wzbdX~!6~jvl0Zlm zw3>ER8NO>JUXgL9tbunaXt9Y zn*Wvq7}LLncN{^S{tdk24@ezYp9|%-F9$>VC-`O;ll!U+{}kSCoSxF;$ltV@T+x|~}?iR*)^2E3njs0!PULj?}eiV=3-(X;+uJF!rbM)x+- z$Ph0{$35o>DyO5l!IRNiA&}9Nxg&h(Ch2lv(15hx4I|p)PL{n%lQqw~L$I)lj3L<3 zB!AS9ev0$6Xw>fE-!(f4YpZRSwP`xS^>(4?4Dh)jrtNVxB0mx)-S!slz%^tH`EzfGrwE?R2DFCrI$tUZ9b~ zW=eWp=X%|0!y3I9Vj`r`RduVrQ-8rsO0`wevTVY61fO&n;kX0grne`7^OpKyXMrF>Tg6I)Nb`O)Ok)|2Di ztb<;ySU@SEFO(Z8M?t|f8J1TtS~|QqHrtQT@IZy_P1yBSRLf4Tv6MYZi6SC756Xck zdKP(FX>^WCbLCg=#5=W=rsg5J{l@1Q87w_dd-1S$r5PI--X0%LuB1?5 z6gtF`?ss=g*`r2<%DG6i*ivddkN_hTK*8j@BBrVk`A1gbkTB&g#}=|XY=p;M538#1 zbu4;|#ltsMHdJSX*__}u(9X*~MbW^VB)J`w(N2F41<9L)v+}me*Ft z`&0YWg(n-qh1XK>LYu_~m=*y#YpMV)>8sXTMip4fh2gB1g7Jt0RcGhUS}E0{Gu2j- z50~I_$*D=SR3Vq`0^ZxlXbuuf#0e9~QD`=YSWpM)Ea?q$JNgkDK&j}S{Q%u0Axl*n z1`|)3uo-9Qz~sFb7|oBV3}1OJ!bdtG#w85sFpCM!bp+8N`n+@7JV29az({&6Iiocd z>+56`@rw{Ut%c@7VVAI9@Tj z$tt&9bOxoJb$Nm8iJek|R{*Ej*(D>p2C?l9aA>t;93ERAiV0?n%jn&w_&_CCm#@ zf-1^|1dH&(vcsWet0#)y!x2UZ0LQ>fDL4Ad0S2+rQ5RKYCk!VG$cchMpQw6utCQpb zNkONwK8~%Lr`QVLmv8l6ezeeR)%XIz9WmbwtWRJ3_>~HjQ^@Mu35jOJPI~ZwMbHpO zbwFkkmqulSOeg?SK&`)FE85YIyxcwu{@%!?aVytM!5x>nLD4=1zv48Q?NOJdsnW_MIaF*7Pows6Gab>qy#!Erui|2Cwb!Du z(7{%44Crdo2kaufqcBN?zlc%WYDaVNBuL2fY8a{t)HuZa)SXwY*K36;{7UFuMX$Fs zu5_W{PzqeC4efcFWBk*&Pj@huT!=8vDkZ(ue6w|PtrcPXirdP%zcngIbC>b`y9SuY zC&}pQxJP2V0>GazAo(dp7edDgJl0ozj5&5HYJSpiztPZ8?R`ATjwz^g!KP&sp9+#f zW8+`8o@}d}H73@Af@LnrwZL>W*KwTnsI|_QRy}I0+liy~GAM9apHhIVmBi$b(&z{Q zd=BP6JI%;2!ivxW$J&zhcsmi#ygpzoHd}DyLk3U>F!kLE)kB(bjIS4$jv1UT0rwag|W9%(s4|r1xLa)?swM85r*<= z%^iCe4w;We^F!U74Zgvi6&=6MKiiU9>pQfEsbc8Q$p(Ur4(z?>~G}p+Lb|NG4wQF|b5Lp&wAQc>$ zx)RnxfOehBMH##BB^rd*nFMW9F0yF>Iv3OqFn**fd2ax+p8y+eIntobZ(4AG3p|3wD%qUvo$kkzjWIub;m!Rn3gnBh%zano*&vWcjc_52^ZIN?}l_6tEg%=Mxj>$99M!` zBq*Q2|boP>fvOiu6%oRR*vCgZ{)Fo>yFaegeX)ug0)`32$FWcRb8*|fz>L3L+3+5*&pO<<><+lz6PPm@Qn!H^CdBI zTagyA5~5FeI$UvmZYPYhO4pTX3Z-UcJ&8~jmdx@Z(aA1NBGc%}_OqQm%rDp1jn#cn z3?%k~Y`f7fn;NAJCi)Y9Go0@iayrphu=l=}9E~o0-&-9`zOH zrU7A!^#>R{TSwCrJssg~#d8(GJstOYlH4S>`qg4^hbV5uJRq)w6gnnel7ZaR=&E2K zDu7ECK=x)(30t(#)z5Q}x9LH4k-IbYhyl@Cmo5Mnn`6S&)vYw$&jS?5ZNYesw(C|b zIg@DNBfuFZowHfRR)o^xQ1@^V6uQtuZ8jQ09#G;WC#We&ha@!n&3k7hvLodUrVl7PE#f8XyE$-f*e%%o7)@Q@DOS2(%ii`H)Jf#2(cD=P!)v`$7O2|5DUpWn?T(&`28YpijBUPsmn|GV^)zgE6DHIA-$D4hHZaK6)h6?Pus0* z*bWRFNoHL>H(mryD zJt0$l0~%X$rRHG0m@6~n@YRTCx;BheAu86`yj$vvuHhW z)iDYag`x=N`rgau+Xp+F*WMWbY`(RAwEd5xg=l_pU4`gAcy?%6rw~dcjOp2gbnWb5 zxIu=eq;#W&CIm!F4L(iEJZW>8KY z_?*Lck`2Gy|JjL3c*}$ZhGY;eP{`8EK8p617Zb~%F_v$LB`sUwhu>|T^hRsG49-er z7_Q}Pj4hHwVwzNKT4h&()dY-=_wt(IV1-CCDZZn<{UbK(p#wFHjdc;ayu28u=gQW} zsc#xfO`v(iCzj^Yh+5$i-ba^x1&5T_K<2e6PYh>IQpDH(@xsD_x)~LOZie)rnqjLa zH0vg>P#jejDwZq0Z*;`EV{~Ih`i;T}IBH5f9JH6=OsPKLEkgE3;xI=l3H06R#RJ}l zTib`5RBPjKQ*La^gd`awE;8d5j6*hI*~JBnFZa;R3$yWZ?`K7EtJC9XCSe(RoNPxh zLiKR-=otE6i-PcIi1gEvwHPWA?>ss0oDZrc75B80_mW?cQR!xO4m%+!tB+27&o>TX zG%F%#%inOyMC6H-R!9vdPyRV3o9iGfm}qBG4%xXlit~=jpGF}ff|Y5x#8=&}jJZFj zsJ(N*qmbI6VbJd46hU&I`80#ZJ(iV&QACHy2lmA*H`O2t;GIh5Jo0SgZEpZ_2=y|S zQDpOjZR8usOx{gx%@jzTf(my`9CNz5Fr#qX*P%)}v<=c6@QK^CKH$tiY-E%5lF*9o zC;g43PHa1FdO4~E6&uo|P6RE5axjSBi^jqWa7Ni4LuMCZDZsr*U!WPZbe*j#GLYX0R!dY8^=~>=-BGT)>`wLdMWqY^>W%`-PDEBnzV1kpb&AV|O(taZW07FqvpO zFN{J_hWm(3gLEjzqYUXRNjt@Pd9CD|BIg3m34>@T$+7|~`FBkyBf=}zI_H*36F>K@ZJZIP8jMjre5|f>{ zHdu+tH(L5a$X8glrw9AbVZh{REu>|v1W?9i!y+%)N9TI#QVrZvM`gXWASV(;v|Ldz z=v=HSdn%nG6|LJNlxCUG@0`%|OUR^z@*Yt{Apre~3cpr}X8>m$_o>e4!Oll>19m@h zwIq0HvR!?yUE>97=)R0>MUZHJ1&5%vH2nQI!%x}N;6s{oH3#% z9WNHy8-i#2fgAc>AA~ihbHRhnr*VV}?Y;#yQw!__UAf*BK4&XBM?xcACDA}uMbn9N9thHBM6FxuKe!6|I zy|=l2sPGh*A+yR{x<@@gNKD^QGo#Ej;X;st`(tapTvm%V9-4T4hVggy*1uAx)Tz95pvOKysWLHlSWbrK0 zSyo%Z9gP^$N_{GA_sAX|8BL;B2;ce=_ok1%LW#VctXxbw#OAx$+oE|UIayiaNhU*b z#RTLvK=b%UgsMg5DrX&qZD>eXg=wP+K3C=6j)kXW}}RLL`}K!q--tZJZL(ga$Fg? zu-~MB2sOzXR9zEVDGp+iF%$1x zrW%kpWqQ(l0!wDiRDy<>&~6arQ;>*#um~*;X1||slupAR0Z?L@1#)iP+Z1>Th;m;r zXI(Km$O>yEsCYyvfHwD^Ki@gh(AY3lU%_JhNX`>^)_a@i>sC1pp(+H=fM^-DjE=~J zkATC9OG^fgsNy5wus zSy-k`5@LJa-=4+C2KmZTbBq;$}vnsK%7UUBsqQ2?W&SXl_n2WU3|K+vm2f^b^Z7~W!n?L z_JiEgVAJ(z68cHZW$M4}Q`QwL3#I6C2SFsZ9*6{0*U2%7F~iM7eDbqBa_%sz%rXOQ z4>BY-CNh3x&had;5<(qpzu4W_ zbb2-b4(BrEm?~OUK!ycY2c0Owq5VoT#OZTgQ+-UjC-*mZNKDyLs7)(7-B3i@nGLP< zga_L|lkIFC)qxp4;>_k)Wpm?jb7N~eibZ(|IKC$lVerIQxAlSz#ZRxv$AkQ;oxP-A4*jci=tKm2(L$IE))-Xa|9qFSh zcQNiY@};GtBX5h3!@n5cXFRDicMKN@Ssv zw48ucZT7{uiNkPW=PA-rBf;rHN%bnglGF`$VtC^3CCsU@iK zQWkz2SoltplXQ1l@^_KEM~VBkYwYZ8ZT|ymw4(hzuDDq5G&PgH!_3~1aEQugMh1+X zf;x4gqtR*Bigw9yVwea)38BMwSc(t+%Dh3S0b1|N7PkQq(9xHj5?gA07VQOt{-_xL zxIWs#%ec_U!r-=f4{#eFFdU6qt;TC?z>eCWI^}33B7LEJDBEkL0pq$1G*l;PGX2N(+!zQ z4jszcFcuB6pSLADJTZR007ThFIW4cty+t%FM*No>nzJBqu1$fi5-%8?9*1Rh3n;I5 z$Lr7?Ea_s9exf7`bjNCeCh;L`6HJh_FBU48;S^?9Rx5~ntX$H{5X4H5i`C`J2(i6q4+ z+LhM_Z=q6!!3&Ce%VJTwJW+w*PC_9LRM^eVx;g9S)~{PPHW}(FvPl6!!MoOeIA+zp zwoUoFR{_uB^e|yxyIxgLP!y;D_-2S&<>zQ+v`y9nD>VhzD9X!(2rm(LKqU1zn5oPr>(4!kYBtUkO!v;yn@caHm z9pg%)3#7?S7D13%0nt-dUh=!LIaK6x9Bs53H7(r_#o8s0RCura zOHW{W`Bl!2zb=?Q_F^?!Y_55@z)O0K%o&ZOxE)A4=P#MgMNc6CDSBB+G&s*jkKqEG z1t8N?B@Pj(!4X|098{hl5A|m33L7*`G{2l{#~3^$K0%~=Hx#?yJUaUM_}R7!X{Q5` zvsp~na`)G1z8|kwgpD9c6NNd+S#!*tQ~`=iuZTkvI0WRBaKUgM?Yrl*;e7JXaon57 zJR<^FXC2p*%dRhpJ6(eV%9erKlE3dJCnL#h)HZc-qs#j=mpc%};EGFB#_wX>Z?7m8 zRW_VX)4T?$ExXFp%4qFnpO+BVfWk>zUD6gbM3%bUt=mnAB_2y_a2fF;#`8n9PsOun znC4oJM3prm*uy(_NLtCdIdFUf58p5bqT7b$EjkGqpG&39bN0EW`G@BbI>Q2=wY2~r z#P)$K1&wssgg0dsRX&CTR2(gDeUU@JuH4+;effOPtZjPaDF*d^bF3^#fnr-GS>3S+r~AS7N( z&R2tLKhK@qI6bvyl{g{|QKVl&6spkPDnh04JbL^0v+BU<&ff{FM ze*x`=QSKo@xf*aQRDM8Ek8u}O>Ek>$QL6~ELHM4~x$iX6*V|ANI;wm=i2HuDf=%cC z$qMJ#*jOF0s@i9jFe=VqeO+UBjRIxGc=KqT(8Qq&?0NKhHsYW}+Q!GewH0E}wXo;D z(<=_ANFkl)AH%{xHF$gQa=RW4#=YLeUJ1q*#Z*FVVqb)vRh?9LI2)GOaJk(JA!Rh~ z%c(T#)p{J4aB|;xpQcQ@I-7<8J?1U*p(IAW%5W)udL$gO^!>vnDaacL}8sc1)I z-Bz(!-HJ{SR;*@+VKwdPN^bO3tl-99l`2*%ZrIfj){)R__SQmPF&l7N=5p!k%!*L+(n2&iuw9kdGDdw70igRN+gk5^08j z0)VO7Kyj{9Zz@3aVB#0P6iE3ubKzZ0|Df;N~@ z!Z(EG-=%a7=oncPM!h_&f!$NN)@cw%l(k`Jg$Mvp>1cJ7ChIcudUcG`MqShQoZmeW zorEURH8OD{dvis)NP=OV{YxX@b!B2+h`Q!*6Zb)bzM(sfshH+L%Ll4)j`^F-N&%J!`WrUqFt4*MI5c9Pze-$h*E>ce#qbgOd zMZaw9zT7^<%#KS$RiRMo=wRm=8atw)YxHFMDVi{dp3kbL8qmUc%9^kc zFCch*0O=@eOMXeP;KeJH>0$YX6<$GDB+n8));2nBWJ_iUt*9JoSiwo6yqAiBsV zgTFz-z&Lqw)0I(0s3J8;3{M8*Twj0V2*bNBUfJoESf^PVVG4|L4KAUO*{@y)a0>Uw z#wbO^;5h=Ao;hZ2-ODmLFp5x&mlX?xV|yLD;$CTvUnwzD(2R-IlkNCW=JcRs!tB9; z5{)*ySp=LXm{wCkX$={u6B}`ckA+yLa*)09tCCB{l5~NBjwwHR6J?tX#p;u+ZxKs4 z_Z@iw@TjBMwh)fC$t`#b>1N=6>vXC7D|Eb?D^VXF ztW65oXLdnq!uQ$xfR7u3y1{Wn6cjvd(!aoQQ%v!ibKLY?sC0e4Gr<(cHB@?|m&Unc z3|x6qF$#^SvVr6sJ~|t6jD5%5v$9c9047>HHV-I_=l;J zDe=6DDxLc^t zq3B3rxh4BaW4;A7)qIuPjM#r+V(-1}1BYdlt#K8-Nm+oF_WP`QM`keB1F?YYZ5+Kk z*x0qg<+~~**r|QYX&(0~q3XNaPmipSNK4As1|>k*7%7K9C7^76I*ROQ`0V4w;=i(5 z`!A2I;Wiug(V}-1G$Fb`b2m;_K}r=Dh7J`&Fj@-6xX+o#(V(+0_XeyAb%LhfaM#-H zpbxAxIt^qfo<~{!uRm=AiKZ?$MAdk#Vj~{b38|crF?PfQ2_jHV)@rqqeTk8_ca-$I zI^Duxn7&nJ32d5xDz6USP-8idj;9*2eSEkmhlIJu$oW?4IdNjF99oLfN}ng^KKu2Y zt)nn1u&e&3V7;ENpiSRs@@AadYJNl+YsCC_@;2||7(0c;MBV~?ZYH~<0!y!XP6+KS%0)PslKwbHEMT4mjtDA)v+Bzvq3!? zG~u^pnJBP`+X#9@RUGI_il-CBO=}a@3Hdp-ha)=WeE$Axe`n9Ky70x|Xzob{OsSP& zjt~*XhtG!L$w~YB0~98_Xwtu}wc>zGXI!O#wL%BUTYrYP#D2UJYt;}YgF!8{6Vt(^ zg`JaZ@v%cmhJ=<==%jZR_ueWeJ!85>cRWR+7hcFjRAIn0c6BGRnHI->>YbQ+BQ#Vk zRAV{QL~{z;##|W)a>u9vlHkU<=%2Oiu~>^y5qN~YSIkw&woFG?h11WGV`26=)8E`c za{Wb`NF<^~N%<`YPB)gbxnB8%%RyM1>Y&ge5i4f{;|U(dwU0im{ar7VxI>NFnBQQQ z_-)eNGc+12P{e9XiOez7waSk`Q}`q~P5V_lCNlKPhEfiO`SKzZ3o#p7rQ8V|2cs`B zv)Lv~TEgt2xyS&CSdp8E6G;-eo|Ka$TSG93A@^R0p;Tw`ougwc$TZ}w>5O8V1{gga z)=SvaJ;^0l_caG(lwwquBeqEL^`~inFdoVEty7;TeYPv%b0m5PV$Dt_^sSe&eS&1a zpn!fXiN_q&0>64Y%chI#> zoQtEVzkhNfF(Rc3C+FF5Vqn>o9IKuj^CnBHg7d5xT_Qfmm*nRnZ3PO#A9__KiL2XX zF`L2nHQ53^wC0JB0+hCG@NG2 zu54S$X9xQ)UqnxS3pMdm{8o5Lr-`37ez90ezYP-XyKU?rYyqj|wW0a=7f47swys23 z<#PJ^wyjdGaF62htve34P+e_Cbwktn!F{#=^y%UDk+Fx=5f7C%$0jHlRO)~dl5z-_ zQ%!NMdEu8F0~^oSh}$s8mb7R-y;ge~QTG)!!pD1{G*9{1{_-;DlQEY`==PHe`m z!dk>eT4Dow*+=9qKg&Tt*Ff05>?A50wS4oVJ&5|XY_ z=!K>zaxUlB9=8>b5jC6Q-h{?!C_){YRIETNbbAJ-kxu-|LA&Hski&9Zh<}<#RnqZQ zl#-9s$d&l*Y4xO8tJEB?Ao9N;P9WAPj$!n1?QPZB`8Msi{H7@{?#T z=mk%@Ok%*gY{LpB=ZCrFCRxSZ6Jp4;ev#;el>rh}O`>blm^-%U9Mhgw0O#i&tLim| z(yj=`)UY14v(Xt#>ihH7N)eH(?Cr$IJFt!>m!3s0sLbT{JTQwk47;F_YP)E>=ULHl z3>YQAPS{RO`KVG|6mT-l<=v6|(7gr4c2wPTq>NFd-jPdws%&(afLN3Kn1zWeh{0wL zE++|IGBD=*D3c{RnQsmkupM$mW^I8c!_rDR&)3%*b)E|2o$p#7nKNY*VrogWq|8yv z!zo8Mh68ry78a@>Sa65duIR{uO}@Mhi?{HF z5G-X-dFqr_Pe9;~rhK{_K2^@6ddWRd2runR5KoSY2q=1pu3$vp*e6)+(bHbm#?Wm{ zyrUR?D4^{%VW9=Ch$L&9>$Z#3p&PW%j8D@(!%oq>;(!D7Gxoq6&`A%WX`Joh@Ogf^ z=2#uFd;K{qBl<7dR)05fbzGExrS%JbL>a;`y;WKILov_Hy*7!Xa8TL-fh znRb=YOB}4?__Q3wX>ZM>nIdf!5^e*ktCQ>{=V>SFWnSB&^4d!-OmZ;NTG>8e?1>Hw z!h$ZxFO|Rq6ZXhF_fJz5SdBNA>^eOmIda()Q&PpoRaX>eJy1rS#(Hz6+}aZMYEK8t z!g+T|2qmHsXC=e1zzLXO-G$pe=lqgRYPs?%D(NXSWfaSn`q4^!)(@yQ3?PeG7tu_P z!C)-ebl+^8Kz));gzNd{TW&yljkOEbXH@x@c*2CCdw`)ZXxDjV7%B{`i#J1hFQ=0H<%OBBkH4Bs~wjtbM6z!~I>x}3fUn#Q}(5}0XTgKnq= zd&)!-rNnl|p+zU^C3%xWdRVpJPh1TaC5%Os9co=MJif%gXkVy$@7|bZ(w?LvMj&Em z3~2a8OJ`5nit83`j^9CI`bCs4_Yr@I@^j`ucy+Sq%x&5XH;ETPl1;%-t2 zf{V3xHx7?Dr(mnJwn=+itiO4vnqMlduT#mnKc4xEf7IrrLuO-Xf*@Log`m8C&pjh z1o@MWkwY}1afOh*DfM!?D5A-AT@YAyFhOVKXdYEO(~8v^U7UIl0>%y=ydX=)HP@92*zSXHM-Z9t;(Cv^x5pv>=ckRcEt*xRW7aorUdWSnGou4Ub3XYm>mSO)TLptv4CqEl`3FNuP@B z4Mj-6$Y*#DSo8;`+R?{)O~ooU>6+XFNSToG;vTYzqf1wGPUuY^i$H`2Ke$6wpljR% zPkpxZkTlhnBG*PK2uz2Ww=5u~Kl2K&sEcc-{Ia5E-3v?FymIhvmA@b~6VJ6m^P;e3 zt>7CO#I3T&5t21;9`;l7v|usRo?DxHEAW)4qLkUn#fPWum8veP5afsK@%Z2pyS#ySc=DuI3Uq#-!1Af+zG%2z30 zl_jlagJ^x-V5=HF%!U{%2Y2ZFV-*p2#5S9o`+HA!F$$oLnu8UTqb^l&v4`zlfH{Xm z=!zfp2-(6}u2&m%C{#h))4k`55@r)Kh#~^gO2)%e*2zG>HbgFB%!vcJTde3lDE}fT z1FaIgc67$KX)~|j1vWTP@B^o>xq&5~P1%0v9mH?1enw=AhyP8_$)Iwn>fr)nq!)Nvr z1|vKO#ShI+rXP>*r|{9^aW?gaoq$jWhBDn$CULd|LB9>`?Bty6PS7o#nU9xLvRaF} zS!b+`ZwW6ABu8zf07tnts`>Y6Te@@JYs<^Ek0j9QR_Fm^$Vn*Biym!7V@yV!g-}8S zSMIMab}{9lBgNOVxo(-_2s%@CjT6#NJI&NN+C)Bnv%=%!7~e1D({nKo}9_%mC+s`%p}`! z@wFUbm^e~C49RjN1WrG>*y&y>SWdPLCppwxl=7=2Nmk5!v9UvuJ7aU*ymk9QBMVl< z;Cz8H@OTe(@awm@uMn6D!=skL9)n{)7*hxVxvQjfO>SZyAcC_^@^}K^mazs;WI)`@ zPBAnHl;WCo>IRf_M_?_6P1X%CT=A7qB9_5^Qo`#PW{wGQG0G(Rk-N2ElPMZ zx3AJSq4Z3PJ5D5^7>TpGqP&3Mi(1}Xil9!=R}trXptMo6vVVEi6KNwtk_EFgpN|KmgfoE zSjT>EDc7m)r_GcVFb@yk#Z)mZeVg>I z%#KCN`_yEe9woRL>Y>S2iCPfcLXcL$ZoZ!hISmTEP=feOvTYXyTG}K!=OG7VSQZEG zWl;qRS8N5Np?C7O`DQyLC}Jr7-OSIQ9IEIzz|Ot${pYj^bO!}^sr|R zHg*oTtDH5UR+^8hKz@a%FraDjE_YR*%ppX@YmTm@o4?*!TVG1{C2w4=6pj2ey=1R@ zWnPiXvA>Eg;@%rSOrtU)?-n9T-=g)!slqWL^w;CW!|7Y*^ooJXYD@{OgR#pSyK_^(%g(RVA8-& zua?KFWQrgV!)V^zWr^EU3l@{dun9;|?s*bV3Cqxaq(>2h7iBDf*EiOa2xLTCVc;Ky zLgn1cb)&8D5uD^$A&V=i&UfwGWOyc-5!>UmCpXjuTcGz0hO!71x{fe~6H(6n%pe?! zXiw-1mNglY5fH2l>Ya}9)ErC6W9Zd*pm+Wb-b84AsBM&hN*HC7#vFGax#7?zKO7Br zHqQrDd-dwhTGrOw;(OPWN58a@Qwgs( zX&`kTt&|iL1Bm0eiVx;Oh2~6`2p$(KLgcRL71|mPj_oO&TzaoiJet_&P0VA#7VD-% zI4wypPl6Ls4GoH49mE&al6hg^Ws~7F9hw1e4+V!^7&Q($|{?$+4zs}u^+rSLpItykd$r-CS}N)R#uEZbKwU;)Jf4O0ZaZwv;oS1f>bPl`~n zj0KshxY)6uj;dliz*FbX+>2p+dLFB(c7`k`#X)p%XQ+$fknAT6^g?NJoFu>sd=a3? z;uK7gBPyV7VL;30>8QM@Q02O-z@fqx-#=lglIjC*BYx&Jun&{}JVtjK0##+J!nc8; z9irbc7b=^%;$SzrUDngObqa;{GD-!bw|@xG3(gMlzqYpn4s85z6MT-V2@ zy;in{*}&6 z03gh&1|6Uii0D%A)i}%)sUoTkr)b%wg70=t(5&8tZ1!5H{8O|#pHRVB<)^8-2oxf9 zDM1HwIW>35-rT|16RJvx9MdSD<|!Jr_d*{9o*VrxZz30jKD-V&Gq?&Yx{F!^6ZuQr z8IRAsi^!*-r4Unm^~exOrqr`u)^<5vovB1vz`#QX!fyH|`4|W`heKgUMv4 zEK)MUuZFj=iD$~G(@*l8863s@2I%VzASX*`>TdE&GE7gdgq$xW$_PmvnbeQvC7Dhy z77ceTSk9fYoqUt>d-q2r3%Zl$rd(n#hu*n9WSVqQ(YHSd0Ogq-DExk-> z!~8nr>a6p&_e_}X50($`-YAI)T*!1{39%L^)H0S^K~j`Mm;%O97I_h(zp;p+Mngmv z0nr4Fb|5wPj+Q8duAb6WK9Cp?PsV9)l=c;n5-wVm-ogtqJx@Z#EfO<6Nk&)u{YfuR zPA0r%tR2QZ#KCU@4VU@{C5U=RYV9*%YE~4jt}!t_WNc8Fu%{F*y8zJGh?MXu#07e_ z!lb@c^2MmoL_p{zZ}RO+Lw`l4LPRy}e_iIm=El2-gZyr~HRQXHO!mnyHv|tKS!APC z-wP-qNWTWTWi$0vdl`_dbIiEyx#E*Vbu2ESv^e8HZbEQ_W|c!6x6q@d@R;^@;FVGR z=ha`8p8yzrlT>X2*H8W z;Ir0L*dwDT4ma9XTS=gbvs<5__WLOieW)VgX*FR2T)oA+r)e*tNZK>yhzUceCX5{W zFHY+b!H?$V1_S!!()Q^kNySA?4jpuGWMIn#1^`uMS6Xm_;s-3rVj8QUMpsTbQdO8z z0k(w8c+H0I0eEX;Ra4xfQ0j}V zC-ArG=~Msq_2)n0XY0wtTKZc9ejctYJAd(K zdAaqsCKOs;T52pVu0Z+4<)y{HMU5{p0b>k08%2LRk4K|P<*s}GANr&3^kcq?{&9Hx zlXly-o}tG$+LqkX4`KhUCp*!h%7=M48lRj*^U+4P%Vt>5VZs5o4o{Pq3>a_e$2g_$ zZEtTKLmyyxzib~IV$`+o7hyj7o!+>cL_g50g|o-zQKj4Nrsso&vx-#=o*iH2XIRiG zDcPo>q`HOwL(c!`!L7H^Xe>1zE-#m!fB3=k-)bx_EkAtNfb-vKwU+-DEq^`#f5!SZ z8tphwI}4*Ph5uWNO&|ZSw3=V>|Cbql5*;P^Xl>@n_OqS6=sl)1>5~a$9<4u)n$d@u z?Y%8{p1rBw>t!)u=Ndf2da!p^S7r08&B)99_t$1-#-u%|R!*`E{b{rDXfPfIWkIlqeTb=zmrI)0sh z3@l$CSz#cHQiTUryKQ9e*X69!FC1q?9#GSKnt%LWm`=!!I3=>HP-37!8|XL!t6k4InR{I4vpc;|m-!{_2{Gpzl${lg`LPp z*a@yO7$#&2AR#-VlLe} z;N2N+n)APg@Y0t#|BD&`#&hTi#athBzK|G&ch|NU*B`O+h62TM6okx{CD zuSfWQ%{saK3E@zz4s~GFajrZaCS7dz36Qa;Iet2UC%^yLrtb@#?7UJFXbb>wj!k@^ z$5eF|;}{i(R-bW%;m<}nZATY)I zJ8*ae5GE8+NZ}+Ib}BKv>c`ENd4D(Zi}%K!cv=f8Cu=YJ-OEFvGlHtIe`K!jjngfbrB`QcGi zO}q7|*X|KfP*U#bU@xlnvwDPO|2ev%vQoH1-B^ph!T1mt+3?NZEhsh_f{igDQUx|* zcIRmOd2`llwWNGY%D1L0zbNGwCzZ!RN%`3gU_78x%TpGA0>zi*G^k zMMSBl_)rXjooOyb^fL<61Js4Ii|M|1w(2-R3%gHt@$1pf(eAdf8aaIVyo$?8ulA2N zcKL>Y>UF3z!-3im*v=L-hH!SaW^}3*d7)E>$@i`8!_7*q9Pd{xvJp0RW4lqA$U9!o zDN=ZUre)(T_tt_&jwxjPFgXDpRr0gjH`Xd&Sn-y=us+=Qx(VU`6$+y8<>bE);hl&7 zA2z?rfBt&-U+Hyb0lUxE)P3Mz2ebBdfF)t;%Wr`WtViS#uOBpsFihUYoGJSrMuZ2% zGn?n#6Zk*k--y3;^Aq`moncwcy&nb7bG;7PM5-8K7$AsRs>b!GU7KZO#U-r}qgFu) z1B&Rsb(8Xoh&yLPU6G`090^TVJWjip6wk)$BGoTW#kCz>u6fgO)ARp`yLzlbhkPm~ zxaRyXFE@St@AAXeSN+dlL;w58K>+!<9rb~~;>(CrXGa(a60gP&{66k>TT%cJL^Zkx zhwWZFssWz(@px^_5A8MAD^4b_wd_#)L5ej5{{f+Tt?L&kJY7!KUDNS z+@P0S_=D39ywr{Gf#I6n6os%VL=HwYx=Q<}tHcT(n_HFYp-t?u0DP|=^7oe25h+nc zOxsl<`X#g0)mbl)_ukj znne}Z8&Cb6P)Q|HR(1 z^Dy7UiQuodFcl04mZ!!1$P!Q;%d_PZ(+u>Du!HUzeY=I85ggn%h;h2GF?65qDln># za6ngAp?p4q1NZOfK>#~3ln2GmTPR8o!FqNJ1F@h5hofM@Ubw4KRrth8pDnzo`)obC zg+5!*s-ND|me0#!w-~oeq^ext)V0z^ctD`dE%`t_43k`Bf_jvnr6(iJjN~c{M8q7(dn)_^ErShnqDun;ihJq1M6oZ(9dz*M zT2;BC^9V`^(=_9-JRJh8Mv}GvFx&Wc2cwy-^u%V$ny+tfWD^E<5~sZhBh$_G;vD7D zGA66bRSZ9?3fPRaW{Uw@wMGqbbZbn4fINWbxtS^`^N-)pV(Hlrgo>g1?3z>7=5?bf zp-|y49JPAi${=9r%#chCfYZwpZ-5>MZV`6?Ed+upfC+2}nkM`{d7f}=w7yt|hlQ19 z%QgxNCFI$SL92?h&VIq%+$g}kPTaHXh*5sIsku)PSdr>W-c**Fot!?hC}F1@9IVp zgVKIRTIog$rMvy3hK~L8I8x`l&z2pNoAg*QUbHkHb52_S!7bi!W&Vsd3FnbL zbdDY`SCdV;G%cD@EE@n*+aLo zy80|6Z$q1%U5g^ETELOOL#*r)Q&j<8TeI#7*~(OsUW*inz`(BdH}R~leuD`&(8K8d z8-VA?3~^`q@ep1J* zSe+yiI*HOH^pm%gd`U2sfWS2GE(XWveM;(eB8y@XPq#F?-e&$L`YTSdsBk9iS)r8a zjC-4YrnrTv@HAWa#uH4C%eL>e^9m!QS;)__F%z9BSt zZ>PH&S-YYB7UiG#U({+emL4=7!T-QAt~M4|mmftqLm0j&x+nE1-wu(@j9M_`o6Z=7 z$#A;E470_J7NSEwm2FIDN~U&Qf)Jlzeqn4KI_2G#f?#`WGyk{d}W~lRfJi4_2BB3k~W?r25go8%Ex4adlWa z1&Yd&pyDtY!gm^F)deauP_1mneNMYZq5`s{u(3SbRMcngRDK_Ar<9ZLDjN@@oFJ>D zZQ}v$kKwpa8R9c46rIIyF`c8XKfvtTlKYmjk##T=uH^XLI^2uy;pRKWt)uIhJt;c| zH>GMvI)P1Nx~wF!S}-79^b*{_#*@z*fP#i#RJTKYmVAqF6AiBx*c>#nH^v9G*`LQi z1@|({rwdKLO_;O-7A+eCsnxAV15BPrA{@2~!*qR69IEqHtR8VjD`Q6bO+?Y?aJx~u zGu`?40*1Aq313$hiD1y#fq3m)M~YvJD5h- z-c&+Q`Yrtk098wfLXLBobBtT7_9%?(G3J?F)2HYzSEu7cax6G%vc-2LwX!}d2r?3o zt9(c`(&%#Q1jjl=JVRXeg9|z7cWJxWhDhFkeEktQq4LVe`d}iwtEiiv5Lq(9{XCmn zCC;y?Tf3Y&NDbOW3+Gq)KYM@|pg|WeoWqqr3$u?~)SMD>RK>HZ%B~XWMk7~k!6H

>i~d2 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 D)BfZ$ diff --git a/dbLifeLog/DBD-SQLite2-0.33/Changes b/dbLifeLog/DBD-SQLite2-0.33/Changes deleted file mode 100644 index 0f50e6c..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/Changes +++ /dev/null @@ -1,148 +0,0 @@ -Revision history for Perl extension DBD::SQLite. - -0.33 - - Set HAVE_USLEEP appropriately. This massively improves - concurrent access to your SQLite DB. - -0.32 - - Renamed to DBD::SQLite2 to allow backwards compatibility - - Implemented busy_timeout API - - Add internal line number to error reporting - -0.31 - - Fixed a free() bug on Win32 - - Silence warnings in test suite - - Updated to sqlite 2.8.12 - -0.30 - - Updated to sqlite 2.8.11 - - A few minor bugs fixed - -0.29 - - Updated to sqlite 2.8.7 - - A number of bugs fixed - -0.28 - - Perl 5.8.0 removed long deprecated SvOK_off() - - Aliases for perl_call_* - - Updated to sqlite 2.8.6 - - use sqlite_freemem everywhere - -0.27 - - Changed API to use sqlite streaming API. This makes things slightly - slower for large result sets, at the benefit of being more "sane" - internally. - -0.26 - - Update to sqlite 2.8.5 - - Automatic binary encoding added (via a flag) - - Better getsqlite.pl - now deals with new files - - Extension functions and aggregates can be created in - perl space now. - -0.25 - - Fixed Makefile.PL to no longer try creating a .c file to determine - the OS ptrsize - use Config.pm directly in the DEFINE - - Major updates from Tim Bunce to bring DBD::SQLite in line with - the DBI spec and other drivers, including: - - Support for table_info_all() and primary_key_info() - - $sth->{NAME} updates - - execute() returns number of rows updated - - $dbh->{sqlite_version} returns the SQLite version in use - - $dbh->{sqlite_encoding} returns the SQLite encoding in use - - Improved trace debugging - - Improved error handling - (many MANY thanks to Tim for all these patches!) - - Updated to sqlite 2.8.0 - -0.24 - - Fixed major crash bug affecting Mac OS X - - Removed test.pl from distribution - - Upgraded to sqlite 2.7.6 - -0.23 - - Fixed unicode tests - -0.22 - - Merge with sqlite 2.7.4 - -0.21 - - Ooops - forgot new opcodes files from MANIFEST - -0.20 - - Port to SQLite 2.7.2 - - Fixed bug in not freeing memory if you re-execute a $sth - -0.19 - - Upgrade to SQLite 2.6.3 - this now allows databases to work across - different endian architectures. - -0.18 - - Upgraded to SQLite 2.5.6 - All users are advised to upgrade - due to a corruption bug in SQLite 2.4.0 - 2.5.6 - -0.17 - - Upgraded to SQLite 2.5.3 - - Fixed getsqlite.pl - -0.16 - - Upgraded to SQLite 2.5.0 - -0.15 - - Upgraded to SQLite 2.4.5 - -0.14 - - Added NoUTF8Flag option, so that returned strings don't get flagged - with SvUTF8_on() - needed when you're storing non-unicode in the database - -0.13 - - Upgraded to SQLite 2.4.3 - - Added script to download sqlite core library when it's upgraded - -0.12 - - Upgraded to SQLite 2.4.2 - -0.11 - - Upgraded to SQLite 2.4.0, which adds views, subqueries, new builtin - functions, performance, and even sheds some weight - - Changed transaction support to only BEGIN TRAN when you execute some - SQL, which should improve locking problems. - -0.10 - - Fixed missing SQLiteXS.h from 0.09 - -0.09 - - Updated to SQLite 2.3.3, and some file cleanups to make that easier - next time. - -0.08 - - Last of the mem leaks fixed - - Doc fix on last_insert_rowid - -0.07 - - Memory leak fixes (though still leaks some, beware) - - Some API cleanups and test cleanups - - Added last_insert_rowid() method and docs - -0.06 - - Win32 and 5.00404 build fixes - - Added some more performance tests to test.pl - - Make sure to set $sth->{Active} only on selects - -0.05 - - Added all DBD::CSV tests (ported, of course) - - Fixed bugs that the above revealed. - -0.04 - - Fix multiple placeholders bug - -0.03 - - Fixed multiple execute on single $sth - -0.02 - - Fixed transactions - -0.01 Sat Feb 16 16:10:42 2002 - - original version; created by h2xs 1.20 with options - -A -X -n DBD::SQLite - diff --git a/dbLifeLog/DBD-SQLite2-0.33/MANIFEST b/dbLifeLog/DBD-SQLite2-0.33/MANIFEST deleted file mode 100644 index 780fe79..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/MANIFEST +++ /dev/null @@ -1,79 +0,0 @@ -Changes -MANIFEST -MANIFEST.SKIP -Makefile.PL -README -SQLite2.xs -SQLiteXS.h -attach.c -auth.c -btree.c -btree.h -btree_rb.c -build.c -copy.c -date.c -dbdimp.c -dbdimp.h -delete.c -encode.c -expr.c -func.c -getsqlite.pl -hash.c -hash.h -insert.c -lib/DBD/SQLite2.pm -main.c -opcodes.c -opcodes.h -os.c -os.h -pager.c -pager.h -parse.c -parse.h -pragma.c -printf.c -random.c -select.c -sqlite.h -sqliteInt.h -t/00basic.t -t/01logon.t -t/02cr_table.t -t/03insert.t -t/04select.t -t/05tran.t -t/06error.t -t/08create_function.t -t/09create_aggregate.t -t/10dsnlist.t -t/20createdrop.t -t/30insertfetch.t -t/40bindparam.t -t/40blobs.t -t/40listfields.t -t/40nulls.t -t/40numrows.t -t/50chopblanks.t -t/50commit.t -t/60metadata.t -t/90cppcomments.t -t/99cleanup.t -t/SQLite2.dbtest -t/ak-dbd.t -t/dbdadmin.t -t/lib.pl -table.c -tokenize.c -trigger.c -update.c -util.c -vacuum.c -vdbe.c -vdbe.h -vdbeaux.c -vdbeInt.h -where.c -META.yml Module meta-data (added by MakeMaker) diff --git a/dbLifeLog/DBD-SQLite2-0.33/MANIFEST.SKIP b/dbLifeLog/DBD-SQLite2-0.33/MANIFEST.SKIP deleted file mode 100644 index a535f37..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/MANIFEST.SKIP +++ /dev/null @@ -1,20 +0,0 @@ -CVS/.* -\.bak$ -\.sw[a-z]$ -\.tar$ -\.tgz$ -\.tar\.gz$ -\.o$ -\.xsi$ -\.bs$ -output/.* -^.# -^mess/ -^sqlite/ -^output/ -^tmp/ -^blib/ -^Makefile$ -^Makefile\.[a-z]+$ -^pm_to_blib$ -~$ diff --git a/dbLifeLog/DBD-SQLite2-0.33/META.yml b/dbLifeLog/DBD-SQLite2-0.33/META.yml deleted file mode 100644 index ea02849..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/META.yml +++ /dev/null @@ -1,11 +0,0 @@ -# http://module-build.sourceforge.net/META-spec.html -#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# -name: DBD-SQLite2 -version: 0.33 -version_from: lib/DBD/SQLite2.pm -installdirs: site -requires: - DBI: 1.21 - -distribution_type: module -generated_by: ExtUtils::MakeMaker version 6.21 diff --git a/dbLifeLog/DBD-SQLite2-0.33/MYMETA.json b/dbLifeLog/DBD-SQLite2-0.33/MYMETA.json deleted file mode 100644 index 3738892..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/MYMETA.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "abstract" : "unknown", - "author" : [ - "unknown" - ], - "dynamic_config" : 0, - "generated_by" : "ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001", - "license" : [ - "unknown" - ], - "meta-spec" : { - "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" - }, - "name" : "DBD-SQLite2", - "no_index" : { - "directory" : [ - "t", - "inc" - ] - }, - "prereqs" : { - "build" : { - "requires" : { - "ExtUtils::MakeMaker" : "0" - } - }, - "configure" : { - "requires" : { - "ExtUtils::MakeMaker" : "0" - } - }, - "runtime" : { - "requires" : { - "DBI" : "1.21" - } - } - }, - "release_status" : "stable", - "version" : "0.33" -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/MYMETA.yml b/dbLifeLog/DBD-SQLite2-0.33/MYMETA.yml deleted file mode 100644 index 2894bed..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/MYMETA.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -abstract: unknown -author: - - unknown -build_requires: - ExtUtils::MakeMaker: '0' -configure_requires: - ExtUtils::MakeMaker: '0' -dynamic_config: 0 -generated_by: 'ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001' -license: unknown -meta-spec: - url: http://module-build.sourceforge.net/META-spec-v1.4.html - version: '1.4' -name: DBD-SQLite2 -no_index: - directory: - - t - - inc -requires: - DBI: '1.21' -version: '0.33' diff --git a/dbLifeLog/DBD-SQLite2-0.33/Makefile b/dbLifeLog/DBD-SQLite2-0.33/Makefile deleted file mode 100644 index 3a75ee1..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/Makefile +++ /dev/null @@ -1,1122 +0,0 @@ -# This Makefile is for the DBD::SQLite2 extension to perl. -# -# It was generated automatically by MakeMaker version -# 7.0401 (Revision: 70401) from the contents of -# Makefile.PL. Don't edit this file, edit Makefile.PL instead. -# -# ANY CHANGES MADE HERE WILL BE LOST! -# -# MakeMaker ARGV: () -# - -# MakeMaker Parameters: - -# BUILD_REQUIRES => { } -# CONFIGURE_REQUIRES => { } -# DEFINE => q[-DNDEBUG=1 -DSQLITE_PTR_SZ=8 -DHAVE_USLEEP=1] -# INC => q[-I$(DBI_INSTARCH_DIR)] -# NAME => q[DBD::SQLite2] -# OBJECT => q[$(O_FILES)] -# OPTIMIZE => q[-O2] -# PREREQ_PM => { DBI=>q[1.21] } -# TEST_REQUIRES => { } -# VERSION_FROM => q[lib/DBD/SQLite2.pm] -# clean => { FILES=>q[SQLite2.xsi config.h] } - -# --- MakeMaker post_initialize section: - - -# --- MakeMaker const_config section: - -# These definitions are from config.sh (via /usr/lib/x86_64-linux-gnu/perl/5.22/Config.pm). -# They may have been overridden via Makefile.PL or on the command line. -AR = ar -CC = x86_64-linux-gnu-gcc -CCCDLFLAGS = -fPIC -CCDLFLAGS = -Wl,-E -DLEXT = so -DLSRC = dl_dlopen.xs -EXE_EXT = -FULL_AR = /usr/bin/ar -LD = x86_64-linux-gnu-gcc -LDDLFLAGS = -shared -L/usr/local/lib -fstack-protector-strong -LDFLAGS = -fstack-protector-strong -L/usr/local/lib -LIBC = libc-2.23.so -LIB_EXT = .a -OBJ_EXT = .o -OSNAME = linux -OSVERS = 3.16.0 -RANLIB = : -SITELIBEXP = /usr/local/share/perl/5.22.1 -SITEARCHEXP = /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 -SO = so -VENDORARCHEXP = /usr/lib/x86_64-linux-gnu/perl5/5.22 -VENDORLIBEXP = /usr/share/perl5 - - -# --- MakeMaker constants section: -AR_STATIC_ARGS = cr -DIRFILESEP = / -DFSEP = $(DIRFILESEP) -NAME = DBD::SQLite2 -NAME_SYM = DBD_SQLite2 -VERSION = 0.33 -VERSION_MACRO = VERSION -VERSION_SYM = 0_33 -DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" -XS_VERSION = 0.33 -XS_VERSION_MACRO = XS_VERSION -XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" -INST_ARCHLIB = blib/arch -INST_SCRIPT = blib/script -INST_BIN = blib/bin -INST_LIB = blib/lib -INST_MAN1DIR = blib/man1 -INST_MAN3DIR = blib/man3 -MAN1EXT = 1p -MAN3EXT = 3pm -INSTALLDIRS = site -DESTDIR = -PREFIX = $(SITEPREFIX) -PERLPREFIX = /usr -SITEPREFIX = /usr/local -VENDORPREFIX = /usr -INSTALLPRIVLIB = /usr/share/perl/5.22 -DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) -INSTALLSITELIB = /usr/local/share/perl/5.22.1 -DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) -INSTALLVENDORLIB = /usr/share/perl5 -DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) -INSTALLARCHLIB = /usr/lib/x86_64-linux-gnu/perl/5.22 -DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) -INSTALLSITEARCH = /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 -DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) -INSTALLVENDORARCH = /usr/lib/x86_64-linux-gnu/perl5/5.22 -DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) -INSTALLBIN = /usr/bin -DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) -INSTALLSITEBIN = /usr/local/bin -DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) -INSTALLVENDORBIN = /usr/bin -DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) -INSTALLSCRIPT = /usr/bin -DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) -INSTALLSITESCRIPT = /usr/local/bin -DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT) -INSTALLVENDORSCRIPT = /usr/bin -DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT) -INSTALLMAN1DIR = /usr/share/man/man1 -DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) -INSTALLSITEMAN1DIR = /usr/local/man/man1 -DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) -INSTALLVENDORMAN1DIR = /usr/share/man/man1 -DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) -INSTALLMAN3DIR = /usr/share/man/man3 -DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) -INSTALLSITEMAN3DIR = /usr/local/man/man3 -DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) -INSTALLVENDORMAN3DIR = /usr/share/man/man3 -DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) -PERL_LIB = /usr/share/perl/5.22 -PERL_ARCHLIB = /usr/lib/x86_64-linux-gnu/perl/5.22 -PERL_ARCHLIBDEP = /usr/lib/x86_64-linux-gnu/perl/5.22 -LIBPERL_A = libperl.a -FIRST_MAKEFILE = Makefile -MAKEFILE_OLD = Makefile.old -MAKE_APERL_FILE = Makefile.aperl -PERLMAINCC = $(CC) -PERL_INC = /usr/lib/x86_64-linux-gnu/perl/5.22/CORE -PERL_INCDEP = /usr/lib/x86_64-linux-gnu/perl/5.22/CORE -PERL = "/usr/bin/perl" -FULLPERL = "/usr/bin/perl" -ABSPERL = $(PERL) -PERLRUN = $(PERL) -FULLPERLRUN = $(FULLPERL) -ABSPERLRUN = $(ABSPERL) -PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" -FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" -ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" -PERL_CORE = 0 -PERM_DIR = 755 -PERM_RW = 644 -PERM_RWX = 755 - -MAKEMAKER = /usr/share/perl/5.22/ExtUtils/MakeMaker.pm -MM_VERSION = 7.0401 -MM_REVISION = 70401 - -# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). -# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) -# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) -# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. -MAKE = make -FULLEXT = DBD/SQLite2 -BASEEXT = SQLite2 -PARENT_NAME = DBD -DLBASE = $(BASEEXT) -VERSION_FROM = lib/DBD/SQLite2.pm -INC = -I$(DBI_INSTARCH_DIR) -DEFINE = -DNDEBUG=1 -DSQLITE_PTR_SZ=8 -DHAVE_USLEEP=1 -OBJECT = $(O_FILES) -LDFROM = $(OBJECT) -LINKTYPE = dynamic -BOOTDEP = - -# Handy lists of source code files: -XS_FILES = SQLite2.xs -C_FILES = SQLite2.c \ - attach.c \ - auth.c \ - btree.c \ - btree_rb.c \ - build.c \ - copy.c \ - date.c \ - dbdimp.c \ - delete.c \ - encode.c \ - expr.c \ - func.c \ - hash.c \ - insert.c \ - main.c \ - opcodes.c \ - os.c \ - pager.c \ - parse.c \ - pragma.c \ - printf.c \ - random.c \ - select.c \ - table.c \ - tokenize.c \ - trigger.c \ - update.c \ - util.c \ - vacuum.c \ - vdbe.c \ - vdbeaux.c \ - where.c -O_FILES = SQLite2.o \ - attach.o \ - auth.o \ - btree.o \ - btree_rb.o \ - build.o \ - copy.o \ - date.o \ - dbdimp.o \ - delete.o \ - encode.o \ - expr.o \ - func.o \ - hash.o \ - insert.o \ - main.o \ - opcodes.o \ - os.o \ - pager.o \ - parse.o \ - pragma.o \ - printf.o \ - random.o \ - select.o \ - table.o \ - tokenize.o \ - trigger.o \ - update.o \ - util.o \ - vacuum.o \ - vdbe.o \ - vdbeaux.o \ - where.o -H_FILES = SQLiteXS.h \ - btree.h \ - dbdimp.h \ - hash.h \ - opcodes.h \ - os.h \ - pager.h \ - parse.h \ - sqlite.h \ - sqliteInt.h \ - vdbe.h \ - vdbeInt.h -MAN1PODS = -MAN3PODS = lib/DBD/SQLite2.pm - -# Where is the Config information that we are using/depend on -CONFIGDEP = $(PERL_ARCHLIBDEP)$(DFSEP)Config.pm $(PERL_INCDEP)$(DFSEP)config.h - -# Where to build things -INST_LIBDIR = $(INST_LIB)/DBD -INST_ARCHLIBDIR = $(INST_ARCHLIB)/DBD - -INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) -INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) - -INST_STATIC = $(INST_ARCHAUTODIR)/$(BASEEXT)$(LIB_EXT) -INST_DYNAMIC = $(INST_ARCHAUTODIR)/$(DLBASE).$(DLEXT) -INST_BOOT = $(INST_ARCHAUTODIR)/$(BASEEXT).bs - -# Extra linker info -EXPORT_LIST = -PERL_ARCHIVE = -PERL_ARCHIVEDEP = -PERL_ARCHIVE_AFTER = - - -TO_INST_PM = getsqlite.pl \ - lib/DBD/SQLite2.pm - -PM_TO_BLIB = getsqlite.pl \ - $(INST_LIB)/DBD/getsqlite.pl \ - lib/DBD/SQLite2.pm \ - blib/lib/DBD/SQLite2.pm - - -# --- MakeMaker platform_constants section: -MM_Unix_VERSION = 7.0401 -PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc - - -# --- MakeMaker tool_autosplit section: -# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto -AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$$$ARGV[0], $$$$ARGV[1], 0, 1, 1)' -- - - - -# --- MakeMaker tool_xsubpp section: - -XSUBPPDIR = /usr/share/perl/5.22/ExtUtils -XSUBPP = "$(XSUBPPDIR)$(DFSEP)xsubpp" -XSUBPPRUN = $(PERLRUN) $(XSUBPP) -XSPROTOARG = -XSUBPPDEPS = /usr/share/perl/5.22/ExtUtils/typemap /usr/share/perl/5.22/ExtUtils$(DFSEP)xsubpp -XSUBPPARGS = -typemap "/usr/share/perl/5.22/ExtUtils/typemap" -XSUBPP_EXTRA_ARGS = - - -# --- MakeMaker tools_other section: -SHELL = /bin/sh -CHMOD = chmod -CP = cp -MV = mv -NOOP = $(TRUE) -NOECHO = @ -RM_F = rm -f -RM_RF = rm -rf -TEST_F = test -f -TOUCH = touch -UMASK_NULL = umask 0 -DEV_NULL = > /dev/null 2>&1 -MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' -- -EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' -- -FALSE = false -TRUE = true -ECHO = echo -ECHO_N = echo -n -UNINST = 0 -VERBINST = 0 -MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' -- -DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' -- -UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' -- -WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' -- -MACROSTART = -MACROEND = -USEMAKEFILE = -f -FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' -- -CP_NONEMPTY = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'cp_nonempty' -- - - -# --- MakeMaker makemakerdflt section: -makemakerdflt : all - $(NOECHO) $(NOOP) - - -# --- MakeMaker dist section: -TAR = tar -TARFLAGS = cvf -ZIP = zip -ZIPFLAGS = -r -COMPRESS = gzip --best -SUFFIX = .gz -SHAR = shar -PREOP = $(NOECHO) $(NOOP) -POSTOP = $(NOECHO) $(NOOP) -TO_UNIX = $(NOECHO) $(NOOP) -CI = ci -u -RCS_LABEL = rcs -Nv$(VERSION_SYM): -q -DIST_CP = best -DIST_DEFAULT = tardist -DISTNAME = DBD-SQLite2 -DISTVNAME = DBD-SQLite2-0.33 - - -# --- MakeMaker macro section: - - -# --- MakeMaker depend section: - - -# --- MakeMaker cflags section: - -CCFLAGS = -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fwrapv -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -OPTIMIZE = -O2 -PERLTYPE = -MPOLLUTE = - - -# --- MakeMaker const_loadlibs section: - -# DBD::SQLite2 might depend on some other libraries: -# See ExtUtils::Liblist for details -# - - -# --- MakeMaker const_cccmd section: -CCCMD = $(CC) -c $(PASTHRU_INC) $(INC) \ - $(CCFLAGS) $(OPTIMIZE) \ - $(PERLTYPE) $(MPOLLUTE) $(DEFINE_VERSION) \ - $(XS_DEFINE_VERSION) - -# --- MakeMaker post_constants section: - - -# --- MakeMaker pasthru section: - -PASTHRU = LIBPERL_A="$(LIBPERL_A)"\ - LINKTYPE="$(LINKTYPE)"\ - OPTIMIZE="$(OPTIMIZE)"\ - LD="$(LD)"\ - PREFIX="$(PREFIX)"\ - PASTHRU_DEFINE="$(PASTHRU_DEFINE)"\ - PASTHRU_INC="$(PASTHRU_INC)" - - -# --- MakeMaker special_targets section: -.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) - -.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir - - - -# --- MakeMaker c_o section: - -.c.i: - x86_64-linux-gnu-gcc -E -c $(PASTHRU_INC) $(INC) \ - $(CCFLAGS) $(OPTIMIZE) \ - $(PERLTYPE) $(MPOLLUTE) $(DEFINE_VERSION) \ - $(XS_DEFINE_VERSION) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c > $*.i - -.c.s: - $(CCCMD) -S $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c - -.c$(OBJ_EXT): - $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c - -.cpp$(OBJ_EXT): - $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.cpp - -.cxx$(OBJ_EXT): - $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.cxx - -.cc$(OBJ_EXT): - $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.cc - -.C$(OBJ_EXT): - $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.C - - -# --- MakeMaker xs_c section: - -.xs.c: - $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c - - -# --- MakeMaker xs_o section: - -.xs$(OBJ_EXT): - $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c - $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c - - -# --- MakeMaker top_targets section: -all :: pure_all manifypods - $(NOECHO) $(NOOP) - - -pure_all :: config pm_to_blib subdirs linkext - $(NOECHO) $(NOOP) - -subdirs :: $(MYEXTLIB) - $(NOECHO) $(NOOP) - -config :: $(FIRST_MAKEFILE) blibdirs - $(NOECHO) $(NOOP) - -$(O_FILES): $(H_FILES) - -help : - perldoc ExtUtils::MakeMaker - - -# --- MakeMaker blibdirs section: -blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists - $(NOECHO) $(NOOP) - -# Backwards compat with 6.18 through 6.25 -blibdirs.ts : blibdirs - $(NOECHO) $(NOOP) - -$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL - $(NOECHO) $(MKPATH) $(INST_LIBDIR) - $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR) - $(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists - -$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL - $(NOECHO) $(MKPATH) $(INST_ARCHLIB) - $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB) - $(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists - -$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL - $(NOECHO) $(MKPATH) $(INST_AUTODIR) - $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR) - $(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists - -$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL - $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) - $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR) - $(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists - -$(INST_BIN)$(DFSEP).exists :: Makefile.PL - $(NOECHO) $(MKPATH) $(INST_BIN) - $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN) - $(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists - -$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL - $(NOECHO) $(MKPATH) $(INST_SCRIPT) - $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT) - $(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists - -$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL - $(NOECHO) $(MKPATH) $(INST_MAN1DIR) - $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR) - $(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists - -$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL - $(NOECHO) $(MKPATH) $(INST_MAN3DIR) - $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR) - $(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists - - - -# --- MakeMaker linkext section: - -linkext :: $(LINKTYPE) - $(NOECHO) $(NOOP) - - -# --- MakeMaker dlsyms section: - - -# --- MakeMaker dynamic_bs section: -BOOTSTRAP = $(BASEEXT).bs - -# As Mkbootstrap might not write a file (if none is required) -# we use touch to prevent make continually trying to remake it. -# The DynaLoader only reads a non-empty file. -$(BOOTSTRAP) : $(FIRST_MAKEFILE) $(BOOTDEP) $(INST_ARCHAUTODIR)$(DFSEP).exists - $(NOECHO) $(ECHO) "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))" - $(NOECHO) $(PERLRUN) \ - "-MExtUtils::Mkbootstrap" \ - -e "Mkbootstrap('$(BASEEXT)','$(BSLOADLIBS)');" - $(NOECHO) $(TOUCH) "$@" - $(CHMOD) $(PERM_RW) "$@" - - -# --- MakeMaker dynamic section: - -dynamic :: $(FIRST_MAKEFILE) $(BOOTSTRAP) $(INST_DYNAMIC) - $(NOECHO) $(NOOP) - - -# --- MakeMaker dynamic_lib section: - -# This section creates the dynamically loadable $(INST_DYNAMIC) -# from $(OBJECT) and possibly $(MYEXTLIB). -ARMAYBE = : -OTHERLDFLAGS = -INST_DYNAMIC_DEP = -INST_DYNAMIC_FIX = - -$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVEDEP) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP) - $(RM_F) $@ - $(LD) $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) \ - $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) \ - $(INST_DYNAMIC_FIX) - $(CHMOD) $(PERM_RWX) $@ - $(NOECHO) $(RM_RF) $(BOOTSTRAP) - - $(CP_NONEMPTY) $(BOOTSTRAP) $(INST_BOOT) $(PERM_RW) - - -# --- MakeMaker static section: - -## $(INST_PM) has been moved to the all: target. -## It remains here for awhile to allow for old usage: "make static" -static :: $(FIRST_MAKEFILE) $(INST_STATIC) - $(NOECHO) $(NOOP) - - -# --- MakeMaker static_lib section: - -$(INST_STATIC) : $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists - $(RM_RF) $@ - $(FULL_AR) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@ - $(CHMOD) $(PERM_RWX) $@ - $(NOECHO) $(ECHO) "$(EXTRALIBS)" > "$(INST_ARCHAUTODIR)/extralibs.ld" - - -# --- MakeMaker manifypods section: - -POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" -POD2MAN = $(POD2MAN_EXE) - - -manifypods : pure_all \ - lib/DBD/SQLite2.pm - $(NOECHO) $(POD2MAN) --section=$(MAN3EXT) --perm_rw=$(PERM_RW) -u \ - lib/DBD/SQLite2.pm $(INST_MAN3DIR)/DBD::SQLite2.$(MAN3EXT) - - - - -# --- MakeMaker processPL section: - - -# --- MakeMaker installbin section: - - -# --- MakeMaker subdirs section: - -# none - -# --- MakeMaker clean_subdirs section: -clean_subdirs : - $(NOECHO) $(NOOP) - - -# --- MakeMaker clean section: - -# Delete temporary files but do not touch installed files. We don't delete -# the Makefile here so a later make realclean still has a makefile to use. - -clean :: clean_subdirs - - $(RM_F) \ - $(BASEEXT).bso $(BASEEXT).def \ - $(BASEEXT).exp $(BASEEXT).x \ - $(BOOTSTRAP) $(INST_ARCHAUTODIR)/extralibs.all \ - $(INST_ARCHAUTODIR)/extralibs.ld $(MAKE_APERL_FILE) \ - *$(LIB_EXT) *$(OBJ_EXT) \ - *perl.core MYMETA.json \ - MYMETA.yml SQLite2.c \ - blibdirs.ts core \ - core.*perl.*.? core.[0-9] \ - core.[0-9][0-9] core.[0-9][0-9][0-9] \ - core.[0-9][0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9][0-9] \ - lib$(BASEEXT).def mon.out \ - perl perl$(EXE_EXT) \ - perl.exe perlmain.c \ - pm_to_blib pm_to_blib.ts \ - so_locations tmon.out - - $(RM_RF) \ - SQLite2.xsi blib \ - config.h - $(NOECHO) $(RM_F) $(MAKEFILE_OLD) - - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) - - -# --- MakeMaker realclean_subdirs section: -realclean_subdirs : - $(NOECHO) $(NOOP) - - -# --- MakeMaker realclean section: -# Delete temporary files (via clean) and also delete dist files -realclean purge :: clean realclean_subdirs - - $(RM_F) \ - $(MAKEFILE_OLD) $(FIRST_MAKEFILE) \ - $(OBJECT) - - $(RM_RF) \ - $(DISTVNAME) - - -# --- MakeMaker metafile section: -metafile : create_distdir - $(NOECHO) $(ECHO) Generating META.yml - $(NOECHO) $(ECHO) '---' > META_new.yml - $(NOECHO) $(ECHO) 'abstract: unknown' >> META_new.yml - $(NOECHO) $(ECHO) 'author:' >> META_new.yml - $(NOECHO) $(ECHO) ' - unknown' >> META_new.yml - $(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml - $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml - $(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml - $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml - $(NOECHO) $(ECHO) 'dynamic_config: 1' >> META_new.yml - $(NOECHO) $(ECHO) 'generated_by: '\''ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001'\''' >> META_new.yml - $(NOECHO) $(ECHO) 'license: unknown' >> META_new.yml - $(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml - $(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml - $(NOECHO) $(ECHO) ' version: '\''1.4'\''' >> META_new.yml - $(NOECHO) $(ECHO) 'name: DBD-SQLite2' >> META_new.yml - $(NOECHO) $(ECHO) 'no_index:' >> META_new.yml - $(NOECHO) $(ECHO) ' directory:' >> META_new.yml - $(NOECHO) $(ECHO) ' - t' >> META_new.yml - $(NOECHO) $(ECHO) ' - inc' >> META_new.yml - $(NOECHO) $(ECHO) 'requires:' >> META_new.yml - $(NOECHO) $(ECHO) ' DBI: '\''1.21'\''' >> META_new.yml - $(NOECHO) $(ECHO) 'version: '\''0.33'\''' >> META_new.yml - -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml - $(NOECHO) $(ECHO) Generating META.json - $(NOECHO) $(ECHO) '{' > META_new.json - $(NOECHO) $(ECHO) ' "abstract" : "unknown",' >> META_new.json - $(NOECHO) $(ECHO) ' "author" : [' >> META_new.json - $(NOECHO) $(ECHO) ' "unknown"' >> META_new.json - $(NOECHO) $(ECHO) ' ],' >> META_new.json - $(NOECHO) $(ECHO) ' "dynamic_config" : 1,' >> META_new.json - $(NOECHO) $(ECHO) ' "generated_by" : "ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001",' >> META_new.json - $(NOECHO) $(ECHO) ' "license" : [' >> META_new.json - $(NOECHO) $(ECHO) ' "unknown"' >> META_new.json - $(NOECHO) $(ECHO) ' ],' >> META_new.json - $(NOECHO) $(ECHO) ' "meta-spec" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",' >> META_new.json - $(NOECHO) $(ECHO) ' "version" : "2"' >> META_new.json - $(NOECHO) $(ECHO) ' },' >> META_new.json - $(NOECHO) $(ECHO) ' "name" : "DBD-SQLite2",' >> META_new.json - $(NOECHO) $(ECHO) ' "no_index" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "directory" : [' >> META_new.json - $(NOECHO) $(ECHO) ' "t",' >> META_new.json - $(NOECHO) $(ECHO) ' "inc"' >> META_new.json - $(NOECHO) $(ECHO) ' ]' >> META_new.json - $(NOECHO) $(ECHO) ' },' >> META_new.json - $(NOECHO) $(ECHO) ' "prereqs" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "build" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json - $(NOECHO) $(ECHO) ' }' >> META_new.json - $(NOECHO) $(ECHO) ' },' >> META_new.json - $(NOECHO) $(ECHO) ' "configure" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json - $(NOECHO) $(ECHO) ' }' >> META_new.json - $(NOECHO) $(ECHO) ' },' >> META_new.json - $(NOECHO) $(ECHO) ' "runtime" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json - $(NOECHO) $(ECHO) ' "DBI" : "1.21"' >> META_new.json - $(NOECHO) $(ECHO) ' }' >> META_new.json - $(NOECHO) $(ECHO) ' }' >> META_new.json - $(NOECHO) $(ECHO) ' },' >> META_new.json - $(NOECHO) $(ECHO) ' "release_status" : "stable",' >> META_new.json - $(NOECHO) $(ECHO) ' "version" : "0.33"' >> META_new.json - $(NOECHO) $(ECHO) '}' >> META_new.json - -$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json - - -# --- MakeMaker signature section: -signature : - cpansign -s - - -# --- MakeMaker dist_basics section: -distclean :: realclean distcheck - $(NOECHO) $(NOOP) - -distcheck : - $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck - -skipcheck : - $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck - -manifest : - $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest - -veryclean : realclean - $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old - - - -# --- MakeMaker dist_core section: - -dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) - $(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ - -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' -- - -tardist : $(DISTVNAME).tar$(SUFFIX) - $(NOECHO) $(NOOP) - -uutardist : $(DISTVNAME).tar$(SUFFIX) - uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu - $(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)_uu' - -$(DISTVNAME).tar$(SUFFIX) : distdir - $(PREOP) - $(TO_UNIX) - $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) - $(RM_RF) $(DISTVNAME) - $(COMPRESS) $(DISTVNAME).tar - $(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)' - $(POSTOP) - -zipdist : $(DISTVNAME).zip - $(NOECHO) $(NOOP) - -$(DISTVNAME).zip : distdir - $(PREOP) - $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) - $(RM_RF) $(DISTVNAME) - $(NOECHO) $(ECHO) 'Created $(DISTVNAME).zip' - $(POSTOP) - -shdist : distdir - $(PREOP) - $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar - $(RM_RF) $(DISTVNAME) - $(NOECHO) $(ECHO) 'Created $(DISTVNAME).shar' - $(POSTOP) - - -# --- MakeMaker distdir section: -create_distdir : - $(RM_RF) $(DISTVNAME) - $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ - -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" - -distdir : create_distdir distmeta - $(NOECHO) $(NOOP) - - - -# --- MakeMaker dist_test section: -disttest : distdir - cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL - cd $(DISTVNAME) && $(MAKE) $(PASTHRU) - cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) - - - -# --- MakeMaker dist_ci section: - -ci : - $(PERLRUN) "-MExtUtils::Manifest=maniread" \ - -e "@all = keys %{ maniread() };" \ - -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \ - -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});" - - -# --- MakeMaker distmeta section: -distmeta : create_distdir metafile - $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -e q{META.yml};' \ - -e 'eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }' \ - -e ' or print "Could not add META.yml to MANIFEST: $$$${'\''@'\''}\n"' -- - $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -f q{META.json};' \ - -e 'eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }' \ - -e ' or print "Could not add META.json to MANIFEST: $$$${'\''@'\''}\n"' -- - - - -# --- MakeMaker distsignature section: -distsignature : create_distdir - $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) }' \ - -e ' or print "Could not add SIGNATURE to MANIFEST: $$$${'\''@'\''}\n"' -- - $(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE - cd $(DISTVNAME) && cpansign -s - - - -# --- MakeMaker install section: - -install :: pure_install doc_install - $(NOECHO) $(NOOP) - -install_perl :: pure_perl_install doc_perl_install - $(NOECHO) $(NOOP) - -install_site :: pure_site_install doc_site_install - $(NOECHO) $(NOOP) - -install_vendor :: pure_vendor_install doc_vendor_install - $(NOECHO) $(NOOP) - -pure_install :: pure_$(INSTALLDIRS)_install - $(NOECHO) $(NOOP) - -doc_install :: doc_$(INSTALLDIRS)_install - $(NOECHO) $(NOOP) - -pure__install : pure_site_install - $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site - -doc__install : doc_site_install - $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site - -pure_perl_install :: all - $(NOECHO) umask 022; $(MOD_INSTALL) \ - "$(INST_LIB)" "$(DESTINSTALLPRIVLIB)" \ - "$(INST_ARCHLIB)" "$(DESTINSTALLARCHLIB)" \ - "$(INST_BIN)" "$(DESTINSTALLBIN)" \ - "$(INST_SCRIPT)" "$(DESTINSTALLSCRIPT)" \ - "$(INST_MAN1DIR)" "$(DESTINSTALLMAN1DIR)" \ - "$(INST_MAN3DIR)" "$(DESTINSTALLMAN3DIR)" - $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ - "$(SITEARCHEXP)/auto/$(FULLEXT)" - - -pure_site_install :: all - $(NOECHO) umask 02; $(MOD_INSTALL) \ - read "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" \ - write "$(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist" \ - "$(INST_LIB)" "$(DESTINSTALLSITELIB)" \ - "$(INST_ARCHLIB)" "$(DESTINSTALLSITEARCH)" \ - "$(INST_BIN)" "$(DESTINSTALLSITEBIN)" \ - "$(INST_SCRIPT)" "$(DESTINSTALLSITESCRIPT)" \ - "$(INST_MAN1DIR)" "$(DESTINSTALLSITEMAN1DIR)" \ - "$(INST_MAN3DIR)" "$(DESTINSTALLSITEMAN3DIR)" - $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ - "$(PERL_ARCHLIB)/auto/$(FULLEXT)" - -pure_vendor_install :: all - $(NOECHO) umask 022; $(MOD_INSTALL) \ - "$(INST_LIB)" "$(DESTINSTALLVENDORLIB)" \ - "$(INST_ARCHLIB)" "$(DESTINSTALLVENDORARCH)" \ - "$(INST_BIN)" "$(DESTINSTALLVENDORBIN)" \ - "$(INST_SCRIPT)" "$(DESTINSTALLVENDORSCRIPT)" \ - "$(INST_MAN1DIR)" "$(DESTINSTALLVENDORMAN1DIR)" \ - "$(INST_MAN3DIR)" "$(DESTINSTALLVENDORMAN3DIR)" - - -doc_perl_install :: all - -doc_site_install :: all - $(NOECHO) $(ECHO) Appending installation info to "$(DESTINSTALLSITEARCH)/perllocal.pod" - -$(NOECHO) umask 02; $(MKPATH) "$(DESTINSTALLSITEARCH)" - -$(NOECHO) umask 02; $(DOC_INSTALL) \ - "Module" "$(NAME)" \ - "installed into" $(INSTALLSITELIB) \ - LINKTYPE "$(LINKTYPE)" \ - VERSION "$(VERSION)" \ - EXE_FILES "$(EXE_FILES)" \ - >> "$(DESTINSTALLSITEARCH)/perllocal.pod" - -doc_vendor_install :: all - - -uninstall :: uninstall_from_$(INSTALLDIRS)dirs - $(NOECHO) $(NOOP) - -uninstall_from_perldirs :: - -uninstall_from_sitedirs :: - $(NOECHO) $(UNINSTALL) "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" - -uninstall_from_vendordirs :: - - -# --- MakeMaker force section: -# Phony target to force checking subdirectories. -FORCE : - $(NOECHO) $(NOOP) - - -# --- MakeMaker perldepend section: -PERL_HDRS = \ - $(PERL_INCDEP)/EXTERN.h \ - $(PERL_INCDEP)/INTERN.h \ - $(PERL_INCDEP)/XSUB.h \ - $(PERL_INCDEP)/av.h \ - $(PERL_INCDEP)/bitcount.h \ - $(PERL_INCDEP)/charclass_invlists.h \ - $(PERL_INCDEP)/config.h \ - $(PERL_INCDEP)/cop.h \ - $(PERL_INCDEP)/cv.h \ - $(PERL_INCDEP)/dosish.h \ - $(PERL_INCDEP)/ebcdic_tables.h \ - $(PERL_INCDEP)/embed.h \ - $(PERL_INCDEP)/embedvar.h \ - $(PERL_INCDEP)/fakesdio.h \ - $(PERL_INCDEP)/feature.h \ - $(PERL_INCDEP)/form.h \ - $(PERL_INCDEP)/git_version.h \ - $(PERL_INCDEP)/gv.h \ - $(PERL_INCDEP)/handy.h \ - $(PERL_INCDEP)/hv.h \ - $(PERL_INCDEP)/hv_func.h \ - $(PERL_INCDEP)/inline.h \ - $(PERL_INCDEP)/intrpvar.h \ - $(PERL_INCDEP)/iperlsys.h \ - $(PERL_INCDEP)/keywords.h \ - $(PERL_INCDEP)/l1_char_class_tab.h \ - $(PERL_INCDEP)/malloc_ctl.h \ - $(PERL_INCDEP)/metaconfig.h \ - $(PERL_INCDEP)/mg.h \ - $(PERL_INCDEP)/mg_data.h \ - $(PERL_INCDEP)/mg_raw.h \ - $(PERL_INCDEP)/mg_vtable.h \ - $(PERL_INCDEP)/mydtrace.h \ - $(PERL_INCDEP)/nostdio.h \ - $(PERL_INCDEP)/op.h \ - $(PERL_INCDEP)/op_reg_common.h \ - $(PERL_INCDEP)/opcode.h \ - $(PERL_INCDEP)/opnames.h \ - $(PERL_INCDEP)/overload.h \ - $(PERL_INCDEP)/pad.h \ - $(PERL_INCDEP)/parser.h \ - $(PERL_INCDEP)/patchlevel-debian.h \ - $(PERL_INCDEP)/patchlevel.h \ - $(PERL_INCDEP)/perl.h \ - $(PERL_INCDEP)/perlapi.h \ - $(PERL_INCDEP)/perlio.h \ - $(PERL_INCDEP)/perliol.h \ - $(PERL_INCDEP)/perlsdio.h \ - $(PERL_INCDEP)/perlvars.h \ - $(PERL_INCDEP)/perly.h \ - $(PERL_INCDEP)/pp.h \ - $(PERL_INCDEP)/pp_proto.h \ - $(PERL_INCDEP)/proto.h \ - $(PERL_INCDEP)/reentr.h \ - $(PERL_INCDEP)/regcharclass.h \ - $(PERL_INCDEP)/regcomp.h \ - $(PERL_INCDEP)/regexp.h \ - $(PERL_INCDEP)/regnodes.h \ - $(PERL_INCDEP)/scope.h \ - $(PERL_INCDEP)/sv.h \ - $(PERL_INCDEP)/thread.h \ - $(PERL_INCDEP)/time64.h \ - $(PERL_INCDEP)/time64_config.h \ - $(PERL_INCDEP)/uconfig.h \ - $(PERL_INCDEP)/unicode_constants.h \ - $(PERL_INCDEP)/unixish.h \ - $(PERL_INCDEP)/utf8.h \ - $(PERL_INCDEP)/utfebcdic.h \ - $(PERL_INCDEP)/util.h \ - $(PERL_INCDEP)/uudmap.h \ - $(PERL_INCDEP)/vutil.h \ - $(PERL_INCDEP)/warnings.h - -$(OBJECT) : $(PERL_HDRS) - -SQLite2.c : $(XSUBPPDEPS) - - -# --- MakeMaker makefile section: - -$(OBJECT) : $(FIRST_MAKEFILE) - -# We take a very conservative approach here, but it's worth it. -# We move Makefile to Makefile.old here to avoid gnu make looping. -$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) - $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" - $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." - -$(NOECHO) $(RM_F) $(MAKEFILE_OLD) - -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) - - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL) - $(PERLRUN) Makefile.PL - $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" - $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <==" - $(FALSE) - - - -# --- MakeMaker staticmake section: - -# --- MakeMaker makeaperl section --- -MAP_TARGET = perl -FULLPERL = "/usr/bin/perl" - -$(MAP_TARGET) :: static $(MAKE_APERL_FILE) - $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ - -$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib - $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) - $(NOECHO) $(PERLRUNINST) \ - Makefile.PL DIR="" \ - MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ - MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= - - -# --- MakeMaker test section: - -TEST_VERBOSE=0 -TEST_TYPE=test_$(LINKTYPE) -TEST_FILE = test.pl -TEST_FILES = t/*.t -TESTDB_SW = -d - -testdb :: testdb_$(LINKTYPE) - -test :: $(TEST_TYPE) subdirs-test - -subdirs-test :: - $(NOECHO) $(NOOP) - - -test_dynamic :: pure_all - PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES) - -testdb_dynamic :: pure_all - PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) - -test_ : test_dynamic - -test_static :: pure_all $(MAP_TARGET) - PERL_DL_NONLAZY=1 ./$(MAP_TARGET) "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES) - -testdb_static :: pure_all $(MAP_TARGET) - PERL_DL_NONLAZY=1 ./$(MAP_TARGET) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) - - - -# --- MakeMaker ppd section: -# Creates a PPD (Perl Package Description) for a binary distribution. -ppd : - $(NOECHO) $(ECHO) '' > $(DISTNAME).ppd - $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd - $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd - $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd - $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd - $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd - $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd - $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd - $(NOECHO) $(ECHO) '' >> $(DISTNAME).ppd - - -# --- MakeMaker pm_to_blib section: - -pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM) - $(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \ - getsqlite.pl $(INST_LIB)/DBD/getsqlite.pl \ - lib/DBD/SQLite2.pm blib/lib/DBD/SQLite2.pm - $(NOECHO) $(TOUCH) pm_to_blib - - -# --- MakeMaker selfdocument section: - - -# --- MakeMaker postamble section: - -# --- This section was generated by DBI::DBD::dbd_postamble() -DBI_INSTARCH_DIR=/usr/local/lib/x86_64-linux-gnu/perl/5.22.1/auto/DBI -DBI_DRIVER_XST=/usr/local/lib/x86_64-linux-gnu/perl/5.22.1/auto/DBI/Driver.xst - -# The main dependency (technically correct but probably not used) -$(BASEEXT).c: $(BASEEXT).xsi - -# This dependency is needed since MakeMaker uses the .xs.o rule -$(BASEEXT)$(OBJ_EXT): $(BASEEXT).xsi - -$(BASEEXT).xsi: $(DBI_DRIVER_XST) /usr/local/lib/x86_64-linux-gnu/perl/5.22.1/auto/DBI/Driver_xst.h - $(PERL) -p -e "s/~DRIVER~/$(BASEEXT)/g" $(DBI_DRIVER_XST) > $(BASEEXT).xsi - -# --- - - -# End. diff --git a/dbLifeLog/DBD-SQLite2-0.33/Makefile.PL b/dbLifeLog/DBD-SQLite2-0.33/Makefile.PL deleted file mode 100644 index 5e0aabc..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/Makefile.PL +++ /dev/null @@ -1,29 +0,0 @@ -eval { - require DBI; - require DBI::DBD; - die "Too old" unless $DBI::VERSION >= 1.03; -}; -use ExtUtils::MakeMaker; -use Config; -use strict; - -WriteMakefile( - 'NAME' => 'DBD::SQLite2', - 'VERSION_FROM' => 'lib/DBD/SQLite2.pm', # finds $VERSION - 'PREREQ_PM' => {DBI => 1.21}, # e.g., Module::Name => 1.1 - 'OBJECT' => '$(O_FILES)', - 'INC' => '-I$(DBI_INSTARCH_DIR)', - 'OPTIMIZE' => "-O2", - 'DEFINE' => "-DNDEBUG=1 -DSQLITE_PTR_SZ=$Config{ptrsize}" . - ($Config{d_usleep} ? " -DHAVE_USLEEP=1" : ""), - 'clean' => { FILES => 'SQLite2.xsi config.h' }, -); - -package MY; -sub postamble { - DBI::DBD::dbd_postamble(@_); -} -sub libscan { - my ($self, $path) = @_; - ($path =~ m/\~$/) ? undef : $path; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/README b/dbLifeLog/DBD-SQLite2-0.33/README deleted file mode 100644 index 15370f0..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/README +++ /dev/null @@ -1,36 +0,0 @@ -DBD::SQLite2 -============ - -SQLite is a small fast embedded SQL database engine. - -DBD::SQLite2 embeds that database engine into a DBD driver, so -if you want a relational database for your project, but don't -want to install a large RDBMS system like MySQL or PostgreSQL, -then DBD::SQLite2 may be just what you need. - -Note: DBD::SQLite2 is the old version of DBD::SQLite, and embeds -version 2.x.x of the sqlite library. The current version of -DBD::SQLite embeds version 3 (or possibly later if I forget to -update this file). This release is designed to allow you to have -both versions installed on the same system. - -SQLite supports quite a lot of features, such as transactions (atomic -commit and rollback), indexes, DBA-free operation, a large subset -of SQL92 supported, and more. - -Installation requires a compiler. - -The engine is very fast, but for updates/inserts/dml it does -perform a global lock on the entire database. This, obviously, -might not be good for multiple user systems. So beware. The -database also appears to be significantly faster if your -transactions are coarse. One performance benchmark I did was -inserting 100_000 rows into the database - with AutoCommit -on it was doing about 50 rows per second. When I turned AutoCommit -off it went up to 1000 rows per second. - -This module is distributed under the same terms as Perl itself, and -is copyright Matt Sergeant, 2002. - -The underlying SQLite database engine is copyright free. - diff --git a/dbLifeLog/DBD-SQLite2-0.33/SQLite2.bs b/dbLifeLog/DBD-SQLite2-0.33/SQLite2.bs deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/SQLite2.c b/dbLifeLog/DBD-SQLite2-0.33/SQLite2.c deleted file mode 100644 index 2143730..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/SQLite2.c +++ /dev/null @@ -1,1630 +0,0 @@ -/* - * This file was generated automatically by ExtUtils::ParseXS version 3.28 from the - * contents of SQLite2.xs. Do not edit this file, edit SQLite2.xs instead. - * - * ANY CHANGES MADE HERE WILL BE LOST! - * - */ - -#line 1 "SQLite2.xs" -/* $Id: SQLite2.xs,v 1.2 2004/08/09 13:23:55 matt Exp $ */ - -#include "SQLiteXS.h" - -DBISTATE_DECLARE; - -#line 17 "SQLite2.c" -#ifndef PERL_UNUSED_VAR -# define PERL_UNUSED_VAR(var) if (0) var = var -#endif - -#ifndef dVAR -# define dVAR dNOOP -#endif - - -/* This stuff is not part of the API! You have been warned. */ -#ifndef PERL_VERSION_DECIMAL -# define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s) -#endif -#ifndef PERL_DECIMAL_VERSION -# define PERL_DECIMAL_VERSION \ - PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION) -#endif -#ifndef PERL_VERSION_GE -# define PERL_VERSION_GE(r,v,s) \ - (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s)) -#endif -#ifndef PERL_VERSION_LE -# define PERL_VERSION_LE(r,v,s) \ - (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s)) -#endif - -/* XS_INTERNAL is the explicit static-linkage variant of the default - * XS macro. - * - * XS_EXTERNAL is the same as XS_INTERNAL except it does not include - * "STATIC", ie. it exports XSUB symbols. You probably don't want that - * for anything but the BOOT XSUB. - * - * See XSUB.h in core! - */ - - -/* TODO: This might be compatible further back than 5.10.0. */ -#if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1) -# undef XS_EXTERNAL -# undef XS_INTERNAL -# if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING) -# define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name) -# define XS_INTERNAL(name) STATIC XSPROTO(name) -# endif -# if defined(__SYMBIAN32__) -# define XS_EXTERNAL(name) EXPORT_C XSPROTO(name) -# define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name) -# endif -# ifndef XS_EXTERNAL -# if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus) -# define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__) -# define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__) -# else -# ifdef __cplusplus -# define XS_EXTERNAL(name) extern "C" XSPROTO(name) -# define XS_INTERNAL(name) static XSPROTO(name) -# else -# define XS_EXTERNAL(name) XSPROTO(name) -# define XS_INTERNAL(name) STATIC XSPROTO(name) -# endif -# endif -# endif -#endif - -/* perl >= 5.10.0 && perl <= 5.15.1 */ - - -/* The XS_EXTERNAL macro is used for functions that must not be static - * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL - * macro defined, the best we can do is assume XS is the same. - * Dito for XS_INTERNAL. - */ -#ifndef XS_EXTERNAL -# define XS_EXTERNAL(name) XS(name) -#endif -#ifndef XS_INTERNAL -# define XS_INTERNAL(name) XS(name) -#endif - -/* Now, finally, after all this mess, we want an ExtUtils::ParseXS - * internal macro that we're free to redefine for varying linkage due - * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use - * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to! - */ - -#undef XS_EUPXS -#if defined(PERL_EUPXS_ALWAYS_EXPORT) -# define XS_EUPXS(name) XS_EXTERNAL(name) -#else - /* default to internal */ -# define XS_EUPXS(name) XS_INTERNAL(name) -#endif - -#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE -#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params) - -/* prototype to pass -Wmissing-prototypes */ -STATIC void -S_croak_xs_usage(const CV *const cv, const char *const params); - -STATIC void -S_croak_xs_usage(const CV *const cv, const char *const params) -{ - const GV *const gv = CvGV(cv); - - PERL_ARGS_ASSERT_CROAK_XS_USAGE; - - if (gv) { - const char *const gvname = GvNAME(gv); - const HV *const stash = GvSTASH(gv); - const char *const hvname = stash ? HvNAME(stash) : NULL; - - if (hvname) - Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params); - else - Perl_croak_nocontext("Usage: %s(%s)", gvname, params); - } else { - /* Pants. I don't think that it should be possible to get here. */ - Perl_croak_nocontext("Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params); - } -} -#undef PERL_ARGS_ASSERT_CROAK_XS_USAGE - -#define croak_xs_usage S_croak_xs_usage - -#endif - -/* NOTE: the prototype of newXSproto() is different in versions of perls, - * so we define a portable version of newXSproto() - */ -#ifdef newXS_flags -#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0) -#else -#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv) -#endif /* !defined(newXS_flags) */ - -#if PERL_VERSION_LE(5, 21, 5) -# define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file) -#else -# define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b) -#endif - -#line 161 "SQLite2.c" - -XS_EUPXS(XS_DBD__SQLite2__db_list_tables); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_list_tables) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "dbh"); - { - SV * dbh = ST(0) -; - AV * RETVAL; -#line 15 "SQLite2.xs" - { - RETVAL = newAV(); - } -#line 177 "SQLite2.c" - { - SV * RETVALSV; - RETVALSV = newRV((SV*)RETVAL); - RETVALSV = sv_2mortal(RETVALSV); - ST(0) = RETVALSV; - } - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_last_insert_rowid); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_last_insert_rowid) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "dbh"); - { - SV * dbh = ST(0) -; - int RETVAL; - dXSTARG; -#line 25 "SQLite2.xs" - { - D_imp_dbh(dbh); - RETVAL = sqlite_last_insert_rowid(imp_dbh->db); - } -#line 205 "SQLite2.c" - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_create_function); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_create_function) -{ - dVAR; dXSARGS; - if (items != 4) - croak_xs_usage(cv, "dbh, name, argc, func"); - { - SV * dbh = ST(0) -; - char * name = (char *)SvPV_nolen(ST(1)) -; - int argc = (int)SvIV(ST(2)) -; - SV * func = ST(3) -; -#line 39 "SQLite2.xs" - { - sqlite2_db_create_function( dbh, name, argc, func ); - } -#line 231 "SQLite2.c" - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_DBD__SQLite2__db_create_aggregate); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_create_aggregate) -{ - dVAR; dXSARGS; - if (items != 4) - croak_xs_usage(cv, "dbh, name, argc, aggr"); - { - SV * dbh = ST(0) -; - char * name = (char *)SvPV_nolen(ST(1)) -; - int argc = (int)SvIV(ST(2)) -; - SV * aggr = ST(3) -; -#line 50 "SQLite2.xs" - { - sqlite2_db_create_aggregate( dbh, name, argc, aggr ); - } -#line 256 "SQLite2.c" - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_DBD__SQLite2__db_busy_timeout); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_busy_timeout) -{ - dVAR; dXSARGS; - if (items < 1 || items > 2) - croak_xs_usage(cv, "dbh, timeout=0"); - { - SV * dbh = ST(0) -; - int timeout; - int RETVAL; - dXSTARG; - - if (items < 2) - timeout = 0; - else { - timeout = (int)SvIV(ST(1)) -; - } -#line 59 "SQLite2.xs" - RETVAL = sqlite2_busy_timeout( dbh, timeout ); -#line 283 "SQLite2.c" - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - - -/* INCLUDE: Including 'SQLite2.xsi' from 'SQLite2.xs' */ - -#include "Driver_xst.h" -#if defined(dbd_st_execute_iv) -#undef dbd_st_execute -#define dbd_st_execute dbd_st_execute_iv -#endif -#if defined(dbd_st_rows_iv) -#undef dbd_st_rows -#define dbd_st_rows dbd_st_rows_iv -#endif -#if defined(dbd_db_do4_iv) -#undef dbd_db_do4 -#define dbd_db_do4 dbd_db_do4_iv -#endif - -XS_EUPXS(XS_DBD__SQLite2__dr_dbixs_revision); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__dr_dbixs_revision) -{ - dVAR; dXSARGS; - PERL_UNUSED_VAR(cv); /* -W */ - PERL_UNUSED_VAR(ax); /* -Wall */ - SP -= items; - { -#line 57 "./SQLite2.xsi" - ST(0) = sv_2mortal(newSViv(DBIXS_REVISION)); -#line 316 "SQLite2.c" - PUTBACK; - return; - } -} - -#ifdef dbd_discon_all -#define XSubPPtmpAAAA 1 - - -XS_EUPXS(XS_DBD__SQLite2__dr_discon_all_); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__dr_discon_all_) -{ - dVAR; dXSARGS; - dXSI32; - if (items != 1) - croak_xs_usage(cv, "drh"); - { - SV * drh = ST(0) -; -#line 69 "./SQLite2.xsi" - D_imp_drh(drh); - PERL_UNUSED_VAR(ix); - ST(0) = dbd_discon_all(drh, imp_drh) ? &PL_sv_yes : &PL_sv_no; -#line 340 "SQLite2.c" - } - XSRETURN(1); -} - -#endif /* dbd_discon_all */ -#ifdef dbd_dr_data_sources -#define XSubPPtmpAAAB 1 - - -XS_EUPXS(XS_DBD__SQLite2__dr_data_sources); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__dr_data_sources) -{ - dVAR; dXSARGS; - if (items < 1 || items > 2) - croak_xs_usage(cv, "drh, attr = Nullsv"); - PERL_UNUSED_VAR(ax); /* -Wall */ - SP -= items; - { - SV * drh = ST(0) -; - SV * attr; - - if (items < 2) - attr = Nullsv; - else { - attr = ST(1) -; - } -#line 83 "./SQLite2.xsi" - { - D_imp_drh(drh); - AV *av = dbd_dr_data_sources(drh, imp_drh, attr); - if (av) { - int i; - int n = AvFILL(av)+1; - EXTEND(sp, n); - for (i = 0; i < n; ++i) { - PUSHs(AvARRAY(av)[i]); - } - } - } -#line 382 "SQLite2.c" - PUTBACK; - return; - } -} - -#endif - -XS_EUPXS(XS_DBD__SQLite2__db__login); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db__login) -{ - dVAR; dXSARGS; - if (items < 4 || items > 5) - croak_xs_usage(cv, "dbh, dbname, username, password, attribs=Nullsv"); - { - SV * dbh = ST(0) -; - SV * dbname = ST(1) -; - SV * username = ST(2) -; - SV * password = ST(3) -; - SV * attribs; - - if (items < 5) - attribs = Nullsv; - else { - attribs = ST(4) -; - } -#line 113 "./SQLite2.xsi" - { - D_imp_dbh(dbh); -#if !defined(dbd_db_login6_sv) - STRLEN lna; - char *u = (SvOK(username)) ? SvPV(username,lna) : (char*)""; - char *p = (SvOK(password)) ? SvPV(password,lna) : (char*)""; -#endif -#ifdef dbd_db_login6_sv - ST(0) = dbd_db_login6_sv(dbh, imp_dbh, dbname, username, password, attribs) ? &PL_sv_yes : &PL_sv_no; -#elif defined(dbd_db_login6) - ST(0) = dbd_db_login6(dbh, imp_dbh, SvPV_nolen(dbname), u, p, attribs) ? &PL_sv_yes : &PL_sv_no; -#else - PERL_UNUSED_ARG(attribs); - ST(0) = dbd_db_login( dbh, imp_dbh, SvPV_nolen(dbname), u, p) ? &PL_sv_yes : &PL_sv_no; -#endif - } -#line 430 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_selectall_arrayref); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_selectall_arrayref) -{ - dVAR; dXSARGS; - PERL_UNUSED_VAR(cv); /* -W */ - { -#line 134 "./SQLite2.xsi" - SV *sth; - SV **maxrows_svp; - SV **tmp_svp; - SV *tmp_sv; - SV *attr = &PL_sv_undef; - imp_sth_t *imp_sth; -#line 449 "SQLite2.c" -#line 141 "./SQLite2.xsi" - if (items > 2) { - attr = ST(2); - if (SvROK(attr) && - (DBD_ATTRIB_TRUE(attr,"Slice",5,tmp_svp) || DBD_ATTRIB_TRUE(attr,"Columns",7,tmp_svp)) - ) { - /* fallback to perl implementation */ - SV *tmp =dbixst_bounce_method("DBD::SQLite2::db::SUPER::selectall_arrayref", items); - SPAGAIN; - ST(0) = tmp; - XSRETURN(1); - } - } - /* --- prepare --- */ - if (SvROK(ST(1))) { - MAGIC *mg; - sth = ST(1); - /* switch to inner handle if not already */ - if ( (mg = mg_find(SvRV(sth),'P')) ) - sth = mg->mg_obj; - } - else { - sth = dbixst_bounce_method("prepare", 3); - SPAGAIN; SP -= items; /* because stack might have been realloc'd */ - if (!SvROK(sth)) - XSRETURN_UNDEF; - /* switch to inner handle */ - sth = mg_find(SvRV(sth),'P')->mg_obj; - } - imp_sth = (imp_sth_t*)(DBIh_COM(sth)); - /* --- bind_param --- */ - if (items > 3) { /* need to bind params before execute */ - if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) { - XSRETURN_UNDEF; - } - } - /* --- execute --- */ - DBIc_ROW_COUNT(imp_sth) = 0; - if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */ - XSRETURN_UNDEF; - } - /* --- fetchall --- */ - maxrows_svp = DBD_ATTRIB_GET_SVP(attr, "MaxRows", 7); - tmp_sv = dbdxst_fetchall_arrayref(sth, &PL_sv_undef, (maxrows_svp) ? *maxrows_svp : &PL_sv_undef); - SPAGAIN; - ST(0) = tmp_sv; -#line 496 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_selectrow_arrayref); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_selectrow_arrayref) -{ - dVAR; dXSARGS; - dXSI32; - PERL_UNUSED_VAR(cv); /* -W */ - PERL_UNUSED_VAR(ax); /* -Wall */ - SP -= items; - { -#line 193 "./SQLite2.xsi" - int is_selectrow_array = (ix == 1); - imp_sth_t *imp_sth; - SV *sth; - AV *row_av; -#line 516 "SQLite2.c" -#line 198 "./SQLite2.xsi" - if (SvROK(ST(1))) { - MAGIC *mg; - sth = ST(1); - /* switch to inner handle if not already */ - if ( (mg = mg_find(SvRV(sth),'P')) ) - sth = mg->mg_obj; - } - else { - /* --- prepare --- */ - sth = dbixst_bounce_method("prepare", 3); - SPAGAIN; SP -= items; /* because stack might have been realloc'd */ - if (!SvROK(sth)) { - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - /* switch to inner handle */ - sth = mg_find(SvRV(sth),'P')->mg_obj; - } - imp_sth = (imp_sth_t*)(DBIh_COM(sth)); - /* --- bind_param --- */ - if (items > 3) { /* need to bind params before execute */ - if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) { - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - } - /* --- execute --- */ - DBIc_ROW_COUNT(imp_sth) = 0; - if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */ - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - /* --- fetchrow_arrayref --- */ - row_av = dbd_st_fetch(sth, imp_sth); - if (!row_av) { - if (GIMME == G_SCALAR) - PUSHs(&PL_sv_undef); - } - else if (is_selectrow_array) { - int i; - int num_fields = AvFILL(row_av)+1; - if (GIMME == G_SCALAR) - num_fields = 1; /* return just first field */ - EXTEND(sp, num_fields); - for(i=0; i < num_fields; ++i) { - PUSHs(AvARRAY(row_av)[i]); - } - } - else { - PUSHs( sv_2mortal(newRV((SV *)row_av)) ); - } - /* --- finish --- */ -#ifdef dbd_st_finish3 - dbd_st_finish3(sth, imp_sth, 0); -#else - dbd_st_finish(sth, imp_sth); -#endif -#line 572 "SQLite2.c" - PUTBACK; - return; - } -} - -#ifdef dbd_db_do4 /* deebeedee-deebee-doo, deebee-doobee-dah? */ -#define XSubPPtmpAAAC 1 - - -XS_EUPXS(XS_DBD__SQLite2__db_do); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_do) -{ - dVAR; dXSARGS; - if (items < 2 || items > 3) - croak_xs_usage(cv, "dbh, statement, params = Nullsv"); - { - SV * dbh = ST(0) -; - char * statement = (char *)SvPV_nolen(ST(1)) -; - SV * params; - - if (items < 3) - params = Nullsv; - else { - params = ST(2) -; - } -#line 262 "./SQLite2.xsi" - { - D_imp_dbh(dbh); - IV retval; - retval = dbd_db_do4(dbh, imp_dbh, statement, params); /* might be dbd_db_do4_iv via macro */ - /* remember that dbd_db_do4 must return <= -2 for error */ - if (retval == 0) /* ok with no rows affected */ - XST_mPV(0, "0E0"); /* (true but zero) */ - else if (retval < -1) /* -1 == unknown number of rows */ - XST_mUNDEF(0); /* <= -2 means error */ - else - XST_mIV(0, retval); /* typically 1, rowcount or -1 */ - } -#line 614 "SQLite2.c" - } - XSRETURN(1); -} - -#endif -#ifdef dbd_db_last_insert_id -#define XSubPPtmpAAAD 1 - - -XS_EUPXS(XS_DBD__SQLite2__db_last_insert_id); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_last_insert_id) -{ - dVAR; dXSARGS; - if (items < 5 || items > 6) - croak_xs_usage(cv, "dbh, catalog, schema, table, field, attr=Nullsv"); - { - SV * dbh = ST(0) -; - SV * catalog = ST(1) -; - SV * schema = ST(2) -; - SV * table = ST(3) -; - SV * field = ST(4) -; - SV * attr; - - if (items < 6) - attr = Nullsv; - else { - attr = ST(5) -; - } -#line 289 "./SQLite2.xsi" - { - D_imp_dbh(dbh); - ST(0) = dbd_db_last_insert_id(dbh, imp_dbh, catalog, schema, table, field, attr); - } -#line 654 "SQLite2.c" - } - XSRETURN(1); -} - -#endif - -XS_EUPXS(XS_DBD__SQLite2__db_commit); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_commit) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "dbh"); - { - SV * dbh = ST(0) -; -#line 301 "./SQLite2.xsi" - D_imp_dbh(dbh); - if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh)) - warn("commit ineffective with AutoCommit enabled"); - ST(0) = dbd_db_commit(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; -#line 675 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_rollback); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_rollback) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "dbh"); - { - SV * dbh = ST(0) -; -#line 311 "./SQLite2.xsi" - D_imp_dbh(dbh); - if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh)) - warn("rollback ineffective with AutoCommit enabled"); - ST(0) = dbd_db_rollback(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; -#line 695 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_disconnect); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_disconnect) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "dbh"); - { - SV * dbh = ST(0) -; -#line 321 "./SQLite2.xsi" - D_imp_dbh(dbh); - if ( !DBIc_ACTIVE(imp_dbh) ) { - XSRETURN_YES; - } - /* Check for disconnect() being called whilst refs to cursors */ - /* still exists. This possibly needs some more thought. */ - if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !PL_dirty) { - STRLEN lna; - char *plural = (DBIc_ACTIVE_KIDS(imp_dbh)==1) ? (char*)"" : (char*)"s"; - warn("%s->disconnect invalidates %d active statement handle%s %s", - SvPV(dbh,lna), (int)DBIc_ACTIVE_KIDS(imp_dbh), plural, - "(either destroy statement handles or call finish on them before disconnecting)"); - } - ST(0) = dbd_db_disconnect(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; - DBIc_ACTIVE_off(imp_dbh); /* ensure it's off, regardless */ -#line 726 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_STORE); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_STORE) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "dbh, keysv, valuesv"); - { - SV * dbh = ST(0) -; - SV * keysv = ST(1) -; - SV * valuesv = ST(2) -; -#line 344 "./SQLite2.xsi" - D_imp_dbh(dbh); - if (SvGMAGICAL(valuesv)) - mg_get(valuesv); - ST(0) = &PL_sv_yes; - if (!dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv)) - if (!DBIc_DBISTATE(imp_dbh)->set_attr(dbh, keysv, valuesv)) - ST(0) = &PL_sv_no; -#line 753 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_FETCH); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_FETCH) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "dbh, keysv"); - { - SV * dbh = ST(0) -; - SV * keysv = ST(1) -; -#line 358 "./SQLite2.xsi" - D_imp_dbh(dbh); - SV *valuesv = dbd_db_FETCH_attrib(dbh, imp_dbh, keysv); - if (!valuesv) - valuesv = DBIc_DBISTATE(imp_dbh)->get_attr(dbh, keysv); - ST(0) = valuesv; /* dbd_db_FETCH_attrib did sv_2mortal */ -#line 776 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__db_DESTROY); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_DESTROY) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "dbh"); - PERL_UNUSED_VAR(ax); /* -Wall */ - SP -= items; - { - SV * dbh = ST(0) -; -#line 369 "./SQLite2.xsi" - /* keep in sync with default DESTROY in DBI.xs */ - D_imp_dbh(dbh); - ST(0) = &PL_sv_yes; - if (!DBIc_IMPSET(imp_dbh)) { /* was never fully set up */ - STRLEN lna; - if (DBIc_WARN(imp_dbh) && !PL_dirty && DBIc_DBISTATE(imp_dbh)->debug >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), - " DESTROY for %s ignored - handle not initialised\n", - SvPV(dbh,lna)); - } - else { - if (DBIc_IADESTROY(imp_dbh)) { /* wants ineffective destroy */ - DBIc_ACTIVE_off(imp_dbh); - if (DBIc_DBISTATE(imp_dbh)->debug) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), " DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(dbh)); - } - if (DBIc_ACTIVE(imp_dbh)) { - if (!DBIc_has(imp_dbh,DBIcf_AutoCommit)) { - /* Application is using transactions and hasn't explicitly disconnected. - Some databases will automatically commit on graceful disconnect. - Since we're about to gracefully disconnect as part of the DESTROY - we want to be sure we're not about to implicitly commit changes - that are incomplete and should be rolled back. (The DESTROY may - be due to a RaiseError, for example.) So we rollback here. - This will be harmless if the application has issued a commit, - XXX Could add an attribute flag to indicate that the driver - doesn't have this problem. Patches welcome. - */ - if (DBIc_WARN(imp_dbh) /* only warn if likely to be useful... */ - && DBIc_is(imp_dbh, DBIcf_Executed) /* has not just called commit/rollback */ - /* && !DBIc_is(imp_dbh, DBIcf_ReadOnly) -- is not read only */ - && (!PL_dirty || DBIc_DBISTATE(imp_dbh)->debug >= 3) - ) { - warn("Issuing rollback() due to DESTROY without explicit disconnect() of %s handle %s", - SvPV_nolen(*hv_fetch((HV*)SvRV(dbh), "ImplementorClass", 16, 1)), - SvPV_nolen(*hv_fetch((HV*)SvRV(dbh), "Name", 4, 1)) - ); - } - dbd_db_rollback(dbh, imp_dbh); /* ROLLBACK! */ - } - dbd_db_disconnect(dbh, imp_dbh); - DBIc_ACTIVE_off(imp_dbh); /* ensure it's off, regardless */ - } - dbd_db_destroy(dbh, imp_dbh); - } -#line 839 "SQLite2.c" - PUTBACK; - return; - } -} - -#ifdef dbd_take_imp_data -#define XSubPPtmpAAAE 1 - - -XS_EUPXS(XS_DBD__SQLite2__db_take_imp_data); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_take_imp_data) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "h"); - { - SV * h = ST(0) -; -#line 422 "./SQLite2.xsi" - D_imp_xxh(h); - /* dbd_take_imp_data() returns &sv_no (or other defined but false value) - * to indicate "preparations complete, now call SUPER::take_imp_data" for me. - * Anything else is returned to the caller via sv_2mortal(sv), typically that - * would be &sv_undef for error or an SV holding the imp_data. - */ - SV *sv = dbd_take_imp_data(h, imp_xxh, NULL); - if (SvOK(sv) && !SvTRUE(sv)) { - SV *tmp = dbixst_bounce_method("DBD::SQLite2::db::SUPER::take_imp_data", items); - SPAGAIN; - ST(0) = tmp; - } else { - ST(0) = sv_2mortal(sv); - } -#line 873 "SQLite2.c" - } - XSRETURN(1); -} - -#endif -#ifdef dbd_db_data_sources -#define XSubPPtmpAAAF 1 - - -XS_EUPXS(XS_DBD__SQLite2__db_data_sources); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__db_data_sources) -{ - dVAR; dXSARGS; - if (items < 1 || items > 2) - croak_xs_usage(cv, "dbh, attr = Nullsv"); - PERL_UNUSED_VAR(ax); /* -Wall */ - SP -= items; - { - SV * dbh = ST(0) -; - SV * attr; - - if (items < 2) - attr = Nullsv; - else { - attr = ST(1) -; - } -#line 446 "./SQLite2.xsi" - { - D_imp_dbh(dbh); - AV *av = dbd_db_data_sources(dbh, imp_dbh, attr); - if (av) { - int i; - int n = AvFILL(av)+1; - EXTEND(sp, n); - for (i = 0; i < n; ++i) { - PUSHs(AvARRAY(av)[i]); - } - } - } -#line 915 "SQLite2.c" - PUTBACK; - return; - } -} - -#endif - -XS_EUPXS(XS_DBD__SQLite2__st__prepare); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st__prepare) -{ - dVAR; dXSARGS; - if (items < 2 || items > 3) - croak_xs_usage(cv, "sth, statement, attribs=Nullsv"); - { - SV * sth = ST(0) -; - SV * statement = ST(1) -; - SV * attribs; - - if (items < 3) - attribs = Nullsv; - else { - attribs = ST(2) -; - } -#line 475 "./SQLite2.xsi" - { - D_imp_sth(sth); - DBD_ATTRIBS_CHECK("_prepare", sth, attribs); -#ifdef dbd_st_prepare_sv - ST(0) = dbd_st_prepare_sv(sth, imp_sth, statement, attribs) ? &PL_sv_yes : &PL_sv_no; -#else - ST(0) = dbd_st_prepare(sth, imp_sth, SvPV_nolen(statement), attribs) ? &PL_sv_yes : &PL_sv_no; -#endif - } -#line 952 "SQLite2.c" - } - XSRETURN(1); -} - -#ifdef dbd_st_rows -#define XSubPPtmpAAAG 1 - - -XS_EUPXS(XS_DBD__SQLite2__st_rows); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_rows) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "sth"); - { - SV * sth = ST(0) -; -#line 492 "./SQLite2.xsi" - D_imp_sth(sth); - XST_mIV(0, dbd_st_rows(sth, imp_sth)); -#line 973 "SQLite2.c" - } - XSRETURN(1); -} - -#endif /* dbd_st_rows */ -#ifdef dbd_st_bind_col -#define XSubPPtmpAAAH 1 - - -XS_EUPXS(XS_DBD__SQLite2__st_bind_col); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_bind_col) -{ - dVAR; dXSARGS; - if (items < 3 || items > 4) - croak_xs_usage(cv, "sth, col, ref, attribs=Nullsv"); - { - SV * sth = ST(0) -; - SV * col = ST(1) -; - SV * ref = ST(2) -; - SV * attribs; - - if (items < 4) - attribs = Nullsv; - else { - attribs = ST(3) -; - } -#line 507 "./SQLite2.xsi" - { - IV sql_type = 0; - D_imp_sth(sth); - if (SvGMAGICAL(ref)) - mg_get(ref); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_col", sth, attribs); - /* XXX we should perhaps complain if TYPE is not SvNIOK */ - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - switch(dbd_st_bind_col(sth, imp_sth, col, ref, sql_type, attribs)) { - case 2: ST(0) = &PL_sv_yes; /* job done completely */ - break; - case 1: /* fallback to DBI default */ - ST(0) = (DBIc_DBISTATE(imp_sth)->bind_col(sth, col, ref, attribs)) - ? &PL_sv_yes : &PL_sv_no; - break; - default: ST(0) = &PL_sv_no; /* dbd_st_bind_col has called set_err */ - break; - } - } -#line 1033 "SQLite2.c" - } - XSRETURN(1); -} - -#endif /* dbd_st_bind_col */ - -XS_EUPXS(XS_DBD__SQLite2__st_bind_param); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_bind_param) -{ - dVAR; dXSARGS; - if (items < 3 || items > 4) - croak_xs_usage(cv, "sth, param, value, attribs=Nullsv"); - { - SV * sth = ST(0) -; - SV * param = ST(1) -; - SV * value = ST(2) -; - SV * attribs; - - if (items < 4) - attribs = Nullsv; - else { - attribs = ST(3) -; - } -#line 545 "./SQLite2.xsi" - { - IV sql_type = 0; - D_imp_sth(sth); - if (SvGMAGICAL(value)) - mg_get(value); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_param", sth, attribs); - /* XXX we should perhaps complain if TYPE is not SvNIOK */ - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - ST(0) = dbd_bind_ph(sth, imp_sth, param, value, sql_type, attribs, FALSE, 0) - ? &PL_sv_yes : &PL_sv_no; - } -#line 1082 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__st_bind_param_inout); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_bind_param_inout) -{ - dVAR; dXSARGS; - if (items < 4 || items > 5) - croak_xs_usage(cv, "sth, param, value_ref, maxlen, attribs=Nullsv"); - { - SV * sth = ST(0) -; - SV * param = ST(1) -; - SV * value_ref = ST(2) -; - IV maxlen = (IV)SvIV(ST(3)) -; - SV * attribs; - - if (items < 5) - attribs = Nullsv; - else { - attribs = ST(4) -; - } -#line 575 "./SQLite2.xsi" - { - IV sql_type = 0; - D_imp_sth(sth); - SV *value; - if (!SvROK(value_ref) || SvTYPE(SvRV(value_ref)) > SVt_PVMG) - croak("bind_param_inout needs a reference to a scalar value"); - value = SvRV(value_ref); - if (SvREADONLY(value)) - croak("Modification of a read-only value attempted"); - if (SvGMAGICAL(value)) - mg_get(value); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_param", sth, attribs); - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - ST(0) = dbd_bind_ph(sth, imp_sth, param, value, sql_type, attribs, TRUE, maxlen) - ? &PL_sv_yes : &PL_sv_no; - } -#line 1137 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__st_execute); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_execute) -{ - dVAR; dXSARGS; - if (items < 1) - croak_xs_usage(cv, "sth, ..."); - { - SV * sth = ST(0) -; -#line 606 "./SQLite2.xsi" - D_imp_sth(sth); - IV retval; - if (items > 1) { /* need to bind params */ - if (!dbdxst_bind_params(sth, imp_sth, items, ax) ) { - XSRETURN_UNDEF; - } - } - /* XXX this code is duplicated in selectrow_arrayref above */ - DBIc_ROW_COUNT(imp_sth) = 0; - retval = dbd_st_execute(sth, imp_sth); /* might be dbd_st_execute_iv via macro */ - /* remember that dbd_st_execute must return <= -2 for error */ - if (retval == 0) /* ok with no rows affected */ - XST_mPV(0, "0E0"); /* (true but zero) */ - else if (retval < -1) /* -1 == unknown number of rows */ - XST_mUNDEF(0); /* <= -2 means error */ - else - XST_mIV(0, retval); /* typically 1, rowcount or -1 */ -#line 1170 "SQLite2.c" - } - XSRETURN(1); -} - -#ifdef dbd_st_execute_for_fetch -#define XSubPPtmpAAAI 1 - - -XS_EUPXS(XS_DBD__SQLite2__st_execute_for_fetch); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_execute_for_fetch) -{ - dVAR; dXSARGS; - if (items < 2 || items > 3) - croak_xs_usage(cv, "sth, fetch_tuple_sub, tuple_status = Nullsv"); - { - SV * sth = ST(0) -; - SV * fetch_tuple_sub = ST(1) -; - SV * tuple_status; - - if (items < 3) - tuple_status = Nullsv; - else { - tuple_status = ST(2) -; - } -#line 633 "./SQLite2.xsi" - { - D_imp_sth(sth); - ST(0) = dbd_st_execute_for_fetch(sth, imp_sth, fetch_tuple_sub, tuple_status); - } -#line 1203 "SQLite2.c" - } - XSRETURN(1); -} - -#endif - -XS_EUPXS(XS_DBD__SQLite2__st_fetchrow_arrayref); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_fetchrow_arrayref) -{ - dVAR; dXSARGS; - dXSI32; - if (items != 1) - croak_xs_usage(cv, "sth"); - { - SV * sth = ST(0) -; -#line 648 "./SQLite2.xsi" - D_imp_sth(sth); - AV *av; - PERL_UNUSED_VAR(ix); - av = dbd_st_fetch(sth, imp_sth); - ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef; -#line 1226 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__st_fetchrow_array); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_fetchrow_array) -{ - dVAR; dXSARGS; - dXSI32; - if (items != 1) - croak_xs_usage(cv, "sth"); - PERL_UNUSED_VAR(ax); /* -Wall */ - SP -= items; - { - SV * sth = ST(0) -; -#line 661 "./SQLite2.xsi" - D_imp_sth(sth); - AV *av; - av = dbd_st_fetch(sth, imp_sth); - if (av) { - int i; - int num_fields = AvFILL(av)+1; - EXTEND(sp, num_fields); - for(i=0; i < num_fields; ++i) { - PUSHs(AvARRAY(av)[i]); - } - PERL_UNUSED_VAR(ix); - } -#line 1257 "SQLite2.c" - PUTBACK; - return; - } -} - - -XS_EUPXS(XS_DBD__SQLite2__st_fetchall_arrayref); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_fetchall_arrayref) -{ - dVAR; dXSARGS; - if (items < 1 || items > 3) - croak_xs_usage(cv, "sth, slice=&PL_sv_undef, batch_row_count=&PL_sv_undef"); - { - SV * sth = ST(0) -; - SV * slice; - SV * batch_row_count; - - if (items < 2) - slice = &PL_sv_undef; - else { - slice = ST(1) -; - } - - if (items < 3) - batch_row_count = &PL_sv_undef; - else { - batch_row_count = ST(2) -; - } -#line 681 "./SQLite2.xsi" - if (SvOK(slice)) { /* fallback to perl implementation */ - SV *tmp = dbixst_bounce_method("DBD::SQLite2::st::SUPER::fetchall_arrayref", 3); - SPAGAIN; - ST(0) = tmp; - } - else { - SV *tmp = dbdxst_fetchall_arrayref(sth, slice, batch_row_count); - SPAGAIN; - ST(0) = tmp; - } -#line 1300 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__st_finish); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_finish) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "sth"); - { - SV * sth = ST(0) -; -#line 697 "./SQLite2.xsi" - D_imp_sth(sth); - D_imp_dbh_from_sth; - if (!DBIc_ACTIVE(imp_sth)) { - /* No active statement to finish */ - XSRETURN_YES; - } - if (!DBIc_ACTIVE(imp_dbh)) { - /* Either an explicit disconnect() or global destruction */ - /* has disconnected us from the database. Finish is meaningless */ - DBIc_ACTIVE_off(imp_sth); - XSRETURN_YES; - } -#ifdef dbd_st_finish3 - ST(0) = dbd_st_finish3(sth, imp_sth, 0) ? &PL_sv_yes : &PL_sv_no; -#else - ST(0) = dbd_st_finish(sth, imp_sth) ? &PL_sv_yes : &PL_sv_no; -#endif -#line 1333 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__st_blob_read); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_blob_read) -{ - dVAR; dXSARGS; - if (items < 4 || items > 6) - croak_xs_usage(cv, "sth, field, offset, len, destrv=Nullsv, destoffset=0"); - { - SV * sth = ST(0) -; - int field = (int)SvIV(ST(1)) -; - long offset = (long)SvIV(ST(2)) -; - long len = (long)SvIV(ST(3)) -; - SV * destrv; - long destoffset; - - if (items < 5) - destrv = Nullsv; - else { - destrv = ST(4) -; - } - - if (items < 6) - destoffset = 0; - else { - destoffset = (long)SvIV(ST(5)) -; - } -#line 725 "./SQLite2.xsi" - { - D_imp_sth(sth); - if (!destrv) - destrv = sv_2mortal(newRV(sv_2mortal(newSV(0)))); - if (dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset)) - ST(0) = SvRV(destrv); - else ST(0) = &PL_sv_undef; - } -#line 1379 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__st_STORE); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_STORE) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "sth, keysv, valuesv"); - { - SV * sth = ST(0) -; - SV * keysv = ST(1) -; - SV * valuesv = ST(2) -; -#line 741 "./SQLite2.xsi" - D_imp_sth(sth); - if (SvGMAGICAL(valuesv)) - mg_get(valuesv); - ST(0) = &PL_sv_yes; - if (!dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv)) - if (!DBIc_DBISTATE(imp_sth)->set_attr(sth, keysv, valuesv)) - ST(0) = &PL_sv_no; -#line 1406 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__st_FETCH_attrib); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_FETCH_attrib) -{ - dVAR; dXSARGS; - dXSI32; - if (items != 2) - croak_xs_usage(cv, "sth, keysv"); - { - SV * sth = ST(0) -; - SV * keysv = ST(1) -; -#line 758 "./SQLite2.xsi" - D_imp_sth(sth); - SV *valuesv; - PERL_UNUSED_VAR(ix); - valuesv = dbd_st_FETCH_attrib(sth, imp_sth, keysv); - if (!valuesv) - valuesv = DBIc_DBISTATE(imp_sth)->get_attr(sth, keysv); - ST(0) = valuesv; /* dbd_st_FETCH_attrib did sv_2mortal */ -#line 1432 "SQLite2.c" - } - XSRETURN(1); -} - - -XS_EUPXS(XS_DBD__SQLite2__st_DESTROY); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_DBD__SQLite2__st_DESTROY) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "sth"); - PERL_UNUSED_VAR(ax); /* -Wall */ - SP -= items; - { - SV * sth = ST(0) -; -#line 771 "./SQLite2.xsi" - /* keep in sync with default DESTROY in DBI.xs */ - D_imp_sth(sth); - ST(0) = &PL_sv_yes; - if (!DBIc_IMPSET(imp_sth)) { /* was never fully set up */ - STRLEN lna; - if (DBIc_WARN(imp_sth) && !PL_dirty && DBIc_DBISTATE(imp_sth)->debug >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_sth), - " DESTROY for %s ignored - handle not initialised\n", - SvPV(sth,lna)); - } - else { - if (DBIc_IADESTROY(imp_sth)) { /* wants ineffective destroy */ - DBIc_ACTIVE_off(imp_sth); - if (DBIc_DBISTATE(imp_sth)->debug) - PerlIO_printf(DBIc_LOGPIO(imp_sth), " DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(sth)); - } - if (DBIc_ACTIVE(imp_sth)) { - D_imp_dbh_from_sth; - if (!PL_dirty && DBIc_ACTIVE(imp_dbh)) { -#ifdef dbd_st_finish3 - dbd_st_finish3(sth, imp_sth, 1); -#else - dbd_st_finish(sth, imp_sth); -#endif - } - else { - DBIc_ACTIVE_off(imp_sth); - } - } - dbd_st_destroy(sth, imp_sth); - } -#line 1481 "SQLite2.c" - PUTBACK; - return; - } -} - - -/* INCLUDE: Returning to 'SQLite2.xs' from 'SQLite2.xsi' */ - -#ifdef __cplusplus -extern "C" -#endif -XS_EXTERNAL(boot_DBD__SQLite2); /* prototype to pass -Wmissing-prototypes */ -XS_EXTERNAL(boot_DBD__SQLite2) -{ -#if PERL_VERSION_LE(5, 21, 5) - dVAR; dXSARGS; -#else - dVAR; dXSBOOTARGSXSAPIVERCHK; -#endif -#if (PERL_REVISION == 5 && PERL_VERSION < 9) - char* file = __FILE__; -#else - const char* file = __FILE__; -#endif - - PERL_UNUSED_VAR(file); - - PERL_UNUSED_VAR(cv); /* -W */ - PERL_UNUSED_VAR(items); /* -W */ -#if PERL_VERSION_LE(5, 21, 5) - XS_VERSION_BOOTCHECK; -# ifdef XS_APIVERSION_BOOTCHECK - XS_APIVERSION_BOOTCHECK; -# endif -#endif - - newXS_deffile("DBD::SQLite2::db::list_tables", XS_DBD__SQLite2__db_list_tables); - newXS_deffile("DBD::SQLite2::db::last_insert_rowid", XS_DBD__SQLite2__db_last_insert_rowid); - newXS_deffile("DBD::SQLite2::db::create_function", XS_DBD__SQLite2__db_create_function); - newXS_deffile("DBD::SQLite2::db::create_aggregate", XS_DBD__SQLite2__db_create_aggregate); - newXS_deffile("DBD::SQLite2::db::busy_timeout", XS_DBD__SQLite2__db_busy_timeout); - newXS_deffile("DBD::SQLite2::dr::dbixs_revision", XS_DBD__SQLite2__dr_dbixs_revision); -#if XSubPPtmpAAAA - cv = newXS_deffile("DBD::SQLite2::dr::discon_all_", XS_DBD__SQLite2__dr_discon_all_); - XSANY.any_i32 = 0; - cv = newXS_deffile("DBD::SQLite2::dr::disconnect_all", XS_DBD__SQLite2__dr_discon_all_); - XSANY.any_i32 = 1; -#endif -#if XSubPPtmpAAAB - newXS_deffile("DBD::SQLite2::dr::data_sources", XS_DBD__SQLite2__dr_data_sources); -#endif - newXS_deffile("DBD::SQLite2::db::_login", XS_DBD__SQLite2__db__login); - newXS_deffile("DBD::SQLite2::db::selectall_arrayref", XS_DBD__SQLite2__db_selectall_arrayref); - cv = newXS_deffile("DBD::SQLite2::db::selectrow_array", XS_DBD__SQLite2__db_selectrow_arrayref); - XSANY.any_i32 = 1; - cv = newXS_deffile("DBD::SQLite2::db::selectrow_arrayref", XS_DBD__SQLite2__db_selectrow_arrayref); - XSANY.any_i32 = 0; -#if XSubPPtmpAAAC - newXS_deffile("DBD::SQLite2::db::do", XS_DBD__SQLite2__db_do); -#endif -#if XSubPPtmpAAAD - newXS_deffile("DBD::SQLite2::db::last_insert_id", XS_DBD__SQLite2__db_last_insert_id); -#endif - newXS_deffile("DBD::SQLite2::db::commit", XS_DBD__SQLite2__db_commit); - newXS_deffile("DBD::SQLite2::db::rollback", XS_DBD__SQLite2__db_rollback); - newXS_deffile("DBD::SQLite2::db::disconnect", XS_DBD__SQLite2__db_disconnect); - newXS_deffile("DBD::SQLite2::db::STORE", XS_DBD__SQLite2__db_STORE); - newXS_deffile("DBD::SQLite2::db::FETCH", XS_DBD__SQLite2__db_FETCH); - newXS_deffile("DBD::SQLite2::db::DESTROY", XS_DBD__SQLite2__db_DESTROY); -#if XSubPPtmpAAAE - newXS_deffile("DBD::SQLite2::db::take_imp_data", XS_DBD__SQLite2__db_take_imp_data); -#endif -#if XSubPPtmpAAAF - newXS_deffile("DBD::SQLite2::db::data_sources", XS_DBD__SQLite2__db_data_sources); -#endif - newXS_deffile("DBD::SQLite2::st::_prepare", XS_DBD__SQLite2__st__prepare); -#if XSubPPtmpAAAG - newXS_deffile("DBD::SQLite2::st::rows", XS_DBD__SQLite2__st_rows); -#endif -#if XSubPPtmpAAAH - newXS_deffile("DBD::SQLite2::st::bind_col", XS_DBD__SQLite2__st_bind_col); -#endif - newXS_deffile("DBD::SQLite2::st::bind_param", XS_DBD__SQLite2__st_bind_param); - newXS_deffile("DBD::SQLite2::st::bind_param_inout", XS_DBD__SQLite2__st_bind_param_inout); - newXS_deffile("DBD::SQLite2::st::execute", XS_DBD__SQLite2__st_execute); -#if XSubPPtmpAAAI - newXS_deffile("DBD::SQLite2::st::execute_for_fetch", XS_DBD__SQLite2__st_execute_for_fetch); -#endif - cv = newXS_deffile("DBD::SQLite2::st::fetch", XS_DBD__SQLite2__st_fetchrow_arrayref); - XSANY.any_i32 = 1; - cv = newXS_deffile("DBD::SQLite2::st::fetchrow_arrayref", XS_DBD__SQLite2__st_fetchrow_arrayref); - XSANY.any_i32 = 0; - cv = newXS_deffile("DBD::SQLite2::st::fetchrow", XS_DBD__SQLite2__st_fetchrow_array); - XSANY.any_i32 = 1; - cv = newXS_deffile("DBD::SQLite2::st::fetchrow_array", XS_DBD__SQLite2__st_fetchrow_array); - XSANY.any_i32 = 0; - newXS_deffile("DBD::SQLite2::st::fetchall_arrayref", XS_DBD__SQLite2__st_fetchall_arrayref); - newXS_deffile("DBD::SQLite2::st::finish", XS_DBD__SQLite2__st_finish); - newXS_deffile("DBD::SQLite2::st::blob_read", XS_DBD__SQLite2__st_blob_read); - newXS_deffile("DBD::SQLite2::st::STORE", XS_DBD__SQLite2__st_STORE); - cv = newXS_deffile("DBD::SQLite2::st::FETCH", XS_DBD__SQLite2__st_FETCH_attrib); - XSANY.any_i32 = 1; - cv = newXS_deffile("DBD::SQLite2::st::FETCH_attrib", XS_DBD__SQLite2__st_FETCH_attrib); - XSANY.any_i32 = 0; - newXS_deffile("DBD::SQLite2::st::DESTROY", XS_DBD__SQLite2__st_DESTROY); - - /* Initialisation Section */ - -#line 39 "./SQLite2.xsi" - PERL_UNUSED_VAR(items); - DBISTATE_INIT; - /* XXX this interface will change: */ - DBI_IMP_SIZE("DBD::SQLite2::dr::imp_data_size", sizeof(imp_drh_t)); - DBI_IMP_SIZE("DBD::SQLite2::db::imp_data_size", sizeof(imp_dbh_t)); - DBI_IMP_SIZE("DBD::SQLite2::st::imp_data_size", sizeof(imp_sth_t)); - dbd_init(DBIS); - -#if XSubPPtmpAAAA -#endif -#if XSubPPtmpAAAB -#endif -#if XSubPPtmpAAAC -#endif -#if XSubPPtmpAAAD -#endif -#if XSubPPtmpAAAE -#endif -#if XSubPPtmpAAAF -#endif -#if XSubPPtmpAAAG -#endif -#if XSubPPtmpAAAH -#endif -#if XSubPPtmpAAAI -#endif -#line 1617 "SQLite2.c" - - /* End of Initialisation Section */ - -#if PERL_VERSION_LE(5, 21, 5) -# if PERL_VERSION_GE(5, 9, 0) - if (PL_unitcheckav) - call_list(PL_scopestack_ix, PL_unitcheckav); -# endif - XSRETURN_YES; -#else - Perl_xs_boot_epilog(aTHX_ ax); -#endif -} - diff --git a/dbLifeLog/DBD-SQLite2-0.33/SQLite2.o b/dbLifeLog/DBD-SQLite2-0.33/SQLite2.o deleted file mode 100644 index 170db6c1c5fd7a29a15ce1f155d62ed4b0323f9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56064 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 Q^cT=W5w6un{>}9NFI}_9VE_OC diff --git a/dbLifeLog/DBD-SQLite2-0.33/SQLite2.xs b/dbLifeLog/DBD-SQLite2-0.33/SQLite2.xs deleted file mode 100644 index fa4ec4e..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/SQLite2.xs +++ /dev/null @@ -1,69 +0,0 @@ -/* $Id: SQLite2.xs,v 1.2 2004/08/09 13:23:55 matt Exp $ */ - -#include "SQLiteXS.h" - -DBISTATE_DECLARE; - -MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2::db - -PROTOTYPES: DISABLE - -AV * -list_tables(dbh) - SV *dbh - CODE: - { - RETVAL = newAV(); - } - OUTPUT: - RETVAL - -int -last_insert_rowid(dbh) - SV *dbh - CODE: - { - D_imp_dbh(dbh); - RETVAL = sqlite_last_insert_rowid(imp_dbh->db); - } - OUTPUT: - RETVAL - -void -create_function(dbh, name, argc, func) - SV *dbh - char *name - int argc - SV *func - CODE: - { - sqlite2_db_create_function( dbh, name, argc, func ); - } - -void -create_aggregate(dbh, name, argc, aggr) - SV *dbh - char *name - int argc - SV *aggr - CODE: - { - sqlite2_db_create_aggregate( dbh, name, argc, aggr ); - } - -int -busy_timeout(dbh, timeout=0) - SV *dbh - int timeout - CODE: - RETVAL = sqlite2_busy_timeout( dbh, timeout ); - OUTPUT: - RETVAL - -MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2::st - -PROTOTYPES: DISABLE - -MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2 - -INCLUDE: SQLite2.xsi diff --git a/dbLifeLog/DBD-SQLite2-0.33/SQLite2.xsi b/dbLifeLog/DBD-SQLite2-0.33/SQLite2.xsi deleted file mode 100644 index 1103619..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/SQLite2.xsi +++ /dev/null @@ -1,804 +0,0 @@ -# $Id$ -# Copyright (c) 1997-2002 Tim Bunce Ireland -# Copyright (c) 2002 Jonathan Leffler -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - -#include "Driver_xst.h" - -# Historically dbd_db_do4, dbd_st_execute, and dbd_st_rows returned an 'int' type. -# That's only 32 bits (31+sign) so isn't sufficient for very large row counts -# So now instead of defining those macros, drivers can define dbd_db_do4_iv, -# dbd_st_execute_iv, and dbd_st_rows_iv to be the names of functions that -# return an 'IV' type. They could also set DBIc_ROW_COUNT(imp_sth). -# -# To save a mess of #ifdef's we arrange for dbd_st_execute (etc) to work -# as dbd_st_execute_iv if that's defined -# -#if defined(dbd_st_execute_iv) -#undef dbd_st_execute -#define dbd_st_execute dbd_st_execute_iv -#endif -#if defined(dbd_st_rows_iv) -#undef dbd_st_rows -#define dbd_st_rows dbd_st_rows_iv -#endif -#if defined(dbd_db_do4_iv) -#undef dbd_db_do4 -#define dbd_db_do4 dbd_db_do4_iv -#endif - -MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2 - -REQUIRE: 1.929 -PROTOTYPES: DISABLE - -BOOT: - PERL_UNUSED_VAR(items); - DBISTATE_INIT; - /* XXX this interface will change: */ - DBI_IMP_SIZE("DBD::SQLite2::dr::imp_data_size", sizeof(imp_drh_t)); - DBI_IMP_SIZE("DBD::SQLite2::db::imp_data_size", sizeof(imp_dbh_t)); - DBI_IMP_SIZE("DBD::SQLite2::st::imp_data_size", sizeof(imp_sth_t)); - dbd_init(DBIS); - - -# ------------------------------------------------------------ -# driver level interface -# ------------------------------------------------------------ -MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2::dr - - -void -dbixs_revision(...) - PPCODE: - ST(0) = sv_2mortal(newSViv(DBIXS_REVISION)); - - -#ifdef dbd_discon_all - -# disconnect_all renamed and ALIAS'd to avoid length clash on VMS :-( -void -discon_all_(drh) - SV * drh - ALIAS: - disconnect_all = 1 - CODE: - D_imp_drh(drh); - PERL_UNUSED_VAR(ix); - ST(0) = dbd_discon_all(drh, imp_drh) ? &PL_sv_yes : &PL_sv_no; - -#endif /* dbd_discon_all */ - - -#ifdef dbd_dr_data_sources - -void -data_sources(drh, attr = Nullsv) - SV *drh - SV *attr - PPCODE: - { - D_imp_drh(drh); - AV *av = dbd_dr_data_sources(drh, imp_drh, attr); - if (av) { - int i; - int n = AvFILL(av)+1; - EXTEND(sp, n); - for (i = 0; i < n; ++i) { - PUSHs(AvARRAY(av)[i]); - } - } - } - -#endif - - -# ------------------------------------------------------------ -# database level interface -# ------------------------------------------------------------ -MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2::db - - -void -_login(dbh, dbname, username, password, attribs=Nullsv) - SV * dbh - SV * dbname - SV * username - SV * password - SV * attribs - CODE: - { - D_imp_dbh(dbh); -#if !defined(dbd_db_login6_sv) - STRLEN lna; - char *u = (SvOK(username)) ? SvPV(username,lna) : (char*)""; - char *p = (SvOK(password)) ? SvPV(password,lna) : (char*)""; -#endif -#ifdef dbd_db_login6_sv - ST(0) = dbd_db_login6_sv(dbh, imp_dbh, dbname, username, password, attribs) ? &PL_sv_yes : &PL_sv_no; -#elif defined(dbd_db_login6) - ST(0) = dbd_db_login6(dbh, imp_dbh, SvPV_nolen(dbname), u, p, attribs) ? &PL_sv_yes : &PL_sv_no; -#else - PERL_UNUSED_ARG(attribs); - ST(0) = dbd_db_login( dbh, imp_dbh, SvPV_nolen(dbname), u, p) ? &PL_sv_yes : &PL_sv_no; -#endif - } - - -void -selectall_arrayref(...) - PREINIT: - SV *sth; - SV **maxrows_svp; - SV **tmp_svp; - SV *tmp_sv; - SV *attr = &PL_sv_undef; - imp_sth_t *imp_sth; - CODE: - if (items > 2) { - attr = ST(2); - if (SvROK(attr) && - (DBD_ATTRIB_TRUE(attr,"Slice",5,tmp_svp) || DBD_ATTRIB_TRUE(attr,"Columns",7,tmp_svp)) - ) { - /* fallback to perl implementation */ - SV *tmp =dbixst_bounce_method("DBD::SQLite2::db::SUPER::selectall_arrayref", items); - SPAGAIN; - ST(0) = tmp; - XSRETURN(1); - } - } - /* --- prepare --- */ - if (SvROK(ST(1))) { - MAGIC *mg; - sth = ST(1); - /* switch to inner handle if not already */ - if ( (mg = mg_find(SvRV(sth),'P')) ) - sth = mg->mg_obj; - } - else { - sth = dbixst_bounce_method("prepare", 3); - SPAGAIN; SP -= items; /* because stack might have been realloc'd */ - if (!SvROK(sth)) - XSRETURN_UNDEF; - /* switch to inner handle */ - sth = mg_find(SvRV(sth),'P')->mg_obj; - } - imp_sth = (imp_sth_t*)(DBIh_COM(sth)); - /* --- bind_param --- */ - if (items > 3) { /* need to bind params before execute */ - if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) { - XSRETURN_UNDEF; - } - } - /* --- execute --- */ - DBIc_ROW_COUNT(imp_sth) = 0; - if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */ - XSRETURN_UNDEF; - } - /* --- fetchall --- */ - maxrows_svp = DBD_ATTRIB_GET_SVP(attr, "MaxRows", 7); - tmp_sv = dbdxst_fetchall_arrayref(sth, &PL_sv_undef, (maxrows_svp) ? *maxrows_svp : &PL_sv_undef); - SPAGAIN; - ST(0) = tmp_sv; - - -void -selectrow_arrayref(...) - ALIAS: - selectrow_array = 1 - PREINIT: - int is_selectrow_array = (ix == 1); - imp_sth_t *imp_sth; - SV *sth; - AV *row_av; - PPCODE: - if (SvROK(ST(1))) { - MAGIC *mg; - sth = ST(1); - /* switch to inner handle if not already */ - if ( (mg = mg_find(SvRV(sth),'P')) ) - sth = mg->mg_obj; - } - else { - /* --- prepare --- */ - sth = dbixst_bounce_method("prepare", 3); - SPAGAIN; SP -= items; /* because stack might have been realloc'd */ - if (!SvROK(sth)) { - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - /* switch to inner handle */ - sth = mg_find(SvRV(sth),'P')->mg_obj; - } - imp_sth = (imp_sth_t*)(DBIh_COM(sth)); - /* --- bind_param --- */ - if (items > 3) { /* need to bind params before execute */ - if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) { - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - } - /* --- execute --- */ - DBIc_ROW_COUNT(imp_sth) = 0; - if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */ - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - /* --- fetchrow_arrayref --- */ - row_av = dbd_st_fetch(sth, imp_sth); - if (!row_av) { - if (GIMME == G_SCALAR) - PUSHs(&PL_sv_undef); - } - else if (is_selectrow_array) { - int i; - int num_fields = AvFILL(row_av)+1; - if (GIMME == G_SCALAR) - num_fields = 1; /* return just first field */ - EXTEND(sp, num_fields); - for(i=0; i < num_fields; ++i) { - PUSHs(AvARRAY(row_av)[i]); - } - } - else { - PUSHs( sv_2mortal(newRV((SV *)row_av)) ); - } - /* --- finish --- */ -#ifdef dbd_st_finish3 - dbd_st_finish3(sth, imp_sth, 0); -#else - dbd_st_finish(sth, imp_sth); -#endif - - -#ifdef dbd_db_do4 /* deebeedee-deebee-doo, deebee-doobee-dah? */ - -void -do(dbh, statement, params = Nullsv) - SV * dbh - char * statement - SV * params - CODE: - { - D_imp_dbh(dbh); - IV retval; - retval = dbd_db_do4(dbh, imp_dbh, statement, params); /* might be dbd_db_do4_iv via macro */ - /* remember that dbd_db_do4 must return <= -2 for error */ - if (retval == 0) /* ok with no rows affected */ - XST_mPV(0, "0E0"); /* (true but zero) */ - else if (retval < -1) /* -1 == unknown number of rows */ - XST_mUNDEF(0); /* <= -2 means error */ - else - XST_mIV(0, retval); /* typically 1, rowcount or -1 */ - } - -#endif - - -#ifdef dbd_db_last_insert_id - -void -last_insert_id(dbh, catalog, schema, table, field, attr=Nullsv) - SV * dbh - SV * catalog - SV * schema - SV * table - SV * field - SV * attr - CODE: - { - D_imp_dbh(dbh); - ST(0) = dbd_db_last_insert_id(dbh, imp_dbh, catalog, schema, table, field, attr); - } - -#endif - - -void -commit(dbh) - SV * dbh - CODE: - D_imp_dbh(dbh); - if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh)) - warn("commit ineffective with AutoCommit enabled"); - ST(0) = dbd_db_commit(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; - - -void -rollback(dbh) - SV * dbh - CODE: - D_imp_dbh(dbh); - if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh)) - warn("rollback ineffective with AutoCommit enabled"); - ST(0) = dbd_db_rollback(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; - - -void -disconnect(dbh) - SV * dbh - CODE: - D_imp_dbh(dbh); - if ( !DBIc_ACTIVE(imp_dbh) ) { - XSRETURN_YES; - } - /* Check for disconnect() being called whilst refs to cursors */ - /* still exists. This possibly needs some more thought. */ - if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !PL_dirty) { - STRLEN lna; - char *plural = (DBIc_ACTIVE_KIDS(imp_dbh)==1) ? (char*)"" : (char*)"s"; - warn("%s->disconnect invalidates %d active statement handle%s %s", - SvPV(dbh,lna), (int)DBIc_ACTIVE_KIDS(imp_dbh), plural, - "(either destroy statement handles or call finish on them before disconnecting)"); - } - ST(0) = dbd_db_disconnect(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; - DBIc_ACTIVE_off(imp_dbh); /* ensure it's off, regardless */ - - -void -STORE(dbh, keysv, valuesv) - SV * dbh - SV * keysv - SV * valuesv - CODE: - D_imp_dbh(dbh); - if (SvGMAGICAL(valuesv)) - mg_get(valuesv); - ST(0) = &PL_sv_yes; - if (!dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv)) - if (!DBIc_DBISTATE(imp_dbh)->set_attr(dbh, keysv, valuesv)) - ST(0) = &PL_sv_no; - - -void -FETCH(dbh, keysv) - SV * dbh - SV * keysv - CODE: - D_imp_dbh(dbh); - SV *valuesv = dbd_db_FETCH_attrib(dbh, imp_dbh, keysv); - if (!valuesv) - valuesv = DBIc_DBISTATE(imp_dbh)->get_attr(dbh, keysv); - ST(0) = valuesv; /* dbd_db_FETCH_attrib did sv_2mortal */ - - -void -DESTROY(dbh) - SV * dbh - PPCODE: - /* keep in sync with default DESTROY in DBI.xs */ - D_imp_dbh(dbh); - ST(0) = &PL_sv_yes; - if (!DBIc_IMPSET(imp_dbh)) { /* was never fully set up */ - STRLEN lna; - if (DBIc_WARN(imp_dbh) && !PL_dirty && DBIc_DBISTATE(imp_dbh)->debug >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), - " DESTROY for %s ignored - handle not initialised\n", - SvPV(dbh,lna)); - } - else { - if (DBIc_IADESTROY(imp_dbh)) { /* wants ineffective destroy */ - DBIc_ACTIVE_off(imp_dbh); - if (DBIc_DBISTATE(imp_dbh)->debug) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), " DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(dbh)); - } - if (DBIc_ACTIVE(imp_dbh)) { - if (!DBIc_has(imp_dbh,DBIcf_AutoCommit)) { - /* Application is using transactions and hasn't explicitly disconnected. - Some databases will automatically commit on graceful disconnect. - Since we're about to gracefully disconnect as part of the DESTROY - we want to be sure we're not about to implicitly commit changes - that are incomplete and should be rolled back. (The DESTROY may - be due to a RaiseError, for example.) So we rollback here. - This will be harmless if the application has issued a commit, - XXX Could add an attribute flag to indicate that the driver - doesn't have this problem. Patches welcome. - */ - if (DBIc_WARN(imp_dbh) /* only warn if likely to be useful... */ - && DBIc_is(imp_dbh, DBIcf_Executed) /* has not just called commit/rollback */ - /* && !DBIc_is(imp_dbh, DBIcf_ReadOnly) -- is not read only */ - && (!PL_dirty || DBIc_DBISTATE(imp_dbh)->debug >= 3) - ) { - warn("Issuing rollback() due to DESTROY without explicit disconnect() of %s handle %s", - SvPV_nolen(*hv_fetch((HV*)SvRV(dbh), "ImplementorClass", 16, 1)), - SvPV_nolen(*hv_fetch((HV*)SvRV(dbh), "Name", 4, 1)) - ); - } - dbd_db_rollback(dbh, imp_dbh); /* ROLLBACK! */ - } - dbd_db_disconnect(dbh, imp_dbh); - DBIc_ACTIVE_off(imp_dbh); /* ensure it's off, regardless */ - } - dbd_db_destroy(dbh, imp_dbh); - } - - -#ifdef dbd_take_imp_data - -void -take_imp_data(h) - SV * h - CODE: - D_imp_xxh(h); - /* dbd_take_imp_data() returns &sv_no (or other defined but false value) - * to indicate "preparations complete, now call SUPER::take_imp_data" for me. - * Anything else is returned to the caller via sv_2mortal(sv), typically that - * would be &sv_undef for error or an SV holding the imp_data. - */ - SV *sv = dbd_take_imp_data(h, imp_xxh, NULL); - if (SvOK(sv) && !SvTRUE(sv)) { - SV *tmp = dbixst_bounce_method("DBD::SQLite2::db::SUPER::take_imp_data", items); - SPAGAIN; - ST(0) = tmp; - } else { - ST(0) = sv_2mortal(sv); - } - -#endif - -#ifdef dbd_db_data_sources - -void -data_sources(dbh, attr = Nullsv) - SV *dbh - SV *attr - PPCODE: - { - D_imp_dbh(dbh); - AV *av = dbd_db_data_sources(dbh, imp_dbh, attr); - if (av) { - int i; - int n = AvFILL(av)+1; - EXTEND(sp, n); - for (i = 0; i < n; ++i) { - PUSHs(AvARRAY(av)[i]); - } - } - } - -#endif - -# -- end of DBD::SQLite2::db - -# ------------------------------------------------------------ -# statement interface -# ------------------------------------------------------------ -MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2::st - - -void -_prepare(sth, statement, attribs=Nullsv) - SV * sth - SV * statement - SV * attribs - CODE: - { - D_imp_sth(sth); - DBD_ATTRIBS_CHECK("_prepare", sth, attribs); -#ifdef dbd_st_prepare_sv - ST(0) = dbd_st_prepare_sv(sth, imp_sth, statement, attribs) ? &PL_sv_yes : &PL_sv_no; -#else - ST(0) = dbd_st_prepare(sth, imp_sth, SvPV_nolen(statement), attribs) ? &PL_sv_yes : &PL_sv_no; -#endif - } - - -#ifdef dbd_st_rows - -void -rows(sth) - SV * sth - CODE: - D_imp_sth(sth); - XST_mIV(0, dbd_st_rows(sth, imp_sth)); - -#endif /* dbd_st_rows */ - - -#ifdef dbd_st_bind_col - -void -bind_col(sth, col, ref, attribs=Nullsv) - SV * sth - SV * col - SV * ref - SV * attribs - CODE: - { - IV sql_type = 0; - D_imp_sth(sth); - if (SvGMAGICAL(ref)) - mg_get(ref); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_col", sth, attribs); - /* XXX we should perhaps complain if TYPE is not SvNIOK */ - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - switch(dbd_st_bind_col(sth, imp_sth, col, ref, sql_type, attribs)) { - case 2: ST(0) = &PL_sv_yes; /* job done completely */ - break; - case 1: /* fallback to DBI default */ - ST(0) = (DBIc_DBISTATE(imp_sth)->bind_col(sth, col, ref, attribs)) - ? &PL_sv_yes : &PL_sv_no; - break; - default: ST(0) = &PL_sv_no; /* dbd_st_bind_col has called set_err */ - break; - } - } - -#endif /* dbd_st_bind_col */ - -void -bind_param(sth, param, value, attribs=Nullsv) - SV * sth - SV * param - SV * value - SV * attribs - CODE: - { - IV sql_type = 0; - D_imp_sth(sth); - if (SvGMAGICAL(value)) - mg_get(value); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_param", sth, attribs); - /* XXX we should perhaps complain if TYPE is not SvNIOK */ - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - ST(0) = dbd_bind_ph(sth, imp_sth, param, value, sql_type, attribs, FALSE, 0) - ? &PL_sv_yes : &PL_sv_no; - } - - -void -bind_param_inout(sth, param, value_ref, maxlen, attribs=Nullsv) - SV * sth - SV * param - SV * value_ref - IV maxlen - SV * attribs - CODE: - { - IV sql_type = 0; - D_imp_sth(sth); - SV *value; - if (!SvROK(value_ref) || SvTYPE(SvRV(value_ref)) > SVt_PVMG) - croak("bind_param_inout needs a reference to a scalar value"); - value = SvRV(value_ref); - if (SvREADONLY(value)) - croak("Modification of a read-only value attempted"); - if (SvGMAGICAL(value)) - mg_get(value); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_param", sth, attribs); - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - ST(0) = dbd_bind_ph(sth, imp_sth, param, value, sql_type, attribs, TRUE, maxlen) - ? &PL_sv_yes : &PL_sv_no; - } - - -void -execute(sth, ...) - SV * sth - CODE: - D_imp_sth(sth); - IV retval; - if (items > 1) { /* need to bind params */ - if (!dbdxst_bind_params(sth, imp_sth, items, ax) ) { - XSRETURN_UNDEF; - } - } - /* XXX this code is duplicated in selectrow_arrayref above */ - DBIc_ROW_COUNT(imp_sth) = 0; - retval = dbd_st_execute(sth, imp_sth); /* might be dbd_st_execute_iv via macro */ - /* remember that dbd_st_execute must return <= -2 for error */ - if (retval == 0) /* ok with no rows affected */ - XST_mPV(0, "0E0"); /* (true but zero) */ - else if (retval < -1) /* -1 == unknown number of rows */ - XST_mUNDEF(0); /* <= -2 means error */ - else - XST_mIV(0, retval); /* typically 1, rowcount or -1 */ - - -#ifdef dbd_st_execute_for_fetch - -void -execute_for_fetch(sth, fetch_tuple_sub, tuple_status = Nullsv) - SV * sth - SV * fetch_tuple_sub - SV * tuple_status - CODE: - { - D_imp_sth(sth); - ST(0) = dbd_st_execute_for_fetch(sth, imp_sth, fetch_tuple_sub, tuple_status); - } - -#endif - - - -void -fetchrow_arrayref(sth) - SV * sth - ALIAS: - fetch = 1 - CODE: - D_imp_sth(sth); - AV *av; - PERL_UNUSED_VAR(ix); - av = dbd_st_fetch(sth, imp_sth); - ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef; - - -void -fetchrow_array(sth) - SV * sth - ALIAS: - fetchrow = 1 - PPCODE: - D_imp_sth(sth); - AV *av; - av = dbd_st_fetch(sth, imp_sth); - if (av) { - int i; - int num_fields = AvFILL(av)+1; - EXTEND(sp, num_fields); - for(i=0; i < num_fields; ++i) { - PUSHs(AvARRAY(av)[i]); - } - PERL_UNUSED_VAR(ix); - } - - -void -fetchall_arrayref(sth, slice=&PL_sv_undef, batch_row_count=&PL_sv_undef) - SV * sth - SV * slice - SV * batch_row_count - CODE: - if (SvOK(slice)) { /* fallback to perl implementation */ - SV *tmp = dbixst_bounce_method("DBD::SQLite2::st::SUPER::fetchall_arrayref", 3); - SPAGAIN; - ST(0) = tmp; - } - else { - SV *tmp = dbdxst_fetchall_arrayref(sth, slice, batch_row_count); - SPAGAIN; - ST(0) = tmp; - } - - -void -finish(sth) - SV * sth - CODE: - D_imp_sth(sth); - D_imp_dbh_from_sth; - if (!DBIc_ACTIVE(imp_sth)) { - /* No active statement to finish */ - XSRETURN_YES; - } - if (!DBIc_ACTIVE(imp_dbh)) { - /* Either an explicit disconnect() or global destruction */ - /* has disconnected us from the database. Finish is meaningless */ - DBIc_ACTIVE_off(imp_sth); - XSRETURN_YES; - } -#ifdef dbd_st_finish3 - ST(0) = dbd_st_finish3(sth, imp_sth, 0) ? &PL_sv_yes : &PL_sv_no; -#else - ST(0) = dbd_st_finish(sth, imp_sth) ? &PL_sv_yes : &PL_sv_no; -#endif - - -void -blob_read(sth, field, offset, len, destrv=Nullsv, destoffset=0) - SV * sth - int field - long offset - long len - SV * destrv - long destoffset - CODE: - { - D_imp_sth(sth); - if (!destrv) - destrv = sv_2mortal(newRV(sv_2mortal(newSV(0)))); - if (dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset)) - ST(0) = SvRV(destrv); - else ST(0) = &PL_sv_undef; - } - - -void -STORE(sth, keysv, valuesv) - SV * sth - SV * keysv - SV * valuesv - CODE: - D_imp_sth(sth); - if (SvGMAGICAL(valuesv)) - mg_get(valuesv); - ST(0) = &PL_sv_yes; - if (!dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv)) - if (!DBIc_DBISTATE(imp_sth)->set_attr(sth, keysv, valuesv)) - ST(0) = &PL_sv_no; - - -# FETCH renamed and ALIAS'd to avoid case clash on VMS :-( -void -FETCH_attrib(sth, keysv) - SV * sth - SV * keysv - ALIAS: - FETCH = 1 - CODE: - D_imp_sth(sth); - SV *valuesv; - PERL_UNUSED_VAR(ix); - valuesv = dbd_st_FETCH_attrib(sth, imp_sth, keysv); - if (!valuesv) - valuesv = DBIc_DBISTATE(imp_sth)->get_attr(sth, keysv); - ST(0) = valuesv; /* dbd_st_FETCH_attrib did sv_2mortal */ - - -void -DESTROY(sth) - SV * sth - PPCODE: - /* keep in sync with default DESTROY in DBI.xs */ - D_imp_sth(sth); - ST(0) = &PL_sv_yes; - if (!DBIc_IMPSET(imp_sth)) { /* was never fully set up */ - STRLEN lna; - if (DBIc_WARN(imp_sth) && !PL_dirty && DBIc_DBISTATE(imp_sth)->debug >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_sth), - " DESTROY for %s ignored - handle not initialised\n", - SvPV(sth,lna)); - } - else { - if (DBIc_IADESTROY(imp_sth)) { /* wants ineffective destroy */ - DBIc_ACTIVE_off(imp_sth); - if (DBIc_DBISTATE(imp_sth)->debug) - PerlIO_printf(DBIc_LOGPIO(imp_sth), " DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(sth)); - } - if (DBIc_ACTIVE(imp_sth)) { - D_imp_dbh_from_sth; - if (!PL_dirty && DBIc_ACTIVE(imp_dbh)) { -#ifdef dbd_st_finish3 - dbd_st_finish3(sth, imp_sth, 1); -#else - dbd_st_finish(sth, imp_sth); -#endif - } - else { - DBIc_ACTIVE_off(imp_sth); - } - } - dbd_st_destroy(sth, imp_sth); - } - -# end of SQLite2.xst -# vim:ts=8:sw=4:et diff --git a/dbLifeLog/DBD-SQLite2-0.33/SQLiteXS.h b/dbLifeLog/DBD-SQLite2-0.33/SQLiteXS.h deleted file mode 100644 index a4d7b8e..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/SQLiteXS.h +++ /dev/null @@ -1,15 +0,0 @@ - -#ifndef _SQLITEXS_H -#define _SQLITEXS_H 1 - -/************************************************************************ - DBI Specific Stuff - Added by Matt Sergeant - ************************************************************************/ -#define NEED_DBIXS_VERSION 93 -#include -#include "dbdimp.h" -#include - -#include "sqlite.h" - -#endif diff --git a/dbLifeLog/DBD-SQLite2-0.33/attach.c b/dbLifeLog/DBD-SQLite2-0.33/attach.c deleted file mode 100644 index 16263de..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/attach.c +++ /dev/null @@ -1,311 +0,0 @@ -/* -** 2003 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the ATTACH and DETACH commands. -** -** $Id: attach.c,v 1.1.1.1 2004/08/08 15:03:56 matt Exp $ -*/ -#include "sqliteInt.h" - -/* -** This routine is called by the parser to process an ATTACH statement: -** -** ATTACH DATABASE filename AS dbname -** -** The pFilename and pDbname arguments are the tokens that define the -** filename and dbname in the ATTACH statement. -*/ -void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){ - Db *aNew; - int rc, i; - char *zFile, *zName; - sqlite *db; - Vdbe *v; - - v = sqliteGetVdbe(pParse); - sqliteVdbeAddOp(v, OP_Halt, 0, 0); - if( pParse->explain ) return; - db = pParse->db; - if( db->file_format<4 ){ - sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an " - "older format master database", 0); - pParse->rc = SQLITE_ERROR; - return; - } - if( db->nDb>=MAX_ATTACHED+2 ){ - sqliteErrorMsg(pParse, "too many attached databases - max %d", - MAX_ATTACHED); - pParse->rc = SQLITE_ERROR; - return; - } - - zFile = 0; - sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0); - if( zFile==0 ) return; - sqliteDequote(zFile); -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ - sqliteFree(zFile); - return; - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ - - zName = 0; - sqliteSetNString(&zName, pDbname->z, pDbname->n, 0); - if( zName==0 ) return; - sqliteDequote(zName); - for(i=0; inDb; i++){ - if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){ - sqliteErrorMsg(pParse, "database %z is already in use", zName); - pParse->rc = SQLITE_ERROR; - sqliteFree(zFile); - return; - } - } - - if( db->aDb==db->aDbStatic ){ - aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); - if( aNew==0 ) return; - memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); - }else{ - aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); - if( aNew==0 ) return; - } - db->aDb = aNew; - aNew = &db->aDb[db->nDb++]; - memset(aNew, 0, sizeof(*aNew)); - sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); - sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); - sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); - sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); - aNew->zName = zName; - rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); - if( rc ){ - sqliteErrorMsg(pParse, "unable to open database: %s", zFile); - } -#if SQLITE_HAS_CODEC - { - extern int sqliteCodecAttach(sqlite*, int, void*, int); - char *zKey = 0; - int nKey; - if( pKey && pKey->z && pKey->n ){ - sqliteSetNString(&zKey, pKey->z, pKey->n, 0); - sqliteDequote(zKey); - nKey = strlen(zKey); - }else{ - zKey = 0; - nKey = 0; - } - sqliteCodecAttach(db, db->nDb-1, zKey, nKey); - } -#endif - sqliteFree(zFile); - db->flags &= ~SQLITE_Initialized; - if( pParse->nErr ) return; - if( rc==SQLITE_OK ){ - rc = sqliteInit(pParse->db, &pParse->zErrMsg); - } - if( rc ){ - int i = db->nDb - 1; - assert( i>=2 ); - if( db->aDb[i].pBt ){ - sqliteBtreeClose(db->aDb[i].pBt); - db->aDb[i].pBt = 0; - } - sqliteResetInternalSchema(db, 0); - pParse->nErr++; - pParse->rc = SQLITE_ERROR; - } -} - -/* -** This routine is called by the parser to process a DETACH statement: -** -** DETACH DATABASE dbname -** -** The pDbname argument is the name of the database in the DETACH statement. -*/ -void sqliteDetach(Parse *pParse, Token *pDbname){ - int i; - sqlite *db; - Vdbe *v; - Db *pDb; - - v = sqliteGetVdbe(pParse); - sqliteVdbeAddOp(v, OP_Halt, 0, 0); - if( pParse->explain ) return; - db = pParse->db; - for(i=0; inDb; i++){ - pDb = &db->aDb[i]; - if( pDb->pBt==0 || pDb->zName==0 ) continue; - if( strlen(pDb->zName)!=pDbname->n ) continue; - if( sqliteStrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break; - } - if( i>=db->nDb ){ - sqliteErrorMsg(pParse, "no such database: %T", pDbname); - return; - } - if( i<2 ){ - sqliteErrorMsg(pParse, "cannot detach database %T", pDbname); - return; - } -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ - return; - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ - sqliteBtreeClose(pDb->pBt); - pDb->pBt = 0; - sqliteFree(pDb->zName); - sqliteResetInternalSchema(db, i); - if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux); - db->nDb--; - if( inDb ){ - db->aDb[i] = db->aDb[db->nDb]; - memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0])); - sqliteResetInternalSchema(db, i); - } -} - -/* -** Initialize a DbFixer structure. This routine must be called prior -** to passing the structure to one of the sqliteFixAAAA() routines below. -** -** The return value indicates whether or not fixation is required. TRUE -** means we do need to fix the database references, FALSE means we do not. -*/ -int sqliteFixInit( - DbFixer *pFix, /* The fixer to be initialized */ - Parse *pParse, /* Error messages will be written here */ - int iDb, /* This is the database that must must be used */ - const char *zType, /* "view", "trigger", or "index" */ - const Token *pName /* Name of the view, trigger, or index */ -){ - sqlite *db; - - if( iDb<0 || iDb==1 ) return 0; - db = pParse->db; - assert( db->nDb>iDb ); - pFix->pParse = pParse; - pFix->zDb = db->aDb[iDb].zName; - pFix->zType = zType; - pFix->pName = pName; - return 1; -} - -/* -** The following set of routines walk through the parse tree and assign -** a specific database to all table references where the database name -** was left unspecified in the original SQL statement. The pFix structure -** must have been initialized by a prior call to sqliteFixInit(). -** -** These routines are used to make sure that an index, trigger, or -** view in one database does not refer to objects in a different database. -** (Exception: indices, triggers, and views in the TEMP database are -** allowed to refer to anything.) If a reference is explicitly made -** to an object in a different database, an error message is added to -** pParse->zErrMsg and these routines return non-zero. If everything -** checks out, these routines return 0. -*/ -int sqliteFixSrcList( - DbFixer *pFix, /* Context of the fixation */ - SrcList *pList /* The Source list to check and modify */ -){ - int i; - const char *zDb; - - if( pList==0 ) return 0; - zDb = pFix->zDb; - for(i=0; inSrc; i++){ - if( pList->a[i].zDatabase==0 ){ - pList->a[i].zDatabase = sqliteStrDup(zDb); - }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){ - sqliteErrorMsg(pFix->pParse, - "%s %z cannot reference objects in database %s", - pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n), - pList->a[i].zDatabase); - return 1; - } - if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1; - if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1; - } - return 0; -} -int sqliteFixSelect( - DbFixer *pFix, /* Context of the fixation */ - Select *pSelect /* The SELECT statement to be fixed to one database */ -){ - while( pSelect ){ - if( sqliteFixExprList(pFix, pSelect->pEList) ){ - return 1; - } - if( sqliteFixSrcList(pFix, pSelect->pSrc) ){ - return 1; - } - if( sqliteFixExpr(pFix, pSelect->pWhere) ){ - return 1; - } - if( sqliteFixExpr(pFix, pSelect->pHaving) ){ - return 1; - } - pSelect = pSelect->pPrior; - } - return 0; -} -int sqliteFixExpr( - DbFixer *pFix, /* Context of the fixation */ - Expr *pExpr /* The expression to be fixed to one database */ -){ - while( pExpr ){ - if( sqliteFixSelect(pFix, pExpr->pSelect) ){ - return 1; - } - if( sqliteFixExprList(pFix, pExpr->pList) ){ - return 1; - } - if( sqliteFixExpr(pFix, pExpr->pRight) ){ - return 1; - } - pExpr = pExpr->pLeft; - } - return 0; -} -int sqliteFixExprList( - DbFixer *pFix, /* Context of the fixation */ - ExprList *pList /* The expression to be fixed to one database */ -){ - int i; - if( pList==0 ) return 0; - for(i=0; inExpr; i++){ - if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){ - return 1; - } - } - return 0; -} -int sqliteFixTriggerStep( - DbFixer *pFix, /* Context of the fixation */ - TriggerStep *pStep /* The trigger step be fixed to one database */ -){ - while( pStep ){ - if( sqliteFixSelect(pFix, pStep->pSelect) ){ - return 1; - } - if( sqliteFixExpr(pFix, pStep->pWhere) ){ - return 1; - } - if( sqliteFixExprList(pFix, pStep->pExprList) ){ - return 1; - } - pStep = pStep->pNext; - } - return 0; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/attach.o b/dbLifeLog/DBD-SQLite2-0.33/attach.o deleted file mode 100644 index 27326ed5226f1a6ef75e98bdfb546cf26c62349e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7536 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 = xAuth; - db->pAuthArg = pArg; - return SQLITE_OK; -} - -/* -** Write an error message into pParse->zErrMsg that explains that the -** user-supplied authorization function returned an illegal value. -*/ -static void sqliteAuthBadReturnCode(Parse *pParse, int rc){ - sqliteErrorMsg(pParse, "illegal return value (%d) from the " - "authorization function - should be SQLITE_OK, SQLITE_IGNORE, " - "or SQLITE_DENY", rc); - pParse->rc = SQLITE_MISUSE; -} - -/* -** The pExpr should be a TK_COLUMN expression. The table referred to -** is in pTabList or else it is the NEW or OLD table of a trigger. -** Check to see if it is OK to read this particular column. -** -** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN -** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, -** then generate an error. -*/ -void sqliteAuthRead( - Parse *pParse, /* The parser context */ - Expr *pExpr, /* The expression to check authorization on */ - SrcList *pTabList /* All table that pExpr might refer to */ -){ - sqlite *db = pParse->db; - int rc; - Table *pTab; /* The table being read */ - const char *zCol; /* Name of the column of the table */ - int iSrc; /* Index in pTabList->a[] of table being read */ - const char *zDBase; /* Name of database being accessed */ - - if( db->xAuth==0 ) return; - assert( pExpr->op==TK_COLUMN ); - for(iSrc=0; iSrcnSrc; iSrc++){ - if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; - } - if( iSrc>=0 && iSrcnSrc ){ - pTab = pTabList->a[iSrc].pTab; - }else{ - /* This must be an attempt to read the NEW or OLD pseudo-tables - ** of a trigger. - */ - TriggerStack *pStack; /* The stack of current triggers */ - pStack = pParse->trigStack; - assert( pStack!=0 ); - assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx ); - pTab = pStack->pTab; - } - if( pTab==0 ) return; - if( pExpr->iColumn>=0 ){ - assert( pExpr->iColumnnCol ); - zCol = pTab->aCol[pExpr->iColumn].zName; - }else if( pTab->iPKey>=0 ){ - assert( pTab->iPKeynCol ); - zCol = pTab->aCol[pTab->iPKey].zName; - }else{ - zCol = "ROWID"; - } - assert( pExpr->iDbnDb ); - zDBase = db->aDb[pExpr->iDb].zName; - rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, - pParse->zAuthContext); - if( rc==SQLITE_IGNORE ){ - pExpr->op = TK_NULL; - }else if( rc==SQLITE_DENY ){ - if( db->nDb>2 || pExpr->iDb!=0 ){ - sqliteErrorMsg(pParse, "access to %s.%s.%s is prohibited", - zDBase, pTab->zName, zCol); - }else{ - sqliteErrorMsg(pParse, "access to %s.%s is prohibited", pTab->zName,zCol); - } - pParse->rc = SQLITE_AUTH; - }else if( rc!=SQLITE_OK ){ - sqliteAuthBadReturnCode(pParse, rc); - } -} - -/* -** Do an authorization check using the code and arguments given. Return -** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY -** is returned, then the error count and error message in pParse are -** modified appropriately. -*/ -int sqliteAuthCheck( - Parse *pParse, - int code, - const char *zArg1, - const char *zArg2, - const char *zArg3 -){ - sqlite *db = pParse->db; - int rc; - - if( db->init.busy || db->xAuth==0 ){ - return SQLITE_OK; - } - rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext); - if( rc==SQLITE_DENY ){ - sqliteErrorMsg(pParse, "not authorized"); - pParse->rc = SQLITE_AUTH; - }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ - rc = SQLITE_DENY; - sqliteAuthBadReturnCode(pParse, rc); - } - return rc; -} - -/* -** Push an authorization context. After this routine is called, the -** zArg3 argument to authorization callbacks will be zContext until -** popped. Or if pParse==0, this routine is a no-op. -*/ -void sqliteAuthContextPush( - Parse *pParse, - AuthContext *pContext, - const char *zContext -){ - pContext->pParse = pParse; - if( pParse ){ - pContext->zAuthContext = pParse->zAuthContext; - pParse->zAuthContext = zContext; - } -} - -/* -** Pop an authorization context that was previously pushed -** by sqliteAuthContextPush -*/ -void sqliteAuthContextPop(AuthContext *pContext){ - if( pContext->pParse ){ - pContext->pParse->zAuthContext = pContext->zAuthContext; - pContext->pParse = 0; - } -} - -#endif /* SQLITE_OMIT_AUTHORIZATION */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/auth.o b/dbLifeLog/DBD-SQLite2-0.33/auth.o deleted file mode 100644 index 0115904774de042c08fe719fc53c8c6a3d4abbe0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3472 zcmbtVU2GIp6u!G#+Lhw$@?&U%rXvBfB<*CEmI{*S&i+nuw#EKP3_r_uJMC`R?&8j@ z7BsZUc9F?YE%*R0KAC8Y@zEbJ>OzU-k?`aTkvBm!K{1g;Og(4z-gcZ$jnUKeo^!wZ zopaAU_srd?xSVjiT!e{>JWrNq3?<~oW6O5fG{eM4))7hn-0LQwF8D!(>hr$#7$IYV zuYJa3i3h}&#bI%1cu=bT)R4UvEP0?51gHwrRg)45MF@3{SZm#~nsVPGB2D!H_-kN$)cR+()rX8HHfdbo1jQqr5D*U)+ZtrmtBNP4AOUE3fTnX9|2-(JJL4|5~O{QTV|2(H;C)xirCRIb|toM$4Cq{8*)!HH}VQ&6O&JQGP_> z2VatVhvMn}7dx2Qo9yc!h57?9D3L)#Mo&z1E_9u8% z5zhaPJHoZS?TK*wY*T~_oLwVw!PCtmx4YUB*giUv+2ZId2q=>{_tmtw&&NoasL0va{j&oA4|kPc_s( zj!11HzbrbDJdQ6TAs+a15)VXj5)WD91VfbORq&QoaLc1?VR*<|%dBCVUxY*a$Iayy zf_1ja26M7 z;2lY;ik4n_M#>Zw!FNE(jFNOx?vIFax<8Q^j1Q%U#E2YEQ&PNKE|pX2xWy-$Q?kdb z^HNb$Cbj()HRphqjzjL7={Yfdy!}V;BBOL!@Ky`{0>!aIH(GGj!e3{>tE=$MHy(Jn zFZL4KcVQL&Mp|D~)_k^7+@8-~3!k&ZkFUb#frEm}lw!`i&2bs$>HNA4XZ`Y<4L?eQ zc`fxpXqs&zs3#`0%m@)wt=!N#W|fsfM!*Xs!e~az5Me}Bi3tdmVj+J_DV!iexrA%z z9TK3^tkc~@$d)E1lp+LxpDRU3_6>KcS_XPVFk>sZ^jJAFq0pTFkK(}@k7)nC!+@c@ z$IjcBuK4!00FHMUrt3^yr%ws1ANC6F!(N6qN_>Xm_80Y*ZC^?^V=x|2h~>{d0p7Cn*v82j4m7&-w>{N1RfX=uhQo q>d%xd9rGUSxg+->CIu3pi})7d?~Z+c+{S5tp7#F-ux=Im{(k{Dx-R7a diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/arch/.exists b/dbLifeLog/DBD-SQLite2-0.33/blib/arch/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/arch/auto/DBD/SQLite2/.exists b/dbLifeLog/DBD-SQLite2-0.33/blib/arch/auto/DBD/SQLite2/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/arch/auto/DBD/SQLite2/SQLite2.so b/dbLifeLog/DBD-SQLite2-0.33/blib/arch/auto/DBD/SQLite2/SQLite2.so deleted file mode 100755 index 72e31c307edf2518a0306768622c78131dc60b29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 415248 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

RE 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%0DRU8~h3Ww)Koe4{1 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 diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/bin/.exists b/dbLifeLog/DBD-SQLite2-0.33/blib/bin/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/.exists b/dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/SQLite2.pm b/dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/SQLite2.pm deleted file mode 100644 index 62c4e19..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/SQLite2.pm +++ /dev/null @@ -1,542 +0,0 @@ -# $Id: SQLite2.pm,v 1.2 2004/09/10 15:43:39 matt Exp $ - -package DBD::SQLite2; -use strict; - -use DBI; -use vars qw($err $errstr $state $drh $VERSION @ISA); -$VERSION = '0.33'; - -use DynaLoader(); -@ISA = ('DynaLoader'); - -__PACKAGE__->bootstrap($VERSION); - -$drh = undef; - -sub driver { - return $drh if $drh; - my ($class, $attr) = @_; - - $class .= "::dr"; - - $drh = DBI::_new_drh($class, { - Name => 'SQLite2', - Version => $VERSION, - Attribution => 'DBD::SQLite2 by Matt Sergeant', - }); - - return $drh; -} - -sub CLONE { - undef $drh; -} - -package DBD::SQLite2::dr; - -sub connect { - my ($drh, $dbname, $user, $auth, $attr) = @_; - - my $dbh = DBI::_new_dbh($drh, { - Name => $dbname, - }); - - my $real_dbname = $dbname; - if ($dbname =~ /=/) { - foreach my $attrib (split(/;/, $dbname)) { - my ($k, $v) = split(/=/, $attrib, 2); - if ($k eq 'dbname') { - $real_dbname = $v; - } - else { - # TODO: add to attribs - } - } - } - DBD::SQLite2::db::_login($dbh, $real_dbname, $user, $auth) - or return undef; - - return $dbh; -} - -package DBD::SQLite2::db; - -sub prepare { - my ($dbh, $statement, @attribs) = @_; - - my $sth = DBI::_new_sth($dbh, { - Statement => $statement, - }); - - DBD::SQLite2::st::_prepare($sth, $statement, @attribs) - or return undef; - - return $sth; -} - - -sub table_info { - my ($dbh, $CatVal, $SchVal, $TblVal, $TypVal) = @_; - # SQL/CLI (ISO/IEC JTC 1/SC 32 N 0595), 6.63 Tables - # Based on DBD::Oracle's - # See also http://www.ch-werner.de/sqliteodbc/html/sqliteodbc_8c.html#a117 - - my @Where = (); - my $Sql; - if ( defined($CatVal) && $CatVal eq '%' - && defined($SchVal) && $SchVal eq '' - && defined($TblVal) && $TblVal eq '') { # Rule 19a - $Sql = <<'SQL'; -SELECT NULL TABLE_CAT - , NULL TABLE_SCHEM - , NULL TABLE_NAME - , NULL TABLE_TYPE - , NULL REMARKS -SQL - } - elsif ( defined($SchVal) && $SchVal eq '%' - && defined($CatVal) && $CatVal eq '' - && defined($TblVal) && $TblVal eq '') { # Rule 19b - $Sql = <<'SQL'; -SELECT NULL TABLE_CAT - , NULL TABLE_SCHEM - , NULL TABLE_NAME - , NULL TABLE_TYPE - , NULL REMARKS -SQL - } - elsif ( defined($TypVal) && $TypVal eq '%' - && defined($CatVal) && $CatVal eq '' - && defined($SchVal) && $SchVal eq '' - && defined($TblVal) && $TblVal eq '') { # Rule 19c - $Sql = <<'SQL'; -SELECT NULL TABLE_CAT - , NULL TABLE_SCHEM - , NULL TABLE_NAME - , t.tt TABLE_TYPE - , NULL REMARKS -FROM ( - SELECT 'TABLE' tt UNION - SELECT 'VIEW' tt UNION - SELECT 'LOCAL TEMPORARY' tt -) t -ORDER BY TABLE_TYPE -SQL - } - else { - $Sql = <<'SQL'; -SELECT * -FROM -( -SELECT NULL TABLE_CAT - , NULL TABLE_SCHEM - , tbl_name TABLE_NAME - , TABLE_TYPE - , NULL REMARKS - , sql sqlite_sql -FROM ( - SELECT tbl_name, upper(type) TABLE_TYPE, sql - FROM sqlite_master - WHERE type IN ( 'table','view') -UNION ALL - SELECT tbl_name, 'LOCAL TEMPORARY' TABLE_TYPE, sql - FROM sqlite_temp_master - WHERE type IN ( 'table','view') -UNION ALL - SELECT 'sqlite_master' tbl_name, 'SYSTEM TABLE' TABLE_TYPE, NULL sql -UNION ALL - SELECT 'sqlite_temp_master' tbl_name, 'SYSTEM TABLE' TABLE_TYPE, NULL sql -) -) -SQL - if ( defined $TblVal ) { - push @Where, "TABLE_NAME LIKE '$TblVal'"; - } - if ( defined $TypVal ) { - my $table_type_list; - $TypVal =~ s/^\s+//; - $TypVal =~ s/\s+$//; - my @ttype_list = split (/\s*,\s*/, $TypVal); - foreach my $table_type (@ttype_list) { - if ($table_type !~ /^'.*'$/) { - $table_type = "'" . $table_type . "'"; - } - $table_type_list = join(", ", @ttype_list); - } - push @Where, "TABLE_TYPE IN (\U$table_type_list)" - if $table_type_list; - } - $Sql .= ' WHERE ' . join("\n AND ", @Where ) . "\n" if @Where; - $Sql .= " ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME\n"; - } - my $sth = $dbh->prepare($Sql) or return undef; - $sth->execute or return undef; - $sth; -} - - -sub primary_key_info { - my($dbh, $catalog, $schema, $table) = @_; - - my @pk_info; - - my $sth_tables = $dbh->table_info($catalog, $schema, $table, ''); - - # this is a hack but much simpler than using pragma index_list etc - # also the pragma doesn't list 'INTEGER PRIMARK KEY' autoinc PKs! - while ( my $row = $sth_tables->fetchrow_hashref ) { - my $sql = $row->{sqlite_sql} or next; - next unless $sql =~ /(.*?)\s*PRIMARY\s+KEY\s*(?:\(\s*(.*?)\s*\))?/si; - my @pk = split /\s*,\s*/, $2 || ''; - unless (@pk) { - my $prefix = $1; - $prefix =~ s/.*create\s+table\s+.*?\(//i; - $prefix = (split /\s*,\s*/, $prefix)[-1]; - @pk = (split /\s+/, $prefix)[0]; # take first word as name - } - #warn "GOT PK $row->{TABLE_NAME} (@pk)\n"; - my $key_seq = 0; - for my $pk_field (@pk) { - push @pk_info, { - TABLE_SCHEM => $row->{TABLE_SCHEM}, - TABLE_NAME => $row->{TABLE_NAME}, - COLUMN_NAME => $pk_field, - KEY_SEQ => ++$key_seq, - PK_NAME => 'PRIMARY KEY', - }; - } - } - - my $sponge = DBI->connect("DBI:Sponge:", '','') - or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr"); - my @names = qw(TABLE_CAT TABLE_SCHEM TABLE_NAME COLUMN_NAME KEY_SEQ PK_NAME); - my $sth = $sponge->prepare("column_info $table", { - rows => [ map { [ @{$_}{@names} ] } @pk_info ], - NUM_OF_FIELDS => scalar @names, - NAME => \@names, - }) or return $dbh->DBI::set_err($sponge->err(), $sponge->errstr()); - return $sth; -} - -sub type_info_all { - my ($dbh) = @_; -return; # XXX code just copied from DBD::Oracle, not yet thought about - my $names = { - TYPE_NAME => 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - FIXED_PREC_SCALE =>10, - AUTO_UNIQUE_VALUE =>11, - LOCAL_TYPE_NAME =>12, - MINIMUM_SCALE =>13, - MAXIMUM_SCALE =>14, - SQL_DATA_TYPE =>15, - SQL_DATETIME_SUB=>16, - NUM_PREC_RADIX =>17, - }; - my $ti = [ - $names, - [ 'CHAR', 1, 255, '\'', '\'', 'max length', 1, 1, 3, - undef, '0', '0', undef, undef, undef, 1, undef, undef - ], - [ 'NUMBER', 3, 38, undef, undef, 'precision,scale', 1, '0', 3, - '0', '0', '0', undef, '0', 38, 3, undef, 10 - ], - [ 'DOUBLE', 8, 15, undef, undef, undef, 1, '0', 3, - '0', '0', '0', undef, undef, undef, 8, undef, 10 - ], - [ 'DATE', 9, 19, '\'', '\'', undef, 1, '0', 3, - undef, '0', '0', undef, '0', '0', 11, undef, undef - ], - [ 'VARCHAR', 12, 1024*1024, '\'', '\'', 'max length', 1, 1, 3, - undef, '0', '0', undef, undef, undef, 12, undef, undef - ] - ]; - return $ti; -} - - -1; -__END__ - -=head1 NAME - -DBD::SQLite2 - Self Contained RDBMS in a DBI Driver (sqlite 2.x) - -=head1 SYNOPSIS - - use DBI; - my $dbh = DBI->connect("dbi:SQLite2:dbname=dbfile","",""); - -=head1 DESCRIPTION - -SQLite is a public domain RDBMS database engine that you can find -at http://www.hwaci.com/sw/sqlite/. - -Rather than ask you to install SQLite first, because SQLite is public -domain, DBD::SQLite2 includes the entire thing in the distribution. So -in order to get a fast transaction capable RDBMS working for your -perl project you simply have to install this module, and B -else. - -SQLite supports the following features: - -=over 4 - -=item Implements a large subset of SQL92 - -See http://www.hwaci.com/sw/sqlite/lang.html for details. - -=item A complete DB in a single disk file - -Everything for your database is stored in a single disk file, making it -easier to move things around than with DBD::CSV. - -=item Atomic commit and rollback - -Yes, DBD::SQLite2 is small and light, but it supports full transactions! - -=item Extensible - -User-defined aggregate or regular functions can be registered with the -SQL parser. - -=back - -There's lots more to it, so please refer to the docs on the SQLite web -page, listed above, for SQL details. Also refer to L for details -on how to use DBI itself. - -=head1 CONFORMANCE WITH DBI SPECIFICATION - -The API works like every DBI module does. Please see L for more -details about core features. - -Currently many statement attributes are not implemented or are -limited by the typeless nature of the SQLite database. - -=head1 DRIVER PRIVATE ATTRIBUTES - -=head2 Database Handle Attributes - -=over 4 - -=item sqlite_version - -Returns the version of the SQLite library which DBD::SQLite2 is using, e.g., "2.8.0". - -=item sqlite_encoding - -Returns either "UTF-8" or "iso8859" to indicate how the SQLite library was compiled. - -=item sqlite_handle_binary_nulls - -Set this attribute to 1 to transparently handle binary nulls in quoted -and returned data. - -B This will cause all backslash characters (C<\>) to be doubled -up in all columns regardless of whether or not they contain binary -data or not. This may break your database if you use it from another -application. This does not use the built in sqlite_encode_binary -and sqlite_decode_binary functions, which may be considered a bug. - -=back - -=head1 DRIVER PRIVATE METHODS - -=head2 $dbh->func('last_insert_rowid') - -This method returns the last inserted rowid. If you specify an INTEGER PRIMARY -KEY as the first column in your table, that is the column that is returned. -Otherwise, it is the hidden ROWID column. See the sqlite docs for details. - -=head2 $dbh->func( $name, $argc, $func_ref, "create_function" ) - -This method will register a new function which will be useable in SQL -query. The method's parameters are: - -=over - -=item $name - -The name of the function. This is the name of the function as it will -be used from SQL. - -=item $argc - -The number of arguments taken by the function. If this number is -1, -the function can take any number of arguments. - -=item $func_ref - -This should be a reference to the function's implementation. - -=back - -For example, here is how to define a now() function which returns the -current number of seconds since the epoch: - - $dbh->func( 'now', 0, sub { return time }, 'create_function' ); - -After this, it could be use from SQL as: - - INSERT INTO mytable ( now() ); - -=head2 $dbh->func( $name, $argc, $pkg, 'create_aggregate' ) - -This method will register a new aggregate function which can then used -from SQL. The method's parameters are: - -=over - -=item $name - -The name of the aggregate function, this is the name under which the -function will be available from SQL. - -=item $argc - -This is an integer which tells the SQL parser how many arguments the -function takes. If that number is -1, the function can take any number -of arguments. - -=item $pkg - -This is the package which implements the aggregator interface. - -=back - -The aggregator interface consists of defining three methods: - -=over - -=item new() - -This method will be called once to create an object which should -be used to aggregate the rows in a particular group. The step() and -finalize() methods will be called upon the reference return by -the method. - -=item step(@_) - -This method will be called once for each rows in the aggregate. - -=item finalize() - -This method will be called once all rows in the aggregate were -processed and it should return the aggregate function's result. When -there is no rows in the aggregate, finalize() will be called right -after new(). - -=back - -Here is a simple aggregate function which returns the variance -(example adapted from pysqlite): - - package variance; - - sub new { bless [], shift; } - - sub step { - my ( $self, $value ) = @_; - - push @$self, $value; - } - - sub finalize { - my $self = $_[0]; - - my $n = @$self; - - # Variance is NULL unless there is more than one row - return undef unless $n || $n == 1; - - my $mu = 0; - foreach my $v ( @$self ) { - $mu += $v; - } - $mu /= $n; - - my $sigma = 0; - foreach my $v ( @$self ) { - $sigma += ($x - $mu)**2; - } - $sigma = $sigma / ($n - 1); - - return $sigma; - } - - $dbh->func( "variance", 1, 'variance', "create_aggregate" ); - -The aggregate function can then be used as: - - SELECT group_name, variance(score) FROM results - GROUP BY group_name; - -=head1 NOTES - -To access the database from the command line, try using dbish which comes with -the DBI module. Just type: - - dbish dbi:SQLite:foo.db - -On the command line to access the file F. - -Alternatively you can install SQLite from the link above without conflicting -with DBD::SQLite2 and use the supplied C command line tool. - -=head1 PERFORMANCE - -SQLite is fast, very fast. I recently processed my 72MB log file with it, -inserting the data (400,000+ rows) by using transactions and only committing -every 1000 rows (otherwise the insertion is quite slow), and then performing -queries on the data. - -Queries like count(*) and avg(bytes) took fractions of a second to return, -but what surprised me most of all was: - - SELECT url, count(*) as count FROM access_log - GROUP BY url - ORDER BY count desc - LIMIT 20 - -To discover the top 20 hit URLs on the site (http://axkit.org), and it -returned within 2 seconds. I'm seriously considering switching my log -analysis code to use this little speed demon! - -Oh yeah, and that was with no indexes on the table, on a 400MHz PIII. - -For best performance be sure to tune your hdparm settings if you are -using linux. Also you might want to set: - - PRAGMA default_synchronous = OFF - -Which will prevent sqlite from doing fsync's when writing (which -slows down non-transactional writes significantly) at the expense of some -peace of mind. Also try playing with the cache_size pragma. - -=head1 BUGS - -Likely to be many, please use http://rt.cpan.org/ for reporting bugs. - -=head1 AUTHOR - -Matt Sergeant, matt@sergeant.org - -Perl extension functions contributed by Francis J. Lacoste - and Wolfgang Sourdeau - - -=head1 SEE ALSO - -L. - -=cut diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/getsqlite.pl b/dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/getsqlite.pl deleted file mode 100644 index da13684..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/blib/lib/DBD/getsqlite.pl +++ /dev/null @@ -1,52 +0,0 @@ -use strict; -use LWP::Simple qw(getstore); -use Fatal qw(chdir); -use ExtUtils::Command; - -my $version = shift || die "Usage: getsqlite.pl \n"; - -print("downloading http://www.sqlite.org/sqlite-$version.tar.gz\n"); -if (getstore( - "http://www.sqlite.org/sqlite-$version.tar.gz", - "sqlite.tar.gz") != 200) { - die "Failed to download"; -} -print("done\n"); - -rm_rf('sqlite'); -xsystem("tar zxvf sqlite.tar.gz"); -chdir("sqlite"); -xsystem("sh configure --enable-utf8"); -xsystem("make parse.c sqlite.h opcodes.h opcodes.c"); - -my %skip = map { $_ => 1 } map { chomp; $_ } ; -warn("Skip: $_\n") for keys %skip; - -foreach (<*.[ch]>, `find src -name \\*.[ch]`) { - chomp; - next if $skip{$_}; - xsystem("cp $_ ../"); -} - -exit(0); - -sub xsystem { - local $, = ", "; - print("@_\n"); - my $ret = system(@_); - if ($ret != 0) { - die "system(@_) failed: $?"; - } -} - -__DATA__ -lempar.c -src/threadtest.c -src/test1.c -src/test2.c -src/test3.c -src/tclsqlite.c -src/shell.c -src/lemon.c -src/md5.c - diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/lib/auto/DBD/SQLite2/.exists b/dbLifeLog/DBD-SQLite2-0.33/blib/lib/auto/DBD/SQLite2/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/man1/.exists b/dbLifeLog/DBD-SQLite2-0.33/blib/man1/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/man3/.exists b/dbLifeLog/DBD-SQLite2-0.33/blib/man3/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/man3/DBD::SQLite2.3pm b/dbLifeLog/DBD-SQLite2-0.33/blib/man3/DBD::SQLite2.3pm deleted file mode 100644 index 88fa4c6..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/blib/man3/DBD::SQLite2.3pm +++ /dev/null @@ -1,326 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::SQLite2 3pm" -.TH DBD::SQLite2 3pm "2004-09-10" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::SQLite2 \- Self Contained RDBMS in a DBI Driver (sqlite 2.x) -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 2 -\& use DBI; -\& my $dbh = DBI\->connect("dbi:SQLite2:dbname=dbfile","",""); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -SQLite is a public domain \s-1RDBMS\s0 database engine that you can find -at http://www.hwaci.com/sw/sqlite/. -.PP -Rather than ask you to install SQLite first, because SQLite is public -domain, DBD::SQLite2 includes the entire thing in the distribution. So -in order to get a fast transaction capable \s-1RDBMS\s0 working for your -perl project you simply have to install this module, and \fBnothing\fR -else. -.PP -SQLite supports the following features: -.IP "Implements a large subset of \s-1SQL92\s0" 4 -.IX Item "Implements a large subset of SQL92" -See http://www.hwaci.com/sw/sqlite/lang.html for details. -.IP "A complete \s-1DB\s0 in a single disk file" 4 -.IX Item "A complete DB in a single disk file" -Everything for your database is stored in a single disk file, making it -easier to move things around than with \s-1DBD::CSV.\s0 -.IP "Atomic commit and rollback" 4 -.IX Item "Atomic commit and rollback" -Yes, DBD::SQLite2 is small and light, but it supports full transactions! -.IP "Extensible" 4 -.IX Item "Extensible" -User-defined aggregate or regular functions can be registered with the -\&\s-1SQL\s0 parser. -.PP -There's lots more to it, so please refer to the docs on the SQLite web -page, listed above, for \s-1SQL\s0 details. Also refer to \s-1DBI\s0 for details -on how to use \s-1DBI\s0 itself. -.SH "CONFORMANCE WITH DBI SPECIFICATION" -.IX Header "CONFORMANCE WITH DBI SPECIFICATION" -The \s-1API\s0 works like every \s-1DBI\s0 module does. Please see \s-1DBI\s0 for more -details about core features. -.PP -Currently many statement attributes are not implemented or are -limited by the typeless nature of the SQLite database. -.SH "DRIVER PRIVATE ATTRIBUTES" -.IX Header "DRIVER PRIVATE ATTRIBUTES" -.SS "Database Handle Attributes" -.IX Subsection "Database Handle Attributes" -.IP "sqlite_version" 4 -.IX Item "sqlite_version" -Returns the version of the SQLite library which DBD::SQLite2 is using, e.g., \*(L"2.8.0\*(R". -.IP "sqlite_encoding" 4 -.IX Item "sqlite_encoding" -Returns either \*(L"\s-1UTF\-8\*(R"\s0 or \*(L"iso8859\*(R" to indicate how the SQLite library was compiled. -.IP "sqlite_handle_binary_nulls" 4 -.IX Item "sqlite_handle_binary_nulls" -Set this attribute to 1 to transparently handle binary nulls in quoted -and returned data. -.Sp -\&\fB\s-1NOTE:\s0\fR This will cause all backslash characters (\f(CW\*(C`\e\*(C'\fR) to be doubled -up in all columns regardless of whether or not they contain binary -data or not. This may break your database if you use it from another -application. This does not use the built in sqlite_encode_binary -and sqlite_decode_binary functions, which may be considered a bug. -.SH "DRIVER PRIVATE METHODS" -.IX Header "DRIVER PRIVATE METHODS" -.ie n .SS "$dbh\->func('last_insert_rowid')" -.el .SS "\f(CW$dbh\fP\->func('last_insert_rowid')" -.IX Subsection "$dbh->func('last_insert_rowid')" -This method returns the last inserted rowid. If you specify an \s-1INTEGER PRIMARY -KEY\s0 as the first column in your table, that is the column that is returned. -Otherwise, it is the hidden \s-1ROWID\s0 column. See the sqlite docs for details. -.ie n .SS "$dbh\->func( $name, $argc, $func_ref, ""create_function"" )" -.el .SS "\f(CW$dbh\fP\->func( \f(CW$name\fP, \f(CW$argc\fP, \f(CW$func_ref\fP, ``create_function'' )" -.IX Subsection "$dbh->func( $name, $argc, $func_ref, create_function )" -This method will register a new function which will be useable in \s-1SQL\s0 -query. The method's parameters are: -.ie n .IP "$name" 4 -.el .IP "\f(CW$name\fR" 4 -.IX Item "$name" -The name of the function. This is the name of the function as it will -be used from \s-1SQL.\s0 -.ie n .IP "$argc" 4 -.el .IP "\f(CW$argc\fR" 4 -.IX Item "$argc" -The number of arguments taken by the function. If this number is \-1, -the function can take any number of arguments. -.ie n .IP "$func_ref" 4 -.el .IP "\f(CW$func_ref\fR" 4 -.IX Item "$func_ref" -This should be a reference to the function's implementation. -.PP -For example, here is how to define a \fInow()\fR function which returns the -current number of seconds since the epoch: -.PP -.Vb 1 -\& $dbh\->func( \*(Aqnow\*(Aq, 0, sub { return time }, \*(Aqcreate_function\*(Aq ); -.Ve -.PP -After this, it could be use from \s-1SQL\s0 as: -.PP -.Vb 1 -\& INSERT INTO mytable ( now() ); -.Ve -.ie n .SS "$dbh\->func( $name, $argc, $pkg, 'create_aggregate' )" -.el .SS "\f(CW$dbh\fP\->func( \f(CW$name\fP, \f(CW$argc\fP, \f(CW$pkg\fP, 'create_aggregate' )" -.IX Subsection "$dbh->func( $name, $argc, $pkg, 'create_aggregate' )" -This method will register a new aggregate function which can then used -from \s-1SQL.\s0 The method's parameters are: -.ie n .IP "$name" 4 -.el .IP "\f(CW$name\fR" 4 -.IX Item "$name" -The name of the aggregate function, this is the name under which the -function will be available from \s-1SQL.\s0 -.ie n .IP "$argc" 4 -.el .IP "\f(CW$argc\fR" 4 -.IX Item "$argc" -This is an integer which tells the \s-1SQL\s0 parser how many arguments the -function takes. If that number is \-1, the function can take any number -of arguments. -.ie n .IP "$pkg" 4 -.el .IP "\f(CW$pkg\fR" 4 -.IX Item "$pkg" -This is the package which implements the aggregator interface. -.PP -The aggregator interface consists of defining three methods: -.IP "\fInew()\fR" 4 -.IX Item "new()" -This method will be called once to create an object which should -be used to aggregate the rows in a particular group. The \fIstep()\fR and -\&\fIfinalize()\fR methods will be called upon the reference return by -the method. -.IP "step(@_)" 4 -.IX Item "step(@_)" -This method will be called once for each rows in the aggregate. -.IP "\fIfinalize()\fR" 4 -.IX Item "finalize()" -This method will be called once all rows in the aggregate were -processed and it should return the aggregate function's result. When -there is no rows in the aggregate, \fIfinalize()\fR will be called right -after \fInew()\fR. -.PP -Here is a simple aggregate function which returns the variance -(example adapted from pysqlite): -.PP -.Vb 1 -\& package variance; -\& -\& sub new { bless [], shift; } -\& -\& sub step { -\& my ( $self, $value ) = @_; -\& -\& push @$self, $value; -\& } -\& -\& sub finalize { -\& my $self = $_[0]; -\& -\& my $n = @$self; -\& -\& # Variance is NULL unless there is more than one row -\& return undef unless $n || $n == 1; -\& -\& my $mu = 0; -\& foreach my $v ( @$self ) { -\& $mu += $v; -\& } -\& $mu /= $n; -\& -\& my $sigma = 0; -\& foreach my $v ( @$self ) { -\& $sigma += ($x \- $mu)**2; -\& } -\& $sigma = $sigma / ($n \- 1); -\& -\& return $sigma; -\& } -\& -\& $dbh\->func( "variance", 1, \*(Aqvariance\*(Aq, "create_aggregate" ); -.Ve -.PP -The aggregate function can then be used as: -.PP -.Vb 2 -\& SELECT group_name, variance(score) FROM results -\& GROUP BY group_name; -.Ve -.SH "NOTES" -.IX Header "NOTES" -To access the database from the command line, try using dbish which comes with -the \s-1DBI\s0 module. Just type: -.PP -.Vb 1 -\& dbish dbi:SQLite:foo.db -.Ve -.PP -On the command line to access the file \fIfoo.db\fR. -.PP -Alternatively you can install SQLite from the link above without conflicting -with DBD::SQLite2 and use the supplied \f(CW\*(C`sqlite\*(C'\fR command line tool. -.SH "PERFORMANCE" -.IX Header "PERFORMANCE" -SQLite is fast, very fast. I recently processed my 72MB log file with it, -inserting the data (400,000+ rows) by using transactions and only committing -every 1000 rows (otherwise the insertion is quite slow), and then performing -queries on the data. -.PP -Queries like count(*) and avg(bytes) took fractions of a second to return, -but what surprised me most of all was: -.PP -.Vb 4 -\& SELECT url, count(*) as count FROM access_log -\& GROUP BY url -\& ORDER BY count desc -\& LIMIT 20 -.Ve -.PP -To discover the top 20 hit URLs on the site (http://axkit.org), and it -returned within 2 seconds. I'm seriously considering switching my log -analysis code to use this little speed demon! -.PP -Oh yeah, and that was with no indexes on the table, on a 400MHz \s-1PIII.\s0 -.PP -For best performance be sure to tune your hdparm settings if you are -using linux. Also you might want to set: -.PP -.Vb 1 -\& PRAGMA default_synchronous = OFF -.Ve -.PP -Which will prevent sqlite from doing fsync's when writing (which -slows down non-transactional writes significantly) at the expense of some -peace of mind. Also try playing with the cache_size pragma. -.SH "BUGS" -.IX Header "BUGS" -Likely to be many, please use http://rt.cpan.org/ for reporting bugs. -.SH "AUTHOR" -.IX Header "AUTHOR" -Matt Sergeant, matt@sergeant.org -.PP -Perl extension functions contributed by Francis J. Lacoste - and Wolfgang Sourdeau - -.SH "SEE ALSO" -.IX Header "SEE ALSO" -\&\s-1DBI\s0. diff --git a/dbLifeLog/DBD-SQLite2-0.33/blib/script/.exists b/dbLifeLog/DBD-SQLite2-0.33/blib/script/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBD-SQLite2-0.33/btree.c b/dbLifeLog/DBD-SQLite2-0.33/btree.c deleted file mode 100644 index ad65216..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/btree.c +++ /dev/null @@ -1,3584 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** $Id: btree.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -** -** This file implements a external (disk-based) database using BTrees. -** For a detailed discussion of BTrees, refer to -** -** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: -** "Sorting And Searching", pages 473-480. Addison-Wesley -** Publishing Company, Reading, Massachusetts. -** -** The basic idea is that each page of the file contains N database -** entries and N+1 pointers to subpages. -** -** ---------------------------------------------------------------- -** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N) | Ptr(N+1) | -** ---------------------------------------------------------------- -** -** All of the keys on the page that Ptr(0) points to have values less -** than Key(0). All of the keys on page Ptr(1) and its subpages have -** values greater than Key(0) and less than Key(1). All of the keys -** on Ptr(N+1) and its subpages have values greater than Key(N). And -** so forth. -** -** Finding a particular key requires reading O(log(M)) pages from the -** disk where M is the number of entries in the tree. -** -** In this implementation, a single file can hold one or more separate -** BTrees. Each BTree is identified by the index of its root page. The -** key and data for any entry are combined to form the "payload". Up to -** MX_LOCAL_PAYLOAD bytes of payload can be carried directly on the -** database page. If the payload is larger than MX_LOCAL_PAYLOAD bytes -** then surplus bytes are stored on overflow pages. The payload for an -** entry and the preceding pointer are combined to form a "Cell". Each -** page has a small header which contains the Ptr(N+1) pointer. -** -** The first page of the file contains a magic string used to verify that -** the file really is a valid BTree database, a pointer to a list of unused -** pages in the file, and some meta information. The root of the first -** BTree begins on page 2 of the file. (Pages are numbered beginning with -** 1, not 0.) Thus a minimum database contains 2 pages. -*/ -#include "sqliteInt.h" -#include "pager.h" -#include "btree.h" -#include - -/* Forward declarations */ -static BtOps sqliteBtreeOps; -static BtCursorOps sqliteBtreeCursorOps; - -/* -** Macros used for byteswapping. B is a pointer to the Btree -** structure. This is needed to access the Btree.needSwab boolean -** in order to tell if byte swapping is needed or not. -** X is an unsigned integer. SWAB16 byte swaps a 16-bit integer. -** SWAB32 byteswaps a 32-bit integer. -*/ -#define SWAB16(B,X) ((B)->needSwab? swab16((u16)X) : ((u16)X)) -#define SWAB32(B,X) ((B)->needSwab? swab32(X) : (X)) -#define SWAB_ADD(B,X,A) \ - if((B)->needSwab){ X=swab32(swab32(X)+A); }else{ X += (A); } - -/* -** The following global variable - available only if SQLITE_TEST is -** defined - is used to determine whether new databases are created in -** native byte order or in non-native byte order. Non-native byte order -** databases are created for testing purposes only. Under normal operation, -** only native byte-order databases should be created, but we should be -** able to read or write existing databases regardless of the byteorder. -*/ -#ifdef SQLITE_TEST -int btree_native_byte_order = 1; -#else -# define btree_native_byte_order 1 -#endif - -/* -** Forward declarations of structures used only in this file. -*/ -typedef struct PageOne PageOne; -typedef struct MemPage MemPage; -typedef struct PageHdr PageHdr; -typedef struct Cell Cell; -typedef struct CellHdr CellHdr; -typedef struct FreeBlk FreeBlk; -typedef struct OverflowPage OverflowPage; -typedef struct FreelistInfo FreelistInfo; - -/* -** All structures on a database page are aligned to 4-byte boundries. -** This routine rounds up a number of bytes to the next multiple of 4. -** -** This might need to change for computer architectures that require -** and 8-byte alignment boundry for structures. -*/ -#define ROUNDUP(X) ((X+3) & ~3) - -/* -** This is a magic string that appears at the beginning of every -** SQLite database in order to identify the file as a real database. -*/ -static const char zMagicHeader[] = - "** This file contains an SQLite 2.1 database **"; -#define MAGIC_SIZE (sizeof(zMagicHeader)) - -/* -** This is a magic integer also used to test the integrity of the database -** file. This integer is used in addition to the string above so that -** if the file is written on a little-endian architecture and read -** on a big-endian architectures (or vice versa) we can detect the -** problem. -** -** The number used was obtained at random and has no special -** significance other than the fact that it represents a different -** integer on little-endian and big-endian machines. -*/ -#define MAGIC 0xdae37528 - -/* -** The first page of the database file contains a magic header string -** to identify the file as an SQLite database file. It also contains -** a pointer to the first free page of the file. Page 2 contains the -** root of the principle BTree. The file might contain other BTrees -** rooted on pages above 2. -** -** The first page also contains SQLITE_N_BTREE_META integers that -** can be used by higher-level routines. -** -** Remember that pages are numbered beginning with 1. (See pager.c -** for additional information.) Page 0 does not exist and a page -** number of 0 is used to mean "no such page". -*/ -struct PageOne { - char zMagic[MAGIC_SIZE]; /* String that identifies the file as a database */ - int iMagic; /* Integer to verify correct byte order */ - Pgno freeList; /* First free page in a list of all free pages */ - int nFree; /* Number of pages on the free list */ - int aMeta[SQLITE_N_BTREE_META-1]; /* User defined integers */ -}; - -/* -** Each database page has a header that is an instance of this -** structure. -** -** PageHdr.firstFree is 0 if there is no free space on this page. -** Otherwise, PageHdr.firstFree is the index in MemPage.u.aDisk[] of a -** FreeBlk structure that describes the first block of free space. -** All free space is defined by a linked list of FreeBlk structures. -** -** Data is stored in a linked list of Cell structures. PageHdr.firstCell -** is the index into MemPage.u.aDisk[] of the first cell on the page. The -** Cells are kept in sorted order. -** -** A Cell contains all information about a database entry and a pointer -** to a child page that contains other entries less than itself. In -** other words, the i-th Cell contains both Ptr(i) and Key(i). The -** right-most pointer of the page is contained in PageHdr.rightChild. -*/ -struct PageHdr { - Pgno rightChild; /* Child page that comes after all cells on this page */ - u16 firstCell; /* Index in MemPage.u.aDisk[] of the first cell */ - u16 firstFree; /* Index in MemPage.u.aDisk[] of the first free block */ -}; - -/* -** Entries on a page of the database are called "Cells". Each Cell -** has a header and data. This structure defines the header. The -** key and data (collectively the "payload") follow this header on -** the database page. -** -** A definition of the complete Cell structure is given below. The -** header for the cell must be defined first in order to do some -** of the sizing #defines that follow. -*/ -struct CellHdr { - Pgno leftChild; /* Child page that comes before this cell */ - u16 nKey; /* Number of bytes in the key */ - u16 iNext; /* Index in MemPage.u.aDisk[] of next cell in sorted order */ - u8 nKeyHi; /* Upper 8 bits of key size for keys larger than 64K bytes */ - u8 nDataHi; /* Upper 8 bits of data size when the size is more than 64K */ - u16 nData; /* Number of bytes of data */ -}; - -/* -** The key and data size are split into a lower 16-bit segment and an -** upper 8-bit segment in order to pack them together into a smaller -** space. The following macros reassembly a key or data size back -** into an integer. -*/ -#define NKEY(b,h) (SWAB16(b,h.nKey) + h.nKeyHi*65536) -#define NDATA(b,h) (SWAB16(b,h.nData) + h.nDataHi*65536) - -/* -** The minimum size of a complete Cell. The Cell must contain a header -** and at least 4 bytes of payload. -*/ -#define MIN_CELL_SIZE (sizeof(CellHdr)+4) - -/* -** The maximum number of database entries that can be held in a single -** page of the database. -*/ -#define MX_CELL ((SQLITE_USABLE_SIZE-sizeof(PageHdr))/MIN_CELL_SIZE) - -/* -** The amount of usable space on a single page of the BTree. This is the -** page size minus the overhead of the page header. -*/ -#define USABLE_SPACE (SQLITE_USABLE_SIZE - sizeof(PageHdr)) - -/* -** The maximum amount of payload (in bytes) that can be stored locally for -** a database entry. If the entry contains more data than this, the -** extra goes onto overflow pages. -** -** This number is chosen so that at least 4 cells will fit on every page. -*/ -#define MX_LOCAL_PAYLOAD ((USABLE_SPACE/4-(sizeof(CellHdr)+sizeof(Pgno)))&~3) - -/* -** Data on a database page is stored as a linked list of Cell structures. -** Both the key and the data are stored in aPayload[]. The key always comes -** first. The aPayload[] field grows as necessary to hold the key and data, -** up to a maximum of MX_LOCAL_PAYLOAD bytes. If the size of the key and -** data combined exceeds MX_LOCAL_PAYLOAD bytes, then Cell.ovfl is the -** page number of the first overflow page. -** -** Though this structure is fixed in size, the Cell on the database -** page varies in size. Every cell has a CellHdr and at least 4 bytes -** of payload space. Additional payload bytes (up to the maximum of -** MX_LOCAL_PAYLOAD) and the Cell.ovfl value are allocated only as -** needed. -*/ -struct Cell { - CellHdr h; /* The cell header */ - char aPayload[MX_LOCAL_PAYLOAD]; /* Key and data */ - Pgno ovfl; /* The first overflow page */ -}; - -/* -** Free space on a page is remembered using a linked list of the FreeBlk -** structures. Space on a database page is allocated in increments of -** at least 4 bytes and is always aligned to a 4-byte boundry. The -** linked list of FreeBlks is always kept in order by address. -*/ -struct FreeBlk { - u16 iSize; /* Number of bytes in this block of free space */ - u16 iNext; /* Index in MemPage.u.aDisk[] of the next free block */ -}; - -/* -** The number of bytes of payload that will fit on a single overflow page. -*/ -#define OVERFLOW_SIZE (SQLITE_USABLE_SIZE-sizeof(Pgno)) - -/* -** When the key and data for a single entry in the BTree will not fit in -** the MX_LOCAL_PAYLOAD bytes of space available on the database page, -** then all extra bytes are written to a linked list of overflow pages. -** Each overflow page is an instance of the following structure. -** -** Unused pages in the database are also represented by instances of -** the OverflowPage structure. The PageOne.freeList field is the -** page number of the first page in a linked list of unused database -** pages. -*/ -struct OverflowPage { - Pgno iNext; - char aPayload[OVERFLOW_SIZE]; -}; - -/* -** The PageOne.freeList field points to a linked list of overflow pages -** hold information about free pages. The aPayload section of each -** overflow page contains an instance of the following structure. The -** aFree[] array holds the page number of nFree unused pages in the disk -** file. -*/ -struct FreelistInfo { - int nFree; - Pgno aFree[(OVERFLOW_SIZE-sizeof(int))/sizeof(Pgno)]; -}; - -/* -** For every page in the database file, an instance of the following structure -** is stored in memory. The u.aDisk[] array contains the raw bits read from -** the disk. The rest is auxiliary information held in memory only. The -** auxiliary info is only valid for regular database pages - it is not -** used for overflow pages and pages on the freelist. -** -** Of particular interest in the auxiliary info is the apCell[] entry. Each -** apCell[] entry is a pointer to a Cell structure in u.aDisk[]. The cells are -** put in this array so that they can be accessed in constant time, rather -** than in linear time which would be needed if we had to walk the linked -** list on every access. -** -** Note that apCell[] contains enough space to hold up to two more Cells -** than can possibly fit on one page. In the steady state, every apCell[] -** points to memory inside u.aDisk[]. But in the middle of an insert -** operation, some apCell[] entries may temporarily point to data space -** outside of u.aDisk[]. This is a transient situation that is quickly -** resolved. But while it is happening, it is possible for a database -** page to hold as many as two more cells than it might otherwise hold. -** The extra two entries in apCell[] are an allowance for this situation. -** -** The pParent field points back to the parent page. This allows us to -** walk up the BTree from any leaf to the root. Care must be taken to -** unref() the parent page pointer when this page is no longer referenced. -** The pageDestructor() routine handles that chore. -*/ -struct MemPage { - union u_page_data { - char aDisk[SQLITE_PAGE_SIZE]; /* Page data stored on disk */ - PageHdr hdr; /* Overlay page header */ - } u; - u8 isInit; /* True if auxiliary data is initialized */ - u8 idxShift; /* True if apCell[] indices have changed */ - u8 isOverfull; /* Some apCell[] points outside u.aDisk[] */ - MemPage *pParent; /* The parent of this page. NULL for root */ - int idxParent; /* Index in pParent->apCell[] of this node */ - int nFree; /* Number of free bytes in u.aDisk[] */ - int nCell; /* Number of entries on this page */ - Cell *apCell[MX_CELL+2]; /* All data entires in sorted order */ -}; - -/* -** The in-memory image of a disk page has the auxiliary information appended -** to the end. EXTRA_SIZE is the number of bytes of space needed to hold -** that extra information. -*/ -#define EXTRA_SIZE (sizeof(MemPage)-sizeof(union u_page_data)) - -/* -** Everything we need to know about an open database -*/ -struct Btree { - BtOps *pOps; /* Function table */ - Pager *pPager; /* The page cache */ - BtCursor *pCursor; /* A list of all open cursors */ - PageOne *page1; /* First page of the database */ - u8 inTrans; /* True if a transaction is in progress */ - u8 inCkpt; /* True if there is a checkpoint on the transaction */ - u8 readOnly; /* True if the underlying file is readonly */ - u8 needSwab; /* Need to byte-swapping */ -}; -typedef Btree Bt; - -/* -** A cursor is a pointer to a particular entry in the BTree. -** The entry is identified by its MemPage and the index in -** MemPage.apCell[] of the entry. -*/ -struct BtCursor { - BtCursorOps *pOps; /* Function table */ - Btree *pBt; /* The Btree to which this cursor belongs */ - BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ - BtCursor *pShared; /* Loop of cursors with the same root page */ - Pgno pgnoRoot; /* The root page of this tree */ - MemPage *pPage; /* Page that contains the entry */ - int idx; /* Index of the entry in pPage->apCell[] */ - u8 wrFlag; /* True if writable */ - u8 eSkip; /* Determines if next step operation is a no-op */ - u8 iMatch; /* compare result from last sqliteBtreeMoveto() */ -}; - -/* -** Legal values for BtCursor.eSkip. -*/ -#define SKIP_NONE 0 /* Always step the cursor */ -#define SKIP_NEXT 1 /* The next sqliteBtreeNext() is a no-op */ -#define SKIP_PREV 2 /* The next sqliteBtreePrevious() is a no-op */ -#define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */ - -/* Forward declarations */ -static int fileBtreeCloseCursor(BtCursor *pCur); - -/* -** Routines for byte swapping. -*/ -u16 swab16(u16 x){ - return ((x & 0xff)<<8) | ((x>>8)&0xff); -} -u32 swab32(u32 x){ - return ((x & 0xff)<<24) | ((x & 0xff00)<<8) | - ((x>>8) & 0xff00) | ((x>>24)&0xff); -} - -/* -** Compute the total number of bytes that a Cell needs on the main -** database page. The number returned includes the Cell header, -** local payload storage, and the pointer to overflow pages (if -** applicable). Additional space allocated on overflow pages -** is NOT included in the value returned from this routine. -*/ -static int cellSize(Btree *pBt, Cell *pCell){ - int n = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h); - if( n>MX_LOCAL_PAYLOAD ){ - n = MX_LOCAL_PAYLOAD + sizeof(Pgno); - }else{ - n = ROUNDUP(n); - } - n += sizeof(CellHdr); - return n; -} - -/* -** Defragment the page given. All Cells are moved to the -** beginning of the page and all free space is collected -** into one big FreeBlk at the end of the page. -*/ -static void defragmentPage(Btree *pBt, MemPage *pPage){ - int pc, i, n; - FreeBlk *pFBlk; - char newPage[SQLITE_USABLE_SIZE]; - - assert( sqlitepager_iswriteable(pPage) ); - assert( pPage->isInit ); - pc = sizeof(PageHdr); - pPage->u.hdr.firstCell = SWAB16(pBt, pc); - memcpy(newPage, pPage->u.aDisk, pc); - for(i=0; inCell; i++){ - Cell *pCell = pPage->apCell[i]; - - /* This routine should never be called on an overfull page. The - ** following asserts verify that constraint. */ - assert( Addr(pCell) > Addr(pPage) ); - assert( Addr(pCell) < Addr(pPage) + SQLITE_USABLE_SIZE ); - - n = cellSize(pBt, pCell); - pCell->h.iNext = SWAB16(pBt, pc + n); - memcpy(&newPage[pc], pCell, n); - pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc]; - pc += n; - } - assert( pPage->nFree==SQLITE_USABLE_SIZE-pc ); - memcpy(pPage->u.aDisk, newPage, pc); - if( pPage->nCell>0 ){ - pPage->apCell[pPage->nCell-1]->h.iNext = 0; - } - pFBlk = (FreeBlk*)&pPage->u.aDisk[pc]; - pFBlk->iSize = SWAB16(pBt, SQLITE_USABLE_SIZE - pc); - pFBlk->iNext = 0; - pPage->u.hdr.firstFree = SWAB16(pBt, pc); - memset(&pFBlk[1], 0, SQLITE_USABLE_SIZE - pc - sizeof(FreeBlk)); -} - -/* -** Allocate nByte bytes of space on a page. nByte must be a -** multiple of 4. -** -** Return the index into pPage->u.aDisk[] of the first byte of -** the new allocation. Or return 0 if there is not enough free -** space on the page to satisfy the allocation request. -** -** If the page contains nBytes of free space but does not contain -** nBytes of contiguous free space, then this routine automatically -** calls defragementPage() to consolidate all free space before -** allocating the new chunk. -*/ -static int allocateSpace(Btree *pBt, MemPage *pPage, int nByte){ - FreeBlk *p; - u16 *pIdx; - int start; - int iSize; -#ifndef NDEBUG - int cnt = 0; -#endif - - assert( sqlitepager_iswriteable(pPage) ); - assert( nByte==ROUNDUP(nByte) ); - assert( pPage->isInit ); - if( pPage->nFreeisOverfull ) return 0; - pIdx = &pPage->u.hdr.firstFree; - p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)]; - while( (iSize = SWAB16(pBt, p->iSize))iNext==0 ){ - defragmentPage(pBt, pPage); - pIdx = &pPage->u.hdr.firstFree; - }else{ - pIdx = &p->iNext; - } - p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)]; - } - if( iSize==nByte ){ - start = SWAB16(pBt, *pIdx); - *pIdx = p->iNext; - }else{ - FreeBlk *pNew; - start = SWAB16(pBt, *pIdx); - pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte]; - pNew->iNext = p->iNext; - pNew->iSize = SWAB16(pBt, iSize - nByte); - *pIdx = SWAB16(pBt, start + nByte); - } - pPage->nFree -= nByte; - return start; -} - -/* -** Return a section of the MemPage.u.aDisk[] to the freelist. -** The first byte of the new free block is pPage->u.aDisk[start] -** and the size of the block is "size" bytes. Size must be -** a multiple of 4. -** -** Most of the effort here is involved in coalesing adjacent -** free blocks into a single big free block. -*/ -static void freeSpace(Btree *pBt, MemPage *pPage, int start, int size){ - int end = start + size; - u16 *pIdx, idx; - FreeBlk *pFBlk; - FreeBlk *pNew; - FreeBlk *pNext; - int iSize; - - assert( sqlitepager_iswriteable(pPage) ); - assert( size == ROUNDUP(size) ); - assert( start == ROUNDUP(start) ); - assert( pPage->isInit ); - pIdx = &pPage->u.hdr.firstFree; - idx = SWAB16(pBt, *pIdx); - while( idx!=0 && idxu.aDisk[idx]; - iSize = SWAB16(pBt, pFBlk->iSize); - if( idx + iSize == start ){ - pFBlk->iSize = SWAB16(pBt, iSize + size); - if( idx + iSize + size == SWAB16(pBt, pFBlk->iNext) ){ - pNext = (FreeBlk*)&pPage->u.aDisk[idx + iSize + size]; - if( pBt->needSwab ){ - pFBlk->iSize = swab16((u16)swab16(pNext->iSize)+iSize+size); - }else{ - pFBlk->iSize += pNext->iSize; - } - pFBlk->iNext = pNext->iNext; - } - pPage->nFree += size; - return; - } - pIdx = &pFBlk->iNext; - idx = SWAB16(pBt, *pIdx); - } - pNew = (FreeBlk*)&pPage->u.aDisk[start]; - if( idx != end ){ - pNew->iSize = SWAB16(pBt, size); - pNew->iNext = SWAB16(pBt, idx); - }else{ - pNext = (FreeBlk*)&pPage->u.aDisk[idx]; - pNew->iSize = SWAB16(pBt, size + SWAB16(pBt, pNext->iSize)); - pNew->iNext = pNext->iNext; - } - *pIdx = SWAB16(pBt, start); - pPage->nFree += size; -} - -/* -** Initialize the auxiliary information for a disk block. -** -** The pParent parameter must be a pointer to the MemPage which -** is the parent of the page being initialized. The root of the -** BTree (usually page 2) has no parent and so for that page, -** pParent==NULL. -** -** Return SQLITE_OK on success. If we see that the page does -** not contain a well-formed database page, then return -** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not -** guarantee that the page is well-formed. It only shows that -** we failed to detect any corruption. -*/ -static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){ - int idx; /* An index into pPage->u.aDisk[] */ - Cell *pCell; /* A pointer to a Cell in pPage->u.aDisk[] */ - FreeBlk *pFBlk; /* A pointer to a free block in pPage->u.aDisk[] */ - int sz; /* The size of a Cell in bytes */ - int freeSpace; /* Amount of free space on the page */ - - if( pPage->pParent ){ - assert( pPage->pParent==pParent ); - return SQLITE_OK; - } - if( pParent ){ - pPage->pParent = pParent; - sqlitepager_ref(pParent); - } - if( pPage->isInit ) return SQLITE_OK; - pPage->isInit = 1; - pPage->nCell = 0; - freeSpace = USABLE_SPACE; - idx = SWAB16(pBt, pPage->u.hdr.firstCell); - while( idx!=0 ){ - if( idx>SQLITE_USABLE_SIZE-MIN_CELL_SIZE ) goto page_format_error; - if( idxu.aDisk[idx]; - sz = cellSize(pBt, pCell); - if( idx+sz > SQLITE_USABLE_SIZE ) goto page_format_error; - freeSpace -= sz; - pPage->apCell[pPage->nCell++] = pCell; - idx = SWAB16(pBt, pCell->h.iNext); - } - pPage->nFree = 0; - idx = SWAB16(pBt, pPage->u.hdr.firstFree); - while( idx!=0 ){ - int iNext; - if( idx>SQLITE_USABLE_SIZE-sizeof(FreeBlk) ) goto page_format_error; - if( idxu.aDisk[idx]; - pPage->nFree += SWAB16(pBt, pFBlk->iSize); - iNext = SWAB16(pBt, pFBlk->iNext); - if( iNext>0 && iNext <= idx ) goto page_format_error; - idx = iNext; - } - if( pPage->nCell==0 && pPage->nFree==0 ){ - /* As a special case, an uninitialized root page appears to be - ** an empty database */ - return SQLITE_OK; - } - if( pPage->nFree!=freeSpace ) goto page_format_error; - return SQLITE_OK; - -page_format_error: - return SQLITE_CORRUPT; -} - -/* -** Set up a raw page so that it looks like a database page holding -** no entries. -*/ -static void zeroPage(Btree *pBt, MemPage *pPage){ - PageHdr *pHdr; - FreeBlk *pFBlk; - assert( sqlitepager_iswriteable(pPage) ); - memset(pPage, 0, SQLITE_USABLE_SIZE); - pHdr = &pPage->u.hdr; - pHdr->firstCell = 0; - pHdr->firstFree = SWAB16(pBt, sizeof(*pHdr)); - pFBlk = (FreeBlk*)&pHdr[1]; - pFBlk->iNext = 0; - pPage->nFree = SQLITE_USABLE_SIZE - sizeof(*pHdr); - pFBlk->iSize = SWAB16(pBt, pPage->nFree); - pPage->nCell = 0; - pPage->isOverfull = 0; -} - -/* -** This routine is called when the reference count for a page -** reaches zero. We need to unref the pParent pointer when that -** happens. -*/ -static void pageDestructor(void *pData){ - MemPage *pPage = (MemPage*)pData; - if( pPage->pParent ){ - MemPage *pParent = pPage->pParent; - pPage->pParent = 0; - sqlitepager_unref(pParent); - } -} - -/* -** Open a new database. -** -** Actually, this routine just sets up the internal data structures -** for accessing the database. We do not open the database file -** until the first page is loaded. -** -** zFilename is the name of the database file. If zFilename is NULL -** a new database with a random name is created. This randomly named -** database file will be deleted when sqliteBtreeClose() is called. -*/ -int sqliteBtreeOpen( - const char *zFilename, /* Name of the file containing the BTree database */ - int omitJournal, /* if TRUE then do not journal this file */ - int nCache, /* How many pages in the page cache */ - Btree **ppBtree /* Pointer to new Btree object written here */ -){ - Btree *pBt; - int rc; - - /* - ** The following asserts make sure that structures used by the btree are - ** the right size. This is to guard against size changes that result - ** when compiling on a different architecture. - */ - assert( sizeof(u32)==4 ); - assert( sizeof(u16)==2 ); - assert( sizeof(Pgno)==4 ); - assert( sizeof(PageHdr)==8 ); - assert( sizeof(CellHdr)==12 ); - assert( sizeof(FreeBlk)==4 ); - assert( sizeof(OverflowPage)==SQLITE_USABLE_SIZE ); - assert( sizeof(FreelistInfo)==OVERFLOW_SIZE ); - assert( sizeof(ptr)==sizeof(char*) ); - assert( sizeof(uptr)==sizeof(ptr) ); - - pBt = sqliteMalloc( sizeof(*pBt) ); - if( pBt==0 ){ - *ppBtree = 0; - return SQLITE_NOMEM; - } - if( nCache<10 ) nCache = 10; - rc = sqlitepager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE, - !omitJournal); - if( rc!=SQLITE_OK ){ - if( pBt->pPager ) sqlitepager_close(pBt->pPager); - sqliteFree(pBt); - *ppBtree = 0; - return rc; - } - sqlitepager_set_destructor(pBt->pPager, pageDestructor); - pBt->pCursor = 0; - pBt->page1 = 0; - pBt->readOnly = sqlitepager_isreadonly(pBt->pPager); - pBt->pOps = &sqliteBtreeOps; - *ppBtree = pBt; - return SQLITE_OK; -} - -/* -** Close an open database and invalidate all cursors. -*/ -static int fileBtreeClose(Btree *pBt){ - while( pBt->pCursor ){ - fileBtreeCloseCursor(pBt->pCursor); - } - sqlitepager_close(pBt->pPager); - sqliteFree(pBt); - return SQLITE_OK; -} - -/* -** Change the limit on the number of pages allowed in the cache. -** -** The maximum number of cache pages is set to the absolute -** value of mxPage. If mxPage is negative, the pager will -** operate asynchronously - it will not stop to do fsync()s -** to insure data is written to the disk surface before -** continuing. Transactions still work if synchronous is off, -** and the database cannot be corrupted if this program -** crashes. But if the operating system crashes or there is -** an abrupt power failure when synchronous is off, the database -** could be left in an inconsistent and unrecoverable state. -** Synchronous is on by default so database corruption is not -** normally a worry. -*/ -static int fileBtreeSetCacheSize(Btree *pBt, int mxPage){ - sqlitepager_set_cachesize(pBt->pPager, mxPage); - return SQLITE_OK; -} - -/* -** Change the way data is synced to disk in order to increase or decrease -** how well the database resists damage due to OS crashes and power -** failures. Level 1 is the same as asynchronous (no syncs() occur and -** there is a high probability of damage) Level 2 is the default. There -** is a very low but non-zero probability of damage. Level 3 reduces the -** probability of damage to near zero but with a write performance reduction. -*/ -static int fileBtreeSetSafetyLevel(Btree *pBt, int level){ - sqlitepager_set_safety_level(pBt->pPager, level); - return SQLITE_OK; -} - -/* -** Get a reference to page1 of the database file. This will -** also acquire a readlock on that file. -** -** SQLITE_OK is returned on success. If the file is not a -** well-formed database file, then SQLITE_CORRUPT is returned. -** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM -** is returned if we run out of memory. SQLITE_PROTOCOL is returned -** if there is a locking protocol violation. -*/ -static int lockBtree(Btree *pBt){ - int rc; - if( pBt->page1 ) return SQLITE_OK; - rc = sqlitepager_get(pBt->pPager, 1, (void**)&pBt->page1); - if( rc!=SQLITE_OK ) return rc; - - /* Do some checking to help insure the file we opened really is - ** a valid database file. - */ - if( sqlitepager_pagecount(pBt->pPager)>0 ){ - PageOne *pP1 = pBt->page1; - if( strcmp(pP1->zMagic,zMagicHeader)!=0 || - (pP1->iMagic!=MAGIC && swab32(pP1->iMagic)!=MAGIC) ){ - rc = SQLITE_NOTADB; - goto page1_init_failed; - } - pBt->needSwab = pP1->iMagic!=MAGIC; - } - return rc; - -page1_init_failed: - sqlitepager_unref(pBt->page1); - pBt->page1 = 0; - return rc; -} - -/* -** If there are no outstanding cursors and we are not in the middle -** of a transaction but there is a read lock on the database, then -** this routine unrefs the first page of the database file which -** has the effect of releasing the read lock. -** -** If there are any outstanding cursors, this routine is a no-op. -** -** If there is a transaction in progress, this routine is a no-op. -*/ -static void unlockBtreeIfUnused(Btree *pBt){ - if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){ - sqlitepager_unref(pBt->page1); - pBt->page1 = 0; - pBt->inTrans = 0; - pBt->inCkpt = 0; - } -} - -/* -** Create a new database by initializing the first two pages of the -** file. -*/ -static int newDatabase(Btree *pBt){ - MemPage *pRoot; - PageOne *pP1; - int rc; - if( sqlitepager_pagecount(pBt->pPager)>1 ) return SQLITE_OK; - pP1 = pBt->page1; - rc = sqlitepager_write(pBt->page1); - if( rc ) return rc; - rc = sqlitepager_get(pBt->pPager, 2, (void**)&pRoot); - if( rc ) return rc; - rc = sqlitepager_write(pRoot); - if( rc ){ - sqlitepager_unref(pRoot); - return rc; - } - strcpy(pP1->zMagic, zMagicHeader); - if( btree_native_byte_order ){ - pP1->iMagic = MAGIC; - pBt->needSwab = 0; - }else{ - pP1->iMagic = swab32(MAGIC); - pBt->needSwab = 1; - } - zeroPage(pBt, pRoot); - sqlitepager_unref(pRoot); - return SQLITE_OK; -} - -/* -** Attempt to start a new transaction. -** -** A transaction must be started before attempting any changes -** to the database. None of the following routines will work -** unless a transaction is started first: -** -** sqliteBtreeCreateTable() -** sqliteBtreeCreateIndex() -** sqliteBtreeClearTable() -** sqliteBtreeDropTable() -** sqliteBtreeInsert() -** sqliteBtreeDelete() -** sqliteBtreeUpdateMeta() -*/ -static int fileBtreeBeginTrans(Btree *pBt){ - int rc; - if( pBt->inTrans ) return SQLITE_ERROR; - if( pBt->readOnly ) return SQLITE_READONLY; - if( pBt->page1==0 ){ - rc = lockBtree(pBt); - if( rc!=SQLITE_OK ){ - return rc; - } - } - rc = sqlitepager_begin(pBt->page1); - if( rc==SQLITE_OK ){ - rc = newDatabase(pBt); - } - if( rc==SQLITE_OK ){ - pBt->inTrans = 1; - pBt->inCkpt = 0; - }else{ - unlockBtreeIfUnused(pBt); - } - return rc; -} - -/* -** Commit the transaction currently in progress. -** -** This will release the write lock on the database file. If there -** are no active cursors, it also releases the read lock. -*/ -static int fileBtreeCommit(Btree *pBt){ - int rc; - rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager); - pBt->inTrans = 0; - pBt->inCkpt = 0; - unlockBtreeIfUnused(pBt); - return rc; -} - -/* -** Rollback the transaction in progress. All cursors will be -** invalided by this operation. Any attempt to use a cursor -** that was open at the beginning of this operation will result -** in an error. -** -** This will release the write lock on the database file. If there -** are no active cursors, it also releases the read lock. -*/ -static int fileBtreeRollback(Btree *pBt){ - int rc; - BtCursor *pCur; - if( pBt->inTrans==0 ) return SQLITE_OK; - pBt->inTrans = 0; - pBt->inCkpt = 0; - rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager); - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( pCur->pPage && pCur->pPage->isInit==0 ){ - sqlitepager_unref(pCur->pPage); - pCur->pPage = 0; - } - } - unlockBtreeIfUnused(pBt); - return rc; -} - -/* -** Set the checkpoint for the current transaction. The checkpoint serves -** as a sub-transaction that can be rolled back independently of the -** main transaction. You must start a transaction before starting a -** checkpoint. The checkpoint is ended automatically if the transaction -** commits or rolls back. -** -** Only one checkpoint may be active at a time. It is an error to try -** to start a new checkpoint if another checkpoint is already active. -*/ -static int fileBtreeBeginCkpt(Btree *pBt){ - int rc; - if( !pBt->inTrans || pBt->inCkpt ){ - return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - } - rc = pBt->readOnly ? SQLITE_OK : sqlitepager_ckpt_begin(pBt->pPager); - pBt->inCkpt = 1; - return rc; -} - - -/* -** Commit a checkpoint to transaction currently in progress. If no -** checkpoint is active, this is a no-op. -*/ -static int fileBtreeCommitCkpt(Btree *pBt){ - int rc; - if( pBt->inCkpt && !pBt->readOnly ){ - rc = sqlitepager_ckpt_commit(pBt->pPager); - }else{ - rc = SQLITE_OK; - } - pBt->inCkpt = 0; - return rc; -} - -/* -** Rollback the checkpoint to the current transaction. If there -** is no active checkpoint or transaction, this routine is a no-op. -** -** All cursors will be invalided by this operation. Any attempt -** to use a cursor that was open at the beginning of this operation -** will result in an error. -*/ -static int fileBtreeRollbackCkpt(Btree *pBt){ - int rc; - BtCursor *pCur; - if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK; - rc = sqlitepager_ckpt_rollback(pBt->pPager); - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( pCur->pPage && pCur->pPage->isInit==0 ){ - sqlitepager_unref(pCur->pPage); - pCur->pPage = 0; - } - } - pBt->inCkpt = 0; - return rc; -} - -/* -** Create a new cursor for the BTree whose root is on the page -** iTable. The act of acquiring a cursor gets a read lock on -** the database file. -** -** If wrFlag==0, then the cursor can only be used for reading. -** If wrFlag==1, then the cursor can be used for reading or for -** writing if other conditions for writing are also met. These -** are the conditions that must be met in order for writing to -** be allowed: -** -** 1: The cursor must have been opened with wrFlag==1 -** -** 2: No other cursors may be open with wrFlag==0 on the same table -** -** 3: The database must be writable (not on read-only media) -** -** 4: There must be an active transaction. -** -** Condition 2 warrants further discussion. If any cursor is opened -** on a table with wrFlag==0, that prevents all other cursors from -** writing to that table. This is a kind of "read-lock". When a cursor -** is opened with wrFlag==0 it is guaranteed that the table will not -** change as long as the cursor is open. This allows the cursor to -** do a sequential scan of the table without having to worry about -** entries being inserted or deleted during the scan. Cursors should -** be opened with wrFlag==0 only if this read-lock property is needed. -** That is to say, cursors should be opened with wrFlag==0 only if they -** intend to use the sqliteBtreeNext() system call. All other cursors -** should be opened with wrFlag==1 even if they never really intend -** to write. -** -** No checking is done to make sure that page iTable really is the -** root page of a b-tree. If it is not, then the cursor acquired -** will not work correctly. -*/ -static -int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){ - int rc; - BtCursor *pCur, *pRing; - - if( pBt->readOnly && wrFlag ){ - *ppCur = 0; - return SQLITE_READONLY; - } - if( pBt->page1==0 ){ - rc = lockBtree(pBt); - if( rc!=SQLITE_OK ){ - *ppCur = 0; - return rc; - } - } - pCur = sqliteMalloc( sizeof(*pCur) ); - if( pCur==0 ){ - rc = SQLITE_NOMEM; - goto create_cursor_exception; - } - pCur->pgnoRoot = (Pgno)iTable; - rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage); - if( rc!=SQLITE_OK ){ - goto create_cursor_exception; - } - rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0); - if( rc!=SQLITE_OK ){ - goto create_cursor_exception; - } - pCur->pOps = &sqliteBtreeCursorOps; - pCur->pBt = pBt; - pCur->wrFlag = wrFlag; - pCur->idx = 0; - pCur->eSkip = SKIP_INVALID; - pCur->pNext = pBt->pCursor; - if( pCur->pNext ){ - pCur->pNext->pPrev = pCur; - } - pCur->pPrev = 0; - pRing = pBt->pCursor; - while( pRing && pRing->pgnoRoot!=pCur->pgnoRoot ){ pRing = pRing->pNext; } - if( pRing ){ - pCur->pShared = pRing->pShared; - pRing->pShared = pCur; - }else{ - pCur->pShared = pCur; - } - pBt->pCursor = pCur; - *ppCur = pCur; - return SQLITE_OK; - -create_cursor_exception: - *ppCur = 0; - if( pCur ){ - if( pCur->pPage ) sqlitepager_unref(pCur->pPage); - sqliteFree(pCur); - } - unlockBtreeIfUnused(pBt); - return rc; -} - -/* -** Close a cursor. The read lock on the database file is released -** when the last cursor is closed. -*/ -static int fileBtreeCloseCursor(BtCursor *pCur){ - Btree *pBt = pCur->pBt; - if( pCur->pPrev ){ - pCur->pPrev->pNext = pCur->pNext; - }else{ - pBt->pCursor = pCur->pNext; - } - if( pCur->pNext ){ - pCur->pNext->pPrev = pCur->pPrev; - } - if( pCur->pPage ){ - sqlitepager_unref(pCur->pPage); - } - if( pCur->pShared!=pCur ){ - BtCursor *pRing = pCur->pShared; - while( pRing->pShared!=pCur ){ pRing = pRing->pShared; } - pRing->pShared = pCur->pShared; - } - unlockBtreeIfUnused(pBt); - sqliteFree(pCur); - return SQLITE_OK; -} - -/* -** Make a temporary cursor by filling in the fields of pTempCur. -** The temporary cursor is not on the cursor list for the Btree. -*/ -static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){ - memcpy(pTempCur, pCur, sizeof(*pCur)); - pTempCur->pNext = 0; - pTempCur->pPrev = 0; - if( pTempCur->pPage ){ - sqlitepager_ref(pTempCur->pPage); - } -} - -/* -** Delete a temporary cursor such as was made by the CreateTemporaryCursor() -** function above. -*/ -static void releaseTempCursor(BtCursor *pCur){ - if( pCur->pPage ){ - sqlitepager_unref(pCur->pPage); - } -} - -/* -** Set *pSize to the number of bytes of key in the entry the -** cursor currently points to. Always return SQLITE_OK. -** Failure is not possible. If the cursor is not currently -** pointing to an entry (which can happen, for example, if -** the database is empty) then *pSize is set to 0. -*/ -static int fileBtreeKeySize(BtCursor *pCur, int *pSize){ - Cell *pCell; - MemPage *pPage; - - pPage = pCur->pPage; - assert( pPage!=0 ); - if( pCur->idx >= pPage->nCell ){ - *pSize = 0; - }else{ - pCell = pPage->apCell[pCur->idx]; - *pSize = NKEY(pCur->pBt, pCell->h); - } - return SQLITE_OK; -} - -/* -** Read payload information from the entry that the pCur cursor is -** pointing to. Begin reading the payload at "offset" and read -** a total of "amt" bytes. Put the result in zBuf. -** -** This routine does not make a distinction between key and data. -** It just reads bytes from the payload area. -*/ -static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){ - char *aPayload; - Pgno nextPage; - int rc; - Btree *pBt = pCur->pBt; - assert( pCur!=0 && pCur->pPage!=0 ); - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); - aPayload = pCur->pPage->apCell[pCur->idx]->aPayload; - if( offsetMX_LOCAL_PAYLOAD ){ - a = MX_LOCAL_PAYLOAD - offset; - } - memcpy(zBuf, &aPayload[offset], a); - if( a==amt ){ - return SQLITE_OK; - } - offset = 0; - zBuf += a; - amt -= a; - }else{ - offset -= MX_LOCAL_PAYLOAD; - } - if( amt>0 ){ - nextPage = SWAB32(pBt, pCur->pPage->apCell[pCur->idx]->ovfl); - } - while( amt>0 && nextPage ){ - OverflowPage *pOvfl; - rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl); - if( rc!=0 ){ - return rc; - } - nextPage = SWAB32(pBt, pOvfl->iNext); - if( offset OVERFLOW_SIZE ){ - a = OVERFLOW_SIZE - offset; - } - memcpy(zBuf, &pOvfl->aPayload[offset], a); - offset = 0; - amt -= a; - zBuf += a; - }else{ - offset -= OVERFLOW_SIZE; - } - sqlitepager_unref(pOvfl); - } - if( amt>0 ){ - return SQLITE_CORRUPT; - } - return SQLITE_OK; -} - -/* -** Read part of the key associated with cursor pCur. A maximum -** of "amt" bytes will be transfered into zBuf[]. The transfer -** begins at "offset". The number of bytes actually read is -** returned. -** -** Change: It used to be that the amount returned will be smaller -** than the amount requested if there are not enough bytes in the key -** to satisfy the request. But now, it must be the case that there -** is enough data available to satisfy the request. If not, an exception -** is raised. The change was made in an effort to boost performance -** by eliminating unneeded tests. -*/ -static int fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){ - MemPage *pPage; - - assert( amt>=0 ); - assert( offset>=0 ); - assert( pCur->pPage!=0 ); - pPage = pCur->pPage; - if( pCur->idx >= pPage->nCell ){ - return 0; - } - assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) ); - getPayload(pCur, offset, amt, zBuf); - return amt; -} - -/* -** Set *pSize to the number of bytes of data in the entry the -** cursor currently points to. Always return SQLITE_OK. -** Failure is not possible. If the cursor is not currently -** pointing to an entry (which can happen, for example, if -** the database is empty) then *pSize is set to 0. -*/ -static int fileBtreeDataSize(BtCursor *pCur, int *pSize){ - Cell *pCell; - MemPage *pPage; - - pPage = pCur->pPage; - assert( pPage!=0 ); - if( pCur->idx >= pPage->nCell ){ - *pSize = 0; - }else{ - pCell = pPage->apCell[pCur->idx]; - *pSize = NDATA(pCur->pBt, pCell->h); - } - return SQLITE_OK; -} - -/* -** Read part of the data associated with cursor pCur. A maximum -** of "amt" bytes will be transfered into zBuf[]. The transfer -** begins at "offset". The number of bytes actually read is -** returned. The amount returned will be smaller than the -** amount requested if there are not enough bytes in the data -** to satisfy the request. -*/ -static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){ - Cell *pCell; - MemPage *pPage; - - assert( amt>=0 ); - assert( offset>=0 ); - assert( pCur->pPage!=0 ); - pPage = pCur->pPage; - if( pCur->idx >= pPage->nCell ){ - return 0; - } - pCell = pPage->apCell[pCur->idx]; - assert( amt+offset <= NDATA(pCur->pBt, pCell->h) ); - getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf); - return amt; -} - -/* -** Compare an external key against the key on the entry that pCur points to. -** -** The external key is pKey and is nKey bytes long. The last nIgnore bytes -** of the key associated with pCur are ignored, as if they do not exist. -** (The normal case is for nIgnore to be zero in which case the entire -** internal key is used in the comparison.) -** -** The comparison result is written to *pRes as follows: -** -** *pRes<0 This means pCur0 This means pCur>pKey -** -** When one key is an exact prefix of the other, the shorter key is -** considered less than the longer one. In order to be equal the -** keys must be exactly the same length. (The length of the pCur key -** is the actual key length minus nIgnore bytes.) -*/ -static int fileBtreeKeyCompare( - BtCursor *pCur, /* Pointer to entry to compare against */ - const void *pKey, /* Key to compare against entry that pCur points to */ - int nKey, /* Number of bytes in pKey */ - int nIgnore, /* Ignore this many bytes at the end of pCur */ - int *pResult /* Write the result here */ -){ - Pgno nextPage; - int n, c, rc, nLocal; - Cell *pCell; - Btree *pBt = pCur->pBt; - const char *zKey = (const char*)pKey; - - assert( pCur->pPage ); - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); - pCell = pCur->pPage->apCell[pCur->idx]; - nLocal = NKEY(pBt, pCell->h) - nIgnore; - if( nLocal<0 ) nLocal = 0; - n = nKeyMX_LOCAL_PAYLOAD ){ - n = MX_LOCAL_PAYLOAD; - } - c = memcmp(pCell->aPayload, zKey, n); - if( c!=0 ){ - *pResult = c; - return SQLITE_OK; - } - zKey += n; - nKey -= n; - nLocal -= n; - nextPage = SWAB32(pBt, pCell->ovfl); - while( nKey>0 && nLocal>0 ){ - OverflowPage *pOvfl; - if( nextPage==0 ){ - return SQLITE_CORRUPT; - } - rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl); - if( rc ){ - return rc; - } - nextPage = SWAB32(pBt, pOvfl->iNext); - n = nKeyOVERFLOW_SIZE ){ - n = OVERFLOW_SIZE; - } - c = memcmp(pOvfl->aPayload, zKey, n); - sqlitepager_unref(pOvfl); - if( c!=0 ){ - *pResult = c; - return SQLITE_OK; - } - nKey -= n; - nLocal -= n; - zKey += n; - } - if( c==0 ){ - c = nLocal - nKey; - } - *pResult = c; - return SQLITE_OK; -} - -/* -** Move the cursor down to a new child page. The newPgno argument is the -** page number of the child page in the byte order of the disk image. -*/ -static int moveToChild(BtCursor *pCur, int newPgno){ - int rc; - MemPage *pNewPage; - Btree *pBt = pCur->pBt; - - newPgno = SWAB32(pBt, newPgno); - rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage); - if( rc ) return rc; - rc = initPage(pBt, pNewPage, newPgno, pCur->pPage); - if( rc ) return rc; - assert( pCur->idx>=pCur->pPage->nCell - || pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) ); - assert( pCur->idxpPage->nCell - || pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) ); - pNewPage->idxParent = pCur->idx; - pCur->pPage->idxShift = 0; - sqlitepager_unref(pCur->pPage); - pCur->pPage = pNewPage; - pCur->idx = 0; - if( pNewPage->nCell<1 ){ - return SQLITE_CORRUPT; - } - return SQLITE_OK; -} - -/* -** Move the cursor up to the parent page. -** -** pCur->idx is set to the cell index that contains the pointer -** to the page we are coming from. If we are coming from the -** right-most child page then pCur->idx is set to one more than -** the largest cell index. -*/ -static void moveToParent(BtCursor *pCur){ - Pgno oldPgno; - MemPage *pParent; - MemPage *pPage; - int idxParent; - pPage = pCur->pPage; - assert( pPage!=0 ); - pParent = pPage->pParent; - assert( pParent!=0 ); - idxParent = pPage->idxParent; - sqlitepager_ref(pParent); - sqlitepager_unref(pPage); - pCur->pPage = pParent; - assert( pParent->idxShift==0 ); - if( pParent->idxShift==0 ){ - pCur->idx = idxParent; -#ifndef NDEBUG - /* Verify that pCur->idx is the correct index to point back to the child - ** page we just came from - */ - oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage)); - if( pCur->idxnCell ){ - assert( pParent->apCell[idxParent]->h.leftChild==oldPgno ); - }else{ - assert( pParent->u.hdr.rightChild==oldPgno ); - } -#endif - }else{ - /* The MemPage.idxShift flag indicates that cell indices might have - ** changed since idxParent was set and hence idxParent might be out - ** of date. So recompute the parent cell index by scanning all cells - ** and locating the one that points to the child we just came from. - */ - int i; - pCur->idx = pParent->nCell; - oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage)); - for(i=0; inCell; i++){ - if( pParent->apCell[i]->h.leftChild==oldPgno ){ - pCur->idx = i; - break; - } - } - } -} - -/* -** Move the cursor to the root page -*/ -static int moveToRoot(BtCursor *pCur){ - MemPage *pNew; - int rc; - Btree *pBt = pCur->pBt; - - rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew); - if( rc ) return rc; - rc = initPage(pBt, pNew, pCur->pgnoRoot, 0); - if( rc ) return rc; - sqlitepager_unref(pCur->pPage); - pCur->pPage = pNew; - pCur->idx = 0; - return SQLITE_OK; -} - -/* -** Move the cursor down to the left-most leaf entry beneath the -** entry to which it is currently pointing. -*/ -static int moveToLeftmost(BtCursor *pCur){ - Pgno pgno; - int rc; - - while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){ - rc = moveToChild(pCur, pgno); - if( rc ) return rc; - } - return SQLITE_OK; -} - -/* -** Move the cursor down to the right-most leaf entry beneath the -** page to which it is currently pointing. Notice the difference -** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() -** finds the left-most entry beneath the *entry* whereas moveToRightmost() -** finds the right-most entry beneath the *page*. -*/ -static int moveToRightmost(BtCursor *pCur){ - Pgno pgno; - int rc; - - while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){ - pCur->idx = pCur->pPage->nCell; - rc = moveToChild(pCur, pgno); - if( rc ) return rc; - } - pCur->idx = pCur->pPage->nCell - 1; - return SQLITE_OK; -} - -/* Move the cursor to the first entry in the table. Return SQLITE_OK -** on success. Set *pRes to 0 if the cursor actually points to something -** or set *pRes to 1 if the table is empty. -*/ -static int fileBtreeFirst(BtCursor *pCur, int *pRes){ - int rc; - if( pCur->pPage==0 ) return SQLITE_ABORT; - rc = moveToRoot(pCur); - if( rc ) return rc; - if( pCur->pPage->nCell==0 ){ - *pRes = 1; - return SQLITE_OK; - } - *pRes = 0; - rc = moveToLeftmost(pCur); - pCur->eSkip = SKIP_NONE; - return rc; -} - -/* Move the cursor to the last entry in the table. Return SQLITE_OK -** on success. Set *pRes to 0 if the cursor actually points to something -** or set *pRes to 1 if the table is empty. -*/ -static int fileBtreeLast(BtCursor *pCur, int *pRes){ - int rc; - if( pCur->pPage==0 ) return SQLITE_ABORT; - rc = moveToRoot(pCur); - if( rc ) return rc; - assert( pCur->pPage->isInit ); - if( pCur->pPage->nCell==0 ){ - *pRes = 1; - return SQLITE_OK; - } - *pRes = 0; - rc = moveToRightmost(pCur); - pCur->eSkip = SKIP_NONE; - return rc; -} - -/* Move the cursor so that it points to an entry near pKey. -** Return a success code. -** -** If an exact match is not found, then the cursor is always -** left pointing at a leaf page which would hold the entry if it -** were present. The cursor might point to an entry that comes -** before or after the key. -** -** The result of comparing the key with the entry to which the -** cursor is left pointing is stored in pCur->iMatch. The same -** value is also written to *pRes if pRes!=NULL. The meaning of -** this value is as follows: -** -** *pRes<0 The cursor is left pointing at an entry that -** is smaller than pKey or if the table is empty -** and the cursor is therefore left point to nothing. -** -** *pRes==0 The cursor is left pointing at an entry that -** exactly matches pKey. -** -** *pRes>0 The cursor is left pointing at an entry that -** is larger than pKey. -*/ -static -int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){ - int rc; - if( pCur->pPage==0 ) return SQLITE_ABORT; - pCur->eSkip = SKIP_NONE; - rc = moveToRoot(pCur); - if( rc ) return rc; - for(;;){ - int lwr, upr; - Pgno chldPg; - MemPage *pPage = pCur->pPage; - int c = -1; /* pRes return if table is empty must be -1 */ - lwr = 0; - upr = pPage->nCell-1; - while( lwr<=upr ){ - pCur->idx = (lwr+upr)/2; - rc = fileBtreeKeyCompare(pCur, pKey, nKey, 0, &c); - if( rc ) return rc; - if( c==0 ){ - pCur->iMatch = c; - if( pRes ) *pRes = 0; - return SQLITE_OK; - } - if( c<0 ){ - lwr = pCur->idx+1; - }else{ - upr = pCur->idx-1; - } - } - assert( lwr==upr+1 ); - assert( pPage->isInit ); - if( lwr>=pPage->nCell ){ - chldPg = pPage->u.hdr.rightChild; - }else{ - chldPg = pPage->apCell[lwr]->h.leftChild; - } - if( chldPg==0 ){ - pCur->iMatch = c; - if( pRes ) *pRes = c; - return SQLITE_OK; - } - pCur->idx = lwr; - rc = moveToChild(pCur, chldPg); - if( rc ) return rc; - } - /* NOT REACHED */ -} - -/* -** Advance the cursor to the next entry in the database. If -** successful then set *pRes=0. If the cursor -** was already pointing to the last entry in the database before -** this routine was called, then set *pRes=1. -*/ -static int fileBtreeNext(BtCursor *pCur, int *pRes){ - int rc; - MemPage *pPage = pCur->pPage; - assert( pRes!=0 ); - if( pPage==0 ){ - *pRes = 1; - return SQLITE_ABORT; - } - assert( pPage->isInit ); - assert( pCur->eSkip!=SKIP_INVALID ); - if( pPage->nCell==0 ){ - *pRes = 1; - return SQLITE_OK; - } - assert( pCur->idxnCell ); - if( pCur->eSkip==SKIP_NEXT ){ - pCur->eSkip = SKIP_NONE; - *pRes = 0; - return SQLITE_OK; - } - pCur->eSkip = SKIP_NONE; - pCur->idx++; - if( pCur->idx>=pPage->nCell ){ - if( pPage->u.hdr.rightChild ){ - rc = moveToChild(pCur, pPage->u.hdr.rightChild); - if( rc ) return rc; - rc = moveToLeftmost(pCur); - *pRes = 0; - return rc; - } - do{ - if( pPage->pParent==0 ){ - *pRes = 1; - return SQLITE_OK; - } - moveToParent(pCur); - pPage = pCur->pPage; - }while( pCur->idx>=pPage->nCell ); - *pRes = 0; - return SQLITE_OK; - } - *pRes = 0; - if( pPage->u.hdr.rightChild==0 ){ - return SQLITE_OK; - } - rc = moveToLeftmost(pCur); - return rc; -} - -/* -** Step the cursor to the back to the previous entry in the database. If -** successful then set *pRes=0. If the cursor -** was already pointing to the first entry in the database before -** this routine was called, then set *pRes=1. -*/ -static int fileBtreePrevious(BtCursor *pCur, int *pRes){ - int rc; - Pgno pgno; - MemPage *pPage; - pPage = pCur->pPage; - if( pPage==0 ){ - *pRes = 1; - return SQLITE_ABORT; - } - assert( pPage->isInit ); - assert( pCur->eSkip!=SKIP_INVALID ); - if( pPage->nCell==0 ){ - *pRes = 1; - return SQLITE_OK; - } - if( pCur->eSkip==SKIP_PREV ){ - pCur->eSkip = SKIP_NONE; - *pRes = 0; - return SQLITE_OK; - } - pCur->eSkip = SKIP_NONE; - assert( pCur->idx>=0 ); - if( (pgno = pPage->apCell[pCur->idx]->h.leftChild)!=0 ){ - rc = moveToChild(pCur, pgno); - if( rc ) return rc; - rc = moveToRightmost(pCur); - }else{ - while( pCur->idx==0 ){ - if( pPage->pParent==0 ){ - if( pRes ) *pRes = 1; - return SQLITE_OK; - } - moveToParent(pCur); - pPage = pCur->pPage; - } - pCur->idx--; - rc = SQLITE_OK; - } - *pRes = 0; - return rc; -} - -/* -** Allocate a new page from the database file. -** -** The new page is marked as dirty. (In other words, sqlitepager_write() -** has already been called on the new page.) The new page has also -** been referenced and the calling routine is responsible for calling -** sqlitepager_unref() on the new page when it is done. -** -** SQLITE_OK is returned on success. Any other return value indicates -** an error. *ppPage and *pPgno are undefined in the event of an error. -** Do not invoke sqlitepager_unref() on *ppPage if an error is returned. -** -** If the "nearby" parameter is not 0, then a (feeble) effort is made to -** locate a page close to the page number "nearby". This can be used in an -** attempt to keep related pages close to each other in the database file, -** which in turn can make database access faster. -*/ -static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){ - PageOne *pPage1 = pBt->page1; - int rc; - if( pPage1->freeList ){ - OverflowPage *pOvfl; - FreelistInfo *pInfo; - - rc = sqlitepager_write(pPage1); - if( rc ) return rc; - SWAB_ADD(pBt, pPage1->nFree, -1); - rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList), - (void**)&pOvfl); - if( rc ) return rc; - rc = sqlitepager_write(pOvfl); - if( rc ){ - sqlitepager_unref(pOvfl); - return rc; - } - pInfo = (FreelistInfo*)pOvfl->aPayload; - if( pInfo->nFree==0 ){ - *pPgno = SWAB32(pBt, pPage1->freeList); - pPage1->freeList = pOvfl->iNext; - *ppPage = (MemPage*)pOvfl; - }else{ - int closest, n; - n = SWAB32(pBt, pInfo->nFree); - if( n>1 && nearby>0 ){ - int i, dist; - closest = 0; - dist = SWAB32(pBt, pInfo->aFree[0]) - nearby; - if( dist<0 ) dist = -dist; - for(i=1; iaFree[i]) - nearby; - if( d2<0 ) d2 = -d2; - if( d2nFree, -1); - *pPgno = SWAB32(pBt, pInfo->aFree[closest]); - pInfo->aFree[closest] = pInfo->aFree[n-1]; - rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage); - sqlitepager_unref(pOvfl); - if( rc==SQLITE_OK ){ - sqlitepager_dont_rollback(*ppPage); - rc = sqlitepager_write(*ppPage); - } - } - }else{ - *pPgno = sqlitepager_pagecount(pBt->pPager) + 1; - rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage); - if( rc ) return rc; - rc = sqlitepager_write(*ppPage); - } - return rc; -} - -/* -** Add a page of the database file to the freelist. Either pgno or -** pPage but not both may be 0. -** -** sqlitepager_unref() is NOT called for pPage. -*/ -static int freePage(Btree *pBt, void *pPage, Pgno pgno){ - PageOne *pPage1 = pBt->page1; - OverflowPage *pOvfl = (OverflowPage*)pPage; - int rc; - int needUnref = 0; - MemPage *pMemPage; - - if( pgno==0 ){ - assert( pOvfl!=0 ); - pgno = sqlitepager_pagenumber(pOvfl); - } - assert( pgno>2 ); - assert( sqlitepager_pagenumber(pOvfl)==pgno ); - pMemPage = (MemPage*)pPage; - pMemPage->isInit = 0; - if( pMemPage->pParent ){ - sqlitepager_unref(pMemPage->pParent); - pMemPage->pParent = 0; - } - rc = sqlitepager_write(pPage1); - if( rc ){ - return rc; - } - SWAB_ADD(pBt, pPage1->nFree, 1); - if( pPage1->nFree!=0 && pPage1->freeList!=0 ){ - OverflowPage *pFreeIdx; - rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList), - (void**)&pFreeIdx); - if( rc==SQLITE_OK ){ - FreelistInfo *pInfo = (FreelistInfo*)pFreeIdx->aPayload; - int n = SWAB32(pBt, pInfo->nFree); - if( n<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){ - rc = sqlitepager_write(pFreeIdx); - if( rc==SQLITE_OK ){ - pInfo->aFree[n] = SWAB32(pBt, pgno); - SWAB_ADD(pBt, pInfo->nFree, 1); - sqlitepager_unref(pFreeIdx); - sqlitepager_dont_write(pBt->pPager, pgno); - return rc; - } - } - sqlitepager_unref(pFreeIdx); - } - } - if( pOvfl==0 ){ - assert( pgno>0 ); - rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pOvfl); - if( rc ) return rc; - needUnref = 1; - } - rc = sqlitepager_write(pOvfl); - if( rc ){ - if( needUnref ) sqlitepager_unref(pOvfl); - return rc; - } - pOvfl->iNext = pPage1->freeList; - pPage1->freeList = SWAB32(pBt, pgno); - memset(pOvfl->aPayload, 0, OVERFLOW_SIZE); - if( needUnref ) rc = sqlitepager_unref(pOvfl); - return rc; -} - -/* -** Erase all the data out of a cell. This involves returning overflow -** pages back the freelist. -*/ -static int clearCell(Btree *pBt, Cell *pCell){ - Pager *pPager = pBt->pPager; - OverflowPage *pOvfl; - Pgno ovfl, nextOvfl; - int rc; - - if( NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h) <= MX_LOCAL_PAYLOAD ){ - return SQLITE_OK; - } - ovfl = SWAB32(pBt, pCell->ovfl); - pCell->ovfl = 0; - while( ovfl ){ - rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl); - if( rc ) return rc; - nextOvfl = SWAB32(pBt, pOvfl->iNext); - rc = freePage(pBt, pOvfl, ovfl); - if( rc ) return rc; - sqlitepager_unref(pOvfl); - ovfl = nextOvfl; - } - return SQLITE_OK; -} - -/* -** Create a new cell from key and data. Overflow pages are allocated as -** necessary and linked to this cell. -*/ -static int fillInCell( - Btree *pBt, /* The whole Btree. Needed to allocate pages */ - Cell *pCell, /* Populate this Cell structure */ - const void *pKey, int nKey, /* The key */ - const void *pData,int nData /* The data */ -){ - OverflowPage *pOvfl, *pPrior; - Pgno *pNext; - int spaceLeft; - int n, rc; - int nPayload; - const char *pPayload; - char *pSpace; - Pgno nearby = 0; - - pCell->h.leftChild = 0; - pCell->h.nKey = SWAB16(pBt, nKey & 0xffff); - pCell->h.nKeyHi = nKey >> 16; - pCell->h.nData = SWAB16(pBt, nData & 0xffff); - pCell->h.nDataHi = nData >> 16; - pCell->h.iNext = 0; - - pNext = &pCell->ovfl; - pSpace = pCell->aPayload; - spaceLeft = MX_LOCAL_PAYLOAD; - pPayload = pKey; - pKey = 0; - nPayload = nKey; - pPrior = 0; - while( nPayload>0 ){ - if( spaceLeft==0 ){ - rc = allocatePage(pBt, (MemPage**)&pOvfl, pNext, nearby); - if( rc ){ - *pNext = 0; - }else{ - nearby = *pNext; - } - if( pPrior ) sqlitepager_unref(pPrior); - if( rc ){ - clearCell(pBt, pCell); - return rc; - } - if( pBt->needSwab ) *pNext = swab32(*pNext); - pPrior = pOvfl; - spaceLeft = OVERFLOW_SIZE; - pSpace = pOvfl->aPayload; - pNext = &pOvfl->iNext; - } - n = nPayload; - if( n>spaceLeft ) n = spaceLeft; - memcpy(pSpace, pPayload, n); - nPayload -= n; - if( nPayload==0 && pData ){ - pPayload = pData; - nPayload = nData; - pData = 0; - }else{ - pPayload += n; - } - spaceLeft -= n; - pSpace += n; - } - *pNext = 0; - if( pPrior ){ - sqlitepager_unref(pPrior); - } - return SQLITE_OK; -} - -/* -** Change the MemPage.pParent pointer on the page whose number is -** given in the second argument so that MemPage.pParent holds the -** pointer in the third argument. -*/ -static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx){ - MemPage *pThis; - - if( pgno==0 ) return; - assert( pPager!=0 ); - pThis = sqlitepager_lookup(pPager, pgno); - if( pThis && pThis->isInit ){ - if( pThis->pParent!=pNewParent ){ - if( pThis->pParent ) sqlitepager_unref(pThis->pParent); - pThis->pParent = pNewParent; - if( pNewParent ) sqlitepager_ref(pNewParent); - } - pThis->idxParent = idx; - sqlitepager_unref(pThis); - } -} - -/* -** Reparent all children of the given page to be the given page. -** In other words, for every child of pPage, invoke reparentPage() -** to make sure that each child knows that pPage is its parent. -** -** This routine gets called after you memcpy() one page into -** another. -*/ -static void reparentChildPages(Btree *pBt, MemPage *pPage){ - int i; - Pager *pPager = pBt->pPager; - for(i=0; inCell; i++){ - reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage, i); - } - reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage, i); - pPage->idxShift = 0; -} - -/* -** Remove the i-th cell from pPage. This routine effects pPage only. -** The cell content is not freed or deallocated. It is assumed that -** the cell content has been copied someplace else. This routine just -** removes the reference to the cell from pPage. -** -** "sz" must be the number of bytes in the cell. -** -** Do not bother maintaining the integrity of the linked list of Cells. -** Only the pPage->apCell[] array is important. The relinkCellList() -** routine will be called soon after this routine in order to rebuild -** the linked list. -*/ -static void dropCell(Btree *pBt, MemPage *pPage, int idx, int sz){ - int j; - assert( idx>=0 && idxnCell ); - assert( sz==cellSize(pBt, pPage->apCell[idx]) ); - assert( sqlitepager_iswriteable(pPage) ); - freeSpace(pBt, pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz); - for(j=idx; jnCell-1; j++){ - pPage->apCell[j] = pPage->apCell[j+1]; - } - pPage->nCell--; - pPage->idxShift = 1; -} - -/* -** Insert a new cell on pPage at cell index "i". pCell points to the -** content of the cell. -** -** If the cell content will fit on the page, then put it there. If it -** will not fit, then just make pPage->apCell[i] point to the content -** and set pPage->isOverfull. -** -** Do not bother maintaining the integrity of the linked list of Cells. -** Only the pPage->apCell[] array is important. The relinkCellList() -** routine will be called soon after this routine in order to rebuild -** the linked list. -*/ -static void insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz){ - int idx, j; - assert( i>=0 && i<=pPage->nCell ); - assert( sz==cellSize(pBt, pCell) ); - assert( sqlitepager_iswriteable(pPage) ); - idx = allocateSpace(pBt, pPage, sz); - for(j=pPage->nCell; j>i; j--){ - pPage->apCell[j] = pPage->apCell[j-1]; - } - pPage->nCell++; - if( idx<=0 ){ - pPage->isOverfull = 1; - pPage->apCell[i] = pCell; - }else{ - memcpy(&pPage->u.aDisk[idx], pCell, sz); - pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx]; - } - pPage->idxShift = 1; -} - -/* -** Rebuild the linked list of cells on a page so that the cells -** occur in the order specified by the pPage->apCell[] array. -** Invoke this routine once to repair damage after one or more -** invocations of either insertCell() or dropCell(). -*/ -static void relinkCellList(Btree *pBt, MemPage *pPage){ - int i; - u16 *pIdx; - assert( sqlitepager_iswriteable(pPage) ); - pIdx = &pPage->u.hdr.firstCell; - for(i=0; inCell; i++){ - int idx = Addr(pPage->apCell[i]) - Addr(pPage); - assert( idx>0 && idxapCell[i]->h.iNext; - } - *pIdx = 0; -} - -/* -** Make a copy of the contents of pFrom into pTo. The pFrom->apCell[] -** pointers that point into pFrom->u.aDisk[] must be adjusted to point -** into pTo->u.aDisk[] instead. But some pFrom->apCell[] entries might -** not point to pFrom->u.aDisk[]. Those are unchanged. -*/ -static void copyPage(MemPage *pTo, MemPage *pFrom){ - uptr from, to; - int i; - memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_USABLE_SIZE); - pTo->pParent = 0; - pTo->isInit = 1; - pTo->nCell = pFrom->nCell; - pTo->nFree = pFrom->nFree; - pTo->isOverfull = pFrom->isOverfull; - to = Addr(pTo); - from = Addr(pFrom); - for(i=0; inCell; i++){ - uptr x = Addr(pFrom->apCell[i]); - if( x>from && xapCell[i]) = x + to - from; - }else{ - pTo->apCell[i] = pFrom->apCell[i]; - } - } -} - -/* -** The following parameters determine how many adjacent pages get involved -** in a balancing operation. NN is the number of neighbors on either side -** of the page that participate in the balancing operation. NB is the -** total number of pages that participate, including the target page and -** NN neighbors on either side. -** -** The minimum value of NN is 1 (of course). Increasing NN above 1 -** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance -** in exchange for a larger degradation in INSERT and UPDATE performance. -** The value of NN appears to give the best results overall. -*/ -#define NN 1 /* Number of neighbors on either side of pPage */ -#define NB (NN*2+1) /* Total pages involved in the balance */ - -/* -** This routine redistributes Cells on pPage and up to two siblings -** of pPage so that all pages have about the same amount of free space. -** Usually one sibling on either side of pPage is used in the balancing, -** though both siblings might come from one side if pPage is the first -** or last child of its parent. If pPage has fewer than two siblings -** (something which can only happen if pPage is the root page or a -** child of root) then all available siblings participate in the balancing. -** -** The number of siblings of pPage might be increased or decreased by -** one in an effort to keep pages between 66% and 100% full. The root page -** is special and is allowed to be less than 66% full. If pPage is -** the root page, then the depth of the tree might be increased -** or decreased by one, as necessary, to keep the root page from being -** overfull or empty. -** -** This routine calls relinkCellList() on its input page regardless of -** whether or not it does any real balancing. Client routines will typically -** invoke insertCell() or dropCell() before calling this routine, so we -** need to call relinkCellList() to clean up the mess that those other -** routines left behind. -** -** pCur is left pointing to the same cell as when this routine was called -** even if that cell gets moved to a different page. pCur may be NULL. -** Set the pCur parameter to NULL if you do not care about keeping track -** of a cell as that will save this routine the work of keeping track of it. -** -** Note that when this routine is called, some of the Cells on pPage -** might not actually be stored in pPage->u.aDisk[]. This can happen -** if the page is overfull. Part of the job of this routine is to -** make sure all Cells for pPage once again fit in pPage->u.aDisk[]. -** -** In the course of balancing the siblings of pPage, the parent of pPage -** might become overfull or underfull. If that happens, then this routine -** is called recursively on the parent. -** -** If this routine fails for any reason, it might leave the database -** in a corrupted state. So if this routine fails, the database should -** be rolled back. -*/ -static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){ - MemPage *pParent; /* The parent of pPage */ - int nCell; /* Number of cells in apCell[] */ - int nOld; /* Number of pages in apOld[] */ - int nNew; /* Number of pages in apNew[] */ - int nDiv; /* Number of cells in apDiv[] */ - int i, j, k; /* Loop counters */ - int idx; /* Index of pPage in pParent->apCell[] */ - int nxDiv; /* Next divider slot in pParent->apCell[] */ - int rc; /* The return code */ - int iCur; /* apCell[iCur] is the cell of the cursor */ - MemPage *pOldCurPage; /* The cursor originally points to this page */ - int subtotal; /* Subtotal of bytes in cells on one page */ - MemPage *extraUnref = 0; /* A page that needs to be unref-ed */ - MemPage *apOld[NB]; /* pPage and up to two siblings */ - Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */ - MemPage *apNew[NB+1]; /* pPage and up to NB siblings after balancing */ - Pgno pgnoNew[NB+1]; /* Page numbers for each page in apNew[] */ - int idxDiv[NB]; /* Indices of divider cells in pParent */ - Cell *apDiv[NB]; /* Divider cells in pParent */ - Cell aTemp[NB]; /* Temporary holding area for apDiv[] */ - int cntNew[NB+1]; /* Index in apCell[] of cell after i-th page */ - int szNew[NB+1]; /* Combined size of cells place on i-th page */ - MemPage aOld[NB]; /* Temporary copies of pPage and its siblings */ - Cell *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */ - int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */ - - /* - ** Return without doing any work if pPage is neither overfull nor - ** underfull. - */ - assert( sqlitepager_iswriteable(pPage) ); - if( !pPage->isOverfull && pPage->nFreenCell>=2){ - relinkCellList(pBt, pPage); - return SQLITE_OK; - } - - /* - ** Find the parent of the page to be balanceed. - ** If there is no parent, it means this page is the root page and - ** special rules apply. - */ - pParent = pPage->pParent; - if( pParent==0 ){ - Pgno pgnoChild; - MemPage *pChild; - assert( pPage->isInit ); - if( pPage->nCell==0 ){ - if( pPage->u.hdr.rightChild ){ - /* - ** The root page is empty. Copy the one child page - ** into the root page and return. This reduces the depth - ** of the BTree by one. - */ - pgnoChild = SWAB32(pBt, pPage->u.hdr.rightChild); - rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild); - if( rc ) return rc; - memcpy(pPage, pChild, SQLITE_USABLE_SIZE); - pPage->isInit = 0; - rc = initPage(pBt, pPage, sqlitepager_pagenumber(pPage), 0); - assert( rc==SQLITE_OK ); - reparentChildPages(pBt, pPage); - if( pCur && pCur->pPage==pChild ){ - sqlitepager_unref(pChild); - pCur->pPage = pPage; - sqlitepager_ref(pPage); - } - freePage(pBt, pChild, pgnoChild); - sqlitepager_unref(pChild); - }else{ - relinkCellList(pBt, pPage); - } - return SQLITE_OK; - } - if( !pPage->isOverfull ){ - /* It is OK for the root page to be less than half full. - */ - relinkCellList(pBt, pPage); - return SQLITE_OK; - } - /* - ** If we get to here, it means the root page is overfull. - ** When this happens, Create a new child page and copy the - ** contents of the root into the child. Then make the root - ** page an empty page with rightChild pointing to the new - ** child. Then fall thru to the code below which will cause - ** the overfull child page to be split. - */ - rc = sqlitepager_write(pPage); - if( rc ) return rc; - rc = allocatePage(pBt, &pChild, &pgnoChild, sqlitepager_pagenumber(pPage)); - if( rc ) return rc; - assert( sqlitepager_iswriteable(pChild) ); - copyPage(pChild, pPage); - pChild->pParent = pPage; - pChild->idxParent = 0; - sqlitepager_ref(pPage); - pChild->isOverfull = 1; - if( pCur && pCur->pPage==pPage ){ - sqlitepager_unref(pPage); - pCur->pPage = pChild; - }else{ - extraUnref = pChild; - } - zeroPage(pBt, pPage); - pPage->u.hdr.rightChild = SWAB32(pBt, pgnoChild); - pParent = pPage; - pPage = pChild; - } - rc = sqlitepager_write(pParent); - if( rc ) return rc; - assert( pParent->isInit ); - - /* - ** Find the Cell in the parent page whose h.leftChild points back - ** to pPage. The "idx" variable is the index of that cell. If pPage - ** is the rightmost child of pParent then set idx to pParent->nCell - */ - if( pParent->idxShift ){ - Pgno pgno, swabPgno; - pgno = sqlitepager_pagenumber(pPage); - swabPgno = SWAB32(pBt, pgno); - for(idx=0; idxnCell; idx++){ - if( pParent->apCell[idx]->h.leftChild==swabPgno ){ - break; - } - } - assert( idxnCell || pParent->u.hdr.rightChild==swabPgno ); - }else{ - idx = pPage->idxParent; - } - - /* - ** Initialize variables so that it will be safe to jump - ** directly to balance_cleanup at any moment. - */ - nOld = nNew = 0; - sqlitepager_ref(pParent); - - /* - ** Find sibling pages to pPage and the Cells in pParent that divide - ** the siblings. An attempt is made to find NN siblings on either - ** side of pPage. More siblings are taken from one side, however, if - ** pPage there are fewer than NN siblings on the other side. If pParent - ** has NB or fewer children then all children of pParent are taken. - */ - nxDiv = idx - NN; - if( nxDiv + NB > pParent->nCell ){ - nxDiv = pParent->nCell - NB + 1; - } - if( nxDiv<0 ){ - nxDiv = 0; - } - nDiv = 0; - for(i=0, k=nxDiv; inCell ){ - idxDiv[i] = k; - apDiv[i] = pParent->apCell[k]; - nDiv++; - pgnoOld[i] = SWAB32(pBt, apDiv[i]->h.leftChild); - }else if( k==pParent->nCell ){ - pgnoOld[i] = SWAB32(pBt, pParent->u.hdr.rightChild); - }else{ - break; - } - rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]); - if( rc ) goto balance_cleanup; - rc = initPage(pBt, apOld[i], pgnoOld[i], pParent); - if( rc ) goto balance_cleanup; - apOld[i]->idxParent = k; - nOld++; - } - - /* - ** Set iCur to be the index in apCell[] of the cell that the cursor - ** is pointing to. We will need this later on in order to keep the - ** cursor pointing at the same cell. If pCur points to a page that - ** has no involvement with this rebalancing, then set iCur to a large - ** number so that the iCur==j tests always fail in the main cell - ** distribution loop below. - */ - if( pCur ){ - iCur = 0; - for(i=0; ipPage==apOld[i] ){ - iCur += pCur->idx; - break; - } - iCur += apOld[i]->nCell; - if( ipPage==pParent && pCur->idx==idxDiv[i] ){ - break; - } - iCur++; - } - pOldCurPage = pCur->pPage; - } - - /* - ** Make copies of the content of pPage and its siblings into aOld[]. - ** The rest of this function will use data from the copies rather - ** that the original pages since the original pages will be in the - ** process of being overwritten. - */ - for(i=0; inCell; j++){ - apCell[nCell] = pOld->apCell[j]; - szCell[nCell] = cellSize(pBt, apCell[nCell]); - nCell++; - } - if( ih.leftChild)==pgnoOld[i] ); - apCell[nCell]->h.leftChild = pOld->u.hdr.rightChild; - nCell++; - } - } - - /* - ** Figure out the number of pages needed to hold all nCell cells. - ** Store this number in "k". Also compute szNew[] which is the total - ** size of all cells on the i-th page and cntNew[] which is the index - ** in apCell[] of the cell that divides path i from path i+1. - ** cntNew[k] should equal nCell. - ** - ** This little patch of code is critical for keeping the tree - ** balanced. - */ - for(subtotal=k=i=0; i USABLE_SPACE ){ - szNew[k] = subtotal - szCell[i]; - cntNew[k] = i; - subtotal = 0; - k++; - } - } - szNew[k] = subtotal; - cntNew[k] = nCell; - k++; - for(i=k-1; i>0; i--){ - while( szNew[i]0 ); - szNew[i] += szCell[cntNew[i-1]]; - szNew[i-1] -= szCell[cntNew[i-1]-1]; - } - } - assert( cntNew[0]>0 ); - - /* - ** Allocate k new pages. Reuse old pages where possible. - */ - for(i=0; iisInit = 1; - } - - /* Free any old pages that were not reused as new pages. - */ - while( ii ){ - int t; - MemPage *pT; - t = pgnoNew[i]; - pT = apNew[i]; - pgnoNew[i] = pgnoNew[minI]; - apNew[i] = apNew[minI]; - pgnoNew[minI] = t; - apNew[minI] = pT; - } - } - - /* - ** Evenly distribute the data in apCell[] across the new pages. - ** Insert divider cells into pParent as necessary. - */ - j = 0; - for(i=0; inFree>=szCell[j] ); - if( pCur && iCur==j ){ pCur->pPage = pNew; pCur->idx = pNew->nCell; } - insertCell(pBt, pNew, pNew->nCell, apCell[j], szCell[j]); - j++; - } - assert( pNew->nCell>0 ); - assert( !pNew->isOverfull ); - relinkCellList(pBt, pNew); - if( iu.hdr.rightChild = apCell[j]->h.leftChild; - apCell[j]->h.leftChild = SWAB32(pBt, pgnoNew[i]); - if( pCur && iCur==j ){ pCur->pPage = pParent; pCur->idx = nxDiv; } - insertCell(pBt, pParent, nxDiv, apCell[j], szCell[j]); - j++; - nxDiv++; - } - } - assert( j==nCell ); - apNew[nNew-1]->u.hdr.rightChild = aOld[nOld-1].u.hdr.rightChild; - if( nxDiv==pParent->nCell ){ - pParent->u.hdr.rightChild = SWAB32(pBt, pgnoNew[nNew-1]); - }else{ - pParent->apCell[nxDiv]->h.leftChild = SWAB32(pBt, pgnoNew[nNew-1]); - } - if( pCur ){ - if( j<=iCur && pCur->pPage==pParent && pCur->idx>idxDiv[nOld-1] ){ - assert( pCur->pPage==pOldCurPage ); - pCur->idx += nNew - nOld; - }else{ - assert( pOldCurPage!=0 ); - sqlitepager_ref(pCur->pPage); - sqlitepager_unref(pOldCurPage); - } - } - - /* - ** Reparent children of all cells. - */ - for(i=0; ipPage==0 ){ - pCur->pPage = pParent; - pCur->idx = 0; - }else{ - sqlitepager_unref(pParent); - } - return rc; -} - -/* -** This routine checks all cursors that point to the same table -** as pCur points to. If any of those cursors were opened with -** wrFlag==0 then this routine returns SQLITE_LOCKED. If all -** cursors point to the same table were opened with wrFlag==1 -** then this routine returns SQLITE_OK. -** -** In addition to checking for read-locks (where a read-lock -** means a cursor opened with wrFlag==0) this routine also moves -** all cursors other than pCur so that they are pointing to the -** first Cell on root page. This is necessary because an insert -** or delete might change the number of cells on a page or delete -** a page entirely and we do not want to leave any cursors -** pointing to non-existant pages or cells. -*/ -static int checkReadLocks(BtCursor *pCur){ - BtCursor *p; - assert( pCur->wrFlag ); - for(p=pCur->pShared; p!=pCur; p=p->pShared){ - assert( p ); - assert( p->pgnoRoot==pCur->pgnoRoot ); - if( p->wrFlag==0 ) return SQLITE_LOCKED; - if( sqlitepager_pagenumber(p->pPage)!=p->pgnoRoot ){ - moveToRoot(p); - } - } - return SQLITE_OK; -} - -/* -** Insert a new record into the BTree. The key is given by (pKey,nKey) -** and the data is given by (pData,nData). The cursor is used only to -** define what database the record should be inserted into. The cursor -** is left pointing at the new record. -*/ -static int fileBtreeInsert( - BtCursor *pCur, /* Insert data into the table of this cursor */ - const void *pKey, int nKey, /* The key of the new record */ - const void *pData, int nData /* The data of the new record */ -){ - Cell newCell; - int rc; - int loc; - int szNew; - MemPage *pPage; - Btree *pBt = pCur->pBt; - - if( pCur->pPage==0 ){ - return SQLITE_ABORT; /* A rollback destroyed this cursor */ - } - if( !pBt->inTrans || nKey+nData==0 ){ - /* Must start a transaction before doing an insert */ - return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - } - assert( !pBt->readOnly ); - if( !pCur->wrFlag ){ - return SQLITE_PERM; /* Cursor not open for writing */ - } - if( checkReadLocks(pCur) ){ - return SQLITE_LOCKED; /* The table pCur points to has a read lock */ - } - rc = fileBtreeMoveto(pCur, pKey, nKey, &loc); - if( rc ) return rc; - pPage = pCur->pPage; - assert( pPage->isInit ); - rc = sqlitepager_write(pPage); - if( rc ) return rc; - rc = fillInCell(pBt, &newCell, pKey, nKey, pData, nData); - if( rc ) return rc; - szNew = cellSize(pBt, &newCell); - if( loc==0 ){ - newCell.h.leftChild = pPage->apCell[pCur->idx]->h.leftChild; - rc = clearCell(pBt, pPage->apCell[pCur->idx]); - if( rc ) return rc; - dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pPage->apCell[pCur->idx])); - }else if( loc<0 && pPage->nCell>0 ){ - assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */ - pCur->idx++; - }else{ - assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */ - } - insertCell(pBt, pPage, pCur->idx, &newCell, szNew); - rc = balance(pCur->pBt, pPage, pCur); - /* sqliteBtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */ - /* fflush(stdout); */ - pCur->eSkip = SKIP_INVALID; - return rc; -} - -/* -** Delete the entry that the cursor is pointing to. -** -** The cursor is left pointing at either the next or the previous -** entry. If the cursor is left pointing to the next entry, then -** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to -** sqliteBtreeNext() to be a no-op. That way, you can always call -** sqliteBtreeNext() after a delete and the cursor will be left -** pointing to the first entry after the deleted entry. Similarly, -** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to -** the entry prior to the deleted entry so that a subsequent call to -** sqliteBtreePrevious() will always leave the cursor pointing at the -** entry immediately before the one that was deleted. -*/ -static int fileBtreeDelete(BtCursor *pCur){ - MemPage *pPage = pCur->pPage; - Cell *pCell; - int rc; - Pgno pgnoChild; - Btree *pBt = pCur->pBt; - - assert( pPage->isInit ); - if( pCur->pPage==0 ){ - return SQLITE_ABORT; /* A rollback destroyed this cursor */ - } - if( !pBt->inTrans ){ - /* Must start a transaction before doing a delete */ - return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - } - assert( !pBt->readOnly ); - if( pCur->idx >= pPage->nCell ){ - return SQLITE_ERROR; /* The cursor is not pointing to anything */ - } - if( !pCur->wrFlag ){ - return SQLITE_PERM; /* Did not open this cursor for writing */ - } - if( checkReadLocks(pCur) ){ - return SQLITE_LOCKED; /* The table pCur points to has a read lock */ - } - rc = sqlitepager_write(pPage); - if( rc ) return rc; - pCell = pPage->apCell[pCur->idx]; - pgnoChild = SWAB32(pBt, pCell->h.leftChild); - clearCell(pBt, pCell); - if( pgnoChild ){ - /* - ** The entry we are about to delete is not a leaf so if we do not - ** do something we will leave a hole on an internal page. - ** We have to fill the hole by moving in a cell from a leaf. The - ** next Cell after the one to be deleted is guaranteed to exist and - ** to be a leaf so we can use it. - */ - BtCursor leafCur; - Cell *pNext; - int szNext; - int notUsed; - getTempCursor(pCur, &leafCur); - rc = fileBtreeNext(&leafCur, ¬Used); - if( rc!=SQLITE_OK ){ - if( rc!=SQLITE_NOMEM ) rc = SQLITE_CORRUPT; - return rc; - } - rc = sqlitepager_write(leafCur.pPage); - if( rc ) return rc; - dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell)); - pNext = leafCur.pPage->apCell[leafCur.idx]; - szNext = cellSize(pBt, pNext); - pNext->h.leftChild = SWAB32(pBt, pgnoChild); - insertCell(pBt, pPage, pCur->idx, pNext, szNext); - rc = balance(pBt, pPage, pCur); - if( rc ) return rc; - pCur->eSkip = SKIP_NEXT; - dropCell(pBt, leafCur.pPage, leafCur.idx, szNext); - rc = balance(pBt, leafCur.pPage, pCur); - releaseTempCursor(&leafCur); - }else{ - dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell)); - if( pCur->idx>=pPage->nCell ){ - pCur->idx = pPage->nCell-1; - if( pCur->idx<0 ){ - pCur->idx = 0; - pCur->eSkip = SKIP_NEXT; - }else{ - pCur->eSkip = SKIP_PREV; - } - }else{ - pCur->eSkip = SKIP_NEXT; - } - rc = balance(pBt, pPage, pCur); - } - return rc; -} - -/* -** Create a new BTree table. Write into *piTable the page -** number for the root page of the new table. -** -** In the current implementation, BTree tables and BTree indices are the -** the same. In the future, we may change this so that BTree tables -** are restricted to having a 4-byte integer key and arbitrary data and -** BTree indices are restricted to having an arbitrary key and no data. -** But for now, this routine also serves to create indices. -*/ -static int fileBtreeCreateTable(Btree *pBt, int *piTable){ - MemPage *pRoot; - Pgno pgnoRoot; - int rc; - if( !pBt->inTrans ){ - /* Must start a transaction first */ - return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - } - if( pBt->readOnly ){ - return SQLITE_READONLY; - } - rc = allocatePage(pBt, &pRoot, &pgnoRoot, 0); - if( rc ) return rc; - assert( sqlitepager_iswriteable(pRoot) ); - zeroPage(pBt, pRoot); - sqlitepager_unref(pRoot); - *piTable = (int)pgnoRoot; - return SQLITE_OK; -} - -/* -** Erase the given database page and all its children. Return -** the page to the freelist. -*/ -static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){ - MemPage *pPage; - int rc; - Cell *pCell; - int idx; - - rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pPage); - if( rc ) return rc; - rc = sqlitepager_write(pPage); - if( rc ) return rc; - rc = initPage(pBt, pPage, pgno, 0); - if( rc ) return rc; - idx = SWAB16(pBt, pPage->u.hdr.firstCell); - while( idx>0 ){ - pCell = (Cell*)&pPage->u.aDisk[idx]; - idx = SWAB16(pBt, pCell->h.iNext); - if( pCell->h.leftChild ){ - rc = clearDatabasePage(pBt, SWAB32(pBt, pCell->h.leftChild), 1); - if( rc ) return rc; - } - rc = clearCell(pBt, pCell); - if( rc ) return rc; - } - if( pPage->u.hdr.rightChild ){ - rc = clearDatabasePage(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1); - if( rc ) return rc; - } - if( freePageFlag ){ - rc = freePage(pBt, pPage, pgno); - }else{ - zeroPage(pBt, pPage); - } - sqlitepager_unref(pPage); - return rc; -} - -/* -** Delete all information from a single table in the database. -*/ -static int fileBtreeClearTable(Btree *pBt, int iTable){ - int rc; - BtCursor *pCur; - if( !pBt->inTrans ){ - return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - } - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( pCur->pgnoRoot==(Pgno)iTable ){ - if( pCur->wrFlag==0 ) return SQLITE_LOCKED; - moveToRoot(pCur); - } - } - rc = clearDatabasePage(pBt, (Pgno)iTable, 0); - if( rc ){ - fileBtreeRollback(pBt); - } - return rc; -} - -/* -** Erase all information in a table and add the root of the table to -** the freelist. Except, the root of the principle table (the one on -** page 2) is never added to the freelist. -*/ -static int fileBtreeDropTable(Btree *pBt, int iTable){ - int rc; - MemPage *pPage; - BtCursor *pCur; - if( !pBt->inTrans ){ - return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - } - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( pCur->pgnoRoot==(Pgno)iTable ){ - return SQLITE_LOCKED; /* Cannot drop a table that has a cursor */ - } - } - rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage); - if( rc ) return rc; - rc = fileBtreeClearTable(pBt, iTable); - if( rc ) return rc; - if( iTable>2 ){ - rc = freePage(pBt, pPage, iTable); - }else{ - zeroPage(pBt, pPage); - } - sqlitepager_unref(pPage); - return rc; -} - -#if 0 /* UNTESTED */ -/* -** Copy all cell data from one database file into another. -** pages back the freelist. -*/ -static int copyCell(Btree *pBtFrom, BTree *pBtTo, Cell *pCell){ - Pager *pFromPager = pBtFrom->pPager; - OverflowPage *pOvfl; - Pgno ovfl, nextOvfl; - Pgno *pPrev; - int rc = SQLITE_OK; - MemPage *pNew, *pPrevPg; - Pgno new; - - if( NKEY(pBtTo, pCell->h) + NDATA(pBtTo, pCell->h) <= MX_LOCAL_PAYLOAD ){ - return SQLITE_OK; - } - pPrev = &pCell->ovfl; - pPrevPg = 0; - ovfl = SWAB32(pBtTo, pCell->ovfl); - while( ovfl && rc==SQLITE_OK ){ - rc = sqlitepager_get(pFromPager, ovfl, (void**)&pOvfl); - if( rc ) return rc; - nextOvfl = SWAB32(pBtFrom, pOvfl->iNext); - rc = allocatePage(pBtTo, &pNew, &new, 0); - if( rc==SQLITE_OK ){ - rc = sqlitepager_write(pNew); - if( rc==SQLITE_OK ){ - memcpy(pNew, pOvfl, SQLITE_USABLE_SIZE); - *pPrev = SWAB32(pBtTo, new); - if( pPrevPg ){ - sqlitepager_unref(pPrevPg); - } - pPrev = &pOvfl->iNext; - pPrevPg = pNew; - } - } - sqlitepager_unref(pOvfl); - ovfl = nextOvfl; - } - if( pPrevPg ){ - sqlitepager_unref(pPrevPg); - } - return rc; -} -#endif - - -#if 0 /* UNTESTED */ -/* -** Copy a page of data from one database over to another. -*/ -static int copyDatabasePage( - Btree *pBtFrom, - Pgno pgnoFrom, - Btree *pBtTo, - Pgno *pTo -){ - MemPage *pPageFrom, *pPage; - Pgno to; - int rc; - Cell *pCell; - int idx; - - rc = sqlitepager_get(pBtFrom->pPager, pgno, (void**)&pPageFrom); - if( rc ) return rc; - rc = allocatePage(pBt, &pPage, pTo, 0); - if( rc==SQLITE_OK ){ - rc = sqlitepager_write(pPage); - } - if( rc==SQLITE_OK ){ - memcpy(pPage, pPageFrom, SQLITE_USABLE_SIZE); - idx = SWAB16(pBt, pPage->u.hdr.firstCell); - while( idx>0 ){ - pCell = (Cell*)&pPage->u.aDisk[idx]; - idx = SWAB16(pBt, pCell->h.iNext); - if( pCell->h.leftChild ){ - Pgno newChld; - rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pCell->h.leftChild), - pBtTo, &newChld); - if( rc ) return rc; - pCell->h.leftChild = SWAB32(pBtFrom, newChld); - } - rc = copyCell(pBtFrom, pBtTo, pCell); - if( rc ) return rc; - } - if( pPage->u.hdr.rightChild ){ - Pgno newChld; - rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pPage->u.hdr.rightChild), - pBtTo, &newChld); - if( rc ) return rc; - pPage->u.hdr.rightChild = SWAB32(pBtTo, newChild); - } - } - sqlitepager_unref(pPage); - return rc; -} -#endif - -/* -** Read the meta-information out of a database file. -*/ -static int fileBtreeGetMeta(Btree *pBt, int *aMeta){ - PageOne *pP1; - int rc; - int i; - - rc = sqlitepager_get(pBt->pPager, 1, (void**)&pP1); - if( rc ) return rc; - aMeta[0] = SWAB32(pBt, pP1->nFree); - for(i=0; iaMeta)/sizeof(pP1->aMeta[0]); i++){ - aMeta[i+1] = SWAB32(pBt, pP1->aMeta[i]); - } - sqlitepager_unref(pP1); - return SQLITE_OK; -} - -/* -** Write meta-information back into the database. -*/ -static int fileBtreeUpdateMeta(Btree *pBt, int *aMeta){ - PageOne *pP1; - int rc, i; - if( !pBt->inTrans ){ - return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - } - pP1 = pBt->page1; - rc = sqlitepager_write(pP1); - if( rc ) return rc; - for(i=0; iaMeta)/sizeof(pP1->aMeta[0]); i++){ - pP1->aMeta[i] = SWAB32(pBt, aMeta[i+1]); - } - return SQLITE_OK; -} - -/****************************************************************************** -** The complete implementation of the BTree subsystem is above this line. -** All the code the follows is for testing and troubleshooting the BTree -** subsystem. None of the code that follows is used during normal operation. -******************************************************************************/ - -/* -** Print a disassembly of the given page on standard output. This routine -** is used for debugging and testing only. -*/ -#ifdef SQLITE_TEST -static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){ - int rc; - MemPage *pPage; - int i, j; - int nFree; - u16 idx; - char range[20]; - unsigned char payload[20]; - rc = sqlitepager_get(pBt->pPager, (Pgno)pgno, (void**)&pPage); - if( rc ){ - return rc; - } - if( recursive ) printf("PAGE %d:\n", pgno); - i = 0; - idx = SWAB16(pBt, pPage->u.hdr.firstCell); - while( idx>0 && idx<=SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){ - Cell *pCell = (Cell*)&pPage->u.aDisk[idx]; - int sz = cellSize(pBt, pCell); - sprintf(range,"%d..%d", idx, idx+sz-1); - sz = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h); - if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1; - memcpy(payload, pCell->aPayload, sz); - for(j=0; j0x7f ) payload[j] = '.'; - } - payload[sz] = 0; - printf( - "cell %2d: i=%-10s chld=%-4d nk=%-4d nd=%-4d payload=%s\n", - i, range, (int)pCell->h.leftChild, - NKEY(pBt, pCell->h), NDATA(pBt, pCell->h), - payload - ); - if( pPage->isInit && pPage->apCell[i]!=pCell ){ - printf("**** apCell[%d] does not match on prior entry ****\n", i); - } - i++; - idx = SWAB16(pBt, pCell->h.iNext); - } - if( idx!=0 ){ - printf("ERROR: next cell index out of range: %d\n", idx); - } - printf("right_child: %d\n", SWAB32(pBt, pPage->u.hdr.rightChild)); - nFree = 0; - i = 0; - idx = SWAB16(pBt, pPage->u.hdr.firstFree); - while( idx>0 && idxu.aDisk[idx]; - sprintf(range,"%d..%d", idx, idx+p->iSize-1); - nFree += SWAB16(pBt, p->iSize); - printf("freeblock %2d: i=%-10s size=%-4d total=%d\n", - i, range, SWAB16(pBt, p->iSize), nFree); - idx = SWAB16(pBt, p->iNext); - i++; - } - if( idx!=0 ){ - printf("ERROR: next freeblock index out of range: %d\n", idx); - } - if( recursive && pPage->u.hdr.rightChild!=0 ){ - idx = SWAB16(pBt, pPage->u.hdr.firstCell); - while( idx>0 && idxu.aDisk[idx]; - fileBtreePageDump(pBt, SWAB32(pBt, pCell->h.leftChild), 1); - idx = SWAB16(pBt, pCell->h.iNext); - } - fileBtreePageDump(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1); - } - sqlitepager_unref(pPage); - return SQLITE_OK; -} -#endif - -#ifdef SQLITE_TEST -/* -** Fill aResult[] with information about the entry and page that the -** cursor is pointing to. -** -** aResult[0] = The page number -** aResult[1] = The entry number -** aResult[2] = Total number of entries on this page -** aResult[3] = Size of this entry -** aResult[4] = Number of free bytes on this page -** aResult[5] = Number of free blocks on the page -** aResult[6] = Page number of the left child of this entry -** aResult[7] = Page number of the right child for the whole page -** -** This routine is used for testing and debugging only. -*/ -static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){ - int cnt, idx; - MemPage *pPage = pCur->pPage; - Btree *pBt = pCur->pBt; - aResult[0] = sqlitepager_pagenumber(pPage); - aResult[1] = pCur->idx; - aResult[2] = pPage->nCell; - if( pCur->idx>=0 && pCur->idxnCell ){ - aResult[3] = cellSize(pBt, pPage->apCell[pCur->idx]); - aResult[6] = SWAB32(pBt, pPage->apCell[pCur->idx]->h.leftChild); - }else{ - aResult[3] = 0; - aResult[6] = 0; - } - aResult[4] = pPage->nFree; - cnt = 0; - idx = SWAB16(pBt, pPage->u.hdr.firstFree); - while( idx>0 && idxu.aDisk[idx])->iNext); - } - aResult[5] = cnt; - aResult[7] = SWAB32(pBt, pPage->u.hdr.rightChild); - return SQLITE_OK; -} -#endif - -/* -** Return the pager associated with a BTree. This routine is used for -** testing and debugging only. -*/ -static Pager *fileBtreePager(Btree *pBt){ - return pBt->pPager; -} - -/* -** This structure is passed around through all the sanity checking routines -** in order to keep track of some global state information. -*/ -typedef struct IntegrityCk IntegrityCk; -struct IntegrityCk { - Btree *pBt; /* The tree being checked out */ - Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ - int nPage; /* Number of pages in the database */ - int *anRef; /* Number of times each page is referenced */ - char *zErrMsg; /* An error message. NULL of no errors seen. */ -}; - -/* -** Append a message to the error message string. -*/ -static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){ - if( pCheck->zErrMsg ){ - char *zOld = pCheck->zErrMsg; - pCheck->zErrMsg = 0; - sqliteSetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0); - sqliteFree(zOld); - }else{ - sqliteSetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0); - } -} - -/* -** Add 1 to the reference count for page iPage. If this is the second -** reference to the page, add an error message to pCheck->zErrMsg. -** Return 1 if there are 2 ore more references to the page and 0 if -** if this is the first reference to the page. -** -** Also check that the page number is in bounds. -*/ -static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ - if( iPage==0 ) return 1; - if( iPage>pCheck->nPage || iPage<0 ){ - char zBuf[100]; - sprintf(zBuf, "invalid page number %d", iPage); - checkAppendMsg(pCheck, zContext, zBuf); - return 1; - } - if( pCheck->anRef[iPage]==1 ){ - char zBuf[100]; - sprintf(zBuf, "2nd reference to page %d", iPage); - checkAppendMsg(pCheck, zContext, zBuf); - return 1; - } - return (pCheck->anRef[iPage]++)>1; -} - -/* -** Check the integrity of the freelist or of an overflow page list. -** Verify that the number of pages on the list is N. -*/ -static void checkList( - IntegrityCk *pCheck, /* Integrity checking context */ - int isFreeList, /* True for a freelist. False for overflow page list */ - int iPage, /* Page number for first page in the list */ - int N, /* Expected number of pages in the list */ - char *zContext /* Context for error messages */ -){ - int i; - char zMsg[100]; - while( N-- > 0 ){ - OverflowPage *pOvfl; - if( iPage<1 ){ - sprintf(zMsg, "%d pages missing from overflow list", N+1); - checkAppendMsg(pCheck, zContext, zMsg); - break; - } - if( checkRef(pCheck, iPage, zContext) ) break; - if( sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){ - sprintf(zMsg, "failed to get page %d", iPage); - checkAppendMsg(pCheck, zContext, zMsg); - break; - } - if( isFreeList ){ - FreelistInfo *pInfo = (FreelistInfo*)pOvfl->aPayload; - int n = SWAB32(pCheck->pBt, pInfo->nFree); - for(i=0; ipBt, pInfo->aFree[i]), zContext); - } - N -= n; - } - iPage = SWAB32(pCheck->pBt, pOvfl->iNext); - sqlitepager_unref(pOvfl); - } -} - -/* -** Return negative if zKey1zKey2. -*/ -static int keyCompare( - const char *zKey1, int nKey1, - const char *zKey2, int nKey2 -){ - int min = nKey1>nKey2 ? nKey2 : nKey1; - int c = memcmp(zKey1, zKey2, min); - if( c==0 ){ - c = nKey1 - nKey2; - } - return c; -} - -/* -** Do various sanity checks on a single page of a tree. Return -** the tree depth. Root pages return 0. Parents of root pages -** return 1, and so forth. -** -** These checks are done: -** -** 1. Make sure that cells and freeblocks do not overlap -** but combine to completely cover the page. -** 2. Make sure cell keys are in order. -** 3. Make sure no key is less than or equal to zLowerBound. -** 4. Make sure no key is greater than or equal to zUpperBound. -** 5. Check the integrity of overflow pages. -** 6. Recursively call checkTreePage on all children. -** 7. Verify that the depth of all children is the same. -** 8. Make sure this page is at least 33% full or else it is -** the root of the tree. -*/ -static int checkTreePage( - IntegrityCk *pCheck, /* Context for the sanity check */ - int iPage, /* Page number of the page to check */ - MemPage *pParent, /* Parent page */ - char *zParentContext, /* Parent context */ - char *zLowerBound, /* All keys should be greater than this, if not NULL */ - int nLower, /* Number of characters in zLowerBound */ - char *zUpperBound, /* All keys should be less than this, if not NULL */ - int nUpper /* Number of characters in zUpperBound */ -){ - MemPage *pPage; - int i, rc, depth, d2, pgno; - char *zKey1, *zKey2; - int nKey1, nKey2; - BtCursor cur; - Btree *pBt; - char zMsg[100]; - char zContext[100]; - char hit[SQLITE_USABLE_SIZE]; - - /* Check that the page exists - */ - cur.pBt = pBt = pCheck->pBt; - if( iPage==0 ) return 0; - if( checkRef(pCheck, iPage, zParentContext) ) return 0; - sprintf(zContext, "On tree page %d: ", iPage); - if( (rc = sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pPage))!=0 ){ - sprintf(zMsg, "unable to get the page. error code=%d", rc); - checkAppendMsg(pCheck, zContext, zMsg); - return 0; - } - if( (rc = initPage(pBt, pPage, (Pgno)iPage, pParent))!=0 ){ - sprintf(zMsg, "initPage() returns error code %d", rc); - checkAppendMsg(pCheck, zContext, zMsg); - sqlitepager_unref(pPage); - return 0; - } - - /* Check out all the cells. - */ - depth = 0; - if( zLowerBound ){ - zKey1 = sqliteMalloc( nLower+1 ); - memcpy(zKey1, zLowerBound, nLower); - zKey1[nLower] = 0; - }else{ - zKey1 = 0; - } - nKey1 = nLower; - cur.pPage = pPage; - for(i=0; inCell; i++){ - Cell *pCell = pPage->apCell[i]; - int sz; - - /* Check payload overflow pages - */ - nKey2 = NKEY(pBt, pCell->h); - sz = nKey2 + NDATA(pBt, pCell->h); - sprintf(zContext, "On page %d cell %d: ", iPage, i); - if( sz>MX_LOCAL_PAYLOAD ){ - int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE; - checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext); - } - - /* Check that keys are in the right order - */ - cur.idx = i; - zKey2 = sqliteMallocRaw( nKey2+1 ); - getPayload(&cur, 0, nKey2, zKey2); - if( zKey1 && keyCompare(zKey1, nKey1, zKey2, nKey2)>=0 ){ - checkAppendMsg(pCheck, zContext, "Key is out of order"); - } - - /* Check sanity of left child page. - */ - pgno = SWAB32(pBt, pCell->h.leftChild); - d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zKey2,nKey2); - if( i>0 && d2!=depth ){ - checkAppendMsg(pCheck, zContext, "Child page depth differs"); - } - depth = d2; - sqliteFree(zKey1); - zKey1 = zKey2; - nKey1 = nKey2; - } - pgno = SWAB32(pBt, pPage->u.hdr.rightChild); - sprintf(zContext, "On page %d at right child: ", iPage); - checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zUpperBound,nUpper); - sqliteFree(zKey1); - - /* Check for complete coverage of the page - */ - memset(hit, 0, sizeof(hit)); - memset(hit, 1, sizeof(PageHdr)); - for(i=SWAB16(pBt, pPage->u.hdr.firstCell); i>0 && iu.aDisk[i]; - int j; - for(j=i+cellSize(pBt, pCell)-1; j>=i; j--) hit[j]++; - i = SWAB16(pBt, pCell->h.iNext); - } - for(i=SWAB16(pBt,pPage->u.hdr.firstFree); i>0 && iu.aDisk[i]; - int j; - for(j=i+SWAB16(pBt,pFBlk->iSize)-1; j>=i; j--) hit[j]++; - i = SWAB16(pBt,pFBlk->iNext); - } - for(i=0; i1 ){ - sprintf(zMsg, "Multiple uses for byte %d of page %d", i, iPage); - checkAppendMsg(pCheck, zMsg, 0); - break; - } - } - - /* Check that free space is kept to a minimum - */ -#if 0 - if( pParent && pParent->nCell>2 && pPage->nFree>3*SQLITE_USABLE_SIZE/4 ){ - sprintf(zMsg, "free space (%d) greater than max (%d)", pPage->nFree, - SQLITE_USABLE_SIZE/3); - checkAppendMsg(pCheck, zContext, zMsg); - } -#endif - - sqlitepager_unref(pPage); - return depth; -} - -/* -** This routine does a complete check of the given BTree file. aRoot[] is -** an array of pages numbers were each page number is the root page of -** a table. nRoot is the number of entries in aRoot. -** -** If everything checks out, this routine returns NULL. If something is -** amiss, an error message is written into memory obtained from malloc() -** and a pointer to that error message is returned. The calling function -** is responsible for freeing the error message when it is done. -*/ -char *fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ - int i; - int nRef; - IntegrityCk sCheck; - - nRef = *sqlitepager_stats(pBt->pPager); - if( lockBtree(pBt)!=SQLITE_OK ){ - return sqliteStrDup("Unable to acquire a read lock on the database"); - } - sCheck.pBt = pBt; - sCheck.pPager = pBt->pPager; - sCheck.nPage = sqlitepager_pagecount(sCheck.pPager); - if( sCheck.nPage==0 ){ - unlockBtreeIfUnused(pBt); - return 0; - } - sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); - sCheck.anRef[1] = 1; - for(i=2; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } - sCheck.zErrMsg = 0; - - /* Check the integrity of the freelist - */ - checkList(&sCheck, 1, SWAB32(pBt, pBt->page1->freeList), - SWAB32(pBt, pBt->page1->nFree), "Main freelist: "); - - /* Check all the tables. - */ - for(i=0; ipPager) ){ - char zBuf[100]; - sprintf(zBuf, - "Outstanding page count goes from %d to %d during this analysis", - nRef, *sqlitepager_stats(pBt->pPager) - ); - checkAppendMsg(&sCheck, zBuf, 0); - } - - /* Clean up and report errors. - */ - sqliteFree(sCheck.anRef); - return sCheck.zErrMsg; -} - -/* -** Return the full pathname of the underlying database file. -*/ -static const char *fileBtreeGetFilename(Btree *pBt){ - assert( pBt->pPager!=0 ); - return sqlitepager_filename(pBt->pPager); -} - -/* -** Copy the complete content of pBtFrom into pBtTo. A transaction -** must be active for both files. -** -** The size of file pBtFrom may be reduced by this operation. -** If anything goes wrong, the transaction on pBtFrom is rolled back. -*/ -static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ - int rc = SQLITE_OK; - Pgno i, nPage, nToPage; - - if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR; - if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR; - if( pBtTo->pCursor ) return SQLITE_BUSY; - memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_USABLE_SIZE); - rc = sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1); - nToPage = sqlitepager_pagecount(pBtTo->pPager); - nPage = sqlitepager_pagecount(pBtFrom->pPager); - for(i=2; rc==SQLITE_OK && i<=nPage; i++){ - void *pPage; - rc = sqlitepager_get(pBtFrom->pPager, i, &pPage); - if( rc ) break; - rc = sqlitepager_overwrite(pBtTo->pPager, i, pPage); - if( rc ) break; - sqlitepager_unref(pPage); - } - for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ - void *pPage; - rc = sqlitepager_get(pBtTo->pPager, i, &pPage); - if( rc ) break; - rc = sqlitepager_write(pPage); - sqlitepager_unref(pPage); - sqlitepager_dont_write(pBtTo->pPager, i); - } - if( !rc && nPagepPager, nPage); - } - if( rc ){ - fileBtreeRollback(pBtTo); - } - return rc; -} - -/* -** The following tables contain pointers to all of the interface -** routines for this implementation of the B*Tree backend. To -** substitute a different implemention of the backend, one has merely -** to provide pointers to alternative functions in similar tables. -*/ -static BtOps sqliteBtreeOps = { - fileBtreeClose, - fileBtreeSetCacheSize, - fileBtreeSetSafetyLevel, - fileBtreeBeginTrans, - fileBtreeCommit, - fileBtreeRollback, - fileBtreeBeginCkpt, - fileBtreeCommitCkpt, - fileBtreeRollbackCkpt, - fileBtreeCreateTable, - fileBtreeCreateTable, /* Really sqliteBtreeCreateIndex() */ - fileBtreeDropTable, - fileBtreeClearTable, - fileBtreeCursor, - fileBtreeGetMeta, - fileBtreeUpdateMeta, - fileBtreeIntegrityCheck, - fileBtreeGetFilename, - fileBtreeCopyFile, - fileBtreePager, -#ifdef SQLITE_TEST - fileBtreePageDump, -#endif -}; -static BtCursorOps sqliteBtreeCursorOps = { - fileBtreeMoveto, - fileBtreeDelete, - fileBtreeInsert, - fileBtreeFirst, - fileBtreeLast, - fileBtreeNext, - fileBtreePrevious, - fileBtreeKeySize, - fileBtreeKey, - fileBtreeKeyCompare, - fileBtreeDataSize, - fileBtreeData, - fileBtreeCloseCursor, -#ifdef SQLITE_TEST - fileBtreeCursorDump, -#endif -}; diff --git a/dbLifeLog/DBD-SQLite2-0.33/btree.h b/dbLifeLog/DBD-SQLite2-0.33/btree.h deleted file mode 100644 index 8f3fd1a..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/btree.h +++ /dev/null @@ -1,156 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the sqlite B-Tree file -** subsystem. See comments in the source code for a detailed description -** of what each interface routine does. -** -** @(#) $Id: btree.h,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ -#ifndef _BTREE_H_ -#define _BTREE_H_ - -/* -** Forward declarations of structure -*/ -typedef struct Btree Btree; -typedef struct BtCursor BtCursor; -typedef struct BtOps BtOps; -typedef struct BtCursorOps BtCursorOps; - - -/* -** An instance of the following structure contains pointers to all -** methods against an open BTree. Alternative BTree implementations -** (examples: file based versus in-memory) can be created by substituting -** different methods. Users of the BTree cannot tell the difference. -** -** In C++ we could do this by defining a virtual base class and then -** creating subclasses for each different implementation. But this is -** C not C++ so we have to be a little more explicit. -*/ -struct BtOps { - int (*Close)(Btree*); - int (*SetCacheSize)(Btree*, int); - int (*SetSafetyLevel)(Btree*, int); - int (*BeginTrans)(Btree*); - int (*Commit)(Btree*); - int (*Rollback)(Btree*); - int (*BeginCkpt)(Btree*); - int (*CommitCkpt)(Btree*); - int (*RollbackCkpt)(Btree*); - int (*CreateTable)(Btree*, int*); - int (*CreateIndex)(Btree*, int*); - int (*DropTable)(Btree*, int); - int (*ClearTable)(Btree*, int); - int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur); - int (*GetMeta)(Btree*, int*); - int (*UpdateMeta)(Btree*, int*); - char *(*IntegrityCheck)(Btree*, int*, int); - const char *(*GetFilename)(Btree*); - int (*Copyfile)(Btree*,Btree*); - struct Pager *(*Pager)(Btree*); -#ifdef SQLITE_TEST - int (*PageDump)(Btree*, int, int); -#endif -}; - -/* -** An instance of this structure defines all of the methods that can -** be executed against a cursor. -*/ -struct BtCursorOps { - int (*Moveto)(BtCursor*, const void *pKey, int nKey, int *pRes); - int (*Delete)(BtCursor*); - int (*Insert)(BtCursor*, const void *pKey, int nKey, - const void *pData, int nData); - int (*First)(BtCursor*, int *pRes); - int (*Last)(BtCursor*, int *pRes); - int (*Next)(BtCursor*, int *pRes); - int (*Previous)(BtCursor*, int *pRes); - int (*KeySize)(BtCursor*, int *pSize); - int (*Key)(BtCursor*, int offset, int amt, char *zBuf); - int (*KeyCompare)(BtCursor*, const void *pKey, int nKey, - int nIgnore, int *pRes); - int (*DataSize)(BtCursor*, int *pSize); - int (*Data)(BtCursor*, int offset, int amt, char *zBuf); - int (*CloseCursor)(BtCursor*); -#ifdef SQLITE_TEST - int (*CursorDump)(BtCursor*, int*); -#endif -}; - -/* -** The number of 4-byte "meta" values contained on the first page of each -** database file. -*/ -#define SQLITE_N_BTREE_META 10 - -int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); -int sqliteRbtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); - -#define btOps(pBt) (*((BtOps **)(pBt))) -#define btCOps(pCur) (*((BtCursorOps **)(pCur))) - -#define sqliteBtreeClose(pBt) (btOps(pBt)->Close(pBt)) -#define sqliteBtreeSetCacheSize(pBt, sz) (btOps(pBt)->SetCacheSize(pBt, sz)) -#define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl)) -#define sqliteBtreeBeginTrans(pBt) (btOps(pBt)->BeginTrans(pBt)) -#define sqliteBtreeCommit(pBt) (btOps(pBt)->Commit(pBt)) -#define sqliteBtreeRollback(pBt) (btOps(pBt)->Rollback(pBt)) -#define sqliteBtreeBeginCkpt(pBt) (btOps(pBt)->BeginCkpt(pBt)) -#define sqliteBtreeCommitCkpt(pBt) (btOps(pBt)->CommitCkpt(pBt)) -#define sqliteBtreeRollbackCkpt(pBt) (btOps(pBt)->RollbackCkpt(pBt)) -#define sqliteBtreeCreateTable(pBt,piTable)\ - (btOps(pBt)->CreateTable(pBt,piTable)) -#define sqliteBtreeCreateIndex(pBt, piIndex)\ - (btOps(pBt)->CreateIndex(pBt, piIndex)) -#define sqliteBtreeDropTable(pBt, iTable) (btOps(pBt)->DropTable(pBt, iTable)) -#define sqliteBtreeClearTable(pBt, iTable)\ - (btOps(pBt)->ClearTable(pBt, iTable)) -#define sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur)\ - (btOps(pBt)->Cursor(pBt, iTable, wrFlag, ppCur)) -#define sqliteBtreeMoveto(pCur, pKey, nKey, pRes)\ - (btCOps(pCur)->Moveto(pCur, pKey, nKey, pRes)) -#define sqliteBtreeDelete(pCur) (btCOps(pCur)->Delete(pCur)) -#define sqliteBtreeInsert(pCur, pKey, nKey, pData, nData) \ - (btCOps(pCur)->Insert(pCur, pKey, nKey, pData, nData)) -#define sqliteBtreeFirst(pCur, pRes) (btCOps(pCur)->First(pCur, pRes)) -#define sqliteBtreeLast(pCur, pRes) (btCOps(pCur)->Last(pCur, pRes)) -#define sqliteBtreeNext(pCur, pRes) (btCOps(pCur)->Next(pCur, pRes)) -#define sqliteBtreePrevious(pCur, pRes) (btCOps(pCur)->Previous(pCur, pRes)) -#define sqliteBtreeKeySize(pCur, pSize) (btCOps(pCur)->KeySize(pCur, pSize) ) -#define sqliteBtreeKey(pCur, offset, amt, zBuf)\ - (btCOps(pCur)->Key(pCur, offset, amt, zBuf)) -#define sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes)\ - (btCOps(pCur)->KeyCompare(pCur, pKey, nKey, nIgnore, pRes)) -#define sqliteBtreeDataSize(pCur, pSize) (btCOps(pCur)->DataSize(pCur, pSize)) -#define sqliteBtreeData(pCur, offset, amt, zBuf)\ - (btCOps(pCur)->Data(pCur, offset, amt, zBuf)) -#define sqliteBtreeCloseCursor(pCur) (btCOps(pCur)->CloseCursor(pCur)) -#define sqliteBtreeGetMeta(pBt, aMeta) (btOps(pBt)->GetMeta(pBt, aMeta)) -#define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta)) -#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\ - (btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot)) -#define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt)) -#define sqliteBtreeCopyFile(pBt1, pBt2) (btOps(pBt1)->Copyfile(pBt1, pBt2)) -#define sqliteBtreePager(pBt) (btOps(pBt)->Pager(pBt)) - -#ifdef SQLITE_TEST -#define sqliteBtreePageDump(pBt, pgno, recursive)\ - (btOps(pBt)->PageDump(pBt, pgno, recursive)) -#define sqliteBtreeCursorDump(pCur, aResult)\ - (btCOps(pCur)->CursorDump(pCur, aResult)) -int btree_native_byte_order; -#endif /* SQLITE_TEST */ - - -#endif /* _BTREE_H_ */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/btree.o b/dbLifeLog/DBD-SQLite2-0.33/btree.o deleted file mode 100644 index 941f5cb3588c15cc7e594ad391b89261daf358dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43248 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 O - -/* -** Omit this whole file if the SQLITE_OMIT_INMEMORYDB macro is -** defined. This allows a lot of code to be omitted for installations -** that do not need it. -*/ -#ifndef SQLITE_OMIT_INMEMORYDB - - -typedef struct BtRbTree BtRbTree; -typedef struct BtRbNode BtRbNode; -typedef struct BtRollbackOp BtRollbackOp; -typedef struct Rbtree Rbtree; -typedef struct RbtCursor RbtCursor; - -/* Forward declarations */ -static BtOps sqliteRbtreeOps; -static BtCursorOps sqliteRbtreeCursorOps; - -/* - * During each transaction (or checkpoint), a linked-list of - * "rollback-operations" is accumulated. If the transaction is rolled back, - * then the list of operations must be executed (to restore the database to - * it's state before the transaction started). If the transaction is to be - * committed, just delete the list. - * - * Each operation is represented as follows, depending on the value of eOp: - * - * ROLLBACK_INSERT -> Need to insert (pKey, pData) into table iTab. - * ROLLBACK_DELETE -> Need to delete the record (pKey) into table iTab. - * ROLLBACK_CREATE -> Need to create table iTab. - * ROLLBACK_DROP -> Need to drop table iTab. - */ -struct BtRollbackOp { - u8 eOp; - int iTab; - int nKey; - void *pKey; - int nData; - void *pData; - BtRollbackOp *pNext; -}; - -/* -** Legal values for BtRollbackOp.eOp: -*/ -#define ROLLBACK_INSERT 1 /* Insert a record */ -#define ROLLBACK_DELETE 2 /* Delete a record */ -#define ROLLBACK_CREATE 3 /* Create a table */ -#define ROLLBACK_DROP 4 /* Drop a table */ - -struct Rbtree { - BtOps *pOps; /* Function table */ - int aMetaData[SQLITE_N_BTREE_META]; - - int next_idx; /* next available table index */ - Hash tblHash; /* All created tables, by index */ - u8 isAnonymous; /* True if this Rbtree is to be deleted when closed */ - u8 eTransState; /* State of this Rbtree wrt transactions */ - - BtRollbackOp *pTransRollback; - BtRollbackOp *pCheckRollback; - BtRollbackOp *pCheckRollbackTail; -}; - -/* -** Legal values for Rbtree.eTransState. -*/ -#define TRANS_NONE 0 /* No transaction is in progress */ -#define TRANS_INTRANSACTION 1 /* A transaction is in progress */ -#define TRANS_INCHECKPOINT 2 /* A checkpoint is in progress */ -#define TRANS_ROLLBACK 3 /* We are currently rolling back a checkpoint or - * transaction. */ - -struct RbtCursor { - BtCursorOps *pOps; /* Function table */ - Rbtree *pRbtree; - BtRbTree *pTree; - int iTree; /* Index of pTree in pRbtree */ - BtRbNode *pNode; - RbtCursor *pShared; /* List of all cursors on the same Rbtree */ - u8 eSkip; /* Determines if next step operation is a no-op */ - u8 wrFlag; /* True if this cursor is open for writing */ -}; - -/* -** Legal values for RbtCursor.eSkip. -*/ -#define SKIP_NONE 0 /* Always step the cursor */ -#define SKIP_NEXT 1 /* The next sqliteRbtreeNext() is a no-op */ -#define SKIP_PREV 2 /* The next sqliteRbtreePrevious() is a no-op */ -#define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */ - -struct BtRbTree { - RbtCursor *pCursors; /* All cursors pointing to this tree */ - BtRbNode *pHead; /* Head of the tree, or NULL */ -}; - -struct BtRbNode { - int nKey; - void *pKey; - int nData; - void *pData; - u8 isBlack; /* true for a black node, 0 for a red node */ - BtRbNode *pParent; /* Nodes parent node, NULL for the tree head */ - BtRbNode *pLeft; /* Nodes left child, or NULL */ - BtRbNode *pRight; /* Nodes right child, or NULL */ - - int nBlackHeight; /* Only used during the red-black integrity check */ -}; - -/* Forward declarations */ -static int memRbtreeMoveto( - RbtCursor* pCur, - const void *pKey, - int nKey, - int *pRes -); -static int memRbtreeClearTable(Rbtree* tree, int n); -static int memRbtreeNext(RbtCursor* pCur, int *pRes); -static int memRbtreeLast(RbtCursor* pCur, int *pRes); -static int memRbtreePrevious(RbtCursor* pCur, int *pRes); - - -/* -** This routine checks all cursors that point to the same table -** as pCur points to. If any of those cursors were opened with -** wrFlag==0 then this routine returns SQLITE_LOCKED. If all -** cursors point to the same table were opened with wrFlag==1 -** then this routine returns SQLITE_OK. -** -** In addition to checking for read-locks (where a read-lock -** means a cursor opened with wrFlag==0) this routine also NULLs -** out the pNode field of all other cursors. -** This is necessary because an insert -** or delete might change erase the node out from under -** another cursor. -*/ -static int checkReadLocks(RbtCursor *pCur){ - RbtCursor *p; - assert( pCur->wrFlag ); - for(p=pCur->pTree->pCursors; p; p=p->pShared){ - if( p!=pCur ){ - if( p->wrFlag==0 ) return SQLITE_LOCKED; - p->pNode = 0; - } - } - return SQLITE_OK; -} - -/* - * The key-compare function for the red-black trees. Returns as follows: - * - * (key1 < key2) -1 - * (key1 == key2) 0 - * (key1 > key2) 1 - * - * Keys are compared using memcmp(). If one key is an exact prefix of the - * other, then the shorter key is less than the longer key. - */ -static int key_compare(void const*pKey1, int nKey1, void const*pKey2, int nKey2) -{ - int mcmp = memcmp(pKey1, pKey2, (nKey1 <= nKey2)?nKey1:nKey2); - if( mcmp == 0){ - if( nKey1 == nKey2 ) return 0; - return ((nKey1 < nKey2)?-1:1); - } - return ((mcmp>0)?1:-1); -} - -/* - * Perform the LEFT-rotate transformation on node X of tree pTree. This - * transform is part of the red-black balancing code. - * - * | | - * X Y - * / \ / \ - * a Y X c - * / \ / \ - * b c a b - * - * BEFORE AFTER - */ -static void leftRotate(BtRbTree *pTree, BtRbNode *pX) -{ - BtRbNode *pY; - BtRbNode *pb; - pY = pX->pRight; - pb = pY->pLeft; - - pY->pParent = pX->pParent; - if( pX->pParent ){ - if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY; - else pX->pParent->pRight = pY; - } - pY->pLeft = pX; - pX->pParent = pY; - pX->pRight = pb; - if( pb ) pb->pParent = pX; - if( pTree->pHead == pX ) pTree->pHead = pY; -} - -/* - * Perform the RIGHT-rotate transformation on node X of tree pTree. This - * transform is part of the red-black balancing code. - * - * | | - * X Y - * / \ / \ - * Y c a X - * / \ / \ - * a b b c - * - * BEFORE AFTER - */ -static void rightRotate(BtRbTree *pTree, BtRbNode *pX) -{ - BtRbNode *pY; - BtRbNode *pb; - pY = pX->pLeft; - pb = pY->pRight; - - pY->pParent = pX->pParent; - if( pX->pParent ){ - if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY; - else pX->pParent->pRight = pY; - } - pY->pRight = pX; - pX->pParent = pY; - pX->pLeft = pb; - if( pb ) pb->pParent = pX; - if( pTree->pHead == pX ) pTree->pHead = pY; -} - -/* - * A string-manipulation helper function for check_redblack_tree(). If (orig == - * NULL) a copy of val is returned. If (orig != NULL) then a copy of the * - * concatenation of orig and val is returned. The original orig is deleted - * (using sqliteFree()). - */ -static char *append_val(char * orig, char const * val){ - char *z; - if( !orig ){ - z = sqliteStrDup( val ); - } else{ - z = 0; - sqliteSetString(&z, orig, val, (char*)0); - sqliteFree( orig ); - } - return z; -} - -/* - * Append a string representation of the entire node to orig and return it. - * This is used to produce debugging information if check_redblack_tree() finds - * a problem with a red-black binary tree. - */ -static char *append_node(char * orig, BtRbNode *pNode, int indent) -{ - char buf[128]; - int i; - - for( i=0; iisBlack ){ - orig = append_val(orig, " B \n"); - }else{ - orig = append_val(orig, " R \n"); - } - orig = append_node( orig, pNode->pLeft, indent ); - orig = append_node( orig, pNode->pRight, indent ); - }else{ - orig = append_val(orig, "\n"); - } - return orig; -} - -/* - * Print a representation of a node to stdout. This function is only included - * so you can call it from within a debugger if things get really bad. It - * is not called from anyplace in the code. - */ -static void print_node(BtRbNode *pNode) -{ - char * str = append_node(0, pNode, 0); - printf("%s", str); - - /* Suppress a warning message about print_node() being unused */ - (void)print_node; -} - -/* - * Check the following properties of the red-black tree: - * (1) - If a node is red, both of it's children are black - * (2) - Each path from a given node to a leaf (NULL) node passes thru the - * same number of black nodes - * - * If there is a problem, append a description (using append_val() ) to *msg. - */ -static void check_redblack_tree(BtRbTree * tree, char ** msg) -{ - BtRbNode *pNode; - - /* 0 -> came from parent - * 1 -> came from left - * 2 -> came from right */ - int prev_step = 0; - - pNode = tree->pHead; - while( pNode ){ - switch( prev_step ){ - case 0: - if( pNode->pLeft ){ - pNode = pNode->pLeft; - }else{ - prev_step = 1; - } - break; - case 1: - if( pNode->pRight ){ - pNode = pNode->pRight; - prev_step = 0; - }else{ - prev_step = 2; - } - break; - case 2: - /* Check red-black property (1) */ - if( !pNode->isBlack && - ( (pNode->pLeft && !pNode->pLeft->isBlack) || - (pNode->pRight && !pNode->pRight->isBlack) ) - ){ - char buf[128]; - sprintf(buf, "Red node with red child at %p\n", pNode); - *msg = append_val(*msg, buf); - *msg = append_node(*msg, tree->pHead, 0); - *msg = append_val(*msg, "\n"); - } - - /* Check red-black property (2) */ - { - int leftHeight = 0; - int rightHeight = 0; - if( pNode->pLeft ){ - leftHeight += pNode->pLeft->nBlackHeight; - leftHeight += (pNode->pLeft->isBlack?1:0); - } - if( pNode->pRight ){ - rightHeight += pNode->pRight->nBlackHeight; - rightHeight += (pNode->pRight->isBlack?1:0); - } - if( leftHeight != rightHeight ){ - char buf[128]; - sprintf(buf, "Different black-heights at %p\n", pNode); - *msg = append_val(*msg, buf); - *msg = append_node(*msg, tree->pHead, 0); - *msg = append_val(*msg, "\n"); - } - pNode->nBlackHeight = leftHeight; - } - - if( pNode->pParent ){ - if( pNode == pNode->pParent->pLeft ) prev_step = 1; - else prev_step = 2; - } - pNode = pNode->pParent; - break; - default: assert(0); - } - } -} - -/* - * Node pX has just been inserted into pTree (by code in sqliteRbtreeInsert()). - * It is possible that pX is a red node with a red parent, which is a violation - * of the red-black tree properties. This function performs rotations and - * color changes to rebalance the tree - */ -static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX) -{ - /* In the first iteration of this loop, pX points to the red node just - * inserted in the tree. If the parent of pX exists (pX is not the root - * node) and is red, then the properties of the red-black tree are - * violated. - * - * At the start of any subsequent iterations, pX points to a red node - * with a red parent. In all other respects the tree is a legal red-black - * binary tree. */ - while( pX != pTree->pHead && !pX->pParent->isBlack ){ - BtRbNode *pUncle; - BtRbNode *pGrandparent; - - /* Grandparent of pX must exist and must be black. */ - pGrandparent = pX->pParent->pParent; - assert( pGrandparent ); - assert( pGrandparent->isBlack ); - - /* Uncle of pX may or may not exist. */ - if( pX->pParent == pGrandparent->pLeft ) - pUncle = pGrandparent->pRight; - else - pUncle = pGrandparent->pLeft; - - /* If the uncle of pX exists and is red, we do the following: - * | | - * G(b) G(r) - * / \ / \ - * U(r) P(r) U(b) P(b) - * \ \ - * X(r) X(r) - * - * BEFORE AFTER - * pX is then set to G. If the parent of G is red, then the while loop - * will run again. */ - if( pUncle && !pUncle->isBlack ){ - pGrandparent->isBlack = 0; - pUncle->isBlack = 1; - pX->pParent->isBlack = 1; - pX = pGrandparent; - }else{ - - if( pX->pParent == pGrandparent->pLeft ){ - if( pX == pX->pParent->pRight ){ - /* If pX is a right-child, do the following transform, essentially - * to change pX into a left-child: - * | | - * G(b) G(b) - * / \ / \ - * P(r) U(b) X(r) U(b) - * \ / - * X(r) P(r) <-- new X - * - * BEFORE AFTER - */ - pX = pX->pParent; - leftRotate(pTree, pX); - } - - /* Do the following transform, which balances the tree :) - * | | - * G(b) P(b) - * / \ / \ - * P(r) U(b) X(r) G(r) - * / \ - * X(r) U(b) - * - * BEFORE AFTER - */ - assert( pGrandparent == pX->pParent->pParent ); - pGrandparent->isBlack = 0; - pX->pParent->isBlack = 1; - rightRotate( pTree, pGrandparent ); - - }else{ - /* This code is symetric to the illustrated case above. */ - if( pX == pX->pParent->pLeft ){ - pX = pX->pParent; - rightRotate(pTree, pX); - } - assert( pGrandparent == pX->pParent->pParent ); - pGrandparent->isBlack = 0; - pX->pParent->isBlack = 1; - leftRotate( pTree, pGrandparent ); - } - } - } - pTree->pHead->isBlack = 1; -} - -/* - * A child of pParent, which in turn had child pX, has just been removed from - * pTree (the figure below depicts the operation, Z is being removed). pParent - * or pX, or both may be NULL. - * | | - * P P - * / \ / \ - * Z X - * / \ - * X nil - * - * This function is only called if Z was black. In this case the red-black tree - * properties have been violated, and pX has an "extra black". This function - * performs rotations and color-changes to re-balance the tree. - */ -static -void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent) -{ - BtRbNode *pSib; - - /* TODO: Comment this code! */ - while( pX != pTree->pHead && (!pX || pX->isBlack) ){ - if( pX == pParent->pLeft ){ - pSib = pParent->pRight; - if( pSib && !(pSib->isBlack) ){ - pSib->isBlack = 1; - pParent->isBlack = 0; - leftRotate(pTree, pParent); - pSib = pParent->pRight; - } - if( !pSib ){ - pX = pParent; - }else if( - (!pSib->pLeft || pSib->pLeft->isBlack) && - (!pSib->pRight || pSib->pRight->isBlack) ) { - pSib->isBlack = 0; - pX = pParent; - }else{ - if( (!pSib->pRight || pSib->pRight->isBlack) ){ - if( pSib->pLeft ) pSib->pLeft->isBlack = 1; - pSib->isBlack = 0; - rightRotate( pTree, pSib ); - pSib = pParent->pRight; - } - pSib->isBlack = pParent->isBlack; - pParent->isBlack = 1; - if( pSib->pRight ) pSib->pRight->isBlack = 1; - leftRotate(pTree, pParent); - pX = pTree->pHead; - } - }else{ - pSib = pParent->pLeft; - if( pSib && !(pSib->isBlack) ){ - pSib->isBlack = 1; - pParent->isBlack = 0; - rightRotate(pTree, pParent); - pSib = pParent->pLeft; - } - if( !pSib ){ - pX = pParent; - }else if( - (!pSib->pLeft || pSib->pLeft->isBlack) && - (!pSib->pRight || pSib->pRight->isBlack) ){ - pSib->isBlack = 0; - pX = pParent; - }else{ - if( (!pSib->pLeft || pSib->pLeft->isBlack) ){ - if( pSib->pRight ) pSib->pRight->isBlack = 1; - pSib->isBlack = 0; - leftRotate( pTree, pSib ); - pSib = pParent->pLeft; - } - pSib->isBlack = pParent->isBlack; - pParent->isBlack = 1; - if( pSib->pLeft ) pSib->pLeft->isBlack = 1; - rightRotate(pTree, pParent); - pX = pTree->pHead; - } - } - pParent = pX->pParent; - } - if( pX ) pX->isBlack = 1; -} - -/* - * Create table n in tree pRbtree. Table n must not exist. - */ -static void btreeCreateTable(Rbtree* pRbtree, int n) -{ - BtRbTree *pNewTbl = sqliteMalloc(sizeof(BtRbTree)); - sqliteHashInsert(&pRbtree->tblHash, 0, n, pNewTbl); -} - -/* - * Log a single "rollback-op" for the given Rbtree. See comments for struct - * BtRollbackOp. - */ -static void btreeLogRollbackOp(Rbtree* pRbtree, BtRollbackOp *pRollbackOp) -{ - assert( pRbtree->eTransState == TRANS_INCHECKPOINT || - pRbtree->eTransState == TRANS_INTRANSACTION ); - if( pRbtree->eTransState == TRANS_INTRANSACTION ){ - pRollbackOp->pNext = pRbtree->pTransRollback; - pRbtree->pTransRollback = pRollbackOp; - } - if( pRbtree->eTransState == TRANS_INCHECKPOINT ){ - if( !pRbtree->pCheckRollback ){ - pRbtree->pCheckRollbackTail = pRollbackOp; - } - pRollbackOp->pNext = pRbtree->pCheckRollback; - pRbtree->pCheckRollback = pRollbackOp; - } -} - -int sqliteRbtreeOpen( - const char *zFilename, - int mode, - int nPg, - Btree **ppBtree -){ - Rbtree **ppRbtree = (Rbtree**)ppBtree; - *ppRbtree = (Rbtree *)sqliteMalloc(sizeof(Rbtree)); - if( sqlite_malloc_failed ) goto open_no_mem; - sqliteHashInit(&(*ppRbtree)->tblHash, SQLITE_HASH_INT, 0); - - /* Create a binary tree for the SQLITE_MASTER table at location 2 */ - btreeCreateTable(*ppRbtree, 2); - if( sqlite_malloc_failed ) goto open_no_mem; - (*ppRbtree)->next_idx = 3; - (*ppRbtree)->pOps = &sqliteRbtreeOps; - /* Set file type to 4; this is so that "attach ':memory:' as ...." does not - ** think that the database in uninitialised and refuse to attach - */ - (*ppRbtree)->aMetaData[2] = 4; - - return SQLITE_OK; - -open_no_mem: - *ppBtree = 0; - return SQLITE_NOMEM; -} - -/* - * Create a new table in the supplied Rbtree. Set *n to the new table number. - * Return SQLITE_OK if the operation is a success. - */ -static int memRbtreeCreateTable(Rbtree* tree, int* n) -{ - assert( tree->eTransState != TRANS_NONE ); - - *n = tree->next_idx++; - btreeCreateTable(tree, *n); - if( sqlite_malloc_failed ) return SQLITE_NOMEM; - - /* Set up the rollback structure (if we are not doing this as part of a - * rollback) */ - if( tree->eTransState != TRANS_ROLLBACK ){ - BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp)); - if( pRollbackOp==0 ) return SQLITE_NOMEM; - pRollbackOp->eOp = ROLLBACK_DROP; - pRollbackOp->iTab = *n; - btreeLogRollbackOp(tree, pRollbackOp); - } - - return SQLITE_OK; -} - -/* - * Delete table n from the supplied Rbtree. - */ -static int memRbtreeDropTable(Rbtree* tree, int n) -{ - BtRbTree *pTree; - assert( tree->eTransState != TRANS_NONE ); - - memRbtreeClearTable(tree, n); - pTree = sqliteHashInsert(&tree->tblHash, 0, n, 0); - assert(pTree); - assert( pTree->pCursors==0 ); - sqliteFree(pTree); - - if( tree->eTransState != TRANS_ROLLBACK ){ - BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp)); - if( pRollbackOp==0 ) return SQLITE_NOMEM; - pRollbackOp->eOp = ROLLBACK_CREATE; - pRollbackOp->iTab = n; - btreeLogRollbackOp(tree, pRollbackOp); - } - - return SQLITE_OK; -} - -static int memRbtreeKeyCompare(RbtCursor* pCur, const void *pKey, int nKey, - int nIgnore, int *pRes) -{ - assert(pCur); - - if( !pCur->pNode ) { - *pRes = -1; - } else { - if( (pCur->pNode->nKey - nIgnore) < 0 ){ - *pRes = -1; - }else{ - *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore, - pKey, nKey); - } - } - return SQLITE_OK; -} - -/* - * Get a new cursor for table iTable of the supplied Rbtree. The wrFlag - * parameter indicates that the cursor is open for writing. - * - * Note that RbtCursor.eSkip and RbtCursor.pNode both initialize to 0. - */ -static int memRbtreeCursor( - Rbtree* tree, - int iTable, - int wrFlag, - RbtCursor **ppCur -){ - RbtCursor *pCur; - assert(tree); - pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor)); - if( sqlite_malloc_failed ) return SQLITE_NOMEM; - pCur->pTree = sqliteHashFind(&tree->tblHash, 0, iTable); - assert( pCur->pTree ); - pCur->pRbtree = tree; - pCur->iTree = iTable; - pCur->pOps = &sqliteRbtreeCursorOps; - pCur->wrFlag = wrFlag; - pCur->pShared = pCur->pTree->pCursors; - pCur->pTree->pCursors = pCur; - - assert( (*ppCur)->pTree ); - return SQLITE_OK; -} - -/* - * Insert a new record into the Rbtree. The key is given by (pKey,nKey) - * and the data is given by (pData,nData). The cursor is used only to - * define what database the record should be inserted into. The cursor - * is left pointing at the new record. - * - * If the key exists already in the tree, just replace the data. - */ -static int memRbtreeInsert( - RbtCursor* pCur, - const void *pKey, - int nKey, - const void *pDataInput, - int nData -){ - void * pData; - int match; - - /* It is illegal to call sqliteRbtreeInsert() if we are - ** not in a transaction */ - assert( pCur->pRbtree->eTransState != TRANS_NONE ); - - /* Make sure some other cursor isn't trying to read this same table */ - if( checkReadLocks(pCur) ){ - return SQLITE_LOCKED; /* The table pCur points to has a read lock */ - } - - /* Take a copy of the input data now, in case we need it for the - * replace case */ - pData = sqliteMallocRaw(nData); - if( sqlite_malloc_failed ) return SQLITE_NOMEM; - memcpy(pData, pDataInput, nData); - - /* Move the cursor to a node near the key to be inserted. If the key already - * exists in the table, then (match == 0). In this case we can just replace - * the data associated with the entry, we don't need to manipulate the tree. - * - * If there is no exact match, then the cursor points at what would be either - * the predecessor (match == -1) or successor (match == 1) of the - * searched-for key, were it to be inserted. The new node becomes a child of - * this node. - * - * The new node is initially red. - */ - memRbtreeMoveto( pCur, pKey, nKey, &match); - if( match ){ - BtRbNode *pNode = sqliteMalloc(sizeof(BtRbNode)); - if( pNode==0 ) return SQLITE_NOMEM; - pNode->nKey = nKey; - pNode->pKey = sqliteMallocRaw(nKey); - if( sqlite_malloc_failed ) return SQLITE_NOMEM; - memcpy(pNode->pKey, pKey, nKey); - pNode->nData = nData; - pNode->pData = pData; - if( pCur->pNode ){ - switch( match ){ - case -1: - assert( !pCur->pNode->pRight ); - pNode->pParent = pCur->pNode; - pCur->pNode->pRight = pNode; - break; - case 1: - assert( !pCur->pNode->pLeft ); - pNode->pParent = pCur->pNode; - pCur->pNode->pLeft = pNode; - break; - default: - assert(0); - } - }else{ - pCur->pTree->pHead = pNode; - } - - /* Point the cursor at the node just inserted, as per SQLite requirements */ - pCur->pNode = pNode; - - /* A new node has just been inserted, so run the balancing code */ - do_insert_balancing(pCur->pTree, pNode); - - /* Set up a rollback-op in case we have to roll this operation back */ - if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){ - BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) ); - if( pOp==0 ) return SQLITE_NOMEM; - pOp->eOp = ROLLBACK_DELETE; - pOp->iTab = pCur->iTree; - pOp->nKey = pNode->nKey; - pOp->pKey = sqliteMallocRaw( pOp->nKey ); - if( sqlite_malloc_failed ) return SQLITE_NOMEM; - memcpy( pOp->pKey, pNode->pKey, pOp->nKey ); - btreeLogRollbackOp(pCur->pRbtree, pOp); - } - - }else{ - /* No need to insert a new node in the tree, as the key already exists. - * Just clobber the current nodes data. */ - - /* Set up a rollback-op in case we have to roll this operation back */ - if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){ - BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) ); - if( pOp==0 ) return SQLITE_NOMEM; - pOp->iTab = pCur->iTree; - pOp->nKey = pCur->pNode->nKey; - pOp->pKey = sqliteMallocRaw( pOp->nKey ); - if( sqlite_malloc_failed ) return SQLITE_NOMEM; - memcpy( pOp->pKey, pCur->pNode->pKey, pOp->nKey ); - pOp->nData = pCur->pNode->nData; - pOp->pData = pCur->pNode->pData; - pOp->eOp = ROLLBACK_INSERT; - btreeLogRollbackOp(pCur->pRbtree, pOp); - }else{ - sqliteFree( pCur->pNode->pData ); - } - - /* Actually clobber the nodes data */ - pCur->pNode->pData = pData; - pCur->pNode->nData = nData; - } - - return SQLITE_OK; -} - -/* Move the cursor so that it points to an entry near pKey. -** Return a success code. -** -** *pRes<0 The cursor is left pointing at an entry that -** is smaller than pKey or if the table is empty -** and the cursor is therefore left point to nothing. -** -** *pRes==0 The cursor is left pointing at an entry that -** exactly matches pKey. -** -** *pRes>0 The cursor is left pointing at an entry that -** is larger than pKey. -*/ -static int memRbtreeMoveto( - RbtCursor* pCur, - const void *pKey, - int nKey, - int *pRes -){ - BtRbNode *pTmp = 0; - - pCur->pNode = pCur->pTree->pHead; - *pRes = -1; - while( pCur->pNode && *pRes ) { - *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey, pKey, nKey); - pTmp = pCur->pNode; - switch( *pRes ){ - case 1: /* cursor > key */ - pCur->pNode = pCur->pNode->pLeft; - break; - case -1: /* cursor < key */ - pCur->pNode = pCur->pNode->pRight; - break; - } - } - - /* If (pCur->pNode == NULL), then we have failed to find a match. Set - * pCur->pNode to pTmp, which is either NULL (if the tree is empty) or the - * last node traversed in the search. In either case the relation ship - * between pTmp and the searched for key is already stored in *pRes. pTmp is - * either the successor or predecessor of the key we tried to move to. */ - if( !pCur->pNode ) pCur->pNode = pTmp; - pCur->eSkip = SKIP_NONE; - - return SQLITE_OK; -} - - -/* -** Delete the entry that the cursor is pointing to. -** -** The cursor is left pointing at either the next or the previous -** entry. If the cursor is left pointing to the next entry, then -** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to -** sqliteRbtreeNext() to be a no-op. That way, you can always call -** sqliteRbtreeNext() after a delete and the cursor will be left -** pointing to the first entry after the deleted entry. Similarly, -** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to -** the entry prior to the deleted entry so that a subsequent call to -** sqliteRbtreePrevious() will always leave the cursor pointing at the -** entry immediately before the one that was deleted. -*/ -static int memRbtreeDelete(RbtCursor* pCur) -{ - BtRbNode *pZ; /* The one being deleted */ - BtRbNode *pChild; /* The child of the spliced out node */ - - /* It is illegal to call sqliteRbtreeDelete() if we are - ** not in a transaction */ - assert( pCur->pRbtree->eTransState != TRANS_NONE ); - - /* Make sure some other cursor isn't trying to read this same table */ - if( checkReadLocks(pCur) ){ - return SQLITE_LOCKED; /* The table pCur points to has a read lock */ - } - - pZ = pCur->pNode; - if( !pZ ){ - return SQLITE_OK; - } - - /* If we are not currently doing a rollback, set up a rollback op for this - * deletion */ - if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){ - BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) ); - if( pOp==0 ) return SQLITE_NOMEM; - pOp->iTab = pCur->iTree; - pOp->nKey = pZ->nKey; - pOp->pKey = pZ->pKey; - pOp->nData = pZ->nData; - pOp->pData = pZ->pData; - pOp->eOp = ROLLBACK_INSERT; - btreeLogRollbackOp(pCur->pRbtree, pOp); - } - - /* First do a standard binary-tree delete (node pZ is to be deleted). How - * to do this depends on how many children pZ has: - * - * If pZ has no children or one child, then splice out pZ. If pZ has two - * children, splice out the successor of pZ and replace the key and data of - * pZ with the key and data of the spliced out successor. */ - if( pZ->pLeft && pZ->pRight ){ - BtRbNode *pTmp; - int dummy; - pCur->eSkip = SKIP_NONE; - memRbtreeNext(pCur, &dummy); - assert( dummy == 0 ); - if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){ - sqliteFree(pZ->pKey); - sqliteFree(pZ->pData); - } - pZ->pData = pCur->pNode->pData; - pZ->nData = pCur->pNode->nData; - pZ->pKey = pCur->pNode->pKey; - pZ->nKey = pCur->pNode->nKey; - pTmp = pZ; - pZ = pCur->pNode; - pCur->pNode = pTmp; - pCur->eSkip = SKIP_NEXT; - }else{ - int res; - pCur->eSkip = SKIP_NONE; - memRbtreeNext(pCur, &res); - pCur->eSkip = SKIP_NEXT; - if( res ){ - memRbtreeLast(pCur, &res); - memRbtreePrevious(pCur, &res); - pCur->eSkip = SKIP_PREV; - } - if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){ - sqliteFree(pZ->pKey); - sqliteFree(pZ->pData); - } - } - - /* pZ now points at the node to be spliced out. This block does the - * splicing. */ - { - BtRbNode **ppParentSlot = 0; - assert( !pZ->pLeft || !pZ->pRight ); /* pZ has at most one child */ - pChild = ((pZ->pLeft)?pZ->pLeft:pZ->pRight); - if( pZ->pParent ){ - assert( pZ == pZ->pParent->pLeft || pZ == pZ->pParent->pRight ); - ppParentSlot = ((pZ == pZ->pParent->pLeft) - ?&pZ->pParent->pLeft:&pZ->pParent->pRight); - *ppParentSlot = pChild; - }else{ - pCur->pTree->pHead = pChild; - } - if( pChild ) pChild->pParent = pZ->pParent; - } - - /* pZ now points at the spliced out node. pChild is the only child of pZ, or - * NULL if pZ has no children. If pZ is black, and not the tree root, then we - * will have violated the "same number of black nodes in every path to a - * leaf" property of the red-black tree. The code in do_delete_balancing() - * repairs this. */ - if( pZ->isBlack ){ - do_delete_balancing(pCur->pTree, pChild, pZ->pParent); - } - - sqliteFree(pZ); - return SQLITE_OK; -} - -/* - * Empty table n of the Rbtree. - */ -static int memRbtreeClearTable(Rbtree* tree, int n) -{ - BtRbTree *pTree; - BtRbNode *pNode; - - pTree = sqliteHashFind(&tree->tblHash, 0, n); - assert(pTree); - - pNode = pTree->pHead; - while( pNode ){ - if( pNode->pLeft ){ - pNode = pNode->pLeft; - } - else if( pNode->pRight ){ - pNode = pNode->pRight; - } - else { - BtRbNode *pTmp = pNode->pParent; - if( tree->eTransState == TRANS_ROLLBACK ){ - sqliteFree( pNode->pKey ); - sqliteFree( pNode->pData ); - }else{ - BtRollbackOp *pRollbackOp = sqliteMallocRaw(sizeof(BtRollbackOp)); - if( pRollbackOp==0 ) return SQLITE_NOMEM; - pRollbackOp->eOp = ROLLBACK_INSERT; - pRollbackOp->iTab = n; - pRollbackOp->nKey = pNode->nKey; - pRollbackOp->pKey = pNode->pKey; - pRollbackOp->nData = pNode->nData; - pRollbackOp->pData = pNode->pData; - btreeLogRollbackOp(tree, pRollbackOp); - } - sqliteFree( pNode ); - if( pTmp ){ - if( pTmp->pLeft == pNode ) pTmp->pLeft = 0; - else if( pTmp->pRight == pNode ) pTmp->pRight = 0; - } - pNode = pTmp; - } - } - - pTree->pHead = 0; - return SQLITE_OK; -} - -static int memRbtreeFirst(RbtCursor* pCur, int *pRes) -{ - if( pCur->pTree->pHead ){ - pCur->pNode = pCur->pTree->pHead; - while( pCur->pNode->pLeft ){ - pCur->pNode = pCur->pNode->pLeft; - } - } - if( pCur->pNode ){ - *pRes = 0; - }else{ - *pRes = 1; - } - pCur->eSkip = SKIP_NONE; - return SQLITE_OK; -} - -static int memRbtreeLast(RbtCursor* pCur, int *pRes) -{ - if( pCur->pTree->pHead ){ - pCur->pNode = pCur->pTree->pHead; - while( pCur->pNode->pRight ){ - pCur->pNode = pCur->pNode->pRight; - } - } - if( pCur->pNode ){ - *pRes = 0; - }else{ - *pRes = 1; - } - pCur->eSkip = SKIP_NONE; - return SQLITE_OK; -} - -/* -** Advance the cursor to the next entry in the database. If -** successful then set *pRes=0. If the cursor -** was already pointing to the last entry in the database before -** this routine was called, then set *pRes=1. -*/ -static int memRbtreeNext(RbtCursor* pCur, int *pRes) -{ - if( pCur->pNode && pCur->eSkip != SKIP_NEXT ){ - if( pCur->pNode->pRight ){ - pCur->pNode = pCur->pNode->pRight; - while( pCur->pNode->pLeft ) - pCur->pNode = pCur->pNode->pLeft; - }else{ - BtRbNode * pX = pCur->pNode; - pCur->pNode = pX->pParent; - while( pCur->pNode && (pCur->pNode->pRight == pX) ){ - pX = pCur->pNode; - pCur->pNode = pX->pParent; - } - } - } - pCur->eSkip = SKIP_NONE; - - if( !pCur->pNode ){ - *pRes = 1; - }else{ - *pRes = 0; - } - - return SQLITE_OK; -} - -static int memRbtreePrevious(RbtCursor* pCur, int *pRes) -{ - if( pCur->pNode && pCur->eSkip != SKIP_PREV ){ - if( pCur->pNode->pLeft ){ - pCur->pNode = pCur->pNode->pLeft; - while( pCur->pNode->pRight ) - pCur->pNode = pCur->pNode->pRight; - }else{ - BtRbNode * pX = pCur->pNode; - pCur->pNode = pX->pParent; - while( pCur->pNode && (pCur->pNode->pLeft == pX) ){ - pX = pCur->pNode; - pCur->pNode = pX->pParent; - } - } - } - pCur->eSkip = SKIP_NONE; - - if( !pCur->pNode ){ - *pRes = 1; - }else{ - *pRes = 0; - } - - return SQLITE_OK; -} - -static int memRbtreeKeySize(RbtCursor* pCur, int *pSize) -{ - if( pCur->pNode ){ - *pSize = pCur->pNode->nKey; - }else{ - *pSize = 0; - } - return SQLITE_OK; -} - -static int memRbtreeKey(RbtCursor* pCur, int offset, int amt, char *zBuf) -{ - if( !pCur->pNode ) return 0; - if( !pCur->pNode->pKey || ((amt + offset) <= pCur->pNode->nKey) ){ - memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, amt); - }else{ - memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, pCur->pNode->nKey-offset); - amt = pCur->pNode->nKey-offset; - } - return amt; -} - -static int memRbtreeDataSize(RbtCursor* pCur, int *pSize) -{ - if( pCur->pNode ){ - *pSize = pCur->pNode->nData; - }else{ - *pSize = 0; - } - return SQLITE_OK; -} - -static int memRbtreeData(RbtCursor *pCur, int offset, int amt, char *zBuf) -{ - if( !pCur->pNode ) return 0; - if( (amt + offset) <= pCur->pNode->nData ){ - memcpy(zBuf, ((char*)pCur->pNode->pData)+offset, amt); - }else{ - memcpy(zBuf, ((char*)pCur->pNode->pData)+offset ,pCur->pNode->nData-offset); - amt = pCur->pNode->nData-offset; - } - return amt; -} - -static int memRbtreeCloseCursor(RbtCursor* pCur) -{ - if( pCur->pTree->pCursors==pCur ){ - pCur->pTree->pCursors = pCur->pShared; - }else{ - RbtCursor *p = pCur->pTree->pCursors; - while( p && p->pShared!=pCur ){ p = p->pShared; } - assert( p!=0 ); - if( p ){ - p->pShared = pCur->pShared; - } - } - sqliteFree(pCur); - return SQLITE_OK; -} - -static int memRbtreeGetMeta(Rbtree* tree, int* aMeta) -{ - memcpy( aMeta, tree->aMetaData, sizeof(int) * SQLITE_N_BTREE_META ); - return SQLITE_OK; -} - -static int memRbtreeUpdateMeta(Rbtree* tree, int* aMeta) -{ - memcpy( tree->aMetaData, aMeta, sizeof(int) * SQLITE_N_BTREE_META ); - return SQLITE_OK; -} - -/* - * Check that each table in the Rbtree meets the requirements for a red-black - * binary tree. If an error is found, return an explanation of the problem in - * memory obtained from sqliteMalloc(). Parameters aRoot and nRoot are ignored. - */ -static char *memRbtreeIntegrityCheck(Rbtree* tree, int* aRoot, int nRoot) -{ - char * msg = 0; - HashElem *p; - - for(p=sqliteHashFirst(&tree->tblHash); p; p=sqliteHashNext(p)){ - BtRbTree *pTree = sqliteHashData(p); - check_redblack_tree(pTree, &msg); - } - - return msg; -} - -static int memRbtreeSetCacheSize(Rbtree* tree, int sz) -{ - return SQLITE_OK; -} - -static int memRbtreeSetSafetyLevel(Rbtree *pBt, int level){ - return SQLITE_OK; -} - -static int memRbtreeBeginTrans(Rbtree* tree) -{ - if( tree->eTransState != TRANS_NONE ) - return SQLITE_ERROR; - - assert( tree->pTransRollback == 0 ); - tree->eTransState = TRANS_INTRANSACTION; - return SQLITE_OK; -} - -/* -** Delete a linked list of BtRollbackOp structures. -*/ -static void deleteRollbackList(BtRollbackOp *pOp){ - while( pOp ){ - BtRollbackOp *pTmp = pOp->pNext; - sqliteFree(pOp->pData); - sqliteFree(pOp->pKey); - sqliteFree(pOp); - pOp = pTmp; - } -} - -static int memRbtreeCommit(Rbtree* tree){ - /* Just delete pTransRollback and pCheckRollback */ - deleteRollbackList(tree->pCheckRollback); - deleteRollbackList(tree->pTransRollback); - tree->pTransRollback = 0; - tree->pCheckRollback = 0; - tree->pCheckRollbackTail = 0; - tree->eTransState = TRANS_NONE; - return SQLITE_OK; -} - -/* - * Close the supplied Rbtree. Delete everything associated with it. - */ -static int memRbtreeClose(Rbtree* tree) -{ - HashElem *p; - memRbtreeCommit(tree); - while( (p=sqliteHashFirst(&tree->tblHash))!=0 ){ - tree->eTransState = TRANS_ROLLBACK; - memRbtreeDropTable(tree, sqliteHashKeysize(p)); - } - sqliteHashClear(&tree->tblHash); - sqliteFree(tree); - return SQLITE_OK; -} - -/* - * Execute and delete the supplied rollback-list on pRbtree. - */ -static void execute_rollback_list(Rbtree *pRbtree, BtRollbackOp *pList) -{ - BtRollbackOp *pTmp; - RbtCursor cur; - int res; - - cur.pRbtree = pRbtree; - cur.wrFlag = 1; - while( pList ){ - switch( pList->eOp ){ - case ROLLBACK_INSERT: - cur.pTree = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab ); - assert(cur.pTree); - cur.iTree = pList->iTab; - cur.eSkip = SKIP_NONE; - memRbtreeInsert( &cur, pList->pKey, - pList->nKey, pList->pData, pList->nData ); - break; - case ROLLBACK_DELETE: - cur.pTree = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab ); - assert(cur.pTree); - cur.iTree = pList->iTab; - cur.eSkip = SKIP_NONE; - memRbtreeMoveto(&cur, pList->pKey, pList->nKey, &res); - assert(res == 0); - memRbtreeDelete( &cur ); - break; - case ROLLBACK_CREATE: - btreeCreateTable(pRbtree, pList->iTab); - break; - case ROLLBACK_DROP: - memRbtreeDropTable(pRbtree, pList->iTab); - break; - default: - assert(0); - } - sqliteFree(pList->pKey); - sqliteFree(pList->pData); - pTmp = pList->pNext; - sqliteFree(pList); - pList = pTmp; - } -} - -static int memRbtreeRollback(Rbtree* tree) -{ - tree->eTransState = TRANS_ROLLBACK; - execute_rollback_list(tree, tree->pCheckRollback); - execute_rollback_list(tree, tree->pTransRollback); - tree->pTransRollback = 0; - tree->pCheckRollback = 0; - tree->pCheckRollbackTail = 0; - tree->eTransState = TRANS_NONE; - return SQLITE_OK; -} - -static int memRbtreeBeginCkpt(Rbtree* tree) -{ - if( tree->eTransState != TRANS_INTRANSACTION ) - return SQLITE_ERROR; - - assert( tree->pCheckRollback == 0 ); - assert( tree->pCheckRollbackTail == 0 ); - tree->eTransState = TRANS_INCHECKPOINT; - return SQLITE_OK; -} - -static int memRbtreeCommitCkpt(Rbtree* tree) -{ - if( tree->eTransState == TRANS_INCHECKPOINT ){ - if( tree->pCheckRollback ){ - tree->pCheckRollbackTail->pNext = tree->pTransRollback; - tree->pTransRollback = tree->pCheckRollback; - tree->pCheckRollback = 0; - tree->pCheckRollbackTail = 0; - } - tree->eTransState = TRANS_INTRANSACTION; - } - return SQLITE_OK; -} - -static int memRbtreeRollbackCkpt(Rbtree* tree) -{ - if( tree->eTransState != TRANS_INCHECKPOINT ) return SQLITE_OK; - tree->eTransState = TRANS_ROLLBACK; - execute_rollback_list(tree, tree->pCheckRollback); - tree->pCheckRollback = 0; - tree->pCheckRollbackTail = 0; - tree->eTransState = TRANS_INTRANSACTION; - return SQLITE_OK; -} - -#ifdef SQLITE_TEST -static int memRbtreePageDump(Rbtree* tree, int pgno, int rec) -{ - assert(!"Cannot call sqliteRbtreePageDump"); - return SQLITE_OK; -} - -static int memRbtreeCursorDump(RbtCursor* pCur, int* aRes) -{ - assert(!"Cannot call sqliteRbtreeCursorDump"); - return SQLITE_OK; -} -#endif - -static struct Pager *memRbtreePager(Rbtree* tree) -{ - return 0; -} - -/* -** Return the full pathname of the underlying database file. -*/ -static const char *memRbtreeGetFilename(Rbtree *pBt){ - return 0; /* A NULL return indicates there is no underlying file */ -} - -/* -** The copy file function is not implemented for the in-memory database -*/ -static int memRbtreeCopyFile(Rbtree *pBt, Rbtree *pBt2){ - return SQLITE_INTERNAL; /* Not implemented */ -} - -static BtOps sqliteRbtreeOps = { - (int(*)(Btree*)) memRbtreeClose, - (int(*)(Btree*,int)) memRbtreeSetCacheSize, - (int(*)(Btree*,int)) memRbtreeSetSafetyLevel, - (int(*)(Btree*)) memRbtreeBeginTrans, - (int(*)(Btree*)) memRbtreeCommit, - (int(*)(Btree*)) memRbtreeRollback, - (int(*)(Btree*)) memRbtreeBeginCkpt, - (int(*)(Btree*)) memRbtreeCommitCkpt, - (int(*)(Btree*)) memRbtreeRollbackCkpt, - (int(*)(Btree*,int*)) memRbtreeCreateTable, - (int(*)(Btree*,int*)) memRbtreeCreateTable, - (int(*)(Btree*,int)) memRbtreeDropTable, - (int(*)(Btree*,int)) memRbtreeClearTable, - (int(*)(Btree*,int,int,BtCursor**)) memRbtreeCursor, - (int(*)(Btree*,int*)) memRbtreeGetMeta, - (int(*)(Btree*,int*)) memRbtreeUpdateMeta, - (char*(*)(Btree*,int*,int)) memRbtreeIntegrityCheck, - (const char*(*)(Btree*)) memRbtreeGetFilename, - (int(*)(Btree*,Btree*)) memRbtreeCopyFile, - (struct Pager*(*)(Btree*)) memRbtreePager, -#ifdef SQLITE_TEST - (int(*)(Btree*,int,int)) memRbtreePageDump, -#endif -}; - -static BtCursorOps sqliteRbtreeCursorOps = { - (int(*)(BtCursor*,const void*,int,int*)) memRbtreeMoveto, - (int(*)(BtCursor*)) memRbtreeDelete, - (int(*)(BtCursor*,const void*,int,const void*,int)) memRbtreeInsert, - (int(*)(BtCursor*,int*)) memRbtreeFirst, - (int(*)(BtCursor*,int*)) memRbtreeLast, - (int(*)(BtCursor*,int*)) memRbtreeNext, - (int(*)(BtCursor*,int*)) memRbtreePrevious, - (int(*)(BtCursor*,int*)) memRbtreeKeySize, - (int(*)(BtCursor*,int,int,char*)) memRbtreeKey, - (int(*)(BtCursor*,const void*,int,int,int*)) memRbtreeKeyCompare, - (int(*)(BtCursor*,int*)) memRbtreeDataSize, - (int(*)(BtCursor*,int,int,char*)) memRbtreeData, - (int(*)(BtCursor*)) memRbtreeCloseCursor, -#ifdef SQLITE_TEST - (int(*)(BtCursor*,int*)) memRbtreeCursorDump, -#endif - -}; - -#endif /* SQLITE_OMIT_INMEMORYDB */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/btree_rb.o b/dbLifeLog/DBD-SQLite2-0.33/btree_rb.o deleted file mode 100644 index 39ee16977d2ba8c6d59c30c52af334c48870473c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16752 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 - -/* -** This routine is called when a new SQL statement is beginning to -** be parsed. Check to see if the schema for the database needs -** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables. -** If it does, then read it. -*/ -void sqliteBeginParse(Parse *pParse, int explainFlag){ - sqlite *db = pParse->db; - int i; - pParse->explain = explainFlag; - if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){ - int rc = sqliteInit(db, &pParse->zErrMsg); - if( rc!=SQLITE_OK ){ - pParse->rc = rc; - pParse->nErr++; - } - } - for(i=0; inDb; i++){ - DbClearProperty(db, i, DB_Locked); - if( !db->aDb[i].inTrans ){ - DbClearProperty(db, i, DB_Cookie); - } - } - pParse->nVar = 0; -} - -/* -** This routine is called after a single SQL statement has been -** parsed and we want to execute the VDBE code to implement -** that statement. Prior action routines should have already -** constructed VDBE code to do the work of the SQL statement. -** This routine just has to execute the VDBE code. -** -** Note that if an error occurred, it might be the case that -** no VDBE code was generated. -*/ -void sqliteExec(Parse *pParse){ - sqlite *db = pParse->db; - Vdbe *v = pParse->pVdbe; - - if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){ - sqliteVdbeAddOp(v, OP_Halt, 0, 0); - } - if( sqlite_malloc_failed ) return; - if( v && pParse->nErr==0 ){ - FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; - sqliteVdbeTrace(v, trace); - sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain); - pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE; - pParse->colNamesSet = 0; - }else if( pParse->rc==SQLITE_OK ){ - pParse->rc = SQLITE_ERROR; - } - pParse->nTab = 0; - pParse->nMem = 0; - pParse->nSet = 0; - pParse->nAgg = 0; - pParse->nVar = 0; -} - -/* -** Locate the in-memory structure that describes -** a particular database table given the name -** of that table and (optionally) the name of the database -** containing the table. Return NULL if not found. -** -** If zDatabase is 0, all databases are searched for the -** table and the first matching table is returned. (No checking -** for duplicate table names is done.) The search order is -** TEMP first, then MAIN, then any auxiliary databases added -** using the ATTACH command. -** -** See also sqliteLocateTable(). -*/ -Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){ - Table *p = 0; - int i; - for(i=0; inDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue; - p = sqliteHashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1); - if( p ) break; - } - return p; -} - -/* -** Locate the in-memory structure that describes -** a particular database table given the name -** of that table and (optionally) the name of the database -** containing the table. Return NULL if not found. -** Also leave an error message in pParse->zErrMsg. -** -** The difference between this routine and sqliteFindTable() -** is that this routine leaves an error message in pParse->zErrMsg -** where sqliteFindTable() does not. -*/ -Table *sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase){ - Table *p; - - p = sqliteFindTable(pParse->db, zName, zDbase); - if( p==0 ){ - if( zDbase ){ - sqliteErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); - }else if( sqliteFindTable(pParse->db, zName, 0)!=0 ){ - sqliteErrorMsg(pParse, "table \"%s\" is not in database \"%s\"", - zName, zDbase); - }else{ - sqliteErrorMsg(pParse, "no such table: %s", zName); - } - } - return p; -} - -/* -** Locate the in-memory structure that describes -** a particular index given the name of that index -** and the name of the database that contains the index. -** Return NULL if not found. -** -** If zDatabase is 0, all databases are searched for the -** table and the first matching index is returned. (No checking -** for duplicate index names is done.) The search order is -** TEMP first, then MAIN, then any auxiliary databases added -** using the ATTACH command. -*/ -Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){ - Index *p = 0; - int i; - for(i=0; inDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue; - p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); - if( p ) break; - } - return p; -} - -/* -** Remove the given index from the index hash table, and free -** its memory structures. -** -** The index is removed from the database hash tables but -** it is not unlinked from the Table that it indexes. -** Unlinking from the Table must be done by the calling function. -*/ -static void sqliteDeleteIndex(sqlite *db, Index *p){ - Index *pOld; - - assert( db!=0 && p->zName!=0 ); - pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName, - strlen(p->zName)+1, 0); - if( pOld!=0 && pOld!=p ){ - sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName, - strlen(pOld->zName)+1, pOld); - } - sqliteFree(p); -} - -/* -** Unlink the given index from its table, then remove -** the index from the index hash table and free its memory -** structures. -*/ -void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){ - if( pIndex->pTable->pIndex==pIndex ){ - pIndex->pTable->pIndex = pIndex->pNext; - }else{ - Index *p; - for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} - if( p && p->pNext==pIndex ){ - p->pNext = pIndex->pNext; - } - } - sqliteDeleteIndex(db, pIndex); -} - -/* -** Erase all schema information from the in-memory hash tables of -** database connection. This routine is called to reclaim memory -** before the connection closes. It is also called during a rollback -** if there were schema changes during the transaction. -** -** If iDb<=0 then reset the internal schema tables for all database -** files. If iDb>=2 then reset the internal schema for only the -** single file indicated. -*/ -void sqliteResetInternalSchema(sqlite *db, int iDb){ - HashElem *pElem; - Hash temp1; - Hash temp2; - int i, j; - - assert( iDb>=0 && iDbnDb ); - db->flags &= ~SQLITE_Initialized; - for(i=iDb; inDb; i++){ - Db *pDb = &db->aDb[i]; - temp1 = pDb->tblHash; - temp2 = pDb->trigHash; - sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); - sqliteHashClear(&pDb->aFKey); - sqliteHashClear(&pDb->idxHash); - for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ - Trigger *pTrigger = sqliteHashData(pElem); - sqliteDeleteTrigger(pTrigger); - } - sqliteHashClear(&temp2); - sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); - for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ - Table *pTab = sqliteHashData(pElem); - sqliteDeleteTable(db, pTab); - } - sqliteHashClear(&temp1); - DbClearProperty(db, i, DB_SchemaLoaded); - if( iDb>0 ) return; - } - assert( iDb==0 ); - db->flags &= ~SQLITE_InternChanges; - - /* If one or more of the auxiliary database files has been closed, - ** then remove then from the auxiliary database list. We take the - ** opportunity to do this here since we have just deleted all of the - ** schema hash tables and therefore do not have to make any changes - ** to any of those tables. - */ - for(i=0; inDb; i++){ - struct Db *pDb = &db->aDb[i]; - if( pDb->pBt==0 ){ - if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux); - pDb->pAux = 0; - } - } - for(i=j=2; inDb; i++){ - struct Db *pDb = &db->aDb[i]; - if( pDb->pBt==0 ){ - sqliteFree(pDb->zName); - pDb->zName = 0; - continue; - } - if( jaDb[j] = db->aDb[i]; - } - j++; - } - memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); - db->nDb = j; - if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ - memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); - sqliteFree(db->aDb); - db->aDb = db->aDbStatic; - } -} - -/* -** This routine is called whenever a rollback occurs. If there were -** schema changes during the transaction, then we have to reset the -** internal hash tables and reload them from disk. -*/ -void sqliteRollbackInternalChanges(sqlite *db){ - if( db->flags & SQLITE_InternChanges ){ - sqliteResetInternalSchema(db, 0); - } -} - -/* -** This routine is called when a commit occurs. -*/ -void sqliteCommitInternalChanges(sqlite *db){ - db->aDb[0].schema_cookie = db->next_cookie; - db->flags &= ~SQLITE_InternChanges; -} - -/* -** Remove the memory data structures associated with the given -** Table. No changes are made to disk by this routine. -** -** This routine just deletes the data structure. It does not unlink -** the table data structure from the hash table. Nor does it remove -** foreign keys from the sqlite.aFKey hash table. But it does destroy -** memory structures of the indices and foreign keys associated with -** the table. -** -** Indices associated with the table are unlinked from the "db" -** data structure if db!=NULL. If db==NULL, indices attached to -** the table are deleted, but it is assumed they have already been -** unlinked. -*/ -void sqliteDeleteTable(sqlite *db, Table *pTable){ - int i; - Index *pIndex, *pNext; - FKey *pFKey, *pNextFKey; - - if( pTable==0 ) return; - - /* Delete all indices associated with this table - */ - for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ - pNext = pIndex->pNext; - assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); - sqliteDeleteIndex(db, pIndex); - } - - /* Delete all foreign keys associated with this table. The keys - ** should have already been unlinked from the db->aFKey hash table - */ - for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ - pNextFKey = pFKey->pNextFrom; - assert( pTable->iDbnDb ); - assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey, - pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); - sqliteFree(pFKey); - } - - /* Delete the Table structure itself. - */ - for(i=0; inCol; i++){ - sqliteFree(pTable->aCol[i].zName); - sqliteFree(pTable->aCol[i].zDflt); - sqliteFree(pTable->aCol[i].zType); - } - sqliteFree(pTable->zName); - sqliteFree(pTable->aCol); - sqliteSelectDelete(pTable->pSelect); - sqliteFree(pTable); -} - -/* -** Unlink the given table from the hash tables and the delete the -** table structure with all its indices and foreign keys. -*/ -static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){ - Table *pOld; - FKey *pF1, *pF2; - int i = p->iDb; - assert( db!=0 ); - pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0); - assert( pOld==0 || pOld==p ); - for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ - int nTo = strlen(pF1->zTo) + 1; - pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo); - if( pF2==pF1 ){ - sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo); - }else{ - while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } - if( pF2 ){ - pF2->pNextTo = pF1->pNextTo; - } - } - } - sqliteDeleteTable(db, p); -} - -/* -** Construct the name of a user table or index from a token. -** -** Space to hold the name is obtained from sqliteMalloc() and must -** be freed by the calling function. -*/ -char *sqliteTableNameFromToken(Token *pName){ - char *zName = sqliteStrNDup(pName->z, pName->n); - sqliteDequote(zName); - return zName; -} - -/* -** Generate code to open the appropriate master table. The table -** opened will be SQLITE_MASTER for persistent tables and -** SQLITE_TEMP_MASTER for temporary tables. The table is opened -** on cursor 0. -*/ -void sqliteOpenMasterTable(Vdbe *v, int isTemp){ - sqliteVdbeAddOp(v, OP_Integer, isTemp, 0); - sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2); -} - -/* -** Begin constructing a new table representation in memory. This is -** the first of several action routines that get called in response -** to a CREATE TABLE statement. In particular, this routine is called -** after seeing tokens "CREATE" and "TABLE" and the table name. The -** pStart token is the CREATE and pName is the table name. The isTemp -** flag is true if the table should be stored in the auxiliary database -** file instead of in the main database file. This is normally the case -** when the "TEMP" or "TEMPORARY" keyword occurs in between -** CREATE and TABLE. -** -** The new table record is initialized and put in pParse->pNewTable. -** As more of the CREATE TABLE statement is parsed, additional action -** routines will be called to add more information to this record. -** At the end of the CREATE TABLE statement, the sqliteEndTable() routine -** is called to complete the construction of the new table record. -*/ -void sqliteStartTable( - Parse *pParse, /* Parser context */ - Token *pStart, /* The "CREATE" token */ - Token *pName, /* Name of table or view to create */ - int isTemp, /* True if this is a TEMP table */ - int isView /* True if this is a VIEW */ -){ - Table *pTable; - Index *pIdx; - char *zName; - sqlite *db = pParse->db; - Vdbe *v; - int iDb; - - pParse->sFirstToken = *pStart; - zName = sqliteTableNameFromToken(pName); - if( zName==0 ) return; - if( db->init.iDb==1 ) isTemp = 1; -#ifndef SQLITE_OMIT_AUTHORIZATION - assert( (isTemp & 1)==isTemp ); - { - int code; - char *zDb = isTemp ? "temp" : "main"; - if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ - sqliteFree(zName); - return; - } - if( isView ){ - if( isTemp ){ - code = SQLITE_CREATE_TEMP_VIEW; - }else{ - code = SQLITE_CREATE_VIEW; - } - }else{ - if( isTemp ){ - code = SQLITE_CREATE_TEMP_TABLE; - }else{ - code = SQLITE_CREATE_TABLE; - } - } - if( sqliteAuthCheck(pParse, code, zName, 0, zDb) ){ - sqliteFree(zName); - return; - } - } -#endif - - - /* Before trying to create a temporary table, make sure the Btree for - ** holding temporary tables is open. - */ - if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){ - int rc = sqliteBtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt); - if( rc!=SQLITE_OK ){ - sqliteErrorMsg(pParse, "unable to open a temporary database " - "file for storing temporary tables"); - pParse->nErr++; - return; - } - if( db->flags & SQLITE_InTrans ){ - rc = sqliteBtreeBeginTrans(db->aDb[1].pBt); - if( rc!=SQLITE_OK ){ - sqliteErrorMsg(pParse, "unable to get a write lock on " - "the temporary database file"); - return; - } - } - } - - /* Make sure the new table name does not collide with an existing - ** index or table name. Issue an error message if it does. - ** - ** If we are re-reading the sqlite_master table because of a schema - ** change and a new permanent table is found whose name collides with - ** an existing temporary table, that is not an error. - */ - pTable = sqliteFindTable(db, zName, 0); - iDb = isTemp ? 1 : db->init.iDb; - if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){ - sqliteErrorMsg(pParse, "table %T already exists", pName); - sqliteFree(zName); - return; - } - if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 && - (pIdx->iDb==0 || !db->init.busy) ){ - sqliteErrorMsg(pParse, "there is already an index named %s", zName); - sqliteFree(zName); - return; - } - pTable = sqliteMalloc( sizeof(Table) ); - if( pTable==0 ){ - sqliteFree(zName); - return; - } - pTable->zName = zName; - pTable->nCol = 0; - pTable->aCol = 0; - pTable->iPKey = -1; - pTable->pIndex = 0; - pTable->iDb = iDb; - if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable); - pParse->pNewTable = pTable; - - /* Begin generating the code that will insert the table record into - ** the SQLITE_MASTER table. Note in particular that we must go ahead - ** and allocate the record number for the table entry now. Before any - ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause - ** indices to be created and the table record must come before the - ** indices. Hence, the record number for the table must be allocated - ** now. - */ - if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){ - sqliteBeginWriteOperation(pParse, 0, isTemp); - if( !isTemp ){ - sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0); - sqliteVdbeAddOp(v, OP_SetCookie, 0, 1); - } - sqliteOpenMasterTable(v, isTemp); - sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); - sqliteVdbeAddOp(v, OP_Dup, 0, 0); - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); - } -} - -/* -** Add a new column to the table currently being constructed. -** -** The parser calls this routine once for each column declaration -** in a CREATE TABLE statement. sqliteStartTable() gets called -** first to get things going. Then this routine is called for each -** column. -*/ -void sqliteAddColumn(Parse *pParse, Token *pName){ - Table *p; - int i; - char *z = 0; - Column *pCol; - if( (p = pParse->pNewTable)==0 ) return; - sqliteSetNString(&z, pName->z, pName->n, 0); - if( z==0 ) return; - sqliteDequote(z); - for(i=0; inCol; i++){ - if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){ - sqliteErrorMsg(pParse, "duplicate column name: %s", z); - sqliteFree(z); - return; - } - } - if( (p->nCol & 0x7)==0 ){ - Column *aNew; - aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); - if( aNew==0 ) return; - p->aCol = aNew; - } - pCol = &p->aCol[p->nCol]; - memset(pCol, 0, sizeof(p->aCol[0])); - pCol->zName = z; - pCol->sortOrder = SQLITE_SO_NUM; - p->nCol++; -} - -/* -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. A "NOT NULL" constraint has -** been seen on a column. This routine sets the notNull flag on -** the column currently under construction. -*/ -void sqliteAddNotNull(Parse *pParse, int onError){ - Table *p; - int i; - if( (p = pParse->pNewTable)==0 ) return; - i = p->nCol-1; - if( i>=0 ) p->aCol[i].notNull = onError; -} - -/* -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. The pFirst token is the first -** token in the sequence of tokens that describe the type of the -** column currently under construction. pLast is the last token -** in the sequence. Use this information to construct a string -** that contains the typename of the column and store that string -** in zType. -*/ -void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ - Table *p; - int i, j; - int n; - char *z, **pz; - Column *pCol; - if( (p = pParse->pNewTable)==0 ) return; - i = p->nCol-1; - if( i<0 ) return; - pCol = &p->aCol[i]; - pz = &pCol->zType; - n = pLast->n + Addr(pLast->z) - Addr(pFirst->z); - sqliteSetNString(pz, pFirst->z, n, 0); - z = *pz; - if( z==0 ) return; - for(i=j=0; z[i]; i++){ - int c = z[i]; - if( isspace(c) ) continue; - z[j++] = c; - } - z[j] = 0; - if( pParse->db->file_format>=4 ){ - pCol->sortOrder = sqliteCollateType(z, n); - }else{ - pCol->sortOrder = SQLITE_SO_NUM; - } -} - -/* -** The given token is the default value for the last column added to -** the table currently under construction. If "minusFlag" is true, it -** means the value token was preceded by a minus sign. -** -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. -*/ -void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){ - Table *p; - int i; - char **pz; - if( (p = pParse->pNewTable)==0 ) return; - i = p->nCol-1; - if( i<0 ) return; - pz = &p->aCol[i].zDflt; - if( minusFlag ){ - sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0); - }else{ - sqliteSetNString(pz, pVal->z, pVal->n, 0); - } - sqliteDequote(*pz); -} - -/* -** Designate the PRIMARY KEY for the table. pList is a list of names -** of columns that form the primary key. If pList is NULL, then the -** most recently added column of the table is the primary key. -** -** A table can have at most one primary key. If the table already has -** a primary key (and this is the second primary key) then create an -** error. -** -** If the PRIMARY KEY is on a single column whose datatype is INTEGER, -** then we will try to use that column as the row id. (Exception: -** For backwards compatibility with older databases, do not do this -** if the file format version number is less than 1.) Set the Table.iPKey -** field of the table under construction to be the index of the -** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is -** no INTEGER PRIMARY KEY. -** -** If the key is not an INTEGER PRIMARY KEY, then create a unique -** index for the key. No index is created for INTEGER PRIMARY KEYs. -*/ -void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){ - Table *pTab = pParse->pNewTable; - char *zType = 0; - int iCol = -1, i; - if( pTab==0 ) goto primary_key_exit; - if( pTab->hasPrimKey ){ - sqliteErrorMsg(pParse, - "table \"%s\" has more than one primary key", pTab->zName); - goto primary_key_exit; - } - pTab->hasPrimKey = 1; - if( pList==0 ){ - iCol = pTab->nCol - 1; - pTab->aCol[iCol].isPrimKey = 1; - }else{ - for(i=0; inId; i++){ - for(iCol=0; iColnCol; iCol++){ - if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ) break; - } - if( iColnCol ) pTab->aCol[iCol].isPrimKey = 1; - } - if( pList->nId>1 ) iCol = -1; - } - if( iCol>=0 && iColnCol ){ - zType = pTab->aCol[iCol].zType; - } - if( pParse->db->file_format>=1 && - zType && sqliteStrICmp(zType, "INTEGER")==0 ){ - pTab->iPKey = iCol; - pTab->keyConf = onError; - }else{ - sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0); - pList = 0; - } - -primary_key_exit: - sqliteIdListDelete(pList); - return; -} - -/* -** Return the appropriate collating type given a type name. -** -** The collation type is text (SQLITE_SO_TEXT) if the type -** name contains the character stream "text" or "blob" or -** "clob". Any other type name is collated as numeric -** (SQLITE_SO_NUM). -*/ -int sqliteCollateType(const char *zType, int nType){ - int i; - for(i=0; ipNewTable)==0 ) return; - i = p->nCol-1; - if( i>=0 ) p->aCol[i].sortOrder = collType; -} - -/* -** Come up with a new random value for the schema cookie. Make sure -** the new value is different from the old. -** -** The schema cookie is used to determine when the schema for the -** database changes. After each schema change, the cookie value -** changes. When a process first reads the schema it records the -** cookie. Thereafter, whenever it goes to access the database, -** it checks the cookie to make sure the schema has not changed -** since it was last read. -** -** This plan is not completely bullet-proof. It is possible for -** the schema to change multiple times and for the cookie to be -** set back to prior value. But schema changes are infrequent -** and the probability of hitting the same cookie value is only -** 1 chance in 2^32. So we're safe enough. -*/ -void sqliteChangeCookie(sqlite *db, Vdbe *v){ - if( db->next_cookie==db->aDb[0].schema_cookie ){ - unsigned char r; - sqliteRandomness(1, &r); - db->next_cookie = db->aDb[0].schema_cookie + r + 1; - db->flags |= SQLITE_InternChanges; - sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0); - sqliteVdbeAddOp(v, OP_SetCookie, 0, 0); - } -} - -/* -** Measure the number of characters needed to output the given -** identifier. The number returned includes any quotes used -** but does not include the null terminator. -*/ -static int identLength(const char *z){ - int n; - int needQuote = 0; - for(n=0; *z; n++, z++){ - if( *z=='\'' ){ n++; needQuote=1; } - } - return n + needQuote*2; -} - -/* -** Write an identifier onto the end of the given string. Add -** quote characters as needed. -*/ -static void identPut(char *z, int *pIdx, char *zIdent){ - int i, j, needQuote; - i = *pIdx; - for(j=0; zIdent[j]; j++){ - if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break; - } - needQuote = zIdent[j]!=0 || isdigit(zIdent[0]) - || sqliteKeywordCode(zIdent, j)!=TK_ID; - if( needQuote ) z[i++] = '\''; - for(j=0; zIdent[j]; j++){ - z[i++] = zIdent[j]; - if( zIdent[j]=='\'' ) z[i++] = '\''; - } - if( needQuote ) z[i++] = '\''; - z[i] = 0; - *pIdx = i; -} - -/* -** Generate a CREATE TABLE statement appropriate for the given -** table. Memory to hold the text of the statement is obtained -** from sqliteMalloc() and must be freed by the calling function. -*/ -static char *createTableStmt(Table *p){ - int i, k, n; - char *zStmt; - char *zSep, *zSep2, *zEnd; - n = 0; - for(i=0; inCol; i++){ - n += identLength(p->aCol[i].zName); - } - n += identLength(p->zName); - if( n<40 ){ - zSep = ""; - zSep2 = ","; - zEnd = ")"; - }else{ - zSep = "\n "; - zSep2 = ",\n "; - zEnd = "\n)"; - } - n += 35 + 6*p->nCol; - zStmt = sqliteMallocRaw( n ); - if( zStmt==0 ) return 0; - strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE "); - k = strlen(zStmt); - identPut(zStmt, &k, p->zName); - zStmt[k++] = '('; - for(i=0; inCol; i++){ - strcpy(&zStmt[k], zSep); - k += strlen(&zStmt[k]); - zSep = zSep2; - identPut(zStmt, &k, p->aCol[i].zName); - } - strcpy(&zStmt[k], zEnd); - return zStmt; -} - -/* -** This routine is called to report the final ")" that terminates -** a CREATE TABLE statement. -** -** The table structure that other action routines have been building -** is added to the internal hash tables, assuming no errors have -** occurred. -** -** An entry for the table is made in the master table on disk, unless -** this is a temporary table or db->init.busy==1. When db->init.busy==1 -** it means we are reading the sqlite_master table because we just -** connected to the database or because the sqlite_master table has -** recently changes, so the entry for this table already exists in -** the sqlite_master table. We do not want to create it again. -** -** If the pSelect argument is not NULL, it means that this routine -** was called to create a table generated from a -** "CREATE TABLE ... AS SELECT ..." statement. The column names of -** the new table will match the result set of the SELECT. -*/ -void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){ - Table *p; - sqlite *db = pParse->db; - - if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite_malloc_failed ) return; - p = pParse->pNewTable; - if( p==0 ) return; - - /* If the table is generated from a SELECT, then construct the - ** list of columns and the text of the table. - */ - if( pSelect ){ - Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect); - if( pSelTab==0 ) return; - assert( p->aCol==0 ); - p->nCol = pSelTab->nCol; - p->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqliteDeleteTable(0, pSelTab); - } - - /* If the db->init.busy is 1 it means we are reading the SQL off the - ** "sqlite_master" or "sqlite_temp_master" table on the disk. - ** So do not write to the disk again. Extract the root page number - ** for the table from the db->init.newTnum field. (The page number - ** should have been put there by the sqliteOpenCb routine.) - */ - if( db->init.busy ){ - p->tnum = db->init.newTnum; - } - - /* If not initializing, then create a record for the new table - ** in the SQLITE_MASTER table of the database. The record number - ** for the new table entry should already be on the stack. - ** - ** If this is a TEMPORARY table, write the entry into the auxiliary - ** file instead of into the main database file. - */ - if( !db->init.busy ){ - int n; - Vdbe *v; - - v = sqliteGetVdbe(pParse); - if( v==0 ) return; - if( p->pSelect==0 ){ - /* A regular table */ - sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER); - }else{ - /* A view */ - sqliteVdbeAddOp(v, OP_Integer, 0, 0); - } - p->tnum = 0; - sqliteVdbeAddOp(v, OP_Pull, 1, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC); - sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0); - sqliteVdbeAddOp(v, OP_Dup, 4, 0); - sqliteVdbeAddOp(v, OP_String, 0, 0); - if( pSelect ){ - char *z = createTableStmt(p); - n = z ? strlen(z) : 0; - sqliteVdbeChangeP3(v, -1, z, n); - sqliteFree(z); - }else{ - assert( pEnd!=0 ); - n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1; - sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n); - } - sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); - if( !p->iDb ){ - sqliteChangeCookie(db, v); - } - sqliteVdbeAddOp(v, OP_Close, 0, 0); - if( pSelect ){ - sqliteVdbeAddOp(v, OP_Integer, p->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0); - pParse->nTab = 2; - sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0); - } - sqliteEndWriteOperation(pParse); - } - - /* Add the table to the in-memory representation of the database. - */ - if( pParse->explain==0 && pParse->nErr==0 ){ - Table *pOld; - FKey *pFKey; - pOld = sqliteHashInsert(&db->aDb[p->iDb].tblHash, - p->zName, strlen(p->zName)+1, p); - if( pOld ){ - assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ - return; - } - for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ - int nTo = strlen(pFKey->zTo) + 1; - pFKey->pNextTo = sqliteHashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo); - sqliteHashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey); - } - pParse->pNewTable = 0; - db->nTable++; - db->flags |= SQLITE_InternChanges; - } -} - -/* -** The parser calls this routine in order to create a new VIEW -*/ -void sqliteCreateView( - Parse *pParse, /* The parsing context */ - Token *pBegin, /* The CREATE token that begins the statement */ - Token *pName, /* The token that holds the name of the view */ - Select *pSelect, /* A SELECT statement that will become the new view */ - int isTemp /* TRUE for a TEMPORARY view */ -){ - Table *p; - int n; - const char *z; - Token sEnd; - DbFixer sFix; - - sqliteStartTable(pParse, pBegin, pName, isTemp, 1); - p = pParse->pNewTable; - if( p==0 || pParse->nErr ){ - sqliteSelectDelete(pSelect); - return; - } - if( sqliteFixInit(&sFix, pParse, p->iDb, "view", pName) - && sqliteFixSelect(&sFix, pSelect) - ){ - sqliteSelectDelete(pSelect); - return; - } - - /* Make a copy of the entire SELECT statement that defines the view. - ** This will force all the Expr.token.z values to be dynamically - ** allocated rather than point to the input string - which means that - ** they will persist after the current sqlite_exec() call returns. - */ - p->pSelect = sqliteSelectDup(pSelect); - sqliteSelectDelete(pSelect); - if( !pParse->db->init.busy ){ - sqliteViewGetColumnNames(pParse, p); - } - - /* Locate the end of the CREATE VIEW statement. Make sEnd point to - ** the end. - */ - sEnd = pParse->sLastToken; - if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ - sEnd.z += sEnd.n; - } - sEnd.n = 0; - n = sEnd.z - pBegin->z; - z = pBegin->z; - while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; } - sEnd.z = &z[n-1]; - sEnd.n = 1; - - /* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */ - sqliteEndTable(pParse, &sEnd, 0); - return; -} - -/* -** The Table structure pTable is really a VIEW. Fill in the names of -** the columns of the view in the pTable structure. Return the number -** of errors. If an error is seen leave an error message in pParse->zErrMsg. -*/ -int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){ - ExprList *pEList; - Select *pSel; - Table *pSelTab; - int nErr = 0; - - assert( pTable ); - - /* A positive nCol means the columns names for this view are - ** already known. - */ - if( pTable->nCol>0 ) return 0; - - /* A negative nCol is a special marker meaning that we are currently - ** trying to compute the column names. If we enter this routine with - ** a negative nCol, it means two or more views form a loop, like this: - ** - ** CREATE VIEW one AS SELECT * FROM two; - ** CREATE VIEW two AS SELECT * FROM one; - ** - ** Actually, this error is caught previously and so the following test - ** should always fail. But we will leave it in place just to be safe. - */ - if( pTable->nCol<0 ){ - sqliteErrorMsg(pParse, "view %s is circularly defined", pTable->zName); - return 1; - } - - /* If we get this far, it means we need to compute the table names. - */ - assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */ - pSel = pTable->pSelect; - - /* Note that the call to sqliteResultSetOfSelect() will expand any - ** "*" elements in this list. But we will need to restore the list - ** back to its original configuration afterwards, so we save a copy of - ** the original in pEList. - */ - pEList = pSel->pEList; - pSel->pEList = sqliteExprListDup(pEList); - if( pSel->pEList==0 ){ - pSel->pEList = pEList; - return 1; /* Malloc failed */ - } - pTable->nCol = -1; - pSelTab = sqliteResultSetOfSelect(pParse, 0, pSel); - if( pSelTab ){ - assert( pTable->aCol==0 ); - pTable->nCol = pSelTab->nCol; - pTable->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqliteDeleteTable(0, pSelTab); - DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews); - }else{ - pTable->nCol = 0; - nErr++; - } - sqliteSelectUnbind(pSel); - sqliteExprListDelete(pSel->pEList); - pSel->pEList = pEList; - return nErr; -} - -/* -** Clear the column names from the VIEW pTable. -** -** This routine is called whenever any other table or view is modified. -** The view passed into this routine might depend directly or indirectly -** on the modified or deleted table so we need to clear the old column -** names so that they will be recomputed. -*/ -static void sqliteViewResetColumnNames(Table *pTable){ - int i; - Column *pCol; - assert( pTable!=0 && pTable->pSelect!=0 ); - for(i=0, pCol=pTable->aCol; inCol; i++, pCol++){ - sqliteFree(pCol->zName); - sqliteFree(pCol->zDflt); - sqliteFree(pCol->zType); - } - sqliteFree(pTable->aCol); - pTable->aCol = 0; - pTable->nCol = 0; -} - -/* -** Clear the column names from every VIEW in database idx. -*/ -static void sqliteViewResetAll(sqlite *db, int idx){ - HashElem *i; - if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; - for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){ - Table *pTab = sqliteHashData(i); - if( pTab->pSelect ){ - sqliteViewResetColumnNames(pTab); - } - } - DbClearProperty(db, idx, DB_UnresetViews); -} - -/* -** Given a token, look up a table with that name. If not found, leave -** an error for the parser to find and return NULL. -*/ -Table *sqliteTableFromToken(Parse *pParse, Token *pTok){ - char *zName; - Table *pTab; - zName = sqliteTableNameFromToken(pTok); - if( zName==0 ) return 0; - pTab = sqliteFindTable(pParse->db, zName, 0); - sqliteFree(zName); - if( pTab==0 ){ - sqliteErrorMsg(pParse, "no such table: %T", pTok); - } - return pTab; -} - -/* -** This routine is called to do the work of a DROP TABLE statement. -** pName is the name of the table to be dropped. -*/ -void sqliteDropTable(Parse *pParse, Token *pName, int isView){ - Table *pTable; - Vdbe *v; - int base; - sqlite *db = pParse->db; - int iDb; - - if( pParse->nErr || sqlite_malloc_failed ) return; - pTable = sqliteTableFromToken(pParse, pName); - if( pTable==0 ) return; - iDb = pTable->iDb; - assert( iDb>=0 && iDbnDb ); -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int code; - const char *zTab = SCHEMA_TABLE(pTable->iDb); - const char *zDb = db->aDb[pTable->iDb].zName; - if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ - return; - } - if( isView ){ - if( iDb==1 ){ - code = SQLITE_DROP_TEMP_VIEW; - }else{ - code = SQLITE_DROP_VIEW; - } - }else{ - if( iDb==1 ){ - code = SQLITE_DROP_TEMP_TABLE; - }else{ - code = SQLITE_DROP_TABLE; - } - } - if( sqliteAuthCheck(pParse, code, pTable->zName, 0, zDb) ){ - return; - } - if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0, zDb) ){ - return; - } - } -#endif - if( pTable->readOnly ){ - sqliteErrorMsg(pParse, "table %s may not be dropped", pTable->zName); - pParse->nErr++; - return; - } - if( isView && pTable->pSelect==0 ){ - sqliteErrorMsg(pParse, "use DROP TABLE to delete table %s", pTable->zName); - return; - } - if( !isView && pTable->pSelect ){ - sqliteErrorMsg(pParse, "use DROP VIEW to delete view %s", pTable->zName); - return; - } - - /* Generate code to remove the table from the master table - ** on disk. - */ - v = sqliteGetVdbe(pParse); - if( v ){ - static VdbeOpList dropTable[] = { - { OP_Rewind, 0, ADDR(8), 0}, - { OP_String, 0, 0, 0}, /* 1 */ - { OP_MemStore, 1, 1, 0}, - { OP_MemLoad, 1, 0, 0}, /* 3 */ - { OP_Column, 0, 2, 0}, - { OP_Ne, 0, ADDR(7), 0}, - { OP_Delete, 0, 0, 0}, - { OP_Next, 0, ADDR(3), 0}, /* 7 */ - }; - Index *pIdx; - Trigger *pTrigger; - sqliteBeginWriteOperation(pParse, 0, pTable->iDb); - - /* Drop all triggers associated with the table being dropped */ - pTrigger = pTable->pTrigger; - while( pTrigger ){ - assert( pTrigger->iDb==pTable->iDb || pTrigger->iDb==1 ); - sqliteDropTriggerPtr(pParse, pTrigger, 1); - if( pParse->explain ){ - pTrigger = pTrigger->pNext; - }else{ - pTrigger = pTable->pTrigger; - } - } - - /* Drop all SQLITE_MASTER entries that refer to the table */ - sqliteOpenMasterTable(v, pTable->iDb); - base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable); - sqliteVdbeChangeP3(v, base+1, pTable->zName, 0); - - /* Drop all SQLITE_TEMP_MASTER entries that refer to the table */ - if( pTable->iDb!=1 ){ - sqliteOpenMasterTable(v, 1); - base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable); - sqliteVdbeChangeP3(v, base+1, pTable->zName, 0); - } - - if( pTable->iDb==0 ){ - sqliteChangeCookie(db, v); - } - sqliteVdbeAddOp(v, OP_Close, 0, 0); - if( !isView ){ - sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb); - for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){ - sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb); - } - } - sqliteEndWriteOperation(pParse); - } - - /* Delete the in-memory description of the table. - ** - ** Exception: if the SQL statement began with the EXPLAIN keyword, - ** then no changes should be made. - */ - if( !pParse->explain ){ - sqliteUnlinkAndDeleteTable(db, pTable); - db->flags |= SQLITE_InternChanges; - } - sqliteViewResetAll(db, iDb); -} - -/* -** This routine constructs a P3 string suitable for an OP_MakeIdxKey -** opcode and adds that P3 string to the most recently inserted instruction -** in the virtual machine. The P3 string consists of a single character -** for each column in the index pIdx of table pTab. If the column uses -** a numeric sort order, then the P3 string character corresponding to -** that column is 'n'. If the column uses a text sort order, then the -** P3 string is 't'. See the OP_MakeIdxKey opcode documentation for -** additional information. See also the sqliteAddKeyType() routine. -*/ -void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){ - char *zType; - Table *pTab; - int i, n; - assert( pIdx!=0 && pIdx->pTable!=0 ); - pTab = pIdx->pTable; - n = pIdx->nColumn; - zType = sqliteMallocRaw( n+1 ); - if( zType==0 ) return; - for(i=0; iaiColumn[i]; - assert( iCol>=0 && iColnCol ); - if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ - zType[i] = 't'; - }else{ - zType[i] = 'n'; - } - } - zType[n] = 0; - sqliteVdbeChangeP3(v, -1, zType, n); - sqliteFree(zType); -} - -/* -** This routine is called to create a new foreign key on the table -** currently under construction. pFromCol determines which columns -** in the current table point to the foreign key. If pFromCol==0 then -** connect the key to the last column inserted. pTo is the name of -** the table referred to. pToCol is a list of tables in the other -** pTo table that the foreign key points to. flags contains all -** information about the conflict resolution algorithms specified -** in the ON DELETE, ON UPDATE and ON INSERT clauses. -** -** An FKey structure is created and added to the table currently -** under construction in the pParse->pNewTable field. The new FKey -** is not linked into db->aFKey at this point - that does not happen -** until sqliteEndTable(). -** -** The foreign key is set for IMMEDIATE processing. A subsequent call -** to sqliteDeferForeignKey() might change this to DEFERRED. -*/ -void sqliteCreateForeignKey( - Parse *pParse, /* Parsing context */ - IdList *pFromCol, /* Columns in this table that point to other table */ - Token *pTo, /* Name of the other table */ - IdList *pToCol, /* Columns in the other table */ - int flags /* Conflict resolution algorithms. */ -){ - Table *p = pParse->pNewTable; - int nByte; - int i; - int nCol; - char *z; - FKey *pFKey = 0; - - assert( pTo!=0 ); - if( p==0 || pParse->nErr ) goto fk_end; - if( pFromCol==0 ){ - int iCol = p->nCol-1; - if( iCol<0 ) goto fk_end; - if( pToCol && pToCol->nId!=1 ){ - sqliteErrorMsg(pParse, "foreign key on %s" - " should reference only one column of table %T", - p->aCol[iCol].zName, pTo); - goto fk_end; - } - nCol = 1; - }else if( pToCol && pToCol->nId!=pFromCol->nId ){ - sqliteErrorMsg(pParse, - "number of columns in foreign key does not match the number of " - "columns in the referenced table"); - goto fk_end; - }else{ - nCol = pFromCol->nId; - } - nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1; - if( pToCol ){ - for(i=0; inId; i++){ - nByte += strlen(pToCol->a[i].zName) + 1; - } - } - pFKey = sqliteMalloc( nByte ); - if( pFKey==0 ) goto fk_end; - pFKey->pFrom = p; - pFKey->pNextFrom = p->pFKey; - z = (char*)&pFKey[1]; - pFKey->aCol = (struct sColMap*)z; - z += sizeof(struct sColMap)*nCol; - pFKey->zTo = z; - memcpy(z, pTo->z, pTo->n); - z[pTo->n] = 0; - z += pTo->n+1; - pFKey->pNextTo = 0; - pFKey->nCol = nCol; - if( pFromCol==0 ){ - pFKey->aCol[0].iFrom = p->nCol-1; - }else{ - for(i=0; inCol; j++){ - if( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){ - pFKey->aCol[i].iFrom = j; - break; - } - } - if( j>=p->nCol ){ - sqliteErrorMsg(pParse, - "unknown column \"%s\" in foreign key definition", - pFromCol->a[i].zName); - goto fk_end; - } - } - } - if( pToCol ){ - for(i=0; ia[i].zName); - pFKey->aCol[i].zCol = z; - memcpy(z, pToCol->a[i].zName, n); - z[n] = 0; - z += n+1; - } - } - pFKey->isDeferred = 0; - pFKey->deleteConf = flags & 0xff; - pFKey->updateConf = (flags >> 8 ) & 0xff; - pFKey->insertConf = (flags >> 16 ) & 0xff; - - /* Link the foreign key to the table as the last step. - */ - p->pFKey = pFKey; - pFKey = 0; - -fk_end: - sqliteFree(pFKey); - sqliteIdListDelete(pFromCol); - sqliteIdListDelete(pToCol); -} - -/* -** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED -** clause is seen as part of a foreign key definition. The isDeferred -** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. -** The behavior of the most recently created foreign key is adjusted -** accordingly. -*/ -void sqliteDeferForeignKey(Parse *pParse, int isDeferred){ - Table *pTab; - FKey *pFKey; - if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; - pFKey->isDeferred = isDeferred; -} - -/* -** Create a new index for an SQL table. pIndex is the name of the index -** and pTable is the name of the table that is to be indexed. Both will -** be NULL for a primary key or an index that is created to satisfy a -** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable -** as the table to be indexed. pParse->pNewTable is a table that is -** currently being constructed by a CREATE TABLE statement. -** -** pList is a list of columns to be indexed. pList will be NULL if this -** is a primary key or unique-constraint on the most recent column added -** to the table currently under construction. -*/ -void sqliteCreateIndex( - Parse *pParse, /* All information about this parse */ - Token *pName, /* Name of the index. May be NULL */ - SrcList *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */ - IdList *pList, /* A list of columns to be indexed */ - int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ - Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ - Token *pEnd /* The ")" that closes the CREATE INDEX statement */ -){ - Table *pTab; /* Table to be indexed */ - Index *pIndex; /* The index to be created */ - char *zName = 0; - int i, j; - Token nullId; /* Fake token for an empty ID list */ - DbFixer sFix; /* For assigning database names to pTable */ - int isTemp; /* True for a temporary index */ - sqlite *db = pParse->db; - - if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index; - if( db->init.busy - && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName) - && sqliteFixSrcList(&sFix, pTable) - ){ - goto exit_create_index; - } - - /* - ** Find the table that is to be indexed. Return early if not found. - */ - if( pTable!=0 ){ - assert( pName!=0 ); - assert( pTable->nSrc==1 ); - pTab = sqliteSrcListLookup(pParse, pTable); - }else{ - assert( pName==0 ); - pTab = pParse->pNewTable; - } - if( pTab==0 || pParse->nErr ) goto exit_create_index; - if( pTab->readOnly ){ - sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName); - goto exit_create_index; - } - if( pTab->iDb>=2 && db->init.busy==0 ){ - sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName); - goto exit_create_index; - } - if( pTab->pSelect ){ - sqliteErrorMsg(pParse, "views may not be indexed"); - goto exit_create_index; - } - isTemp = pTab->iDb==1; - - /* - ** Find the name of the index. Make sure there is not already another - ** index or table with the same name. - ** - ** Exception: If we are reading the names of permanent indices from the - ** sqlite_master table (because some other process changed the schema) and - ** one of the index names collides with the name of a temporary table or - ** index, then we will continue to process this index. - ** - ** If pName==0 it means that we are - ** dealing with a primary key or UNIQUE constraint. We have to invent our - ** own name. - */ - if( pName && !db->init.busy ){ - Index *pISameName; /* Another index with the same name */ - Table *pTSameName; /* A table with same name as the index */ - zName = sqliteTableNameFromToken(pName); - if( zName==0 ) goto exit_create_index; - if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){ - sqliteErrorMsg(pParse, "index %s already exists", zName); - goto exit_create_index; - } - if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){ - sqliteErrorMsg(pParse, "there is already a table named %s", zName); - goto exit_create_index; - } - }else if( pName==0 ){ - char zBuf[30]; - int n; - Index *pLoop; - for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} - sprintf(zBuf,"%d)",n); - zName = 0; - sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0); - if( zName==0 ) goto exit_create_index; - }else{ - zName = sqliteStrNDup(pName->z, pName->n); - } - - /* Check for authorization to create an index. - */ -#ifndef SQLITE_OMIT_AUTHORIZATION - { - const char *zDb = db->aDb[pTab->iDb].zName; - - assert( pTab->iDb==db->init.iDb || isTemp ); - if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ - goto exit_create_index; - } - i = SQLITE_CREATE_INDEX; - if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX; - if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){ - goto exit_create_index; - } - } -#endif - - /* If pList==0, it means this routine was called to make a primary - ** key out of the last column added to the table under construction. - ** So create a fake list to simulate this. - */ - if( pList==0 ){ - nullId.z = pTab->aCol[pTab->nCol-1].zName; - nullId.n = strlen(nullId.z); - pList = sqliteIdListAppend(0, &nullId); - if( pList==0 ) goto exit_create_index; - } - - /* - ** Allocate the index structure. - */ - pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + - sizeof(int)*pList->nId ); - if( pIndex==0 ) goto exit_create_index; - pIndex->aiColumn = (int*)&pIndex[1]; - pIndex->zName = (char*)&pIndex->aiColumn[pList->nId]; - strcpy(pIndex->zName, zName); - pIndex->pTable = pTab; - pIndex->nColumn = pList->nId; - pIndex->onError = onError; - pIndex->autoIndex = pName==0; - pIndex->iDb = isTemp ? 1 : db->init.iDb; - - /* Scan the names of the columns of the table to be indexed and - ** load the column indices into the Index structure. Report an error - ** if any column is not found. - */ - for(i=0; inId; i++){ - for(j=0; jnCol; j++){ - if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break; - } - if( j>=pTab->nCol ){ - sqliteErrorMsg(pParse, "table %s has no column named %s", - pTab->zName, pList->a[i].zName); - sqliteFree(pIndex); - goto exit_create_index; - } - pIndex->aiColumn[i] = j; - } - - /* Link the new Index structure to its table and to the other - ** in-memory database structures. - */ - if( !pParse->explain ){ - Index *p; - p = sqliteHashInsert(&db->aDb[pIndex->iDb].idxHash, - pIndex->zName, strlen(pIndex->zName)+1, pIndex); - if( p ){ - assert( p==pIndex ); /* Malloc must have failed */ - sqliteFree(pIndex); - goto exit_create_index; - } - db->flags |= SQLITE_InternChanges; - } - - /* When adding an index to the list of indices for a table, make - ** sure all indices labeled OE_Replace come after all those labeled - ** OE_Ignore. This is necessary for the correct operation of UPDATE - ** and INSERT. - */ - if( onError!=OE_Replace || pTab->pIndex==0 - || pTab->pIndex->onError==OE_Replace){ - pIndex->pNext = pTab->pIndex; - pTab->pIndex = pIndex; - }else{ - Index *pOther = pTab->pIndex; - while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ - pOther = pOther->pNext; - } - pIndex->pNext = pOther->pNext; - pOther->pNext = pIndex; - } - - /* If the db->init.busy is 1 it means we are reading the SQL off the - ** "sqlite_master" table on the disk. So do not write to the disk - ** again. Extract the table number from the db->init.newTnum field. - */ - if( db->init.busy && pTable!=0 ){ - pIndex->tnum = db->init.newTnum; - } - - /* If the db->init.busy is 0 then create the index on disk. This - ** involves writing the index into the master table and filling in the - ** index with the current table contents. - ** - ** The db->init.busy is 0 when the user first enters a CREATE INDEX - ** command. db->init.busy is 1 when a database is opened and - ** CREATE INDEX statements are read out of the master table. In - ** the latter case the index already exists on disk, which is why - ** we don't want to recreate it. - ** - ** If pTable==0 it means this index is generated as a primary key - ** or UNIQUE constraint of a CREATE TABLE statement. Since the table - ** has just been created, it contains no data and the index initialization - ** step can be skipped. - */ - else if( db->init.busy==0 ){ - int n; - Vdbe *v; - int lbl1, lbl2; - int i; - int addr; - - v = sqliteGetVdbe(pParse); - if( v==0 ) goto exit_create_index; - if( pTable!=0 ){ - sqliteBeginWriteOperation(pParse, 0, isTemp); - sqliteOpenMasterTable(v, isTemp); - } - sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC); - sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0); - sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER); - pIndex->tnum = 0; - if( pTable ){ - sqliteVdbeCode(v, - OP_Dup, 0, 0, - OP_Integer, isTemp, 0, - OP_OpenWrite, 1, 0, - 0); - } - addr = sqliteVdbeAddOp(v, OP_String, 0, 0); - if( pStart && pEnd ){ - n = Addr(pEnd->z) - Addr(pStart->z) + 1; - sqliteVdbeChangeP3(v, addr, pStart->z, n); - } - sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); - if( pTable ){ - sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0); - lbl2 = sqliteVdbeMakeLabel(v); - sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2); - lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0); - for(i=0; inColumn; i++){ - int iCol = pIndex->aiColumn[i]; - if( pTab->iPKey==iCol ){ - sqliteVdbeAddOp(v, OP_Dup, i, 0); - }else{ - sqliteVdbeAddOp(v, OP_Column, 2, iCol); - } - } - sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); - if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex); - sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None, - "indexed columns are not unique", P3_STATIC); - sqliteVdbeAddOp(v, OP_Next, 2, lbl1); - sqliteVdbeResolveLabel(v, lbl2); - sqliteVdbeAddOp(v, OP_Close, 2, 0); - sqliteVdbeAddOp(v, OP_Close, 1, 0); - } - if( pTable!=0 ){ - if( !isTemp ){ - sqliteChangeCookie(db, v); - } - sqliteVdbeAddOp(v, OP_Close, 0, 0); - sqliteEndWriteOperation(pParse); - } - } - - /* Clean up before exiting */ -exit_create_index: - sqliteIdListDelete(pList); - sqliteSrcListDelete(pTable); - sqliteFree(zName); - return; -} - -/* -** This routine will drop an existing named index. This routine -** implements the DROP INDEX statement. -*/ -void sqliteDropIndex(Parse *pParse, SrcList *pName){ - Index *pIndex; - Vdbe *v; - sqlite *db = pParse->db; - - if( pParse->nErr || sqlite_malloc_failed ) return; - assert( pName->nSrc==1 ); - pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); - if( pIndex==0 ){ - sqliteErrorMsg(pParse, "no such index: %S", pName, 0); - goto exit_drop_index; - } - if( pIndex->autoIndex ){ - sqliteErrorMsg(pParse, "index associated with UNIQUE " - "or PRIMARY KEY constraint cannot be dropped", 0); - goto exit_drop_index; - } - if( pIndex->iDb>1 ){ - sqliteErrorMsg(pParse, "cannot alter schema of attached " - "databases", 0); - goto exit_drop_index; - } -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int code = SQLITE_DROP_INDEX; - Table *pTab = pIndex->pTable; - const char *zDb = db->aDb[pIndex->iDb].zName; - const char *zTab = SCHEMA_TABLE(pIndex->iDb); - if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ - goto exit_drop_index; - } - if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX; - if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ - goto exit_drop_index; - } - } -#endif - - /* Generate code to remove the index and from the master table */ - v = sqliteGetVdbe(pParse); - if( v ){ - static VdbeOpList dropIndex[] = { - { OP_Rewind, 0, ADDR(9), 0}, - { OP_String, 0, 0, 0}, /* 1 */ - { OP_MemStore, 1, 1, 0}, - { OP_MemLoad, 1, 0, 0}, /* 3 */ - { OP_Column, 0, 1, 0}, - { OP_Eq, 0, ADDR(8), 0}, - { OP_Next, 0, ADDR(3), 0}, - { OP_Goto, 0, ADDR(9), 0}, - { OP_Delete, 0, 0, 0}, /* 8 */ - }; - int base; - - sqliteBeginWriteOperation(pParse, 0, pIndex->iDb); - sqliteOpenMasterTable(v, pIndex->iDb); - base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex); - sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0); - if( pIndex->iDb==0 ){ - sqliteChangeCookie(db, v); - } - sqliteVdbeAddOp(v, OP_Close, 0, 0); - sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); - sqliteEndWriteOperation(pParse); - } - - /* Delete the in-memory description of this index. - */ - if( !pParse->explain ){ - sqliteUnlinkAndDeleteIndex(db, pIndex); - db->flags |= SQLITE_InternChanges; - } - -exit_drop_index: - sqliteSrcListDelete(pName); -} - -/* -** Append a new element to the given IdList. Create a new IdList if -** need be. -** -** A new IdList is returned, or NULL if malloc() fails. -*/ -IdList *sqliteIdListAppend(IdList *pList, Token *pToken){ - if( pList==0 ){ - pList = sqliteMalloc( sizeof(IdList) ); - if( pList==0 ) return 0; - pList->nAlloc = 0; - } - if( pList->nId>=pList->nAlloc ){ - struct IdList_item *a; - pList->nAlloc = pList->nAlloc*2 + 5; - a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) ); - if( a==0 ){ - sqliteIdListDelete(pList); - return 0; - } - pList->a = a; - } - memset(&pList->a[pList->nId], 0, sizeof(pList->a[0])); - if( pToken ){ - char **pz = &pList->a[pList->nId].zName; - sqliteSetNString(pz, pToken->z, pToken->n, 0); - if( *pz==0 ){ - sqliteIdListDelete(pList); - return 0; - }else{ - sqliteDequote(*pz); - } - } - pList->nId++; - return pList; -} - -/* -** Append a new table name to the given SrcList. Create a new SrcList if -** need be. A new entry is created in the SrcList even if pToken is NULL. -** -** A new SrcList is returned, or NULL if malloc() fails. -** -** If pDatabase is not null, it means that the table has an optional -** database name prefix. Like this: "database.table". The pDatabase -** points to the table name and the pTable points to the database name. -** The SrcList.a[].zName field is filled with the table name which might -** come from pTable (if pDatabase is NULL) or from pDatabase. -** SrcList.a[].zDatabase is filled with the database name from pTable, -** or with NULL if no database is specified. -** -** In other words, if call like this: -** -** sqliteSrcListAppend(A,B,0); -** -** Then B is a table name and the database name is unspecified. If called -** like this: -** -** sqliteSrcListAppend(A,B,C); -** -** Then C is the table name and B is the database name. -*/ -SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ - if( pList==0 ){ - pList = sqliteMalloc( sizeof(SrcList) ); - if( pList==0 ) return 0; - pList->nAlloc = 1; - } - if( pList->nSrc>=pList->nAlloc ){ - SrcList *pNew; - pList->nAlloc *= 2; - pNew = sqliteRealloc(pList, - sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); - if( pNew==0 ){ - sqliteSrcListDelete(pList); - return 0; - } - pList = pNew; - } - memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0])); - if( pDatabase && pDatabase->z==0 ){ - pDatabase = 0; - } - if( pDatabase && pTable ){ - Token *pTemp = pDatabase; - pDatabase = pTable; - pTable = pTemp; - } - if( pTable ){ - char **pz = &pList->a[pList->nSrc].zName; - sqliteSetNString(pz, pTable->z, pTable->n, 0); - if( *pz==0 ){ - sqliteSrcListDelete(pList); - return 0; - }else{ - sqliteDequote(*pz); - } - } - if( pDatabase ){ - char **pz = &pList->a[pList->nSrc].zDatabase; - sqliteSetNString(pz, pDatabase->z, pDatabase->n, 0); - if( *pz==0 ){ - sqliteSrcListDelete(pList); - return 0; - }else{ - sqliteDequote(*pz); - } - } - pList->a[pList->nSrc].iCursor = -1; - pList->nSrc++; - return pList; -} - -/* -** Assign cursors to all tables in a SrcList -*/ -void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){ - int i; - for(i=0; inSrc; i++){ - if( pList->a[i].iCursor<0 ){ - pList->a[i].iCursor = pParse->nTab++; - } - } -} - -/* -** Add an alias to the last identifier on the given identifier list. -*/ -void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){ - if( pList && pList->nSrc>0 ){ - int i = pList->nSrc - 1; - sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0); - sqliteDequote(pList->a[i].zAlias); - } -} - -/* -** Delete an IdList. -*/ -void sqliteIdListDelete(IdList *pList){ - int i; - if( pList==0 ) return; - for(i=0; inId; i++){ - sqliteFree(pList->a[i].zName); - } - sqliteFree(pList->a); - sqliteFree(pList); -} - -/* -** Return the index in pList of the identifier named zId. Return -1 -** if not found. -*/ -int sqliteIdListIndex(IdList *pList, const char *zName){ - int i; - if( pList==0 ) return -1; - for(i=0; inId; i++){ - if( sqliteStrICmp(pList->a[i].zName, zName)==0 ) return i; - } - return -1; -} - -/* -** Delete an entire SrcList including all its substructure. -*/ -void sqliteSrcListDelete(SrcList *pList){ - int i; - if( pList==0 ) return; - for(i=0; inSrc; i++){ - sqliteFree(pList->a[i].zDatabase); - sqliteFree(pList->a[i].zName); - sqliteFree(pList->a[i].zAlias); - if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){ - sqliteDeleteTable(0, pList->a[i].pTab); - } - sqliteSelectDelete(pList->a[i].pSelect); - sqliteExprDelete(pList->a[i].pOn); - sqliteIdListDelete(pList->a[i].pUsing); - } - sqliteFree(pList); -} - -/* -** Begin a transaction -*/ -void sqliteBeginTransaction(Parse *pParse, int onError){ - sqlite *db; - - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite_malloc_failed ) return; - if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; - if( db->flags & SQLITE_InTrans ){ - sqliteErrorMsg(pParse, "cannot start a transaction within a transaction"); - return; - } - sqliteBeginWriteOperation(pParse, 0, 0); - if( !pParse->explain ){ - db->flags |= SQLITE_InTrans; - db->onError = onError; - } -} - -/* -** Commit a transaction -*/ -void sqliteCommitTransaction(Parse *pParse){ - sqlite *db; - - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite_malloc_failed ) return; - if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; - if( (db->flags & SQLITE_InTrans)==0 ){ - sqliteErrorMsg(pParse, "cannot commit - no transaction is active"); - return; - } - if( !pParse->explain ){ - db->flags &= ~SQLITE_InTrans; - } - sqliteEndWriteOperation(pParse); - if( !pParse->explain ){ - db->onError = OE_Default; - } -} - -/* -** Rollback a transaction -*/ -void sqliteRollbackTransaction(Parse *pParse){ - sqlite *db; - Vdbe *v; - - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite_malloc_failed ) return; - if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; - if( (db->flags & SQLITE_InTrans)==0 ){ - sqliteErrorMsg(pParse, "cannot rollback - no transaction is active"); - return; - } - v = sqliteGetVdbe(pParse); - if( v ){ - sqliteVdbeAddOp(v, OP_Rollback, 0, 0); - } - if( !pParse->explain ){ - db->flags &= ~SQLITE_InTrans; - db->onError = OE_Default; - } -} - -/* -** Generate VDBE code that will verify the schema cookie for all -** named database files. -*/ -void sqliteCodeVerifySchema(Parse *pParse, int iDb){ - sqlite *db = pParse->db; - Vdbe *v = sqliteGetVdbe(pParse); - assert( iDb>=0 && iDbnDb ); - assert( db->aDb[iDb].pBt!=0 ); - if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){ - sqliteVdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie); - DbSetProperty(db, iDb, DB_Cookie); - } -} - -/* -** Generate VDBE code that prepares for doing an operation that -** might change the database. -** -** This routine starts a new transaction if we are not already within -** a transaction. If we are already within a transaction, then a checkpoint -** is set if the setCheckpoint parameter is true. A checkpoint should -** be set for operations that might fail (due to a constraint) part of -** the way through and which will need to undo some writes without having to -** rollback the whole transaction. For operations where all constraints -** can be checked before any changes are made to the database, it is never -** necessary to undo a write and the checkpoint should not be set. -** -** Only database iDb and the temp database are made writable by this call. -** If iDb==0, then the main and temp databases are made writable. If -** iDb==1 then only the temp database is made writable. If iDb>1 then the -** specified auxiliary database and the temp database are made writable. -*/ -void sqliteBeginWriteOperation(Parse *pParse, int setCheckpoint, int iDb){ - Vdbe *v; - sqlite *db = pParse->db; - if( DbHasProperty(db, iDb, DB_Locked) ) return; - v = sqliteGetVdbe(pParse); - if( v==0 ) return; - if( !db->aDb[iDb].inTrans ){ - sqliteVdbeAddOp(v, OP_Transaction, iDb, 0); - DbSetProperty(db, iDb, DB_Locked); - sqliteCodeVerifySchema(pParse, iDb); - if( iDb!=1 ){ - sqliteBeginWriteOperation(pParse, setCheckpoint, 1); - } - }else if( setCheckpoint ){ - sqliteVdbeAddOp(v, OP_Checkpoint, iDb, 0); - DbSetProperty(db, iDb, DB_Locked); - } -} - -/* -** Generate code that concludes an operation that may have changed -** the database. If a statement transaction was started, then emit -** an OP_Commit that will cause the changes to be committed to disk. -** -** Note that checkpoints are automatically committed at the end of -** a statement. Note also that there can be multiple calls to -** sqliteBeginWriteOperation() but there should only be a single -** call to sqliteEndWriteOperation() at the conclusion of the statement. -*/ -void sqliteEndWriteOperation(Parse *pParse){ - Vdbe *v; - sqlite *db = pParse->db; - if( pParse->trigStack ) return; /* if this is in a trigger */ - v = sqliteGetVdbe(pParse); - if( v==0 ) return; - if( db->flags & SQLITE_InTrans ){ - /* A BEGIN has executed. Do not commit until we see an explicit - ** COMMIT statement. */ - }else{ - sqliteVdbeAddOp(v, OP_Commit, 0, 0); - } -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/build.o b/dbLifeLog/DBD-SQLite2-0.33/build.o deleted file mode 100644 index 62d1beecb213946854a0ec8ebc5be86072f3a835..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37824 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 - - - if( sqlite_malloc_failed ) goto copy_cleanup; - assert( pTableName->nSrc==1 ); - pTab = sqliteSrcListLookup(pParse, pTableName); - if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup; - zFile = sqliteStrNDup(pFilename->z, pFilename->n); - sqliteDequote(zFile); - assert( pTab->iDbnDb ); - zDb = db->aDb[pTab->iDb].zName; - if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) - || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){ - goto copy_cleanup; - } - v = sqliteGetVdbe(pParse); - if( v ){ - sqliteBeginWriteOperation(pParse, 1, pTab->iDb); - addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n); - sqliteVdbeDequoteP3(v, addr); - sqliteOpenTableAndIndices(pParse, pTab, 0); - if( db->flags & SQLITE_CountRows ){ - sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */ - } - end = sqliteVdbeMakeLabel(v); - addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end); - if( pDelimiter ){ - sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n); - sqliteVdbeDequoteP3(v, addr); - }else{ - sqliteVdbeChangeP3(v, addr, "\t", 1); - } - if( pTab->iPKey>=0 ){ - sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0); - sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); - }else{ - sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); - } - for(i=0; inCol; i++){ - if( i==pTab->iPKey ){ - /* The integer primary key column is filled with NULL since its - ** value is always pulled from the record number */ - sqliteVdbeAddOp(v, OP_String, 0, 0); - }else{ - sqliteVdbeAddOp(v, OP_FileColumn, i, 0); - } - } - sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0, - 0, onError, addr); - sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1); - if( (db->flags & SQLITE_CountRows)!=0 ){ - sqliteVdbeAddOp(v, OP_AddImm, 1, 0); /* Increment row count */ - } - sqliteVdbeAddOp(v, OP_Goto, 0, addr); - sqliteVdbeResolveLabel(v, end); - sqliteVdbeAddOp(v, OP_Noop, 0, 0); - sqliteEndWriteOperation(pParse); - if( db->flags & SQLITE_CountRows ){ - sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); - sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC); - sqliteVdbeAddOp(v, OP_Callback, 1, 0); - } - } - -copy_cleanup: - sqliteSrcListDelete(pTableName); - sqliteFree(zFile); - return; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/copy.o b/dbLifeLog/DBD-SQLite2-0.33/copy.o deleted file mode 100644 index f6e08428c442552e415803b8e5257d9291291132..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4360 zcmbuCe{2&~9Khe!0p*9+iU>o7tFf9%OUsN#0Y;ZBf*U&#>k9+7>Qyufr){r$)<^He!s8pjYr!{O#CLd z_ul9G^L_97?sg`sw^UbE5iV8aMRI?|DIsScx<7BC(>p?#Ys)LW;SJ=C>v;>yQ zJXQa6KdG;<6I6Vy6(+Gvzi(_SP)ORfX98Qt^=(d+M4dL8DIN4HvlDsHs@LXpwhI{T zDVkcD)$K*@r#Z0q`H>-rHR3B=g+X_~pL?lJmlr)RPaKDEx(zC*qK?LCE6l6*7rwFU z;G{Zxp+6h#Dc!Mxe$2W+Z6fv^K7~-V%1mL_clKSH1?(nH(4a+AWd@4gA^_Eid!x#H zVdl(}x1+xL2yE6l74%2!Kd2v#uZ~VtMfaTWo(?KAFxKX;QyYl15+YHP+u!&3>c?P3 zph2y*YG+iLflUW6U$GJD!q@xM%eU&OxiSm-s4@w+jCN_dCI}5*qPl}GKiIBMAST_g zG8?hy=>6ckg*MdjIo+9zwyY}^n?Dx0x3t8fU4#yiiFKmO_@l7G2p1QjoQdU{l$lG^ z7=JQ6{@maHz>|Z`qN(vWLhGLkfG^`kug%M%2U}M#5`$^TXziP|6Ro)A*yAI%WO!tllCSl3{c6C^)eajP;0^>Ddsp0$zRSLbi zQk8a(u4%z~u@b_If>CFtClzWM+H!JujL~_T{Da&XEOuAe3cv#iD<1H=i(T?s8 zHLORwnL+npBAw3kcK0PxX*eW`UhUalJ(aT}M%u6p##*ulpE9+c$qeL&m^zl*ZzPg& zGkucBu(Eq2%j$@6ET379rRJ^v=6<7hfZ4Vh)`4UX4<9y;rp&G^R39HQvI#4dF_|42 z#fNqZD;9SjXW(IWBzn?@Y9?c5GSzG31naiMfT1UPjI_YiWHQb-f$^LB6XsE4Ibf?{ zVhzwpGiPNJDbu2b^Qg_4!69r?jGnR&R=VHFWzxqVNEkJfB^!h15rvy7i92ti8u zLJ?EG5$4=}6FjddXuk-wz7r#rG5E9}67M zO3vxqli7=TzZ2}mIKR4Zi5={vc@-CaMBtAL^_&uTy}&;ZxLD7p0uKoGR|GEFe<|=M z1p5Vni}s6*uoeg*|D#(BYoce(IE7k-*?tY?i-&pE+ftfvWVP_Rxs z=Xw1Bn4@4Ewne%oa_;1ymFR)d$`;3dKFb>EglrkZ7Lk()D?#L*T#m@u3@*@Ik>LnN zy_`4GsR09yM7cLJIB1yQVZtdWx9;uSp0g5g{>e0$(cj&dO$-{v)c@yi0G#pBEd5ex z0*1oB6N;^YI|_ zFEJyV@upM|?#ESwFhTafvkdD1^B>}dY~=Tk<9?V_y8nOS4F}=(8JGA-aDUG6T~w)6 t{^AEN!G9}7DXqU!?P!02)gNNPF&x%VnjdSblz) -#include -#include -#include - -#ifndef SQLITE_OMIT_DATETIME_FUNCS - -/* -** A structure for holding a single date and time. -*/ -typedef struct DateTime DateTime; -struct DateTime { - double rJD; /* The julian day number */ - int Y, M, D; /* Year, month, and day */ - int h, m; /* Hour and minutes */ - int tz; /* Timezone offset in minutes */ - double s; /* Seconds */ - char validYMD; /* True if Y,M,D are valid */ - char validHMS; /* True if h,m,s are valid */ - char validJD; /* True if rJD is valid */ - char validTZ; /* True if tz is valid */ -}; - - -/* -** Convert zDate into one or more integers. Additional arguments -** come in groups of 5 as follows: -** -** N number of digits in the integer -** min minimum allowed value of the integer -** max maximum allowed value of the integer -** nextC first character after the integer -** pVal where to write the integers value. -** -** Conversions continue until one with nextC==0 is encountered. -** The function returns the number of successful conversions. -*/ -static int getDigits(const char *zDate, ...){ - va_list ap; - int val; - int N; - int min; - int max; - int nextC; - int *pVal; - int cnt = 0; - va_start(ap, zDate); - do{ - N = va_arg(ap, int); - min = va_arg(ap, int); - max = va_arg(ap, int); - nextC = va_arg(ap, int); - pVal = va_arg(ap, int*); - val = 0; - while( N-- ){ - if( !isdigit(*zDate) ){ - return cnt; - } - val = val*10 + *zDate - '0'; - zDate++; - } - if( valmax || (nextC!=0 && nextC!=*zDate) ){ - return cnt; - } - *pVal = val; - zDate++; - cnt++; - }while( nextC ); - return cnt; -} - -/* -** Read text from z[] and convert into a floating point number. Return -** the number of digits converted. -*/ -static int getValue(const char *z, double *pR){ - const char *zEnd; - *pR = sqliteAtoF(z, &zEnd); - return zEnd - z; -} - -/* -** Parse a timezone extension on the end of a date-time. -** The extension is of the form: -** -** (+/-)HH:MM -** -** If the parse is successful, write the number of minutes -** of change in *pnMin and return 0. If a parser error occurs, -** return 0. -** -** A missing specifier is not considered an error. -*/ -static int parseTimezone(const char *zDate, DateTime *p){ - int sgn = 0; - int nHr, nMn; - while( isspace(*zDate) ){ zDate++; } - p->tz = 0; - if( *zDate=='-' ){ - sgn = -1; - }else if( *zDate=='+' ){ - sgn = +1; - }else{ - return *zDate!=0; - } - zDate++; - if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){ - return 1; - } - zDate += 5; - p->tz = sgn*(nMn + nHr*60); - while( isspace(*zDate) ){ zDate++; } - return *zDate!=0; -} - -/* -** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF. -** The HH, MM, and SS must each be exactly 2 digits. The -** fractional seconds FFFF can be one or more digits. -** -** Return 1 if there is a parsing error and 0 on success. -*/ -static int parseHhMmSs(const char *zDate, DateTime *p){ - int h, m, s; - double ms = 0.0; - if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){ - return 1; - } - zDate += 5; - if( *zDate==':' ){ - zDate++; - if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){ - return 1; - } - zDate += 2; - if( *zDate=='.' && isdigit(zDate[1]) ){ - double rScale = 1.0; - zDate++; - while( isdigit(*zDate) ){ - ms = ms*10.0 + *zDate - '0'; - rScale *= 10.0; - zDate++; - } - ms /= rScale; - } - }else{ - s = 0; - } - p->validJD = 0; - p->validHMS = 1; - p->h = h; - p->m = m; - p->s = s + ms; - if( parseTimezone(zDate, p) ) return 1; - p->validTZ = p->tz!=0; - return 0; -} - -/* -** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume -** that the YYYY-MM-DD is according to the Gregorian calendar. -** -** Reference: Meeus page 61 -*/ -static void computeJD(DateTime *p){ - int Y, M, D, A, B, X1, X2; - - if( p->validJD ) return; - if( p->validYMD ){ - Y = p->Y; - M = p->M; - D = p->D; - }else{ - Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */ - M = 1; - D = 1; - } - if( M<=2 ){ - Y--; - M += 12; - } - A = Y/100; - B = 2 - A + (A/4); - X1 = 365.25*(Y+4716); - X2 = 30.6001*(M+1); - p->rJD = X1 + X2 + D + B - 1524.5; - p->validJD = 1; - p->validYMD = 0; - if( p->validHMS ){ - p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0; - if( p->validTZ ){ - p->rJD += p->tz*60/86400.0; - p->validHMS = 0; - p->validTZ = 0; - } - } -} - -/* -** Parse dates of the form -** -** YYYY-MM-DD HH:MM:SS.FFF -** YYYY-MM-DD HH:MM:SS -** YYYY-MM-DD HH:MM -** YYYY-MM-DD -** -** Write the result into the DateTime structure and return 0 -** on success and 1 if the input string is not a well-formed -** date. -*/ -static int parseYyyyMmDd(const char *zDate, DateTime *p){ - int Y, M, D, neg; - - if( zDate[0]=='-' ){ - zDate++; - neg = 1; - }else{ - neg = 0; - } - if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){ - return 1; - } - zDate += 10; - while( isspace(*zDate) ){ zDate++; } - if( parseHhMmSs(zDate, p)==0 ){ - /* We got the time */ - }else if( *zDate==0 ){ - p->validHMS = 0; - }else{ - return 1; - } - p->validJD = 0; - p->validYMD = 1; - p->Y = neg ? -Y : Y; - p->M = M; - p->D = D; - if( p->validTZ ){ - computeJD(p); - } - return 0; -} - -/* -** Attempt to parse the given string into a Julian Day Number. Return -** the number of errors. -** -** The following are acceptable forms for the input string: -** -** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM -** DDDD.DD -** now -** -** In the first form, the +/-HH:MM is always optional. The fractional -** seconds extension (the ".FFF") is optional. The seconds portion -** (":SS.FFF") is option. The year and date can be omitted as long -** as there is a time string. The time string can be omitted as long -** as there is a year and date. -*/ -static int parseDateOrTime(const char *zDate, DateTime *p){ - memset(p, 0, sizeof(*p)); - if( parseYyyyMmDd(zDate,p)==0 ){ - return 0; - }else if( parseHhMmSs(zDate, p)==0 ){ - return 0; - }else if( sqliteStrICmp(zDate,"now")==0){ - double r; - if( sqliteOsCurrentTime(&r)==0 ){ - p->rJD = r; - p->validJD = 1; - return 0; - } - return 1; - }else if( sqliteIsNumber(zDate) ){ - p->rJD = sqliteAtoF(zDate, 0); - p->validJD = 1; - return 0; - } - return 1; -} - -/* -** Compute the Year, Month, and Day from the julian day number. -*/ -static void computeYMD(DateTime *p){ - int Z, A, B, C, D, E, X1; - if( p->validYMD ) return; - if( !p->validJD ){ - p->Y = 2000; - p->M = 1; - p->D = 1; - }else{ - Z = p->rJD + 0.5; - A = (Z - 1867216.25)/36524.25; - A = Z + 1 + A - (A/4); - B = A + 1524; - C = (B - 122.1)/365.25; - D = 365.25*C; - E = (B-D)/30.6001; - X1 = 30.6001*E; - p->D = B - D - X1; - p->M = E<14 ? E-1 : E-13; - p->Y = p->M>2 ? C - 4716 : C - 4715; - } - p->validYMD = 1; -} - -/* -** Compute the Hour, Minute, and Seconds from the julian day number. -*/ -static void computeHMS(DateTime *p){ - int Z, s; - if( p->validHMS ) return; - Z = p->rJD + 0.5; - s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5; - p->s = 0.001*s; - s = p->s; - p->s -= s; - p->h = s/3600; - s -= p->h*3600; - p->m = s/60; - p->s += s - p->m*60; - p->validHMS = 1; -} - -/* -** Compute both YMD and HMS -*/ -static void computeYMD_HMS(DateTime *p){ - computeYMD(p); - computeHMS(p); -} - -/* -** Clear the YMD and HMS and the TZ -*/ -static void clearYMD_HMS_TZ(DateTime *p){ - p->validYMD = 0; - p->validHMS = 0; - p->validTZ = 0; -} - -/* -** Compute the difference (in days) between localtime and UTC (a.k.a. GMT) -** for the time value p where p is in UTC. -*/ -static double localtimeOffset(DateTime *p){ - DateTime x, y; - time_t t; - struct tm *pTm; - x = *p; - computeYMD_HMS(&x); - if( x.Y<1971 || x.Y>=2038 ){ - x.Y = 2000; - x.M = 1; - x.D = 1; - x.h = 0; - x.m = 0; - x.s = 0.0; - } else { - int s = x.s + 0.5; - x.s = s; - } - x.tz = 0; - x.validJD = 0; - computeJD(&x); - t = (x.rJD-2440587.5)*86400.0 + 0.5; - sqliteOsEnterMutex(); - pTm = localtime(&t); - y.Y = pTm->tm_year + 1900; - y.M = pTm->tm_mon + 1; - y.D = pTm->tm_mday; - y.h = pTm->tm_hour; - y.m = pTm->tm_min; - y.s = pTm->tm_sec; - sqliteOsLeaveMutex(); - y.validYMD = 1; - y.validHMS = 1; - y.validJD = 0; - y.validTZ = 0; - computeJD(&y); - return y.rJD - x.rJD; -} - -/* -** Process a modifier to a date-time stamp. The modifiers are -** as follows: -** -** NNN days -** NNN hours -** NNN minutes -** NNN.NNNN seconds -** NNN months -** NNN years -** start of month -** start of year -** start of week -** start of day -** weekday N -** unixepoch -** localtime -** utc -** -** Return 0 on success and 1 if there is any kind of error. -*/ -static int parseModifier(const char *zMod, DateTime *p){ - int rc = 1; - int n; - double r; - char *z, zBuf[30]; - z = zBuf; - for(n=0; nrJD += localtimeOffset(p); - clearYMD_HMS_TZ(p); - rc = 0; - } - break; - } - case 'u': { - /* - ** unixepoch - ** - ** Treat the current value of p->rJD as the number of - ** seconds since 1970. Convert to a real julian day number. - */ - if( strcmp(z, "unixepoch")==0 && p->validJD ){ - p->rJD = p->rJD/86400.0 + 2440587.5; - clearYMD_HMS_TZ(p); - rc = 0; - }else if( strcmp(z, "utc")==0 ){ - double c1; - computeJD(p); - c1 = localtimeOffset(p); - p->rJD -= c1; - clearYMD_HMS_TZ(p); - p->rJD += c1 - localtimeOffset(p); - rc = 0; - } - break; - } - case 'w': { - /* - ** weekday N - ** - ** Move the date to the same time on the next occurrance of - ** weekday N where 0==Sunday, 1==Monday, and so forth. If the - ** date is already on the appropriate weekday, this is a no-op. - */ - if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0 - && (n=r)==r && n>=0 && r<7 ){ - int Z; - computeYMD_HMS(p); - p->validTZ = 0; - p->validJD = 0; - computeJD(p); - Z = p->rJD + 1.5; - Z %= 7; - if( Z>n ) Z -= 7; - p->rJD += n - Z; - clearYMD_HMS_TZ(p); - rc = 0; - } - break; - } - case 's': { - /* - ** start of TTTTT - ** - ** Move the date backwards to the beginning of the current day, - ** or month or year. - */ - if( strncmp(z, "start of ", 9)!=0 ) break; - z += 9; - computeYMD(p); - p->validHMS = 1; - p->h = p->m = 0; - p->s = 0.0; - p->validTZ = 0; - p->validJD = 0; - if( strcmp(z,"month")==0 ){ - p->D = 1; - rc = 0; - }else if( strcmp(z,"year")==0 ){ - computeYMD(p); - p->M = 1; - p->D = 1; - rc = 0; - }else if( strcmp(z,"day")==0 ){ - rc = 0; - } - break; - } - case '+': - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - n = getValue(z, &r); - if( n<=0 ) break; - if( z[n]==':' ){ - /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the - ** specified number of hours, minutes, seconds, and fractional seconds - ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be - ** omitted. - */ - const char *z2 = z; - DateTime tx; - int day; - if( !isdigit(*z2) ) z2++; - memset(&tx, 0, sizeof(tx)); - if( parseHhMmSs(z2, &tx) ) break; - computeJD(&tx); - tx.rJD -= 0.5; - day = (int)tx.rJD; - tx.rJD -= day; - if( z[0]=='-' ) tx.rJD = -tx.rJD; - computeJD(p); - clearYMD_HMS_TZ(p); - p->rJD += tx.rJD; - rc = 0; - break; - } - z += n; - while( isspace(z[0]) ) z++; - n = strlen(z); - if( n>10 || n<3 ) break; - if( z[n-1]=='s' ){ z[n-1] = 0; n--; } - computeJD(p); - rc = 0; - if( n==3 && strcmp(z,"day")==0 ){ - p->rJD += r; - }else if( n==4 && strcmp(z,"hour")==0 ){ - p->rJD += r/24.0; - }else if( n==6 && strcmp(z,"minute")==0 ){ - p->rJD += r/(24.0*60.0); - }else if( n==6 && strcmp(z,"second")==0 ){ - p->rJD += r/(24.0*60.0*60.0); - }else if( n==5 && strcmp(z,"month")==0 ){ - int x, y; - computeYMD_HMS(p); - p->M += r; - x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; - p->Y += x; - p->M -= x*12; - p->validJD = 0; - computeJD(p); - y = r; - if( y!=r ){ - p->rJD += (r - y)*30.0; - } - }else if( n==4 && strcmp(z,"year")==0 ){ - computeYMD_HMS(p); - p->Y += r; - p->validJD = 0; - computeJD(p); - }else{ - rc = 1; - } - clearYMD_HMS_TZ(p); - break; - } - default: { - break; - } - } - return rc; -} - -/* -** Process time function arguments. argv[0] is a date-time stamp. -** argv[1] and following are modifiers. Parse them all and write -** the resulting time into the DateTime structure p. Return 0 -** on success and 1 if there are any errors. -*/ -static int isDate(int argc, const char **argv, DateTime *p){ - int i; - if( argc==0 ) return 1; - if( argv[0]==0 || parseDateOrTime(argv[0], p) ) return 1; - for(i=1; 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 >= 3) { - PerlIO_printf(DBILOGFP, "sqlite error %d recorded: %s at %s line %d\n", - rc, what, file, line); - } -} - -int -sqlite2_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pass) -{ - dTHR; - int retval; - char *errmsg = NULL; - - if (DBIS->debug >= 3) { - PerlIO_printf(DBILOGFP, " login '%s' (version %s, encoding %s)\n", - dbname, sqlite_version, sqlite_encoding); - } - - if ((imp_dbh->db = sqlite_open(dbname, 0, &errmsg)) == NULL) { - sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, 1, errmsg); - sqlite_freemem(errmsg); - return FALSE; - } - DBIc_IMPSET_on(imp_dbh); - - imp_dbh->in_tran = FALSE; - imp_dbh->no_utf8_flag = FALSE; - imp_dbh->functions = newAV(); - imp_dbh->aggregates = newAV(); - imp_dbh->timeout = SQL_TIMEOUT; - - imp_dbh->handle_binary_nulls = FALSE; - - sqlite_busy_timeout(imp_dbh->db, SQL_TIMEOUT); - - if (retval = sqlite_exec(imp_dbh->db, "PRAGMA empty_result_callbacks = ON", - NULL, NULL, &errmsg) - != SQLITE_OK) - { - /* warn("failed to set pragma: %s\n", errmsg); */ - sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); - sqlite_freemem(errmsg); - return FALSE; - } - - if (retval = sqlite_exec(imp_dbh->db, "PRAGMA show_datatypes = ON", - NULL, NULL, &errmsg) - != SQLITE_OK) - { - /* warn("failed to set pragma: %s\n", errmsg); */ - sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); - sqlite_freemem(errmsg); - return FALSE; - } - - DBIc_ACTIVE_on(imp_dbh); - - return TRUE; -} - -int -sqlite2_busy_timeout ( SV *dbh, int timeout ) -{ - D_imp_dbh(dbh); - if (timeout) { - imp_dbh->timeout = timeout; - sqlite_busy_timeout(imp_dbh->db, timeout); - } - return imp_dbh->timeout; -} - -int -sqlite2_db_disconnect (SV *dbh, imp_dbh_t *imp_dbh) -{ - dTHR; - DBIc_ACTIVE_off(imp_dbh); - - if (DBIc_is(imp_dbh, DBIcf_AutoCommit) == FALSE) { - sqlite2_db_rollback(dbh, imp_dbh); - } - - sqlite_close(imp_dbh->db); - imp_dbh->db = NULL; - - av_undef(imp_dbh->functions); - imp_dbh->functions = (AV *)NULL; - - av_undef(imp_dbh->aggregates); - imp_dbh->aggregates = (AV *)NULL; - - return TRUE; -} - -void -sqlite2_db_destroy (SV *dbh, imp_dbh_t *imp_dbh) -{ - dTHR; - if (DBIc_ACTIVE(imp_dbh)) { - sqlite2_db_disconnect(dbh, imp_dbh); - } - DBIc_IMPSET_off(imp_dbh); -} - -int -sqlite2_db_rollback(SV *dbh, imp_dbh_t *imp_dbh) -{ - dTHR; - int retval; - char *errmsg; - - if (imp_dbh->in_tran) { - if (retval = sqlite_exec(imp_dbh->db, "ROLLBACK TRANSACTION", - NULL, NULL, &errmsg) - != SQLITE_OK) - { - sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); - sqlite_freemem(errmsg); - return FALSE; - } - imp_dbh->in_tran = FALSE; - } - - return TRUE; -} - -int -sqlite2_db_commit(SV *dbh, imp_dbh_t *imp_dbh) -{ - dTHR; - int retval; - char *errmsg; - - if (DBIc_is(imp_dbh, DBIcf_AutoCommit)) { - warn("commit ineffective with AutoCommit"); - return TRUE; - } - - if (imp_dbh->in_tran) { - if (retval = sqlite_exec(imp_dbh->db, "COMMIT TRANSACTION", - NULL, NULL, &errmsg) - != SQLITE_OK) - { - sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); - sqlite_freemem(errmsg); - return FALSE; - } - imp_dbh->in_tran = FALSE; - } - return TRUE; -} - -int -sqlite2_discon_all(SV *drh, imp_drh_t *imp_drh) -{ - dTHR; - return FALSE; /* no way to do this */ -} - -void -sqlite2_st_parse_sql(imp_sth_t *imp_sth, char *statement) -{ - D_imp_dbh_from_sth; - bool in_literal = FALSE; - SV *chunk; - int num_params = 0; - - chunk = NEWSV(0, strlen(statement)); - sv_setpv(chunk, ""); - - /* warn("parsing: %s\n", statement); */ - - while (*statement) { - /* warn("parse: %c => %s\n", *statement, SvPV_nolen(chunk)); */ - if (*statement == '\'') { - if (in_literal) { - /* either end of literal, or escape */ - if (statement[1] && statement[1] == '\'') { - statement++; - sv_catpvn(chunk, "''", 2); - } - else { - sv_catpvn(chunk, "'", 1); - in_literal = FALSE; - } - } - else { - in_literal = TRUE; - sv_catpvn(chunk, "'", 1); - } - } - else if (*statement == '?') { - if (in_literal) { - sv_catpvn(chunk, "?", 1); - } - else { - num_params++; - if (!imp_dbh->no_utf8_flag) { - /* sv_utf8_encode(chunk); */ - } - av_push(imp_sth->sql, chunk); - chunk = NEWSV(0, 20); - sv_setpvn(chunk, "", 0); - } - } - else { - sv_catpvn(chunk, statement, 1); - } - statement++; - } - av_push(imp_sth->sql, chunk); - DBIc_NUM_PARAMS(imp_sth) = num_params; -} - -int -sqlite2_st_prepare (SV *sth, imp_sth_t *imp_sth, - char *statement, SV *attribs) -{ - dTHR; - D_imp_dbh_from_sth; - - if (!DBIc_ACTIVE(imp_dbh)) { - die("prepare on an inactive database handle"); - } - - /* warn("prepare statement\n"); */ - imp_sth->nrow = 0; - imp_sth->ncols = 0; - imp_sth->params = newAV(); - imp_sth->sql = newAV(); - imp_sth->results = 0; - imp_sth->coldata = 0; - imp_sth->retval = SQLITE_OK; - sqlite2_st_parse_sql(imp_sth, statement); - - return TRUE; -} - -char * -sqlite2_quote(imp_dbh_t *imp_dbh, SV *val) -{ - STRLEN len; - char *cval = SvPV(val, len); - SV *ret = sv_2mortal(NEWSV(0, SvCUR(val) + 2)); - sv_setpvn(ret, "", 0); - - while (len) { - switch (*cval) { - case '\'': - sv_catpvn(ret, "''", 2); - break; - case 0: - if (imp_dbh->handle_binary_nulls) { - sv_catpvn(ret, "\\0", 2); - break; - } - else { - die("attempt to quote binary null without sqlite_handle_binary_nulls on"); - } - case '\\': - if (imp_dbh->handle_binary_nulls) { - sv_catpvn(ret, "\\\\", 2); - break; - } - default: - sv_catpvn(ret, cval, 1); - } - *cval++; len--; - } - return SvPV_nolen(ret); -} - -char * -sqlite2_decode(imp_dbh_t *imp_dbh, char *input, size_t *len) -{ - char *ret; - char *swit; - - New(1, ret, *len, char); - swit = ret; - - while (*input) { - switch (*input) { - case '\\': - if (imp_dbh->handle_binary_nulls && input[1] && input[1] == '0') { - *swit++ = '\0'; - *input++; - (*len)--; - break; - } - else if (imp_dbh->handle_binary_nulls && input[1] && input[1] == '\\') { - *swit++ = '\\'; - *input++; - (*len)--; - break; - } - default: - *swit++ = *input; - } - *input++; - } - return ret; -} - -int -_sqlite2_fetch_row (imp_sth_t *imp_sth) -{ - while (1) - { - imp_sth->retval = sqlite_step(imp_sth->vm, - &(imp_sth->ncols), (const char ***)&(imp_sth->results), (const char ***)&(imp_sth->coldata)); - if (imp_sth->retval == SQLITE_BUSY) { - break; /* We should never get "busy" here because we set sqlite_timeout, so assume error */ - } - break; - } - /* warn("step got: %d\nCol1: %s\n", imp_sth->retval, imp_sth->coldata[0]); */ - return imp_sth->retval; -} - -int -sqlite2_st_execute (SV *sth, imp_sth_t *imp_sth) -{ - dTHR; - D_imp_dbh_from_sth; - SV *sql; - I32 pos = 0; - char *errmsg; - int num_params = DBIc_NUM_PARAMS(imp_sth); - I32 i; - int retval; - - /* warn("execute\n"); */ - - if (DBIc_ACTIVE(imp_sth)) { - sqlite2_st_finish(sth, imp_sth); - } - - sql = sv_2mortal(newSVsv(AvARRAY(imp_sth->sql)[pos++])); - - for (i = 0; i < num_params; i++) { - SV *value = av_shift(imp_sth->params); - if (value && SvOK(value)) { - /* warn("binding param: %s\n", SvPV_nolen(value); */ - sv_catpvn(sql, "'", 1); - sv_catpv(sql, sqlite2_quote(imp_dbh, value)); - sv_catpvn(sql, "'", 1); - /* warn("inserting string length: %d\n", SvCUR(sql)); */ - } - else { - /* warn("binding NULL\n"); */ - sv_catpvn(sql, "NULL", 4); - } - if (value) { - SvREFCNT_dec(value); - } - sv_catsv(sql, AvARRAY(imp_sth->sql)[pos++]); - } - /* warn("Executing: %s;\n", SvPV_nolen(sql)); */ - - if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (!imp_dbh->in_tran) ) { - if (retval = sqlite_exec(imp_dbh->db, "BEGIN TRANSACTION", - NULL, NULL, &errmsg) - != SQLITE_OK) - { - sqlite2_error(sth, (imp_xxh_t*)imp_sth, retval, errmsg); - sqlite_freemem(errmsg); - return -2; - } - imp_dbh->in_tran = TRUE; - } - - imp_sth->results = NULL; - if (retval = sqlite_compile(imp_dbh->db, SvPV_nolen(sql), 0, &(imp_sth->vm), &errmsg) != SQLITE_OK) - { - sqlite2_error(sth, (imp_xxh_t*)imp_sth, retval, errmsg); - sqlite_freemem(errmsg); - return -2; - } - - if (_sqlite2_fetch_row(imp_sth) == SQLITE_ERROR) { - sqlite_finalize(imp_sth->vm, &errmsg); - sqlite2_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, errmsg); - sqlite_freemem(errmsg); - return -2; - } - - DBIc_NUM_FIELDS(imp_sth) = imp_sth->ncols; - imp_sth->nrow = -1; - - /* warn("Execute returned %d cols\n", imp_sth->ncols); */ - if (imp_sth->ncols == 0) { - sqlite_finalize(imp_sth->vm, 0); - imp_sth->nrow = sqlite_changes(imp_dbh->db); - DBIc_IMPSET_on(imp_sth); - return imp_sth->nrow; - } - - DBIc_ACTIVE_on(imp_sth); - /* warn("exec ok - %d rows, %d cols\n", imp_sth->nrow, imp_sth->ncols); */ - DBIc_IMPSET_on(imp_sth); - return 0; -} - -int -sqlite2_st_rows (SV *sth, imp_sth_t *imp_sth) -{ - return imp_sth->nrow; -} - -int -sqlite2_bind_ph (SV *sth, imp_sth_t *imp_sth, - SV *param, SV *value, IV sql_type, SV *attribs, - int is_inout, IV maxlen) -{ - if (is_inout) { - croak("InOut bind params not implemented"); - } - /* warn("bind: %s => %s\n", SvPV_nolen(param), SvPV_nolen(value)); */ - if (sql_type >= SQL_NUMERIC && sql_type <= SQL_DOUBLE) { - av_store(imp_sth->params, SvIV(param) - 1, newSVnv(SvNV(value))); - } - else { - av_store(imp_sth->params, SvIV(param) - 1, SvREFCNT_inc(value)); - } -} - -AV * -sqlite2_st_fetch (SV *sth, imp_sth_t *imp_sth) -{ - AV *av; - D_imp_dbh_from_sth; - int numFields = DBIc_NUM_FIELDS(imp_sth); - int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks); - int i; - - /* warn("current_entry == %d\nnumFields == %d\nnrow == %d", - current_entry, numFields, imp_sth->nrow); */ - - /* - if (!DBIc_ACTIVE(imp_sth)) { - return Nullav; - } - */ - - if ((imp_sth->retval == SQLITE_DONE) || (imp_sth->retval == SQLITE_ERROR)) { - sqlite2_st_finish(sth, imp_sth); - return Nullav; - } - - if (imp_sth->nrow == -1) { - imp_sth->nrow++; - } - imp_sth->nrow++; - - av = DBIS->get_fbav(imp_sth); - for (i = 0; i < numFields; i++) { - char *val = imp_sth->results[i]; - /* warn("fetching: %d == %s\n", i, val); */ - if (val != NULL) { - size_t len = strlen(val); - char *decoded; - if (chopBlanks) { - val = savepv(val); - while((len > 0) && (val[len-1] == ' ')) { - len--; - } - val[len] = '\0'; - } - decoded = sqlite2_decode(imp_dbh, val, &len); - sv_setpvn(AvARRAY(av)[i], decoded, len); - Safefree(decoded); - if (chopBlanks) Safefree(val); - - if (!imp_dbh->no_utf8_flag) { - /* sv_utf8_encode(AvARRAY(av)[i]); */ - } - } - else { - sv_setsv(AvARRAY(av)[i], &PL_sv_undef); - } - } - _sqlite2_fetch_row(imp_sth); - return av; -} - -int -sqlite2_st_finish (SV *sth, imp_sth_t *imp_sth) -{ - /* warn("finish statement\n"); */ - if (DBIc_ACTIVE(imp_sth)) { - char *errmsg; - DBIc_ACTIVE_off(imp_sth); - if (imp_sth->retval = sqlite_finalize(imp_sth->vm, &errmsg) == SQLITE_ERROR) { - warn("finalize failed! %s\n", errmsg); - sqlite2_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, errmsg); - sqlite_freemem(errmsg); - return FALSE; - } - } - return TRUE; -} - -void -sqlite2_st_destroy (SV *sth, imp_sth_t *imp_sth) -{ - /* warn("destroy statement\n"); */ - if (DBIc_ACTIVE(imp_sth)) { - sqlite2_st_finish(sth, imp_sth); - } - SvREFCNT_dec((SV*)imp_sth->sql); - SvREFCNT_dec((SV*)imp_sth->params); - DBIc_IMPSET_off(imp_sth); -} - -int -sqlite2_st_blob_read (SV *sth, imp_sth_t *imp_sth, - int field, long offset, long len, SV *destrv, long destoffset) -{ - return 0; -} - -int -sqlite2_db_STORE_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) -{ - dTHR; - char *key = SvPV_nolen(keysv); - char *errmsg; - int retval; - - if (strEQ(key, "AutoCommit")) { - if (SvTRUE(valuesv)) { - /* commit tran? */ - if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (imp_dbh->in_tran) ) { - if (retval = sqlite_exec(imp_dbh->db, "COMMIT TRANSACTION", - NULL, NULL, &errmsg) - != SQLITE_OK) - { - sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); - sqlite_freemem(errmsg); - return TRUE; - } - imp_dbh->in_tran = FALSE; - } - } - DBIc_set(imp_dbh, DBIcf_AutoCommit, SvTRUE(valuesv)); - return TRUE; - } - else if (strEQ(key, "sqlite_no_utf8_flag") || strEQ(key, "NoUTF8Flag")) { - warn("NoUTF8Flag is deprecated due to perl unicode weirdness\n"); - if (SvTRUE(valuesv)) { - imp_dbh->no_utf8_flag = TRUE; - } - else { - imp_dbh->no_utf8_flag = FALSE; - } - return TRUE; - } - else if (strEQ(key, "sqlite_handle_binary_nulls")) { - if (SvTRUE(valuesv)) { - imp_dbh->handle_binary_nulls = TRUE; - } - else { - imp_dbh->handle_binary_nulls = FALSE; - } - return TRUE; - } - return FALSE; -} - -SV * -sqlite2_db_FETCH_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) -{ - dTHR; - char *key = SvPV_nolen(keysv); - - if (strEQ(key, "sqlite_no_utf8_flag") || strEQ(key, "NoUTF8Flag")) { - return newSViv(imp_dbh->no_utf8_flag ? 1 : 0); - } - if (strEQ(key, "sqlite_version")) { - return newSVpv(sqlite_version, strlen(sqlite_version)); - } - if (strEQ(key, "sqlite_encoding")) { - return newSVpv(sqlite_encoding, strlen(sqlite_encoding)); - } - return NULL; -} - -int -sqlite2_st_STORE_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv) -{ - char *key = SvPV_nolen(keysv); - return FALSE; -} - -SV * -sqlite2_st_FETCH_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv) -{ - char *key = SvPV_nolen(keysv); - SV *retsv = NULL; - int i; - - if (!imp_sth->coldata) { - return retsv; - } - - i = DBIc_NUM_FIELDS(imp_sth); - - if (strEQ(key, "NAME")) { - AV *av = newAV(); - av_extend(av, i); - retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); - while (--i >= 0) { - char *fieldname = imp_sth->coldata[i]; - /* warn("Name [%d]: %s\n", i, fieldname); */ - char *dot = instr(fieldname, "."); - if (dot) /* drop table name from field name */ - fieldname = ++dot; - av_store(av, i, newSVpv(fieldname, 0)); - } - } - else if (strEQ(key, "PRECISION")) { - AV *av = newAV(); - retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); - } - else if (strEQ(key, "TYPE")) { - int i_base = i; - AV *av = newAV(); - av_extend(av, i); - retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); - i = i * 2; - while (--i >= i_base) { - char *fieldname = imp_sth->coldata[i]; - /* warn("Type [%d]: %s\n", i, fieldname); */ - char *dot = instr(fieldname, "."); - if (dot) /* drop table name from field name */ - fieldname = ++dot; - av_store(av, i - i_base, newSVpv(fieldname, 0)); - } - } - else if (strEQ(key, "NULLABLE")) { - AV *av = newAV(); - retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); - } - else if (strEQ(key, "SCALE")) { - AV *av = newAV(); - retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); - } - else if (strEQ(key, "NUM_OF_FIELDS")) { - retsv = sv_2mortal(newSViv(i)); - } - - return retsv; -} - -static void -sqlite2_db_set_result(sqlite_func *context, SV *result, int is_error ) -{ - STRLEN len; - char *s; - - if ( is_error ) { - s = SvPV(result, len); - sqlite_set_result_error( context, s, len ); - return; - } - - if ( !SvOK(result) ) { - sqlite_set_result_string( context, NULL, -1 ); - } else if( SvIOK(result) ) { - sqlite_set_result_int( context, SvIV(result)); - } else if ( !is_error && SvIOK(result) ) { - sqlite_set_result_double( context, SvNV(result)); - } else { - s = SvPV(result, len); - sqlite_set_result_string( context, s, len ); - } -} - -static void -sqlite2_db_func_dispatcher(sqlite_func *context, int argc, const char **argv) -{ - dSP; - int count; - int i; - SV *func; - - func = sqlite_user_data(context); - - ENTER; - SAVETMPS; - - PUSHMARK(SP); - for ( i=0; i < argc; i++ ) { - SV *arg; - - if ( !argv[i] ) { - arg = &PL_sv_undef; - } else { - arg = sv_2mortal( newSVpv(argv[i], 0)); - } - - XPUSHs(arg); - } - PUTBACK; - - count = call_sv(func, G_SCALAR|G_EVAL); - - SPAGAIN; - - /* Check for an error */ - if (SvTRUE(ERRSV) ) { - sqlite2_db_set_result( context, ERRSV, 1); - POPs; - } else if ( count != 1 ) { - SV *err = sv_2mortal(newSVpvf( "function should return 1 argument, got %d", - count )); - - sqlite2_db_set_result( context, err, 1); - /* Clear the stack */ - for ( i=0; i < count; i++ ) { - POPs; - } - } else { - sqlite2_db_set_result( context, POPs, 0 ); - } - - PUTBACK; - - FREETMPS; - LEAVE; -} - -void -sqlite2_db_create_function( SV *dbh, const char *name, int argc, SV *func ) -{ - D_imp_dbh(dbh); - int rv; - - /* Copy the function reference */ - SV *func_sv = newSVsv(func); - av_push( imp_dbh->functions, func_sv ); - - rv = sqlite_create_function( imp_dbh->db, name, argc, - sqlite2_db_func_dispatcher, func_sv ); - if ( rv != SQLITE_OK ) - { - croak( "sqlite_create_function failed with error %s", - sqlite_error_string(rv) ); - } -} - -typedef struct aggrInfo aggrInfo; -struct aggrInfo { - SV *aggr_inst; - SV *err; - int inited; -}; - -static void -sqlite2_db_aggr_new_dispatcher( sqlite_func *context, aggrInfo *aggr_info ) -{ - dSP; - SV *pkg = NULL; - int count = 0; - - aggr_info->err = NULL; - aggr_info->aggr_inst = NULL; - - pkg = sqlite_user_data(context); - if ( !pkg ) - return; - - ENTER; - SAVETMPS; - - PUSHMARK(SP); - XPUSHs( sv_2mortal( newSVsv(pkg) ) ); - PUTBACK; - - count = call_method ("new", G_EVAL|G_SCALAR); - SPAGAIN; - - aggr_info->inited = 1; - - if ( SvTRUE( ERRSV ) ) { - aggr_info->err = newSVpvf ("error during aggregator's new(): %s", - SvPV_nolen (ERRSV)); - POPs; - } else if ( count != 1 ) { - int i; - - aggr_info->err = newSVpvf( "new() should return one value, got %d", - count ); - /* Clear the stack */ - for ( i=0; i < count; i++ ) { - POPs; - } - } else { - SV *aggr = POPs; - if ( SvROK(aggr) ) { - aggr_info->aggr_inst = newSVsv(aggr); - } else{ - aggr_info->err = newSVpvf( "new() should return a blessed reference" ); - } - } - - PUTBACK; - - FREETMPS; - LEAVE; - - return; -} - -static void -sqlite2_db_aggr_step_dispatcher (sqlite_func *context, - int argc, const char **argv) -{ - dSP; - int i; - aggrInfo *aggr; - - aggr = sqlite_aggregate_context (context, sizeof (aggrInfo)); - if ( !aggr ) - return; - - ENTER; - SAVETMPS; - - /* initialize on first step */ - if ( !aggr->inited ) { - sqlite2_db_aggr_new_dispatcher( context, aggr ); - } - - if ( aggr->err || !aggr->aggr_inst ) - goto cleanup; - - PUSHMARK(SP); - XPUSHs( sv_2mortal( newSVsv( aggr->aggr_inst ) )); - for ( i=0; i < argc; i++ ) { - SV *arg; - - if ( !argv[i] ) { - arg = &PL_sv_undef; - } else { - arg = sv_2mortal( newSVpv(argv[i], 0)); - } - - XPUSHs(arg); - } - PUTBACK; - - call_method ("step", G_SCALAR|G_EVAL|G_DISCARD); - - /* Check for an error */ - if (SvTRUE(ERRSV) ) { - aggr->err = newSVpvf( "error during aggregator's step(): %s", - SvPV_nolen(ERRSV)); - POPs; - } - - cleanup: - FREETMPS; - LEAVE; -} - -static void -sqlite2_db_aggr_finalize_dispatcher( sqlite_func *context ) -{ - dSP; - aggrInfo *aggr, myAggr; - int count = 0; - - aggr = sqlite_aggregate_context (context, sizeof (aggrInfo)); - - ENTER; - SAVETMPS; - - if ( !aggr ) { - /* SQLite seems to refuse to create a context structure - from finalize() */ - aggr = &myAggr; - aggr->aggr_inst = NULL; - aggr->err = NULL; - sqlite2_db_aggr_new_dispatcher (context, aggr); - } - - if ( ! aggr->err && aggr->aggr_inst ) { - PUSHMARK(SP); - XPUSHs( sv_2mortal( newSVsv( aggr->aggr_inst )) ); - PUTBACK; - - count = call_method( "finalize", G_SCALAR|G_EVAL ); - SPAGAIN; - - if ( SvTRUE(ERRSV) ) { - aggr->err = newSVpvf ("error during aggregator's finalize(): %s", - SvPV_nolen(ERRSV) ) ; - POPs; - } else if ( count != 1 ) { - int i; - aggr->err = newSVpvf( "finalize() should return 1 value, got %d", - count ); - /* Clear the stack */ - for ( i=0; ierr ) { - warn( "DBD::SQLite: error in aggregator cannot be reported to SQLite: %s", SvPV_nolen( aggr->err ) ); - - /* sqlite2_db_set_result( context, aggr->err, 1 ); */ - SvREFCNT_dec( aggr->err ); - aggr->err = NULL; - } - - if ( aggr->aggr_inst ) { - SvREFCNT_dec( aggr->aggr_inst ); - aggr->aggr_inst = NULL; - } - - FREETMPS; - LEAVE; -} - -void -sqlite2_db_create_aggregate( SV *dbh, const char *name, int argc, SV *aggr_pkg ) -{ - D_imp_dbh(dbh); - int rv; - - /* Copy the aggregate reference */ - SV *aggr_pkg_copy = newSVsv(aggr_pkg); - av_push( imp_dbh->aggregates, aggr_pkg_copy ); - - rv = sqlite_create_aggregate( imp_dbh->db, name, argc, - sqlite2_db_aggr_step_dispatcher, - sqlite2_db_aggr_finalize_dispatcher, - aggr_pkg_copy ); - - if ( rv != SQLITE_OK ) - { - croak( "sqlite_create_aggregate failed with error %s", - sqlite_error_string(rv) ); - } -} - -/* end */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/dbdimp.h b/dbLifeLog/DBD-SQLite2-0.33/dbdimp.h deleted file mode 100644 index a1907e0..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/dbdimp.h +++ /dev/null @@ -1,104 +0,0 @@ -/* $Id: dbdimp.h,v 1.2 2004/08/09 13:17:59 matt Exp $ */ - -#ifndef _DBDIMP_H -#define _DBDIMP_H 1 - -#include "SQLiteXS.h" -#include "sqliteInt.h" - -/* 30 second timeout by default */ -#define SQL_TIMEOUT 30000 -#define BUSY_PAUSE_USEC 500 - -/* Driver Handle */ -struct imp_drh_st { - dbih_drc_t com; - /* sqlite specific bits */ -}; - -/* Database Handle */ -struct imp_dbh_st { - dbih_dbc_t com; - /* sqlite specific bits */ - struct sqlite *db; - bool in_tran; - bool no_utf8_flag; - bool handle_binary_nulls; - int timeout; - AV *functions; - AV *aggregates; -}; - -/* Statement Handle */ -struct imp_sth_st { - dbih_stc_t com; - /* sqlite specific bits */ - AV *sql; - sqlite_vm *vm; - char **results; - char **coldata; - int retval; - int nrow; - int ncols; - AV *params; -}; - -#define dbd_init sqlite2_init -#define dbd_discon_all sqlite2_discon_all -#define dbd_db_login sqlite2_db_login -#define dbd_db_do sqlite2_db_do -#define dbd_db_commit sqlite2_db_commit -#define dbd_db_rollback sqlite2_db_rollback -#define dbd_db_disconnect sqlite2_db_disconnect -#define dbd_db_destroy sqlite2_db_destroy -#define dbd_db_STORE_attrib sqlite2_db_STORE_attrib -#define dbd_db_FETCH_attrib sqlite2_db_FETCH_attrib -#define dbd_db_STORE_attrib_k sqlite2_db_STORE_attrib_k -#define dbd_db_FETCH_attrib_k sqlite2_db_FETCH_attrib_k -#define dbd_st_prepare sqlite2_st_prepare -#define dbd_st_rows sqlite2_st_rows -#define dbd_st_execute sqlite2_st_execute -#define dbd_st_fetch sqlite2_st_fetch -#define dbd_st_finish sqlite2_st_finish -#define dbd_st_destroy sqlite2_st_destroy -#define dbd_st_blob_read sqlite2_st_blob_read -#define dbd_st_STORE_attrib sqlite2_st_STORE_attrib -#define dbd_st_FETCH_attrib sqlite2_st_FETCH_attrib -#define dbd_st_STORE_attrib_k sqlite2_st_STORE_attrib_k -#define dbd_st_FETCH_attrib_k sqlite2_st_FETCH_attrib_k -#define dbd_bind_ph sqlite2_bind_ph - -void sqlite2_db_create_function(SV *dbh, const char *name, int argc, SV *func); -void sqlite2_db_create_aggregate( SV *dbh, const char *name, int argc, SV *aggr ); - -#ifdef SvUTF8_on - -static SV * -newUTF8SVpv(char *s, STRLEN len) { - register SV *sv; - - sv = newSVpv(s, len); - SvUTF8_on(sv); - return sv; -} /* End new UTF8SVpv */ - -static SV * -newUTF8SVpvn(char *s, STRLEN len) { - register SV *sv; - - sv = newSV(0); - sv_setpvn(sv, s, len); - SvUTF8_on(sv); - return sv; -} - -#else /* SvUTF8_on not defined */ - -#define newUTF8SVpv newSVpv -#define newUTF8SVpvn newSVpvn -#define SvUTF8_on(a) (a) -#define sv_utf8_upgrade(a) (a) - -#endif - -#endif /* _DBDIMP_H */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/dbdimp.o b/dbLifeLog/DBD-SQLite2-0.33/dbdimp.o deleted file mode 100644 index 38ddd962696f9f726d4b70d900f5a2be7fd3b95c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55512 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 Z#LJuicfc~`?{9F^{lz43PkZ?K{{bfk-D>~< diff --git a/dbLifeLog/DBD-SQLite2-0.33/delete.c b/dbLifeLog/DBD-SQLite2-0.33/delete.c deleted file mode 100644 index d289328..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/delete.c +++ /dev/null @@ -1,393 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle DELETE FROM statements. -** -** $Id: delete.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ -#include "sqliteInt.h" - -/* -** Look up every table that is named in pSrc. If any table is not found, -** add an error message to pParse->zErrMsg and return NULL. If all tables -** are found, return a pointer to the last table. -*/ -Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){ - Table *pTab = 0; - int i; - for(i=0; inSrc; i++){ - const char *zTab = pSrc->a[i].zName; - const char *zDb = pSrc->a[i].zDatabase; - pTab = sqliteLocateTable(pParse, zTab, zDb); - pSrc->a[i].pTab = pTab; - } - return pTab; -} - -/* -** Check to make sure the given table is writable. If it is not -** writable, generate an error message and return 1. If it is -** writable return 0; -*/ -int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){ - if( pTab->readOnly ){ - sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName); - return 1; - } - if( !viewOk && pTab->pSelect ){ - sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName); - return 1; - } - return 0; -} - -/* -** Process a DELETE FROM statement. -*/ -void sqliteDeleteFrom( - Parse *pParse, /* The parser context */ - SrcList *pTabList, /* The table from which we should delete things */ - Expr *pWhere /* The WHERE clause. May be null */ -){ - Vdbe *v; /* The virtual database engine */ - Table *pTab; /* The table from which records will be deleted */ - const char *zDb; /* Name of database holding pTab */ - int end, addr; /* A couple addresses of generated code */ - int i; /* Loop counter */ - WhereInfo *pWInfo; /* Information about the WHERE clause */ - Index *pIdx; /* For looping over indices of the table */ - int iCur; /* VDBE Cursor number for pTab */ - sqlite *db; /* Main database structure */ - int isView; /* True if attempting to delete from a view */ - AuthContext sContext; /* Authorization context */ - - int row_triggers_exist = 0; /* True if any triggers exist */ - int before_triggers; /* True if there are BEFORE triggers */ - int after_triggers; /* True if there are AFTER triggers */ - int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ - - sContext.pParse = 0; - if( pParse->nErr || sqlite_malloc_failed ){ - pTabList = 0; - goto delete_from_cleanup; - } - db = pParse->db; - assert( pTabList->nSrc==1 ); - - /* Locate the table which we want to delete. This table has to be - ** put in an SrcList structure because some of the subroutines we - ** will be calling are designed to work with multiple tables and expect - ** an SrcList* parameter instead of just a Table* parameter. - */ - pTab = sqliteSrcListLookup(pParse, pTabList); - if( pTab==0 ) goto delete_from_cleanup; - before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, - TK_DELETE, TK_BEFORE, TK_ROW, 0); - after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, - TK_DELETE, TK_AFTER, TK_ROW, 0); - row_triggers_exist = before_triggers || after_triggers; - isView = pTab->pSelect!=0; - if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){ - goto delete_from_cleanup; - } - assert( pTab->iDbnDb ); - zDb = db->aDb[pTab->iDb].zName; - if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ - goto delete_from_cleanup; - } - - /* If pTab is really a view, make sure it has been initialized. - */ - if( isView && sqliteViewGetColumnNames(pParse, pTab) ){ - goto delete_from_cleanup; - } - - /* Allocate a cursor used to store the old.* data for a trigger. - */ - if( row_triggers_exist ){ - oldIdx = pParse->nTab++; - } - - /* Resolve the column names in all the expressions. - */ - assert( pTabList->nSrc==1 ); - iCur = pTabList->a[0].iCursor = pParse->nTab++; - if( pWhere ){ - if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){ - goto delete_from_cleanup; - } - if( sqliteExprCheck(pParse, pWhere, 0, 0) ){ - goto delete_from_cleanup; - } - } - - /* Start the view context - */ - if( isView ){ - sqliteAuthContextPush(pParse, &sContext, pTab->zName); - } - - /* Begin generating code. - */ - v = sqliteGetVdbe(pParse); - if( v==0 ){ - goto delete_from_cleanup; - } - sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb); - - /* If we are trying to delete from a view, construct that view into - ** a temporary table. - */ - if( isView ){ - Select *pView = sqliteSelectDup(pTab->pSelect); - sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0); - sqliteSelectDelete(pView); - } - - /* Initialize the counter of the number of rows deleted, if - ** we are counting rows. - */ - if( db->flags & SQLITE_CountRows ){ - sqliteVdbeAddOp(v, OP_Integer, 0, 0); - } - - /* Special case: A DELETE without a WHERE clause deletes everything. - ** It is easier just to erase the whole table. Note, however, that - ** this means that the row change count will be incorrect. - */ - if( pWhere==0 && !row_triggers_exist ){ - if( db->flags & SQLITE_CountRows ){ - /* If counting rows deleted, just count the total number of - ** entries in the table. */ - int endOfLoop = sqliteVdbeMakeLabel(v); - int addr; - if( !isView ){ - sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); - } - sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2); - addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0); - sqliteVdbeAddOp(v, OP_Next, iCur, addr); - sqliteVdbeResolveLabel(v, endOfLoop); - sqliteVdbeAddOp(v, OP_Close, iCur, 0); - } - if( !isView ){ - sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb); - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb); - } - } - } - - /* The usual case: There is a WHERE clause so we have to scan through - ** the table and pick which records to delete. - */ - else{ - /* Begin the database scan - */ - pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0); - if( pWInfo==0 ) goto delete_from_cleanup; - - /* Remember the key of every item to be deleted. - */ - sqliteVdbeAddOp(v, OP_ListWrite, 0, 0); - if( db->flags & SQLITE_CountRows ){ - sqliteVdbeAddOp(v, OP_AddImm, 1, 0); - } - - /* End the database scan loop. - */ - sqliteWhereEnd(pWInfo); - - /* Open the pseudo-table used to store OLD if there are triggers. - */ - if( row_triggers_exist ){ - sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); - } - - /* Delete every item whose key was written to the list during the - ** database scan. We have to delete items after the scan is complete - ** because deleting an item can change the scan order. - */ - sqliteVdbeAddOp(v, OP_ListRewind, 0, 0); - end = sqliteVdbeMakeLabel(v); - - /* This is the beginning of the delete loop when there are - ** row triggers. - */ - if( row_triggers_exist ){ - addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); - sqliteVdbeAddOp(v, OP_Dup, 0, 0); - if( !isView ){ - sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); - } - sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0); - - sqliteVdbeAddOp(v, OP_Recno, iCur, 0); - sqliteVdbeAddOp(v, OP_RowData, iCur, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0); - if( !isView ){ - sqliteVdbeAddOp(v, OP_Close, iCur, 0); - } - - sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, - oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, - addr); - } - - if( !isView ){ - /* Open cursors for the table we are deleting from and all its - ** indices. If there are row triggers, this happens inside the - ** OP_ListRead loop because the cursor have to all be closed - ** before the trigger fires. If there are no row triggers, the - ** cursors are opened only once on the outside the loop. - */ - pParse->nTab = iCur + 1; - sqliteOpenTableAndIndices(pParse, pTab, iCur); - - /* This is the beginning of the delete loop when there are no - ** row triggers */ - if( !row_triggers_exist ){ - addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); - } - - /* Delete the row */ - sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0); - } - - /* If there are row triggers, close all cursors then invoke - ** the AFTER triggers - */ - if( row_triggers_exist ){ - if( !isView ){ - for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); - } - sqliteVdbeAddOp(v, OP_Close, iCur, 0); - } - sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, - oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, - addr); - } - - /* End of the delete loop */ - sqliteVdbeAddOp(v, OP_Goto, 0, addr); - sqliteVdbeResolveLabel(v, end); - sqliteVdbeAddOp(v, OP_ListReset, 0, 0); - - /* Close the cursors after the loop if there are no row triggers */ - if( !row_triggers_exist ){ - for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); - } - sqliteVdbeAddOp(v, OP_Close, iCur, 0); - pParse->nTab = iCur; - } - } - sqliteVdbeAddOp(v, OP_SetCounts, 0, 0); - sqliteEndWriteOperation(pParse); - - /* - ** Return the number of rows that were deleted. - */ - if( db->flags & SQLITE_CountRows ){ - sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); - sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC); - sqliteVdbeAddOp(v, OP_Callback, 1, 0); - } - -delete_from_cleanup: - sqliteAuthContextPop(&sContext); - sqliteSrcListDelete(pTabList); - sqliteExprDelete(pWhere); - return; -} - -/* -** This routine generates VDBE code that causes a single row of a -** single table to be deleted. -** -** The VDBE must be in a particular state when this routine is called. -** These are the requirements: -** -** 1. A read/write cursor pointing to pTab, the table containing the row -** to be deleted, must be opened as cursor number "base". -** -** 2. Read/write cursors for all indices of pTab must be open as -** cursor number base+i for the i-th index. -** -** 3. The record number of the row to be deleted must be on the top -** of the stack. -** -** This routine pops the top of the stack to remove the record number -** and then generates code to remove both the table record and all index -** entries that point to that record. -*/ -void sqliteGenerateRowDelete( - sqlite *db, /* The database containing the index */ - Vdbe *v, /* Generate code into this VDBE */ - Table *pTab, /* Table containing the row to be deleted */ - int iCur, /* Cursor number for the table */ - int count /* Increment the row change counter */ -){ - int addr; - addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0); - sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0); - sqliteVdbeAddOp(v, OP_Delete, iCur, - (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE); - sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); -} - -/* -** This routine generates VDBE code that causes the deletion of all -** index entries associated with a single row of a single table. -** -** The VDBE must be in a particular state when this routine is called. -** These are the requirements: -** -** 1. A read/write cursor pointing to pTab, the table containing the row -** to be deleted, must be opened as cursor number "iCur". -** -** 2. Read/write cursors for all indices of pTab must be open as -** cursor number iCur+i for the i-th index. -** -** 3. The "iCur" cursor must be pointing to the row that is to be -** deleted. -*/ -void sqliteGenerateRowIndexDelete( - sqlite *db, /* The database containing the index */ - Vdbe *v, /* Generate code into this VDBE */ - Table *pTab, /* Table containing the row to be deleted */ - int iCur, /* Cursor number for the table */ - char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */ -){ - int i; - Index *pIdx; - - for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - int j; - if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue; - sqliteVdbeAddOp(v, OP_Recno, iCur, 0); - for(j=0; jnColumn; j++){ - int idx = pIdx->aiColumn[j]; - if( idx==pTab->iPKey ){ - sqliteVdbeAddOp(v, OP_Dup, j, 0); - }else{ - sqliteVdbeAddOp(v, OP_Column, iCur, idx); - } - } - sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); - if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx); - sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0); - } -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/delete.o b/dbLifeLog/DBD-SQLite2-0.33/delete.o deleted file mode 100644 index 70846e99a902ad9107fa47e2cb74d2ba1c214c88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8848 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 -#include - -/* -** How This Encoder Works -** -** The output is allowed to contain any character except 0x27 (') and -** 0x00. This is accomplished by using an escape character to encode -** 0x27 and 0x00 as a two-byte sequence. The escape character is always -** 0x01. An 0x00 is encoded as the two byte sequence 0x01 0x01. The -** 0x27 character is encoded as the two byte sequence 0x01 0x28. Finally, -** the escape character itself is encoded as the two-character sequence -** 0x01 0x02. -** -** To summarize, the encoder works by using an escape sequences as follows: -** -** 0x00 -> 0x01 0x01 -** 0x01 -> 0x01 0x02 -** 0x27 -> 0x01 0x28 -** -** If that were all the encoder did, it would work, but in certain cases -** it could double the size of the encoded string. For example, to -** encode a string of 100 0x27 characters would require 100 instances of -** the 0x01 0x03 escape sequence resulting in a 200-character output. -** We would prefer to keep the size of the encoded string smaller than -** this. -** -** To minimize the encoding size, we first add a fixed offset value to each -** byte in the sequence. The addition is modulo 256. (That is to say, if -** the sum of the original character value and the offset exceeds 256, then -** the higher order bits are truncated.) The offset is chosen to minimize -** the number of characters in the string that need to be escaped. For -** example, in the case above where the string was composed of 100 0x27 -** characters, the offset might be 0x01. Each of the 0x27 characters would -** then be converted into an 0x28 character which would not need to be -** escaped at all and so the 100 character input string would be converted -** into just 100 characters of output. Actually 101 characters of output - -** we have to record the offset used as the first byte in the sequence so -** that the string can be decoded. Since the offset value is stored as -** part of the output string and the output string is not allowed to contain -** characters 0x00 or 0x27, the offset cannot be 0x00 or 0x27. -** -** Here, then, are the encoding steps: -** -** (1) Choose an offset value and make it the first character of -** output. -** -** (2) Copy each input character into the output buffer, one by -** one, adding the offset value as you copy. -** -** (3) If the value of an input character plus offset is 0x00, replace -** that one character by the two-character sequence 0x01 0x01. -** If the sum is 0x01, replace it with 0x01 0x02. If the sum -** is 0x27, replace it with 0x01 0x03. -** -** (4) Put a 0x00 terminator at the end of the output. -** -** Decoding is obvious: -** -** (5) Copy encoded characters except the first into the decode -** buffer. Set the first encoded character aside for use as -** the offset in step 7 below. -** -** (6) Convert each 0x01 0x01 sequence into a single character 0x00. -** Convert 0x01 0x02 into 0x01. Convert 0x01 0x28 into 0x27. -** -** (7) Subtract the offset value that was the first character of -** the encoded buffer from all characters in the output buffer. -** -** The only tricky part is step (1) - how to compute an offset value to -** minimize the size of the output buffer. This is accomplished by testing -** all offset values and picking the one that results in the fewest number -** of escapes. To do that, we first scan the entire input and count the -** number of occurances of each character value in the input. Suppose -** the number of 0x00 characters is N(0), the number of occurances of 0x01 -** is N(1), and so forth up to the number of occurances of 0xff is N(255). -** An offset of 0 is not allowed so we don't have to test it. The number -** of escapes required for an offset of 1 is N(1)+N(2)+N(40). The number -** of escapes required for an offset of 2 is N(2)+N(3)+N(41). And so forth. -** In this way we find the offset that gives the minimum number of escapes, -** and thus minimizes the length of the output string. -*/ - -/* -** Encode a binary buffer "in" of size n bytes so that it contains -** no instances of characters '\'' or '\000'. The output is -** null-terminated and can be used as a string value in an INSERT -** or UPDATE statement. Use sqlite_decode_binary() to convert the -** string back into its original binary. -** -** The result is written into a preallocated output buffer "out". -** "out" must be able to hold at least 2 +(257*n)/254 bytes. -** In other words, the output will be expanded by as much as 3 -** bytes for every 254 bytes of input plus 2 bytes of fixed overhead. -** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.) -** -** The return value is the number of characters in the encoded -** string, excluding the "\000" terminator. -** -** If out==NULL then no output is generated but the routine still returns -** the number of characters that would have been generated if out had -** not been NULL. -*/ -int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){ - int i, j, e, m; - unsigned char x; - int cnt[256]; - if( n<=0 ){ - if( out ){ - out[0] = 'x'; - out[1] = 0; - } - return 1; - } - memset(cnt, 0, sizeof(cnt)); - for(i=n-1; i>=0; i--){ cnt[in[i]]++; } - m = n; - for(i=1; i<256; i++){ - int sum; - if( i=='\'' ) continue; - sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff]; - if( sum -/* -** The subroutines above are not tested by the usual test suite. To test -** these routines, compile just this one file with a -DENCODER_TEST=1 option -** and run the result. -*/ -int main(int argc, char **argv){ - int i, j, n, m, nOut, nByteIn, nByteOut; - unsigned char in[30000]; - unsigned char out[33000]; - - nByteIn = nByteOut = 0; - for(i=0; i%d (max %d)", n, strlen(out)+1, m); - if( strlen(out)+1>m ){ - printf(" ERROR output too big\n"); - exit(1); - } - for(j=0; out[j]; j++){ - if( out[j]=='\'' ){ - printf(" ERROR contains (')\n"); - exit(1); - } - } - j = sqlite_decode_binary(out, out); - if( j!=n ){ - printf(" ERROR decode size %d\n", j); - exit(1); - } - if( memcmp(in, out, n)!=0 ){ - printf(" ERROR decode mismatch\n"); - exit(1); - } - printf(" OK\n"); - } - fprintf(stderr,"Finished. Total encoding: %d->%d bytes\n", - nByteIn, nByteOut); - fprintf(stderr,"Avg size increase: %.3f%%\n", - (nByteOut-nByteIn)*100.0/(double)nByteIn); -} -#endif /* ENCODER_TEST */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/encode.o b/dbLifeLog/DBD-SQLite2-0.33/encode.o deleted file mode 100644 index 4c982473f8aa53c1a55942121cb7c41b338bdad5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2096 zcmbVL?Q2_Q6hBXL=VGk6Q3@+gN$_Rsz+G~;F02YOH_OWnW>#EF=jL`vlN(x^rn9-h zR(wght@P4f*#|%PCkTT0Wo7#yMC-DSfk;6_^h4Pf3mKw}jco|=JU7qd!fiUnPPm+N ze&_w1C!Z#>DGwpQiNG;Vt!8)vrbg=s$kyRZ(TS3N{XxN%V{C* z6;_hAx)0TBR36;=xUpETey1*O*og=+&MrOorv1^28y5Boe(zr?Z)!9$wAwBs1nAL*XXoK@ai=`HidNHTc5X|_yb|Y zlt3^Z@MWGtH=1vl#f>ojFh)}g@K39okGJbf2Jqsq8+kEPH}b-+ZZKxqy#wys0e@l} z?nmU=jy|1TAr`_fxXl~j$PRc4ahiw6|GzuEoS!b}QXVSrmnIBdYwOzBL^(Gz2UfInnyKR-DOA>Aa1{=3$JaBfBpdLyXcDwvV>9{f2wd zKz9}64vfdx)9Yh8-6c)MUlPanG2H!vcXckA<)F;f4!nvO&H1?TGRx_n|55A5SbPL| zC-L}bCx|ldpYu!y*6I5CBhG)0#k<{O3>fcBiZb6nhu=k^+x - -/* -** Construct a new expression node and return a pointer to it. Memory -** for this node is obtained from sqliteMalloc(). The calling function -** is responsible for making sure the node eventually gets freed. -*/ -Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){ - Expr *pNew; - pNew = sqliteMalloc( sizeof(Expr) ); - if( pNew==0 ){ - /* When malloc fails, we leak memory from pLeft and pRight */ - return 0; - } - pNew->op = op; - pNew->pLeft = pLeft; - pNew->pRight = pRight; - if( pToken ){ - assert( pToken->dyn==0 ); - pNew->token = *pToken; - pNew->span = *pToken; - }else{ - assert( pNew->token.dyn==0 ); - assert( pNew->token.z==0 ); - assert( pNew->token.n==0 ); - if( pLeft && pRight ){ - sqliteExprSpan(pNew, &pLeft->span, &pRight->span); - }else{ - pNew->span = pNew->token; - } - } - return pNew; -} - -/* -** Set the Expr.span field of the given expression to span all -** text between the two given tokens. -*/ -void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ - assert( pRight!=0 ); - assert( pLeft!=0 ); - /* Note: pExpr might be NULL due to a prior malloc failure */ - if( pExpr && pRight->z && pLeft->z ){ - if( pLeft->dyn==0 && pRight->dyn==0 ){ - pExpr->span.z = pLeft->z; - pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z); - }else{ - pExpr->span.z = 0; - } - } -} - -/* -** Construct a new expression node for a function with multiple -** arguments. -*/ -Expr *sqliteExprFunction(ExprList *pList, Token *pToken){ - Expr *pNew; - pNew = sqliteMalloc( sizeof(Expr) ); - if( pNew==0 ){ - /* sqliteExprListDelete(pList); // Leak pList when malloc fails */ - return 0; - } - pNew->op = TK_FUNCTION; - pNew->pList = pList; - if( pToken ){ - assert( pToken->dyn==0 ); - pNew->token = *pToken; - }else{ - pNew->token.z = 0; - } - pNew->span = pNew->token; - return pNew; -} - -/* -** Recursively delete an expression tree. -*/ -void sqliteExprDelete(Expr *p){ - if( p==0 ) return; - if( p->span.dyn ) sqliteFree((char*)p->span.z); - if( p->token.dyn ) sqliteFree((char*)p->token.z); - sqliteExprDelete(p->pLeft); - sqliteExprDelete(p->pRight); - sqliteExprListDelete(p->pList); - sqliteSelectDelete(p->pSelect); - sqliteFree(p); -} - - -/* -** The following group of routines make deep copies of expressions, -** expression lists, ID lists, and select statements. The copies can -** be deleted (by being passed to their respective ...Delete() routines) -** without effecting the originals. -** -** The expression list, ID, and source lists return by sqliteExprListDup(), -** sqliteIdListDup(), and sqliteSrcListDup() can not be further expanded -** by subsequent calls to sqlite*ListAppend() routines. -** -** Any tables that the SrcList might point to are not duplicated. -*/ -Expr *sqliteExprDup(Expr *p){ - Expr *pNew; - if( p==0 ) return 0; - pNew = sqliteMallocRaw( sizeof(*p) ); - if( pNew==0 ) return 0; - memcpy(pNew, p, sizeof(*pNew)); - if( p->token.z!=0 ){ - pNew->token.z = sqliteStrDup(p->token.z); - pNew->token.dyn = 1; - }else{ - assert( pNew->token.z==0 ); - } - pNew->span.z = 0; - pNew->pLeft = sqliteExprDup(p->pLeft); - pNew->pRight = sqliteExprDup(p->pRight); - pNew->pList = sqliteExprListDup(p->pList); - pNew->pSelect = sqliteSelectDup(p->pSelect); - return pNew; -} -void sqliteTokenCopy(Token *pTo, Token *pFrom){ - if( pTo->dyn ) sqliteFree((char*)pTo->z); - if( pFrom->z ){ - pTo->n = pFrom->n; - pTo->z = sqliteStrNDup(pFrom->z, pFrom->n); - pTo->dyn = 1; - }else{ - pTo->z = 0; - } -} -ExprList *sqliteExprListDup(ExprList *p){ - ExprList *pNew; - struct ExprList_item *pItem; - int i; - if( p==0 ) return 0; - pNew = sqliteMalloc( sizeof(*pNew) ); - if( pNew==0 ) return 0; - pNew->nExpr = pNew->nAlloc = p->nExpr; - pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) ); - if( pItem==0 ){ - sqliteFree(pNew); - return 0; - } - for(i=0; inExpr; i++, pItem++){ - Expr *pNewExpr, *pOldExpr; - pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr); - if( pOldExpr->span.z!=0 && pNewExpr ){ - /* Always make a copy of the span for top-level expressions in the - ** expression list. The logic in SELECT processing that determines - ** the names of columns in the result set needs this information */ - sqliteTokenCopy(&pNewExpr->span, &pOldExpr->span); - } - assert( pNewExpr==0 || pNewExpr->span.z!=0 - || pOldExpr->span.z==0 || sqlite_malloc_failed ); - pItem->zName = sqliteStrDup(p->a[i].zName); - pItem->sortOrder = p->a[i].sortOrder; - pItem->isAgg = p->a[i].isAgg; - pItem->done = 0; - } - return pNew; -} -SrcList *sqliteSrcListDup(SrcList *p){ - SrcList *pNew; - int i; - int nByte; - if( p==0 ) return 0; - nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); - pNew = sqliteMallocRaw( nByte ); - if( pNew==0 ) return 0; - pNew->nSrc = pNew->nAlloc = p->nSrc; - for(i=0; inSrc; i++){ - struct SrcList_item *pNewItem = &pNew->a[i]; - struct SrcList_item *pOldItem = &p->a[i]; - pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); - pNewItem->zName = sqliteStrDup(pOldItem->zName); - pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); - pNewItem->jointype = pOldItem->jointype; - pNewItem->iCursor = pOldItem->iCursor; - pNewItem->pTab = 0; - pNewItem->pSelect = sqliteSelectDup(pOldItem->pSelect); - pNewItem->pOn = sqliteExprDup(pOldItem->pOn); - pNewItem->pUsing = sqliteIdListDup(pOldItem->pUsing); - } - return pNew; -} -IdList *sqliteIdListDup(IdList *p){ - IdList *pNew; - int i; - if( p==0 ) return 0; - pNew = sqliteMallocRaw( sizeof(*pNew) ); - if( pNew==0 ) return 0; - pNew->nId = pNew->nAlloc = p->nId; - pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) ); - if( pNew->a==0 ) return 0; - for(i=0; inId; i++){ - struct IdList_item *pNewItem = &pNew->a[i]; - struct IdList_item *pOldItem = &p->a[i]; - pNewItem->zName = sqliteStrDup(pOldItem->zName); - pNewItem->idx = pOldItem->idx; - } - return pNew; -} -Select *sqliteSelectDup(Select *p){ - Select *pNew; - if( p==0 ) return 0; - pNew = sqliteMallocRaw( sizeof(*p) ); - if( pNew==0 ) return 0; - pNew->isDistinct = p->isDistinct; - pNew->pEList = sqliteExprListDup(p->pEList); - pNew->pSrc = sqliteSrcListDup(p->pSrc); - pNew->pWhere = sqliteExprDup(p->pWhere); - pNew->pGroupBy = sqliteExprListDup(p->pGroupBy); - pNew->pHaving = sqliteExprDup(p->pHaving); - pNew->pOrderBy = sqliteExprListDup(p->pOrderBy); - pNew->op = p->op; - pNew->pPrior = sqliteSelectDup(p->pPrior); - pNew->nLimit = p->nLimit; - pNew->nOffset = p->nOffset; - pNew->zSelect = 0; - pNew->iLimit = -1; - pNew->iOffset = -1; - return pNew; -} - - -/* -** Add a new element to the end of an expression list. If pList is -** initially NULL, then create a new expression list. -*/ -ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){ - if( pList==0 ){ - pList = sqliteMalloc( sizeof(ExprList) ); - if( pList==0 ){ - /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */ - return 0; - } - assert( pList->nAlloc==0 ); - } - if( pList->nAlloc<=pList->nExpr ){ - pList->nAlloc = pList->nAlloc*2 + 4; - pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0])); - if( pList->a==0 ){ - /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */ - pList->nExpr = pList->nAlloc = 0; - return pList; - } - } - assert( pList->a!=0 ); - if( pExpr || pName ){ - struct ExprList_item *pItem = &pList->a[pList->nExpr++]; - memset(pItem, 0, sizeof(*pItem)); - pItem->pExpr = pExpr; - if( pName ){ - sqliteSetNString(&pItem->zName, pName->z, pName->n, 0); - sqliteDequote(pItem->zName); - } - } - return pList; -} - -/* -** Delete an entire expression list. -*/ -void sqliteExprListDelete(ExprList *pList){ - int i; - if( pList==0 ) return; - assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); - assert( pList->nExpr<=pList->nAlloc ); - for(i=0; inExpr; i++){ - sqliteExprDelete(pList->a[i].pExpr); - sqliteFree(pList->a[i].zName); - } - sqliteFree(pList->a); - sqliteFree(pList); -} - -/* -** Walk an expression tree. Return 1 if the expression is constant -** and 0 if it involves variables. -** -** For the purposes of this function, a double-quoted string (ex: "abc") -** is considered a variable but a single-quoted string (ex: 'abc') is -** a constant. -*/ -int sqliteExprIsConstant(Expr *p){ - switch( p->op ){ - case TK_ID: - case TK_COLUMN: - case TK_DOT: - case TK_FUNCTION: - return 0; - case TK_NULL: - case TK_STRING: - case TK_INTEGER: - case TK_FLOAT: - case TK_VARIABLE: - return 1; - default: { - if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0; - if( p->pRight && !sqliteExprIsConstant(p->pRight) ) return 0; - if( p->pList ){ - int i; - for(i=0; ipList->nExpr; i++){ - if( !sqliteExprIsConstant(p->pList->a[i].pExpr) ) return 0; - } - } - return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0); - } - } - return 0; -} - -/* -** If the given expression codes a constant integer that is small enough -** to fit in a 32-bit integer, return 1 and put the value of the integer -** in *pValue. If the expression is not an integer or if it is too big -** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. -*/ -int sqliteExprIsInteger(Expr *p, int *pValue){ - switch( p->op ){ - case TK_INTEGER: { - if( sqliteFitsIn32Bits(p->token.z) ){ - *pValue = atoi(p->token.z); - return 1; - } - break; - } - case TK_STRING: { - const char *z = p->token.z; - int n = p->token.n; - if( n>0 && z[0]=='-' ){ z++; n--; } - while( n>0 && *z && isdigit(*z) ){ z++; n--; } - if( n==0 && sqliteFitsIn32Bits(p->token.z) ){ - *pValue = atoi(p->token.z); - return 1; - } - break; - } - case TK_UPLUS: { - return sqliteExprIsInteger(p->pLeft, pValue); - } - case TK_UMINUS: { - int v; - if( sqliteExprIsInteger(p->pLeft, &v) ){ - *pValue = -v; - return 1; - } - break; - } - default: break; - } - return 0; -} - -/* -** Return TRUE if the given string is a row-id column name. -*/ -int sqliteIsRowid(const char *z){ - if( sqliteStrICmp(z, "_ROWID_")==0 ) return 1; - if( sqliteStrICmp(z, "ROWID")==0 ) return 1; - if( sqliteStrICmp(z, "OID")==0 ) return 1; - return 0; -} - -/* -** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up -** that name in the set of source tables in pSrcList and make the pExpr -** expression node refer back to that source column. The following changes -** are made to pExpr: -** -** pExpr->iDb Set the index in db->aDb[] of the database holding -** the table. -** pExpr->iTable Set to the cursor number for the table obtained -** from pSrcList. -** pExpr->iColumn Set to the column number within the table. -** pExpr->dataType Set to the appropriate data type for the column. -** pExpr->op Set to TK_COLUMN. -** pExpr->pLeft Any expression this points to is deleted -** pExpr->pRight Any expression this points to is deleted. -** -** The pDbToken is the name of the database (the "X"). This value may be -** NULL meaning that name is of the form Y.Z or Z. Any available database -** can be used. The pTableToken is the name of the table (the "Y"). This -** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it -** means that the form of the name is Z and that columns from any table -** can be used. -** -** If the name cannot be resolved unambiguously, leave an error message -** in pParse and return non-zero. Return zero on success. -*/ -static int lookupName( - Parse *pParse, /* The parsing context */ - Token *pDbToken, /* Name of the database containing table, or NULL */ - Token *pTableToken, /* Name of table containing column, or NULL */ - Token *pColumnToken, /* Name of the column. */ - SrcList *pSrcList, /* List of tables used to resolve column names */ - ExprList *pEList, /* List of expressions used to resolve "AS" */ - Expr *pExpr /* Make this EXPR node point to the selected column */ -){ - char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ - char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */ - char *zCol = 0; /* Name of the column. The "Z" */ - int i, j; /* Loop counters */ - int cnt = 0; /* Number of matching column names */ - int cntTab = 0; /* Number of matching table names */ - sqlite *db = pParse->db; /* The database */ - - assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ - if( pDbToken && pDbToken->z ){ - zDb = sqliteStrNDup(pDbToken->z, pDbToken->n); - sqliteDequote(zDb); - }else{ - zDb = 0; - } - if( pTableToken && pTableToken->z ){ - zTab = sqliteStrNDup(pTableToken->z, pTableToken->n); - sqliteDequote(zTab); - }else{ - assert( zDb==0 ); - zTab = 0; - } - zCol = sqliteStrNDup(pColumnToken->z, pColumnToken->n); - sqliteDequote(zCol); - if( sqlite_malloc_failed ){ - return 1; /* Leak memory (zDb and zTab) if malloc fails */ - } - assert( zTab==0 || pEList==0 ); - - pExpr->iTable = -1; - for(i=0; inSrc; i++){ - struct SrcList_item *pItem = &pSrcList->a[i]; - Table *pTab = pItem->pTab; - Column *pCol; - - if( pTab==0 ) continue; - assert( pTab->nCol>0 ); - if( zTab ){ - if( pItem->zAlias ){ - char *zTabName = pItem->zAlias; - if( sqliteStrICmp(zTabName, zTab)!=0 ) continue; - }else{ - char *zTabName = pTab->zName; - if( zTabName==0 || sqliteStrICmp(zTabName, zTab)!=0 ) continue; - if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){ - continue; - } - } - } - if( 0==(cntTab++) ){ - pExpr->iTable = pItem->iCursor; - pExpr->iDb = pTab->iDb; - } - for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ - if( sqliteStrICmp(pCol->zName, zCol)==0 ){ - cnt++; - pExpr->iTable = pItem->iCursor; - pExpr->iDb = pTab->iDb; - /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ - pExpr->iColumn = j==pTab->iPKey ? -1 : j; - pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK; - break; - } - } - } - - /* If we have not already resolved the name, then maybe - ** it is a new.* or old.* trigger argument reference - */ - if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){ - TriggerStack *pTriggerStack = pParse->trigStack; - Table *pTab = 0; - if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zTab) == 0 ){ - pExpr->iTable = pTriggerStack->newIdx; - assert( pTriggerStack->pTab ); - pTab = pTriggerStack->pTab; - }else if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zTab) == 0 ){ - pExpr->iTable = pTriggerStack->oldIdx; - assert( pTriggerStack->pTab ); - pTab = pTriggerStack->pTab; - } - - if( pTab ){ - int j; - Column *pCol = pTab->aCol; - - pExpr->iDb = pTab->iDb; - cntTab++; - for(j=0; j < pTab->nCol; j++, pCol++) { - if( sqliteStrICmp(pCol->zName, zCol)==0 ){ - cnt++; - pExpr->iColumn = j==pTab->iPKey ? -1 : j; - pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK; - break; - } - } - } - } - - /* - ** Perhaps the name is a reference to the ROWID - */ - if( cnt==0 && cntTab==1 && sqliteIsRowid(zCol) ){ - cnt = 1; - pExpr->iColumn = -1; - pExpr->dataType = SQLITE_SO_NUM; - } - - /* - ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z - ** might refer to an result-set alias. This happens, for example, when - ** we are resolving names in the WHERE clause of the following command: - ** - ** SELECT a+b AS x FROM table WHERE x<10; - ** - ** In cases like this, replace pExpr with a copy of the expression that - ** forms the result set entry ("a+b" in the example) and return immediately. - ** Note that the expression in the result set should have already been - ** resolved by the time the WHERE clause is resolved. - */ - if( cnt==0 && pEList!=0 ){ - for(j=0; jnExpr; j++){ - char *zAs = pEList->a[j].zName; - if( zAs!=0 && sqliteStrICmp(zAs, zCol)==0 ){ - assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - pExpr->op = TK_AS; - pExpr->iColumn = j; - pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr); - sqliteFree(zCol); - assert( zTab==0 && zDb==0 ); - return 0; - } - } - } - - /* - ** If X and Y are NULL (in other words if only the column name Z is - ** supplied) and the value of Z is enclosed in double-quotes, then - ** Z is a string literal if it doesn't match any column names. In that - ** case, we need to return right away and not make any changes to - ** pExpr. - */ - if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ - sqliteFree(zCol); - return 0; - } - - /* - ** cnt==0 means there was not match. cnt>1 means there were two or - ** more matches. Either way, we have an error. - */ - if( cnt!=1 ){ - char *z = 0; - char *zErr; - zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; - if( zDb ){ - sqliteSetString(&z, zDb, ".", zTab, ".", zCol, 0); - }else if( zTab ){ - sqliteSetString(&z, zTab, ".", zCol, 0); - }else{ - z = sqliteStrDup(zCol); - } - sqliteErrorMsg(pParse, zErr, z); - sqliteFree(z); - } - - /* Clean up and return - */ - sqliteFree(zDb); - sqliteFree(zTab); - sqliteFree(zCol); - sqliteExprDelete(pExpr->pLeft); - pExpr->pLeft = 0; - sqliteExprDelete(pExpr->pRight); - pExpr->pRight = 0; - pExpr->op = TK_COLUMN; - sqliteAuthRead(pParse, pExpr, pSrcList); - return cnt!=1; -} - -/* -** This routine walks an expression tree and resolves references to -** table columns. Nodes of the form ID.ID or ID resolve into an -** index to the table in the table list and a column offset. The -** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable -** value is changed to the index of the referenced table in pTabList -** plus the "base" value. The base value will ultimately become the -** VDBE cursor number for a cursor that is pointing into the referenced -** table. The Expr.iColumn value is changed to the index of the column -** of the referenced table. The Expr.iColumn value for the special -** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an -** alias for ROWID. -** -** We also check for instances of the IN operator. IN comes in two -** forms: -** -** expr IN (exprlist) -** and -** expr IN (SELECT ...) -** -** The first form is handled by creating a set holding the list -** of allowed values. The second form causes the SELECT to generate -** a temporary table. -** -** This routine also looks for scalar SELECTs that are part of an expression. -** If it finds any, it generates code to write the value of that select -** into a memory cell. -** -** Unknown columns or tables provoke an error. The function returns -** the number of errors seen and leaves an error message on pParse->zErrMsg. -*/ -int sqliteExprResolveIds( - Parse *pParse, /* The parser context */ - SrcList *pSrcList, /* List of tables used to resolve column names */ - ExprList *pEList, /* List of expressions used to resolve "AS" */ - Expr *pExpr /* The expression to be analyzed. */ -){ - int i; - - if( pExpr==0 || pSrcList==0 ) return 0; - for(i=0; inSrc; i++){ - assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab ); - } - switch( pExpr->op ){ - /* Double-quoted strings (ex: "abc") are used as identifiers if - ** possible. Otherwise they remain as strings. Single-quoted - ** strings (ex: 'abc') are always string literals. - */ - case TK_STRING: { - if( pExpr->token.z[0]=='\'' ) break; - /* Fall thru into the TK_ID case if this is a double-quoted string */ - } - /* A lone identifier is the name of a columnd. - */ - case TK_ID: { - if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){ - return 1; - } - break; - } - - /* A table name and column name: ID.ID - ** Or a database, table and column: ID.ID.ID - */ - case TK_DOT: { - Token *pColumn; - Token *pTable; - Token *pDb; - Expr *pRight; - - pRight = pExpr->pRight; - if( pRight->op==TK_ID ){ - pDb = 0; - pTable = &pExpr->pLeft->token; - pColumn = &pRight->token; - }else{ - assert( pRight->op==TK_DOT ); - pDb = &pExpr->pLeft->token; - pTable = &pRight->pLeft->token; - pColumn = &pRight->pRight->token; - } - if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){ - return 1; - } - break; - } - - case TK_IN: { - Vdbe *v = sqliteGetVdbe(pParse); - if( v==0 ) return 1; - if( sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){ - return 1; - } - if( pExpr->pSelect ){ - /* Case 1: expr IN (SELECT ...) - ** - ** Generate code to write the results of the select into a temporary - ** table. The cursor number of the temporary table has already - ** been put in iTable by sqliteExprResolveInSelect(). - */ - pExpr->iTable = pParse->nTab++; - sqliteVdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1); - sqliteSelect(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0); - }else if( pExpr->pList ){ - /* Case 2: expr IN (exprlist) - ** - ** Create a set to put the exprlist values in. The Set id is stored - ** in iTable. - */ - int i, iSet; - for(i=0; ipList->nExpr; i++){ - Expr *pE2 = pExpr->pList->a[i].pExpr; - if( !sqliteExprIsConstant(pE2) ){ - sqliteErrorMsg(pParse, - "right-hand side of IN operator must be constant"); - return 1; - } - if( sqliteExprCheck(pParse, pE2, 0, 0) ){ - return 1; - } - } - iSet = pExpr->iTable = pParse->nSet++; - for(i=0; ipList->nExpr; i++){ - Expr *pE2 = pExpr->pList->a[i].pExpr; - switch( pE2->op ){ - case TK_FLOAT: - case TK_INTEGER: - case TK_STRING: { - int addr; - assert( pE2->token.z ); - addr = sqliteVdbeOp3(v, OP_SetInsert, iSet, 0, - pE2->token.z, pE2->token.n); - sqliteVdbeDequoteP3(v, addr); - break; - } - default: { - sqliteExprCode(pParse, pE2); - sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0); - break; - } - } - } - } - break; - } - - case TK_SELECT: { - /* This has to be a scalar SELECT. Generate code to put the - ** value of this select in a memory cell and record the number - ** of the memory cell in iColumn. - */ - pExpr->iColumn = pParse->nMem++; - if( sqliteSelect(pParse, pExpr->pSelect, SRT_Mem, pExpr->iColumn,0,0,0) ){ - return 1; - } - break; - } - - /* For all else, just recursively walk the tree */ - default: { - if( pExpr->pLeft - && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){ - return 1; - } - if( pExpr->pRight - && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){ - return 1; - } - if( pExpr->pList ){ - int i; - ExprList *pList = pExpr->pList; - for(i=0; inExpr; i++){ - Expr *pArg = pList->a[i].pExpr; - if( sqliteExprResolveIds(pParse, pSrcList, pEList, pArg) ){ - return 1; - } - } - } - } - } - return 0; -} - -/* -** pExpr is a node that defines a function of some kind. It might -** be a syntactic function like "count(x)" or it might be a function -** that implements an operator, like "a LIKE b". -** -** This routine makes *pzName point to the name of the function and -** *pnName hold the number of characters in the function name. -*/ -static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){ - switch( pExpr->op ){ - case TK_FUNCTION: { - *pzName = pExpr->token.z; - *pnName = pExpr->token.n; - break; - } - case TK_LIKE: { - *pzName = "like"; - *pnName = 4; - break; - } - case TK_GLOB: { - *pzName = "glob"; - *pnName = 4; - break; - } - default: { - *pzName = "can't happen"; - *pnName = 12; - break; - } - } -} - -/* -** Error check the functions in an expression. Make sure all -** function names are recognized and all functions have the correct -** number of arguments. Leave an error message in pParse->zErrMsg -** if anything is amiss. Return the number of errors. -** -** if pIsAgg is not null and this expression is an aggregate function -** (like count(*) or max(value)) then write a 1 into *pIsAgg. -*/ -int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){ - int nErr = 0; - if( pExpr==0 ) return 0; - switch( pExpr->op ){ - case TK_GLOB: - case TK_LIKE: - case TK_FUNCTION: { - int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */ - int no_such_func = 0; /* True if no such function exists */ - int wrong_num_args = 0; /* True if wrong number of arguments */ - int is_agg = 0; /* True if is an aggregate function */ - int i; - int nId; /* Number of characters in function name */ - const char *zId; /* The function name. */ - FuncDef *pDef; - - getFunctionName(pExpr, &zId, &nId); - pDef = sqliteFindFunction(pParse->db, zId, nId, n, 0); - if( pDef==0 ){ - pDef = sqliteFindFunction(pParse->db, zId, nId, -1, 0); - if( pDef==0 ){ - no_such_func = 1; - }else{ - wrong_num_args = 1; - } - }else{ - is_agg = pDef->xFunc==0; - } - if( is_agg && !allowAgg ){ - sqliteErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId); - nErr++; - is_agg = 0; - }else if( no_such_func ){ - sqliteErrorMsg(pParse, "no such function: %.*s", nId, zId); - nErr++; - }else if( wrong_num_args ){ - sqliteErrorMsg(pParse,"wrong number of arguments to function %.*s()", - nId, zId); - nErr++; - } - if( is_agg ){ - pExpr->op = TK_AGG_FUNCTION; - if( pIsAgg ) *pIsAgg = 1; - } - for(i=0; nErr==0 && ipList->a[i].pExpr, - allowAgg && !is_agg, pIsAgg); - } - if( pDef==0 ){ - /* Already reported an error */ - }else if( pDef->dataType>=0 ){ - if( pDef->dataTypedataType = - sqliteExprType(pExpr->pList->a[pDef->dataType].pExpr); - }else{ - pExpr->dataType = SQLITE_SO_NUM; - } - }else if( pDef->dataType==SQLITE_ARGS ){ - pDef->dataType = SQLITE_SO_TEXT; - for(i=0; ipList->a[i].pExpr)==SQLITE_SO_NUM ){ - pExpr->dataType = SQLITE_SO_NUM; - break; - } - } - }else if( pDef->dataType==SQLITE_NUMERIC ){ - pExpr->dataType = SQLITE_SO_NUM; - }else{ - pExpr->dataType = SQLITE_SO_TEXT; - } - } - default: { - if( pExpr->pLeft ){ - nErr = sqliteExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg); - } - if( nErr==0 && pExpr->pRight ){ - nErr = sqliteExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg); - } - if( nErr==0 && pExpr->pList ){ - int n = pExpr->pList->nExpr; - int i; - for(i=0; nErr==0 && ipList->a[i].pExpr; - nErr = sqliteExprCheck(pParse, pE2, allowAgg, pIsAgg); - } - } - break; - } - } - return nErr; -} - -/* -** Return either SQLITE_SO_NUM or SQLITE_SO_TEXT to indicate whether the -** given expression should sort as numeric values or as text. -** -** The sqliteExprResolveIds() and sqliteExprCheck() routines must have -** both been called on the expression before it is passed to this routine. -*/ -int sqliteExprType(Expr *p){ - if( p==0 ) return SQLITE_SO_NUM; - while( p ) switch( p->op ){ - case TK_PLUS: - case TK_MINUS: - case TK_STAR: - case TK_SLASH: - case TK_AND: - case TK_OR: - case TK_ISNULL: - case TK_NOTNULL: - case TK_NOT: - case TK_UMINUS: - case TK_UPLUS: - case TK_BITAND: - case TK_BITOR: - case TK_BITNOT: - case TK_LSHIFT: - case TK_RSHIFT: - case TK_REM: - case TK_INTEGER: - case TK_FLOAT: - case TK_IN: - case TK_BETWEEN: - case TK_GLOB: - case TK_LIKE: - return SQLITE_SO_NUM; - - case TK_STRING: - case TK_NULL: - case TK_CONCAT: - case TK_VARIABLE: - return SQLITE_SO_TEXT; - - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: - if( sqliteExprType(p->pLeft)==SQLITE_SO_NUM ){ - return SQLITE_SO_NUM; - } - p = p->pRight; - break; - - case TK_AS: - p = p->pLeft; - break; - - case TK_COLUMN: - case TK_FUNCTION: - case TK_AGG_FUNCTION: - return p->dataType; - - case TK_SELECT: - assert( p->pSelect ); - assert( p->pSelect->pEList ); - assert( p->pSelect->pEList->nExpr>0 ); - p = p->pSelect->pEList->a[0].pExpr; - break; - - case TK_CASE: { - if( p->pRight && sqliteExprType(p->pRight)==SQLITE_SO_NUM ){ - return SQLITE_SO_NUM; - } - if( p->pList ){ - int i; - ExprList *pList = p->pList; - for(i=1; inExpr; i+=2){ - if( sqliteExprType(pList->a[i].pExpr)==SQLITE_SO_NUM ){ - return SQLITE_SO_NUM; - } - } - } - return SQLITE_SO_TEXT; - } - - default: - assert( p->op==TK_ABORT ); /* Can't Happen */ - break; - } - return SQLITE_SO_NUM; -} - -/* -** Generate code into the current Vdbe to evaluate the given -** expression and leave the result on the top of stack. -*/ -void sqliteExprCode(Parse *pParse, Expr *pExpr){ - Vdbe *v = pParse->pVdbe; - int op; - if( v==0 || pExpr==0 ) return; - switch( pExpr->op ){ - case TK_PLUS: op = OP_Add; break; - case TK_MINUS: op = OP_Subtract; break; - case TK_STAR: op = OP_Multiply; break; - case TK_SLASH: op = OP_Divide; break; - case TK_AND: op = OP_And; break; - case TK_OR: op = OP_Or; break; - case TK_LT: op = OP_Lt; break; - case TK_LE: op = OP_Le; break; - case TK_GT: op = OP_Gt; break; - case TK_GE: op = OP_Ge; break; - case TK_NE: op = OP_Ne; break; - case TK_EQ: op = OP_Eq; break; - case TK_ISNULL: op = OP_IsNull; break; - case TK_NOTNULL: op = OP_NotNull; break; - case TK_NOT: op = OP_Not; break; - case TK_UMINUS: op = OP_Negative; break; - case TK_BITAND: op = OP_BitAnd; break; - case TK_BITOR: op = OP_BitOr; break; - case TK_BITNOT: op = OP_BitNot; break; - case TK_LSHIFT: op = OP_ShiftLeft; break; - case TK_RSHIFT: op = OP_ShiftRight; break; - case TK_REM: op = OP_Remainder; break; - default: break; - } - switch( pExpr->op ){ - case TK_COLUMN: { - if( pParse->useAgg ){ - sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); - }else if( pExpr->iColumn>=0 ){ - sqliteVdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); - }else{ - sqliteVdbeAddOp(v, OP_Recno, pExpr->iTable, 0); - } - break; - } - case TK_STRING: - case TK_FLOAT: - case TK_INTEGER: { - if( pExpr->op==TK_INTEGER && sqliteFitsIn32Bits(pExpr->token.z) ){ - sqliteVdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0); - }else{ - sqliteVdbeAddOp(v, OP_String, 0, 0); - } - assert( pExpr->token.z ); - sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n); - sqliteVdbeDequoteP3(v, -1); - break; - } - case TK_NULL: { - sqliteVdbeAddOp(v, OP_String, 0, 0); - break; - } - case TK_VARIABLE: { - sqliteVdbeAddOp(v, OP_Variable, pExpr->iTable, 0); - break; - } - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ - op += 6; /* Convert numeric opcodes to text opcodes */ - } - /* Fall through into the next case */ - } - case TK_AND: - case TK_OR: - case TK_PLUS: - case TK_STAR: - case TK_MINUS: - case TK_REM: - case TK_BITAND: - case TK_BITOR: - case TK_SLASH: { - sqliteExprCode(pParse, pExpr->pLeft); - sqliteExprCode(pParse, pExpr->pRight); - sqliteVdbeAddOp(v, op, 0, 0); - break; - } - case TK_LSHIFT: - case TK_RSHIFT: { - sqliteExprCode(pParse, pExpr->pRight); - sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, op, 0, 0); - break; - } - case TK_CONCAT: { - sqliteExprCode(pParse, pExpr->pLeft); - sqliteExprCode(pParse, pExpr->pRight); - sqliteVdbeAddOp(v, OP_Concat, 2, 0); - break; - } - case TK_UMINUS: { - assert( pExpr->pLeft ); - if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){ - Token *p = &pExpr->pLeft->token; - char *z = sqliteMalloc( p->n + 2 ); - sprintf(z, "-%.*s", p->n, p->z); - if( pExpr->pLeft->op==TK_INTEGER && sqliteFitsIn32Bits(z) ){ - sqliteVdbeAddOp(v, OP_Integer, atoi(z), 0); - }else{ - sqliteVdbeAddOp(v, OP_String, 0, 0); - } - sqliteVdbeChangeP3(v, -1, z, p->n+1); - sqliteFree(z); - break; - } - /* Fall through into TK_NOT */ - } - case TK_BITNOT: - case TK_NOT: { - sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, op, 0, 0); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - int dest; - sqliteVdbeAddOp(v, OP_Integer, 1, 0); - sqliteExprCode(pParse, pExpr->pLeft); - dest = sqliteVdbeCurrentAddr(v) + 2; - sqliteVdbeAddOp(v, op, 1, dest); - sqliteVdbeAddOp(v, OP_AddImm, -1, 0); - break; - } - case TK_AGG_FUNCTION: { - sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); - break; - } - case TK_GLOB: - case TK_LIKE: - case TK_FUNCTION: { - ExprList *pList = pExpr->pList; - int nExpr = pList ? pList->nExpr : 0; - FuncDef *pDef; - int nId; - const char *zId; - getFunctionName(pExpr, &zId, &nId); - pDef = sqliteFindFunction(pParse->db, zId, nId, nExpr, 0); - assert( pDef!=0 ); - nExpr = sqliteExprCodeExprList(pParse, pList, pDef->includeTypes); - sqliteVdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER); - break; - } - case TK_SELECT: { - sqliteVdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); - break; - } - case TK_IN: { - int addr; - sqliteVdbeAddOp(v, OP_Integer, 1, 0); - sqliteExprCode(pParse, pExpr->pLeft); - addr = sqliteVdbeCurrentAddr(v); - sqliteVdbeAddOp(v, OP_NotNull, -1, addr+4); - sqliteVdbeAddOp(v, OP_Pop, 2, 0); - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, addr+6); - if( pExpr->pSelect ){ - sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, addr+6); - }else{ - sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+6); - } - sqliteVdbeAddOp(v, OP_AddImm, -1, 0); - break; - } - case TK_BETWEEN: { - sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, OP_Dup, 0, 0); - sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); - sqliteVdbeAddOp(v, OP_Ge, 0, 0); - sqliteVdbeAddOp(v, OP_Pull, 1, 0); - sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); - sqliteVdbeAddOp(v, OP_Le, 0, 0); - sqliteVdbeAddOp(v, OP_And, 0, 0); - break; - } - case TK_UPLUS: - case TK_AS: { - sqliteExprCode(pParse, pExpr->pLeft); - break; - } - case TK_CASE: { - int expr_end_label; - int jumpInst; - int addr; - int nExpr; - int i; - - assert(pExpr->pList); - assert((pExpr->pList->nExpr % 2) == 0); - assert(pExpr->pList->nExpr > 0); - nExpr = pExpr->pList->nExpr; - expr_end_label = sqliteVdbeMakeLabel(v); - if( pExpr->pLeft ){ - sqliteExprCode(pParse, pExpr->pLeft); - } - for(i=0; ipList->a[i].pExpr); - if( pExpr->pLeft ){ - sqliteVdbeAddOp(v, OP_Dup, 1, 1); - jumpInst = sqliteVdbeAddOp(v, OP_Ne, 1, 0); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - }else{ - jumpInst = sqliteVdbeAddOp(v, OP_IfNot, 1, 0); - } - sqliteExprCode(pParse, pExpr->pList->a[i+1].pExpr); - sqliteVdbeAddOp(v, OP_Goto, 0, expr_end_label); - addr = sqliteVdbeCurrentAddr(v); - sqliteVdbeChangeP2(v, jumpInst, addr); - } - if( pExpr->pLeft ){ - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - } - if( pExpr->pRight ){ - sqliteExprCode(pParse, pExpr->pRight); - }else{ - sqliteVdbeAddOp(v, OP_String, 0, 0); - } - sqliteVdbeResolveLabel(v, expr_end_label); - break; - } - case TK_RAISE: { - if( !pParse->trigStack ){ - sqliteErrorMsg(pParse, - "RAISE() may only be used within a trigger-program"); - pParse->nErr++; - return; - } - if( pExpr->iColumn == OE_Rollback || - pExpr->iColumn == OE_Abort || - pExpr->iColumn == OE_Fail ){ - sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, - pExpr->token.z, pExpr->token.n); - sqliteVdbeDequoteP3(v, -1); - } else { - assert( pExpr->iColumn == OE_Ignore ); - sqliteVdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump, - "(IGNORE jump)", 0); - } - } - break; - } -} - -/* -** Generate code that pushes the value of every element of the given -** expression list onto the stack. If the includeTypes flag is true, -** then also push a string that is the datatype of each element onto -** the stack after the value. -** -** Return the number of elements pushed onto the stack. -*/ -int sqliteExprCodeExprList( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* The expression list to be coded */ - int includeTypes /* TRUE to put datatypes on the stack too */ -){ - struct ExprList_item *pItem; - int i, n; - Vdbe *v; - if( pList==0 ) return 0; - v = sqliteGetVdbe(pParse); - n = pList->nExpr; - for(pItem=pList->a, i=0; ipExpr); - if( includeTypes ){ - sqliteVdbeOp3(v, OP_String, 0, 0, - sqliteExprType(pItem->pExpr)==SQLITE_SO_NUM ? "numeric" : "text", - P3_STATIC); - } - } - return includeTypes ? n*2 : n; -} - -/* -** Generate code for a boolean expression such that a jump is made -** to the label "dest" if the expression is true but execution -** continues straight thru if the expression is false. -** -** If the expression evaluates to NULL (neither true nor false), then -** take the jump if the jumpIfNull flag is true. -*/ -void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ - Vdbe *v = pParse->pVdbe; - int op = 0; - if( v==0 || pExpr==0 ) return; - switch( pExpr->op ){ - case TK_LT: op = OP_Lt; break; - case TK_LE: op = OP_Le; break; - case TK_GT: op = OP_Gt; break; - case TK_GE: op = OP_Ge; break; - case TK_NE: op = OP_Ne; break; - case TK_EQ: op = OP_Eq; break; - case TK_ISNULL: op = OP_IsNull; break; - case TK_NOTNULL: op = OP_NotNull; break; - default: break; - } - switch( pExpr->op ){ - case TK_AND: { - int d2 = sqliteVdbeMakeLabel(v); - sqliteExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); - sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - sqliteVdbeResolveLabel(v, d2); - break; - } - case TK_OR: { - sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - break; - } - case TK_NOT: { - sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - break; - } - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - sqliteExprCode(pParse, pExpr->pLeft); - sqliteExprCode(pParse, pExpr->pRight); - if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ - op += 6; /* Convert numeric opcodes to text opcodes */ - } - sqliteVdbeAddOp(v, op, jumpIfNull, dest); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, op, 1, dest); - break; - } - case TK_IN: { - int addr; - sqliteExprCode(pParse, pExpr->pLeft); - addr = sqliteVdbeCurrentAddr(v); - sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4); - if( pExpr->pSelect ){ - sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, dest); - }else{ - sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, dest); - } - break; - } - case TK_BETWEEN: { - int addr; - sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, OP_Dup, 0, 0); - sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); - addr = sqliteVdbeAddOp(v, OP_Lt, !jumpIfNull, 0); - sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); - sqliteVdbeAddOp(v, OP_Le, jumpIfNull, dest); - sqliteVdbeAddOp(v, OP_Integer, 0, 0); - sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - break; - } - default: { - sqliteExprCode(pParse, pExpr); - sqliteVdbeAddOp(v, OP_If, jumpIfNull, dest); - break; - } - } -} - -/* -** Generate code for a boolean expression such that a jump is made -** to the label "dest" if the expression is false but execution -** continues straight thru if the expression is true. -** -** If the expression evaluates to NULL (neither true nor false) then -** jump if jumpIfNull is true or fall through if jumpIfNull is false. -*/ -void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ - Vdbe *v = pParse->pVdbe; - int op = 0; - if( v==0 || pExpr==0 ) return; - switch( pExpr->op ){ - case TK_LT: op = OP_Ge; break; - case TK_LE: op = OP_Gt; break; - case TK_GT: op = OP_Le; break; - case TK_GE: op = OP_Lt; break; - case TK_NE: op = OP_Eq; break; - case TK_EQ: op = OP_Ne; break; - case TK_ISNULL: op = OP_NotNull; break; - case TK_NOTNULL: op = OP_IsNull; break; - default: break; - } - switch( pExpr->op ){ - case TK_AND: { - sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - break; - } - case TK_OR: { - int d2 = sqliteVdbeMakeLabel(v); - sqliteExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull); - sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - sqliteVdbeResolveLabel(v, d2); - break; - } - case TK_NOT: { - sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - break; - } - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ - /* Convert numeric comparison opcodes into text comparison opcodes. - ** This step depends on the fact that the text comparision opcodes are - ** always 6 greater than their corresponding numeric comparison - ** opcodes. - */ - assert( OP_Eq+6 == OP_StrEq ); - op += 6; - } - sqliteExprCode(pParse, pExpr->pLeft); - sqliteExprCode(pParse, pExpr->pRight); - sqliteVdbeAddOp(v, op, jumpIfNull, dest); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, op, 1, dest); - break; - } - case TK_IN: { - int addr; - sqliteExprCode(pParse, pExpr->pLeft); - addr = sqliteVdbeCurrentAddr(v); - sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4); - if( pExpr->pSelect ){ - sqliteVdbeAddOp(v, OP_NotFound, pExpr->iTable, dest); - }else{ - sqliteVdbeAddOp(v, OP_SetNotFound, pExpr->iTable, dest); - } - break; - } - case TK_BETWEEN: { - int addr; - sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, OP_Dup, 0, 0); - sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); - addr = sqliteVdbeCurrentAddr(v); - sqliteVdbeAddOp(v, OP_Ge, !jumpIfNull, addr+3); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, dest); - sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); - sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest); - break; - } - default: { - sqliteExprCode(pParse, pExpr); - sqliteVdbeAddOp(v, OP_IfNot, jumpIfNull, dest); - break; - } - } -} - -/* -** Do a deep comparison of two expression trees. Return TRUE (non-zero) -** if they are identical and return FALSE if they differ in any way. -*/ -int sqliteExprCompare(Expr *pA, Expr *pB){ - int i; - if( pA==0 ){ - return pB==0; - }else if( pB==0 ){ - return 0; - } - if( pA->op!=pB->op ) return 0; - if( !sqliteExprCompare(pA->pLeft, pB->pLeft) ) return 0; - if( !sqliteExprCompare(pA->pRight, pB->pRight) ) return 0; - if( pA->pList ){ - if( pB->pList==0 ) return 0; - if( pA->pList->nExpr!=pB->pList->nExpr ) return 0; - for(i=0; ipList->nExpr; i++){ - if( !sqliteExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){ - return 0; - } - } - }else if( pB->pList ){ - return 0; - } - if( pA->pSelect || pB->pSelect ) return 0; - if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; - if( pA->token.z ){ - if( pB->token.z==0 ) return 0; - if( pB->token.n!=pA->token.n ) return 0; - if( sqliteStrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; - } - return 1; -} - -/* -** Add a new element to the pParse->aAgg[] array and return its index. -*/ -static int appendAggInfo(Parse *pParse){ - if( (pParse->nAgg & 0x7)==0 ){ - int amt = pParse->nAgg + 8; - AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0])); - if( aAgg==0 ){ - return -1; - } - pParse->aAgg = aAgg; - } - memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0])); - return pParse->nAgg++; -} - -/* -** Analyze the given expression looking for aggregate functions and -** for variables that need to be added to the pParse->aAgg[] array. -** Make additional entries to the pParse->aAgg[] array as necessary. -** -** This routine should only be called after the expression has been -** analyzed by sqliteExprResolveIds() and sqliteExprCheck(). -** -** If errors are seen, leave an error message in zErrMsg and return -** the number of errors. -*/ -int sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){ - int i; - AggExpr *aAgg; - int nErr = 0; - - if( pExpr==0 ) return 0; - switch( pExpr->op ){ - case TK_COLUMN: { - aAgg = pParse->aAgg; - for(i=0; inAgg; i++){ - if( aAgg[i].isAgg ) continue; - if( aAgg[i].pExpr->iTable==pExpr->iTable - && aAgg[i].pExpr->iColumn==pExpr->iColumn ){ - break; - } - } - if( i>=pParse->nAgg ){ - i = appendAggInfo(pParse); - if( i<0 ) return 1; - pParse->aAgg[i].isAgg = 0; - pParse->aAgg[i].pExpr = pExpr; - } - pExpr->iAgg = i; - break; - } - case TK_AGG_FUNCTION: { - aAgg = pParse->aAgg; - for(i=0; inAgg; i++){ - if( !aAgg[i].isAgg ) continue; - if( sqliteExprCompare(aAgg[i].pExpr, pExpr) ){ - break; - } - } - if( i>=pParse->nAgg ){ - i = appendAggInfo(pParse); - if( i<0 ) return 1; - pParse->aAgg[i].isAgg = 1; - pParse->aAgg[i].pExpr = pExpr; - pParse->aAgg[i].pFunc = sqliteFindFunction(pParse->db, - pExpr->token.z, pExpr->token.n, - pExpr->pList ? pExpr->pList->nExpr : 0, 0); - } - pExpr->iAgg = i; - break; - } - default: { - if( pExpr->pLeft ){ - nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft); - } - if( nErr==0 && pExpr->pRight ){ - nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pRight); - } - if( nErr==0 && pExpr->pList ){ - int n = pExpr->pList->nExpr; - int i; - for(i=0; nErr==0 && ipList->a[i].pExpr); - } - } - break; - } - } - return nErr; -} - -/* -** Locate a user function given a name and a number of arguments. -** Return a pointer to the FuncDef structure that defines that -** function, or return NULL if the function does not exist. -** -** If the createFlag argument is true, then a new (blank) FuncDef -** structure is created and liked into the "db" structure if a -** no matching function previously existed. When createFlag is true -** and the nArg parameter is -1, then only a function that accepts -** any number of arguments will be returned. -** -** If createFlag is false and nArg is -1, then the first valid -** function found is returned. A function is valid if either xFunc -** or xStep is non-zero. -*/ -FuncDef *sqliteFindFunction( - sqlite *db, /* An open database */ - const char *zName, /* Name of the function. Not null-terminated */ - int nName, /* Number of characters in the name */ - int nArg, /* Number of arguments. -1 means any number */ - int createFlag /* Create new entry if true and does not otherwise exist */ -){ - FuncDef *pFirst, *p, *pMaybe; - pFirst = p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, nName); - if( p && !createFlag && nArg<0 ){ - while( p && p->xFunc==0 && p->xStep==0 ){ p = p->pNext; } - return p; - } - pMaybe = 0; - while( p && p->nArg!=nArg ){ - if( p->nArg<0 && !createFlag && (p->xFunc || p->xStep) ) pMaybe = p; - p = p->pNext; - } - if( p && !createFlag && p->xFunc==0 && p->xStep==0 ){ - return 0; - } - if( p==0 && pMaybe ){ - assert( createFlag==0 ); - return pMaybe; - } - if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){ - p->nArg = nArg; - p->pNext = pFirst; - p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC; - sqliteHashInsert(&db->aFunc, zName, nName, (void*)p); - } - return p; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/expr.o b/dbLifeLog/DBD-SQLite2-0.33/expr.o deleted file mode 100644 index 9b40d4d2f7ed9b991fa75795a91508476f90c620..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35232 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 LB^6FN^!)z|C?B*> diff --git a/dbLifeLog/DBD-SQLite2-0.33/func.c b/dbLifeLog/DBD-SQLite2-0.33/func.c deleted file mode 100644 index 47cb7c9..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/func.c +++ /dev/null @@ -1,658 +0,0 @@ -/* -** 2002 February 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C functions that implement various SQL -** functions of SQLite. -** -** There is only one exported symbol in this file - the function -** sqliteRegisterBuildinFunctions() found at the bottom of the file. -** All other code has file scope. -** -** $Id: func.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ -#include -#include -#include -#include -#include "sqliteInt.h" -#include "os.h" - -/* -** Implementation of the non-aggregate min() and max() functions -*/ -static void minmaxFunc(sqlite_func *context, int argc, const char **argv){ - const char *zBest; - int i; - int (*xCompare)(const char*, const char*); - int mask; /* 0 for min() or 0xffffffff for max() */ - - if( argc==0 ) return; - mask = (int)sqlite_user_data(context); - zBest = argv[0]; - if( zBest==0 ) return; - if( argv[1][0]=='n' ){ - xCompare = sqliteCompare; - }else{ - xCompare = strcmp; - } - for(i=2; i0 ){ - p1--; - } - if( p1+p2>len ){ - p2 = len-p1; - } -#ifdef SQLITE_UTF8 - for(i=0; i30 ) n = 30; - if( n<0 ) n = 0; - r = sqliteAtoF(argv[0], 0); - sprintf(zBuf,"%.*f",n,r); - sqlite_set_result_string(context, zBuf, -1); -} - -/* -** Implementation of the upper() and lower() SQL functions. -*/ -static void upperFunc(sqlite_func *context, int argc, const char **argv){ - unsigned char *z; - int i; - if( argc<1 || argv[0]==0 ) return; - z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1); - if( z==0 ) return; - for(i=0; z[i]; i++){ - if( islower(z[i]) ) z[i] = toupper(z[i]); - } -} -static void lowerFunc(sqlite_func *context, int argc, const char **argv){ - unsigned char *z; - int i; - if( argc<1 || argv[0]==0 ) return; - z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1); - if( z==0 ) return; - for(i=0; z[i]; i++){ - if( isupper(z[i]) ) z[i] = tolower(z[i]); - } -} - -/* -** Implementation of the IFNULL(), NVL(), and COALESCE() functions. -** All three do the same thing. They return the first non-NULL -** argument. -*/ -static void ifnullFunc(sqlite_func *context, int argc, const char **argv){ - int i; - for(i=0; i0 ){ - zResult[j++] = code + '0'; - } - } - while( j<4 ){ - zResult[j++] = '0'; - } - zResult[j] = 0; - sqlite_set_result_string(context, zResult, 4); - }else{ - sqlite_set_result_string(context, "?000", 4); - } -} -#endif - -#ifdef SQLITE_TEST -/* -** This function generates a string of random characters. Used for -** generating test data. -*/ -static void randStr(sqlite_func *context, int argc, const char **argv){ - static const unsigned char zSrc[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789" - ".-!,:*^+=_|?/<> "; - int iMin, iMax, n, r, i; - unsigned char zBuf[1000]; - if( argc>=1 ){ - iMin = atoi(argv[0]); - if( iMin<0 ) iMin = 0; - if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; - }else{ - iMin = 1; - } - if( argc>=2 ){ - iMax = atoi(argv[1]); - if( iMax=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; - }else{ - iMax = 50; - } - n = iMin; - if( iMax>iMin ){ - sqliteRandomness(sizeof(r), &r); - r &= 0x7fffffff; - n += r%(iMax + 1 - iMin); - } - assert( nsum += sqliteAtoF(argv[0], 0); - p->cnt++; - } -} -static void sumFinalize(sqlite_func *context){ - SumCtx *p; - p = sqlite_aggregate_context(context, sizeof(*p)); - sqlite_set_result_double(context, p ? p->sum : 0.0); -} -static void avgFinalize(sqlite_func *context){ - SumCtx *p; - p = sqlite_aggregate_context(context, sizeof(*p)); - if( p && p->cnt>0 ){ - sqlite_set_result_double(context, p->sum/(double)p->cnt); - } -} - -/* -** An instance of the following structure holds the context of a -** variance or standard deviation computation. -*/ -typedef struct StdDevCtx StdDevCtx; -struct StdDevCtx { - double sum; /* Sum of terms */ - double sum2; /* Sum of the squares of terms */ - int cnt; /* Number of terms counted */ -}; - -#if 0 /* Omit because math library is required */ -/* -** Routines used to compute the standard deviation as an aggregate. -*/ -static void stdDevStep(sqlite_func *context, int argc, const char **argv){ - StdDevCtx *p; - double x; - if( argc<1 ) return; - p = sqlite_aggregate_context(context, sizeof(*p)); - if( p && argv[0] ){ - x = sqliteAtoF(argv[0], 0); - p->sum += x; - p->sum2 += x*x; - p->cnt++; - } -} -static void stdDevFinalize(sqlite_func *context){ - double rN = sqlite_aggregate_count(context); - StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p)); - if( p && p->cnt>1 ){ - double rCnt = cnt; - sqlite_set_result_double(context, - sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0))); - } -} -#endif - -/* -** The following structure keeps track of state information for the -** count() aggregate function. -*/ -typedef struct CountCtx CountCtx; -struct CountCtx { - int n; -}; - -/* -** Routines to implement the count() aggregate function. -*/ -static void countStep(sqlite_func *context, int argc, const char **argv){ - CountCtx *p; - p = sqlite_aggregate_context(context, sizeof(*p)); - if( (argc==0 || argv[0]) && p ){ - p->n++; - } -} -static void countFinalize(sqlite_func *context){ - CountCtx *p; - p = sqlite_aggregate_context(context, sizeof(*p)); - sqlite_set_result_int(context, p ? p->n : 0); -} - -/* -** This function tracks state information for the min() and max() -** aggregate functions. -*/ -typedef struct MinMaxCtx MinMaxCtx; -struct MinMaxCtx { - char *z; /* The best so far */ - char zBuf[28]; /* Space that can be used for storage */ -}; - -/* -** Routines to implement min() and max() aggregate functions. -*/ -static void minmaxStep(sqlite_func *context, int argc, const char **argv){ - MinMaxCtx *p; - int (*xCompare)(const char*, const char*); - int mask; /* 0 for min() or 0xffffffff for max() */ - - assert( argc==2 ); - if( argv[0]==0 ) return; /* Ignore NULL values */ - if( argv[1][0]=='n' ){ - xCompare = sqliteCompare; - }else{ - xCompare = strcmp; - } - mask = (int)sqlite_user_data(context); - assert( mask==0 || mask==-1 ); - p = sqlite_aggregate_context(context, sizeof(*p)); - if( p==0 || argc<1 ) return; - if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){ - int len; - if( p->zBuf[0] ){ - sqliteFree(p->z); - } - len = strlen(argv[0]); - if( len < sizeof(p->zBuf)-1 ){ - p->z = &p->zBuf[1]; - p->zBuf[0] = 0; - }else{ - p->z = sqliteMalloc( len+1 ); - p->zBuf[0] = 1; - if( p->z==0 ) return; - } - strcpy(p->z, argv[0]); - } -} -static void minMaxFinalize(sqlite_func *context){ - MinMaxCtx *p; - p = sqlite_aggregate_context(context, sizeof(*p)); - if( p && p->z && p->zBuf[0]<2 ){ - sqlite_set_result_string(context, p->z, strlen(p->z)); - } - if( p && p->zBuf[0] ){ - sqliteFree(p->z); - } -} - -/* -** This function registered all of the above C functions as SQL -** functions. This should be the only routine in this file with -** external linkage. -*/ -void sqliteRegisterBuiltinFunctions(sqlite *db){ - static struct { - char *zName; - signed char nArg; - signed char dataType; - u8 argType; /* 0: none. 1: db 2: (-1) */ - void (*xFunc)(sqlite_func*,int,const char**); - } aFuncs[] = { - { "min", -1, SQLITE_ARGS, 0, minmaxFunc }, - { "min", 0, 0, 0, 0 }, - { "max", -1, SQLITE_ARGS, 2, minmaxFunc }, - { "max", 0, 0, 2, 0 }, - { "typeof", 1, SQLITE_TEXT, 0, typeofFunc }, - { "length", 1, SQLITE_NUMERIC, 0, lengthFunc }, - { "substr", 3, SQLITE_TEXT, 0, substrFunc }, - { "abs", 1, SQLITE_NUMERIC, 0, absFunc }, - { "round", 1, SQLITE_NUMERIC, 0, roundFunc }, - { "round", 2, SQLITE_NUMERIC, 0, roundFunc }, - { "upper", 1, SQLITE_TEXT, 0, upperFunc }, - { "lower", 1, SQLITE_TEXT, 0, lowerFunc }, - { "coalesce", -1, SQLITE_ARGS, 0, ifnullFunc }, - { "coalesce", 0, 0, 0, 0 }, - { "coalesce", 1, 0, 0, 0 }, - { "ifnull", 2, SQLITE_ARGS, 0, ifnullFunc }, - { "random", -1, SQLITE_NUMERIC, 0, randomFunc }, - { "like", 2, SQLITE_NUMERIC, 0, likeFunc }, - { "glob", 2, SQLITE_NUMERIC, 0, globFunc }, - { "nullif", 2, SQLITE_ARGS, 0, nullifFunc }, - { "sqlite_version",0,SQLITE_TEXT, 0, versionFunc}, - { "quote", 1, SQLITE_ARGS, 0, quoteFunc }, - { "last_insert_rowid", 0, SQLITE_NUMERIC, 1, last_insert_rowid }, - { "change_count", 0, SQLITE_NUMERIC, 1, change_count }, - { "last_statement_change_count", - 0, SQLITE_NUMERIC, 1, last_statement_change_count }, -#ifdef SQLITE_SOUNDEX - { "soundex", 1, SQLITE_TEXT, 0, soundexFunc}, -#endif -#ifdef SQLITE_TEST - { "randstr", 2, SQLITE_TEXT, 0, randStr }, -#endif - }; - static struct { - char *zName; - signed char nArg; - signed char dataType; - u8 argType; - void (*xStep)(sqlite_func*,int,const char**); - void (*xFinalize)(sqlite_func*); - } aAggs[] = { - { "min", 1, 0, 0, minmaxStep, minMaxFinalize }, - { "max", 1, 0, 2, minmaxStep, minMaxFinalize }, - { "sum", 1, SQLITE_NUMERIC, 0, sumStep, sumFinalize }, - { "avg", 1, SQLITE_NUMERIC, 0, sumStep, avgFinalize }, - { "count", 0, SQLITE_NUMERIC, 0, countStep, countFinalize }, - { "count", 1, SQLITE_NUMERIC, 0, countStep, countFinalize }, -#if 0 - { "stddev", 1, SQLITE_NUMERIC, 0, stdDevStep, stdDevFinalize }, -#endif - }; - static const char *azTypeFuncs[] = { "min", "max", "typeof" }; - int i; - - for(i=0; iaFunc, azTypeFuncs[i], n); - while( p ){ - p->includeTypes = 1; - p = p->pNext; - } - } - sqliteRegisterDateTimeFunctions(db); -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/func.o b/dbLifeLog/DBD-SQLite2-0.33/func.o deleted file mode 100644 index df3d6f4eec022e7cdbd014acbfd4731575e4b766..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14088 zcmb`NeRNbsmcXk&kT$`7Eqa!WAJC3r2+Yu%M#KaV^O8<@tsO+ZmRZoy>2yNIPA7K1 z*5C)m=?=@ArZqc9_i*Oy?6UvtxUPE+XIvx0DmF%ga9qqd%JCca=&ITHfjAQx6|?u& zyOl1Uc{+|$obFfkt6R5jece}m$=!{SCa1%}L~^hdtW*+|G0zpHd>zl$F&{gRt<{Xr z-@~$I9HQrOV|ddjB4th;)ABR5{ulHbWzZQM&lUCWD|7m=Zf+62vc*2-fufdu%ApJv z9m61#D`x(e+U8J{WhciDa zteVgY^&YLT?ucjXf_7yNNNU-lN6TxcQJ`F_9m#xXTF4b@#!;?wpk%L>PkBn6wGU`{ zr`BK8tB`B`wDJ$Cn`8)iVuzVFitdZoKf%e&`RAu&Rgo?wx$Vje0q z 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 d9-MSY3Vas8$J#&sESswTy>#K\n"; - -print("downloading http://www.sqlite.org/sqlite-$version.tar.gz\n"); -if (getstore( - "http://www.sqlite.org/sqlite-$version.tar.gz", - "sqlite.tar.gz") != 200) { - die "Failed to download"; -} -print("done\n"); - -rm_rf('sqlite'); -xsystem("tar zxvf sqlite.tar.gz"); -chdir("sqlite"); -xsystem("sh configure --enable-utf8"); -xsystem("make parse.c sqlite.h opcodes.h opcodes.c"); - -my %skip = map { $_ => 1 } map { chomp; $_ } ; -warn("Skip: $_\n") for keys %skip; - -foreach (<*.[ch]>, `find src -name \\*.[ch]`) { - chomp; - next if $skip{$_}; - xsystem("cp $_ ../"); -} - -exit(0); - -sub xsystem { - local $, = ", "; - print("@_\n"); - my $ret = system(@_); - if ($ret != 0) { - die "system(@_) failed: $?"; - } -} - -__DATA__ -lempar.c -src/threadtest.c -src/test1.c -src/test2.c -src/test3.c -src/tclsqlite.c -src/shell.c -src/lemon.c -src/md5.c - diff --git a/dbLifeLog/DBD-SQLite2-0.33/hash.c b/dbLifeLog/DBD-SQLite2-0.33/hash.c deleted file mode 100644 index ac3526b..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/hash.c +++ /dev/null @@ -1,356 +0,0 @@ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the implementation of generic hash-tables -** used in SQLite. -** -** $Id: hash.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ -#include "sqliteInt.h" -#include - -/* Turn bulk memory into a hash table object by initializing the -** fields of the Hash structure. -** -** "new" is a pointer to the hash table that is to be initialized. -** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER, -** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass -** determines what kind of key the hash table will use. "copyKey" is -** true if the hash table should make its own private copy of keys and -** false if it should just use the supplied pointer. CopyKey only makes -** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored -** for other key classes. -*/ -void sqliteHashInit(Hash *new, int keyClass, int copyKey){ - assert( new!=0 ); - assert( keyClass>=SQLITE_HASH_INT && keyClass<=SQLITE_HASH_BINARY ); - new->keyClass = keyClass; - new->copyKey = copyKey && - (keyClass==SQLITE_HASH_STRING || keyClass==SQLITE_HASH_BINARY); - new->first = 0; - new->count = 0; - new->htsize = 0; - new->ht = 0; -} - -/* Remove all entries from a hash table. Reclaim all memory. -** Call this routine to delete a hash table or to reset a hash table -** to the empty state. -*/ -void sqliteHashClear(Hash *pH){ - HashElem *elem; /* For looping over all elements of the table */ - - assert( pH!=0 ); - elem = pH->first; - pH->first = 0; - if( pH->ht ) sqliteFree(pH->ht); - pH->ht = 0; - pH->htsize = 0; - while( elem ){ - HashElem *next_elem = elem->next; - if( pH->copyKey && elem->pKey ){ - sqliteFree(elem->pKey); - } - sqliteFree(elem); - elem = next_elem; - } - pH->count = 0; -} - -/* -** Hash and comparison functions when the mode is SQLITE_HASH_INT -*/ -static int intHash(const void *pKey, int nKey){ - return nKey ^ (nKey<<8) ^ (nKey>>8); -} -static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - return n2 - n1; -} - -#if 0 /* NOT USED */ -/* -** Hash and comparison functions when the mode is SQLITE_HASH_POINTER -*/ -static int ptrHash(const void *pKey, int nKey){ - uptr x = Addr(pKey); - return x ^ (x<<8) ^ (x>>8); -} -static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( pKey1==pKey2 ) return 0; - if( pKey1 0 ){ - h = (h<<3) ^ h ^ *(z++); - } - return h & 0x7fffffff; -} -static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return n2-n1; - return memcmp(pKey1,pKey2,n1); -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** The C syntax in this function definition may be unfamilar to some -** programmers, so we provide the following additional explanation: -** -** The name of the function is "hashFunction". The function takes a -** single parameter "keyClass". The return value of hashFunction() -** is a pointer to another function. Specifically, the return value -** of hashFunction() is a pointer to a function that takes two parameters -** with types "const void*" and "int" and returns an "int". -*/ -static int (*hashFunction(int keyClass))(const void*,int){ - switch( keyClass ){ - case SQLITE_HASH_INT: return &intHash; - /* case SQLITE_HASH_POINTER: return &ptrHash; // NOT USED */ - case SQLITE_HASH_STRING: return &strHash; - case SQLITE_HASH_BINARY: return &binHash;; - default: break; - } - return 0; -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** For help in interpreted the obscure C code in the function definition, -** see the header comment on the previous function. -*/ -static int (*compareFunction(int keyClass))(const void*,int,const void*,int){ - switch( keyClass ){ - case SQLITE_HASH_INT: return &intCompare; - /* case SQLITE_HASH_POINTER: return &ptrCompare; // NOT USED */ - case SQLITE_HASH_STRING: return &strCompare; - case SQLITE_HASH_BINARY: return &binCompare; - default: break; - } - return 0; -} - - -/* Resize the hash table so that it cantains "new_size" buckets. -** "new_size" must be a power of 2. The hash table might fail -** to resize if sqliteMalloc() fails. -*/ -static void rehash(Hash *pH, int new_size){ - struct _ht *new_ht; /* The new hash table */ - HashElem *elem, *next_elem; /* For looping over existing elements */ - HashElem *x; /* Element being copied to new hash table */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( (new_size & (new_size-1))==0 ); - new_ht = (struct _ht *)sqliteMalloc( new_size*sizeof(struct _ht) ); - if( new_ht==0 ) return; - if( pH->ht ) sqliteFree(pH->ht); - pH->ht = new_ht; - pH->htsize = new_size; - xHash = hashFunction(pH->keyClass); - for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); - next_elem = elem->next; - x = new_ht[h].chain; - if( x ){ - elem->next = x; - elem->prev = x->prev; - if( x->prev ) x->prev->next = elem; - else pH->first = elem; - x->prev = elem; - }else{ - elem->next = pH->first; - if( pH->first ) pH->first->prev = elem; - elem->prev = 0; - pH->first = elem; - } - new_ht[h].chain = elem; - new_ht[h].count++; - } -} - -/* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key has -** already been computed and is passed as the 4th parameter. -*/ -static HashElem *findElementGivenHash( - const Hash *pH, /* The pH to be searched */ - const void *pKey, /* The key we are searching for */ - int nKey, - int h /* The hash for this key. */ -){ - HashElem *elem; /* Used to loop thru the element list */ - int count; /* Number of elements left to test */ - int (*xCompare)(const void*,int,const void*,int); /* comparison function */ - - if( pH->ht ){ - elem = pH->ht[h].chain; - count = pH->ht[h].count; - xCompare = compareFunction(pH->keyClass); - while( count-- && elem ){ - if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ - return elem; - } - elem = elem->next; - } - } - return 0; -} - -/* Remove a single entry from the hash table given a pointer to that -** element and a hash on the element's key. -*/ -static void removeElementGivenHash( - Hash *pH, /* The pH containing "elem" */ - HashElem* elem, /* The element to be removed from the pH */ - int h /* Hash value for the element */ -){ - if( elem->prev ){ - elem->prev->next = elem->next; - }else{ - pH->first = elem->next; - } - if( elem->next ){ - elem->next->prev = elem->prev; - } - if( pH->ht[h].chain==elem ){ - pH->ht[h].chain = elem->next; - } - pH->ht[h].count--; - if( pH->ht[h].count<=0 ){ - pH->ht[h].chain = 0; - } - if( pH->copyKey && elem->pKey ){ - sqliteFree(elem->pKey); - } - sqliteFree( elem ); - pH->count--; -} - -/* Attempt to locate an element of the hash table pH with a key -** that matches pKey,nKey. Return the data for this element if it is -** found, or NULL if there is no match. -*/ -void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){ - int h; /* A hash on key */ - HashElem *elem; /* The element that matches key */ - int (*xHash)(const void*,int); /* The hash function */ - - if( pH==0 || pH->ht==0 ) return 0; - xHash = hashFunction(pH->keyClass); - assert( xHash!=0 ); - h = (*xHash)(pKey,nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1)); - return elem ? elem->data : 0; -} - -/* Insert an element into the hash table pH. The key is pKey,nKey -** and the data is "data". -** -** If no element exists with a matching key, then a new -** element is created. A copy of the key is made if the copyKey -** flag is set. NULL is returned. -** -** If another element already exists with the same key, then the -** new data replaces the old data and the old data is returned. -** The key is not copied in this instance. If a malloc fails, then -** the new data is returned and the hash table is unchanged. -** -** If the "data" parameter to this function is NULL, then the -** element corresponding to "key" is removed from the hash table. -*/ -void *sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data){ - int hraw; /* Raw hash value of the key */ - int h; /* the hash of the key modulo hash table size */ - HashElem *elem; /* Used to loop thru the element list */ - HashElem *new_elem; /* New element added to the pH */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( pH!=0 ); - xHash = hashFunction(pH->keyClass); - assert( xHash!=0 ); - hraw = (*xHash)(pKey, nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - elem = findElementGivenHash(pH,pKey,nKey,h); - if( elem ){ - void *old_data = elem->data; - if( data==0 ){ - removeElementGivenHash(pH,elem,h); - }else{ - elem->data = data; - } - return old_data; - } - if( data==0 ) return 0; - new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) ); - if( new_elem==0 ) return data; - if( pH->copyKey && pKey!=0 ){ - new_elem->pKey = sqliteMallocRaw( nKey ); - if( new_elem->pKey==0 ){ - sqliteFree(new_elem); - return data; - } - memcpy((void*)new_elem->pKey, pKey, nKey); - }else{ - new_elem->pKey = (void*)pKey; - } - new_elem->nKey = nKey; - pH->count++; - if( pH->htsize==0 ) rehash(pH,8); - if( pH->htsize==0 ){ - pH->count = 0; - sqliteFree(new_elem); - return data; - } - if( pH->count > pH->htsize ){ - rehash(pH,pH->htsize*2); - } - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - elem = pH->ht[h].chain; - if( elem ){ - new_elem->next = elem; - new_elem->prev = elem->prev; - if( elem->prev ){ elem->prev->next = new_elem; } - else { pH->first = new_elem; } - elem->prev = new_elem; - }else{ - new_elem->next = pH->first; - new_elem->prev = 0; - if( pH->first ){ pH->first->prev = new_elem; } - pH->first = new_elem; - } - pH->ht[h].count++; - pH->ht[h].chain = new_elem; - new_elem->data = data; - return 0; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/hash.h b/dbLifeLog/DBD-SQLite2-0.33/hash.h deleted file mode 100644 index 43b0135..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/hash.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the header file for the generic hash-table implemenation -** used in SQLite. -** -** $Id: hash.h,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ -#ifndef _SQLITE_HASH_H_ -#define _SQLITE_HASH_H_ - -/* Forward declarations of structures. */ -typedef struct Hash Hash; -typedef struct HashElem HashElem; - -/* A complete hash table is an instance of the following structure. -** The internals of this structure are intended to be opaque -- client -** code should not attempt to access or modify the fields of this structure -** directly. Change this structure only by using the routines below. -** However, many of the "procedures" and "functions" for modifying and -** accessing this structure are really macros, so we can't really make -** this structure opaque. -*/ -struct Hash { - char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */ - char copyKey; /* True if copy of key made on insert */ - int count; /* Number of entries in this table */ - HashElem *first; /* The first element of the array */ - int htsize; /* Number of buckets in the hash table */ - struct _ht { /* the hash table */ - int count; /* Number of entries with this hash */ - HashElem *chain; /* Pointer to first entry with this hash */ - } *ht; -}; - -/* Each element in the hash table is an instance of the following -** structure. All elements are stored on a single doubly-linked list. -** -** Again, this structure is intended to be opaque, but it can't really -** be opaque because it is used by macros. -*/ -struct HashElem { - HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - void *pKey; int nKey; /* Key associated with this element */ -}; - -/* -** There are 4 different modes of operation for a hash table: -** -** SQLITE_HASH_INT nKey is used as the key and pKey is ignored. -** -** SQLITE_HASH_POINTER pKey is used as the key and nKey is ignored. -** -** SQLITE_HASH_STRING pKey points to a string that is nKey bytes long -** (including the null-terminator, if any). Case -** is ignored in comparisons. -** -** SQLITE_HASH_BINARY pKey points to binary data nKey bytes long. -** memcmp() is used to compare keys. -** -** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY -** if the copyKey parameter to HashInit is 1. -*/ -#define SQLITE_HASH_INT 1 -/* #define SQLITE_HASH_POINTER 2 // NOT USED */ -#define SQLITE_HASH_STRING 3 -#define SQLITE_HASH_BINARY 4 - -/* -** Access routines. To delete, insert a NULL pointer. -*/ -void sqliteHashInit(Hash*, int keytype, int copyKey); -void *sqliteHashInsert(Hash*, const void *pKey, int nKey, void *pData); -void *sqliteHashFind(const Hash*, const void *pKey, int nKey); -void sqliteHashClear(Hash*); - -/* -** Macros for looping over all elements of a hash table. The idiom is -** like this: -** -** Hash h; -** HashElem *p; -** ... -** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ -** SomeStructure *pData = sqliteHashData(p); -** // do something with pData -** } -*/ -#define sqliteHashFirst(H) ((H)->first) -#define sqliteHashNext(E) ((E)->next) -#define sqliteHashData(E) ((E)->data) -#define sqliteHashKey(E) ((E)->pKey) -#define sqliteHashKeysize(E) ((E)->nKey) - -/* -** Number of entries in a hash table -*/ -#define sqliteHashCount(H) ((H)->count) - -#endif /* _SQLITE_HASH_H_ */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/hash.o b/dbLifeLog/DBD-SQLite2-0.33/hash.o deleted file mode 100644 index 783c8c0dff17bfd92b951c67dc2e2121ad7c5d0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4808 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 diff --git a/dbLifeLog/DBD-SQLite2-0.33/insert.c b/dbLifeLog/DBD-SQLite2-0.33/insert.c deleted file mode 100644 index 6bb6438..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/insert.c +++ /dev/null @@ -1,919 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle INSERT statements in SQLite. -** -** $Id: insert.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ -#include "sqliteInt.h" - -/* -** This routine is call to handle SQL of the following forms: -** -** insert into TABLE (IDLIST) values(EXPRLIST) -** insert into TABLE (IDLIST) select -** -** The IDLIST following the table name is always optional. If omitted, -** then a list of all columns for the table is substituted. The IDLIST -** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted. -** -** The pList parameter holds EXPRLIST in the first form of the INSERT -** statement above, and pSelect is NULL. For the second form, pList is -** NULL and pSelect is a pointer to the select statement used to generate -** data for the insert. -** -** The code generated follows one of three templates. For a simple -** select with data coming from a VALUES clause, the code executes -** once straight down through. The template looks like this: -** -** open write cursor to and its indices -** puts VALUES clause expressions onto the stack -** write the resulting record into
-** cleanup -** -** If the statement is of the form -** -** INSERT INTO
SELECT ... -** -** And the SELECT clause does not read from
at any time, then -** the generated code follows this template: -** -** goto B -** A: setup for the SELECT -** loop over the tables in the SELECT -** gosub C -** end loop -** cleanup after the SELECT -** goto D -** B: open write cursor to
and its indices -** goto A -** C: insert the select result into
-** return -** D: cleanup -** -** The third template is used if the insert statement takes its -** values from a SELECT but the data is being inserted into a table -** that is also read as part of the SELECT. In the third form, -** we have to use a intermediate table to store the results of -** the select. The template is like this: -** -** goto B -** A: setup for the SELECT -** loop over the tables in the SELECT -** gosub C -** end loop -** cleanup after the SELECT -** goto D -** C: insert the select result into the intermediate table -** return -** B: open a cursor to an intermediate table -** goto A -** D: open write cursor to
and its indices -** loop over the intermediate table -** transfer values form intermediate table into
-** end the loop -** cleanup -*/ -void sqliteInsert( - Parse *pParse, /* Parser context */ - SrcList *pTabList, /* Name of table into which we are inserting */ - ExprList *pList, /* List of values to be inserted */ - Select *pSelect, /* A SELECT statement to use as the data source */ - IdList *pColumn, /* Column names corresponding to IDLIST. */ - int onError /* How to handle constraint errors */ -){ - Table *pTab; /* The table to insert into */ - char *zTab; /* Name of the table into which we are inserting */ - const char *zDb; /* Name of the database holding this table */ - int i, j, idx; /* Loop counters */ - Vdbe *v; /* Generate code into this virtual machine */ - Index *pIdx; /* For looping over indices of the table */ - int nColumn; /* Number of columns in the data */ - int base; /* VDBE Cursor number for pTab */ - int iCont, iBreak; /* Beginning and end of the loop over srcTab */ - sqlite *db; /* The main database structure */ - int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ - int endOfLoop; /* Label for the end of the insertion loop */ - int useTempTable; /* Store SELECT results in intermediate table */ - int srcTab; /* Data comes from this temporary cursor if >=0 */ - int iSelectLoop; /* Address of code that implements the SELECT */ - int iCleanup; /* Address of the cleanup code */ - int iInsertBlock; /* Address of the subroutine used to insert data */ - int iCntMem; /* Memory cell used for the row counter */ - int isView; /* True if attempting to insert into a view */ - - int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ - int before_triggers; /* True if there are BEFORE triggers */ - int after_triggers; /* True if there are AFTER triggers */ - int newIdx = -1; /* Cursor for the NEW table */ - - if( pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup; - db = pParse->db; - - /* Locate the table into which we will be inserting new information. - */ - assert( pTabList->nSrc==1 ); - zTab = pTabList->a[0].zName; - if( zTab==0 ) goto insert_cleanup; - pTab = sqliteSrcListLookup(pParse, pTabList); - if( pTab==0 ){ - goto insert_cleanup; - } - assert( pTab->iDbnDb ); - zDb = db->aDb[pTab->iDb].zName; - if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ - goto insert_cleanup; - } - - /* Ensure that: - * (a) the table is not read-only, - * (b) that if it is a view then ON INSERT triggers exist - */ - before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT, - TK_BEFORE, TK_ROW, 0); - after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT, - TK_AFTER, TK_ROW, 0); - row_triggers_exist = before_triggers || after_triggers; - isView = pTab->pSelect!=0; - if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){ - goto insert_cleanup; - } - if( pTab==0 ) goto insert_cleanup; - - /* If pTab is really a view, make sure it has been initialized. - */ - if( isView && sqliteViewGetColumnNames(pParse, pTab) ){ - goto insert_cleanup; - } - - /* Allocate a VDBE - */ - v = sqliteGetVdbe(pParse); - if( v==0 ) goto insert_cleanup; - sqliteBeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb); - - /* if there are row triggers, allocate a temp table for new.* references. */ - if( row_triggers_exist ){ - newIdx = pParse->nTab++; - } - - /* Figure out how many columns of data are supplied. If the data - ** is coming from a SELECT statement, then this step also generates - ** all the code to implement the SELECT statement and invoke a subroutine - ** to process each row of the result. (Template 2.) If the SELECT - ** statement uses the the table that is being inserted into, then the - ** subroutine is also coded here. That subroutine stores the SELECT - ** results in a temporary table. (Template 3.) - */ - if( pSelect ){ - /* Data is coming from a SELECT. Generate code to implement that SELECT - */ - int rc, iInitCode; - iInitCode = sqliteVdbeAddOp(v, OP_Goto, 0, 0); - iSelectLoop = sqliteVdbeCurrentAddr(v); - iInsertBlock = sqliteVdbeMakeLabel(v); - rc = sqliteSelect(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0); - if( rc || pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup; - iCleanup = sqliteVdbeMakeLabel(v); - sqliteVdbeAddOp(v, OP_Goto, 0, iCleanup); - assert( pSelect->pEList ); - nColumn = pSelect->pEList->nExpr; - - /* Set useTempTable to TRUE if the result of the SELECT statement - ** should be written into a temporary table. Set to FALSE if each - ** row of the SELECT can be written directly into the result table. - ** - ** A temp table must be used if the table being updated is also one - ** of the tables being read by the SELECT statement. Also use a - ** temp table in the case of row triggers. - */ - if( row_triggers_exist ){ - useTempTable = 1; - }else{ - int addr = sqliteVdbeFindOp(v, OP_OpenRead, pTab->tnum); - useTempTable = 0; - if( addr>0 ){ - VdbeOp *pOp = sqliteVdbeGetOp(v, addr-2); - if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){ - useTempTable = 1; - } - } - } - - if( useTempTable ){ - /* Generate the subroutine that SELECT calls to process each row of - ** the result. Store the result in a temporary table - */ - srcTab = pParse->nTab++; - sqliteVdbeResolveLabel(v, iInsertBlock); - sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); - sqliteVdbeAddOp(v, OP_NewRecno, srcTab, 0); - sqliteVdbeAddOp(v, OP_Pull, 1, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, srcTab, 0); - sqliteVdbeAddOp(v, OP_Return, 0, 0); - - /* The following code runs first because the GOTO at the very top - ** of the program jumps to it. Create the temporary table, then jump - ** back up and execute the SELECT code above. - */ - sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v)); - sqliteVdbeAddOp(v, OP_OpenTemp, srcTab, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop); - sqliteVdbeResolveLabel(v, iCleanup); - }else{ - sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v)); - } - }else{ - /* This is the case if the data for the INSERT is coming from a VALUES - ** clause - */ - SrcList dummy; - assert( pList!=0 ); - srcTab = -1; - useTempTable = 0; - assert( pList ); - nColumn = pList->nExpr; - dummy.nSrc = 0; - for(i=0; ia[i].pExpr) ){ - goto insert_cleanup; - } - if( sqliteExprCheck(pParse, pList->a[i].pExpr, 0, 0) ){ - goto insert_cleanup; - } - } - } - - /* Make sure the number of columns in the source data matches the number - ** of columns to be inserted into the table. - */ - if( pColumn==0 && nColumn!=pTab->nCol ){ - sqliteErrorMsg(pParse, - "table %S has %d columns but %d values were supplied", - pTabList, 0, pTab->nCol, nColumn); - goto insert_cleanup; - } - if( pColumn!=0 && nColumn!=pColumn->nId ){ - sqliteErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); - goto insert_cleanup; - } - - /* If the INSERT statement included an IDLIST term, then make sure - ** all elements of the IDLIST really are columns of the table and - ** remember the column indices. - ** - ** If the table has an INTEGER PRIMARY KEY column and that column - ** is named in the IDLIST, then record in the keyColumn variable - ** the index into IDLIST of the primary key column. keyColumn is - ** the index of the primary key as it appears in IDLIST, not as - ** is appears in the original table. (The index of the primary - ** key in the original table is pTab->iPKey.) - */ - if( pColumn ){ - for(i=0; inId; i++){ - pColumn->a[i].idx = -1; - } - for(i=0; inId; i++){ - for(j=0; jnCol; j++){ - if( sqliteStrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ - pColumn->a[i].idx = j; - if( j==pTab->iPKey ){ - keyColumn = i; - } - break; - } - } - if( j>=pTab->nCol ){ - if( sqliteIsRowid(pColumn->a[i].zName) ){ - keyColumn = i; - }else{ - sqliteErrorMsg(pParse, "table %S has no column named %s", - pTabList, 0, pColumn->a[i].zName); - pParse->nErr++; - goto insert_cleanup; - } - } - } - } - - /* If there is no IDLIST term but the table has an integer primary - ** key, the set the keyColumn variable to the primary key column index - ** in the original table definition. - */ - if( pColumn==0 ){ - keyColumn = pTab->iPKey; - } - - /* Open the temp table for FOR EACH ROW triggers - */ - if( row_triggers_exist ){ - sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0); - } - - /* Initialize the count of rows to be inserted - */ - if( db->flags & SQLITE_CountRows ){ - iCntMem = pParse->nMem++; - sqliteVdbeAddOp(v, OP_Integer, 0, 0); - sqliteVdbeAddOp(v, OP_MemStore, iCntMem, 1); - } - - /* Open tables and indices if there are no row triggers */ - if( !row_triggers_exist ){ - base = pParse->nTab; - idx = sqliteOpenTableAndIndices(pParse, pTab, base); - pParse->nTab += idx; - } - - /* If the data source is a temporary table, then we have to create - ** a loop because there might be multiple rows of data. If the data - ** source is a subroutine call from the SELECT statement, then we need - ** to launch the SELECT statement processing. - */ - if( useTempTable ){ - iBreak = sqliteVdbeMakeLabel(v); - sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak); - iCont = sqliteVdbeCurrentAddr(v); - }else if( pSelect ){ - sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop); - sqliteVdbeResolveLabel(v, iInsertBlock); - } - - /* Run the BEFORE and INSTEAD OF triggers, if there are any - */ - endOfLoop = sqliteVdbeMakeLabel(v); - if( before_triggers ){ - - /* build the NEW.* reference row. Note that if there is an INTEGER - ** PRIMARY KEY into which a NULL is being inserted, that NULL will be - ** translated into a unique ID for the row. But on a BEFORE trigger, - ** we do not know what the unique ID will be (because the insert has - ** not happened yet) so we substitute a rowid of -1 - */ - if( keyColumn<0 ){ - sqliteVdbeAddOp(v, OP_Integer, -1, 0); - }else if( useTempTable ){ - sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn); - }else if( pSelect ){ - sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); - }else{ - sqliteExprCode(pParse, pList->a[keyColumn].pExpr); - sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - sqliteVdbeAddOp(v, OP_Integer, -1, 0); - sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); - } - - /* Create the new column data - */ - for(i=0; inCol; i++){ - if( pColumn==0 ){ - j = i; - }else{ - for(j=0; jnId; j++){ - if( pColumn->a[j].idx==i ) break; - } - } - if( pColumn && j>=pColumn->nId ){ - sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); - }else if( useTempTable ){ - sqliteVdbeAddOp(v, OP_Column, srcTab, j); - }else if( pSelect ){ - sqliteVdbeAddOp(v, OP_Dup, nColumn-j-1, 1); - }else{ - sqliteExprCode(pParse, pList->a[j].pExpr); - } - } - sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); - - /* Fire BEFORE or INSTEAD OF triggers */ - if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, - newIdx, -1, onError, endOfLoop) ){ - goto insert_cleanup; - } - } - - /* If any triggers exists, the opening of tables and indices is deferred - ** until now. - */ - if( row_triggers_exist && !isView ){ - base = pParse->nTab; - idx = sqliteOpenTableAndIndices(pParse, pTab, base); - pParse->nTab += idx; - } - - /* Push the record number for the new entry onto the stack. The - ** record number is a randomly generate integer created by NewRecno - ** except when the table has an INTEGER PRIMARY KEY column, in which - ** case the record number is the same as that column. - */ - if( !isView ){ - if( keyColumn>=0 ){ - if( useTempTable ){ - sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn); - }else if( pSelect ){ - sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); - }else{ - sqliteExprCode(pParse, pList->a[keyColumn].pExpr); - } - /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno - ** to generate a unique primary key value. - */ - sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - sqliteVdbeAddOp(v, OP_NewRecno, base, 0); - sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); - }else{ - sqliteVdbeAddOp(v, OP_NewRecno, base, 0); - } - - /* Push onto the stack, data for all columns of the new entry, beginning - ** with the first column. - */ - for(i=0; inCol; i++){ - if( i==pTab->iPKey ){ - /* The value of the INTEGER PRIMARY KEY column is always a NULL. - ** Whenever this column is read, the record number will be substituted - ** in its place. So will fill this column with a NULL to avoid - ** taking up data space with information that will never be used. */ - sqliteVdbeAddOp(v, OP_String, 0, 0); - continue; - } - if( pColumn==0 ){ - j = i; - }else{ - for(j=0; jnId; j++){ - if( pColumn->a[j].idx==i ) break; - } - } - if( pColumn && j>=pColumn->nId ){ - sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); - }else if( useTempTable ){ - sqliteVdbeAddOp(v, OP_Column, srcTab, j); - }else if( pSelect ){ - sqliteVdbeAddOp(v, OP_Dup, i+nColumn-j, 1); - }else{ - sqliteExprCode(pParse, pList->a[j].pExpr); - } - } - - /* Generate code to check constraints and generate index keys and - ** do the insertion. - */ - sqliteGenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, - 0, onError, endOfLoop); - sqliteCompleteInsertion(pParse, pTab, base, 0,0,0, - after_triggers ? newIdx : -1); - } - - /* Update the count of rows that are inserted - */ - if( (db->flags & SQLITE_CountRows)!=0 ){ - sqliteVdbeAddOp(v, OP_MemIncr, iCntMem, 0); - } - - if( row_triggers_exist ){ - /* Close all tables opened */ - if( !isView ){ - sqliteVdbeAddOp(v, OP_Close, base, 0); - for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ - sqliteVdbeAddOp(v, OP_Close, idx+base, 0); - } - } - - /* Code AFTER triggers */ - if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1, - onError, endOfLoop) ){ - goto insert_cleanup; - } - } - - /* The bottom of the loop, if the data source is a SELECT statement - */ - sqliteVdbeResolveLabel(v, endOfLoop); - if( useTempTable ){ - sqliteVdbeAddOp(v, OP_Next, srcTab, iCont); - sqliteVdbeResolveLabel(v, iBreak); - sqliteVdbeAddOp(v, OP_Close, srcTab, 0); - }else if( pSelect ){ - sqliteVdbeAddOp(v, OP_Pop, nColumn, 0); - sqliteVdbeAddOp(v, OP_Return, 0, 0); - sqliteVdbeResolveLabel(v, iCleanup); - } - - if( !row_triggers_exist ){ - /* Close all tables opened */ - sqliteVdbeAddOp(v, OP_Close, base, 0); - for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ - sqliteVdbeAddOp(v, OP_Close, idx+base, 0); - } - } - - sqliteVdbeAddOp(v, OP_SetCounts, 0, 0); - sqliteEndWriteOperation(pParse); - - /* - ** Return the number of rows inserted. - */ - if( db->flags & SQLITE_CountRows ){ - sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows inserted", P3_STATIC); - sqliteVdbeAddOp(v, OP_MemLoad, iCntMem, 0); - sqliteVdbeAddOp(v, OP_Callback, 1, 0); - } - -insert_cleanup: - sqliteSrcListDelete(pTabList); - if( pList ) sqliteExprListDelete(pList); - if( pSelect ) sqliteSelectDelete(pSelect); - sqliteIdListDelete(pColumn); -} - -/* -** Generate code to do a constraint check prior to an INSERT or an UPDATE. -** -** When this routine is called, the stack contains (from bottom to top) -** the following values: -** -** 1. The recno of the row to be updated before the update. This -** value is omitted unless we are doing an UPDATE that involves a -** change to the record number. -** -** 2. The recno of the row after the update. -** -** 3. The data in the first column of the entry after the update. -** -** i. Data from middle columns... -** -** N. The data in the last column of the entry after the update. -** -** The old recno shown as entry (1) above is omitted unless both isUpdate -** and recnoChng are 1. isUpdate is true for UPDATEs and false for -** INSERTs and recnoChng is true if the record number is being changed. -** -** The code generated by this routine pushes additional entries onto -** the stack which are the keys for new index entries for the new record. -** The order of index keys is the same as the order of the indices on -** the pTable->pIndex list. A key is only created for index i if -** aIdxUsed!=0 and aIdxUsed[i]!=0. -** -** This routine also generates code to check constraints. NOT NULL, -** CHECK, and UNIQUE constraints are all checked. If a constraint fails, -** then the appropriate action is performed. There are five possible -** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE. -** -** Constraint type Action What Happens -** --------------- ---------- ---------------------------------------- -** any ROLLBACK The current transaction is rolled back and -** sqlite_exec() returns immediately with a -** return code of SQLITE_CONSTRAINT. -** -** any ABORT Back out changes from the current command -** only (do not do a complete rollback) then -** cause sqlite_exec() to return immediately -** with SQLITE_CONSTRAINT. -** -** any FAIL Sqlite_exec() returns immediately with a -** return code of SQLITE_CONSTRAINT. The -** transaction is not rolled back and any -** prior changes are retained. -** -** any IGNORE The record number and data is popped from -** the stack and there is an immediate jump -** to label ignoreDest. -** -** NOT NULL REPLACE The NULL value is replace by the default -** value for that column. If the default value -** is NULL, the action is the same as ABORT. -** -** UNIQUE REPLACE The other row that conflicts with the row -** being inserted is removed. -** -** CHECK REPLACE Illegal. The results in an exception. -** -** Which action to take is determined by the overrideError parameter. -** Or if overrideError==OE_Default, then the pParse->onError parameter -** is used. Or if pParse->onError==OE_Default then the onError value -** for the constraint is used. -** -** The calling routine must open a read/write cursor for pTab with -** cursor number "base". All indices of pTab must also have open -** read/write cursors with cursor number base+i for the i-th cursor. -** Except, if there is no possibility of a REPLACE action then -** cursors do not need to be open for indices where aIdxUsed[i]==0. -** -** If the isUpdate flag is true, it means that the "base" cursor is -** initially pointing to an entry that is being updated. The isUpdate -** flag causes extra code to be generated so that the "base" cursor -** is still pointing at the same entry after the routine returns. -** Without the isUpdate flag, the "base" cursor might be moved. -*/ -void sqliteGenerateConstraintChecks( - Parse *pParse, /* The parser context */ - Table *pTab, /* the table into which we are inserting */ - int base, /* Index of a read/write cursor pointing at pTab */ - char *aIdxUsed, /* Which indices are used. NULL means all are used */ - int recnoChng, /* True if the record number will change */ - int isUpdate, /* True for UPDATE, False for INSERT */ - int overrideError, /* Override onError to this if not OE_Default */ - int ignoreDest /* Jump to this label on an OE_Ignore resolution */ -){ - int i; - Vdbe *v; - int nCol; - int onError; - int addr; - int extra; - int iCur; - Index *pIdx; - int seenReplace = 0; - int jumpInst1, jumpInst2; - int contAddr; - int hasTwoRecnos = (isUpdate && recnoChng); - - v = sqliteGetVdbe(pParse); - assert( v!=0 ); - assert( pTab->pSelect==0 ); /* This table is not a VIEW */ - nCol = pTab->nCol; - - /* Test all NOT NULL constraints. - */ - for(i=0; iiPKey ){ - continue; - } - onError = pTab->aCol[i].notNull; - if( onError==OE_None ) continue; - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( pParse->db->onError!=OE_Default ){ - onError = pParse->db->onError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){ - onError = OE_Abort; - } - sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1); - addr = sqliteVdbeAddOp(v, OP_NotNull, 1, 0); - switch( onError ){ - case OE_Rollback: - case OE_Abort: - case OE_Fail: { - char *zMsg = 0; - sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError); - sqliteSetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName, - " may not be NULL", (char*)0); - sqliteVdbeChangeP3(v, -1, zMsg, P3_DYNAMIC); - break; - } - case OE_Ignore: { - sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest); - break; - } - case OE_Replace: { - sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); - sqliteVdbeAddOp(v, OP_Push, nCol-i, 0); - break; - } - default: assert(0); - } - sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); - } - - /* Test all CHECK constraints - */ - /**** TBD ****/ - - /* If we have an INTEGER PRIMARY KEY, make sure the primary key - ** of the new record does not previously exist. Except, if this - ** is an UPDATE and the primary key is not changing, that is OK. - */ - if( recnoChng ){ - onError = pTab->keyConf; - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( pParse->db->onError!=OE_Default ){ - onError = pParse->db->onError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - - if( isUpdate ){ - sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1); - sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1); - jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0); - } - sqliteVdbeAddOp(v, OP_Dup, nCol, 1); - jumpInst2 = sqliteVdbeAddOp(v, OP_NotExists, base, 0); - switch( onError ){ - default: { - onError = OE_Abort; - /* Fall thru into the next case */ - } - case OE_Rollback: - case OE_Abort: - case OE_Fail: { - sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, - "PRIMARY KEY must be unique", P3_STATIC); - break; - } - case OE_Replace: { - sqliteGenerateRowIndexDelete(pParse->db, v, pTab, base, 0); - if( isUpdate ){ - sqliteVdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1); - sqliteVdbeAddOp(v, OP_MoveTo, base, 0); - } - seenReplace = 1; - break; - } - case OE_Ignore: { - assert( seenReplace==0 ); - sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest); - break; - } - } - contAddr = sqliteVdbeCurrentAddr(v); - sqliteVdbeChangeP2(v, jumpInst2, contAddr); - if( isUpdate ){ - sqliteVdbeChangeP2(v, jumpInst1, contAddr); - sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1); - sqliteVdbeAddOp(v, OP_MoveTo, base, 0); - } - } - - /* Test all UNIQUE constraints by creating entries for each UNIQUE - ** index and making sure that duplicate entries do not already exist. - ** Add the new records to the indices as we go. - */ - extra = -1; - for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){ - if( aIdxUsed && aIdxUsed[iCur]==0 ) continue; /* Skip unused indices */ - extra++; - - /* Create a key for accessing the index entry */ - sqliteVdbeAddOp(v, OP_Dup, nCol+extra, 1); - for(i=0; inColumn; i++){ - int idx = pIdx->aiColumn[i]; - if( idx==pTab->iPKey ){ - sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1); - }else{ - sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1); - } - } - jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); - if( pParse->db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx); - - /* Find out what action to take in case there is an indexing conflict */ - onError = pIdx->onError; - if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */ - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( pParse->db->onError!=OE_Default ){ - onError = pParse->db->onError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - if( seenReplace ){ - if( onError==OE_Ignore ) onError = OE_Replace; - else if( onError==OE_Fail ) onError = OE_Abort; - } - - - /* Check to see if the new index entry will be unique */ - sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1); - jumpInst2 = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0); - - /* Generate code that executes if the new index entry is not unique */ - switch( onError ){ - case OE_Rollback: - case OE_Abort: - case OE_Fail: { - int j, n1, n2; - char zErrMsg[200]; - strcpy(zErrMsg, pIdx->nColumn>1 ? "columns " : "column "); - n1 = strlen(zErrMsg); - for(j=0; jnColumn && n1aCol[pIdx->aiColumn[j]].zName; - n2 = strlen(zCol); - if( j>0 ){ - strcpy(&zErrMsg[n1], ", "); - n1 += 2; - } - if( n1+n2>sizeof(zErrMsg)-30 ){ - strcpy(&zErrMsg[n1], "..."); - n1 += 3; - break; - }else{ - strcpy(&zErrMsg[n1], zCol); - n1 += n2; - } - } - strcpy(&zErrMsg[n1], - pIdx->nColumn>1 ? " are not unique" : " is not unique"); - sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0); - break; - } - case OE_Ignore: { - assert( seenReplace==0 ); - sqliteVdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest); - break; - } - case OE_Replace: { - sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0); - if( isUpdate ){ - sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1); - sqliteVdbeAddOp(v, OP_MoveTo, base, 0); - } - seenReplace = 1; - break; - } - default: assert(0); - } - contAddr = sqliteVdbeCurrentAddr(v); -#if NULL_DISTINCT_FOR_UNIQUE - sqliteVdbeChangeP2(v, jumpInst1, contAddr); -#endif - sqliteVdbeChangeP2(v, jumpInst2, contAddr); - } -} - -/* -** This routine generates code to finish the INSERT or UPDATE operation -** that was started by a prior call to sqliteGenerateConstraintChecks. -** The stack must contain keys for all active indices followed by data -** and the recno for the new entry. This routine creates the new -** entries in all indices and in the main table. -** -** The arguments to this routine should be the same as the first six -** arguments to sqliteGenerateConstraintChecks. -*/ -void sqliteCompleteInsertion( - Parse *pParse, /* The parser context */ - Table *pTab, /* the table into which we are inserting */ - int base, /* Index of a read/write cursor pointing at pTab */ - char *aIdxUsed, /* Which indices are used. NULL means all are used */ - int recnoChng, /* True if the record number will change */ - int isUpdate, /* True for UPDATE, False for INSERT */ - int newIdx /* Index of NEW table for triggers. -1 if none */ -){ - int i; - Vdbe *v; - int nIdx; - Index *pIdx; - - v = sqliteGetVdbe(pParse); - assert( v!=0 ); - assert( pTab->pSelect==0 ); /* This table is not a VIEW */ - for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} - for(i=nIdx-1; i>=0; i--){ - if( aIdxUsed && aIdxUsed[i]==0 ) continue; - sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, 0); - } - sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); - if( newIdx>=0 ){ - sqliteVdbeAddOp(v, OP_Dup, 1, 0); - sqliteVdbeAddOp(v, OP_Dup, 1, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); - } - sqliteVdbeAddOp(v, OP_PutIntKey, base, - (pParse->trigStack?0:OPFLAG_NCHANGE) | - (isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE); - if( isUpdate && recnoChng ){ - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - } -} - -/* -** Generate code that will open write cursors for a table and for all -** indices of that table. The "base" parameter is the cursor number used -** for the table. Indices are opened on subsequent cursors. -** -** Return the total number of cursors opened. This is always at least -** 1 (for the main table) plus more for each cursor. -*/ -int sqliteOpenTableAndIndices(Parse *pParse, Table *pTab, int base){ - int i; - Index *pIdx; - Vdbe *v = sqliteGetVdbe(pParse); - assert( v!=0 ); - sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeOp3(v, OP_OpenWrite, base, pTab->tnum, pTab->zName, P3_STATIC); - for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0); - sqliteVdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum, pIdx->zName, P3_STATIC); - } - return i; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/insert.o b/dbLifeLog/DBD-SQLite2-0.33/insert.o deleted file mode 100644 index a7d5d64c2c0d682d47a363ee3f5ee83556de1f88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16792 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 diff --git a/dbLifeLog/DBD-SQLite2-0.33/lib/DBD/SQLite2.pm b/dbLifeLog/DBD-SQLite2-0.33/lib/DBD/SQLite2.pm deleted file mode 100644 index 62c4e19..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/lib/DBD/SQLite2.pm +++ /dev/null @@ -1,542 +0,0 @@ -# $Id: SQLite2.pm,v 1.2 2004/09/10 15:43:39 matt Exp $ - -package DBD::SQLite2; -use strict; - -use DBI; -use vars qw($err $errstr $state $drh $VERSION @ISA); -$VERSION = '0.33'; - -use DynaLoader(); -@ISA = ('DynaLoader'); - -__PACKAGE__->bootstrap($VERSION); - -$drh = undef; - -sub driver { - return $drh if $drh; - my ($class, $attr) = @_; - - $class .= "::dr"; - - $drh = DBI::_new_drh($class, { - Name => 'SQLite2', - Version => $VERSION, - Attribution => 'DBD::SQLite2 by Matt Sergeant', - }); - - return $drh; -} - -sub CLONE { - undef $drh; -} - -package DBD::SQLite2::dr; - -sub connect { - my ($drh, $dbname, $user, $auth, $attr) = @_; - - my $dbh = DBI::_new_dbh($drh, { - Name => $dbname, - }); - - my $real_dbname = $dbname; - if ($dbname =~ /=/) { - foreach my $attrib (split(/;/, $dbname)) { - my ($k, $v) = split(/=/, $attrib, 2); - if ($k eq 'dbname') { - $real_dbname = $v; - } - else { - # TODO: add to attribs - } - } - } - DBD::SQLite2::db::_login($dbh, $real_dbname, $user, $auth) - or return undef; - - return $dbh; -} - -package DBD::SQLite2::db; - -sub prepare { - my ($dbh, $statement, @attribs) = @_; - - my $sth = DBI::_new_sth($dbh, { - Statement => $statement, - }); - - DBD::SQLite2::st::_prepare($sth, $statement, @attribs) - or return undef; - - return $sth; -} - - -sub table_info { - my ($dbh, $CatVal, $SchVal, $TblVal, $TypVal) = @_; - # SQL/CLI (ISO/IEC JTC 1/SC 32 N 0595), 6.63 Tables - # Based on DBD::Oracle's - # See also http://www.ch-werner.de/sqliteodbc/html/sqliteodbc_8c.html#a117 - - my @Where = (); - my $Sql; - if ( defined($CatVal) && $CatVal eq '%' - && defined($SchVal) && $SchVal eq '' - && defined($TblVal) && $TblVal eq '') { # Rule 19a - $Sql = <<'SQL'; -SELECT NULL TABLE_CAT - , NULL TABLE_SCHEM - , NULL TABLE_NAME - , NULL TABLE_TYPE - , NULL REMARKS -SQL - } - elsif ( defined($SchVal) && $SchVal eq '%' - && defined($CatVal) && $CatVal eq '' - && defined($TblVal) && $TblVal eq '') { # Rule 19b - $Sql = <<'SQL'; -SELECT NULL TABLE_CAT - , NULL TABLE_SCHEM - , NULL TABLE_NAME - , NULL TABLE_TYPE - , NULL REMARKS -SQL - } - elsif ( defined($TypVal) && $TypVal eq '%' - && defined($CatVal) && $CatVal eq '' - && defined($SchVal) && $SchVal eq '' - && defined($TblVal) && $TblVal eq '') { # Rule 19c - $Sql = <<'SQL'; -SELECT NULL TABLE_CAT - , NULL TABLE_SCHEM - , NULL TABLE_NAME - , t.tt TABLE_TYPE - , NULL REMARKS -FROM ( - SELECT 'TABLE' tt UNION - SELECT 'VIEW' tt UNION - SELECT 'LOCAL TEMPORARY' tt -) t -ORDER BY TABLE_TYPE -SQL - } - else { - $Sql = <<'SQL'; -SELECT * -FROM -( -SELECT NULL TABLE_CAT - , NULL TABLE_SCHEM - , tbl_name TABLE_NAME - , TABLE_TYPE - , NULL REMARKS - , sql sqlite_sql -FROM ( - SELECT tbl_name, upper(type) TABLE_TYPE, sql - FROM sqlite_master - WHERE type IN ( 'table','view') -UNION ALL - SELECT tbl_name, 'LOCAL TEMPORARY' TABLE_TYPE, sql - FROM sqlite_temp_master - WHERE type IN ( 'table','view') -UNION ALL - SELECT 'sqlite_master' tbl_name, 'SYSTEM TABLE' TABLE_TYPE, NULL sql -UNION ALL - SELECT 'sqlite_temp_master' tbl_name, 'SYSTEM TABLE' TABLE_TYPE, NULL sql -) -) -SQL - if ( defined $TblVal ) { - push @Where, "TABLE_NAME LIKE '$TblVal'"; - } - if ( defined $TypVal ) { - my $table_type_list; - $TypVal =~ s/^\s+//; - $TypVal =~ s/\s+$//; - my @ttype_list = split (/\s*,\s*/, $TypVal); - foreach my $table_type (@ttype_list) { - if ($table_type !~ /^'.*'$/) { - $table_type = "'" . $table_type . "'"; - } - $table_type_list = join(", ", @ttype_list); - } - push @Where, "TABLE_TYPE IN (\U$table_type_list)" - if $table_type_list; - } - $Sql .= ' WHERE ' . join("\n AND ", @Where ) . "\n" if @Where; - $Sql .= " ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME\n"; - } - my $sth = $dbh->prepare($Sql) or return undef; - $sth->execute or return undef; - $sth; -} - - -sub primary_key_info { - my($dbh, $catalog, $schema, $table) = @_; - - my @pk_info; - - my $sth_tables = $dbh->table_info($catalog, $schema, $table, ''); - - # this is a hack but much simpler than using pragma index_list etc - # also the pragma doesn't list 'INTEGER PRIMARK KEY' autoinc PKs! - while ( my $row = $sth_tables->fetchrow_hashref ) { - my $sql = $row->{sqlite_sql} or next; - next unless $sql =~ /(.*?)\s*PRIMARY\s+KEY\s*(?:\(\s*(.*?)\s*\))?/si; - my @pk = split /\s*,\s*/, $2 || ''; - unless (@pk) { - my $prefix = $1; - $prefix =~ s/.*create\s+table\s+.*?\(//i; - $prefix = (split /\s*,\s*/, $prefix)[-1]; - @pk = (split /\s+/, $prefix)[0]; # take first word as name - } - #warn "GOT PK $row->{TABLE_NAME} (@pk)\n"; - my $key_seq = 0; - for my $pk_field (@pk) { - push @pk_info, { - TABLE_SCHEM => $row->{TABLE_SCHEM}, - TABLE_NAME => $row->{TABLE_NAME}, - COLUMN_NAME => $pk_field, - KEY_SEQ => ++$key_seq, - PK_NAME => 'PRIMARY KEY', - }; - } - } - - my $sponge = DBI->connect("DBI:Sponge:", '','') - or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr"); - my @names = qw(TABLE_CAT TABLE_SCHEM TABLE_NAME COLUMN_NAME KEY_SEQ PK_NAME); - my $sth = $sponge->prepare("column_info $table", { - rows => [ map { [ @{$_}{@names} ] } @pk_info ], - NUM_OF_FIELDS => scalar @names, - NAME => \@names, - }) or return $dbh->DBI::set_err($sponge->err(), $sponge->errstr()); - return $sth; -} - -sub type_info_all { - my ($dbh) = @_; -return; # XXX code just copied from DBD::Oracle, not yet thought about - my $names = { - TYPE_NAME => 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - FIXED_PREC_SCALE =>10, - AUTO_UNIQUE_VALUE =>11, - LOCAL_TYPE_NAME =>12, - MINIMUM_SCALE =>13, - MAXIMUM_SCALE =>14, - SQL_DATA_TYPE =>15, - SQL_DATETIME_SUB=>16, - NUM_PREC_RADIX =>17, - }; - my $ti = [ - $names, - [ 'CHAR', 1, 255, '\'', '\'', 'max length', 1, 1, 3, - undef, '0', '0', undef, undef, undef, 1, undef, undef - ], - [ 'NUMBER', 3, 38, undef, undef, 'precision,scale', 1, '0', 3, - '0', '0', '0', undef, '0', 38, 3, undef, 10 - ], - [ 'DOUBLE', 8, 15, undef, undef, undef, 1, '0', 3, - '0', '0', '0', undef, undef, undef, 8, undef, 10 - ], - [ 'DATE', 9, 19, '\'', '\'', undef, 1, '0', 3, - undef, '0', '0', undef, '0', '0', 11, undef, undef - ], - [ 'VARCHAR', 12, 1024*1024, '\'', '\'', 'max length', 1, 1, 3, - undef, '0', '0', undef, undef, undef, 12, undef, undef - ] - ]; - return $ti; -} - - -1; -__END__ - -=head1 NAME - -DBD::SQLite2 - Self Contained RDBMS in a DBI Driver (sqlite 2.x) - -=head1 SYNOPSIS - - use DBI; - my $dbh = DBI->connect("dbi:SQLite2:dbname=dbfile","",""); - -=head1 DESCRIPTION - -SQLite is a public domain RDBMS database engine that you can find -at http://www.hwaci.com/sw/sqlite/. - -Rather than ask you to install SQLite first, because SQLite is public -domain, DBD::SQLite2 includes the entire thing in the distribution. So -in order to get a fast transaction capable RDBMS working for your -perl project you simply have to install this module, and B -else. - -SQLite supports the following features: - -=over 4 - -=item Implements a large subset of SQL92 - -See http://www.hwaci.com/sw/sqlite/lang.html for details. - -=item A complete DB in a single disk file - -Everything for your database is stored in a single disk file, making it -easier to move things around than with DBD::CSV. - -=item Atomic commit and rollback - -Yes, DBD::SQLite2 is small and light, but it supports full transactions! - -=item Extensible - -User-defined aggregate or regular functions can be registered with the -SQL parser. - -=back - -There's lots more to it, so please refer to the docs on the SQLite web -page, listed above, for SQL details. Also refer to L for details -on how to use DBI itself. - -=head1 CONFORMANCE WITH DBI SPECIFICATION - -The API works like every DBI module does. Please see L for more -details about core features. - -Currently many statement attributes are not implemented or are -limited by the typeless nature of the SQLite database. - -=head1 DRIVER PRIVATE ATTRIBUTES - -=head2 Database Handle Attributes - -=over 4 - -=item sqlite_version - -Returns the version of the SQLite library which DBD::SQLite2 is using, e.g., "2.8.0". - -=item sqlite_encoding - -Returns either "UTF-8" or "iso8859" to indicate how the SQLite library was compiled. - -=item sqlite_handle_binary_nulls - -Set this attribute to 1 to transparently handle binary nulls in quoted -and returned data. - -B This will cause all backslash characters (C<\>) to be doubled -up in all columns regardless of whether or not they contain binary -data or not. This may break your database if you use it from another -application. This does not use the built in sqlite_encode_binary -and sqlite_decode_binary functions, which may be considered a bug. - -=back - -=head1 DRIVER PRIVATE METHODS - -=head2 $dbh->func('last_insert_rowid') - -This method returns the last inserted rowid. If you specify an INTEGER PRIMARY -KEY as the first column in your table, that is the column that is returned. -Otherwise, it is the hidden ROWID column. See the sqlite docs for details. - -=head2 $dbh->func( $name, $argc, $func_ref, "create_function" ) - -This method will register a new function which will be useable in SQL -query. The method's parameters are: - -=over - -=item $name - -The name of the function. This is the name of the function as it will -be used from SQL. - -=item $argc - -The number of arguments taken by the function. If this number is -1, -the function can take any number of arguments. - -=item $func_ref - -This should be a reference to the function's implementation. - -=back - -For example, here is how to define a now() function which returns the -current number of seconds since the epoch: - - $dbh->func( 'now', 0, sub { return time }, 'create_function' ); - -After this, it could be use from SQL as: - - INSERT INTO mytable ( now() ); - -=head2 $dbh->func( $name, $argc, $pkg, 'create_aggregate' ) - -This method will register a new aggregate function which can then used -from SQL. The method's parameters are: - -=over - -=item $name - -The name of the aggregate function, this is the name under which the -function will be available from SQL. - -=item $argc - -This is an integer which tells the SQL parser how many arguments the -function takes. If that number is -1, the function can take any number -of arguments. - -=item $pkg - -This is the package which implements the aggregator interface. - -=back - -The aggregator interface consists of defining three methods: - -=over - -=item new() - -This method will be called once to create an object which should -be used to aggregate the rows in a particular group. The step() and -finalize() methods will be called upon the reference return by -the method. - -=item step(@_) - -This method will be called once for each rows in the aggregate. - -=item finalize() - -This method will be called once all rows in the aggregate were -processed and it should return the aggregate function's result. When -there is no rows in the aggregate, finalize() will be called right -after new(). - -=back - -Here is a simple aggregate function which returns the variance -(example adapted from pysqlite): - - package variance; - - sub new { bless [], shift; } - - sub step { - my ( $self, $value ) = @_; - - push @$self, $value; - } - - sub finalize { - my $self = $_[0]; - - my $n = @$self; - - # Variance is NULL unless there is more than one row - return undef unless $n || $n == 1; - - my $mu = 0; - foreach my $v ( @$self ) { - $mu += $v; - } - $mu /= $n; - - my $sigma = 0; - foreach my $v ( @$self ) { - $sigma += ($x - $mu)**2; - } - $sigma = $sigma / ($n - 1); - - return $sigma; - } - - $dbh->func( "variance", 1, 'variance', "create_aggregate" ); - -The aggregate function can then be used as: - - SELECT group_name, variance(score) FROM results - GROUP BY group_name; - -=head1 NOTES - -To access the database from the command line, try using dbish which comes with -the DBI module. Just type: - - dbish dbi:SQLite:foo.db - -On the command line to access the file F. - -Alternatively you can install SQLite from the link above without conflicting -with DBD::SQLite2 and use the supplied C command line tool. - -=head1 PERFORMANCE - -SQLite is fast, very fast. I recently processed my 72MB log file with it, -inserting the data (400,000+ rows) by using transactions and only committing -every 1000 rows (otherwise the insertion is quite slow), and then performing -queries on the data. - -Queries like count(*) and avg(bytes) took fractions of a second to return, -but what surprised me most of all was: - - SELECT url, count(*) as count FROM access_log - GROUP BY url - ORDER BY count desc - LIMIT 20 - -To discover the top 20 hit URLs on the site (http://axkit.org), and it -returned within 2 seconds. I'm seriously considering switching my log -analysis code to use this little speed demon! - -Oh yeah, and that was with no indexes on the table, on a 400MHz PIII. - -For best performance be sure to tune your hdparm settings if you are -using linux. Also you might want to set: - - PRAGMA default_synchronous = OFF - -Which will prevent sqlite from doing fsync's when writing (which -slows down non-transactional writes significantly) at the expense of some -peace of mind. Also try playing with the cache_size pragma. - -=head1 BUGS - -Likely to be many, please use http://rt.cpan.org/ for reporting bugs. - -=head1 AUTHOR - -Matt Sergeant, matt@sergeant.org - -Perl extension functions contributed by Francis J. Lacoste - and Wolfgang Sourdeau - - -=head1 SEE ALSO - -L. - -=cut diff --git a/dbLifeLog/DBD-SQLite2-0.33/main.c b/dbLifeLog/DBD-SQLite2-0.33/main.c deleted file mode 100644 index b143401..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/main.c +++ /dev/null @@ -1,1143 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Main file for the SQLite library. The routines in this file -** implement the programmer interface to the library. Routines in -** other files are for internal use by SQLite and should not be -** accessed by users of the library. -** -** $Id: main.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ -#include "sqliteInt.h" -#include "os.h" -#include - -/* -** A pointer to this structure is used to communicate information -** from sqliteInit into the sqliteInitCallback. -*/ -typedef struct { - sqlite *db; /* The database being initialized */ - char **pzErrMsg; /* Error message stored here */ -} InitData; - -/* -** Fill the InitData structure with an error message that indicates -** that the database is corrupt. -*/ -static void corruptSchema(InitData *pData, const char *zExtra){ - sqliteSetString(pData->pzErrMsg, "malformed database schema", - zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0); -} - -/* -** This is the callback routine for the code that initializes the -** database. See sqliteInit() below for additional information. -** -** Each callback contains the following information: -** -** argv[0] = "file-format" or "schema-cookie" or "table" or "index" -** argv[1] = table or index name or meta statement type. -** argv[2] = root page number for table or index. NULL for meta. -** argv[3] = SQL text for a CREATE TABLE or CREATE INDEX statement. -** argv[4] = "1" for temporary files, "0" for main database, "2" or more -** for auxiliary database files. -** -*/ -static -int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){ - InitData *pData = (InitData*)pInit; - int nErr = 0; - - assert( argc==5 ); - if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ - if( argv[0]==0 ){ - corruptSchema(pData, 0); - return 1; - } - switch( argv[0][0] ){ - case 'v': - case 'i': - case 't': { /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */ - sqlite *db = pData->db; - if( argv[2]==0 || argv[4]==0 ){ - corruptSchema(pData, 0); - return 1; - } - if( argv[3] && argv[3][0] ){ - /* Call the parser to process a CREATE TABLE, INDEX or VIEW. - ** But because db->init.busy is set to 1, no VDBE code is generated - ** or executed. All the parser does is build the internal data - ** structures that describe the table, index, or view. - */ - char *zErr; - assert( db->init.busy ); - db->init.iDb = atoi(argv[4]); - assert( db->init.iDb>=0 && db->init.iDbnDb ); - db->init.newTnum = atoi(argv[2]); - if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){ - corruptSchema(pData, zErr); - sqlite_freemem(zErr); - } - db->init.iDb = 0; - }else{ - /* If the SQL column is blank it means this is an index that - ** was created to be the PRIMARY KEY or to fulfill a UNIQUE - ** constraint for a CREATE TABLE. The index should have already - ** been created when we processed the CREATE TABLE. All we have - ** to do here is record the root page number for that index. - */ - int iDb; - Index *pIndex; - - iDb = atoi(argv[4]); - assert( iDb>=0 && iDbnDb ); - pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName); - if( pIndex==0 || pIndex->tnum!=0 ){ - /* This can occur if there exists an index on a TEMP table which - ** has the same name as another index on a permanent index. Since - ** the permanent table is hidden by the TEMP table, we can also - ** safely ignore the index on the permanent table. - */ - /* Do Nothing */; - }else{ - pIndex->tnum = atoi(argv[2]); - } - } - break; - } - default: { - /* This can not happen! */ - nErr = 1; - assert( nErr==0 ); - } - } - return nErr; -} - -/* -** This is a callback procedure used to reconstruct a table. The -** name of the table to be reconstructed is passed in as argv[0]. -** -** This routine is used to automatically upgrade a database from -** format version 1 or 2 to version 3. The correct operation of -** this routine relys on the fact that no indices are used when -** copying a table out to a temporary file. -** -** The change from version 2 to version 3 occurred between SQLite -** version 2.5.6 and 2.6.0 on 2002-July-18. -*/ -static -int upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){ - InitData *pData = (InitData*)pInit; - int rc; - Table *pTab; - Trigger *pTrig; - char *zErr = 0; - - pTab = sqliteFindTable(pData->db, argv[0], 0); - assert( pTab!=0 ); - assert( sqliteStrICmp(pTab->zName, argv[0])==0 ); - if( pTab ){ - pTrig = pTab->pTrigger; - pTab->pTrigger = 0; /* Disable all triggers before rebuilding the table */ - } - rc = sqlite_exec_printf(pData->db, - "CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; " - "DELETE FROM '%q'; " - "INSERT INTO '%q' SELECT * FROM sqlite_x; " - "DROP TABLE sqlite_x;", - 0, 0, &zErr, argv[0], argv[0], argv[0]); - if( zErr ){ - if( *pData->pzErrMsg ) sqlite_freemem(*pData->pzErrMsg); - *pData->pzErrMsg = zErr; - } - - /* If an error occurred in the SQL above, then the transaction will - ** rollback which will delete the internal symbol tables. This will - ** cause the structure that pTab points to be deleted. In case that - ** happened, we need to refetch pTab. - */ - pTab = sqliteFindTable(pData->db, argv[0], 0); - if( pTab ){ - assert( sqliteStrICmp(pTab->zName, argv[0])==0 ); - pTab->pTrigger = pTrig; /* Re-enable triggers */ - } - return rc!=SQLITE_OK; -} - - - -/* -** Attempt to read the database schema and initialize internal -** data structures for a single database file. The index of the -** database file is given by iDb. iDb==0 is used for the main -** database. iDb==1 should never be used. iDb>=2 is used for -** auxiliary databases. Return one of the SQLITE_ error codes to -** indicate success or failure. -*/ -static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){ - int rc; - BtCursor *curMain; - int size; - Table *pTab; - char const *azArg[6]; - char zDbNum[30]; - int meta[SQLITE_N_BTREE_META]; - InitData initData; - char const *zMasterSchema; - char const *zMasterName; - char *zSql = 0; - - /* - ** The master database table has a structure like this - */ - static char master_schema[] = - "CREATE TABLE sqlite_master(\n" - " type text,\n" - " name text,\n" - " tbl_name text,\n" - " rootpage integer,\n" - " sql text\n" - ")" - ; - static char temp_master_schema[] = - "CREATE TEMP TABLE sqlite_temp_master(\n" - " type text,\n" - " name text,\n" - " tbl_name text,\n" - " rootpage integer,\n" - " sql text\n" - ")" - ; - - assert( iDb>=0 && iDbnDb ); - - /* zMasterSchema and zInitScript are set to point at the master schema - ** and initialisation script appropriate for the database being - ** initialised. zMasterName is the name of the master table. - */ - if( iDb==1 ){ - zMasterSchema = temp_master_schema; - zMasterName = TEMP_MASTER_NAME; - }else{ - zMasterSchema = master_schema; - zMasterName = MASTER_NAME; - } - - /* Construct the schema table. - */ - sqliteSafetyOff(db); - azArg[0] = "table"; - azArg[1] = zMasterName; - azArg[2] = "2"; - azArg[3] = zMasterSchema; - sprintf(zDbNum, "%d", iDb); - azArg[4] = zDbNum; - azArg[5] = 0; - initData.db = db; - initData.pzErrMsg = pzErrMsg; - sqliteInitCallback(&initData, 5, (char **)azArg, 0); - pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName); - if( pTab ){ - pTab->readOnly = 1; - }else{ - return SQLITE_NOMEM; - } - sqliteSafetyOn(db); - - /* Create a cursor to hold the database open - */ - if( db->aDb[iDb].pBt==0 ) return SQLITE_OK; - rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain); - if( rc ){ - sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0); - return rc; - } - - /* Get the database meta information - */ - rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta); - if( rc ){ - sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0); - sqliteBtreeCloseCursor(curMain); - return rc; - } - db->aDb[iDb].schema_cookie = meta[1]; - if( iDb==0 ){ - db->next_cookie = meta[1]; - db->file_format = meta[2]; - size = meta[3]; - if( size==0 ){ size = MAX_PAGES; } - db->cache_size = size; - db->safety_level = meta[4]; - if( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){ - db->temp_store = meta[6]; - } - if( db->safety_level==0 ) db->safety_level = 2; - - /* - ** file_format==1 Version 2.1.0. - ** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. - ** file_format==3 Version 2.6.0. Fix empty-string index bug. - ** file_format==4 Version 2.7.0. Add support for separate numeric and - ** text datatypes. - */ - if( db->file_format==0 ){ - /* This happens if the database was initially empty */ - db->file_format = 4; - }else if( db->file_format>4 ){ - sqliteBtreeCloseCursor(curMain); - sqliteSetString(pzErrMsg, "unsupported file format", (char*)0); - return SQLITE_ERROR; - } - }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){ - assert( db->file_format>=4 ); - if( meta[2]==0 ){ - sqliteSetString(pzErrMsg, "cannot attach empty database: ", - db->aDb[iDb].zName, (char*)0); - }else{ - sqliteSetString(pzErrMsg, "incompatible file format in auxiliary " - "database: ", db->aDb[iDb].zName, (char*)0); - } - sqliteBtreeClose(db->aDb[iDb].pBt); - db->aDb[iDb].pBt = 0; - return SQLITE_FORMAT; - } - sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size); - sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]); - - /* Read the schema information out of the schema tables - */ - assert( db->init.busy ); - sqliteSafetyOff(db); - - /* The following SQL will read the schema from the master tables. - ** The first version works with SQLite file formats 2 or greater. - ** The second version is for format 1 files. - ** - ** Beginning with file format 2, the rowid for new table entries - ** (including entries in sqlite_master) is an increasing integer. - ** So for file format 2 and later, we can play back sqlite_master - ** and all the CREATE statements will appear in the right order. - ** But with file format 1, table entries were random and so we - ** have to make sure the CREATE TABLEs occur before their corresponding - ** CREATE INDEXs. (We don't have to deal with CREATE VIEW or - ** CREATE TRIGGER in file format 1 because those constructs did - ** not exist then.) - */ - if( db->file_format>=2 ){ - sqliteSetString(&zSql, - "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"", - db->aDb[iDb].zName, "\".", zMasterName, (char*)0); - }else{ - sqliteSetString(&zSql, - "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"", - db->aDb[iDb].zName, "\".", zMasterName, - " WHERE type IN ('table', 'index')" - " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0); - } - rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0); - - sqliteFree(zSql); - sqliteSafetyOn(db); - sqliteBtreeCloseCursor(curMain); - if( sqlite_malloc_failed ){ - sqliteSetString(pzErrMsg, "out of memory", (char*)0); - rc = SQLITE_NOMEM; - sqliteResetInternalSchema(db, 0); - } - if( rc==SQLITE_OK ){ - DbSetProperty(db, iDb, DB_SchemaLoaded); - }else{ - sqliteResetInternalSchema(db, iDb); - } - return rc; -} - -/* -** Initialize all database files - the main database file, the file -** used to store temporary tables, and any additional database files -** created using ATTACH statements. Return a success code. If an -** error occurs, write an error message into *pzErrMsg. -** -** After the database is initialized, the SQLITE_Initialized -** bit is set in the flags field of the sqlite structure. An -** attempt is made to initialize the database as soon as it -** is opened. If that fails (perhaps because another process -** has the sqlite_master table locked) than another attempt -** is made the first time the database is accessed. -*/ -int sqliteInit(sqlite *db, char **pzErrMsg){ - int i, rc; - - if( db->init.busy ) return SQLITE_OK; - assert( (db->flags & SQLITE_Initialized)==0 ); - rc = SQLITE_OK; - db->init.busy = 1; - for(i=0; rc==SQLITE_OK && inDb; i++){ - if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; - rc = sqliteInitOne(db, i, pzErrMsg); - if( rc ){ - sqliteResetInternalSchema(db, i); - } - } - - /* Once all the other databases have been initialised, load the schema - ** for the TEMP database. This is loaded last, as the TEMP database - ** schema may contain references to objects in other databases. - */ - if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ - rc = sqliteInitOne(db, 1, pzErrMsg); - if( rc ){ - sqliteResetInternalSchema(db, 1); - } - } - - db->init.busy = 0; - if( rc==SQLITE_OK ){ - db->flags |= SQLITE_Initialized; - sqliteCommitInternalChanges(db); - } - - /* If the database is in formats 1 or 2, then upgrade it to - ** version 3. This will reconstruct all indices. If the - ** upgrade fails for any reason (ex: out of disk space, database - ** is read only, interrupt received, etc.) then fail the init. - */ - if( rc==SQLITE_OK && db->file_format<3 ){ - char *zErr = 0; - InitData initData; - int meta[SQLITE_N_BTREE_META]; - - db->magic = SQLITE_MAGIC_OPEN; - initData.db = db; - initData.pzErrMsg = &zErr; - db->file_format = 3; - rc = sqlite_exec(db, - "BEGIN; SELECT name FROM sqlite_master WHERE type='table';", - upgrade_3_callback, - &initData, - &zErr); - if( rc==SQLITE_OK ){ - sqliteBtreeGetMeta(db->aDb[0].pBt, meta); - meta[2] = 4; - sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta); - sqlite_exec(db, "COMMIT", 0, 0, 0); - } - if( rc!=SQLITE_OK ){ - sqliteSetString(pzErrMsg, - "unable to upgrade database to the version 2.6 format", - zErr ? ": " : 0, zErr, (char*)0); - } - sqlite_freemem(zErr); - } - - if( rc!=SQLITE_OK ){ - db->flags &= ~SQLITE_Initialized; - } - return rc; -} - -/* -** The version of the library -*/ -const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $"; -const char sqlite_version[] = SQLITE_VERSION; - -/* -** Does the library expect data to be encoded as UTF-8 or iso8859? The -** following global constant always lets us know. -*/ -#ifdef SQLITE_UTF8 -const char sqlite_encoding[] = "UTF-8"; -#else -const char sqlite_encoding[] = "iso8859"; -#endif - -/* -** Open a new SQLite database. Construct an "sqlite" structure to define -** the state of this database and return a pointer to that structure. -** -** An attempt is made to initialize the in-memory data structures that -** hold the database schema. But if this fails (because the schema file -** is locked) then that step is deferred until the first call to -** sqlite_exec(). -*/ -sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ - sqlite *db; - int rc, i; - - /* Allocate the sqlite data structure */ - db = sqliteMalloc( sizeof(sqlite) ); - if( pzErrMsg ) *pzErrMsg = 0; - if( db==0 ) goto no_mem_on_open; - db->onError = OE_Default; - db->priorNewRowid = 0; - db->magic = SQLITE_MAGIC_BUSY; - db->nDb = 2; - db->aDb = db->aDbStatic; - /* db->flags |= SQLITE_ShortColNames; */ - sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1); - for(i=0; inDb; i++){ - sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0); - sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0); - sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0); - sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1); - } - - /* Open the backend database driver */ - if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){ - db->temp_store = 2; - } - rc = sqliteBtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); - if( rc!=SQLITE_OK ){ - switch( rc ){ - default: { - sqliteSetString(pzErrMsg, "unable to open database: ", - zFilename, (char*)0); - } - } - sqliteFree(db); - sqliteStrRealloc(pzErrMsg); - return 0; - } - db->aDb[0].zName = "main"; - db->aDb[1].zName = "temp"; - - /* Attempt to read the schema */ - sqliteRegisterBuiltinFunctions(db); - rc = sqliteInit(db, pzErrMsg); - db->magic = SQLITE_MAGIC_OPEN; - if( sqlite_malloc_failed ){ - sqlite_close(db); - goto no_mem_on_open; - }else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ - sqlite_close(db); - sqliteStrRealloc(pzErrMsg); - return 0; - }else if( pzErrMsg ){ - sqliteFree(*pzErrMsg); - *pzErrMsg = 0; - } - - /* Return a pointer to the newly opened database structure */ - return db; - -no_mem_on_open: - sqliteSetString(pzErrMsg, "out of memory", (char*)0); - sqliteStrRealloc(pzErrMsg); - return 0; -} - -/* -** Return the ROWID of the most recent insert -*/ -int sqlite_last_insert_rowid(sqlite *db){ - return db->lastRowid; -} - -/* -** Return the number of changes in the most recent call to sqlite_exec(). -*/ -int sqlite_changes(sqlite *db){ - return db->nChange; -} - -/* -** Return the number of changes produced by the last INSERT, UPDATE, or -** DELETE statement to complete execution. The count does not include -** changes due to SQL statements executed in trigger programs that were -** triggered by that statement -*/ -int sqlite_last_statement_changes(sqlite *db){ - return db->lsChange; -} - -/* -** Close an existing SQLite database -*/ -void sqlite_close(sqlite *db){ - HashElem *i; - int j; - db->want_to_close = 1; - if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){ - /* printf("DID NOT CLOSE\n"); fflush(stdout); */ - return; - } - db->magic = SQLITE_MAGIC_CLOSED; - for(j=0; jnDb; j++){ - struct Db *pDb = &db->aDb[j]; - if( pDb->pBt ){ - sqliteBtreeClose(pDb->pBt); - pDb->pBt = 0; - } - } - sqliteResetInternalSchema(db, 0); - assert( db->nDb<=2 ); - assert( db->aDb==db->aDbStatic ); - for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ - FuncDef *pFunc, *pNext; - for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ - pNext = pFunc->pNext; - sqliteFree(pFunc); - } - } - sqliteHashClear(&db->aFunc); - sqliteFree(db); -} - -/* -** Rollback all database files. -*/ -void sqliteRollbackAll(sqlite *db){ - int i; - for(i=0; inDb; i++){ - if( db->aDb[i].pBt ){ - sqliteBtreeRollback(db->aDb[i].pBt); - db->aDb[i].inTrans = 0; - } - } - sqliteResetInternalSchema(db, 0); - /* sqliteRollbackInternalChanges(db); */ -} - -/* -** Execute SQL code. Return one of the SQLITE_ success/failure -** codes. Also write an error message into memory obtained from -** malloc() and make *pzErrMsg point to that message. -** -** If the SQL is a query, then for each row in the query result -** the xCallback() function is called. pArg becomes the first -** argument to xCallback(). If xCallback=NULL then no callback -** is invoked, even for queries. -*/ -int sqlite_exec( - sqlite *db, /* The database on which the SQL executes */ - const char *zSql, /* The SQL to be executed */ - sqlite_callback xCallback, /* Invoke this callback routine */ - void *pArg, /* First argument to xCallback() */ - char **pzErrMsg /* Write error messages here */ -){ - int rc = SQLITE_OK; - const char *zLeftover; - sqlite_vm *pVm; - int nRetry = 0; - int nChange = 0; - int nCallback; - - if( zSql==0 ) return SQLITE_OK; - while( rc==SQLITE_OK && zSql[0] ){ - pVm = 0; - rc = sqlite_compile(db, zSql, &zLeftover, &pVm, pzErrMsg); - if( rc!=SQLITE_OK ){ - assert( pVm==0 || sqlite_malloc_failed ); - return rc; - } - if( pVm==0 ){ - /* This happens if the zSql input contained only whitespace */ - break; - } - db->nChange += nChange; - nCallback = 0; - while(1){ - int nArg; - char **azArg, **azCol; - rc = sqlite_step(pVm, &nArg, (const char***)&azArg,(const char***)&azCol); - if( rc==SQLITE_ROW ){ - if( xCallback!=0 && xCallback(pArg, nArg, azArg, azCol) ){ - sqlite_finalize(pVm, 0); - return SQLITE_ABORT; - } - nCallback++; - }else{ - if( rc==SQLITE_DONE && nCallback==0 - && (db->flags & SQLITE_NullCallback)!=0 && xCallback!=0 ){ - xCallback(pArg, nArg, azArg, azCol); - } - rc = sqlite_finalize(pVm, pzErrMsg); - if( rc==SQLITE_SCHEMA && nRetry<2 ){ - nRetry++; - rc = SQLITE_OK; - break; - } - if( db->pVdbe==0 ){ - nChange = db->nChange; - } - nRetry = 0; - zSql = zLeftover; - while( isspace(zSql[0]) ) zSql++; - break; - } - } - } - return rc; -} - - -/* -** Compile a single statement of SQL into a virtual machine. Return one -** of the SQLITE_ success/failure codes. Also write an error message into -** memory obtained from malloc() and make *pzErrMsg point to that message. -*/ -int sqlite_compile( - sqlite *db, /* The database on which the SQL executes */ - const char *zSql, /* The SQL to be executed */ - const char **pzTail, /* OUT: Next statement after the first */ - sqlite_vm **ppVm, /* OUT: The virtual machine */ - char **pzErrMsg /* OUT: Write error messages here */ -){ - Parse sParse; - - if( pzErrMsg ) *pzErrMsg = 0; - if( sqliteSafetyOn(db) ) goto exec_misuse; - if( !db->init.busy ){ - if( (db->flags & SQLITE_Initialized)==0 ){ - int rc, cnt = 1; - while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY - && db->xBusyCallback - && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){} - if( rc!=SQLITE_OK ){ - sqliteStrRealloc(pzErrMsg); - sqliteSafetyOff(db); - return rc; - } - if( pzErrMsg ){ - sqliteFree(*pzErrMsg); - *pzErrMsg = 0; - } - } - if( db->file_format<3 ){ - sqliteSafetyOff(db); - sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0); - return SQLITE_ERROR; - } - } - assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy ); - if( db->pVdbe==0 ){ db->nChange = 0; } - memset(&sParse, 0, sizeof(sParse)); - sParse.db = db; - sqliteRunParser(&sParse, zSql, pzErrMsg); - if( db->xTrace && !db->init.busy ){ - /* Trace only the statment that was compiled. - ** Make a copy of that part of the SQL string since zSQL is const - ** and we must pass a zero terminated string to the trace function - ** The copy is unnecessary if the tail pointer is pointing at the - ** beginnig or end of the SQL string. - */ - if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){ - char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql); - if( tmpSql ){ - db->xTrace(db->pTraceArg, tmpSql); - free(tmpSql); - }else{ - /* If a memory error occurred during the copy, - ** trace entire SQL string and fall through to the - ** sqlite_malloc_failed test to report the error. - */ - db->xTrace(db->pTraceArg, zSql); - } - }else{ - db->xTrace(db->pTraceArg, zSql); - } - } - if( sqlite_malloc_failed ){ - sqliteSetString(pzErrMsg, "out of memory", (char*)0); - sParse.rc = SQLITE_NOMEM; - sqliteRollbackAll(db); - sqliteResetInternalSchema(db, 0); - db->flags &= ~SQLITE_InTrans; - } - if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; - if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){ - sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), (char*)0); - } - sqliteStrRealloc(pzErrMsg); - if( sParse.rc==SQLITE_SCHEMA ){ - sqliteResetInternalSchema(db, 0); - } - assert( ppVm ); - *ppVm = (sqlite_vm*)sParse.pVdbe; - if( pzTail ) *pzTail = sParse.zTail; - if( sqliteSafetyOff(db) ) goto exec_misuse; - return sParse.rc; - -exec_misuse: - if( pzErrMsg ){ - *pzErrMsg = 0; - sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0); - sqliteStrRealloc(pzErrMsg); - } - return SQLITE_MISUSE; -} - - -/* -** The following routine destroys a virtual machine that is created by -** the sqlite_compile() routine. -** -** The integer returned is an SQLITE_ success/failure code that describes -** the result of executing the virtual machine. An error message is -** written into memory obtained from malloc and *pzErrMsg is made to -** point to that error if pzErrMsg is not NULL. The calling routine -** should use sqlite_freemem() to delete the message when it has finished -** with it. -*/ -int sqlite_finalize( - sqlite_vm *pVm, /* The virtual machine to be destroyed */ - char **pzErrMsg /* OUT: Write error messages here */ -){ - int rc = sqliteVdbeFinalize((Vdbe*)pVm, pzErrMsg); - sqliteStrRealloc(pzErrMsg); - return rc; -} - -/* -** Terminate the current execution of a virtual machine then -** reset the virtual machine back to its starting state so that it -** can be reused. Any error message resulting from the prior execution -** is written into *pzErrMsg. A success code from the prior execution -** is returned. -*/ -int sqlite_reset( - sqlite_vm *pVm, /* The virtual machine to be destroyed */ - char **pzErrMsg /* OUT: Write error messages here */ -){ - int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg); - sqliteVdbeMakeReady((Vdbe*)pVm, -1, 0); - sqliteStrRealloc(pzErrMsg); - return rc; -} - -/* -** Return a static string that describes the kind of error specified in the -** argument. -*/ -const char *sqlite_error_string(int rc){ - const char *z; - switch( rc ){ - case SQLITE_OK: z = "not an error"; break; - case SQLITE_ERROR: z = "SQL logic error or missing database"; break; - case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break; - case SQLITE_PERM: z = "access permission denied"; break; - case SQLITE_ABORT: z = "callback requested query abort"; break; - case SQLITE_BUSY: z = "database is locked"; break; - case SQLITE_LOCKED: z = "database table is locked"; break; - case SQLITE_NOMEM: z = "out of memory"; break; - case SQLITE_READONLY: z = "attempt to write a readonly database"; break; - case SQLITE_INTERRUPT: z = "interrupted"; break; - case SQLITE_IOERR: z = "disk I/O error"; break; - case SQLITE_CORRUPT: z = "database disk image is malformed"; break; - case SQLITE_NOTFOUND: z = "table or record not found"; break; - case SQLITE_FULL: z = "database is full"; break; - case SQLITE_CANTOPEN: z = "unable to open database file"; break; - case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; - case SQLITE_EMPTY: z = "table contains no data"; break; - case SQLITE_SCHEMA: z = "database schema has changed"; break; - case SQLITE_TOOBIG: z = "too much data for one table row"; break; - case SQLITE_CONSTRAINT: z = "constraint failed"; break; - case SQLITE_MISMATCH: z = "datatype mismatch"; break; - case SQLITE_MISUSE: z = "library routine called out of sequence";break; - case SQLITE_NOLFS: z = "kernel lacks large file support"; break; - case SQLITE_AUTH: z = "authorization denied"; break; - case SQLITE_FORMAT: z = "auxiliary database format error"; break; - case SQLITE_RANGE: z = "bind index out of range"; break; - case SQLITE_NOTADB: z = "file is encrypted or is not a database";break; - default: z = "unknown error"; break; - } - return z; -} - -/* -** This routine implements a busy callback that sleeps and tries -** again until a timeout value is reached. The timeout value is -** an integer number of milliseconds passed in as the first -** argument. -*/ -static int sqliteDefaultBusyCallback( - void *Timeout, /* Maximum amount of time to wait */ - const char *NotUsed, /* The name of the table that is busy */ - int count /* Number of times table has been busy */ -){ -#if SQLITE_MIN_SLEEP_MS==1 - static const char delays[] = - { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 50, 100}; - static const short int totals[] = - { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228, 287}; -# define NDELAY (sizeof(delays)/sizeof(delays[0])) - int timeout = (int)(long)Timeout; - int delay, prior; - - if( count <= NDELAY ){ - delay = delays[count-1]; - prior = totals[count-1]; - }else{ - delay = delays[NDELAY-1]; - prior = totals[NDELAY-1] + delay*(count-NDELAY-1); - } - if( prior + delay > timeout ){ - delay = timeout - prior; - if( delay<=0 ) return 0; - } - sqliteOsSleep(delay); - return 1; -#else - int timeout = (int)(long)Timeout; - if( (count+1)*1000 > timeout ){ - return 0; - } - sqliteOsSleep(1000); - return 1; -#endif -} - -/* -** This routine sets the busy callback for an Sqlite database to the -** given callback function with the given argument. -*/ -void sqlite_busy_handler( - sqlite *db, - int (*xBusy)(void*,const char*,int), - void *pArg -){ - db->xBusyCallback = xBusy; - db->pBusyArg = pArg; -} - -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK -/* -** This routine sets the progress callback for an Sqlite database to the -** given callback function with the given argument. The progress callback will -** be invoked every nOps opcodes. -*/ -void sqlite_progress_handler( - sqlite *db, - int nOps, - int (*xProgress)(void*), - void *pArg -){ - if( nOps>0 ){ - db->xProgress = xProgress; - db->nProgressOps = nOps; - db->pProgressArg = pArg; - }else{ - db->xProgress = 0; - db->nProgressOps = 0; - db->pProgressArg = 0; - } -} -#endif - - -/* -** This routine installs a default busy handler that waits for the -** specified number of milliseconds before returning 0. -*/ -void sqlite_busy_timeout(sqlite *db, int ms){ - if( ms>0 ){ - sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms); - }else{ - sqlite_busy_handler(db, 0, 0); - } -} - -/* -** Cause any pending operation to stop at its earliest opportunity. -*/ -void sqlite_interrupt(sqlite *db){ - db->flags |= SQLITE_Interrupt; -} - -/* -** Windows systems should call this routine to free memory that -** is returned in the in the errmsg parameter of sqlite_open() when -** SQLite is a DLL. For some reason, it does not work to call free() -** directly. -** -** Note that we need to call free() not sqliteFree() here, since every -** string that is exported from SQLite should have already passed through -** sqliteStrRealloc(). -*/ -void sqlite_freemem(void *p){ free(p); } - -/* -** Windows systems need functions to call to return the sqlite_version -** and sqlite_encoding strings since they are unable to access constants -** within DLLs. -*/ -const char *sqlite_libversion(void){ return sqlite_version; } -const char *sqlite_libencoding(void){ return sqlite_encoding; } - -/* -** Create new user-defined functions. The sqlite_create_function() -** routine creates a regular function and sqlite_create_aggregate() -** creates an aggregate function. -** -** Passing a NULL xFunc argument or NULL xStep and xFinalize arguments -** disables the function. Calling sqlite_create_function() with the -** same name and number of arguments as a prior call to -** sqlite_create_aggregate() disables the prior call to -** sqlite_create_aggregate(), and vice versa. -** -** If nArg is -1 it means that this function will accept any number -** of arguments, including 0. The maximum allowed value of nArg is 127. -*/ -int sqlite_create_function( - sqlite *db, /* Add the function to this database connection */ - const char *zName, /* Name of the function to add */ - int nArg, /* Number of arguments */ - void (*xFunc)(sqlite_func*,int,const char**), /* The implementation */ - void *pUserData /* User data */ -){ - FuncDef *p; - int nName; - if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1; - if( nArg<-1 || nArg>127 ) return 1; - nName = strlen(zName); - if( nName>255 ) return 1; - p = sqliteFindFunction(db, zName, nName, nArg, 1); - if( p==0 ) return 1; - p->xFunc = xFunc; - p->xStep = 0; - p->xFinalize = 0; - p->pUserData = pUserData; - return 0; -} -int sqlite_create_aggregate( - sqlite *db, /* Add the function to this database connection */ - const char *zName, /* Name of the function to add */ - int nArg, /* Number of arguments */ - void (*xStep)(sqlite_func*,int,const char**), /* The step function */ - void (*xFinalize)(sqlite_func*), /* The finalizer */ - void *pUserData /* User data */ -){ - FuncDef *p; - int nName; - if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1; - if( nArg<-1 || nArg>127 ) return 1; - nName = strlen(zName); - if( nName>255 ) return 1; - p = sqliteFindFunction(db, zName, nName, nArg, 1); - if( p==0 ) return 1; - p->xFunc = 0; - p->xStep = xStep; - p->xFinalize = xFinalize; - p->pUserData = pUserData; - return 0; -} - -/* -** Change the datatype for all functions with a given name. See the -** header comment for the prototype of this function in sqlite.h for -** additional information. -*/ -int sqlite_function_type(sqlite *db, const char *zName, int dataType){ - FuncDef *p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, strlen(zName)); - while( p ){ - p->dataType = dataType; - p = p->pNext; - } - return SQLITE_OK; -} - -/* -** Register a trace function. The pArg from the previously registered trace -** is returned. -** -** A NULL trace function means that no tracing is executes. A non-NULL -** trace is a pointer to a function that is invoked at the start of each -** sqlite_exec(). -*/ -void *sqlite_trace(sqlite *db, void (*xTrace)(void*,const char*), void *pArg){ - void *pOld = db->pTraceArg; - db->xTrace = xTrace; - db->pTraceArg = pArg; - return pOld; -} - -/*** EXPERIMENTAL *** -** -** Register a function to be invoked when a transaction comments. -** If either function returns non-zero, then the commit becomes a -** rollback. -*/ -void *sqlite_commit_hook( - sqlite *db, /* Attach the hook to this database */ - int (*xCallback)(void*), /* Function to invoke on each commit */ - void *pArg /* Argument to the function */ -){ - void *pOld = db->pCommitArg; - db->xCommitCallback = xCallback; - db->pCommitArg = pArg; - return pOld; -} - - -/* -** This routine is called to create a connection to a database BTree -** driver. If zFilename is the name of a file, then that file is -** opened and used. If zFilename is the magic name ":memory:" then -** the database is stored in memory (and is thus forgotten as soon as -** the connection is closed.) If zFilename is NULL then the database -** is for temporary use only and is deleted as soon as the connection -** is closed. -** -** A temporary database can be either a disk file (that is automatically -** deleted when the file is closed) or a set of red-black trees held in memory, -** depending on the values of the TEMP_STORE compile-time macro and the -** db->temp_store variable, according to the following chart: -** -** TEMP_STORE db->temp_store Location of temporary database -** ---------- -------------- ------------------------------ -** 0 any file -** 1 1 file -** 1 2 memory -** 1 0 file -** 2 1 file -** 2 2 memory -** 2 0 memory -** 3 any memory -*/ -int sqliteBtreeFactory( - const sqlite *db, /* Main database when opening aux otherwise 0 */ - const char *zFilename, /* Name of the file containing the BTree database */ - int omitJournal, /* if TRUE then do not journal this file */ - int nCache, /* How many pages in the page cache */ - Btree **ppBtree){ /* Pointer to new Btree object written here */ - - assert( ppBtree != 0); - -#ifndef SQLITE_OMIT_INMEMORYDB - if( zFilename==0 ){ - if (TEMP_STORE == 0) { - /* Always use file based temporary DB */ - return sqliteBtreeOpen(0, omitJournal, nCache, ppBtree); - } else if (TEMP_STORE == 1 || TEMP_STORE == 2) { - /* Switch depending on compile-time and/or runtime settings. */ - int location = db->temp_store==0 ? TEMP_STORE : db->temp_store; - - if (location == 1) { - return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree); - } else { - return sqliteRbtreeOpen(0, 0, 0, ppBtree); - } - } else { - /* Always use in-core DB */ - return sqliteRbtreeOpen(0, 0, 0, ppBtree); - } - }else if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){ - return sqliteRbtreeOpen(0, 0, 0, ppBtree); - }else -#endif - { - return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree); - } -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/main.o b/dbLifeLog/DBD-SQLite2-0.33/main.o deleted file mode 100644 index aa948577e3187491949b21d2b13bff29d6538a7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21184 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 diff --git a/dbLifeLog/DBD-SQLite2-0.33/os.c b/dbLifeLog/DBD-SQLite2-0.33/os.c deleted file mode 100644 index 1657692..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/os.c +++ /dev/null @@ -1,1845 +0,0 @@ -/* -** 2001 September 16 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code that is specific to particular operating -** systems. The purpose of this file is to provide a uniform abstraction -** on which the rest of SQLite can operate. -*/ -#include "os.h" /* Must be first to enable large file support */ -#include "sqliteInt.h" - -#if OS_UNIX -# include -# include -# include -# ifndef O_LARGEFILE -# define O_LARGEFILE 0 -# endif -# ifdef SQLITE_DISABLE_LFS -# undef O_LARGEFILE -# define O_LARGEFILE 0 -# endif -# ifndef O_NOFOLLOW -# define O_NOFOLLOW 0 -# endif -# ifndef O_BINARY -# define O_BINARY 0 -# endif -#endif - - -#if OS_WIN -# include -#endif - -#if OS_MAC -# include -# include -# include -# include -# include -# include -# include -#endif - -/* -** The DJGPP compiler environment looks mostly like Unix, but it -** lacks the fcntl() system call. So redefine fcntl() to be something -** that always succeeds. This means that locking does not occur under -** DJGPP. But its DOS - what did you expect? -*/ -#ifdef __DJGPP__ -# define fcntl(A,B,C) 0 -#endif - -/* -** Macros used to determine whether or not to use threads. The -** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for -** Posix threads and SQLITE_W32_THREADS is defined if we are -** synchronizing using Win32 threads. -*/ -#if OS_UNIX && defined(THREADSAFE) && THREADSAFE -# include -# define SQLITE_UNIX_THREADS 1 -#endif -#if OS_WIN && defined(THREADSAFE) && THREADSAFE -# define SQLITE_W32_THREADS 1 -#endif -#if OS_MAC && defined(THREADSAFE) && THREADSAFE -# include -# define SQLITE_MACOS_MULTITASKING 1 -#endif - -/* -** Macros for performance tracing. Normally turned off -*/ -#if 0 -static int last_page = 0; -__inline__ unsigned long long int hwtime(void){ - unsigned long long int x; - __asm__("rdtsc\n\t" - "mov %%edx, %%ecx\n\t" - :"=A" (x)); - return x; -} -static unsigned long long int g_start; -static unsigned int elapse; -#define TIMER_START g_start=hwtime() -#define TIMER_END elapse=hwtime()-g_start -#define SEEK(X) last_page=(X) -#define TRACE1(X) fprintf(stderr,X) -#define TRACE2(X,Y) fprintf(stderr,X,Y) -#define TRACE3(X,Y,Z) fprintf(stderr,X,Y,Z) -#define TRACE4(X,Y,Z,A) fprintf(stderr,X,Y,Z,A) -#define TRACE5(X,Y,Z,A,B) fprintf(stderr,X,Y,Z,A,B) -#else -#define TIMER_START -#define TIMER_END -#define SEEK(X) -#define TRACE1(X) -#define TRACE2(X,Y) -#define TRACE3(X,Y,Z) -#define TRACE4(X,Y,Z,A) -#define TRACE5(X,Y,Z,A,B) -#endif - - -#if OS_UNIX -/* -** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) -** section 6.5.2.2 lines 483 through 490 specify that when a process -** sets or clears a lock, that operation overrides any prior locks set -** by the same process. It does not explicitly say so, but this implies -** that it overrides locks set by the same process using a different -** file descriptor. Consider this test case: -** -** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644); -** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); -** -** Suppose ./file1 and ./file2 are really the same file (because -** one is a hard or symbolic link to the other) then if you set -** an exclusive lock on fd1, then try to get an exclusive lock -** on fd2, it works. I would have expected the second lock to -** fail since there was already a lock on the file due to fd1. -** But not so. Since both locks came from the same process, the -** second overrides the first, even though they were on different -** file descriptors opened on different file names. -** -** Bummer. If you ask me, this is broken. Badly broken. It means -** that we cannot use POSIX locks to synchronize file access among -** competing threads of the same process. POSIX locks will work fine -** to synchronize access for threads in separate processes, but not -** threads within the same process. -** -** To work around the problem, SQLite has to manage file locks internally -** on its own. Whenever a new database is opened, we have to find the -** specific inode of the database file (the inode is determined by the -** st_dev and st_ino fields of the stat structure that fstat() fills in) -** and check for locks already existing on that inode. When locks are -** created or removed, we have to look at our own internal record of the -** locks to see if another thread has previously set a lock on that same -** inode. -** -** The OsFile structure for POSIX is no longer just an integer file -** descriptor. It is now a structure that holds the integer file -** descriptor and a pointer to a structure that describes the internal -** locks on the corresponding inode. There is one locking structure -** per inode, so if the same inode is opened twice, both OsFile structures -** point to the same locking structure. The locking structure keeps -** a reference count (so we will know when to delete it) and a "cnt" -** field that tells us its internal lock status. cnt==0 means the -** file is unlocked. cnt==-1 means the file has an exclusive lock. -** cnt>0 means there are cnt shared locks on the file. -** -** Any attempt to lock or unlock a file first checks the locking -** structure. The fcntl() system call is only invoked to set a -** POSIX lock if the internal lock structure transitions between -** a locked and an unlocked state. -** -** 2004-Jan-11: -** More recent discoveries about POSIX advisory locks. (The more -** I discover, the more I realize the a POSIX advisory locks are -** an abomination.) -** -** If you close a file descriptor that points to a file that has locks, -** all locks on that file that are owned by the current process are -** released. To work around this problem, each OsFile structure contains -** a pointer to an openCnt structure. There is one openCnt structure -** per open inode, which means that multiple OsFiles can point to a single -** openCnt. When an attempt is made to close an OsFile, if there are -** other OsFiles open on the same inode that are holding locks, the call -** to close() the file descriptor is deferred until all of the locks clear. -** The openCnt structure keeps a list of file descriptors that need to -** be closed and that list is walked (and cleared) when the last lock -** clears. -** -** First, under Linux threads, because each thread has a separate -** process ID, lock operations in one thread do not override locks -** to the same file in other threads. Linux threads behave like -** separate processes in this respect. But, if you close a file -** descriptor in linux threads, all locks are cleared, even locks -** on other threads and even though the other threads have different -** process IDs. Linux threads is inconsistent in this respect. -** (I'm beginning to think that linux threads is an abomination too.) -** The consequence of this all is that the hash table for the lockInfo -** structure has to include the process id as part of its key because -** locks in different threads are treated as distinct. But the -** openCnt structure should not include the process id in its -** key because close() clears lock on all threads, not just the current -** thread. Were it not for this goofiness in linux threads, we could -** combine the lockInfo and openCnt structures into a single structure. -*/ - -/* -** An instance of the following structure serves as the key used -** to locate a particular lockInfo structure given its inode. Note -** that we have to include the process ID as part of the key. On some -** threading implementations (ex: linux), each thread has a separate -** process ID. -*/ -struct lockKey { - dev_t dev; /* Device number */ - ino_t ino; /* Inode number */ - pid_t pid; /* Process ID */ -}; - -/* -** An instance of the following structure is allocated for each open -** inode on each thread with a different process ID. (Threads have -** different process IDs on linux, but not on most other unixes.) -** -** A single inode can have multiple file descriptors, so each OsFile -** structure contains a pointer to an instance of this object and this -** object keeps a count of the number of OsFiles pointing to it. -*/ -struct lockInfo { - struct lockKey key; /* The lookup key */ - int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */ - int nRef; /* Number of pointers to this structure */ -}; - -/* -** An instance of the following structure serves as the key used -** to locate a particular openCnt structure given its inode. This -** is the same as the lockKey except that the process ID is omitted. -*/ -struct openKey { - dev_t dev; /* Device number */ - ino_t ino; /* Inode number */ -}; - -/* -** An instance of the following structure is allocated for each open -** inode. This structure keeps track of the number of locks on that -** inode. If a close is attempted against an inode that is holding -** locks, the close is deferred until all locks clear by adding the -** file descriptor to be closed to the pending list. -*/ -struct openCnt { - struct openKey key; /* The lookup key */ - int nRef; /* Number of pointers to this structure */ - int nLock; /* Number of outstanding locks */ - int nPending; /* Number of pending close() operations */ - int *aPending; /* Malloced space holding fd's awaiting a close() */ -}; - -/* -** These hash table maps inodes and process IDs into lockInfo and openCnt -** structures. Access to these hash tables must be protected by a mutex. -*/ -static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; -static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; - -/* -** Release a lockInfo structure previously allocated by findLockInfo(). -*/ -static void releaseLockInfo(struct lockInfo *pLock){ - pLock->nRef--; - if( pLock->nRef==0 ){ - sqliteHashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); - sqliteFree(pLock); - } -} - -/* -** Release a openCnt structure previously allocated by findLockInfo(). -*/ -static void releaseOpenCnt(struct openCnt *pOpen){ - pOpen->nRef--; - if( pOpen->nRef==0 ){ - sqliteHashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); - sqliteFree(pOpen->aPending); - sqliteFree(pOpen); - } -} - -/* -** Given a file descriptor, locate lockInfo and openCnt structures that -** describes that file descriptor. Create a new ones if necessary. The -** return values might be unset if an error occurs. -** -** Return the number of errors. -*/ -int findLockInfo( - int fd, /* The file descriptor used in the key */ - struct lockInfo **ppLock, /* Return the lockInfo structure here */ - struct openCnt **ppOpen /* Return the openCnt structure here */ -){ - int rc; - struct lockKey key1; - struct openKey key2; - struct stat statbuf; - struct lockInfo *pLock; - struct openCnt *pOpen; - rc = fstat(fd, &statbuf); - if( rc!=0 ) return 1; - memset(&key1, 0, sizeof(key1)); - key1.dev = statbuf.st_dev; - key1.ino = statbuf.st_ino; - key1.pid = getpid(); - memset(&key2, 0, sizeof(key2)); - key2.dev = statbuf.st_dev; - key2.ino = statbuf.st_ino; - pLock = (struct lockInfo*)sqliteHashFind(&lockHash, &key1, sizeof(key1)); - if( pLock==0 ){ - struct lockInfo *pOld; - pLock = sqliteMallocRaw( sizeof(*pLock) ); - if( pLock==0 ) return 1; - pLock->key = key1; - pLock->nRef = 1; - pLock->cnt = 0; - pOld = sqliteHashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); - if( pOld!=0 ){ - assert( pOld==pLock ); - sqliteFree(pLock); - return 1; - } - }else{ - pLock->nRef++; - } - *ppLock = pLock; - pOpen = (struct openCnt*)sqliteHashFind(&openHash, &key2, sizeof(key2)); - if( pOpen==0 ){ - struct openCnt *pOld; - pOpen = sqliteMallocRaw( sizeof(*pOpen) ); - if( pOpen==0 ){ - releaseLockInfo(pLock); - return 1; - } - pOpen->key = key2; - pOpen->nRef = 1; - pOpen->nLock = 0; - pOpen->nPending = 0; - pOpen->aPending = 0; - pOld = sqliteHashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); - if( pOld!=0 ){ - assert( pOld==pOpen ); - sqliteFree(pOpen); - releaseLockInfo(pLock); - return 1; - } - }else{ - pOpen->nRef++; - } - *ppOpen = pOpen; - return 0; -} - -#endif /** POSIX advisory lock work-around **/ - -/* -** If we compile with the SQLITE_TEST macro set, then the following block -** of code will give us the ability to simulate a disk I/O error. This -** is used for testing the I/O recovery logic. -*/ -#ifdef SQLITE_TEST -int sqlite_io_error_pending = 0; -#define SimulateIOError(A) \ - if( sqlite_io_error_pending ) \ - if( sqlite_io_error_pending-- == 1 ){ local_ioerr(); return A; } -static void local_ioerr(){ - sqlite_io_error_pending = 0; /* Really just a place to set a breakpoint */ -} -#else -#define SimulateIOError(A) -#endif - -/* -** When testing, keep a count of the number of open files. -*/ -#ifdef SQLITE_TEST -int sqlite_open_file_count = 0; -#define OpenCounter(X) sqlite_open_file_count+=(X) -#else -#define OpenCounter(X) -#endif - - -/* -** Delete the named file -*/ -int sqliteOsDelete(const char *zFilename){ -#if OS_UNIX - unlink(zFilename); -#endif -#if OS_WIN - DeleteFile(zFilename); -#endif -#if OS_MAC - unlink(zFilename); -#endif - return SQLITE_OK; -} - -/* -** Return TRUE if the named file exists. -*/ -int sqliteOsFileExists(const char *zFilename){ -#if OS_UNIX - return access(zFilename, 0)==0; -#endif -#if OS_WIN - return GetFileAttributes(zFilename) != 0xffffffff; -#endif -#if OS_MAC - return access(zFilename, 0)==0; -#endif -} - - -#if 0 /* NOT USED */ -/* -** Change the name of an existing file. -*/ -int sqliteOsFileRename(const char *zOldName, const char *zNewName){ -#if OS_UNIX - if( link(zOldName, zNewName) ){ - return SQLITE_ERROR; - } - unlink(zOldName); - return SQLITE_OK; -#endif -#if OS_WIN - if( !MoveFile(zOldName, zNewName) ){ - return SQLITE_ERROR; - } - return SQLITE_OK; -#endif -#if OS_MAC - /**** FIX ME ***/ - return SQLITE_ERROR; -#endif -} -#endif /* NOT USED */ - -/* -** Attempt to open a file for both reading and writing. If that -** fails, try opening it read-only. If the file does not exist, -** try to create it. -** -** On success, a handle for the open file is written to *id -** and *pReadonly is set to 0 if the file was opened for reading and -** writing or 1 if the file was opened read-only. The function returns -** SQLITE_OK. -** -** On failure, the function returns SQLITE_CANTOPEN and leaves -** *id and *pReadonly unchanged. -*/ -int sqliteOsOpenReadWrite( - const char *zFilename, - OsFile *id, - int *pReadonly -){ -#if OS_UNIX - int rc; - id->dirfd = -1; - id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644); - if( id->fd<0 ){ -#ifdef EISDIR - if( errno==EISDIR ){ - return SQLITE_CANTOPEN; - } -#endif - id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); - if( id->fd<0 ){ - return SQLITE_CANTOPEN; - } - *pReadonly = 1; - }else{ - *pReadonly = 0; - } - sqliteOsEnterMutex(); - rc = findLockInfo(id->fd, &id->pLock, &id->pOpen); - sqliteOsLeaveMutex(); - if( rc ){ - close(id->fd); - return SQLITE_NOMEM; - } - id->locked = 0; - TRACE3("OPEN %-3d %s\n", id->fd, zFilename); - OpenCounter(+1); - return SQLITE_OK; -#endif -#if OS_WIN - HANDLE h = CreateFile(zFilename, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); - if( h==INVALID_HANDLE_VALUE ){ - h = CreateFile(zFilename, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); - if( h==INVALID_HANDLE_VALUE ){ - return SQLITE_CANTOPEN; - } - *pReadonly = 1; - }else{ - *pReadonly = 0; - } - id->h = h; - id->locked = 0; - OpenCounter(+1); - return SQLITE_OK; -#endif -#if OS_MAC - FSSpec fsSpec; -# ifdef _LARGE_FILE - HFSUniStr255 dfName; - FSRef fsRef; - if( __path2fss(zFilename, &fsSpec) != noErr ){ - if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) - return SQLITE_CANTOPEN; - } - if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) - return SQLITE_CANTOPEN; - FSGetDataForkName(&dfName); - if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdWrShPerm, &(id->refNum)) != noErr ){ - if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdWrPerm, &(id->refNum)) != noErr ){ - if (FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; - else - *pReadonly = 1; - } else - *pReadonly = 0; - } else - *pReadonly = 0; -# else - __path2fss(zFilename, &fsSpec); - if( !sqliteOsFileExists(zFilename) ){ - if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) - return SQLITE_CANTOPEN; - } - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){ - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){ - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; - else - *pReadonly = 1; - } else - *pReadonly = 0; - } else - *pReadonly = 0; -# endif - if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){ - id->refNumRF = -1; - } - id->locked = 0; - id->delOnClose = 0; - OpenCounter(+1); - return SQLITE_OK; -#endif -} - - -/* -** Attempt to open a new file for exclusive access by this process. -** The file will be opened for both reading and writing. To avoid -** a potential security problem, we do not allow the file to have -** previously existed. Nor do we allow the file to be a symbolic -** link. -** -** If delFlag is true, then make arrangements to automatically delete -** the file when it is closed. -** -** On success, write the file handle into *id and return SQLITE_OK. -** -** On failure, return SQLITE_CANTOPEN. -*/ -int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ -#if OS_UNIX - int rc; - if( access(zFilename, 0)==0 ){ - return SQLITE_CANTOPEN; - } - id->dirfd = -1; - id->fd = open(zFilename, - O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600); - if( id->fd<0 ){ - return SQLITE_CANTOPEN; - } - sqliteOsEnterMutex(); - rc = findLockInfo(id->fd, &id->pLock, &id->pOpen); - sqliteOsLeaveMutex(); - if( rc ){ - close(id->fd); - unlink(zFilename); - return SQLITE_NOMEM; - } - id->locked = 0; - if( delFlag ){ - unlink(zFilename); - } - TRACE3("OPEN-EX %-3d %s\n", id->fd, zFilename); - OpenCounter(+1); - return SQLITE_OK; -#endif -#if OS_WIN - HANDLE h; - int fileflags; - if( delFlag ){ - fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS - | FILE_FLAG_DELETE_ON_CLOSE; - }else{ - fileflags = FILE_FLAG_RANDOM_ACCESS; - } - h = CreateFile(zFilename, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - fileflags, - NULL - ); - if( h==INVALID_HANDLE_VALUE ){ - return SQLITE_CANTOPEN; - } - id->h = h; - id->locked = 0; - OpenCounter(+1); - return SQLITE_OK; -#endif -#if OS_MAC - FSSpec fsSpec; -# ifdef _LARGE_FILE - HFSUniStr255 dfName; - FSRef fsRef; - __path2fss(zFilename, &fsSpec); - if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) - return SQLITE_CANTOPEN; - if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) - return SQLITE_CANTOPEN; - FSGetDataForkName(&dfName); - if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdWrPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; -# else - __path2fss(zFilename, &fsSpec); - if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) - return SQLITE_CANTOPEN; - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; -# endif - id->refNumRF = -1; - id->locked = 0; - id->delOnClose = delFlag; - if (delFlag) - id->pathToDel = sqliteOsFullPathname(zFilename); - OpenCounter(+1); - return SQLITE_OK; -#endif -} - -/* -** Attempt to open a new file for read-only access. -** -** On success, write the file handle into *id and return SQLITE_OK. -** -** On failure, return SQLITE_CANTOPEN. -*/ -int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){ -#if OS_UNIX - int rc; - id->dirfd = -1; - id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); - if( id->fd<0 ){ - return SQLITE_CANTOPEN; - } - sqliteOsEnterMutex(); - rc = findLockInfo(id->fd, &id->pLock, &id->pOpen); - sqliteOsLeaveMutex(); - if( rc ){ - close(id->fd); - return SQLITE_NOMEM; - } - id->locked = 0; - TRACE3("OPEN-RO %-3d %s\n", id->fd, zFilename); - OpenCounter(+1); - return SQLITE_OK; -#endif -#if OS_WIN - HANDLE h = CreateFile(zFilename, - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); - if( h==INVALID_HANDLE_VALUE ){ - return SQLITE_CANTOPEN; - } - id->h = h; - id->locked = 0; - OpenCounter(+1); - return SQLITE_OK; -#endif -#if OS_MAC - FSSpec fsSpec; -# ifdef _LARGE_FILE - HFSUniStr255 dfName; - FSRef fsRef; - if( __path2fss(zFilename, &fsSpec) != noErr ) - return SQLITE_CANTOPEN; - if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) - return SQLITE_CANTOPEN; - FSGetDataForkName(&dfName); - if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; -# else - __path2fss(zFilename, &fsSpec); - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; -# endif - if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){ - id->refNumRF = -1; - } - id->locked = 0; - id->delOnClose = 0; - OpenCounter(+1); - return SQLITE_OK; -#endif -} - -/* -** Attempt to open a file descriptor for the directory that contains a -** file. This file descriptor can be used to fsync() the directory -** in order to make sure the creation of a new file is actually written -** to disk. -** -** This routine is only meaningful for Unix. It is a no-op under -** windows since windows does not support hard links. -** -** On success, a handle for a previously open file is at *id is -** updated with the new directory file descriptor and SQLITE_OK is -** returned. -** -** On failure, the function returns SQLITE_CANTOPEN and leaves -** *id unchanged. -*/ -int sqliteOsOpenDirectory( - const char *zDirname, - OsFile *id -){ -#if OS_UNIX - if( id->fd<0 ){ - /* Do not open the directory if the corresponding file is not already - ** open. */ - return SQLITE_CANTOPEN; - } - assert( id->dirfd<0 ); - id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644); - if( id->dirfd<0 ){ - return SQLITE_CANTOPEN; - } - TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname); -#endif - return SQLITE_OK; -} - -/* -** If the following global variable points to a string which is the -** name of a directory, then that directory will be used to store -** temporary files. -*/ -const char *sqlite_temp_directory = 0; - -/* -** Create a temporary file name in zBuf. zBuf must be big enough to -** hold at least SQLITE_TEMPNAME_SIZE characters. -*/ -int sqliteOsTempFileName(char *zBuf){ -#if OS_UNIX - static const char *azDirs[] = { - 0, - "/var/tmp", - "/usr/tmp", - "/tmp", - ".", - }; - static unsigned char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i, j; - struct stat buf; - const char *zDir = "."; - azDirs[0] = sqlite_temp_directory; - for(i=0; i0 && zTempPath[i-1]=='\\'; i--){} - zTempPath[i] = 0; - zDir = zTempPath; - }else{ - zDir = sqlite_temp_directory; - } - for(;;){ - sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zDir); - j = strlen(zBuf); - sqliteRandomness(15, &zBuf[j]); - for(i=0; i<15; i++, j++){ - zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; - } - zBuf[j] = 0; - if( !sqliteOsFileExists(zBuf) ) break; - } -#endif -#if OS_MAC - static char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i, j; - char *zDir; - char zTempPath[SQLITE_TEMPNAME_SIZE]; - char zdirName[32]; - CInfoPBRec infoRec; - Str31 dirName; - memset(&infoRec, 0, sizeof(infoRec)); - memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE); - if( sqlite_temp_directory!=0 ){ - zDir = sqlite_temp_directory; - }else if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, - &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){ - infoRec.dirInfo.ioNamePtr = dirName; - do{ - infoRec.dirInfo.ioFDirIndex = -1; - infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID; - if( PBGetCatInfoSync(&infoRec) == noErr ){ - CopyPascalStringToC(dirName, zdirName); - i = strlen(zdirName); - memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath)); - strcpy(zTempPath, zdirName); - zTempPath[i] = ':'; - }else{ - *zTempPath = 0; - break; - } - } while( infoRec.dirInfo.ioDrDirID != fsRtDirID ); - zDir = zTempPath; - } - if( zDir[0]==0 ){ - getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24); - zDir = zTempPath; - } - for(;;){ - sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zDir); - j = strlen(zBuf); - sqliteRandomness(15, &zBuf[j]); - for(i=0; i<15; i++, j++){ - zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; - } - zBuf[j] = 0; - if( !sqliteOsFileExists(zBuf) ) break; - } -#endif - return SQLITE_OK; -} - -/* -** Close a file. -*/ -int sqliteOsClose(OsFile *id){ -#if OS_UNIX - sqliteOsUnlock(id); - if( id->dirfd>=0 ) close(id->dirfd); - id->dirfd = -1; - sqliteOsEnterMutex(); - if( id->pOpen->nLock ){ - /* If there are outstanding locks, do not actually close the file just - ** yet because that would clear those locks. Instead, add the file - ** descriptor to pOpen->aPending. It will be automatically closed when - ** the last lock is cleared. - */ - int *aNew; - struct openCnt *pOpen = id->pOpen; - pOpen->nPending++; - aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) ); - if( aNew==0 ){ - /* If a malloc fails, just leak the file descriptor */ - }else{ - pOpen->aPending = aNew; - pOpen->aPending[pOpen->nPending-1] = id->fd; - } - }else{ - /* There are no outstanding locks so we can close the file immediately */ - close(id->fd); - } - releaseLockInfo(id->pLock); - releaseOpenCnt(id->pOpen); - sqliteOsLeaveMutex(); - TRACE2("CLOSE %-3d\n", id->fd); - OpenCounter(-1); - return SQLITE_OK; -#endif -#if OS_WIN - CloseHandle(id->h); - OpenCounter(-1); - return SQLITE_OK; -#endif -#if OS_MAC - if( id->refNumRF!=-1 ) - FSClose(id->refNumRF); -# ifdef _LARGE_FILE - FSCloseFork(id->refNum); -# else - FSClose(id->refNum); -# endif - if( id->delOnClose ){ - unlink(id->pathToDel); - sqliteFree(id->pathToDel); - } - OpenCounter(-1); - return SQLITE_OK; -#endif -} - -/* -** Read data from a file into a buffer. Return SQLITE_OK if all -** bytes were read successfully and SQLITE_IOERR if anything goes -** wrong. -*/ -int sqliteOsRead(OsFile *id, void *pBuf, int amt){ -#if OS_UNIX - int got; - SimulateIOError(SQLITE_IOERR); - TIMER_START; - got = read(id->fd, pBuf, amt); - TIMER_END; - TRACE4("READ %-3d %7d %d\n", id->fd, last_page, elapse); - SEEK(0); - /* if( got<0 ) got = 0; */ - if( got==amt ){ - return SQLITE_OK; - }else{ - return SQLITE_IOERR; - } -#endif -#if OS_WIN - DWORD got; - SimulateIOError(SQLITE_IOERR); - TRACE2("READ %d\n", last_page); - if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ - got = 0; - } - if( got==(DWORD)amt ){ - return SQLITE_OK; - }else{ - return SQLITE_IOERR; - } -#endif -#if OS_MAC - int got; - SimulateIOError(SQLITE_IOERR); - TRACE2("READ %d\n", last_page); -# ifdef _LARGE_FILE - FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got); -# else - got = amt; - FSRead(id->refNum, &got, pBuf); -# endif - if( got==amt ){ - return SQLITE_OK; - }else{ - return SQLITE_IOERR; - } -#endif -} - -/* -** Write data from a buffer into a file. Return SQLITE_OK on success -** or some other error code on failure. -*/ -int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){ -#if OS_UNIX - int wrote = 0; - SimulateIOError(SQLITE_IOERR); - TIMER_START; - while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){ - amt -= wrote; - pBuf = &((char*)pBuf)[wrote]; - } - TIMER_END; - TRACE4("WRITE %-3d %7d %d\n", id->fd, last_page, elapse); - SEEK(0); - if( amt>0 ){ - return SQLITE_FULL; - } - return SQLITE_OK; -#endif -#if OS_WIN - int rc; - DWORD wrote; - SimulateIOError(SQLITE_IOERR); - TRACE2("WRITE %d\n", last_page); - while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ - amt -= wrote; - pBuf = &((char*)pBuf)[wrote]; - } - if( !rc || amt>(int)wrote ){ - return SQLITE_FULL; - } - return SQLITE_OK; -#endif -#if OS_MAC - OSErr oserr; - int wrote = 0; - SimulateIOError(SQLITE_IOERR); - TRACE2("WRITE %d\n", last_page); - while( amt>0 ){ -# ifdef _LARGE_FILE - oserr = FSWriteFork(id->refNum, fsAtMark, 0, - (ByteCount)amt, pBuf, (ByteCount*)&wrote); -# else - wrote = amt; - oserr = FSWrite(id->refNum, &wrote, pBuf); -# endif - if( wrote == 0 || oserr != noErr) - break; - amt -= wrote; - pBuf = &((char*)pBuf)[wrote]; - } - if( oserr != noErr || amt>wrote ){ - return SQLITE_FULL; - } - return SQLITE_OK; -#endif -} - -/* -** Move the read/write pointer in a file. -*/ -int sqliteOsSeek(OsFile *id, off_t offset){ - SEEK(offset/1024 + 1); -#if OS_UNIX - lseek(id->fd, offset, SEEK_SET); - return SQLITE_OK; -#endif -#if OS_WIN - { - LONG upperBits = offset>>32; - LONG lowerBits = offset & 0xffffffff; - DWORD rc; - rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN); - /* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */ - } - return SQLITE_OK; -#endif -#if OS_MAC - { - off_t curSize; - if( sqliteOsFileSize(id, &curSize) != SQLITE_OK ){ - return SQLITE_IOERR; - } - if( offset >= curSize ){ - if( sqliteOsTruncate(id, offset+1) != SQLITE_OK ){ - return SQLITE_IOERR; - } - } -# ifdef _LARGE_FILE - if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){ -# else - if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){ -# endif - return SQLITE_IOERR; - }else{ - return SQLITE_OK; - } - } -#endif -} - -/* -** Make sure all writes to a particular file are committed to disk. -** -** Under Unix, also make sure that the directory entry for the file -** has been created by fsync-ing the directory that contains the file. -** If we do not do this and we encounter a power failure, the directory -** entry for the journal might not exist after we reboot. The next -** SQLite to access the file will not know that the journal exists (because -** the directory entry for the journal was never created) and the transaction -** will not roll back - possibly leading to database corruption. -*/ -int sqliteOsSync(OsFile *id){ -#if OS_UNIX - SimulateIOError(SQLITE_IOERR); - TRACE2("SYNC %-3d\n", id->fd); - if( fsync(id->fd) ){ - return SQLITE_IOERR; - }else{ - if( id->dirfd>=0 ){ - TRACE2("DIRSYNC %-3d\n", id->dirfd); - fsync(id->dirfd); - close(id->dirfd); /* Only need to sync once, so close the directory */ - id->dirfd = -1; /* when we are done. */ - } - return SQLITE_OK; - } -#endif -#if OS_WIN - if( FlushFileBuffers(id->h) ){ - return SQLITE_OK; - }else{ - return SQLITE_IOERR; - } -#endif -#if OS_MAC -# ifdef _LARGE_FILE - if( FSFlushFork(id->refNum) != noErr ){ -# else - ParamBlockRec params; - memset(¶ms, 0, sizeof(ParamBlockRec)); - params.ioParam.ioRefNum = id->refNum; - if( PBFlushFileSync(¶ms) != noErr ){ -# endif - return SQLITE_IOERR; - }else{ - return SQLITE_OK; - } -#endif -} - -/* -** Truncate an open file to a specified size -*/ -int sqliteOsTruncate(OsFile *id, off_t nByte){ - SimulateIOError(SQLITE_IOERR); -#if OS_UNIX - return ftruncate(id->fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; -#endif -#if OS_WIN - { - LONG upperBits = nByte>>32; - SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); - SetEndOfFile(id->h); - } - return SQLITE_OK; -#endif -#if OS_MAC -# ifdef _LARGE_FILE - if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){ -# else - if( SetEOF(id->refNum, nByte) != noErr ){ -# endif - return SQLITE_IOERR; - }else{ - return SQLITE_OK; - } -#endif -} - -/* -** Determine the current size of a file in bytes -*/ -int sqliteOsFileSize(OsFile *id, off_t *pSize){ -#if OS_UNIX - struct stat buf; - SimulateIOError(SQLITE_IOERR); - if( fstat(id->fd, &buf)!=0 ){ - return SQLITE_IOERR; - } - *pSize = buf.st_size; - return SQLITE_OK; -#endif -#if OS_WIN - DWORD upperBits, lowerBits; - SimulateIOError(SQLITE_IOERR); - lowerBits = GetFileSize(id->h, &upperBits); - *pSize = (((off_t)upperBits)<<32) + lowerBits; - return SQLITE_OK; -#endif -#if OS_MAC -# ifdef _LARGE_FILE - if( FSGetForkSize(id->refNum, pSize) != noErr){ -# else - if( GetEOF(id->refNum, pSize) != noErr ){ -# endif - return SQLITE_IOERR; - }else{ - return SQLITE_OK; - } -#endif -} - -#if OS_WIN -/* -** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. -** Return false (zero) for Win95, Win98, or WinME. -** -** Here is an interesting observation: Win95, Win98, and WinME lack -** the LockFileEx() API. But we can still statically link against that -** API as long as we don't call it win running Win95/98/ME. A call to -** this routine is used to determine if the host is Win95/98/ME or -** WinNT/2K/XP so that we will know whether or not we can safely call -** the LockFileEx() API. -*/ -int isNT(void){ - static int osType = 0; /* 0=unknown 1=win95 2=winNT */ - if( osType==0 ){ - OSVERSIONINFO sInfo; - sInfo.dwOSVersionInfoSize = sizeof(sInfo); - GetVersionEx(&sInfo); - osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; - } - return osType==2; -} -#endif - -/* -** Windows file locking notes: [similar issues apply to MacOS] -** -** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because -** those functions are not available. So we use only LockFile() and -** UnlockFile(). -** -** LockFile() prevents not just writing but also reading by other processes. -** (This is a design error on the part of Windows, but there is nothing -** we can do about that.) So the region used for locking is at the -** end of the file where it is unlikely to ever interfere with an -** actual read attempt. -** -** A database read lock is obtained by locking a single randomly-chosen -** byte out of a specific range of bytes. The lock byte is obtained at -** random so two separate readers can probably access the file at the -** same time, unless they are unlucky and choose the same lock byte. -** A database write lock is obtained by locking all bytes in the range. -** There can only be one writer. -** -** A lock is obtained on the first byte of the lock range before acquiring -** either a read lock or a write lock. This prevents two processes from -** attempting to get a lock at a same time. The semantics of -** sqliteOsReadLock() require that if there is already a write lock, that -** lock is converted into a read lock atomically. The lock on the first -** byte allows us to drop the old write lock and get the read lock without -** another process jumping into the middle and messing us up. The same -** argument applies to sqliteOsWriteLock(). -** -** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, -** which means we can use reader/writer locks. When reader writer locks -** are used, the lock is placed on the same range of bytes that is used -** for probabilistic locking in Win95/98/ME. Hence, the locking scheme -** will support two or more Win95 readers or two or more WinNT readers. -** But a single Win95 reader will lock out all WinNT readers and a single -** WinNT reader will lock out all other Win95 readers. -** -** Note: On MacOS we use the resource fork for locking. -** -** The following #defines specify the range of bytes used for locking. -** N_LOCKBYTE is the number of bytes available for doing the locking. -** The first byte used to hold the lock while the lock is changing does -** not count toward this number. FIRST_LOCKBYTE is the address of -** the first byte in the range of bytes used for locking. -*/ -#define N_LOCKBYTE 10239 -#if OS_MAC -# define FIRST_LOCKBYTE (0x000fffff - N_LOCKBYTE) -#else -# define FIRST_LOCKBYTE (0xffffffff - N_LOCKBYTE) -#endif - -/* -** Change the status of the lock on the file "id" to be a readlock. -** If the file was write locked, then this reduces the lock to a read. -** If the file was read locked, then this acquires a new read lock. -** -** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this -** library was compiled with large file support (LFS) but LFS is not -** available on the host, then an SQLITE_NOLFS is returned. -*/ -int sqliteOsReadLock(OsFile *id){ -#if OS_UNIX - int rc; - sqliteOsEnterMutex(); - if( id->pLock->cnt>0 ){ - if( !id->locked ){ - id->pLock->cnt++; - id->locked = 1; - id->pOpen->nLock++; - } - rc = SQLITE_OK; - }else if( id->locked || id->pLock->cnt==0 ){ - struct flock lock; - int s; - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = lock.l_len = 0L; - s = fcntl(id->fd, F_SETLK, &lock); - if( s!=0 ){ - rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; - }else{ - rc = SQLITE_OK; - if( !id->locked ){ - id->pOpen->nLock++; - id->locked = 1; - } - id->pLock->cnt = 1; - } - }else{ - rc = SQLITE_BUSY; - } - sqliteOsLeaveMutex(); - return rc; -#endif -#if OS_WIN - int rc; - if( id->locked>0 ){ - rc = SQLITE_OK; - }else{ - int lk; - int res; - int cnt = 100; - sqliteRandomness(sizeof(lk), &lk); - lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1; - while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){ - Sleep(1); - } - if( res ){ - UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0); - if( isNT() ){ - OVERLAPPED ovlp; - ovlp.Offset = FIRST_LOCKBYTE+1; - ovlp.OffsetHigh = 0; - ovlp.hEvent = 0; - res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, - 0, N_LOCKBYTE, 0, &ovlp); - }else{ - res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0); - } - UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0); - } - if( res ){ - id->locked = lk; - rc = SQLITE_OK; - }else{ - rc = SQLITE_BUSY; - } - } - return rc; -#endif -#if OS_MAC - int rc; - if( id->locked>0 || id->refNumRF == -1 ){ - rc = SQLITE_OK; - }else{ - int lk; - OSErr res; - int cnt = 5; - ParamBlockRec params; - sqliteRandomness(sizeof(lk), &lk); - lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1; - memset(¶ms, 0, sizeof(params)); - params.ioParam.ioRefNum = id->refNumRF; - params.ioParam.ioPosMode = fsFromStart; - params.ioParam.ioPosOffset = FIRST_LOCKBYTE; - params.ioParam.ioReqCount = 1; - while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){ - UInt32 finalTicks; - Delay(1, &finalTicks); /* 1/60 sec */ - } - if( res == noErr ){ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; - params.ioParam.ioReqCount = N_LOCKBYTE; - PBUnlockRangeSync(¶ms); - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk; - params.ioParam.ioReqCount = 1; - res = PBLockRangeSync(¶ms); - params.ioParam.ioPosOffset = FIRST_LOCKBYTE; - params.ioParam.ioReqCount = 1; - PBUnlockRangeSync(¶ms); - } - if( res == noErr ){ - id->locked = lk; - rc = SQLITE_OK; - }else{ - rc = SQLITE_BUSY; - } - } - return rc; -#endif -} - -/* -** Change the lock status to be an exclusive or write lock. Return -** SQLITE_OK on success and SQLITE_BUSY on a failure. If this -** library was compiled with large file support (LFS) but LFS is not -** available on the host, then an SQLITE_NOLFS is returned. -*/ -int sqliteOsWriteLock(OsFile *id){ -#if OS_UNIX - int rc; - sqliteOsEnterMutex(); - if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){ - struct flock lock; - int s; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = lock.l_len = 0L; - s = fcntl(id->fd, F_SETLK, &lock); - if( s!=0 ){ - rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; - }else{ - rc = SQLITE_OK; - if( !id->locked ){ - id->pOpen->nLock++; - id->locked = 1; - } - id->pLock->cnt = -1; - } - }else{ - rc = SQLITE_BUSY; - } - sqliteOsLeaveMutex(); - return rc; -#endif -#if OS_WIN - int rc; - if( id->locked<0 ){ - rc = SQLITE_OK; - }else{ - int res; - int cnt = 100; - while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){ - Sleep(1); - } - if( res ){ - if( id->locked>0 ){ - if( isNT() ){ - UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0); - }else{ - res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0); - } - } - if( res ){ - res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0); - }else{ - res = 0; - } - UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0); - } - if( res ){ - id->locked = -1; - rc = SQLITE_OK; - }else{ - rc = SQLITE_BUSY; - } - } - return rc; -#endif -#if OS_MAC - int rc; - if( id->locked<0 || id->refNumRF == -1 ){ - rc = SQLITE_OK; - }else{ - OSErr res; - int cnt = 5; - ParamBlockRec params; - memset(¶ms, 0, sizeof(params)); - params.ioParam.ioRefNum = id->refNumRF; - params.ioParam.ioPosMode = fsFromStart; - params.ioParam.ioPosOffset = FIRST_LOCKBYTE; - params.ioParam.ioReqCount = 1; - while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){ - UInt32 finalTicks; - Delay(1, &finalTicks); /* 1/60 sec */ - } - if( res == noErr ){ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked; - params.ioParam.ioReqCount = 1; - if( id->locked==0 - || PBUnlockRangeSync(¶ms)==noErr ){ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; - params.ioParam.ioReqCount = N_LOCKBYTE; - res = PBLockRangeSync(¶ms); - }else{ - res = afpRangeNotLocked; - } - params.ioParam.ioPosOffset = FIRST_LOCKBYTE; - params.ioParam.ioReqCount = 1; - PBUnlockRangeSync(¶ms); - } - if( res == noErr ){ - id->locked = -1; - rc = SQLITE_OK; - }else{ - rc = SQLITE_BUSY; - } - } - return rc; -#endif -} - -/* -** Unlock the given file descriptor. If the file descriptor was -** not previously locked, then this routine is a no-op. If this -** library was compiled with large file support (LFS) but LFS is not -** available on the host, then an SQLITE_NOLFS is returned. -*/ -int sqliteOsUnlock(OsFile *id){ -#if OS_UNIX - int rc; - if( !id->locked ) return SQLITE_OK; - sqliteOsEnterMutex(); - assert( id->pLock->cnt!=0 ); - if( id->pLock->cnt>1 ){ - id->pLock->cnt--; - rc = SQLITE_OK; - }else{ - struct flock lock; - int s; - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = lock.l_len = 0L; - s = fcntl(id->fd, F_SETLK, &lock); - if( s!=0 ){ - rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; - }else{ - rc = SQLITE_OK; - id->pLock->cnt = 0; - } - } - if( rc==SQLITE_OK ){ - /* Decrement the count of locks against this same file. When the - ** count reaches zero, close any other file descriptors whose close - ** was deferred because of outstanding locks. - */ - struct openCnt *pOpen = id->pOpen; - pOpen->nLock--; - assert( pOpen->nLock>=0 ); - if( pOpen->nLock==0 && pOpen->nPending>0 ){ - int i; - for(i=0; inPending; i++){ - close(pOpen->aPending[i]); - } - sqliteFree(pOpen->aPending); - pOpen->nPending = 0; - pOpen->aPending = 0; - } - } - sqliteOsLeaveMutex(); - id->locked = 0; - return rc; -#endif -#if OS_WIN - int rc; - if( id->locked==0 ){ - rc = SQLITE_OK; - }else if( isNT() || id->locked<0 ){ - UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0); - rc = SQLITE_OK; - id->locked = 0; - }else{ - UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0); - rc = SQLITE_OK; - id->locked = 0; - } - return rc; -#endif -#if OS_MAC - int rc; - ParamBlockRec params; - memset(¶ms, 0, sizeof(params)); - params.ioParam.ioRefNum = id->refNumRF; - params.ioParam.ioPosMode = fsFromStart; - if( id->locked==0 || id->refNumRF == -1 ){ - rc = SQLITE_OK; - }else if( id->locked<0 ){ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; - params.ioParam.ioReqCount = N_LOCKBYTE; - PBUnlockRangeSync(¶ms); - rc = SQLITE_OK; - id->locked = 0; - }else{ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked; - params.ioParam.ioReqCount = 1; - PBUnlockRangeSync(¶ms); - rc = SQLITE_OK; - id->locked = 0; - } - return rc; -#endif -} - -/* -** Get information to seed the random number generator. The seed -** is written into the buffer zBuf[256]. The calling function must -** supply a sufficiently large buffer. -*/ -int sqliteOsRandomSeed(char *zBuf){ - /* We have to initialize zBuf to prevent valgrind from reporting - ** errors. The reports issued by valgrind are incorrect - we would - ** prefer that the randomness be increased by making use of the - ** uninitialized space in zBuf - but valgrind errors tend to worry - ** some users. Rather than argue, it seems easier just to initialize - ** the whole array and silence valgrind, even if that means less randomness - ** in the random seed. - ** - ** When testing, initializing zBuf[] to zero is all we do. That means - ** that we always use the same random number sequence.* This makes the - ** tests repeatable. - */ - memset(zBuf, 0, 256); -#if OS_UNIX && !defined(SQLITE_TEST) - { - int pid; - time((time_t*)zBuf); - pid = getpid(); - memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); - } -#endif -#if OS_WIN && !defined(SQLITE_TEST) - GetSystemTime((LPSYSTEMTIME)zBuf); -#endif -#if OS_MAC - { - int pid; - Microseconds((UnsignedWide*)zBuf); - pid = getpid(); - memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid)); - } -#endif - return SQLITE_OK; -} - -/* -** Sleep for a little while. Return the amount of time slept. -*/ -int sqliteOsSleep(int ms){ -#if OS_UNIX -#if defined(HAVE_USLEEP) && HAVE_USLEEP - usleep(ms*1000); - return ms; -#else - sleep((ms+999)/1000); - return 1000*((ms+999)/1000); -#endif -#endif -#if OS_WIN - Sleep(ms); - return ms; -#endif -#if OS_MAC - UInt32 finalTicks; - UInt32 ticks = (((UInt32)ms+16)*3)/50; /* 1/60 sec per tick */ - Delay(ticks, &finalTicks); - return (int)((ticks*50)/3); -#endif -} - -/* -** Static variables used for thread synchronization -*/ -static int inMutex = 0; -#ifdef SQLITE_UNIX_THREADS - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -#endif -#ifdef SQLITE_W32_THREADS - static CRITICAL_SECTION cs; -#endif -#ifdef SQLITE_MACOS_MULTITASKING - static MPCriticalRegionID criticalRegion; -#endif - -/* -** The following pair of routine implement mutual exclusion for -** multi-threaded processes. Only a single thread is allowed to -** executed code that is surrounded by EnterMutex() and LeaveMutex(). -** -** SQLite uses only a single Mutex. There is not much critical -** code and what little there is executes quickly and without blocking. -*/ -void sqliteOsEnterMutex(){ -#ifdef SQLITE_UNIX_THREADS - pthread_mutex_lock(&mutex); -#endif -#ifdef SQLITE_W32_THREADS - static int isInit = 0; - while( !isInit ){ - static long lock = 0; - if( InterlockedIncrement(&lock)==1 ){ - InitializeCriticalSection(&cs); - isInit = 1; - }else{ - Sleep(1); - } - } - EnterCriticalSection(&cs); -#endif -#ifdef SQLITE_MACOS_MULTITASKING - static volatile int notInit = 1; - if( notInit ){ - if( notInit == 2 ) /* as close as you can get to thread safe init */ - MPYield(); - else{ - notInit = 2; - MPCreateCriticalRegion(&criticalRegion); - notInit = 0; - } - } - MPEnterCriticalRegion(criticalRegion, kDurationForever); -#endif - assert( !inMutex ); - inMutex = 1; -} -void sqliteOsLeaveMutex(){ - assert( inMutex ); - inMutex = 0; -#ifdef SQLITE_UNIX_THREADS - pthread_mutex_unlock(&mutex); -#endif -#ifdef SQLITE_W32_THREADS - LeaveCriticalSection(&cs); -#endif -#ifdef SQLITE_MACOS_MULTITASKING - MPExitCriticalRegion(criticalRegion); -#endif -} - -/* -** Turn a relative pathname into a full pathname. Return a pointer -** to the full pathname stored in space obtained from sqliteMalloc(). -** The calling function is responsible for freeing this space once it -** is no longer needed. -*/ -char *sqliteOsFullPathname(const char *zRelative){ -#if OS_UNIX - char *zFull = 0; - if( zRelative[0]=='/' ){ - sqliteSetString(&zFull, zRelative, (char*)0); - }else{ - char zBuf[5000]; - sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative, - (char*)0); - } - return zFull; -#endif -#if OS_WIN - char *zNotUsed; - char *zFull; - int nByte; - nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1; - zFull = sqliteMalloc( nByte ); - if( zFull==0 ) return 0; - GetFullPathName(zRelative, nByte, zFull, &zNotUsed); - return zFull; -#endif -#if OS_MAC - char *zFull = 0; - if( zRelative[0]==':' ){ - char zBuf[_MAX_PATH+1]; - sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]), - (char*)0); - }else{ - if( strchr(zRelative, ':') ){ - sqliteSetString(&zFull, zRelative, (char*)0); - }else{ - char zBuf[_MAX_PATH+1]; - sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0); - } - } - return zFull; -#endif -} - -/* -** The following variable, if set to a non-zero value, becomes the result -** returned from sqliteOsCurrentTime(). This is used for testing. -*/ -#ifdef SQLITE_TEST -int sqlite_current_time = 0; -#endif - -/* -** Find the current time (in Universal Coordinated Time). Write the -** current time and date as a Julian Day number into *prNow and -** return 0. Return 1 if the time and date cannot be found. -*/ -int sqliteOsCurrentTime(double *prNow){ -#if OS_UNIX - time_t t; - time(&t); - *prNow = t/86400.0 + 2440587.5; -#endif -#if OS_WIN - FILETIME ft; - /* FILETIME structure is a 64-bit value representing the number of - 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). - */ - double now; - GetSystemTimeAsFileTime( &ft ); - now = ((double)ft.dwHighDateTime) * 4294967296.0; - *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; -#endif -#ifdef SQLITE_TEST - if( sqlite_current_time ){ - *prNow = sqlite_current_time/86400.0 + 2440587.5; - } -#endif - return 0; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/os.h b/dbLifeLog/DBD-SQLite2-0.33/os.h deleted file mode 100644 index d139584..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/os.h +++ /dev/null @@ -1,191 +0,0 @@ -/* -** 2001 September 16 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file (together with is companion C source-code file -** "os.c") attempt to abstract the underlying operating system so that -** the SQLite library will work on both POSIX and windows systems. -*/ -#ifndef _SQLITE_OS_H_ -#define _SQLITE_OS_H_ - -/* -** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE -** to the compiler command line. -*/ - -/* -** These #defines should enable >2GB file support on Posix if the -** underlying operating system supports it. If the OS lacks -** large file support, or if the OS is windows, these should be no-ops. -** -** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch -** on the compiler command line. This is necessary if you are compiling -** on a recent machine (ex: RedHat 7.2) but you want your code to work -** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 -** without this option, LFS is enable. But LFS does not exist in the kernel -** in RedHat 6.0, so the code won't work. Hence, for maximum binary -** portability you should omit LFS. -** -** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. -*/ -#ifndef SQLITE_DISABLE_LFS -# define _LARGE_FILE 1 -# ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -# endif -# define _LARGEFILE_SOURCE 1 -#endif - -/* -** Temporary files are named starting with this prefix followed by 16 random -** alphanumeric characters, and no file extension. They are stored in the -** OS's standard temporary file directory, and are deleted prior to exit. -** If sqlite is being embedded in another program, you may wish to change the -** prefix to reflect your program's name, so that if your program exits -** prematurely, old temporary files can be easily identified. This can be done -** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line. -*/ -#ifndef TEMP_FILE_PREFIX -# define TEMP_FILE_PREFIX "sqlite_" -#endif - -/* -** Figure out if we are dealing with Unix, Windows or MacOS. -** -** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix. -** The MacOS build is designed to use CodeWarrior (tested with v8) -*/ -#ifndef OS_UNIX -# ifndef OS_WIN -# ifndef OS_MAC -# if defined(__MACOS__) -# define OS_MAC 1 -# define OS_WIN 0 -# define OS_UNIX 0 -# elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) -# define OS_MAC 0 -# define OS_WIN 1 -# define OS_UNIX 0 -# else -# define OS_MAC 0 -# define OS_WIN 0 -# define OS_UNIX 1 -# endif -# else -# define OS_WIN 0 -# define OS_UNIX 0 -# endif -# else -# define OS_MAC 0 -# define OS_UNIX 0 -# endif -#else -# define OS_MAC 0 -# ifndef OS_WIN -# define OS_WIN 0 -# endif -#endif - -/* -** A handle for an open file is stored in an OsFile object. -*/ -#if OS_UNIX -# include -# include -# include -# include - typedef struct OsFile OsFile; - struct OsFile { - struct openCnt *pOpen; /* Info about all open fd's on this inode */ - struct lockInfo *pLock; /* Info about locks on this inode */ - int fd; /* The file descriptor */ - int locked; /* True if this instance holds the lock */ - int dirfd; /* File descriptor for the directory */ - }; -# define SQLITE_TEMPNAME_SIZE 200 -# if defined(HAVE_USLEEP) && HAVE_USLEEP -# define SQLITE_MIN_SLEEP_MS 1 -# else -# define SQLITE_MIN_SLEEP_MS 1000 -# endif -#endif - -#if OS_WIN -#include -#include - typedef struct OsFile OsFile; - struct OsFile { - HANDLE h; /* Handle for accessing the file */ - int locked; /* 0: unlocked, <0: write lock, >0: read lock */ - }; -# if defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 off_t; -# else -# if !defined(_CYGWIN_TYPES_H) - typedef long long off_t; -# if defined(__MINGW32__) -# define _OFF_T_ -# endif -# endif -# endif -# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) -# define SQLITE_MIN_SLEEP_MS 1 -#endif - -#if OS_MAC -# include -# include - typedef struct OsFile OsFile; - struct OsFile { - SInt16 refNum; /* Data fork/file reference number */ - SInt16 refNumRF; /* Resource fork reference number (for locking) */ - int locked; /* 0: unlocked, <0: write lock, >0: read lock */ - int delOnClose; /* True if file is to be deleted on close */ - char *pathToDel; /* Name of file to delete on close */ - }; -# ifdef _LARGE_FILE - typedef SInt64 off_t; -# else - typedef SInt32 off_t; -# endif -# define SQLITE_TEMPNAME_SIZE _MAX_PATH -# define SQLITE_MIN_SLEEP_MS 17 -#endif - -int sqliteOsDelete(const char*); -int sqliteOsFileExists(const char*); -int sqliteOsFileRename(const char*, const char*); -int sqliteOsOpenReadWrite(const char*, OsFile*, int*); -int sqliteOsOpenExclusive(const char*, OsFile*, int); -int sqliteOsOpenReadOnly(const char*, OsFile*); -int sqliteOsOpenDirectory(const char*, OsFile*); -int sqliteOsTempFileName(char*); -int sqliteOsClose(OsFile*); -int sqliteOsRead(OsFile*, void*, int amt); -int sqliteOsWrite(OsFile*, const void*, int amt); -int sqliteOsSeek(OsFile*, off_t offset); -int sqliteOsSync(OsFile*); -int sqliteOsTruncate(OsFile*, off_t size); -int sqliteOsFileSize(OsFile*, off_t *pSize); -int sqliteOsReadLock(OsFile*); -int sqliteOsWriteLock(OsFile*); -int sqliteOsUnlock(OsFile*); -int sqliteOsRandomSeed(char*); -int sqliteOsSleep(int ms); -int sqliteOsCurrentTime(double*); -void sqliteOsEnterMutex(void); -void sqliteOsLeaveMutex(void); -char *sqliteOsFullPathname(const char*); - - - -#endif /* _SQLITE_OS_H_ */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/os.o b/dbLifeLog/DBD-SQLite2-0.33/os.o deleted file mode 100644 index 5717298c56c344733e848c10355b76abe451b5dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11920 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 diff --git a/dbLifeLog/DBD-SQLite2-0.33/pager.c b/dbLifeLog/DBD-SQLite2-0.33/pager.c deleted file mode 100644 index b3ba345..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/pager.c +++ /dev/null @@ -1,2220 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the implementation of the page cache subsystem or "pager". -** -** The pager is used to access a database disk file. It implements -** atomic commit and rollback through the use of a journal file that -** is separate from the database file. The pager also implements file -** locking to prevent two processes from writing the same database -** file simultaneously, or one process from reading the database while -** another is writing. -** -** @(#) $Id: pager.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ -#include "os.h" /* Must be first to enable large file support */ -#include "sqliteInt.h" -#include "pager.h" -#include -#include - -/* -** Macros for troubleshooting. Normally turned off -*/ -#if 0 -static Pager *mainPager = 0; -#define SET_PAGER(X) if( mainPager==0 ) mainPager = (X) -#define CLR_PAGER(X) if( mainPager==(X) ) mainPager = 0 -#define TRACE1(X) if( pPager==mainPager ) fprintf(stderr,X) -#define TRACE2(X,Y) if( pPager==mainPager ) fprintf(stderr,X,Y) -#define TRACE3(X,Y,Z) if( pPager==mainPager ) fprintf(stderr,X,Y,Z) -#else -#define SET_PAGER(X) -#define CLR_PAGER(X) -#define TRACE1(X) -#define TRACE2(X,Y) -#define TRACE3(X,Y,Z) -#endif - - -/* -** The page cache as a whole is always in one of the following -** states: -** -** SQLITE_UNLOCK The page cache is not currently reading or -** writing the database file. There is no -** data held in memory. This is the initial -** state. -** -** SQLITE_READLOCK The page cache is reading the database. -** Writing is not permitted. There can be -** multiple readers accessing the same database -** file at the same time. -** -** SQLITE_WRITELOCK The page cache is writing the database. -** Access is exclusive. No other processes or -** threads can be reading or writing while one -** process is writing. -** -** The page cache comes up in SQLITE_UNLOCK. The first time a -** sqlite_page_get() occurs, the state transitions to SQLITE_READLOCK. -** After all pages have been released using sqlite_page_unref(), -** the state transitions back to SQLITE_UNLOCK. The first time -** that sqlite_page_write() is called, the state transitions to -** SQLITE_WRITELOCK. (Note that sqlite_page_write() can only be -** called on an outstanding page which means that the pager must -** be in SQLITE_READLOCK before it transitions to SQLITE_WRITELOCK.) -** The sqlite_page_rollback() and sqlite_page_commit() functions -** transition the state from SQLITE_WRITELOCK back to SQLITE_READLOCK. -*/ -#define SQLITE_UNLOCK 0 -#define SQLITE_READLOCK 1 -#define SQLITE_WRITELOCK 2 - - -/* -** Each in-memory image of a page begins with the following header. -** This header is only visible to this pager module. The client -** code that calls pager sees only the data that follows the header. -** -** Client code should call sqlitepager_write() on a page prior to making -** any modifications to that page. The first time sqlitepager_write() -** is called, the original page contents are written into the rollback -** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once -** the journal page has made it onto the disk surface, PgHdr.needSync -** is cleared. The modified page cannot be written back into the original -** database file until the journal pages has been synced to disk and the -** PgHdr.needSync has been cleared. -** -** The PgHdr.dirty flag is set when sqlitepager_write() is called and -** is cleared again when the page content is written back to the original -** database file. -*/ -typedef struct PgHdr PgHdr; -struct PgHdr { - Pager *pPager; /* The pager to which this page belongs */ - Pgno pgno; /* The page number for this page */ - PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */ - int nRef; /* Number of users of this page */ - PgHdr *pNextFree, *pPrevFree; /* Freelist of pages where nRef==0 */ - PgHdr *pNextAll, *pPrevAll; /* A list of all pages */ - PgHdr *pNextCkpt, *pPrevCkpt; /* List of pages in the checkpoint journal */ - u8 inJournal; /* TRUE if has been written to journal */ - u8 inCkpt; /* TRUE if written to the checkpoint journal */ - u8 dirty; /* TRUE if we need to write back changes */ - u8 needSync; /* Sync journal before writing this page */ - u8 alwaysRollback; /* Disable dont_rollback() for this page */ - PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ - /* SQLITE_PAGE_SIZE bytes of page data follow this header */ - /* Pager.nExtra bytes of local data follow the page data */ -}; - - -/* -** A macro used for invoking the codec if there is one -*/ -#ifdef SQLITE_HAS_CODEC -# define CODEC(P,D,N,X) if( P->xCodec ){ P->xCodec(P->pCodecArg,D,N,X); } -#else -# define CODEC(P,D,N,X) -#endif - -/* -** Convert a pointer to a PgHdr into a pointer to its data -** and back again. -*/ -#define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) -#define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) -#define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE]) - -/* -** How big to make the hash table used for locating in-memory pages -** by page number. -*/ -#define N_PG_HASH 2048 - -/* -** Hash a page number -*/ -#define pager_hash(PN) ((PN)&(N_PG_HASH-1)) - -/* -** A open page cache is an instance of the following structure. -*/ -struct Pager { - char *zFilename; /* Name of the database file */ - char *zJournal; /* Name of the journal file */ - char *zDirectory; /* Directory hold database and journal files */ - OsFile fd, jfd; /* File descriptors for database and journal */ - OsFile cpfd; /* File descriptor for the checkpoint journal */ - int dbSize; /* Number of pages in the file */ - int origDbSize; /* dbSize before the current change */ - int ckptSize; /* Size of database (in pages) at ckpt_begin() */ - off_t ckptJSize; /* Size of journal at ckpt_begin() */ - int nRec; /* Number of pages written to the journal */ - u32 cksumInit; /* Quasi-random value added to every checksum */ - int ckptNRec; /* Number of records in the checkpoint journal */ - int nExtra; /* Add this many bytes to each in-memory page */ - void (*xDestructor)(void*); /* Call this routine when freeing pages */ - int nPage; /* Total number of in-memory pages */ - int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ - int mxPage; /* Maximum number of pages to hold in cache */ - int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ - void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ - void *pCodecArg; /* First argument to xCodec() */ - u8 journalOpen; /* True if journal file descriptors is valid */ - u8 journalStarted; /* True if header of journal is synced */ - u8 useJournal; /* Use a rollback journal on this file */ - u8 ckptOpen; /* True if the checkpoint journal is open */ - u8 ckptInUse; /* True we are in a checkpoint */ - u8 ckptAutoopen; /* Open ckpt journal when main journal is opened*/ - u8 noSync; /* Do not sync the journal if true */ - u8 fullSync; /* Do extra syncs of the journal for robustness */ - u8 state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */ - u8 errMask; /* One of several kinds of errors */ - u8 tempFile; /* zFilename is a temporary file */ - u8 readOnly; /* True for a read-only database */ - u8 needSync; /* True if an fsync() is needed on the journal */ - u8 dirtyFile; /* True if database file has changed in any way */ - u8 alwaysRollback; /* Disable dont_rollback() for all pages */ - u8 *aInJournal; /* One bit for each page in the database file */ - u8 *aInCkpt; /* One bit for each page in the database */ - PgHdr *pFirst, *pLast; /* List of free pages */ - PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ - PgHdr *pAll; /* List of all pages */ - PgHdr *pCkpt; /* List of pages in the checkpoint journal */ - PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number of PgHdr */ -}; - -/* -** These are bits that can be set in Pager.errMask. -*/ -#define PAGER_ERR_FULL 0x01 /* a write() failed */ -#define PAGER_ERR_MEM 0x02 /* malloc() failed */ -#define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */ -#define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */ -#define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */ - -/* -** The journal file contains page records in the following -** format. -** -** Actually, this structure is the complete page record for pager -** formats less than 3. Beginning with format 3, this record is surrounded -** by two checksums. -*/ -typedef struct PageRecord PageRecord; -struct PageRecord { - Pgno pgno; /* The page number */ - char aData[SQLITE_PAGE_SIZE]; /* Original data for page pgno */ -}; - -/* -** Journal files begin with the following magic string. The data -** was obtained from /dev/random. It is used only as a sanity check. -** -** There are three journal formats (so far). The 1st journal format writes -** 32-bit integers in the byte-order of the host machine. New -** formats writes integers as big-endian. All new journals use the -** new format, but we have to be able to read an older journal in order -** to rollback journals created by older versions of the library. -** -** The 3rd journal format (added for 2.8.0) adds additional sanity -** checking information to the journal. If the power fails while the -** journal is being written, semi-random garbage data might appear in -** the journal file after power is restored. If an attempt is then made -** to roll the journal back, the database could be corrupted. The additional -** sanity checking data is an attempt to discover the garbage in the -** journal and ignore it. -** -** The sanity checking information for the 3rd journal format consists -** of a 32-bit checksum on each page of data. The checksum covers both -** the page number and the SQLITE_PAGE_SIZE bytes of data for the page. -** This cksum is initialized to a 32-bit random value that appears in the -** journal file right after the header. The random initializer is important, -** because garbage data that appears at the end of a journal is likely -** data that was once in other files that have now been deleted. If the -** garbage data came from an obsolete journal file, the checksums might -** be correct. But by initializing the checksum to random value which -** is different for every journal, we minimize that risk. -*/ -static const unsigned char aJournalMagic1[] = { - 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd4, -}; -static const unsigned char aJournalMagic2[] = { - 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd5, -}; -static const unsigned char aJournalMagic3[] = { - 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd6, -}; -#define JOURNAL_FORMAT_1 1 -#define JOURNAL_FORMAT_2 2 -#define JOURNAL_FORMAT_3 3 - -/* -** The following integer determines what format to use when creating -** new primary journal files. By default we always use format 3. -** When testing, we can set this value to older journal formats in order to -** make sure that newer versions of the library are able to rollback older -** journal files. -** -** Note that checkpoint journals always use format 2 and omit the header. -*/ -#ifdef SQLITE_TEST -int journal_format = 3; -#else -# define journal_format 3 -#endif - -/* -** The size of the header and of each page in the journal varies according -** to which journal format is being used. The following macros figure out -** the sizes based on format numbers. -*/ -#define JOURNAL_HDR_SZ(X) \ - (sizeof(aJournalMagic1) + sizeof(Pgno) + ((X)>=3)*2*sizeof(u32)) -#define JOURNAL_PG_SZ(X) \ - (SQLITE_PAGE_SIZE + sizeof(Pgno) + ((X)>=3)*sizeof(u32)) - -/* -** Enable reference count tracking here: -*/ -#ifdef SQLITE_TEST - int pager_refinfo_enable = 0; - static void pager_refinfo(PgHdr *p){ - static int cnt = 0; - if( !pager_refinfo_enable ) return; - printf( - "REFCNT: %4d addr=0x%08x nRef=%d\n", - p->pgno, (int)PGHDR_TO_DATA(p), p->nRef - ); - cnt++; /* Something to set a breakpoint on */ - } -# define REFINFO(X) pager_refinfo(X) -#else -# define REFINFO(X) -#endif - -/* -** Read a 32-bit integer from the given file descriptor. Store the integer -** that is read in *pRes. Return SQLITE_OK if everything worked, or an -** error code is something goes wrong. -** -** If the journal format is 2 or 3, read a big-endian integer. If the -** journal format is 1, read an integer in the native byte-order of the -** host machine. -*/ -static int read32bits(int format, OsFile *fd, u32 *pRes){ - u32 res; - int rc; - rc = sqliteOsRead(fd, &res, sizeof(res)); - if( rc==SQLITE_OK && format>JOURNAL_FORMAT_1 ){ - unsigned char ac[4]; - memcpy(ac, &res, 4); - res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; - } - *pRes = res; - return rc; -} - -/* -** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK -** on success or an error code is something goes wrong. -** -** If the journal format is 2 or 3, write the integer as 4 big-endian -** bytes. If the journal format is 1, write the integer in the native -** byte order. In normal operation, only formats 2 and 3 are used. -** Journal format 1 is only used for testing. -*/ -static int write32bits(OsFile *fd, u32 val){ - unsigned char ac[4]; - if( journal_format<=1 ){ - return sqliteOsWrite(fd, &val, 4); - } - ac[0] = (val>>24) & 0xff; - ac[1] = (val>>16) & 0xff; - ac[2] = (val>>8) & 0xff; - ac[3] = val & 0xff; - return sqliteOsWrite(fd, ac, 4); -} - -/* -** Write a 32-bit integer into a page header right before the -** page data. This will overwrite the PgHdr.pDirty pointer. -** -** The integer is big-endian for formats 2 and 3 and native byte order -** for journal format 1. -*/ -static void store32bits(u32 val, PgHdr *p, int offset){ - unsigned char *ac; - ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; - if( journal_format<=1 ){ - memcpy(ac, &val, 4); - }else{ - ac[0] = (val>>24) & 0xff; - ac[1] = (val>>16) & 0xff; - ac[2] = (val>>8) & 0xff; - ac[3] = val & 0xff; - } -} - - -/* -** Convert the bits in the pPager->errMask into an approprate -** return code. -*/ -static int pager_errcode(Pager *pPager){ - int rc = SQLITE_OK; - if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL; - if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR; - if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL; - if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM; - if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT; - return rc; -} - -/* -** Add or remove a page from the list of all pages that are in the -** checkpoint journal. -** -** The Pager keeps a separate list of pages that are currently in -** the checkpoint journal. This helps the sqlitepager_ckpt_commit() -** routine run MUCH faster for the common case where there are many -** pages in memory but only a few are in the checkpoint journal. -*/ -static void page_add_to_ckpt_list(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - if( pPg->inCkpt ) return; - assert( pPg->pPrevCkpt==0 && pPg->pNextCkpt==0 ); - pPg->pPrevCkpt = 0; - if( pPager->pCkpt ){ - pPager->pCkpt->pPrevCkpt = pPg; - } - pPg->pNextCkpt = pPager->pCkpt; - pPager->pCkpt = pPg; - pPg->inCkpt = 1; -} -static void page_remove_from_ckpt_list(PgHdr *pPg){ - if( !pPg->inCkpt ) return; - if( pPg->pPrevCkpt ){ - assert( pPg->pPrevCkpt->pNextCkpt==pPg ); - pPg->pPrevCkpt->pNextCkpt = pPg->pNextCkpt; - }else{ - assert( pPg->pPager->pCkpt==pPg ); - pPg->pPager->pCkpt = pPg->pNextCkpt; - } - if( pPg->pNextCkpt ){ - assert( pPg->pNextCkpt->pPrevCkpt==pPg ); - pPg->pNextCkpt->pPrevCkpt = pPg->pPrevCkpt; - } - pPg->pNextCkpt = 0; - pPg->pPrevCkpt = 0; - pPg->inCkpt = 0; -} - -/* -** Find a page in the hash table given its page number. Return -** a pointer to the page or NULL if not found. -*/ -static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ - PgHdr *p = pPager->aHash[pager_hash(pgno)]; - while( p && p->pgno!=pgno ){ - p = p->pNextHash; - } - return p; -} - -/* -** Unlock the database and clear the in-memory cache. This routine -** sets the state of the pager back to what it was when it was first -** opened. Any outstanding pages are invalidated and subsequent attempts -** to access those pages will likely result in a coredump. -*/ -static void pager_reset(Pager *pPager){ - PgHdr *pPg, *pNext; - for(pPg=pPager->pAll; pPg; pPg=pNext){ - pNext = pPg->pNextAll; - sqliteFree(pPg); - } - pPager->pFirst = 0; - pPager->pFirstSynced = 0; - pPager->pLast = 0; - pPager->pAll = 0; - memset(pPager->aHash, 0, sizeof(pPager->aHash)); - pPager->nPage = 0; - if( pPager->state>=SQLITE_WRITELOCK ){ - sqlitepager_rollback(pPager); - } - sqliteOsUnlock(&pPager->fd); - pPager->state = SQLITE_UNLOCK; - pPager->dbSize = -1; - pPager->nRef = 0; - assert( pPager->journalOpen==0 ); -} - -/* -** When this routine is called, the pager has the journal file open and -** a write lock on the database. This routine releases the database -** write lock and acquires a read lock in its place. The journal file -** is deleted and closed. -** -** TODO: Consider keeping the journal file open for temporary databases. -** This might give a performance improvement on windows where opening -** a file is an expensive operation. -*/ -static int pager_unwritelock(Pager *pPager){ - int rc; - PgHdr *pPg; - if( pPager->stateckptOpen ){ - sqliteOsClose(&pPager->cpfd); - pPager->ckptOpen = 0; - } - if( pPager->journalOpen ){ - sqliteOsClose(&pPager->jfd); - pPager->journalOpen = 0; - sqliteOsDelete(pPager->zJournal); - sqliteFree( pPager->aInJournal ); - pPager->aInJournal = 0; - for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ - pPg->inJournal = 0; - pPg->dirty = 0; - pPg->needSync = 0; - } - }else{ - assert( pPager->dirtyFile==0 || pPager->useJournal==0 ); - } - rc = sqliteOsReadLock(&pPager->fd); - if( rc==SQLITE_OK ){ - pPager->state = SQLITE_READLOCK; - }else{ - /* This can only happen if a process does a BEGIN, then forks and the - ** child process does the COMMIT. Because of the semantics of unix - ** file locking, the unlock will fail. - */ - pPager->state = SQLITE_UNLOCK; - } - return rc; -} - -/* -** Compute and return a checksum for the page of data. -** -** This is not a real checksum. It is really just the sum of the -** random initial value and the page number. We considered do a checksum -** of the database, but that was found to be too slow. -*/ -static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){ - u32 cksum = pPager->cksumInit + pgno; - return cksum; -} - -/* -** Read a single page from the journal file opened on file descriptor -** jfd. Playback this one page. -** -** There are three different journal formats. The format parameter determines -** which format is used by the journal that is played back. -*/ -static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int format){ - int rc; - PgHdr *pPg; /* An existing page in the cache */ - PageRecord pgRec; - u32 cksum; - - rc = read32bits(format, jfd, &pgRec.pgno); - if( rc!=SQLITE_OK ) return rc; - rc = sqliteOsRead(jfd, &pgRec.aData, sizeof(pgRec.aData)); - if( rc!=SQLITE_OK ) return rc; - - /* Sanity checking on the page. This is more important that I originally - ** thought. If a power failure occurs while the journal is being written, - ** it could cause invalid data to be written into the journal. We need to - ** detect this invalid data (with high probability) and ignore it. - */ - if( pgRec.pgno==0 ){ - return SQLITE_DONE; - } - if( pgRec.pgno>(unsigned)pPager->dbSize ){ - return SQLITE_OK; - } - if( format>=JOURNAL_FORMAT_3 ){ - rc = read32bits(format, jfd, &cksum); - if( rc ) return rc; - if( pager_cksum(pPager, pgRec.pgno, pgRec.aData)!=cksum ){ - return SQLITE_DONE; - } - } - - /* Playback the page. Update the in-memory copy of the page - ** at the same time, if there is one. - */ - pPg = pager_lookup(pPager, pgRec.pgno); - TRACE2("PLAYBACK %d\n", pgRec.pgno); - sqliteOsSeek(&pPager->fd, (pgRec.pgno-1)*(off_t)SQLITE_PAGE_SIZE); - rc = sqliteOsWrite(&pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE); - if( pPg ){ - /* No page should ever be rolled back that is in use, except for page - ** 1 which is held in use in order to keep the lock on the database - ** active. - */ - assert( pPg->nRef==0 || pPg->pgno==1 ); - memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE); - memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); - pPg->dirty = 0; - pPg->needSync = 0; - CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); - } - return rc; -} - -/* -** Playback the journal and thus restore the database file to -** the state it was in before we started making changes. -** -** The journal file format is as follows: -** -** * 8 byte prefix. One of the aJournalMagic123 vectors defined -** above. The format of the journal file is determined by which -** of the three prefix vectors is seen. -** * 4 byte big-endian integer which is the number of valid page records -** in the journal. If this value is 0xffffffff, then compute the -** number of page records from the journal size. This field appears -** in format 3 only. -** * 4 byte big-endian integer which is the initial value for the -** sanity checksum. This field appears in format 3 only. -** * 4 byte integer which is the number of pages to truncate the -** database to during a rollback. -** * Zero or more pages instances, each as follows: -** + 4 byte page number. -** + SQLITE_PAGE_SIZE bytes of data. -** + 4 byte checksum (format 3 only) -** -** When we speak of the journal header, we mean the first 4 bullets above. -** Each entry in the journal is an instance of the 5th bullet. Note that -** bullets 2 and 3 only appear in format-3 journals. -** -** Call the value from the second bullet "nRec". nRec is the number of -** valid page entries in the journal. In most cases, you can compute the -** value of nRec from the size of the journal file. But if a power -** failure occurred while the journal was being written, it could be the -** case that the size of the journal file had already been increased but -** the extra entries had not yet made it safely to disk. In such a case, -** the value of nRec computed from the file size would be too large. For -** that reason, we always use the nRec value in the header. -** -** If the nRec value is 0xffffffff it means that nRec should be computed -** from the file size. This value is used when the user selects the -** no-sync option for the journal. A power failure could lead to corruption -** in this case. But for things like temporary table (which will be -** deleted when the power is restored) we don't care. -** -** Journal formats 1 and 2 do not have an nRec value in the header so we -** have to compute nRec from the file size. This has risks (as described -** above) which is why all persistent tables have been changed to use -** format 3. -** -** If the file opened as the journal file is not a well-formed -** journal file then the database will likely already be -** corrupted, so the PAGER_ERR_CORRUPT bit is set in pPager->errMask -** and SQLITE_CORRUPT is returned. If it all works, then this routine -** returns SQLITE_OK. -*/ -static int pager_playback(Pager *pPager, int useJournalSize){ - off_t szJ; /* Size of the journal file in bytes */ - int nRec; /* Number of Records in the journal */ - int i; /* Loop counter */ - Pgno mxPg = 0; /* Size of the original file in pages */ - int format; /* Format of the journal file. */ - unsigned char aMagic[sizeof(aJournalMagic1)]; - int rc; - - /* Figure out how many records are in the journal. Abort early if - ** the journal is empty. - */ - assert( pPager->journalOpen ); - sqliteOsSeek(&pPager->jfd, 0); - rc = sqliteOsFileSize(&pPager->jfd, &szJ); - if( rc!=SQLITE_OK ){ - goto end_playback; - } - - /* If the journal file is too small to contain a complete header, - ** it must mean that the process that created the journal was just - ** beginning to write the journal file when it died. In that case, - ** the database file should have still been completely unchanged. - ** Nothing needs to be rolled back. We can safely ignore this journal. - */ - if( szJ < sizeof(aMagic)+sizeof(Pgno) ){ - goto end_playback; - } - - /* Read the beginning of the journal and truncate the - ** database file back to its original size. - */ - rc = sqliteOsRead(&pPager->jfd, aMagic, sizeof(aMagic)); - if( rc!=SQLITE_OK ){ - rc = SQLITE_PROTOCOL; - goto end_playback; - } - if( memcmp(aMagic, aJournalMagic3, sizeof(aMagic))==0 ){ - format = JOURNAL_FORMAT_3; - }else if( memcmp(aMagic, aJournalMagic2, sizeof(aMagic))==0 ){ - format = JOURNAL_FORMAT_2; - }else if( memcmp(aMagic, aJournalMagic1, sizeof(aMagic))==0 ){ - format = JOURNAL_FORMAT_1; - }else{ - rc = SQLITE_PROTOCOL; - goto end_playback; - } - if( format>=JOURNAL_FORMAT_3 ){ - if( szJ < sizeof(aMagic) + 3*sizeof(u32) ){ - /* Ignore the journal if it is too small to contain a complete - ** header. We already did this test once above, but at the prior - ** test, we did not know the journal format and so we had to assume - ** the smallest possible header. Now we know the header is bigger - ** than the minimum so we test again. - */ - goto end_playback; - } - rc = read32bits(format, &pPager->jfd, (u32*)&nRec); - if( rc ) goto end_playback; - rc = read32bits(format, &pPager->jfd, &pPager->cksumInit); - if( rc ) goto end_playback; - if( nRec==0xffffffff || useJournalSize ){ - nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3); - } - }else{ - nRec = (szJ - JOURNAL_HDR_SZ(2))/JOURNAL_PG_SZ(2); - assert( nRec*JOURNAL_PG_SZ(2)+JOURNAL_HDR_SZ(2)==szJ ); - } - rc = read32bits(format, &pPager->jfd, &mxPg); - if( rc!=SQLITE_OK ){ - goto end_playback; - } - assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg ); - rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)mxPg); - if( rc!=SQLITE_OK ){ - goto end_playback; - } - pPager->dbSize = mxPg; - - /* Copy original pages out of the journal and back into the database file. - */ - for(i=0; ijfd, format); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - } - break; - } - } - - /* Pages that have been written to the journal but never synced - ** where not restored by the loop above. We have to restore those - ** pages by reading them back from the original database. - */ - if( rc==SQLITE_OK ){ - PgHdr *pPg; - for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ - char zBuf[SQLITE_PAGE_SIZE]; - if( !pPg->dirty ) continue; - if( (int)pPg->pgno <= pPager->origDbSize ){ - sqliteOsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)(pPg->pgno-1)); - rc = sqliteOsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE); - TRACE2("REFETCH %d\n", pPg->pgno); - CODEC(pPager, zBuf, pPg->pgno, 2); - if( rc ) break; - }else{ - memset(zBuf, 0, SQLITE_PAGE_SIZE); - } - if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){ - memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE); - memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); - } - pPg->needSync = 0; - pPg->dirty = 0; - } - } - -end_playback: - if( rc!=SQLITE_OK ){ - pager_unwritelock(pPager); - pPager->errMask |= PAGER_ERR_CORRUPT; - rc = SQLITE_CORRUPT; - }else{ - rc = pager_unwritelock(pPager); - } - return rc; -} - -/* -** Playback the checkpoint journal. -** -** This is similar to playing back the transaction journal but with -** a few extra twists. -** -** (1) The number of pages in the database file at the start of -** the checkpoint is stored in pPager->ckptSize, not in the -** journal file itself. -** -** (2) In addition to playing back the checkpoint journal, also -** playback all pages of the transaction journal beginning -** at offset pPager->ckptJSize. -*/ -static int pager_ckpt_playback(Pager *pPager){ - off_t szJ; /* Size of the full journal */ - int nRec; /* Number of Records */ - int i; /* Loop counter */ - int rc; - - /* Truncate the database back to its original size. - */ - rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)pPager->ckptSize); - pPager->dbSize = pPager->ckptSize; - - /* Figure out how many records are in the checkpoint journal. - */ - assert( pPager->ckptInUse && pPager->journalOpen ); - sqliteOsSeek(&pPager->cpfd, 0); - nRec = pPager->ckptNRec; - - /* Copy original pages out of the checkpoint journal and back into the - ** database file. Note that the checkpoint journal always uses format - ** 2 instead of format 3 since it does not need to be concerned with - ** power failures corrupting the journal and can thus omit the checksums. - */ - for(i=nRec-1; i>=0; i--){ - rc = pager_playback_one_page(pPager, &pPager->cpfd, 2); - assert( rc!=SQLITE_DONE ); - if( rc!=SQLITE_OK ) goto end_ckpt_playback; - } - - /* Figure out how many pages need to be copied out of the transaction - ** journal. - */ - rc = sqliteOsSeek(&pPager->jfd, pPager->ckptJSize); - if( rc!=SQLITE_OK ){ - goto end_ckpt_playback; - } - rc = sqliteOsFileSize(&pPager->jfd, &szJ); - if( rc!=SQLITE_OK ){ - goto end_ckpt_playback; - } - nRec = (szJ - pPager->ckptJSize)/JOURNAL_PG_SZ(journal_format); - for(i=nRec-1; i>=0; i--){ - rc = pager_playback_one_page(pPager, &pPager->jfd, journal_format); - if( rc!=SQLITE_OK ){ - assert( rc!=SQLITE_DONE ); - goto end_ckpt_playback; - } - } - -end_ckpt_playback: - if( rc!=SQLITE_OK ){ - pPager->errMask |= PAGER_ERR_CORRUPT; - rc = SQLITE_CORRUPT; - } - return rc; -} - -/* -** Change the maximum number of in-memory pages that are allowed. -** -** The maximum number is the absolute value of the mxPage parameter. -** If mxPage is negative, the noSync flag is also set. noSync bypasses -** calls to sqliteOsSync(). The pager runs much faster with noSync on, -** but if the operating system crashes or there is an abrupt power -** failure, the database file might be left in an inconsistent and -** unrepairable state. -*/ -void sqlitepager_set_cachesize(Pager *pPager, int mxPage){ - if( mxPage>=0 ){ - pPager->noSync = pPager->tempFile; - if( pPager->noSync==0 ) pPager->needSync = 0; - }else{ - pPager->noSync = 1; - mxPage = -mxPage; - } - if( mxPage>10 ){ - pPager->mxPage = mxPage; - } -} - -/* -** Adjust the robustness of the database to damage due to OS crashes -** or power failures by changing the number of syncs()s when writing -** the rollback journal. There are three levels: -** -** OFF sqliteOsSync() is never called. This is the default -** for temporary and transient files. -** -** NORMAL The journal is synced once before writes begin on the -** database. This is normally adequate protection, but -** it is theoretically possible, though very unlikely, -** that an inopertune power failure could leave the journal -** in a state which would cause damage to the database -** when it is rolled back. -** -** FULL The journal is synced twice before writes begin on the -** database (with some additional information - the nRec field -** of the journal header - being written in between the two -** syncs). If we assume that writing a -** single disk sector is atomic, then this mode provides -** assurance that the journal will not be corrupted to the -** point of causing damage to the database during rollback. -** -** Numeric values associated with these states are OFF==1, NORMAL=2, -** and FULL=3. -*/ -void sqlitepager_set_safety_level(Pager *pPager, int level){ - pPager->noSync = level==1 || pPager->tempFile; - pPager->fullSync = level==3 && !pPager->tempFile; - if( pPager->noSync==0 ) pPager->needSync = 0; -} - -/* -** Open a temporary file. Write the name of the file into zName -** (zName must be at least SQLITE_TEMPNAME_SIZE bytes long.) Write -** the file descriptor into *fd. Return SQLITE_OK on success or some -** other error code if we fail. -** -** The OS will automatically delete the temporary file when it is -** closed. -*/ -static int sqlitepager_opentemp(char *zFile, OsFile *fd){ - int cnt = 8; - int rc; - do{ - cnt--; - sqliteOsTempFileName(zFile); - rc = sqliteOsOpenExclusive(zFile, fd, 1); - }while( cnt>0 && rc!=SQLITE_OK ); - return rc; -} - -/* -** Create a new page cache and put a pointer to the page cache in *ppPager. -** The file to be cached need not exist. The file is not locked until -** the first call to sqlitepager_get() and is only held open until the -** last page is released using sqlitepager_unref(). -** -** If zFilename is NULL then a randomly-named temporary file is created -** and used as the file to be cached. The file will be deleted -** automatically when it is closed. -*/ -int sqlitepager_open( - Pager **ppPager, /* Return the Pager structure here */ - const char *zFilename, /* Name of the database file to open */ - int mxPage, /* Max number of in-memory cache pages */ - int nExtra, /* Extra bytes append to each in-memory page */ - int useJournal /* TRUE to use a rollback journal on this file */ -){ - Pager *pPager; - char *zFullPathname; - int nameLen; - OsFile fd; - int rc, i; - int tempFile; - int readOnly = 0; - char zTemp[SQLITE_TEMPNAME_SIZE]; - - *ppPager = 0; - if( sqlite_malloc_failed ){ - return SQLITE_NOMEM; - } - if( zFilename && zFilename[0] ){ - zFullPathname = sqliteOsFullPathname(zFilename); - rc = sqliteOsOpenReadWrite(zFullPathname, &fd, &readOnly); - tempFile = 0; - }else{ - rc = sqlitepager_opentemp(zTemp, &fd); - zFilename = zTemp; - zFullPathname = sqliteOsFullPathname(zFilename); - tempFile = 1; - } - if( sqlite_malloc_failed ){ - return SQLITE_NOMEM; - } - if( rc!=SQLITE_OK ){ - sqliteFree(zFullPathname); - return SQLITE_CANTOPEN; - } - nameLen = strlen(zFullPathname); - pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); - if( pPager==0 ){ - sqliteOsClose(&fd); - sqliteFree(zFullPathname); - return SQLITE_NOMEM; - } - SET_PAGER(pPager); - pPager->zFilename = (char*)&pPager[1]; - pPager->zDirectory = &pPager->zFilename[nameLen+1]; - pPager->zJournal = &pPager->zDirectory[nameLen+1]; - strcpy(pPager->zFilename, zFullPathname); - strcpy(pPager->zDirectory, zFullPathname); - for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} - if( i>0 ) pPager->zDirectory[i-1] = 0; - strcpy(pPager->zJournal, zFullPathname); - sqliteFree(zFullPathname); - strcpy(&pPager->zJournal[nameLen], "-journal"); - pPager->fd = fd; - pPager->journalOpen = 0; - pPager->useJournal = useJournal; - pPager->ckptOpen = 0; - pPager->ckptInUse = 0; - pPager->nRef = 0; - pPager->dbSize = -1; - pPager->ckptSize = 0; - pPager->ckptJSize = 0; - pPager->nPage = 0; - pPager->mxPage = mxPage>5 ? mxPage : 10; - pPager->state = SQLITE_UNLOCK; - pPager->errMask = 0; - pPager->tempFile = tempFile; - pPager->readOnly = readOnly; - pPager->needSync = 0; - pPager->noSync = pPager->tempFile || !useJournal; - pPager->pFirst = 0; - pPager->pFirstSynced = 0; - pPager->pLast = 0; - pPager->nExtra = nExtra; - memset(pPager->aHash, 0, sizeof(pPager->aHash)); - *ppPager = pPager; - return SQLITE_OK; -} - -/* -** Set the destructor for this pager. If not NULL, the destructor is called -** when the reference count on each page reaches zero. The destructor can -** be used to clean up information in the extra segment appended to each page. -** -** The destructor is not called as a result sqlitepager_close(). -** Destructors are only called by sqlitepager_unref(). -*/ -void sqlitepager_set_destructor(Pager *pPager, void (*xDesc)(void*)){ - pPager->xDestructor = xDesc; -} - -/* -** Return the total number of pages in the disk file associated with -** pPager. -*/ -int sqlitepager_pagecount(Pager *pPager){ - off_t n; - assert( pPager!=0 ); - if( pPager->dbSize>=0 ){ - return pPager->dbSize; - } - if( sqliteOsFileSize(&pPager->fd, &n)!=SQLITE_OK ){ - pPager->errMask |= PAGER_ERR_DISK; - return 0; - } - n /= SQLITE_PAGE_SIZE; - if( pPager->state!=SQLITE_UNLOCK ){ - pPager->dbSize = n; - } - return n; -} - -/* -** Forward declaration -*/ -static int syncJournal(Pager*); - -/* -** Truncate the file to the number of pages specified. -*/ -int sqlitepager_truncate(Pager *pPager, Pgno nPage){ - int rc; - if( pPager->dbSize<0 ){ - sqlitepager_pagecount(pPager); - } - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); - return rc; - } - if( nPage>=(unsigned)pPager->dbSize ){ - return SQLITE_OK; - } - syncJournal(pPager); - rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage); - if( rc==SQLITE_OK ){ - pPager->dbSize = nPage; - } - return rc; -} - -/* -** Shutdown the page cache. Free all memory and close all files. -** -** If a transaction was in progress when this routine is called, that -** transaction is rolled back. All outstanding pages are invalidated -** and their memory is freed. Any attempt to use a page associated -** with this page cache after this function returns will likely -** result in a coredump. -*/ -int sqlitepager_close(Pager *pPager){ - PgHdr *pPg, *pNext; - switch( pPager->state ){ - case SQLITE_WRITELOCK: { - sqlitepager_rollback(pPager); - sqliteOsUnlock(&pPager->fd); - assert( pPager->journalOpen==0 ); - break; - } - case SQLITE_READLOCK: { - sqliteOsUnlock(&pPager->fd); - break; - } - default: { - /* Do nothing */ - break; - } - } - for(pPg=pPager->pAll; pPg; pPg=pNext){ - pNext = pPg->pNextAll; - sqliteFree(pPg); - } - sqliteOsClose(&pPager->fd); - assert( pPager->journalOpen==0 ); - /* Temp files are automatically deleted by the OS - ** if( pPager->tempFile ){ - ** sqliteOsDelete(pPager->zFilename); - ** } - */ - CLR_PAGER(pPager); - if( pPager->zFilename!=(char*)&pPager[1] ){ - assert( 0 ); /* Cannot happen */ - sqliteFree(pPager->zFilename); - sqliteFree(pPager->zJournal); - sqliteFree(pPager->zDirectory); - } - sqliteFree(pPager); - return SQLITE_OK; -} - -/* -** Return the page number for the given page data. -*/ -Pgno sqlitepager_pagenumber(void *pData){ - PgHdr *p = DATA_TO_PGHDR(pData); - return p->pgno; -} - -/* -** Increment the reference count for a page. If the page is -** currently on the freelist (the reference count is zero) then -** remove it from the freelist. -*/ -#define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++) -static void _page_ref(PgHdr *pPg){ - if( pPg->nRef==0 ){ - /* The page is currently on the freelist. Remove it. */ - if( pPg==pPg->pPager->pFirstSynced ){ - PgHdr *p = pPg->pNextFree; - while( p && p->needSync ){ p = p->pNextFree; } - pPg->pPager->pFirstSynced = p; - } - if( pPg->pPrevFree ){ - pPg->pPrevFree->pNextFree = pPg->pNextFree; - }else{ - pPg->pPager->pFirst = pPg->pNextFree; - } - if( pPg->pNextFree ){ - pPg->pNextFree->pPrevFree = pPg->pPrevFree; - }else{ - pPg->pPager->pLast = pPg->pPrevFree; - } - pPg->pPager->nRef++; - } - pPg->nRef++; - REFINFO(pPg); -} - -/* -** Increment the reference count for a page. The input pointer is -** a reference to the page data. -*/ -int sqlitepager_ref(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); - page_ref(pPg); - return SQLITE_OK; -} - -/* -** Sync the journal. In other words, make sure all the pages that have -** been written to the journal have actually reached the surface of the -** disk. It is not safe to modify the original database file until after -** the journal has been synced. If the original database is modified before -** the journal is synced and a power failure occurs, the unsynced journal -** data would be lost and we would be unable to completely rollback the -** database changes. Database corruption would occur. -** -** This routine also updates the nRec field in the header of the journal. -** (See comments on the pager_playback() routine for additional information.) -** If the sync mode is FULL, two syncs will occur. First the whole journal -** is synced, then the nRec field is updated, then a second sync occurs. -** -** For temporary databases, we do not care if we are able to rollback -** after a power failure, so sync occurs. -** -** This routine clears the needSync field of every page current held in -** memory. -*/ -static int syncJournal(Pager *pPager){ - PgHdr *pPg; - int rc = SQLITE_OK; - - /* Sync the journal before modifying the main database - ** (assuming there is a journal and it needs to be synced.) - */ - if( pPager->needSync ){ - if( !pPager->tempFile ){ - assert( pPager->journalOpen ); - /* assert( !pPager->noSync ); // noSync might be set if synchronous - ** was turned off after the transaction was started. Ticket #615 */ -#ifndef NDEBUG - { - /* Make sure the pPager->nRec counter we are keeping agrees - ** with the nRec computed from the size of the journal file. - */ - off_t hdrSz, pgSz, jSz; - hdrSz = JOURNAL_HDR_SZ(journal_format); - pgSz = JOURNAL_PG_SZ(journal_format); - rc = sqliteOsFileSize(&pPager->jfd, &jSz); - if( rc!=0 ) return rc; - assert( pPager->nRec*pgSz+hdrSz==jSz ); - } -#endif - if( journal_format>=3 ){ - /* Write the nRec value into the journal file header */ - off_t szJ; - if( pPager->fullSync ){ - TRACE1("SYNC\n"); - rc = sqliteOsSync(&pPager->jfd); - if( rc!=0 ) return rc; - } - sqliteOsSeek(&pPager->jfd, sizeof(aJournalMagic1)); - rc = write32bits(&pPager->jfd, pPager->nRec); - if( rc ) return rc; - szJ = JOURNAL_HDR_SZ(journal_format) + - pPager->nRec*JOURNAL_PG_SZ(journal_format); - sqliteOsSeek(&pPager->jfd, szJ); - } - TRACE1("SYNC\n"); - rc = sqliteOsSync(&pPager->jfd); - if( rc!=0 ) return rc; - pPager->journalStarted = 1; - } - pPager->needSync = 0; - - /* Erase the needSync flag from every page. - */ - for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ - pPg->needSync = 0; - } - pPager->pFirstSynced = pPager->pFirst; - } - -#ifndef NDEBUG - /* If the Pager.needSync flag is clear then the PgHdr.needSync - ** flag must also be clear for all pages. Verify that this - ** invariant is true. - */ - else{ - for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ - assert( pPg->needSync==0 ); - } - assert( pPager->pFirstSynced==pPager->pFirst ); - } -#endif - - return rc; -} - -/* -** Given a list of pages (connected by the PgHdr.pDirty pointer) write -** every one of those pages out to the database file and mark them all -** as clean. -*/ -static int pager_write_pagelist(PgHdr *pList){ - Pager *pPager; - int rc; - - if( pList==0 ) return SQLITE_OK; - pPager = pList->pPager; - while( pList ){ - assert( pList->dirty ); - sqliteOsSeek(&pPager->fd, (pList->pgno-1)*(off_t)SQLITE_PAGE_SIZE); - CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); - TRACE2("STORE %d\n", pList->pgno); - rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pList), SQLITE_PAGE_SIZE); - CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); - if( rc ) return rc; - pList->dirty = 0; - pList = pList->pDirty; - } - return SQLITE_OK; -} - -/* -** Collect every dirty page into a dirty list and -** return a pointer to the head of that list. All pages are -** collected even if they are still in use. -*/ -static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ - PgHdr *p, *pList; - pList = 0; - for(p=pPager->pAll; p; p=p->pNextAll){ - if( p->dirty ){ - p->pDirty = pList; - pList = p; - } - } - return pList; -} - -/* -** Acquire a page. -** -** A read lock on the disk file is obtained when the first page is acquired. -** This read lock is dropped when the last page is released. -** -** A _get works for any page number greater than 0. If the database -** file is smaller than the requested page, then no actual disk -** read occurs and the memory image of the page is initialized to -** all zeros. The extra data appended to a page is always initialized -** to zeros the first time a page is loaded into memory. -** -** The acquisition might fail for several reasons. In all cases, -** an appropriate error code is returned and *ppPage is set to NULL. -** -** See also sqlitepager_lookup(). Both this routine and _lookup() attempt -** to find a page in the in-memory cache first. If the page is not already -** in memory, this routine goes to disk to read it in whereas _lookup() -** just returns 0. This routine acquires a read-lock the first time it -** has to go to disk, and could also playback an old journal if necessary. -** Since _lookup() never goes to disk, it never has to deal with locks -** or journal files. -*/ -int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ - PgHdr *pPg; - int rc; - - /* Make sure we have not hit any critical errors. - */ - assert( pPager!=0 ); - assert( pgno!=0 ); - *ppPage = 0; - if( pPager->errMask & ~(PAGER_ERR_FULL) ){ - return pager_errcode(pPager); - } - - /* If this is the first page accessed, then get a read lock - ** on the database file. - */ - if( pPager->nRef==0 ){ - rc = sqliteOsReadLock(&pPager->fd); - if( rc!=SQLITE_OK ){ - return rc; - } - pPager->state = SQLITE_READLOCK; - - /* If a journal file exists, try to play it back. - */ - if( pPager->useJournal && sqliteOsFileExists(pPager->zJournal) ){ - int rc; - - /* Get a write lock on the database - */ - rc = sqliteOsWriteLock(&pPager->fd); - if( rc!=SQLITE_OK ){ - if( sqliteOsUnlock(&pPager->fd)!=SQLITE_OK ){ - /* This should never happen! */ - rc = SQLITE_INTERNAL; - } - return rc; - } - pPager->state = SQLITE_WRITELOCK; - - /* Open the journal for reading only. Return SQLITE_BUSY if - ** we are unable to open the journal file. - ** - ** The journal file does not need to be locked itself. The - ** journal file is never open unless the main database file holds - ** a write lock, so there is never any chance of two or more - ** processes opening the journal at the same time. - */ - rc = sqliteOsOpenReadOnly(pPager->zJournal, &pPager->jfd); - if( rc!=SQLITE_OK ){ - rc = sqliteOsUnlock(&pPager->fd); - assert( rc==SQLITE_OK ); - return SQLITE_BUSY; - } - pPager->journalOpen = 1; - pPager->journalStarted = 0; - - /* Playback and delete the journal. Drop the database write - ** lock and reacquire the read lock. - */ - rc = pager_playback(pPager, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - } - pPg = 0; - }else{ - /* Search for page in cache */ - pPg = pager_lookup(pPager, pgno); - } - if( pPg==0 ){ - /* The requested page is not in the page cache. */ - int h; - pPager->nMiss++; - if( pPager->nPagemxPage || pPager->pFirst==0 ){ - /* Create a new page */ - pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE - + sizeof(u32) + pPager->nExtra ); - if( pPg==0 ){ - pager_unwritelock(pPager); - pPager->errMask |= PAGER_ERR_MEM; - return SQLITE_NOMEM; - } - memset(pPg, 0, sizeof(*pPg)); - pPg->pPager = pPager; - pPg->pNextAll = pPager->pAll; - if( pPager->pAll ){ - pPager->pAll->pPrevAll = pPg; - } - pPg->pPrevAll = 0; - pPager->pAll = pPg; - pPager->nPage++; - }else{ - /* Find a page to recycle. Try to locate a page that does not - ** require us to do an fsync() on the journal. - */ - pPg = pPager->pFirstSynced; - - /* If we could not find a page that does not require an fsync() - ** on the journal file then fsync the journal file. This is a - ** very slow operation, so we work hard to avoid it. But sometimes - ** it can't be helped. - */ - if( pPg==0 ){ - int rc = syncJournal(pPager); - if( rc!=0 ){ - sqlitepager_rollback(pPager); - return SQLITE_IOERR; - } - pPg = pPager->pFirst; - } - assert( pPg->nRef==0 ); - - /* Write the page to the database file if it is dirty. - */ - if( pPg->dirty ){ - assert( pPg->needSync==0 ); - pPg->pDirty = 0; - rc = pager_write_pagelist( pPg ); - if( rc!=SQLITE_OK ){ - sqlitepager_rollback(pPager); - return SQLITE_IOERR; - } - } - assert( pPg->dirty==0 ); - - /* If the page we are recycling is marked as alwaysRollback, then - ** set the global alwaysRollback flag, thus disabling the - ** sqlite_dont_rollback() optimization for the rest of this transaction. - ** It is necessary to do this because the page marked alwaysRollback - ** might be reloaded at a later time but at that point we won't remember - ** that is was marked alwaysRollback. This means that all pages must - ** be marked as alwaysRollback from here on out. - */ - if( pPg->alwaysRollback ){ - pPager->alwaysRollback = 1; - } - - /* Unlink the old page from the free list and the hash table - */ - if( pPg==pPager->pFirstSynced ){ - PgHdr *p = pPg->pNextFree; - while( p && p->needSync ){ p = p->pNextFree; } - pPager->pFirstSynced = p; - } - if( pPg->pPrevFree ){ - pPg->pPrevFree->pNextFree = pPg->pNextFree; - }else{ - assert( pPager->pFirst==pPg ); - pPager->pFirst = pPg->pNextFree; - } - if( pPg->pNextFree ){ - pPg->pNextFree->pPrevFree = pPg->pPrevFree; - }else{ - assert( pPager->pLast==pPg ); - pPager->pLast = pPg->pPrevFree; - } - pPg->pNextFree = pPg->pPrevFree = 0; - if( pPg->pNextHash ){ - pPg->pNextHash->pPrevHash = pPg->pPrevHash; - } - if( pPg->pPrevHash ){ - pPg->pPrevHash->pNextHash = pPg->pNextHash; - }else{ - h = pager_hash(pPg->pgno); - assert( pPager->aHash[h]==pPg ); - pPager->aHash[h] = pPg->pNextHash; - } - pPg->pNextHash = pPg->pPrevHash = 0; - pPager->nOvfl++; - } - pPg->pgno = pgno; - if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ - sqliteCheckMemory(pPager->aInJournal, pgno/8); - assert( pPager->journalOpen ); - pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; - pPg->needSync = 0; - }else{ - pPg->inJournal = 0; - pPg->needSync = 0; - } - if( pPager->aInCkpt && (int)pgno<=pPager->ckptSize - && (pPager->aInCkpt[pgno/8] & (1<<(pgno&7)))!=0 ){ - page_add_to_ckpt_list(pPg); - }else{ - page_remove_from_ckpt_list(pPg); - } - pPg->dirty = 0; - pPg->nRef = 1; - REFINFO(pPg); - pPager->nRef++; - h = pager_hash(pgno); - pPg->pNextHash = pPager->aHash[h]; - pPager->aHash[h] = pPg; - if( pPg->pNextHash ){ - assert( pPg->pNextHash->pPrevHash==0 ); - pPg->pNextHash->pPrevHash = pPg; - } - if( pPager->nExtra>0 ){ - memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); - } - if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager); - if( pPager->errMask!=0 ){ - sqlitepager_unref(PGHDR_TO_DATA(pPg)); - rc = pager_errcode(pPager); - return rc; - } - if( pPager->dbSize<(int)pgno ){ - memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); - }else{ - int rc; - sqliteOsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE); - rc = sqliteOsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE); - TRACE2("FETCH %d\n", pPg->pgno); - CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); - if( rc!=SQLITE_OK ){ - off_t fileSize; - if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK - || fileSize>=pgno*SQLITE_PAGE_SIZE ){ - sqlitepager_unref(PGHDR_TO_DATA(pPg)); - return rc; - }else{ - memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); - } - } - } - }else{ - /* The requested page is in the page cache. */ - pPager->nHit++; - page_ref(pPg); - } - *ppPage = PGHDR_TO_DATA(pPg); - return SQLITE_OK; -} - -/* -** Acquire a page if it is already in the in-memory cache. Do -** not read the page from disk. Return a pointer to the page, -** or 0 if the page is not in cache. -** -** See also sqlitepager_get(). The difference between this routine -** and sqlitepager_get() is that _get() will go to the disk and read -** in the page if the page is not already in cache. This routine -** returns NULL if the page is not in cache or if a disk I/O error -** has ever happened. -*/ -void *sqlitepager_lookup(Pager *pPager, Pgno pgno){ - PgHdr *pPg; - - assert( pPager!=0 ); - assert( pgno!=0 ); - if( pPager->errMask & ~(PAGER_ERR_FULL) ){ - return 0; - } - /* if( pPager->nRef==0 ){ - ** return 0; - ** } - */ - pPg = pager_lookup(pPager, pgno); - if( pPg==0 ) return 0; - page_ref(pPg); - return PGHDR_TO_DATA(pPg); -} - -/* -** Release a page. -** -** If the number of references to the page drop to zero, then the -** page is added to the LRU list. When all references to all pages -** are released, a rollback occurs and the lock on the database is -** removed. -*/ -int sqlitepager_unref(void *pData){ - PgHdr *pPg; - - /* Decrement the reference count for this page - */ - pPg = DATA_TO_PGHDR(pData); - assert( pPg->nRef>0 ); - pPg->nRef--; - REFINFO(pPg); - - /* When the number of references to a page reach 0, call the - ** destructor and add the page to the freelist. - */ - if( pPg->nRef==0 ){ - Pager *pPager; - pPager = pPg->pPager; - pPg->pNextFree = 0; - pPg->pPrevFree = pPager->pLast; - pPager->pLast = pPg; - if( pPg->pPrevFree ){ - pPg->pPrevFree->pNextFree = pPg; - }else{ - pPager->pFirst = pPg; - } - if( pPg->needSync==0 && pPager->pFirstSynced==0 ){ - pPager->pFirstSynced = pPg; - } - if( pPager->xDestructor ){ - pPager->xDestructor(pData); - } - - /* When all pages reach the freelist, drop the read lock from - ** the database file. - */ - pPager->nRef--; - assert( pPager->nRef>=0 ); - if( pPager->nRef==0 ){ - pager_reset(pPager); - } - } - return SQLITE_OK; -} - -/* -** Create a journal file for pPager. There should already be a write -** lock on the database file when this routine is called. -** -** Return SQLITE_OK if everything. Return an error code and release the -** write lock if anything goes wrong. -*/ -static int pager_open_journal(Pager *pPager){ - int rc; - assert( pPager->state==SQLITE_WRITELOCK ); - assert( pPager->journalOpen==0 ); - assert( pPager->useJournal ); - sqlitepager_pagecount(pPager); - pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); - if( pPager->aInJournal==0 ){ - sqliteOsReadLock(&pPager->fd); - pPager->state = SQLITE_READLOCK; - return SQLITE_NOMEM; - } - rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile); - if( rc!=SQLITE_OK ){ - sqliteFree(pPager->aInJournal); - pPager->aInJournal = 0; - sqliteOsReadLock(&pPager->fd); - pPager->state = SQLITE_READLOCK; - return SQLITE_CANTOPEN; - } - sqliteOsOpenDirectory(pPager->zDirectory, &pPager->jfd); - pPager->journalOpen = 1; - pPager->journalStarted = 0; - pPager->needSync = 0; - pPager->alwaysRollback = 0; - pPager->nRec = 0; - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); - return rc; - } - pPager->origDbSize = pPager->dbSize; - if( journal_format==JOURNAL_FORMAT_3 ){ - rc = sqliteOsWrite(&pPager->jfd, aJournalMagic3, sizeof(aJournalMagic3)); - if( rc==SQLITE_OK ){ - rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0); - } - if( rc==SQLITE_OK ){ - sqliteRandomness(sizeof(pPager->cksumInit), &pPager->cksumInit); - rc = write32bits(&pPager->jfd, pPager->cksumInit); - } - }else if( journal_format==JOURNAL_FORMAT_2 ){ - rc = sqliteOsWrite(&pPager->jfd, aJournalMagic2, sizeof(aJournalMagic2)); - }else{ - assert( journal_format==JOURNAL_FORMAT_1 ); - rc = sqliteOsWrite(&pPager->jfd, aJournalMagic1, sizeof(aJournalMagic1)); - } - if( rc==SQLITE_OK ){ - rc = write32bits(&pPager->jfd, pPager->dbSize); - } - if( pPager->ckptAutoopen && rc==SQLITE_OK ){ - rc = sqlitepager_ckpt_begin(pPager); - } - if( rc!=SQLITE_OK ){ - rc = pager_unwritelock(pPager); - if( rc==SQLITE_OK ){ - rc = SQLITE_FULL; - } - } - return rc; -} - -/* -** Acquire a write-lock on the database. The lock is removed when -** the any of the following happen: -** -** * sqlitepager_commit() is called. -** * sqlitepager_rollback() is called. -** * sqlitepager_close() is called. -** * sqlitepager_unref() is called to on every outstanding page. -** -** The parameter to this routine is a pointer to any open page of the -** database file. Nothing changes about the page - it is used merely -** to acquire a pointer to the Pager structure and as proof that there -** is already a read-lock on the database. -** -** A journal file is opened if this is not a temporary file. For -** temporary files, the opening of the journal file is deferred until -** there is an actual need to write to the journal. -** -** If the database is already write-locked, this routine is a no-op. -*/ -int sqlitepager_begin(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); - Pager *pPager = pPg->pPager; - int rc = SQLITE_OK; - assert( pPg->nRef>0 ); - assert( pPager->state!=SQLITE_UNLOCK ); - if( pPager->state==SQLITE_READLOCK ){ - assert( pPager->aInJournal==0 ); - rc = sqliteOsWriteLock(&pPager->fd); - if( rc!=SQLITE_OK ){ - return rc; - } - pPager->state = SQLITE_WRITELOCK; - pPager->dirtyFile = 0; - TRACE1("TRANSACTION\n"); - if( pPager->useJournal && !pPager->tempFile ){ - rc = pager_open_journal(pPager); - } - } - return rc; -} - -/* -** Mark a data page as writeable. The page is written into the journal -** if it is not there already. This routine must be called before making -** changes to a page. -** -** The first time this routine is called, the pager creates a new -** journal and acquires a write lock on the database. If the write -** lock could not be acquired, this routine returns SQLITE_BUSY. The -** calling routine must check for that return value and be careful not to -** change any page data until this routine returns SQLITE_OK. -** -** If the journal file could not be written because the disk is full, -** then this routine returns SQLITE_FULL and does an immediate rollback. -** All subsequent write attempts also return SQLITE_FULL until there -** is a call to sqlitepager_commit() or sqlitepager_rollback() to -** reset. -*/ -int sqlitepager_write(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); - Pager *pPager = pPg->pPager; - int rc = SQLITE_OK; - - /* Check for errors - */ - if( pPager->errMask ){ - return pager_errcode(pPager); - } - if( pPager->readOnly ){ - return SQLITE_PERM; - } - - /* Mark the page as dirty. If the page has already been written - ** to the journal then we can return right away. - */ - pPg->dirty = 1; - if( pPg->inJournal && (pPg->inCkpt || pPager->ckptInUse==0) ){ - pPager->dirtyFile = 1; - return SQLITE_OK; - } - - /* If we get this far, it means that the page needs to be - ** written to the transaction journal or the ckeckpoint journal - ** or both. - ** - ** First check to see that the transaction journal exists and - ** create it if it does not. - */ - assert( pPager->state!=SQLITE_UNLOCK ); - rc = sqlitepager_begin(pData); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pPager->state==SQLITE_WRITELOCK ); - if( !pPager->journalOpen && pPager->useJournal ){ - rc = pager_open_journal(pPager); - if( rc!=SQLITE_OK ) return rc; - } - assert( pPager->journalOpen || !pPager->useJournal ); - pPager->dirtyFile = 1; - - /* The transaction journal now exists and we have a write lock on the - ** main database file. Write the current page to the transaction - ** journal if it is not there already. - */ - if( !pPg->inJournal && pPager->useJournal ){ - if( (int)pPg->pgno <= pPager->origDbSize ){ - int szPg; - u32 saved; - if( journal_format>=JOURNAL_FORMAT_3 ){ - u32 cksum = pager_cksum(pPager, pPg->pgno, pData); - saved = *(u32*)PGHDR_TO_EXTRA(pPg); - store32bits(cksum, pPg, SQLITE_PAGE_SIZE); - szPg = SQLITE_PAGE_SIZE+8; - }else{ - szPg = SQLITE_PAGE_SIZE+4; - } - store32bits(pPg->pgno, pPg, -4); - CODEC(pPager, pData, pPg->pgno, 7); - rc = sqliteOsWrite(&pPager->jfd, &((char*)pData)[-4], szPg); - TRACE3("JOURNAL %d %d\n", pPg->pgno, pPg->needSync); - CODEC(pPager, pData, pPg->pgno, 0); - if( journal_format>=JOURNAL_FORMAT_3 ){ - *(u32*)PGHDR_TO_EXTRA(pPg) = saved; - } - if( rc!=SQLITE_OK ){ - sqlitepager_rollback(pPager); - pPager->errMask |= PAGER_ERR_FULL; - return rc; - } - pPager->nRec++; - assert( pPager->aInJournal!=0 ); - pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); - pPg->needSync = !pPager->noSync; - pPg->inJournal = 1; - if( pPager->ckptInUse ){ - pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); - page_add_to_ckpt_list(pPg); - } - }else{ - pPg->needSync = !pPager->journalStarted && !pPager->noSync; - TRACE3("APPEND %d %d\n", pPg->pgno, pPg->needSync); - } - if( pPg->needSync ){ - pPager->needSync = 1; - } - } - - /* If the checkpoint journal is open and the page is not in it, - ** then write the current page to the checkpoint journal. Note that - ** the checkpoint journal always uses the simplier format 2 that lacks - ** checksums. The header is also omitted from the checkpoint journal. - */ - if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ - assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); - store32bits(pPg->pgno, pPg, -4); - CODEC(pPager, pData, pPg->pgno, 7); - rc = sqliteOsWrite(&pPager->cpfd, &((char*)pData)[-4], SQLITE_PAGE_SIZE+4); - TRACE2("CKPT-JOURNAL %d\n", pPg->pgno); - CODEC(pPager, pData, pPg->pgno, 0); - if( rc!=SQLITE_OK ){ - sqlitepager_rollback(pPager); - pPager->errMask |= PAGER_ERR_FULL; - return rc; - } - pPager->ckptNRec++; - assert( pPager->aInCkpt!=0 ); - pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); - page_add_to_ckpt_list(pPg); - } - - /* Update the database size and return. - */ - if( pPager->dbSize<(int)pPg->pgno ){ - pPager->dbSize = pPg->pgno; - } - return rc; -} - -/* -** Return TRUE if the page given in the argument was previously passed -** to sqlitepager_write(). In other words, return TRUE if it is ok -** to change the content of the page. -*/ -int sqlitepager_iswriteable(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); - return pPg->dirty; -} - -/* -** Replace the content of a single page with the information in the third -** argument. -*/ -int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){ - void *pPage; - int rc; - - rc = sqlitepager_get(pPager, pgno, &pPage); - if( rc==SQLITE_OK ){ - rc = sqlitepager_write(pPage); - if( rc==SQLITE_OK ){ - memcpy(pPage, pData, SQLITE_PAGE_SIZE); - } - sqlitepager_unref(pPage); - } - return rc; -} - -/* -** A call to this routine tells the pager that it is not necessary to -** write the information on page "pgno" back to the disk, even though -** that page might be marked as dirty. -** -** The overlying software layer calls this routine when all of the data -** on the given page is unused. The pager marks the page as clean so -** that it does not get written to disk. -** -** Tests show that this optimization, together with the -** sqlitepager_dont_rollback() below, more than double the speed -** of large INSERT operations and quadruple the speed of large DELETEs. -** -** When this routine is called, set the alwaysRollback flag to true. -** Subsequent calls to sqlitepager_dont_rollback() for the same page -** will thereafter be ignored. This is necessary to avoid a problem -** where a page with data is added to the freelist during one part of -** a transaction then removed from the freelist during a later part -** of the same transaction and reused for some other purpose. When it -** is first added to the freelist, this routine is called. When reused, -** the dont_rollback() routine is called. But because the page contains -** critical data, we still need to be sure it gets rolled back in spite -** of the dont_rollback() call. -*/ -void sqlitepager_dont_write(Pager *pPager, Pgno pgno){ - PgHdr *pPg; - - pPg = pager_lookup(pPager, pgno); - pPg->alwaysRollback = 1; - if( pPg && pPg->dirty ){ - if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){ - /* If this pages is the last page in the file and the file has grown - ** during the current transaction, then do NOT mark the page as clean. - ** When the database file grows, we must make sure that the last page - ** gets written at least once so that the disk file will be the correct - ** size. If you do not write this page and the size of the file - ** on the disk ends up being too small, that can lead to database - ** corruption during the next transaction. - */ - }else{ - TRACE2("DONT_WRITE %d\n", pgno); - pPg->dirty = 0; - } - } -} - -/* -** A call to this routine tells the pager that if a rollback occurs, -** it is not necessary to restore the data on the given page. This -** means that the pager does not have to record the given page in the -** rollback journal. -*/ -void sqlitepager_dont_rollback(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); - Pager *pPager = pPg->pPager; - - if( pPager->state!=SQLITE_WRITELOCK || pPager->journalOpen==0 ) return; - if( pPg->alwaysRollback || pPager->alwaysRollback ) return; - if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ - assert( pPager->aInJournal!=0 ); - pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); - pPg->inJournal = 1; - if( pPager->ckptInUse ){ - pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); - page_add_to_ckpt_list(pPg); - } - TRACE2("DONT_ROLLBACK %d\n", pPg->pgno); - } - if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ - assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); - assert( pPager->aInCkpt!=0 ); - pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); - page_add_to_ckpt_list(pPg); - } -} - -/* -** Commit all changes to the database and release the write lock. -** -** If the commit fails for any reason, a rollback attempt is made -** and an error code is returned. If the commit worked, SQLITE_OK -** is returned. -*/ -int sqlitepager_commit(Pager *pPager){ - int rc; - PgHdr *pPg; - - if( pPager->errMask==PAGER_ERR_FULL ){ - rc = sqlitepager_rollback(pPager); - if( rc==SQLITE_OK ){ - rc = SQLITE_FULL; - } - return rc; - } - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); - return rc; - } - if( pPager->state!=SQLITE_WRITELOCK ){ - return SQLITE_ERROR; - } - TRACE1("COMMIT\n"); - if( pPager->dirtyFile==0 ){ - /* Exit early (without doing the time-consuming sqliteOsSync() calls) - ** if there have been no changes to the database file. */ - assert( pPager->needSync==0 ); - rc = pager_unwritelock(pPager); - pPager->dbSize = -1; - return rc; - } - assert( pPager->journalOpen ); - rc = syncJournal(pPager); - if( rc!=SQLITE_OK ){ - goto commit_abort; - } - pPg = pager_get_all_dirty_pages(pPager); - if( pPg ){ - rc = pager_write_pagelist(pPg); - if( rc || (!pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK) ){ - goto commit_abort; - } - } - rc = pager_unwritelock(pPager); - pPager->dbSize = -1; - return rc; - - /* Jump here if anything goes wrong during the commit process. - */ -commit_abort: - rc = sqlitepager_rollback(pPager); - if( rc==SQLITE_OK ){ - rc = SQLITE_FULL; - } - return rc; -} - -/* -** Rollback all changes. The database falls back to read-only mode. -** All in-memory cache pages revert to their original data contents. -** The journal is deleted. -** -** This routine cannot fail unless some other process is not following -** the correct locking protocol (SQLITE_PROTOCOL) or unless some other -** process is writing trash into the journal file (SQLITE_CORRUPT) or -** unless a prior malloc() failed (SQLITE_NOMEM). Appropriate error -** codes are returned for all these occasions. Otherwise, -** SQLITE_OK is returned. -*/ -int sqlitepager_rollback(Pager *pPager){ - int rc; - TRACE1("ROLLBACK\n"); - if( !pPager->dirtyFile || !pPager->journalOpen ){ - rc = pager_unwritelock(pPager); - pPager->dbSize = -1; - return rc; - } - - if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ - if( pPager->state>=SQLITE_WRITELOCK ){ - pager_playback(pPager, 1); - } - return pager_errcode(pPager); - } - if( pPager->state!=SQLITE_WRITELOCK ){ - return SQLITE_OK; - } - rc = pager_playback(pPager, 1); - if( rc!=SQLITE_OK ){ - rc = SQLITE_CORRUPT; - pPager->errMask |= PAGER_ERR_CORRUPT; - } - pPager->dbSize = -1; - return rc; -} - -/* -** Return TRUE if the database file is opened read-only. Return FALSE -** if the database is (in theory) writable. -*/ -int sqlitepager_isreadonly(Pager *pPager){ - return pPager->readOnly; -} - -/* -** This routine is used for testing and analysis only. -*/ -int *sqlitepager_stats(Pager *pPager){ - static int a[9]; - a[0] = pPager->nRef; - a[1] = pPager->nPage; - a[2] = pPager->mxPage; - a[3] = pPager->dbSize; - a[4] = pPager->state; - a[5] = pPager->errMask; - a[6] = pPager->nHit; - a[7] = pPager->nMiss; - a[8] = pPager->nOvfl; - return a; -} - -/* -** Set the checkpoint. -** -** This routine should be called with the transaction journal already -** open. A new checkpoint journal is created that can be used to rollback -** changes of a single SQL command within a larger transaction. -*/ -int sqlitepager_ckpt_begin(Pager *pPager){ - int rc; - char zTemp[SQLITE_TEMPNAME_SIZE]; - if( !pPager->journalOpen ){ - pPager->ckptAutoopen = 1; - return SQLITE_OK; - } - assert( pPager->journalOpen ); - assert( !pPager->ckptInUse ); - pPager->aInCkpt = sqliteMalloc( pPager->dbSize/8 + 1 ); - if( pPager->aInCkpt==0 ){ - sqliteOsReadLock(&pPager->fd); - return SQLITE_NOMEM; - } -#ifndef NDEBUG - rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize); - if( rc ) goto ckpt_begin_failed; - assert( pPager->ckptJSize == - pPager->nRec*JOURNAL_PG_SZ(journal_format)+JOURNAL_HDR_SZ(journal_format) ); -#endif - pPager->ckptJSize = pPager->nRec*JOURNAL_PG_SZ(journal_format) - + JOURNAL_HDR_SZ(journal_format); - pPager->ckptSize = pPager->dbSize; - if( !pPager->ckptOpen ){ - rc = sqlitepager_opentemp(zTemp, &pPager->cpfd); - if( rc ) goto ckpt_begin_failed; - pPager->ckptOpen = 1; - pPager->ckptNRec = 0; - } - pPager->ckptInUse = 1; - return SQLITE_OK; - -ckpt_begin_failed: - if( pPager->aInCkpt ){ - sqliteFree(pPager->aInCkpt); - pPager->aInCkpt = 0; - } - return rc; -} - -/* -** Commit a checkpoint. -*/ -int sqlitepager_ckpt_commit(Pager *pPager){ - if( pPager->ckptInUse ){ - PgHdr *pPg, *pNext; - sqliteOsSeek(&pPager->cpfd, 0); - /* sqliteOsTruncate(&pPager->cpfd, 0); */ - pPager->ckptNRec = 0; - pPager->ckptInUse = 0; - sqliteFree( pPager->aInCkpt ); - pPager->aInCkpt = 0; - for(pPg=pPager->pCkpt; pPg; pPg=pNext){ - pNext = pPg->pNextCkpt; - assert( pPg->inCkpt ); - pPg->inCkpt = 0; - pPg->pPrevCkpt = pPg->pNextCkpt = 0; - } - pPager->pCkpt = 0; - } - pPager->ckptAutoopen = 0; - return SQLITE_OK; -} - -/* -** Rollback a checkpoint. -*/ -int sqlitepager_ckpt_rollback(Pager *pPager){ - int rc; - if( pPager->ckptInUse ){ - rc = pager_ckpt_playback(pPager); - sqlitepager_ckpt_commit(pPager); - }else{ - rc = SQLITE_OK; - } - pPager->ckptAutoopen = 0; - return rc; -} - -/* -** Return the full pathname of the database file. -*/ -const char *sqlitepager_filename(Pager *pPager){ - return pPager->zFilename; -} - -/* -** Set the codec for this pager -*/ -void sqlitepager_set_codec( - Pager *pPager, - void (*xCodec)(void*,void*,Pgno,int), - void *pCodecArg -){ - pPager->xCodec = xCodec; - pPager->pCodecArg = pCodecArg; -} - -#ifdef SQLITE_TEST -/* -** Print a listing of all referenced pages and their ref count. -*/ -void sqlitepager_refdump(Pager *pPager){ - PgHdr *pPg; - for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ - if( pPg->nRef<=0 ) continue; - printf("PAGE %3d addr=0x%08x nRef=%d\n", - pPg->pgno, (int)PGHDR_TO_DATA(pPg), pPg->nRef); - } -} -#endif diff --git a/dbLifeLog/DBD-SQLite2-0.33/pager.h b/dbLifeLog/DBD-SQLite2-0.33/pager.h deleted file mode 100644 index 1496dcf..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/pager.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the sqlite page cache -** subsystem. The page cache subsystem reads and writes a file a page -** at a time and provides a journal for rollback. -** -** @(#) $Id: pager.h,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ -*/ - -/* -** The size of one page -** -** You can change this value to another (reasonable) value you want. -** It need not be a power of two, though the interface to the disk -** will likely be faster if it is. -** -** Experiments show that a page size of 1024 gives the best speed -** for common usages. The speed differences for different sizes -** such as 512, 2048, 4096, an so forth, is minimal. Note, however, -** that changing the page size results in a completely imcompatible -** file format. -*/ -#ifndef SQLITE_PAGE_SIZE -#define SQLITE_PAGE_SIZE 1024 -#endif - -/* -** Number of extra bytes of data allocated at the end of each page and -** stored on disk but not used by the higher level btree layer. Changing -** this value results in a completely incompatible file format. -*/ -#ifndef SQLITE_PAGE_RESERVE -#define SQLITE_PAGE_RESERVE 0 -#endif - -/* -** The total number of usable bytes stored on disk for each page. -** The usable bytes come at the beginning of the page and the reserve -** bytes come at the end. -*/ -#define SQLITE_USABLE_SIZE (SQLITE_PAGE_SIZE-SQLITE_PAGE_RESERVE) - -/* -** Maximum number of pages in one database. (This is a limitation of -** imposed by 4GB files size limits.) -*/ -#define SQLITE_MAX_PAGE 1073741823 - -/* -** The type used to represent a page number. The first page in a file -** is called page 1. 0 is used to represent "not a page". -*/ -typedef unsigned int Pgno; - -/* -** Each open file is managed by a separate instance of the "Pager" structure. -*/ -typedef struct Pager Pager; - -/* -** See source code comments for a detailed description of the following -** routines: -*/ -int sqlitepager_open(Pager **ppPager, const char *zFilename, - int nPage, int nExtra, int useJournal); -void sqlitepager_set_destructor(Pager*, void(*)(void*)); -void sqlitepager_set_cachesize(Pager*, int); -int sqlitepager_close(Pager *pPager); -int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage); -void *sqlitepager_lookup(Pager *pPager, Pgno pgno); -int sqlitepager_ref(void*); -int sqlitepager_unref(void*); -Pgno sqlitepager_pagenumber(void*); -int sqlitepager_write(void*); -int sqlitepager_iswriteable(void*); -int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void*); -int sqlitepager_pagecount(Pager*); -int sqlitepager_truncate(Pager*,Pgno); -int sqlitepager_begin(void*); -int sqlitepager_commit(Pager*); -int sqlitepager_rollback(Pager*); -int sqlitepager_isreadonly(Pager*); -int sqlitepager_ckpt_begin(Pager*); -int sqlitepager_ckpt_commit(Pager*); -int sqlitepager_ckpt_rollback(Pager*); -void sqlitepager_dont_rollback(void*); -void sqlitepager_dont_write(Pager*, Pgno); -int *sqlitepager_stats(Pager*); -void sqlitepager_set_safety_level(Pager*,int); -const char *sqlitepager_filename(Pager*); -int sqlitepager_rename(Pager*, const char *zNewName); -void sqlitepager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*); - -#ifdef SQLITE_TEST -void sqlitepager_refdump(Pager*); -int pager_refinfo_enable; -int journal_format; -#endif diff --git a/dbLifeLog/DBD-SQLite2-0.33/pager.o b/dbLifeLog/DBD-SQLite2-0.33/pager.o deleted file mode 100644 index 6ac903944958f42c8a7349ba3f684d7a170aa682..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19384 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 X$0wPtH2#}+paIXvG&$wT9{>LXXh)T5 diff --git a/dbLifeLog/DBD-SQLite2-0.33/parse.c b/dbLifeLog/DBD-SQLite2-0.33/parse.c deleted file mode 100644 index c76507c..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/parse.c +++ /dev/null @@ -1,4035 +0,0 @@ -/* Driver template for the LEMON parser generator. -** The author disclaims copyright to this source code. -*/ -/* First off, code is include which follows the "include" declaration -** in the input file. */ -#include -#line 33 "parse.y" - -#include "sqliteInt.h" -#include "parse.h" - -/* -** An instance of this structure holds information about the -** LIMIT clause of a SELECT statement. -*/ -struct LimitVal { - int limit; /* The LIMIT value. -1 if there is no limit */ - int offset; /* The OFFSET. 0 if there is none */ -}; - -/* -** An instance of the following structure describes the event of a -** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, -** TK_DELETE, or TK_INSTEAD. If the event is of the form -** -** UPDATE ON (a,b,c) -** -** Then the "b" IdList records the list "a,b,c". -*/ -struct TrigEvent { int a; IdList * b; }; - - -#line 34 "parse.c" -/* Next is all token values, in a form suitable for use by makeheaders. -** This section will be null unless lemon is run with the -m switch. -*/ -/* -** These constants (all generated automatically by the parser generator) -** specify the various kinds of tokens (terminals) that the parser -** understands. -** -** Each symbol here is a terminal symbol in the grammar. -*/ -/* Make sure the INTERFACE macro is defined. -*/ -#ifndef INTERFACE -# define INTERFACE 1 -#endif -/* The next thing included is series of defines which control -** various aspects of the generated parser. -** YYCODETYPE is the data type used for storing terminal -** and nonterminal numbers. "unsigned char" is -** used if there are fewer than 250 terminals -** and nonterminals. "int" is used otherwise. -** YYNOCODE is a number of type YYCODETYPE which corresponds -** to no legal terminal or nonterminal number. This -** number is used to fill in empty slots of the hash -** table. -** YYFALLBACK If defined, this indicates that one or more tokens -** have fall-back values which should be used if the -** original value of the token will not parse. -** YYACTIONTYPE is the data type used for storing terminal -** and nonterminal numbers. "unsigned char" is -** used if there are fewer than 250 rules and -** states combined. "int" is used otherwise. -** sqliteParserTOKENTYPE is the data type used for minor tokens given -** directly to the parser from the tokenizer. -** YYMINORTYPE is the data type used for all minor tokens. -** This is typically a union of many types, one of -** which is sqliteParserTOKENTYPE. The entry in the union -** for base tokens is called "yy0". -** YYSTACKDEPTH is the maximum depth of the parser's stack. -** sqliteParserARG_SDECL A static variable declaration for the %extra_argument -** sqliteParserARG_PDECL A parameter declaration for the %extra_argument -** sqliteParserARG_STORE Code to store %extra_argument into yypParser -** sqliteParserARG_FETCH Code to extract %extra_argument from yypParser -** YYNSTATE the combined number of states. -** YYNRULE the number of rules in the grammar -** YYERRORSYMBOL is the code number of the error symbol. If not -** defined, then do no error processing. -*/ -/*  */ -#define YYCODETYPE unsigned char -#define YYNOCODE 221 -#define YYACTIONTYPE unsigned short int -#define sqliteParserTOKENTYPE Token -typedef union { - sqliteParserTOKENTYPE yy0; - TriggerStep * yy19; - struct LimitVal yy124; - Select* yy179; - Expr * yy182; - Expr* yy242; - struct TrigEvent yy290; - Token yy298; - SrcList* yy307; - IdList* yy320; - ExprList* yy322; - int yy372; - struct {int value; int mask;} yy407; - int yy441; -} YYMINORTYPE; -#define YYSTACKDEPTH 100 -#define sqliteParserARG_SDECL Parse *pParse; -#define sqliteParserARG_PDECL ,Parse *pParse -#define sqliteParserARG_FETCH Parse *pParse = yypParser->pParse -#define sqliteParserARG_STORE yypParser->pParse = pParse -#define YYNSTATE 563 -#define YYNRULE 293 -#define YYERRORSYMBOL 131 -#define YYERRSYMDT yy441 -#define YYFALLBACK 1 -#define YY_NO_ACTION (YYNSTATE+YYNRULE+2) -#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) -#define YY_ERROR_ACTION (YYNSTATE+YYNRULE) - -/* Next are that tables used to determine what action to take based on the -** current state and lookahead token. These tables are used to implement -** functions that take a state number and lookahead value and return an -** action integer. -** -** Suppose the action integer is N. Then the action is determined as -** follows -** -** 0 <= N < YYNSTATE Shift N. That is, push the lookahead -** token onto the stack and goto state N. -** -** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. -** -** N == YYNSTATE+YYNRULE A syntax error has occurred. -** -** N == YYNSTATE+YYNRULE+1 The parser accepts its input. -** -** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused -** slots in the yy_action[] table. -** -** The action table is constructed as a single large table named yy_action[]. -** Given state S and lookahead X, the action is computed as -** -** yy_action[ yy_shift_ofst[S] + X ] -** -** If the index value yy_shift_ofst[S]+X is out of range or if the value -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] -** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that yy_default[S] should be used instead. -** -** The formula above is for computing the action when the lookahead is -** a terminal symbol. If the lookahead is a non-terminal (as occurs after -** a reduce action) then the yy_reduce_ofst[] array is used in place of -** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of -** YY_SHIFT_USE_DFLT. -** -** The following are the tables generated in this section: -** -** yy_action[] A single table containing all actions. -** yy_lookahead[] A table containing the lookahead for each entry in -** yy_action. Used to detect hash collisions. -** yy_shift_ofst[] For each state, the offset into yy_action for -** shifting terminals. -** yy_reduce_ofst[] For each state, the offset into yy_action for -** shifting non-terminals after a reduce. -** yy_default[] Default action for each state. -*/ -static YYACTIONTYPE yy_action[] = { - /* 0 */ 264, 106, 262, 119, 123, 117, 121, 129, 131, 133, - /* 10 */ 135, 144, 146, 148, 150, 152, 154, 844, 426, 174, - /* 20 */ 143, 425, 2, 3, 839, 142, 129, 131, 133, 135, - /* 30 */ 144, 146, 148, 150, 152, 154, 247, 837, 427, 115, - /* 40 */ 104, 139, 127, 125, 156, 161, 157, 162, 166, 119, - /* 50 */ 123, 117, 121, 129, 131, 133, 135, 144, 146, 148, - /* 60 */ 150, 152, 154, 448, 361, 218, 263, 143, 363, 369, - /* 70 */ 374, 137, 142, 144, 146, 148, 150, 152, 154, 377, - /* 80 */ 857, 1, 562, 3, 396, 327, 115, 104, 139, 127, - /* 90 */ 125, 156, 161, 157, 162, 166, 119, 123, 117, 121, - /* 100 */ 129, 131, 133, 135, 144, 146, 148, 150, 152, 154, - /* 110 */ 482, 454, 444, 106, 143, 169, 20, 171, 172, 142, - /* 120 */ 310, 73, 4, 6, 402, 68, 398, 29, 248, 64, - /* 130 */ 46, 174, 497, 115, 104, 139, 127, 125, 156, 161, - /* 140 */ 157, 162, 166, 119, 123, 117, 121, 129, 131, 133, - /* 150 */ 135, 144, 146, 148, 150, 152, 154, 69, 193, 65, - /* 160 */ 101, 44, 54, 60, 62, 308, 331, 244, 175, 106, - /* 170 */ 20, 357, 333, 173, 640, 70, 359, 219, 36, 37, - /* 180 */ 21, 22, 510, 143, 181, 179, 303, 299, 142, 31, - /* 190 */ 20, 392, 177, 66, 67, 111, 358, 390, 112, 105, - /* 200 */ 69, 191, 115, 104, 139, 127, 125, 156, 161, 157, - /* 210 */ 162, 166, 119, 123, 117, 121, 129, 131, 133, 135, - /* 220 */ 144, 146, 148, 150, 152, 154, 388, 312, 73, 688, - /* 230 */ 306, 113, 183, 387, 21, 22, 230, 361, 52, 106, - /* 240 */ 20, 363, 369, 374, 361, 544, 542, 53, 363, 369, - /* 250 */ 374, 143, 377, 591, 21, 22, 142, 212, 338, 377, - /* 260 */ 169, 38, 171, 172, 356, 348, 535, 46, 534, 792, - /* 270 */ 115, 104, 139, 127, 125, 156, 161, 157, 162, 166, - /* 280 */ 119, 123, 117, 121, 129, 131, 133, 135, 144, 146, - /* 290 */ 148, 150, 152, 154, 790, 41, 336, 298, 44, 54, - /* 300 */ 60, 62, 308, 331, 21, 22, 197, 167, 20, 333, - /* 310 */ 58, 20, 395, 340, 343, 201, 169, 809, 171, 172, - /* 320 */ 59, 143, 337, 311, 339, 281, 142, 346, 347, 20, - /* 330 */ 205, 20, 639, 195, 35, 536, 537, 538, 842, 45, - /* 340 */ 115, 104, 139, 127, 125, 156, 161, 157, 162, 166, - /* 350 */ 119, 123, 117, 121, 129, 131, 133, 135, 144, 146, - /* 360 */ 148, 150, 152, 154, 300, 276, 148, 150, 152, 154, - /* 370 */ 71, 106, 21, 22, 430, 21, 22, 20, 443, 791, - /* 380 */ 441, 106, 40, 335, 169, 143, 171, 172, 330, 305, - /* 390 */ 142, 84, 86, 21, 22, 21, 22, 10, 572, 174, - /* 400 */ 254, 18, 83, 69, 115, 104, 139, 127, 125, 156, - /* 410 */ 161, 157, 162, 166, 119, 123, 117, 121, 129, 131, - /* 420 */ 133, 135, 144, 146, 148, 150, 152, 154, 467, 106, - /* 430 */ 661, 275, 143, 720, 295, 301, 169, 142, 171, 172, - /* 440 */ 539, 21, 22, 487, 449, 219, 459, 103, 232, 451, - /* 450 */ 282, 115, 104, 139, 127, 125, 156, 161, 157, 162, - /* 460 */ 166, 119, 123, 117, 121, 129, 131, 133, 135, 144, - /* 470 */ 146, 148, 150, 152, 154, 69, 417, 419, 418, 143, - /* 480 */ 95, 237, 312, 494, 142, 489, 47, 283, 259, 75, - /* 490 */ 10, 68, 189, 284, 209, 64, 289, 49, 115, 104, - /* 500 */ 139, 127, 125, 156, 161, 157, 162, 166, 119, 123, - /* 510 */ 117, 121, 129, 131, 133, 135, 144, 146, 148, 150, - /* 520 */ 152, 154, 196, 297, 193, 357, 429, 296, 169, 32, - /* 530 */ 171, 172, 391, 37, 175, 169, 276, 171, 172, 313, - /* 540 */ 316, 323, 325, 663, 106, 689, 245, 251, 143, 651, - /* 550 */ 181, 179, 292, 142, 386, 583, 491, 690, 177, 66, - /* 560 */ 67, 111, 184, 437, 112, 105, 213, 115, 164, 139, - /* 570 */ 127, 125, 156, 161, 157, 162, 166, 119, 123, 117, - /* 580 */ 121, 129, 131, 133, 135, 144, 146, 148, 150, 152, - /* 590 */ 154, 315, 726, 20, 106, 143, 333, 113, 183, 563, - /* 600 */ 142, 43, 278, 440, 170, 185, 330, 666, 560, 561, - /* 610 */ 249, 259, 103, 253, 115, 104, 139, 127, 125, 156, - /* 620 */ 161, 157, 162, 166, 119, 123, 117, 121, 129, 131, - /* 630 */ 133, 135, 144, 146, 148, 150, 152, 154, 800, 10, - /* 640 */ 252, 169, 143, 171, 172, 445, 97, 142, 560, 561, - /* 650 */ 216, 221, 217, 169, 313, 171, 172, 21, 22, 42, - /* 660 */ 159, 115, 227, 139, 127, 125, 156, 161, 157, 162, - /* 670 */ 166, 119, 123, 117, 121, 129, 131, 133, 135, 144, - /* 680 */ 146, 148, 150, 152, 154, 256, 73, 106, 816, 143, - /* 690 */ 169, 158, 171, 172, 142, 234, 397, 217, 545, 475, - /* 700 */ 273, 302, 274, 217, 266, 481, 315, 96, 653, 104, - /* 710 */ 139, 127, 125, 156, 161, 157, 162, 166, 119, 123, - /* 720 */ 117, 121, 129, 131, 133, 135, 144, 146, 148, 150, - /* 730 */ 152, 154, 106, 349, 291, 262, 143, 262, 264, 74, - /* 740 */ 262, 142, 533, 464, 320, 477, 319, 329, 341, 274, - /* 750 */ 481, 342, 137, 415, 416, 321, 266, 139, 127, 125, - /* 760 */ 156, 161, 157, 162, 166, 119, 123, 117, 121, 129, - /* 770 */ 131, 133, 135, 144, 146, 148, 150, 152, 154, 7, - /* 780 */ 322, 23, 25, 27, 394, 68, 267, 13, 393, 64, - /* 790 */ 518, 251, 106, 836, 344, 548, 14, 345, 458, 263, - /* 800 */ 520, 263, 106, 91, 263, 557, 266, 314, 168, 106, - /* 810 */ 462, 15, 443, 69, 16, 231, 276, 106, 193, 531, - /* 820 */ 174, 448, 276, 106, 276, 17, 529, 174, 175, 318, - /* 830 */ 106, 89, 106, 69, 276, 114, 286, 69, 68, 399, - /* 840 */ 69, 116, 64, 328, 181, 179, 106, 106, 118, 366, - /* 850 */ 163, 272, 177, 66, 67, 111, 215, 253, 112, 105, - /* 860 */ 276, 371, 467, 233, 120, 375, 219, 143, 498, 503, - /* 870 */ 444, 193, 142, 219, 486, 720, 401, 73, 453, 73, - /* 880 */ 420, 175, 278, 451, 252, 400, 106, 380, 278, 68, - /* 890 */ 278, 113, 183, 64, 225, 229, 106, 181, 179, 106, - /* 900 */ 278, 69, 106, 106, 122, 177, 66, 67, 111, 411, - /* 910 */ 106, 112, 105, 106, 124, 106, 106, 126, 106, 224, - /* 920 */ 128, 130, 193, 106, 106, 106, 278, 351, 132, 352, - /* 930 */ 831, 134, 175, 136, 138, 422, 141, 106, 367, 376, - /* 940 */ 274, 145, 147, 149, 113, 183, 793, 690, 181, 179, - /* 950 */ 106, 424, 106, 106, 424, 151, 177, 66, 67, 111, - /* 960 */ 106, 106, 112, 105, 106, 106, 808, 106, 153, 106, - /* 970 */ 155, 165, 106, 106, 106, 106, 106, 464, 176, 178, - /* 980 */ 852, 106, 180, 182, 106, 190, 293, 192, 245, 106, - /* 990 */ 210, 214, 226, 228, 241, 113, 183, 106, 474, 246, - /* 1000 */ 137, 690, 280, 372, 290, 274, 381, 412, 274, 106, - /* 1010 */ 471, 221, 832, 421, 438, 466, 274, 472, 480, 422, - /* 1020 */ 478, 73, 515, 69, 519, 255, 478, 479, 221, 690, - /* 1030 */ 540, 527, 508, 541, 516, 85, 39, 403, 406, 257, - /* 1040 */ 317, 404, 198, 407, 405, 221, 408, 69, 413, 5, - /* 1050 */ 824, 221, 211, 409, 817, 410, 546, 582, 258, 414, - /* 1060 */ 90, 547, 199, 260, 223, 829, 830, 261, 324, 200, - /* 1070 */ 815, 72, 34, 526, 222, 186, 423, 326, 94, 57, - /* 1080 */ 428, 56, 187, 188, 265, 202, 431, 554, 332, 88, - /* 1090 */ 33, 432, 433, 434, 279, 268, 436, 556, 435, 51, - /* 1100 */ 578, 30, 549, 270, 439, 798, 334, 269, 799, 203, - /* 1110 */ 442, 577, 204, 271, 28, 550, 447, 812, 446, 98, - /* 1120 */ 532, 450, 727, 728, 823, 452, 819, 576, 26, 81, - /* 1130 */ 82, 445, 235, 838, 80, 457, 575, 463, 461, 455, - /* 1140 */ 24, 456, 551, 93, 813, 460, 277, 840, 465, 528, - /* 1150 */ 79, 206, 807, 468, 469, 593, 470, 55, 552, 473, - /* 1160 */ 350, 820, 355, 850, 592, 476, 250, 19, 207, 553, - /* 1170 */ 353, 354, 841, 285, 236, 814, 484, 555, 287, 483, - /* 1180 */ 843, 208, 660, 485, 488, 389, 63, 490, 662, 360, - /* 1190 */ 492, 288, 851, 100, 806, 849, 495, 493, 362, 496, - /* 1200 */ 92, 499, 719, 364, 240, 238, 500, 365, 501, 502, - /* 1210 */ 239, 294, 504, 505, 507, 506, 568, 61, 11, 722, - /* 1220 */ 108, 368, 571, 511, 12, 517, 512, 9, 8, 559, - /* 1230 */ 370, 514, 725, 509, 50, 558, 373, 78, 243, 217, - /* 1240 */ 18, 242, 818, 521, 77, 513, 110, 543, 855, 109, - /* 1250 */ 522, 154, 245, 524, 107, 379, 378, 160, 523, 87, - /* 1260 */ 194, 385, 48, 304, 530, 383, 382, 140, 76, 811, - /* 1270 */ 99, 384, 525, 220, 810, 515, 49, 102, 515, 307, - /* 1280 */ 515, 515, 309, 515, 515, 667, 668, 669, -}; -static YYCODETYPE yy_lookahead[] = { - /* 0 */ 21, 140, 23, 70, 71, 72, 73, 74, 75, 76, - /* 10 */ 77, 78, 79, 80, 81, 82, 83, 9, 25, 158, - /* 20 */ 41, 28, 134, 135, 14, 46, 74, 75, 76, 77, - /* 30 */ 78, 79, 80, 81, 82, 83, 22, 11, 45, 60, - /* 40 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - /* 50 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 60 */ 81, 82, 83, 53, 90, 204, 87, 41, 94, 95, - /* 70 */ 96, 200, 46, 78, 79, 80, 81, 82, 83, 105, - /* 80 */ 132, 133, 134, 135, 17, 19, 60, 61, 62, 63, - /* 90 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - /* 100 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 110 */ 100, 101, 102, 140, 41, 107, 23, 109, 110, 46, - /* 120 */ 159, 111, 136, 137, 57, 19, 59, 141, 114, 23, - /* 130 */ 62, 158, 146, 60, 61, 62, 63, 64, 65, 66, - /* 140 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - /* 150 */ 77, 78, 79, 80, 81, 82, 83, 171, 52, 19, - /* 160 */ 23, 93, 94, 95, 96, 97, 98, 194, 62, 140, - /* 170 */ 23, 140, 104, 20, 20, 146, 22, 204, 147, 148, - /* 180 */ 87, 88, 196, 41, 78, 79, 80, 158, 46, 19, - /* 190 */ 23, 21, 86, 87, 88, 89, 165, 166, 92, 93, - /* 200 */ 171, 128, 60, 61, 62, 63, 64, 65, 66, 67, - /* 210 */ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - /* 220 */ 78, 79, 80, 81, 82, 83, 161, 162, 111, 20, - /* 230 */ 20, 125, 126, 168, 87, 88, 19, 90, 34, 140, - /* 240 */ 23, 94, 95, 96, 90, 78, 79, 43, 94, 95, - /* 250 */ 96, 41, 105, 113, 87, 88, 46, 158, 23, 105, - /* 260 */ 107, 149, 109, 110, 152, 153, 99, 62, 140, 127, - /* 270 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - /* 280 */ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - /* 290 */ 80, 81, 82, 83, 14, 90, 91, 20, 93, 94, - /* 300 */ 95, 96, 97, 98, 87, 88, 15, 19, 23, 104, - /* 310 */ 26, 23, 143, 78, 79, 24, 107, 9, 109, 110, - /* 320 */ 36, 41, 87, 160, 89, 19, 46, 92, 93, 23, - /* 330 */ 39, 23, 20, 42, 22, 207, 208, 209, 9, 139, - /* 340 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - /* 350 */ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - /* 360 */ 80, 81, 82, 83, 20, 140, 80, 81, 82, 83, - /* 370 */ 172, 140, 87, 88, 205, 87, 88, 23, 146, 14, - /* 380 */ 211, 140, 155, 156, 107, 41, 109, 110, 161, 158, - /* 390 */ 46, 78, 79, 87, 88, 87, 88, 99, 9, 158, - /* 400 */ 115, 12, 89, 171, 60, 61, 62, 63, 64, 65, - /* 410 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 420 */ 76, 77, 78, 79, 80, 81, 82, 83, 196, 140, - /* 430 */ 9, 206, 41, 9, 80, 194, 107, 46, 109, 110, - /* 440 */ 210, 87, 88, 17, 212, 204, 22, 158, 20, 217, - /* 450 */ 146, 60, 61, 62, 63, 64, 65, 66, 67, 68, - /* 460 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 470 */ 79, 80, 81, 82, 83, 171, 100, 101, 102, 41, - /* 480 */ 191, 192, 162, 57, 46, 59, 93, 183, 184, 174, - /* 490 */ 99, 19, 127, 189, 129, 23, 181, 104, 60, 61, - /* 500 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 510 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - /* 520 */ 82, 83, 20, 108, 52, 140, 18, 112, 107, 144, - /* 530 */ 109, 110, 147, 148, 62, 107, 140, 109, 110, 47, - /* 540 */ 100, 101, 102, 9, 140, 20, 122, 22, 41, 9, - /* 550 */ 78, 79, 80, 46, 62, 9, 130, 19, 86, 87, - /* 560 */ 88, 89, 158, 167, 92, 93, 128, 60, 61, 62, - /* 570 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - /* 580 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - /* 590 */ 83, 99, 9, 23, 140, 41, 104, 125, 126, 0, - /* 600 */ 46, 156, 206, 95, 108, 201, 161, 111, 9, 10, - /* 610 */ 183, 184, 158, 88, 60, 61, 62, 63, 64, 65, - /* 620 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 630 */ 76, 77, 78, 79, 80, 81, 82, 83, 130, 99, - /* 640 */ 115, 107, 41, 109, 110, 60, 192, 46, 9, 10, - /* 650 */ 20, 113, 22, 107, 47, 109, 110, 87, 88, 140, - /* 660 */ 62, 60, 61, 62, 63, 64, 65, 66, 67, 68, - /* 670 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 680 */ 79, 80, 81, 82, 83, 115, 111, 140, 9, 41, - /* 690 */ 107, 93, 109, 110, 46, 20, 140, 22, 19, 124, - /* 700 */ 20, 20, 22, 22, 152, 158, 99, 22, 123, 61, - /* 710 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 720 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - /* 730 */ 82, 83, 140, 19, 182, 23, 41, 23, 21, 173, - /* 740 */ 23, 46, 63, 140, 91, 198, 93, 20, 89, 22, - /* 750 */ 158, 92, 200, 55, 56, 29, 152, 62, 63, 64, - /* 760 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - /* 770 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 11, - /* 780 */ 54, 13, 14, 15, 16, 19, 182, 15, 146, 23, - /* 790 */ 198, 22, 140, 11, 89, 27, 24, 92, 195, 87, - /* 800 */ 32, 87, 140, 22, 87, 37, 152, 140, 146, 140, - /* 810 */ 158, 39, 146, 171, 42, 146, 140, 140, 52, 51, - /* 820 */ 158, 53, 140, 140, 140, 53, 58, 158, 62, 103, - /* 830 */ 140, 50, 140, 171, 140, 158, 182, 171, 19, 140, - /* 840 */ 171, 158, 23, 167, 78, 79, 140, 140, 158, 167, - /* 850 */ 158, 167, 86, 87, 88, 89, 194, 88, 92, 93, - /* 860 */ 140, 167, 196, 194, 158, 158, 204, 41, 100, 101, - /* 870 */ 102, 52, 46, 204, 106, 9, 146, 111, 212, 111, - /* 880 */ 49, 62, 206, 217, 115, 21, 140, 167, 206, 19, - /* 890 */ 206, 125, 126, 23, 68, 69, 140, 78, 79, 140, - /* 900 */ 206, 171, 140, 140, 158, 86, 87, 88, 89, 127, - /* 910 */ 140, 92, 93, 140, 158, 140, 140, 158, 140, 93, - /* 920 */ 158, 158, 52, 140, 140, 140, 206, 20, 158, 22, - /* 930 */ 99, 158, 62, 158, 158, 22, 158, 140, 20, 139, - /* 940 */ 22, 158, 158, 158, 125, 126, 127, 9, 78, 79, - /* 950 */ 140, 140, 140, 140, 140, 158, 86, 87, 88, 89, - /* 960 */ 140, 140, 92, 93, 140, 140, 9, 140, 158, 140, - /* 970 */ 158, 158, 140, 140, 140, 140, 140, 140, 158, 158, - /* 980 */ 9, 140, 158, 158, 140, 158, 140, 158, 122, 140, - /* 990 */ 158, 158, 158, 158, 158, 125, 126, 140, 146, 158, - /* 1000 */ 200, 103, 158, 20, 158, 22, 20, 158, 22, 140, - /* 1010 */ 199, 113, 99, 199, 20, 158, 22, 20, 20, 22, - /* 1020 */ 22, 111, 146, 171, 20, 140, 22, 158, 113, 114, - /* 1030 */ 89, 35, 195, 92, 124, 89, 150, 140, 99, 140, - /* 1040 */ 163, 213, 22, 140, 214, 113, 186, 171, 40, 9, - /* 1050 */ 11, 113, 127, 215, 9, 216, 140, 9, 115, 38, - /* 1060 */ 154, 20, 140, 140, 186, 99, 99, 186, 163, 20, - /* 1070 */ 9, 171, 20, 116, 140, 202, 140, 163, 118, 139, - /* 1080 */ 49, 157, 203, 14, 140, 22, 130, 116, 151, 154, - /* 1090 */ 145, 140, 99, 140, 99, 187, 19, 33, 186, 44, - /* 1100 */ 9, 142, 218, 116, 139, 9, 164, 188, 130, 140, - /* 1110 */ 11, 9, 20, 19, 138, 152, 169, 9, 170, 193, - /* 1120 */ 152, 14, 123, 123, 9, 9, 9, 9, 138, 180, - /* 1130 */ 121, 60, 140, 14, 179, 103, 9, 176, 63, 169, - /* 1140 */ 138, 140, 21, 117, 9, 140, 157, 9, 63, 87, - /* 1150 */ 178, 22, 9, 123, 140, 113, 19, 48, 140, 197, - /* 1160 */ 154, 9, 152, 9, 113, 19, 185, 140, 140, 219, - /* 1170 */ 154, 20, 9, 20, 186, 9, 140, 152, 187, 114, - /* 1180 */ 9, 20, 9, 176, 140, 166, 19, 140, 9, 166, - /* 1190 */ 140, 188, 9, 98, 9, 9, 140, 186, 140, 186, - /* 1200 */ 154, 114, 9, 48, 120, 193, 140, 19, 186, 176, - /* 1210 */ 157, 113, 169, 140, 103, 186, 9, 139, 31, 9, - /* 1220 */ 140, 139, 9, 123, 170, 19, 140, 139, 138, 140, - /* 1230 */ 19, 197, 9, 176, 164, 218, 139, 177, 118, 22, - /* 1240 */ 12, 119, 9, 169, 176, 186, 140, 210, 9, 113, - /* 1250 */ 140, 83, 122, 114, 113, 19, 48, 93, 186, 89, - /* 1260 */ 19, 160, 139, 20, 140, 140, 97, 200, 175, 9, - /* 1270 */ 157, 159, 140, 140, 9, 220, 104, 151, 220, 139, - /* 1280 */ 220, 220, 140, 220, 220, 111, 111, 111, -}; -#define YY_SHIFT_USE_DFLT (-68) -static short yy_shift_ofst[] = { - /* 0 */ 639, 599, -68, 768, 1040, -68, 1207, 1228, 540, 1213, - /* 10 */ 1187, 772, -68, -68, -68, -68, -68, -68, 93, -68, - /* 20 */ -68, -68, -68, 389, 1127, 389, 1118, 389, 1102, 170, - /* 30 */ 1091, 93, 312, 1052, 1048, 147, -68, 712, -68, 205, - /* 40 */ -68, 93, 68, -68, 298, -68, 393, 298, -68, 1055, - /* 50 */ -68, 204, -68, -68, 1109, 284, 298, -68, -68, -68, - /* 60 */ 298, -68, 1167, 870, 140, 106, 1051, 1042, 766, -68, - /* 70 */ 277, 117, -68, 415, -68, 14, 1130, 1122, 1084, 1026, - /* 80 */ 1009, -68, 313, -68, 946, -68, 1170, -68, 781, 313, - /* 90 */ -68, 313, -68, 960, 870, 685, 870, 1095, 284, -68, - /* 100 */ 137, -68, -68, 554, 870, -68, 1141, 93, 1136, 93, - /* 110 */ -68, -68, -68, -68, 695, 870, 648, 870, -48, 870, - /* 120 */ -48, 870, -48, 870, -48, 870, -67, 870, -67, 870, - /* 130 */ -5, 870, -5, 870, -5, 870, -5, 870, -67, 826, - /* 140 */ 870, -67, -68, -68, 870, 286, 870, 286, 870, 1168, - /* 150 */ 870, 1168, 870, 1168, 870, -68, -68, 598, -68, 1164, - /* 160 */ -68, -68, 870, 507, 870, -67, 288, 766, 153, 496, - /* 170 */ 1174, 1175, 1176, -68, 554, 870, 695, 870, -68, 870, - /* 180 */ -68, 870, -68, 819, 142, 925, 365, 1069, -68, 870, - /* 190 */ 73, 870, 554, 1241, 291, 502, -68, 1020, 93, 1049, - /* 200 */ -68, 1063, 93, 1092, -68, 1129, 93, 1161, -68, 870, - /* 210 */ 280, 870, 438, 870, 554, 630, -68, 870, -68, -68, - /* 220 */ 932, 93, -68, -68, -68, 870, 601, 870, 695, 217, - /* 230 */ 766, 428, -68, 675, -68, 932, -68, 1095, 284, -68, - /* 240 */ 870, 554, 1120, 870, 1217, 870, 554, -68, -68, 769, - /* 250 */ -68, -68, -68, 285, -68, 570, -68, 943, -68, 306, - /* 260 */ 932, 717, -68, -68, 93, -68, -68, 995, 987, -68, - /* 270 */ 1094, 93, 680, -68, 93, -68, 284, -68, -68, 870, - /* 280 */ 554, 117, 209, 525, 1153, 717, 995, 987, -68, 472, - /* 290 */ -21, -68, -68, 1098, 354, -68, -68, -68, -68, 344, - /* 300 */ -68, 681, -68, 1243, -68, 210, 298, -68, 93, 66, - /* 310 */ -68, 607, -68, 93, -68, 440, 726, -68, 653, -68, - /* 320 */ -68, -68, -68, 726, -68, 726, -68, 93, 727, -68, - /* 330 */ -68, 137, -68, 1055, -68, -68, 235, -68, -68, -68, - /* 340 */ 659, -68, -68, 705, -68, -68, -68, -68, 714, 313, - /* 350 */ 907, -68, 313, 1151, -68, -68, -68, -68, 154, -26, - /* 360 */ -68, 93, -68, 1155, 1188, 93, 918, 298, -68, 1211, - /* 370 */ 93, 983, 298, -68, 870, 391, -68, 1208, 1236, 93, - /* 380 */ 986, 1169, 93, 66, -68, 492, 1172, -68, -68, -68, - /* 390 */ -68, -68, 117, 546, 508, 67, 93, -68, 93, 864, - /* 400 */ 117, 421, 93, -7, 376, 939, 93, 932, 1008, 782, - /* 410 */ 1039, 870, 26, 1021, 698, -68, -68, 966, 967, 831, - /* 420 */ 93, 913, 93, -68, -68, -68, -68, 1031, -68, -68, - /* 430 */ 956, 93, 993, 93, 538, 1077, 93, 994, 540, 1096, - /* 440 */ 978, 1099, 10, 8, 585, 772, -68, 999, 1000, 1107, - /* 450 */ 1115, 1116, 10, 1119, 1071, 93, 1032, 93, 424, 93, - /* 460 */ 1075, 870, 554, 1138, 1085, 870, 554, 1030, 93, 1137, - /* 470 */ 93, 997, -68, 575, 329, 1146, 870, 998, 870, 554, - /* 480 */ 1163, 554, 1065, 93, 866, 1171, 426, 93, 1173, 93, - /* 490 */ 1179, 93, 938, 1185, 93, 938, 1186, 534, 1087, 93, - /* 500 */ 932, 866, 1193, 1071, 93, 898, 1111, 93, 424, 1210, - /* 510 */ 1100, 93, 932, 1137, 910, 583, 1206, 870, 1004, 1223, - /* 520 */ 1071, 93, 915, 1139, 93, 957, 996, 1062, 1143, 308, - /* 530 */ 1265, 712, 679, 167, 1260, 1108, 1135, 1166, 941, 1045, - /* 540 */ 1117, 1152, 941, 1233, -68, 93, 1041, 1061, 1064, 712, - /* 550 */ 1121, 93, 971, 1154, 712, 1183, -68, 1064, 93, 1239, - /* 560 */ -68, -68, -68, -}; -#define YY_REDUCE_USE_DFLT (-140) -static short yy_reduce_ofst[] = { - /* 0 */ -52, -112, -140, -14, -140, -140, -140, 1090, 1088, -140, - /* 10 */ -140, 1054, -140, -140, -140, -140, -140, -140, 1027, -140, - /* 20 */ -140, -140, -140, 1002, -140, 990, -140, 976, -140, 959, - /* 30 */ -140, 385, 945, -140, -140, 31, -140, 112, 886, 227, - /* 40 */ -140, 519, 445, -140, 200, -140, -140, 1123, -140, 1070, - /* 50 */ -140, -140, -140, -140, -140, 924, 940, -140, -140, -140, - /* 60 */ 1078, -140, -140, 231, -140, 241, -140, -140, 29, -140, - /* 70 */ 198, 900, -140, 566, 315, 1093, 1068, 1060, 972, 955, - /* 80 */ 949, -140, 935, -140, -140, -140, -140, -140, -140, 906, - /* 90 */ -140, 1046, -140, -140, 289, -140, 454, 926, 1113, -140, - /* 100 */ 1126, -140, -140, -129, 677, -140, -140, 1080, -140, 1106, - /* 110 */ -140, -140, -140, -140, -129, 683, -129, 690, -129, 706, - /* 120 */ -129, 746, -129, 756, -129, 759, -129, 762, -129, 763, - /* 130 */ -129, 770, -129, 773, -129, 775, -129, 776, -129, 1067, - /* 140 */ 778, -129, -140, -140, 783, -129, 784, -129, 785, -129, - /* 150 */ 797, -129, 810, -129, 812, -129, -140, -140, -140, -140, - /* 160 */ -140, -140, 692, -129, 813, -129, 1133, 662, 198, -140, - /* 170 */ -140, -140, -140, -140, -129, 820, -129, 821, -129, 824, - /* 180 */ -129, 825, -129, 404, -129, 873, 879, -140, -140, 827, - /* 190 */ -129, 829, -129, -140, -140, -140, -140, -140, 922, -140, - /* 200 */ -140, -140, 969, -140, -140, -140, 1028, -140, -140, 832, - /* 210 */ -129, 99, -129, 833, -129, -140, -140, -139, -140, -140, - /* 220 */ 878, 934, -140, -140, -140, 834, -129, 835, -129, 992, - /* 230 */ 669, 198, -140, -140, -140, 988, -140, 1012, 1053, -140, - /* 240 */ 836, -129, -140, -27, -140, 841, -129, -140, 427, 981, - /* 250 */ -140, -140, -140, 885, -140, 899, -140, -140, -140, 923, - /* 260 */ 881, 604, -140, -140, 944, -140, -140, 908, 919, -140, - /* 270 */ -140, 684, -140, -140, 225, -140, 989, -140, -140, 844, - /* 280 */ -129, 304, 198, 981, -140, 654, 991, 1003, -140, 846, - /* 290 */ 552, -140, -140, -140, 1080, -140, -140, -140, -140, -129, - /* 300 */ -140, -140, -140, -140, -140, -129, 1140, -140, 1142, -39, - /* 310 */ 163, 320, -140, 667, -140, -140, 877, -140, -140, -140, - /* 320 */ -140, -140, -140, 905, -140, 914, -140, 676, -140, -140, - /* 330 */ -140, 937, -140, 942, -140, -140, -140, -140, -140, -140, - /* 340 */ -140, -140, -140, -140, -140, -140, -140, -140, 1010, 1006, - /* 350 */ -140, -140, 1016, -140, -140, -140, -140, -140, 1019, 1023, - /* 360 */ -140, 1058, -140, -140, -140, 682, -140, 1082, -140, -140, - /* 370 */ 694, -140, 1097, -140, 707, 800, -140, -140, -140, 720, - /* 380 */ -140, -140, 1125, 1112, 1101, 65, -140, -140, -140, -140, - /* 390 */ -140, -140, 642, 198, 169, -140, 556, -140, 699, -140, - /* 400 */ 730, 198, 897, 828, 830, -140, 903, 860, 838, 839, - /* 410 */ -140, 849, -129, -140, -140, -140, -140, -140, -140, -140, - /* 420 */ 814, -140, 936, -140, -140, -140, -140, -140, -140, -140, - /* 430 */ -140, 951, -140, 953, 912, -140, 396, -140, 965, -140, - /* 440 */ -140, -140, 232, 198, 947, 948, -140, -140, -140, -140, - /* 450 */ -140, -140, 666, -140, 970, 1001, -140, 603, 961, 1005, - /* 460 */ -140, 652, -129, -140, -140, 857, -129, -140, 1014, 962, - /* 470 */ 811, -140, -140, 852, 198, -140, 547, -140, 869, -129, - /* 480 */ -140, -129, -140, 1036, 1007, -140, -140, 1044, -140, 1047, - /* 490 */ -140, 1050, 1011, -140, 1056, 1013, -140, 198, -140, 1066, - /* 500 */ 1022, 1033, -140, 1043, 1073, 1029, -140, 837, 1057, -140, - /* 510 */ -140, 1086, 1059, 1034, 876, 198, -140, 592, -140, -140, - /* 520 */ 1074, 1110, 1072, -140, 1132, -140, -140, -140, -140, 1124, - /* 530 */ -140, 968, -140, 128, -140, -140, -140, -140, 230, -140, - /* 540 */ -140, -140, 1037, -140, -140, 916, -140, -140, 884, 963, - /* 550 */ -140, 1018, 950, -140, 1025, -140, -140, 1017, 1089, -140, - /* 560 */ -140, -140, -140, -}; -static YYACTIONTYPE yy_default[] = { - /* 0 */ 570, 570, 564, 856, 856, 566, 856, 572, 856, 856, - /* 10 */ 856, 856, 652, 655, 656, 657, 658, 659, 573, 574, - /* 20 */ 591, 592, 593, 856, 856, 856, 856, 856, 856, 856, - /* 30 */ 856, 856, 856, 856, 856, 856, 584, 594, 604, 586, - /* 40 */ 603, 856, 856, 605, 651, 616, 856, 651, 617, 636, - /* 50 */ 634, 856, 637, 638, 856, 708, 651, 618, 706, 707, - /* 60 */ 651, 619, 856, 856, 737, 797, 743, 738, 856, 664, - /* 70 */ 856, 856, 665, 673, 675, 682, 720, 711, 713, 701, - /* 80 */ 715, 670, 856, 600, 856, 601, 856, 602, 716, 856, - /* 90 */ 717, 856, 718, 856, 856, 702, 856, 709, 708, 703, - /* 100 */ 856, 588, 710, 705, 856, 736, 856, 856, 739, 856, - /* 110 */ 740, 741, 742, 744, 747, 856, 748, 856, 749, 856, - /* 120 */ 750, 856, 751, 856, 752, 856, 753, 856, 754, 856, - /* 130 */ 755, 856, 756, 856, 757, 856, 758, 856, 759, 856, - /* 140 */ 856, 760, 761, 762, 856, 763, 856, 764, 856, 765, - /* 150 */ 856, 766, 856, 767, 856, 768, 769, 856, 770, 856, - /* 160 */ 773, 771, 856, 856, 856, 779, 856, 797, 856, 856, - /* 170 */ 856, 856, 856, 782, 796, 856, 774, 856, 775, 856, - /* 180 */ 776, 856, 777, 856, 856, 856, 856, 856, 787, 856, - /* 190 */ 856, 856, 788, 856, 856, 856, 845, 856, 856, 856, - /* 200 */ 846, 856, 856, 856, 847, 856, 856, 856, 848, 856, - /* 210 */ 856, 856, 856, 856, 789, 856, 781, 797, 794, 795, - /* 220 */ 690, 856, 691, 785, 772, 856, 856, 856, 780, 856, - /* 230 */ 797, 856, 784, 856, 783, 690, 786, 709, 708, 704, - /* 240 */ 856, 714, 856, 797, 712, 856, 721, 674, 685, 683, - /* 250 */ 684, 692, 693, 856, 694, 856, 695, 856, 696, 856, - /* 260 */ 690, 681, 589, 590, 856, 679, 680, 698, 700, 686, - /* 270 */ 856, 856, 856, 699, 856, 803, 708, 805, 804, 856, - /* 280 */ 697, 685, 856, 856, 856, 681, 698, 700, 687, 856, - /* 290 */ 681, 676, 677, 856, 856, 678, 671, 672, 778, 856, - /* 300 */ 735, 856, 745, 856, 746, 856, 651, 620, 856, 801, - /* 310 */ 624, 621, 625, 856, 626, 856, 856, 627, 856, 630, - /* 320 */ 631, 632, 633, 856, 628, 856, 629, 856, 856, 802, - /* 330 */ 622, 856, 623, 636, 635, 606, 856, 607, 608, 609, - /* 340 */ 856, 610, 613, 856, 611, 614, 612, 615, 595, 856, - /* 350 */ 856, 596, 856, 856, 597, 599, 598, 587, 856, 856, - /* 360 */ 641, 856, 644, 856, 856, 856, 856, 651, 645, 856, - /* 370 */ 856, 856, 651, 646, 856, 651, 647, 856, 856, 856, - /* 380 */ 856, 856, 856, 801, 624, 649, 856, 648, 650, 642, - /* 390 */ 643, 585, 856, 856, 581, 856, 856, 579, 856, 856, - /* 400 */ 856, 856, 856, 828, 856, 856, 856, 690, 833, 856, - /* 410 */ 856, 856, 856, 856, 856, 834, 835, 856, 856, 856, - /* 420 */ 856, 856, 856, 733, 734, 825, 826, 856, 827, 580, - /* 430 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 440 */ 856, 856, 856, 856, 856, 856, 654, 856, 856, 856, - /* 450 */ 856, 856, 856, 856, 653, 856, 856, 856, 856, 856, - /* 460 */ 856, 856, 723, 856, 856, 856, 724, 856, 856, 731, - /* 470 */ 856, 856, 732, 856, 856, 856, 856, 856, 856, 729, - /* 480 */ 856, 730, 856, 856, 856, 856, 856, 856, 856, 856, - /* 490 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 500 */ 690, 856, 856, 653, 856, 856, 856, 856, 856, 856, - /* 510 */ 856, 856, 690, 731, 856, 856, 856, 856, 856, 856, - /* 520 */ 653, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 530 */ 856, 856, 856, 822, 856, 856, 856, 856, 856, 856, - /* 540 */ 856, 856, 856, 856, 821, 856, 856, 856, 854, 856, - /* 550 */ 856, 856, 856, 856, 856, 856, 853, 854, 856, 856, - /* 560 */ 567, 569, 565, -}; -#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) - -/* The next table maps tokens into fallback tokens. If a construct -** like the following: -** -** %fallback ID X Y Z. -** -** appears in the grammer, then ID becomes a fallback token for X, Y, -** and Z. Whenever one of the tokens X, Y, or Z is input to the parser -** but it does not parse, the type of the token is changed to ID and -** the parse is retried before an error is thrown. -*/ -#ifdef YYFALLBACK -static const YYCODETYPE yyFallback[] = { - 0, /* $ => nothing */ - 0, /* END_OF_FILE => nothing */ - 0, /* ILLEGAL => nothing */ - 0, /* SPACE => nothing */ - 0, /* UNCLOSED_STRING => nothing */ - 0, /* COMMENT => nothing */ - 0, /* FUNCTION => nothing */ - 0, /* COLUMN => nothing */ - 0, /* AGG_FUNCTION => nothing */ - 0, /* SEMI => nothing */ - 23, /* EXPLAIN => ID */ - 23, /* BEGIN => ID */ - 0, /* TRANSACTION => nothing */ - 0, /* COMMIT => nothing */ - 23, /* END => ID */ - 0, /* ROLLBACK => nothing */ - 0, /* CREATE => nothing */ - 0, /* TABLE => nothing */ - 23, /* TEMP => ID */ - 0, /* LP => nothing */ - 0, /* RP => nothing */ - 0, /* AS => nothing */ - 0, /* COMMA => nothing */ - 0, /* ID => nothing */ - 23, /* ABORT => ID */ - 23, /* AFTER => ID */ - 23, /* ASC => ID */ - 23, /* ATTACH => ID */ - 23, /* BEFORE => ID */ - 23, /* CASCADE => ID */ - 23, /* CLUSTER => ID */ - 23, /* CONFLICT => ID */ - 23, /* COPY => ID */ - 23, /* DATABASE => ID */ - 23, /* DEFERRED => ID */ - 23, /* DELIMITERS => ID */ - 23, /* DESC => ID */ - 23, /* DETACH => ID */ - 23, /* EACH => ID */ - 23, /* FAIL => ID */ - 23, /* FOR => ID */ - 23, /* GLOB => ID */ - 23, /* IGNORE => ID */ - 23, /* IMMEDIATE => ID */ - 23, /* INITIALLY => ID */ - 23, /* INSTEAD => ID */ - 23, /* LIKE => ID */ - 23, /* MATCH => ID */ - 23, /* KEY => ID */ - 23, /* OF => ID */ - 23, /* OFFSET => ID */ - 23, /* PRAGMA => ID */ - 23, /* RAISE => ID */ - 23, /* REPLACE => ID */ - 23, /* RESTRICT => ID */ - 23, /* ROW => ID */ - 23, /* STATEMENT => ID */ - 23, /* TRIGGER => ID */ - 23, /* VACUUM => ID */ - 23, /* VIEW => ID */ - 0, /* OR => nothing */ - 0, /* AND => nothing */ - 0, /* NOT => nothing */ - 0, /* EQ => nothing */ - 0, /* NE => nothing */ - 0, /* ISNULL => nothing */ - 0, /* NOTNULL => nothing */ - 0, /* IS => nothing */ - 0, /* BETWEEN => nothing */ - 0, /* IN => nothing */ - 0, /* GT => nothing */ - 0, /* GE => nothing */ - 0, /* LT => nothing */ - 0, /* LE => nothing */ - 0, /* BITAND => nothing */ - 0, /* BITOR => nothing */ - 0, /* LSHIFT => nothing */ - 0, /* RSHIFT => nothing */ - 0, /* PLUS => nothing */ - 0, /* MINUS => nothing */ - 0, /* STAR => nothing */ - 0, /* SLASH => nothing */ - 0, /* REM => nothing */ - 0, /* CONCAT => nothing */ - 0, /* UMINUS => nothing */ - 0, /* UPLUS => nothing */ - 0, /* BITNOT => nothing */ - 0, /* STRING => nothing */ - 0, /* JOIN_KW => nothing */ - 0, /* INTEGER => nothing */ - 0, /* CONSTRAINT => nothing */ - 0, /* DEFAULT => nothing */ - 0, /* FLOAT => nothing */ - 0, /* NULL => nothing */ - 0, /* PRIMARY => nothing */ - 0, /* UNIQUE => nothing */ - 0, /* CHECK => nothing */ - 0, /* REFERENCES => nothing */ - 0, /* COLLATE => nothing */ - 0, /* ON => nothing */ - 0, /* DELETE => nothing */ - 0, /* UPDATE => nothing */ - 0, /* INSERT => nothing */ - 0, /* SET => nothing */ - 0, /* DEFERRABLE => nothing */ - 0, /* FOREIGN => nothing */ - 0, /* DROP => nothing */ - 0, /* UNION => nothing */ - 0, /* ALL => nothing */ - 0, /* INTERSECT => nothing */ - 0, /* EXCEPT => nothing */ - 0, /* SELECT => nothing */ - 0, /* DISTINCT => nothing */ - 0, /* DOT => nothing */ - 0, /* FROM => nothing */ - 0, /* JOIN => nothing */ - 0, /* USING => nothing */ - 0, /* ORDER => nothing */ - 0, /* BY => nothing */ - 0, /* GROUP => nothing */ - 0, /* HAVING => nothing */ - 0, /* LIMIT => nothing */ - 0, /* WHERE => nothing */ - 0, /* INTO => nothing */ - 0, /* VALUES => nothing */ - 0, /* VARIABLE => nothing */ - 0, /* CASE => nothing */ - 0, /* WHEN => nothing */ - 0, /* THEN => nothing */ - 0, /* ELSE => nothing */ - 0, /* INDEX => nothing */ -}; -#endif /* YYFALLBACK */ - -/* The following structure represents a single element of the -** parser's stack. Information stored includes: -** -** + The state number for the parser at this level of the stack. -** -** + The value of the token stored at this level of the stack. -** (In other words, the "major" token.) -** -** + The semantic value stored at this level of the stack. This is -** the information used by the action routines in the grammar. -** It is sometimes called the "minor" token. -*/ -struct yyStackEntry { - int stateno; /* The state-number */ - int major; /* The major token value. This is the code - ** number for the token at this stack level */ - YYMINORTYPE minor; /* The user-supplied minor token value. This - ** is the value of the token */ -}; -typedef struct yyStackEntry yyStackEntry; - -/* The state of the parser is completely contained in an instance of -** the following structure */ -struct yyParser { - int yyidx; /* Index of top element in stack */ - int yyerrcnt; /* Shifts left before out of the error */ - sqliteParserARG_SDECL /* A place to hold %extra_argument */ - yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ -}; -typedef struct yyParser yyParser; - -#ifndef NDEBUG -#include -static FILE *yyTraceFILE = 0; -static char *yyTracePrompt = 0; -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* -** Turn parser tracing on by giving a stream to which to write the trace -** and a prompt to preface each trace message. Tracing is turned off -** by making either argument NULL -** -** Inputs: -**
    -**
  • A FILE* to which trace output should be written. -** If NULL, then tracing is turned off. -**
  • A prefix string written at the beginning of every -** line of trace output. If NULL, then tracing is -** turned off. -**
-** -** Outputs: -** None. -*/ -void sqliteParserTrace(FILE *TraceFILE, char *zTracePrompt){ - yyTraceFILE = TraceFILE; - yyTracePrompt = zTracePrompt; - if( yyTraceFILE==0 ) yyTracePrompt = 0; - else if( yyTracePrompt==0 ) yyTraceFILE = 0; -} -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* For tracing shifts, the names of all terminals and nonterminals -** are required. The following table supplies these names */ -static const char *yyTokenName[] = { - "$", "END_OF_FILE", "ILLEGAL", "SPACE", - "UNCLOSED_STRING", "COMMENT", "FUNCTION", "COLUMN", - "AGG_FUNCTION", "SEMI", "EXPLAIN", "BEGIN", - "TRANSACTION", "COMMIT", "END", "ROLLBACK", - "CREATE", "TABLE", "TEMP", "LP", - "RP", "AS", "COMMA", "ID", - "ABORT", "AFTER", "ASC", "ATTACH", - "BEFORE", "CASCADE", "CLUSTER", "CONFLICT", - "COPY", "DATABASE", "DEFERRED", "DELIMITERS", - "DESC", "DETACH", "EACH", "FAIL", - "FOR", "GLOB", "IGNORE", "IMMEDIATE", - "INITIALLY", "INSTEAD", "LIKE", "MATCH", - "KEY", "OF", "OFFSET", "PRAGMA", - "RAISE", "REPLACE", "RESTRICT", "ROW", - "STATEMENT", "TRIGGER", "VACUUM", "VIEW", - "OR", "AND", "NOT", "EQ", - "NE", "ISNULL", "NOTNULL", "IS", - "BETWEEN", "IN", "GT", "GE", - "LT", "LE", "BITAND", "BITOR", - "LSHIFT", "RSHIFT", "PLUS", "MINUS", - "STAR", "SLASH", "REM", "CONCAT", - "UMINUS", "UPLUS", "BITNOT", "STRING", - "JOIN_KW", "INTEGER", "CONSTRAINT", "DEFAULT", - "FLOAT", "NULL", "PRIMARY", "UNIQUE", - "CHECK", "REFERENCES", "COLLATE", "ON", - "DELETE", "UPDATE", "INSERT", "SET", - "DEFERRABLE", "FOREIGN", "DROP", "UNION", - "ALL", "INTERSECT", "EXCEPT", "SELECT", - "DISTINCT", "DOT", "FROM", "JOIN", - "USING", "ORDER", "BY", "GROUP", - "HAVING", "LIMIT", "WHERE", "INTO", - "VALUES", "VARIABLE", "CASE", "WHEN", - "THEN", "ELSE", "INDEX", "error", - "input", "cmdlist", "ecmd", "explain", - "cmdx", "cmd", "trans_opt", "onconf", - "nm", "create_table", "create_table_args", "temp", - "columnlist", "conslist_opt", "select", "column", - "columnid", "type", "carglist", "id", - "ids", "typename", "signed", "carg", - "ccons", "sortorder", "expr", "idxlist_opt", - "refargs", "defer_subclause", "refarg", "refact", - "init_deferred_pred_opt", "conslist", "tcons", "idxlist", - "defer_subclause_opt", "orconf", "resolvetype", "oneselect", - "multiselect_op", "distinct", "selcollist", "from", - "where_opt", "groupby_opt", "having_opt", "orderby_opt", - "limit_opt", "sclp", "as", "seltablist", - "stl_prefix", "joinop", "dbnm", "on_opt", - "using_opt", "seltablist_paren", "joinop2", "sortlist", - "sortitem", "collate", "exprlist", "setlist", - "insert_cmd", "inscollist_opt", "itemlist", "inscollist", - "likeop", "case_operand", "case_exprlist", "case_else", - "expritem", "uniqueflag", "idxitem", "plus_num", - "minus_num", "plus_opt", "number", "trigger_decl", - "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", - "when_clause", "trigger_cmd", "database_kw_opt", "key_opt", -}; -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* For tracing reduce actions, the names of all rules are required. -*/ -static const char *yyRuleName[] = { - /* 0 */ "input ::= cmdlist", - /* 1 */ "cmdlist ::= cmdlist ecmd", - /* 2 */ "cmdlist ::= ecmd", - /* 3 */ "ecmd ::= explain cmdx SEMI", - /* 4 */ "ecmd ::= SEMI", - /* 5 */ "cmdx ::= cmd", - /* 6 */ "explain ::= EXPLAIN", - /* 7 */ "explain ::=", - /* 8 */ "cmd ::= BEGIN trans_opt onconf", - /* 9 */ "trans_opt ::=", - /* 10 */ "trans_opt ::= TRANSACTION", - /* 11 */ "trans_opt ::= TRANSACTION nm", - /* 12 */ "cmd ::= COMMIT trans_opt", - /* 13 */ "cmd ::= END trans_opt", - /* 14 */ "cmd ::= ROLLBACK trans_opt", - /* 15 */ "cmd ::= create_table create_table_args", - /* 16 */ "create_table ::= CREATE temp TABLE nm", - /* 17 */ "temp ::= TEMP", - /* 18 */ "temp ::=", - /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP", - /* 20 */ "create_table_args ::= AS select", - /* 21 */ "columnlist ::= columnlist COMMA column", - /* 22 */ "columnlist ::= column", - /* 23 */ "column ::= columnid type carglist", - /* 24 */ "columnid ::= nm", - /* 25 */ "id ::= ID", - /* 26 */ "ids ::= ID", - /* 27 */ "ids ::= STRING", - /* 28 */ "nm ::= ID", - /* 29 */ "nm ::= STRING", - /* 30 */ "nm ::= JOIN_KW", - /* 31 */ "type ::=", - /* 32 */ "type ::= typename", - /* 33 */ "type ::= typename LP signed RP", - /* 34 */ "type ::= typename LP signed COMMA signed RP", - /* 35 */ "typename ::= ids", - /* 36 */ "typename ::= typename ids", - /* 37 */ "signed ::= INTEGER", - /* 38 */ "signed ::= PLUS INTEGER", - /* 39 */ "signed ::= MINUS INTEGER", - /* 40 */ "carglist ::= carglist carg", - /* 41 */ "carglist ::=", - /* 42 */ "carg ::= CONSTRAINT nm ccons", - /* 43 */ "carg ::= ccons", - /* 44 */ "carg ::= DEFAULT STRING", - /* 45 */ "carg ::= DEFAULT ID", - /* 46 */ "carg ::= DEFAULT INTEGER", - /* 47 */ "carg ::= DEFAULT PLUS INTEGER", - /* 48 */ "carg ::= DEFAULT MINUS INTEGER", - /* 49 */ "carg ::= DEFAULT FLOAT", - /* 50 */ "carg ::= DEFAULT PLUS FLOAT", - /* 51 */ "carg ::= DEFAULT MINUS FLOAT", - /* 52 */ "carg ::= DEFAULT NULL", - /* 53 */ "ccons ::= NULL onconf", - /* 54 */ "ccons ::= NOT NULL onconf", - /* 55 */ "ccons ::= PRIMARY KEY sortorder onconf", - /* 56 */ "ccons ::= UNIQUE onconf", - /* 57 */ "ccons ::= CHECK LP expr RP onconf", - /* 58 */ "ccons ::= REFERENCES nm idxlist_opt refargs", - /* 59 */ "ccons ::= defer_subclause", - /* 60 */ "ccons ::= COLLATE id", - /* 61 */ "refargs ::=", - /* 62 */ "refargs ::= refargs refarg", - /* 63 */ "refarg ::= MATCH nm", - /* 64 */ "refarg ::= ON DELETE refact", - /* 65 */ "refarg ::= ON UPDATE refact", - /* 66 */ "refarg ::= ON INSERT refact", - /* 67 */ "refact ::= SET NULL", - /* 68 */ "refact ::= SET DEFAULT", - /* 69 */ "refact ::= CASCADE", - /* 70 */ "refact ::= RESTRICT", - /* 71 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 72 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 73 */ "init_deferred_pred_opt ::=", - /* 74 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 75 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 76 */ "conslist_opt ::=", - /* 77 */ "conslist_opt ::= COMMA conslist", - /* 78 */ "conslist ::= conslist COMMA tcons", - /* 79 */ "conslist ::= conslist tcons", - /* 80 */ "conslist ::= tcons", - /* 81 */ "tcons ::= CONSTRAINT nm", - /* 82 */ "tcons ::= PRIMARY KEY LP idxlist RP onconf", - /* 83 */ "tcons ::= UNIQUE LP idxlist RP onconf", - /* 84 */ "tcons ::= CHECK expr onconf", - /* 85 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", - /* 86 */ "defer_subclause_opt ::=", - /* 87 */ "defer_subclause_opt ::= defer_subclause", - /* 88 */ "onconf ::=", - /* 89 */ "onconf ::= ON CONFLICT resolvetype", - /* 90 */ "orconf ::=", - /* 91 */ "orconf ::= OR resolvetype", - /* 92 */ "resolvetype ::= ROLLBACK", - /* 93 */ "resolvetype ::= ABORT", - /* 94 */ "resolvetype ::= FAIL", - /* 95 */ "resolvetype ::= IGNORE", - /* 96 */ "resolvetype ::= REPLACE", - /* 97 */ "cmd ::= DROP TABLE nm", - /* 98 */ "cmd ::= CREATE temp VIEW nm AS select", - /* 99 */ "cmd ::= DROP VIEW nm", - /* 100 */ "cmd ::= select", - /* 101 */ "select ::= oneselect", - /* 102 */ "select ::= select multiselect_op oneselect", - /* 103 */ "multiselect_op ::= UNION", - /* 104 */ "multiselect_op ::= UNION ALL", - /* 105 */ "multiselect_op ::= INTERSECT", - /* 106 */ "multiselect_op ::= EXCEPT", - /* 107 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 108 */ "distinct ::= DISTINCT", - /* 109 */ "distinct ::= ALL", - /* 110 */ "distinct ::=", - /* 111 */ "sclp ::= selcollist COMMA", - /* 112 */ "sclp ::=", - /* 113 */ "selcollist ::= sclp expr as", - /* 114 */ "selcollist ::= sclp STAR", - /* 115 */ "selcollist ::= sclp nm DOT STAR", - /* 116 */ "as ::= AS nm", - /* 117 */ "as ::= ids", - /* 118 */ "as ::=", - /* 119 */ "from ::=", - /* 120 */ "from ::= FROM seltablist", - /* 121 */ "stl_prefix ::= seltablist joinop", - /* 122 */ "stl_prefix ::=", - /* 123 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", - /* 124 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", - /* 125 */ "seltablist_paren ::= select", - /* 126 */ "seltablist_paren ::= seltablist", - /* 127 */ "dbnm ::=", - /* 128 */ "dbnm ::= DOT nm", - /* 129 */ "joinop ::= COMMA", - /* 130 */ "joinop ::= JOIN", - /* 131 */ "joinop ::= JOIN_KW JOIN", - /* 132 */ "joinop ::= JOIN_KW nm JOIN", - /* 133 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 134 */ "on_opt ::= ON expr", - /* 135 */ "on_opt ::=", - /* 136 */ "using_opt ::= USING LP idxlist RP", - /* 137 */ "using_opt ::=", - /* 138 */ "orderby_opt ::=", - /* 139 */ "orderby_opt ::= ORDER BY sortlist", - /* 140 */ "sortlist ::= sortlist COMMA sortitem collate sortorder", - /* 141 */ "sortlist ::= sortitem collate sortorder", - /* 142 */ "sortitem ::= expr", - /* 143 */ "sortorder ::= ASC", - /* 144 */ "sortorder ::= DESC", - /* 145 */ "sortorder ::=", - /* 146 */ "collate ::=", - /* 147 */ "collate ::= COLLATE id", - /* 148 */ "groupby_opt ::=", - /* 149 */ "groupby_opt ::= GROUP BY exprlist", - /* 150 */ "having_opt ::=", - /* 151 */ "having_opt ::= HAVING expr", - /* 152 */ "limit_opt ::=", - /* 153 */ "limit_opt ::= LIMIT signed", - /* 154 */ "limit_opt ::= LIMIT signed OFFSET signed", - /* 155 */ "limit_opt ::= LIMIT signed COMMA signed", - /* 156 */ "cmd ::= DELETE FROM nm dbnm where_opt", - /* 157 */ "where_opt ::=", - /* 158 */ "where_opt ::= WHERE expr", - /* 159 */ "cmd ::= UPDATE orconf nm dbnm SET setlist where_opt", - /* 160 */ "setlist ::= setlist COMMA nm EQ expr", - /* 161 */ "setlist ::= nm EQ expr", - /* 162 */ "cmd ::= insert_cmd INTO nm dbnm inscollist_opt VALUES LP itemlist RP", - /* 163 */ "cmd ::= insert_cmd INTO nm dbnm inscollist_opt select", - /* 164 */ "insert_cmd ::= INSERT orconf", - /* 165 */ "insert_cmd ::= REPLACE", - /* 166 */ "itemlist ::= itemlist COMMA expr", - /* 167 */ "itemlist ::= expr", - /* 168 */ "inscollist_opt ::=", - /* 169 */ "inscollist_opt ::= LP inscollist RP", - /* 170 */ "inscollist ::= inscollist COMMA nm", - /* 171 */ "inscollist ::= nm", - /* 172 */ "expr ::= LP expr RP", - /* 173 */ "expr ::= NULL", - /* 174 */ "expr ::= ID", - /* 175 */ "expr ::= JOIN_KW", - /* 176 */ "expr ::= nm DOT nm", - /* 177 */ "expr ::= nm DOT nm DOT nm", - /* 178 */ "expr ::= INTEGER", - /* 179 */ "expr ::= FLOAT", - /* 180 */ "expr ::= STRING", - /* 181 */ "expr ::= VARIABLE", - /* 182 */ "expr ::= ID LP exprlist RP", - /* 183 */ "expr ::= ID LP STAR RP", - /* 184 */ "expr ::= expr AND expr", - /* 185 */ "expr ::= expr OR expr", - /* 186 */ "expr ::= expr LT expr", - /* 187 */ "expr ::= expr GT expr", - /* 188 */ "expr ::= expr LE expr", - /* 189 */ "expr ::= expr GE expr", - /* 190 */ "expr ::= expr NE expr", - /* 191 */ "expr ::= expr EQ expr", - /* 192 */ "expr ::= expr BITAND expr", - /* 193 */ "expr ::= expr BITOR expr", - /* 194 */ "expr ::= expr LSHIFT expr", - /* 195 */ "expr ::= expr RSHIFT expr", - /* 196 */ "expr ::= expr likeop expr", - /* 197 */ "expr ::= expr NOT likeop expr", - /* 198 */ "likeop ::= LIKE", - /* 199 */ "likeop ::= GLOB", - /* 200 */ "expr ::= expr PLUS expr", - /* 201 */ "expr ::= expr MINUS expr", - /* 202 */ "expr ::= expr STAR expr", - /* 203 */ "expr ::= expr SLASH expr", - /* 204 */ "expr ::= expr REM expr", - /* 205 */ "expr ::= expr CONCAT expr", - /* 206 */ "expr ::= expr ISNULL", - /* 207 */ "expr ::= expr IS NULL", - /* 208 */ "expr ::= expr NOTNULL", - /* 209 */ "expr ::= expr NOT NULL", - /* 210 */ "expr ::= expr IS NOT NULL", - /* 211 */ "expr ::= NOT expr", - /* 212 */ "expr ::= BITNOT expr", - /* 213 */ "expr ::= MINUS expr", - /* 214 */ "expr ::= PLUS expr", - /* 215 */ "expr ::= LP select RP", - /* 216 */ "expr ::= expr BETWEEN expr AND expr", - /* 217 */ "expr ::= expr NOT BETWEEN expr AND expr", - /* 218 */ "expr ::= expr IN LP exprlist RP", - /* 219 */ "expr ::= expr IN LP select RP", - /* 220 */ "expr ::= expr NOT IN LP exprlist RP", - /* 221 */ "expr ::= expr NOT IN LP select RP", - /* 222 */ "expr ::= expr IN nm dbnm", - /* 223 */ "expr ::= expr NOT IN nm dbnm", - /* 224 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 225 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 226 */ "case_exprlist ::= WHEN expr THEN expr", - /* 227 */ "case_else ::= ELSE expr", - /* 228 */ "case_else ::=", - /* 229 */ "case_operand ::= expr", - /* 230 */ "case_operand ::=", - /* 231 */ "exprlist ::= exprlist COMMA expritem", - /* 232 */ "exprlist ::= expritem", - /* 233 */ "expritem ::= expr", - /* 234 */ "expritem ::=", - /* 235 */ "cmd ::= CREATE uniqueflag INDEX nm ON nm dbnm LP idxlist RP onconf", - /* 236 */ "uniqueflag ::= UNIQUE", - /* 237 */ "uniqueflag ::=", - /* 238 */ "idxlist_opt ::=", - /* 239 */ "idxlist_opt ::= LP idxlist RP", - /* 240 */ "idxlist ::= idxlist COMMA idxitem", - /* 241 */ "idxlist ::= idxitem", - /* 242 */ "idxitem ::= nm sortorder", - /* 243 */ "cmd ::= DROP INDEX nm dbnm", - /* 244 */ "cmd ::= COPY orconf nm dbnm FROM nm USING DELIMITERS STRING", - /* 245 */ "cmd ::= COPY orconf nm dbnm FROM nm", - /* 246 */ "cmd ::= VACUUM", - /* 247 */ "cmd ::= VACUUM nm", - /* 248 */ "cmd ::= PRAGMA ids EQ nm", - /* 249 */ "cmd ::= PRAGMA ids EQ ON", - /* 250 */ "cmd ::= PRAGMA ids EQ plus_num", - /* 251 */ "cmd ::= PRAGMA ids EQ minus_num", - /* 252 */ "cmd ::= PRAGMA ids LP nm RP", - /* 253 */ "cmd ::= PRAGMA ids", - /* 254 */ "plus_num ::= plus_opt number", - /* 255 */ "minus_num ::= MINUS number", - /* 256 */ "number ::= INTEGER", - /* 257 */ "number ::= FLOAT", - /* 258 */ "plus_opt ::= PLUS", - /* 259 */ "plus_opt ::=", - /* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", - /* 261 */ "trigger_decl ::= temp TRIGGER nm trigger_time trigger_event ON nm dbnm foreach_clause when_clause", - /* 262 */ "trigger_time ::= BEFORE", - /* 263 */ "trigger_time ::= AFTER", - /* 264 */ "trigger_time ::= INSTEAD OF", - /* 265 */ "trigger_time ::=", - /* 266 */ "trigger_event ::= DELETE", - /* 267 */ "trigger_event ::= INSERT", - /* 268 */ "trigger_event ::= UPDATE", - /* 269 */ "trigger_event ::= UPDATE OF inscollist", - /* 270 */ "foreach_clause ::=", - /* 271 */ "foreach_clause ::= FOR EACH ROW", - /* 272 */ "foreach_clause ::= FOR EACH STATEMENT", - /* 273 */ "when_clause ::=", - /* 274 */ "when_clause ::= WHEN expr", - /* 275 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list", - /* 276 */ "trigger_cmd_list ::=", - /* 277 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", - /* 278 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", - /* 279 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", - /* 280 */ "trigger_cmd ::= DELETE FROM nm where_opt", - /* 281 */ "trigger_cmd ::= select", - /* 282 */ "expr ::= RAISE LP IGNORE RP", - /* 283 */ "expr ::= RAISE LP ROLLBACK COMMA nm RP", - /* 284 */ "expr ::= RAISE LP ABORT COMMA nm RP", - /* 285 */ "expr ::= RAISE LP FAIL COMMA nm RP", - /* 286 */ "cmd ::= DROP TRIGGER nm dbnm", - /* 287 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt", - /* 288 */ "key_opt ::= USING ids", - /* 289 */ "key_opt ::=", - /* 290 */ "database_kw_opt ::= DATABASE", - /* 291 */ "database_kw_opt ::=", - /* 292 */ "cmd ::= DETACH database_kw_opt nm", -}; -#endif /* NDEBUG */ - -/* -** This function returns the symbolic name associated with a token -** value. -*/ -const char *sqliteParserTokenName(int tokenType){ -#ifndef NDEBUG - if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ - return yyTokenName[tokenType]; - }else{ - return "Unknown"; - } -#else - return ""; -#endif -} - -/* -** This function allocates a new parser. -** The only argument is a pointer to a function which works like -** malloc. -** -** Inputs: -** A pointer to the function used to allocate memory. -** -** Outputs: -** A pointer to a parser. This pointer is used in subsequent calls -** to sqliteParser and sqliteParserFree. -*/ -void *sqliteParserAlloc(void *(*mallocProc)(size_t)){ - yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); - if( pParser ){ - pParser->yyidx = -1; - } - return pParser; -} - -/* The following function deletes the value associated with a -** symbol. The symbol can be either a terminal or nonterminal. -** "yymajor" is the symbol code, and "yypminor" is a pointer to -** the value. -*/ -static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ - switch( yymajor ){ - /* Here is inserted the actions which take place when a - ** terminal or non-terminal is destroyed. This can happen - ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is - ** being destroyed before it is finished parsing. - ** - ** Note: during a reduce, the only symbols destroyed are those - ** which appear on the RHS of the rule, but which are not used - ** inside the C code. - */ - case 146: -#line 286 "parse.y" -{sqliteSelectDelete((yypminor->yy179));} -#line 1235 "parse.c" - break; - case 158: -#line 533 "parse.y" -{sqliteExprDelete((yypminor->yy242));} -#line 1240 "parse.c" - break; - case 159: -#line 746 "parse.y" -{sqliteIdListDelete((yypminor->yy320));} -#line 1245 "parse.c" - break; - case 167: -#line 744 "parse.y" -{sqliteIdListDelete((yypminor->yy320));} -#line 1250 "parse.c" - break; - case 171: -#line 288 "parse.y" -{sqliteSelectDelete((yypminor->yy179));} -#line 1255 "parse.c" - break; - case 174: -#line 322 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1260 "parse.c" - break; - case 175: -#line 353 "parse.y" -{sqliteSrcListDelete((yypminor->yy307));} -#line 1265 "parse.c" - break; - case 176: -#line 483 "parse.y" -{sqliteExprDelete((yypminor->yy242));} -#line 1270 "parse.c" - break; - case 177: -#line 459 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1275 "parse.c" - break; - case 178: -#line 464 "parse.y" -{sqliteExprDelete((yypminor->yy242));} -#line 1280 "parse.c" - break; - case 179: -#line 431 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1285 "parse.c" - break; - case 181: -#line 324 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1290 "parse.c" - break; - case 183: -#line 349 "parse.y" -{sqliteSrcListDelete((yypminor->yy307));} -#line 1295 "parse.c" - break; - case 184: -#line 351 "parse.y" -{sqliteSrcListDelete((yypminor->yy307));} -#line 1300 "parse.c" - break; - case 187: -#line 420 "parse.y" -{sqliteExprDelete((yypminor->yy242));} -#line 1305 "parse.c" - break; - case 188: -#line 425 "parse.y" -{sqliteIdListDelete((yypminor->yy320));} -#line 1310 "parse.c" - break; - case 189: -#line 400 "parse.y" -{sqliteSelectDelete((yypminor->yy179));} -#line 1315 "parse.c" - break; - case 191: -#line 433 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1320 "parse.c" - break; - case 192: -#line 435 "parse.y" -{sqliteExprDelete((yypminor->yy242));} -#line 1325 "parse.c" - break; - case 194: -#line 719 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1330 "parse.c" - break; - case 195: -#line 489 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1335 "parse.c" - break; - case 197: -#line 520 "parse.y" -{sqliteIdListDelete((yypminor->yy320));} -#line 1340 "parse.c" - break; - case 198: -#line 514 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1345 "parse.c" - break; - case 199: -#line 522 "parse.y" -{sqliteIdListDelete((yypminor->yy320));} -#line 1350 "parse.c" - break; - case 202: -#line 702 "parse.y" -{sqliteExprListDelete((yypminor->yy322));} -#line 1355 "parse.c" - break; - case 204: -#line 721 "parse.y" -{sqliteExprDelete((yypminor->yy242));} -#line 1360 "parse.c" - break; - case 212: -#line 828 "parse.y" -{sqliteDeleteTriggerStep((yypminor->yy19));} -#line 1365 "parse.c" - break; - case 214: -#line 812 "parse.y" -{sqliteIdListDelete((yypminor->yy290).b);} -#line 1370 "parse.c" - break; - case 217: -#line 836 "parse.y" -{sqliteDeleteTriggerStep((yypminor->yy19));} -#line 1375 "parse.c" - break; - default: break; /* If no destructor action specified: do nothing */ - } -} - -/* -** Pop the parser's stack once. -** -** If there is a destructor routine associated with the token which -** is popped from the stack, then call it. -** -** Return the major token number for the symbol popped. -*/ -static int yy_pop_parser_stack(yyParser *pParser){ - YYCODETYPE yymajor; - yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; - - if( pParser->yyidx<0 ) return 0; -#ifndef NDEBUG - if( yyTraceFILE && pParser->yyidx>=0 ){ - fprintf(yyTraceFILE,"%sPopping %s\n", - yyTracePrompt, - yyTokenName[yytos->major]); - } -#endif - yymajor = yytos->major; - yy_destructor( yymajor, &yytos->minor); - pParser->yyidx--; - return yymajor; -} - -/* -** Deallocate and destroy a parser. Destructors are all called for -** all stack elements before shutting the parser down. -** -** Inputs: -**
    -**
  • A pointer to the parser. This should be a pointer -** obtained from sqliteParserAlloc. -**
  • A pointer to a function used to reclaim memory obtained -** from malloc. -**
-*/ -void sqliteParserFree( - void *p, /* The parser to be deleted */ - void (*freeProc)(void*) /* Function used to reclaim memory */ -){ - yyParser *pParser = (yyParser*)p; - if( pParser==0 ) return; - while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); - (*freeProc)((void*)pParser); -} - -/* -** Find the appropriate action for a parser given the terminal -** look-ahead token iLookAhead. -** -** If the look-ahead token is YYNOCODE, then check to see if the action is -** independent of the look-ahead. If it is, return the action, otherwise -** return YY_NO_ACTION. -*/ -static int yy_find_shift_action( - yyParser *pParser, /* The parser */ - int iLookAhead /* The look-ahead token */ -){ - int i; - int stateno = pParser->yystack[pParser->yyidx].stateno; - - /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ){ - return yy_default[stateno]; - } - if( iLookAhead==YYNOCODE ){ - return YY_NO_ACTION; - } - i += iLookAhead; - if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ -#ifdef YYFALLBACK - int iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - return yy_find_shift_action(pParser, iFallback); - } -#endif - return yy_default[stateno]; - }else{ - return yy_action[i]; - } -} - -/* -** Find the appropriate action for a parser given the non-terminal -** look-ahead token iLookAhead. -** -** If the look-ahead token is YYNOCODE, then check to see if the action is -** independent of the look-ahead. If it is, return the action, otherwise -** return YY_NO_ACTION. -*/ -static int yy_find_reduce_action( - yyParser *pParser, /* The parser */ - int iLookAhead /* The look-ahead token */ -){ - int i; - int stateno = pParser->yystack[pParser->yyidx].stateno; - - i = yy_reduce_ofst[stateno]; - if( i==YY_REDUCE_USE_DFLT ){ - return yy_default[stateno]; - } - if( iLookAhead==YYNOCODE ){ - return YY_NO_ACTION; - } - i += iLookAhead; - if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ - return yy_default[stateno]; - }else{ - return yy_action[i]; - } -} - -/* -** Perform a shift action. -*/ -static void yy_shift( - yyParser *yypParser, /* The parser to be shifted */ - int yyNewState, /* The new state to shift in */ - int yyMajor, /* The major token to shift in */ - YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */ -){ - yyStackEntry *yytos; - yypParser->yyidx++; - if( yypParser->yyidx>=YYSTACKDEPTH ){ - sqliteParserARG_FETCH; - yypParser->yyidx--; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will execute if the parser - ** stack every overflows */ - sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument var */ - return; - } - yytos = &yypParser->yystack[yypParser->yyidx]; - yytos->stateno = yyNewState; - yytos->major = yyMajor; - yytos->minor = *yypMinor; -#ifndef NDEBUG - if( yyTraceFILE && yypParser->yyidx>0 ){ - int i; - fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); - fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); - for(i=1; i<=yypParser->yyidx; i++) - fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); - fprintf(yyTraceFILE,"\n"); - } -#endif -} - -/* The following table contains information about every rule that -** is used during the reduce. -*/ -static struct { - YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ - unsigned char nrhs; /* Number of right-hand side symbols in the rule */ -} yyRuleInfo[] = { - { 132, 1 }, - { 133, 2 }, - { 133, 1 }, - { 134, 3 }, - { 134, 1 }, - { 136, 1 }, - { 135, 1 }, - { 135, 0 }, - { 137, 3 }, - { 138, 0 }, - { 138, 1 }, - { 138, 2 }, - { 137, 2 }, - { 137, 2 }, - { 137, 2 }, - { 137, 2 }, - { 141, 4 }, - { 143, 1 }, - { 143, 0 }, - { 142, 4 }, - { 142, 2 }, - { 144, 3 }, - { 144, 1 }, - { 147, 3 }, - { 148, 1 }, - { 151, 1 }, - { 152, 1 }, - { 152, 1 }, - { 140, 1 }, - { 140, 1 }, - { 140, 1 }, - { 149, 0 }, - { 149, 1 }, - { 149, 4 }, - { 149, 6 }, - { 153, 1 }, - { 153, 2 }, - { 154, 1 }, - { 154, 2 }, - { 154, 2 }, - { 150, 2 }, - { 150, 0 }, - { 155, 3 }, - { 155, 1 }, - { 155, 2 }, - { 155, 2 }, - { 155, 2 }, - { 155, 3 }, - { 155, 3 }, - { 155, 2 }, - { 155, 3 }, - { 155, 3 }, - { 155, 2 }, - { 156, 2 }, - { 156, 3 }, - { 156, 4 }, - { 156, 2 }, - { 156, 5 }, - { 156, 4 }, - { 156, 1 }, - { 156, 2 }, - { 160, 0 }, - { 160, 2 }, - { 162, 2 }, - { 162, 3 }, - { 162, 3 }, - { 162, 3 }, - { 163, 2 }, - { 163, 2 }, - { 163, 1 }, - { 163, 1 }, - { 161, 3 }, - { 161, 2 }, - { 164, 0 }, - { 164, 2 }, - { 164, 2 }, - { 145, 0 }, - { 145, 2 }, - { 165, 3 }, - { 165, 2 }, - { 165, 1 }, - { 166, 2 }, - { 166, 6 }, - { 166, 5 }, - { 166, 3 }, - { 166, 10 }, - { 168, 0 }, - { 168, 1 }, - { 139, 0 }, - { 139, 3 }, - { 169, 0 }, - { 169, 2 }, - { 170, 1 }, - { 170, 1 }, - { 170, 1 }, - { 170, 1 }, - { 170, 1 }, - { 137, 3 }, - { 137, 6 }, - { 137, 3 }, - { 137, 1 }, - { 146, 1 }, - { 146, 3 }, - { 172, 1 }, - { 172, 2 }, - { 172, 1 }, - { 172, 1 }, - { 171, 9 }, - { 173, 1 }, - { 173, 1 }, - { 173, 0 }, - { 181, 2 }, - { 181, 0 }, - { 174, 3 }, - { 174, 2 }, - { 174, 4 }, - { 182, 2 }, - { 182, 1 }, - { 182, 0 }, - { 175, 0 }, - { 175, 2 }, - { 184, 2 }, - { 184, 0 }, - { 183, 6 }, - { 183, 7 }, - { 189, 1 }, - { 189, 1 }, - { 186, 0 }, - { 186, 2 }, - { 185, 1 }, - { 185, 1 }, - { 185, 2 }, - { 185, 3 }, - { 185, 4 }, - { 187, 2 }, - { 187, 0 }, - { 188, 4 }, - { 188, 0 }, - { 179, 0 }, - { 179, 3 }, - { 191, 5 }, - { 191, 3 }, - { 192, 1 }, - { 157, 1 }, - { 157, 1 }, - { 157, 0 }, - { 193, 0 }, - { 193, 2 }, - { 177, 0 }, - { 177, 3 }, - { 178, 0 }, - { 178, 2 }, - { 180, 0 }, - { 180, 2 }, - { 180, 4 }, - { 180, 4 }, - { 137, 5 }, - { 176, 0 }, - { 176, 2 }, - { 137, 7 }, - { 195, 5 }, - { 195, 3 }, - { 137, 9 }, - { 137, 6 }, - { 196, 2 }, - { 196, 1 }, - { 198, 3 }, - { 198, 1 }, - { 197, 0 }, - { 197, 3 }, - { 199, 3 }, - { 199, 1 }, - { 158, 3 }, - { 158, 1 }, - { 158, 1 }, - { 158, 1 }, - { 158, 3 }, - { 158, 5 }, - { 158, 1 }, - { 158, 1 }, - { 158, 1 }, - { 158, 1 }, - { 158, 4 }, - { 158, 4 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 4 }, - { 200, 1 }, - { 200, 1 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 3 }, - { 158, 2 }, - { 158, 3 }, - { 158, 2 }, - { 158, 3 }, - { 158, 4 }, - { 158, 2 }, - { 158, 2 }, - { 158, 2 }, - { 158, 2 }, - { 158, 3 }, - { 158, 5 }, - { 158, 6 }, - { 158, 5 }, - { 158, 5 }, - { 158, 6 }, - { 158, 6 }, - { 158, 4 }, - { 158, 5 }, - { 158, 5 }, - { 202, 5 }, - { 202, 4 }, - { 203, 2 }, - { 203, 0 }, - { 201, 1 }, - { 201, 0 }, - { 194, 3 }, - { 194, 1 }, - { 204, 1 }, - { 204, 0 }, - { 137, 11 }, - { 205, 1 }, - { 205, 0 }, - { 159, 0 }, - { 159, 3 }, - { 167, 3 }, - { 167, 1 }, - { 206, 2 }, - { 137, 4 }, - { 137, 9 }, - { 137, 6 }, - { 137, 1 }, - { 137, 2 }, - { 137, 4 }, - { 137, 4 }, - { 137, 4 }, - { 137, 4 }, - { 137, 5 }, - { 137, 2 }, - { 207, 2 }, - { 208, 2 }, - { 210, 1 }, - { 210, 1 }, - { 209, 1 }, - { 209, 0 }, - { 137, 5 }, - { 211, 10 }, - { 213, 1 }, - { 213, 1 }, - { 213, 2 }, - { 213, 0 }, - { 214, 1 }, - { 214, 1 }, - { 214, 1 }, - { 214, 3 }, - { 215, 0 }, - { 215, 3 }, - { 215, 3 }, - { 216, 0 }, - { 216, 2 }, - { 212, 3 }, - { 212, 0 }, - { 217, 6 }, - { 217, 8 }, - { 217, 5 }, - { 217, 4 }, - { 217, 1 }, - { 158, 4 }, - { 158, 6 }, - { 158, 6 }, - { 158, 6 }, - { 137, 4 }, - { 137, 6 }, - { 219, 2 }, - { 219, 0 }, - { 218, 1 }, - { 218, 0 }, - { 137, 3 }, -}; - -static void yy_accept(yyParser*); /* Forward Declaration */ - -/* -** Perform a reduce action and the shift that must immediately -** follow the reduce. -*/ -static void yy_reduce( - yyParser *yypParser, /* The parser */ - int yyruleno /* Number of the rule by which to reduce */ -){ - int yygoto; /* The next state */ - int yyact; /* The next action */ - YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ - yyStackEntry *yymsp; /* The top of the parser's stack */ - int yysize; /* Amount to pop the stack */ - sqliteParserARG_FETCH; - yymsp = &yypParser->yystack[yypParser->yyidx]; -#ifndef NDEBUG - if( yyTraceFILE && yyruleno>=0 - && yyruleno - ** { ... } // User supplied code - ** #line - ** break; - */ - case 0: - /* No destructor defined for cmdlist */ - break; - case 1: - /* No destructor defined for cmdlist */ - /* No destructor defined for ecmd */ - break; - case 2: - /* No destructor defined for ecmd */ - break; - case 3: - /* No destructor defined for explain */ - /* No destructor defined for cmdx */ - /* No destructor defined for SEMI */ - break; - case 4: - /* No destructor defined for SEMI */ - break; - case 5: -#line 72 "parse.y" -{ sqliteExec(pParse); } -#line 1901 "parse.c" - /* No destructor defined for cmd */ - break; - case 6: -#line 73 "parse.y" -{ sqliteBeginParse(pParse, 1); } -#line 1907 "parse.c" - /* No destructor defined for EXPLAIN */ - break; - case 7: -#line 74 "parse.y" -{ sqliteBeginParse(pParse, 0); } -#line 1913 "parse.c" - break; - case 8: -#line 79 "parse.y" -{sqliteBeginTransaction(pParse,yymsp[0].minor.yy372);} -#line 1918 "parse.c" - /* No destructor defined for BEGIN */ - /* No destructor defined for trans_opt */ - break; - case 9: - break; - case 10: - /* No destructor defined for TRANSACTION */ - break; - case 11: - /* No destructor defined for TRANSACTION */ - /* No destructor defined for nm */ - break; - case 12: -#line 83 "parse.y" -{sqliteCommitTransaction(pParse);} -#line 1934 "parse.c" - /* No destructor defined for COMMIT */ - /* No destructor defined for trans_opt */ - break; - case 13: -#line 84 "parse.y" -{sqliteCommitTransaction(pParse);} -#line 1941 "parse.c" - /* No destructor defined for END */ - /* No destructor defined for trans_opt */ - break; - case 14: -#line 85 "parse.y" -{sqliteRollbackTransaction(pParse);} -#line 1948 "parse.c" - /* No destructor defined for ROLLBACK */ - /* No destructor defined for trans_opt */ - break; - case 15: - /* No destructor defined for create_table */ - /* No destructor defined for create_table_args */ - break; - case 16: -#line 90 "parse.y" -{ - sqliteStartTable(pParse,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy298,yymsp[-2].minor.yy372,0); -} -#line 1961 "parse.c" - /* No destructor defined for TABLE */ - break; - case 17: -#line 94 "parse.y" -{yygotominor.yy372 = 1;} -#line 1967 "parse.c" - /* No destructor defined for TEMP */ - break; - case 18: -#line 95 "parse.y" -{yygotominor.yy372 = 0;} -#line 1973 "parse.c" - break; - case 19: -#line 96 "parse.y" -{ - sqliteEndTable(pParse,&yymsp[0].minor.yy0,0); -} -#line 1980 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for columnlist */ - /* No destructor defined for conslist_opt */ - break; - case 20: -#line 99 "parse.y" -{ - sqliteEndTable(pParse,0,yymsp[0].minor.yy179); - sqliteSelectDelete(yymsp[0].minor.yy179); -} -#line 1991 "parse.c" - /* No destructor defined for AS */ - break; - case 21: - /* No destructor defined for columnlist */ - /* No destructor defined for COMMA */ - /* No destructor defined for column */ - break; - case 22: - /* No destructor defined for column */ - break; - case 23: - /* No destructor defined for columnid */ - /* No destructor defined for type */ - /* No destructor defined for carglist */ - break; - case 24: -#line 111 "parse.y" -{sqliteAddColumn(pParse,&yymsp[0].minor.yy298);} -#line 2010 "parse.c" - break; - case 25: -#line 117 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy0;} -#line 2015 "parse.c" - break; - case 26: -#line 149 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy0;} -#line 2020 "parse.c" - break; - case 27: -#line 150 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy0;} -#line 2025 "parse.c" - break; - case 28: -#line 155 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy0;} -#line 2030 "parse.c" - break; - case 29: -#line 156 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy0;} -#line 2035 "parse.c" - break; - case 30: -#line 157 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy0;} -#line 2040 "parse.c" - break; - case 31: - break; - case 32: -#line 160 "parse.y" -{sqliteAddColumnType(pParse,&yymsp[0].minor.yy298,&yymsp[0].minor.yy298);} -#line 2047 "parse.c" - break; - case 33: -#line 161 "parse.y" -{sqliteAddColumnType(pParse,&yymsp[-3].minor.yy298,&yymsp[0].minor.yy0);} -#line 2052 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for signed */ - break; - case 34: -#line 163 "parse.y" -{sqliteAddColumnType(pParse,&yymsp[-5].minor.yy298,&yymsp[0].minor.yy0);} -#line 2059 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for signed */ - /* No destructor defined for COMMA */ - /* No destructor defined for signed */ - break; - case 35: -#line 165 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy298;} -#line 2068 "parse.c" - break; - case 36: -#line 166 "parse.y" -{yygotominor.yy298 = yymsp[-1].minor.yy298;} -#line 2073 "parse.c" - /* No destructor defined for ids */ - break; - case 37: -#line 168 "parse.y" -{ yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); } -#line 2079 "parse.c" - break; - case 38: -#line 169 "parse.y" -{ yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); } -#line 2084 "parse.c" - /* No destructor defined for PLUS */ - break; - case 39: -#line 170 "parse.y" -{ yygotominor.yy372 = -atoi(yymsp[0].minor.yy0.z); } -#line 2090 "parse.c" - /* No destructor defined for MINUS */ - break; - case 40: - /* No destructor defined for carglist */ - /* No destructor defined for carg */ - break; - case 41: - break; - case 42: - /* No destructor defined for CONSTRAINT */ - /* No destructor defined for nm */ - /* No destructor defined for ccons */ - break; - case 43: - /* No destructor defined for ccons */ - break; - case 44: -#line 175 "parse.y" -{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} -#line 2110 "parse.c" - /* No destructor defined for DEFAULT */ - break; - case 45: -#line 176 "parse.y" -{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} -#line 2116 "parse.c" - /* No destructor defined for DEFAULT */ - break; - case 46: -#line 177 "parse.y" -{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} -#line 2122 "parse.c" - /* No destructor defined for DEFAULT */ - break; - case 47: -#line 178 "parse.y" -{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} -#line 2128 "parse.c" - /* No destructor defined for DEFAULT */ - /* No destructor defined for PLUS */ - break; - case 48: -#line 179 "parse.y" -{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);} -#line 2135 "parse.c" - /* No destructor defined for DEFAULT */ - /* No destructor defined for MINUS */ - break; - case 49: -#line 180 "parse.y" -{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} -#line 2142 "parse.c" - /* No destructor defined for DEFAULT */ - break; - case 50: -#line 181 "parse.y" -{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} -#line 2148 "parse.c" - /* No destructor defined for DEFAULT */ - /* No destructor defined for PLUS */ - break; - case 51: -#line 182 "parse.y" -{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);} -#line 2155 "parse.c" - /* No destructor defined for DEFAULT */ - /* No destructor defined for MINUS */ - break; - case 52: - /* No destructor defined for DEFAULT */ - /* No destructor defined for NULL */ - break; - case 53: - /* No destructor defined for NULL */ - /* No destructor defined for onconf */ - break; - case 54: -#line 189 "parse.y" -{sqliteAddNotNull(pParse, yymsp[0].minor.yy372);} -#line 2170 "parse.c" - /* No destructor defined for NOT */ - /* No destructor defined for NULL */ - break; - case 55: -#line 190 "parse.y" -{sqliteAddPrimaryKey(pParse,0,yymsp[0].minor.yy372);} -#line 2177 "parse.c" - /* No destructor defined for PRIMARY */ - /* No destructor defined for KEY */ - /* No destructor defined for sortorder */ - break; - case 56: -#line 191 "parse.y" -{sqliteCreateIndex(pParse,0,0,0,yymsp[0].minor.yy372,0,0);} -#line 2185 "parse.c" - /* No destructor defined for UNIQUE */ - break; - case 57: - /* No destructor defined for CHECK */ - /* No destructor defined for LP */ - yy_destructor(158,&yymsp[-2].minor); - /* No destructor defined for RP */ - /* No destructor defined for onconf */ - break; - case 58: -#line 194 "parse.y" -{sqliteCreateForeignKey(pParse,0,&yymsp[-2].minor.yy298,yymsp[-1].minor.yy320,yymsp[0].minor.yy372);} -#line 2198 "parse.c" - /* No destructor defined for REFERENCES */ - break; - case 59: -#line 195 "parse.y" -{sqliteDeferForeignKey(pParse,yymsp[0].minor.yy372);} -#line 2204 "parse.c" - break; - case 60: -#line 196 "parse.y" -{ - sqliteAddCollateType(pParse, sqliteCollateType(yymsp[0].minor.yy298.z, yymsp[0].minor.yy298.n)); -} -#line 2211 "parse.c" - /* No destructor defined for COLLATE */ - break; - case 61: -#line 206 "parse.y" -{ yygotominor.yy372 = OE_Restrict * 0x010101; } -#line 2217 "parse.c" - break; - case 62: -#line 207 "parse.y" -{ yygotominor.yy372 = (yymsp[-1].minor.yy372 & yymsp[0].minor.yy407.mask) | yymsp[0].minor.yy407.value; } -#line 2222 "parse.c" - break; - case 63: -#line 209 "parse.y" -{ yygotominor.yy407.value = 0; yygotominor.yy407.mask = 0x000000; } -#line 2227 "parse.c" - /* No destructor defined for MATCH */ - /* No destructor defined for nm */ - break; - case 64: -#line 210 "parse.y" -{ yygotominor.yy407.value = yymsp[0].minor.yy372; yygotominor.yy407.mask = 0x0000ff; } -#line 2234 "parse.c" - /* No destructor defined for ON */ - /* No destructor defined for DELETE */ - break; - case 65: -#line 211 "parse.y" -{ yygotominor.yy407.value = yymsp[0].minor.yy372<<8; yygotominor.yy407.mask = 0x00ff00; } -#line 2241 "parse.c" - /* No destructor defined for ON */ - /* No destructor defined for UPDATE */ - break; - case 66: -#line 212 "parse.y" -{ yygotominor.yy407.value = yymsp[0].minor.yy372<<16; yygotominor.yy407.mask = 0xff0000; } -#line 2248 "parse.c" - /* No destructor defined for ON */ - /* No destructor defined for INSERT */ - break; - case 67: -#line 214 "parse.y" -{ yygotominor.yy372 = OE_SetNull; } -#line 2255 "parse.c" - /* No destructor defined for SET */ - /* No destructor defined for NULL */ - break; - case 68: -#line 215 "parse.y" -{ yygotominor.yy372 = OE_SetDflt; } -#line 2262 "parse.c" - /* No destructor defined for SET */ - /* No destructor defined for DEFAULT */ - break; - case 69: -#line 216 "parse.y" -{ yygotominor.yy372 = OE_Cascade; } -#line 2269 "parse.c" - /* No destructor defined for CASCADE */ - break; - case 70: -#line 217 "parse.y" -{ yygotominor.yy372 = OE_Restrict; } -#line 2275 "parse.c" - /* No destructor defined for RESTRICT */ - break; - case 71: -#line 219 "parse.y" -{yygotominor.yy372 = yymsp[0].minor.yy372;} -#line 2281 "parse.c" - /* No destructor defined for NOT */ - /* No destructor defined for DEFERRABLE */ - break; - case 72: -#line 220 "parse.y" -{yygotominor.yy372 = yymsp[0].minor.yy372;} -#line 2288 "parse.c" - /* No destructor defined for DEFERRABLE */ - break; - case 73: -#line 222 "parse.y" -{yygotominor.yy372 = 0;} -#line 2294 "parse.c" - break; - case 74: -#line 223 "parse.y" -{yygotominor.yy372 = 1;} -#line 2299 "parse.c" - /* No destructor defined for INITIALLY */ - /* No destructor defined for DEFERRED */ - break; - case 75: -#line 224 "parse.y" -{yygotominor.yy372 = 0;} -#line 2306 "parse.c" - /* No destructor defined for INITIALLY */ - /* No destructor defined for IMMEDIATE */ - break; - case 76: - break; - case 77: - /* No destructor defined for COMMA */ - /* No destructor defined for conslist */ - break; - case 78: - /* No destructor defined for conslist */ - /* No destructor defined for COMMA */ - /* No destructor defined for tcons */ - break; - case 79: - /* No destructor defined for conslist */ - /* No destructor defined for tcons */ - break; - case 80: - /* No destructor defined for tcons */ - break; - case 81: - /* No destructor defined for CONSTRAINT */ - /* No destructor defined for nm */ - break; - case 82: -#line 236 "parse.y" -{sqliteAddPrimaryKey(pParse,yymsp[-2].minor.yy320,yymsp[0].minor.yy372);} -#line 2335 "parse.c" - /* No destructor defined for PRIMARY */ - /* No destructor defined for KEY */ - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 83: -#line 238 "parse.y" -{sqliteCreateIndex(pParse,0,0,yymsp[-2].minor.yy320,yymsp[0].minor.yy372,0,0);} -#line 2344 "parse.c" - /* No destructor defined for UNIQUE */ - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 84: - /* No destructor defined for CHECK */ - yy_destructor(158,&yymsp[-1].minor); - /* No destructor defined for onconf */ - break; - case 85: -#line 241 "parse.y" -{ - sqliteCreateForeignKey(pParse, yymsp[-6].minor.yy320, &yymsp[-3].minor.yy298, yymsp[-2].minor.yy320, yymsp[-1].minor.yy372); - sqliteDeferForeignKey(pParse, yymsp[0].minor.yy372); -} -#line 2360 "parse.c" - /* No destructor defined for FOREIGN */ - /* No destructor defined for KEY */ - /* No destructor defined for LP */ - /* No destructor defined for RP */ - /* No destructor defined for REFERENCES */ - break; - case 86: -#line 246 "parse.y" -{yygotominor.yy372 = 0;} -#line 2370 "parse.c" - break; - case 87: -#line 247 "parse.y" -{yygotominor.yy372 = yymsp[0].minor.yy372;} -#line 2375 "parse.c" - break; - case 88: -#line 255 "parse.y" -{ yygotominor.yy372 = OE_Default; } -#line 2380 "parse.c" - break; - case 89: -#line 256 "parse.y" -{ yygotominor.yy372 = yymsp[0].minor.yy372; } -#line 2385 "parse.c" - /* No destructor defined for ON */ - /* No destructor defined for CONFLICT */ - break; - case 90: -#line 257 "parse.y" -{ yygotominor.yy372 = OE_Default; } -#line 2392 "parse.c" - break; - case 91: -#line 258 "parse.y" -{ yygotominor.yy372 = yymsp[0].minor.yy372; } -#line 2397 "parse.c" - /* No destructor defined for OR */ - break; - case 92: -#line 259 "parse.y" -{ yygotominor.yy372 = OE_Rollback; } -#line 2403 "parse.c" - /* No destructor defined for ROLLBACK */ - break; - case 93: -#line 260 "parse.y" -{ yygotominor.yy372 = OE_Abort; } -#line 2409 "parse.c" - /* No destructor defined for ABORT */ - break; - case 94: -#line 261 "parse.y" -{ yygotominor.yy372 = OE_Fail; } -#line 2415 "parse.c" - /* No destructor defined for FAIL */ - break; - case 95: -#line 262 "parse.y" -{ yygotominor.yy372 = OE_Ignore; } -#line 2421 "parse.c" - /* No destructor defined for IGNORE */ - break; - case 96: -#line 263 "parse.y" -{ yygotominor.yy372 = OE_Replace; } -#line 2427 "parse.c" - /* No destructor defined for REPLACE */ - break; - case 97: -#line 267 "parse.y" -{sqliteDropTable(pParse,&yymsp[0].minor.yy298,0);} -#line 2433 "parse.c" - /* No destructor defined for DROP */ - /* No destructor defined for TABLE */ - break; - case 98: -#line 271 "parse.y" -{ - sqliteCreateView(pParse, &yymsp[-5].minor.yy0, &yymsp[-2].minor.yy298, yymsp[0].minor.yy179, yymsp[-4].minor.yy372); -} -#line 2442 "parse.c" - /* No destructor defined for VIEW */ - /* No destructor defined for AS */ - break; - case 99: -#line 274 "parse.y" -{ - sqliteDropTable(pParse, &yymsp[0].minor.yy298, 1); -} -#line 2451 "parse.c" - /* No destructor defined for DROP */ - /* No destructor defined for VIEW */ - break; - case 100: -#line 280 "parse.y" -{ - sqliteSelect(pParse, yymsp[0].minor.yy179, SRT_Callback, 0, 0, 0, 0); - sqliteSelectDelete(yymsp[0].minor.yy179); -} -#line 2461 "parse.c" - break; - case 101: -#line 290 "parse.y" -{yygotominor.yy179 = yymsp[0].minor.yy179;} -#line 2466 "parse.c" - break; - case 102: -#line 291 "parse.y" -{ - if( yymsp[0].minor.yy179 ){ - yymsp[0].minor.yy179->op = yymsp[-1].minor.yy372; - yymsp[0].minor.yy179->pPrior = yymsp[-2].minor.yy179; - } - yygotominor.yy179 = yymsp[0].minor.yy179; -} -#line 2477 "parse.c" - break; - case 103: -#line 299 "parse.y" -{yygotominor.yy372 = TK_UNION;} -#line 2482 "parse.c" - /* No destructor defined for UNION */ - break; - case 104: -#line 300 "parse.y" -{yygotominor.yy372 = TK_ALL;} -#line 2488 "parse.c" - /* No destructor defined for UNION */ - /* No destructor defined for ALL */ - break; - case 105: -#line 301 "parse.y" -{yygotominor.yy372 = TK_INTERSECT;} -#line 2495 "parse.c" - /* No destructor defined for INTERSECT */ - break; - case 106: -#line 302 "parse.y" -{yygotominor.yy372 = TK_EXCEPT;} -#line 2501 "parse.c" - /* No destructor defined for EXCEPT */ - break; - case 107: -#line 304 "parse.y" -{ - yygotominor.yy179 = sqliteSelectNew(yymsp[-6].minor.yy322,yymsp[-5].minor.yy307,yymsp[-4].minor.yy242,yymsp[-3].minor.yy322,yymsp[-2].minor.yy242,yymsp[-1].minor.yy322,yymsp[-7].minor.yy372,yymsp[0].minor.yy124.limit,yymsp[0].minor.yy124.offset); -} -#line 2509 "parse.c" - /* No destructor defined for SELECT */ - break; - case 108: -#line 312 "parse.y" -{yygotominor.yy372 = 1;} -#line 2515 "parse.c" - /* No destructor defined for DISTINCT */ - break; - case 109: -#line 313 "parse.y" -{yygotominor.yy372 = 0;} -#line 2521 "parse.c" - /* No destructor defined for ALL */ - break; - case 110: -#line 314 "parse.y" -{yygotominor.yy372 = 0;} -#line 2527 "parse.c" - break; - case 111: -#line 325 "parse.y" -{yygotominor.yy322 = yymsp[-1].minor.yy322;} -#line 2532 "parse.c" - /* No destructor defined for COMMA */ - break; - case 112: -#line 326 "parse.y" -{yygotominor.yy322 = 0;} -#line 2538 "parse.c" - break; - case 113: -#line 327 "parse.y" -{ - yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[-1].minor.yy242,yymsp[0].minor.yy298.n?&yymsp[0].minor.yy298:0); -} -#line 2545 "parse.c" - break; - case 114: -#line 330 "parse.y" -{ - yygotominor.yy322 = sqliteExprListAppend(yymsp[-1].minor.yy322, sqliteExpr(TK_ALL, 0, 0, 0), 0); -} -#line 2552 "parse.c" - /* No destructor defined for STAR */ - break; - case 115: -#line 333 "parse.y" -{ - Expr *pRight = sqliteExpr(TK_ALL, 0, 0, 0); - Expr *pLeft = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298); - yygotominor.yy322 = sqliteExprListAppend(yymsp[-3].minor.yy322, sqliteExpr(TK_DOT, pLeft, pRight, 0), 0); -} -#line 2562 "parse.c" - /* No destructor defined for DOT */ - /* No destructor defined for STAR */ - break; - case 116: -#line 343 "parse.y" -{ yygotominor.yy298 = yymsp[0].minor.yy298; } -#line 2569 "parse.c" - /* No destructor defined for AS */ - break; - case 117: -#line 344 "parse.y" -{ yygotominor.yy298 = yymsp[0].minor.yy298; } -#line 2575 "parse.c" - break; - case 118: -#line 345 "parse.y" -{ yygotominor.yy298.n = 0; } -#line 2580 "parse.c" - break; - case 119: -#line 357 "parse.y" -{yygotominor.yy307 = sqliteMalloc(sizeof(*yygotominor.yy307));} -#line 2585 "parse.c" - break; - case 120: -#line 358 "parse.y" -{yygotominor.yy307 = yymsp[0].minor.yy307;} -#line 2590 "parse.c" - /* No destructor defined for FROM */ - break; - case 121: -#line 363 "parse.y" -{ - yygotominor.yy307 = yymsp[-1].minor.yy307; - if( yygotominor.yy307 && yygotominor.yy307->nSrc>0 ) yygotominor.yy307->a[yygotominor.yy307->nSrc-1].jointype = yymsp[0].minor.yy372; -} -#line 2599 "parse.c" - break; - case 122: -#line 367 "parse.y" -{yygotominor.yy307 = 0;} -#line 2604 "parse.c" - break; - case 123: -#line 368 "parse.y" -{ - yygotominor.yy307 = sqliteSrcListAppend(yymsp[-5].minor.yy307,&yymsp[-4].minor.yy298,&yymsp[-3].minor.yy298); - if( yymsp[-2].minor.yy298.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy298); - if( yymsp[-1].minor.yy242 ){ - if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pOn = yymsp[-1].minor.yy242; } - else { sqliteExprDelete(yymsp[-1].minor.yy242); } - } - if( yymsp[0].minor.yy320 ){ - if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pUsing = yymsp[0].minor.yy320; } - else { sqliteIdListDelete(yymsp[0].minor.yy320); } - } -} -#line 2620 "parse.c" - break; - case 124: -#line 381 "parse.y" -{ - yygotominor.yy307 = sqliteSrcListAppend(yymsp[-6].minor.yy307,0,0); - yygotominor.yy307->a[yygotominor.yy307->nSrc-1].pSelect = yymsp[-4].minor.yy179; - if( yymsp[-2].minor.yy298.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy298); - if( yymsp[-1].minor.yy242 ){ - if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pOn = yymsp[-1].minor.yy242; } - else { sqliteExprDelete(yymsp[-1].minor.yy242); } - } - if( yymsp[0].minor.yy320 ){ - if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pUsing = yymsp[0].minor.yy320; } - else { sqliteIdListDelete(yymsp[0].minor.yy320); } - } -} -#line 2637 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 125: -#line 401 "parse.y" -{yygotominor.yy179 = yymsp[0].minor.yy179;} -#line 2644 "parse.c" - break; - case 126: -#line 402 "parse.y" -{ - yygotominor.yy179 = sqliteSelectNew(0,yymsp[0].minor.yy307,0,0,0,0,0,-1,0); -} -#line 2651 "parse.c" - break; - case 127: -#line 407 "parse.y" -{yygotominor.yy298.z=0; yygotominor.yy298.n=0;} -#line 2656 "parse.c" - break; - case 128: -#line 408 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy298;} -#line 2661 "parse.c" - /* No destructor defined for DOT */ - break; - case 129: -#line 412 "parse.y" -{ yygotominor.yy372 = JT_INNER; } -#line 2667 "parse.c" - /* No destructor defined for COMMA */ - break; - case 130: -#line 413 "parse.y" -{ yygotominor.yy372 = JT_INNER; } -#line 2673 "parse.c" - /* No destructor defined for JOIN */ - break; - case 131: -#line 414 "parse.y" -{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-1].minor.yy0,0,0); } -#line 2679 "parse.c" - /* No destructor defined for JOIN */ - break; - case 132: -#line 415 "parse.y" -{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy298,0); } -#line 2685 "parse.c" - /* No destructor defined for JOIN */ - break; - case 133: -#line 417 "parse.y" -{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy298,&yymsp[-1].minor.yy298); } -#line 2691 "parse.c" - /* No destructor defined for JOIN */ - break; - case 134: -#line 421 "parse.y" -{yygotominor.yy242 = yymsp[0].minor.yy242;} -#line 2697 "parse.c" - /* No destructor defined for ON */ - break; - case 135: -#line 422 "parse.y" -{yygotominor.yy242 = 0;} -#line 2703 "parse.c" - break; - case 136: -#line 426 "parse.y" -{yygotominor.yy320 = yymsp[-1].minor.yy320;} -#line 2708 "parse.c" - /* No destructor defined for USING */ - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 137: -#line 427 "parse.y" -{yygotominor.yy320 = 0;} -#line 2716 "parse.c" - break; - case 138: -#line 437 "parse.y" -{yygotominor.yy322 = 0;} -#line 2721 "parse.c" - break; - case 139: -#line 438 "parse.y" -{yygotominor.yy322 = yymsp[0].minor.yy322;} -#line 2726 "parse.c" - /* No destructor defined for ORDER */ - /* No destructor defined for BY */ - break; - case 140: -#line 439 "parse.y" -{ - yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[-2].minor.yy242,0); - if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372; -} -#line 2736 "parse.c" - /* No destructor defined for COMMA */ - break; - case 141: -#line 443 "parse.y" -{ - yygotominor.yy322 = sqliteExprListAppend(0,yymsp[-2].minor.yy242,0); - if( yygotominor.yy322 ) yygotominor.yy322->a[0].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372; -} -#line 2745 "parse.c" - break; - case 142: -#line 447 "parse.y" -{yygotominor.yy242 = yymsp[0].minor.yy242;} -#line 2750 "parse.c" - break; - case 143: -#line 452 "parse.y" -{yygotominor.yy372 = SQLITE_SO_ASC;} -#line 2755 "parse.c" - /* No destructor defined for ASC */ - break; - case 144: -#line 453 "parse.y" -{yygotominor.yy372 = SQLITE_SO_DESC;} -#line 2761 "parse.c" - /* No destructor defined for DESC */ - break; - case 145: -#line 454 "parse.y" -{yygotominor.yy372 = SQLITE_SO_ASC;} -#line 2767 "parse.c" - break; - case 146: -#line 455 "parse.y" -{yygotominor.yy372 = SQLITE_SO_UNK;} -#line 2772 "parse.c" - break; - case 147: -#line 456 "parse.y" -{yygotominor.yy372 = sqliteCollateType(yymsp[0].minor.yy298.z, yymsp[0].minor.yy298.n);} -#line 2777 "parse.c" - /* No destructor defined for COLLATE */ - break; - case 148: -#line 460 "parse.y" -{yygotominor.yy322 = 0;} -#line 2783 "parse.c" - break; - case 149: -#line 461 "parse.y" -{yygotominor.yy322 = yymsp[0].minor.yy322;} -#line 2788 "parse.c" - /* No destructor defined for GROUP */ - /* No destructor defined for BY */ - break; - case 150: -#line 465 "parse.y" -{yygotominor.yy242 = 0;} -#line 2795 "parse.c" - break; - case 151: -#line 466 "parse.y" -{yygotominor.yy242 = yymsp[0].minor.yy242;} -#line 2800 "parse.c" - /* No destructor defined for HAVING */ - break; - case 152: -#line 469 "parse.y" -{yygotominor.yy124.limit = -1; yygotominor.yy124.offset = 0;} -#line 2806 "parse.c" - break; - case 153: -#line 470 "parse.y" -{yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = 0;} -#line 2811 "parse.c" - /* No destructor defined for LIMIT */ - break; - case 154: -#line 472 "parse.y" -{yygotominor.yy124.limit = yymsp[-2].minor.yy372; yygotominor.yy124.offset = yymsp[0].minor.yy372;} -#line 2817 "parse.c" - /* No destructor defined for LIMIT */ - /* No destructor defined for OFFSET */ - break; - case 155: -#line 474 "parse.y" -{yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = yymsp[-2].minor.yy372;} -#line 2824 "parse.c" - /* No destructor defined for LIMIT */ - /* No destructor defined for COMMA */ - break; - case 156: -#line 478 "parse.y" -{ - sqliteDeleteFrom(pParse, sqliteSrcListAppend(0,&yymsp[-2].minor.yy298,&yymsp[-1].minor.yy298), yymsp[0].minor.yy242); -} -#line 2833 "parse.c" - /* No destructor defined for DELETE */ - /* No destructor defined for FROM */ - break; - case 157: -#line 485 "parse.y" -{yygotominor.yy242 = 0;} -#line 2840 "parse.c" - break; - case 158: -#line 486 "parse.y" -{yygotominor.yy242 = yymsp[0].minor.yy242;} -#line 2845 "parse.c" - /* No destructor defined for WHERE */ - break; - case 159: -#line 494 "parse.y" -{sqliteUpdate(pParse,sqliteSrcListAppend(0,&yymsp[-4].minor.yy298,&yymsp[-3].minor.yy298),yymsp[-1].minor.yy322,yymsp[0].minor.yy242,yymsp[-5].minor.yy372);} -#line 2851 "parse.c" - /* No destructor defined for UPDATE */ - /* No destructor defined for SET */ - break; - case 160: -#line 497 "parse.y" -{yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[0].minor.yy242,&yymsp[-2].minor.yy298);} -#line 2858 "parse.c" - /* No destructor defined for COMMA */ - /* No destructor defined for EQ */ - break; - case 161: -#line 498 "parse.y" -{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,&yymsp[-2].minor.yy298);} -#line 2865 "parse.c" - /* No destructor defined for EQ */ - break; - case 162: -#line 504 "parse.y" -{sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-6].minor.yy298,&yymsp[-5].minor.yy298), yymsp[-1].minor.yy322, 0, yymsp[-4].minor.yy320, yymsp[-8].minor.yy372);} -#line 2871 "parse.c" - /* No destructor defined for INTO */ - /* No destructor defined for VALUES */ - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 163: -#line 506 "parse.y" -{sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-3].minor.yy298,&yymsp[-2].minor.yy298), 0, yymsp[0].minor.yy179, yymsp[-1].minor.yy320, yymsp[-5].minor.yy372);} -#line 2880 "parse.c" - /* No destructor defined for INTO */ - break; - case 164: -#line 509 "parse.y" -{yygotominor.yy372 = yymsp[0].minor.yy372;} -#line 2886 "parse.c" - /* No destructor defined for INSERT */ - break; - case 165: -#line 510 "parse.y" -{yygotominor.yy372 = OE_Replace;} -#line 2892 "parse.c" - /* No destructor defined for REPLACE */ - break; - case 166: -#line 516 "parse.y" -{yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);} -#line 2898 "parse.c" - /* No destructor defined for COMMA */ - break; - case 167: -#line 517 "parse.y" -{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);} -#line 2904 "parse.c" - break; - case 168: -#line 524 "parse.y" -{yygotominor.yy320 = 0;} -#line 2909 "parse.c" - break; - case 169: -#line 525 "parse.y" -{yygotominor.yy320 = yymsp[-1].minor.yy320;} -#line 2914 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 170: -#line 526 "parse.y" -{yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy298);} -#line 2921 "parse.c" - /* No destructor defined for COMMA */ - break; - case 171: -#line 527 "parse.y" -{yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy298);} -#line 2927 "parse.c" - break; - case 172: -#line 535 "parse.y" -{yygotominor.yy242 = yymsp[-1].minor.yy242; sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } -#line 2932 "parse.c" - break; - case 173: -#line 536 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_NULL, 0, 0, &yymsp[0].minor.yy0);} -#line 2937 "parse.c" - break; - case 174: -#line 537 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} -#line 2942 "parse.c" - break; - case 175: -#line 538 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} -#line 2947 "parse.c" - break; - case 176: -#line 539 "parse.y" -{ - Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298); - Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy298); - yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp2, 0); -} -#line 2956 "parse.c" - /* No destructor defined for DOT */ - break; - case 177: -#line 544 "parse.y" -{ - Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-4].minor.yy298); - Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298); - Expr *temp3 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy298); - Expr *temp4 = sqliteExpr(TK_DOT, temp2, temp3, 0); - yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp4, 0); -} -#line 2968 "parse.c" - /* No destructor defined for DOT */ - /* No destructor defined for DOT */ - break; - case 178: -#line 551 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_INTEGER, 0, 0, &yymsp[0].minor.yy0);} -#line 2975 "parse.c" - break; - case 179: -#line 552 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_FLOAT, 0, 0, &yymsp[0].minor.yy0);} -#line 2980 "parse.c" - break; - case 180: -#line 553 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_STRING, 0, 0, &yymsp[0].minor.yy0);} -#line 2985 "parse.c" - break; - case 181: -#line 554 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_VARIABLE, 0, 0, &yymsp[0].minor.yy0); - if( yygotominor.yy242 ) yygotominor.yy242->iTable = ++pParse->nVar; -} -#line 2993 "parse.c" - break; - case 182: -#line 558 "parse.y" -{ - yygotominor.yy242 = sqliteExprFunction(yymsp[-1].minor.yy322, &yymsp[-3].minor.yy0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); -} -#line 3001 "parse.c" - /* No destructor defined for LP */ - break; - case 183: -#line 562 "parse.y" -{ - yygotominor.yy242 = sqliteExprFunction(0, &yymsp[-3].minor.yy0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); -} -#line 3010 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for STAR */ - break; - case 184: -#line 566 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_AND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3017 "parse.c" - /* No destructor defined for AND */ - break; - case 185: -#line 567 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_OR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3023 "parse.c" - /* No destructor defined for OR */ - break; - case 186: -#line 568 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_LT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3029 "parse.c" - /* No destructor defined for LT */ - break; - case 187: -#line 569 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_GT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3035 "parse.c" - /* No destructor defined for GT */ - break; - case 188: -#line 570 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_LE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3041 "parse.c" - /* No destructor defined for LE */ - break; - case 189: -#line 571 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_GE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3047 "parse.c" - /* No destructor defined for GE */ - break; - case 190: -#line 572 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_NE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3053 "parse.c" - /* No destructor defined for NE */ - break; - case 191: -#line 573 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_EQ, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3059 "parse.c" - /* No destructor defined for EQ */ - break; - case 192: -#line 574 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_BITAND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3065 "parse.c" - /* No destructor defined for BITAND */ - break; - case 193: -#line 575 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_BITOR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3071 "parse.c" - /* No destructor defined for BITOR */ - break; - case 194: -#line 576 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_LSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3077 "parse.c" - /* No destructor defined for LSHIFT */ - break; - case 195: -#line 577 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_RSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3083 "parse.c" - /* No destructor defined for RSHIFT */ - break; - case 196: -#line 578 "parse.y" -{ - ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0); - pList = sqliteExprListAppend(pList, yymsp[-2].minor.yy242, 0); - yygotominor.yy242 = sqliteExprFunction(pList, 0); - if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372; - sqliteExprSpan(yygotominor.yy242, &yymsp[-2].minor.yy242->span, &yymsp[0].minor.yy242->span); -} -#line 3095 "parse.c" - break; - case 197: -#line 585 "parse.y" -{ - ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0); - pList = sqliteExprListAppend(pList, yymsp[-3].minor.yy242, 0); - yygotominor.yy242 = sqliteExprFunction(pList, 0); - if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372; - yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy242->span); -} -#line 3107 "parse.c" - /* No destructor defined for NOT */ - break; - case 198: -#line 594 "parse.y" -{yygotominor.yy372 = TK_LIKE;} -#line 3113 "parse.c" - /* No destructor defined for LIKE */ - break; - case 199: -#line 595 "parse.y" -{yygotominor.yy372 = TK_GLOB;} -#line 3119 "parse.c" - /* No destructor defined for GLOB */ - break; - case 200: -#line 596 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_PLUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3125 "parse.c" - /* No destructor defined for PLUS */ - break; - case 201: -#line 597 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_MINUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3131 "parse.c" - /* No destructor defined for MINUS */ - break; - case 202: -#line 598 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_STAR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3137 "parse.c" - /* No destructor defined for STAR */ - break; - case 203: -#line 599 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_SLASH, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3143 "parse.c" - /* No destructor defined for SLASH */ - break; - case 204: -#line 600 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_REM, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3149 "parse.c" - /* No destructor defined for REM */ - break; - case 205: -#line 601 "parse.y" -{yygotominor.yy242 = sqliteExpr(TK_CONCAT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} -#line 3155 "parse.c" - /* No destructor defined for CONCAT */ - break; - case 206: -#line 602 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-1].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3164 "parse.c" - break; - case 207: -#line 606 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-2].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3172 "parse.c" - /* No destructor defined for IS */ - break; - case 208: -#line 610 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-1].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3181 "parse.c" - break; - case 209: -#line 614 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-2].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3189 "parse.c" - /* No destructor defined for NOT */ - break; - case 210: -#line 618 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-3].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3198 "parse.c" - /* No destructor defined for IS */ - /* No destructor defined for NOT */ - break; - case 211: -#line 622 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_NOT, yymsp[0].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span); -} -#line 3208 "parse.c" - break; - case 212: -#line 626 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_BITNOT, yymsp[0].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span); -} -#line 3216 "parse.c" - break; - case 213: -#line 630 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_UMINUS, yymsp[0].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span); -} -#line 3224 "parse.c" - break; - case 214: -#line 634 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_UPLUS, yymsp[0].minor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span); -} -#line 3232 "parse.c" - break; - case 215: -#line 638 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_SELECT, 0, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179; - sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); -} -#line 3241 "parse.c" - break; - case 216: -#line 643 "parse.y" -{ - ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0); - pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0); - yygotominor.yy242 = sqliteExpr(TK_BETWEEN, yymsp[-4].minor.yy242, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pList = pList; - sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy242->span); -} -#line 3252 "parse.c" - /* No destructor defined for BETWEEN */ - /* No destructor defined for AND */ - break; - case 217: -#line 650 "parse.y" -{ - ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0); - pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0); - yygotominor.yy242 = sqliteExpr(TK_BETWEEN, yymsp[-5].minor.yy242, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pList = pList; - yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy242->span); -} -#line 3266 "parse.c" - /* No destructor defined for NOT */ - /* No destructor defined for BETWEEN */ - /* No destructor defined for AND */ - break; - case 218: -#line 658 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322; - sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3278 "parse.c" - /* No destructor defined for IN */ - /* No destructor defined for LP */ - break; - case 219: -#line 663 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179; - sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3289 "parse.c" - /* No destructor defined for IN */ - /* No destructor defined for LP */ - break; - case 220: -#line 668 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322; - yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3301 "parse.c" - /* No destructor defined for NOT */ - /* No destructor defined for IN */ - /* No destructor defined for LP */ - break; - case 221: -#line 674 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179; - yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0); -} -#line 3314 "parse.c" - /* No destructor defined for NOT */ - /* No destructor defined for IN */ - /* No destructor defined for LP */ - break; - case 222: -#line 680 "parse.y" -{ - SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298); - yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-3].minor.yy242, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,yymsp[0].minor.yy298.z?&yymsp[0].minor.yy298:&yymsp[-1].minor.yy298); -} -#line 3327 "parse.c" - /* No destructor defined for IN */ - break; - case 223: -#line 686 "parse.y" -{ - SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298); - yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0); - yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); - sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,yymsp[0].minor.yy298.z?&yymsp[0].minor.yy298:&yymsp[-1].minor.yy298); -} -#line 3339 "parse.c" - /* No destructor defined for NOT */ - /* No destructor defined for IN */ - break; - case 224: -#line 696 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_CASE, yymsp[-3].minor.yy242, yymsp[-1].minor.yy242, 0); - if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-2].minor.yy322; - sqliteExprSpan(yygotominor.yy242, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); -} -#line 3350 "parse.c" - break; - case 225: -#line 703 "parse.y" -{ - yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322, yymsp[-2].minor.yy242, 0); - yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0); -} -#line 3358 "parse.c" - /* No destructor defined for WHEN */ - /* No destructor defined for THEN */ - break; - case 226: -#line 707 "parse.y" -{ - yygotominor.yy322 = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0); - yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0); -} -#line 3368 "parse.c" - /* No destructor defined for WHEN */ - /* No destructor defined for THEN */ - break; - case 227: -#line 712 "parse.y" -{yygotominor.yy242 = yymsp[0].minor.yy242;} -#line 3375 "parse.c" - /* No destructor defined for ELSE */ - break; - case 228: -#line 713 "parse.y" -{yygotominor.yy242 = 0;} -#line 3381 "parse.c" - break; - case 229: -#line 715 "parse.y" -{yygotominor.yy242 = yymsp[0].minor.yy242;} -#line 3386 "parse.c" - break; - case 230: -#line 716 "parse.y" -{yygotominor.yy242 = 0;} -#line 3391 "parse.c" - break; - case 231: -#line 724 "parse.y" -{yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);} -#line 3396 "parse.c" - /* No destructor defined for COMMA */ - break; - case 232: -#line 725 "parse.y" -{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);} -#line 3402 "parse.c" - break; - case 233: -#line 726 "parse.y" -{yygotominor.yy242 = yymsp[0].minor.yy242;} -#line 3407 "parse.c" - break; - case 234: -#line 727 "parse.y" -{yygotominor.yy242 = 0;} -#line 3412 "parse.c" - break; - case 235: -#line 732 "parse.y" -{ - SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-5].minor.yy298, &yymsp[-4].minor.yy298); - if( yymsp[-9].minor.yy372!=OE_None ) yymsp[-9].minor.yy372 = yymsp[0].minor.yy372; - if( yymsp[-9].minor.yy372==OE_Default) yymsp[-9].minor.yy372 = OE_Abort; - sqliteCreateIndex(pParse, &yymsp[-7].minor.yy298, pSrc, yymsp[-2].minor.yy320, yymsp[-9].minor.yy372, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0); -} -#line 3422 "parse.c" - /* No destructor defined for INDEX */ - /* No destructor defined for ON */ - /* No destructor defined for LP */ - break; - case 236: -#line 740 "parse.y" -{ yygotominor.yy372 = OE_Abort; } -#line 3430 "parse.c" - /* No destructor defined for UNIQUE */ - break; - case 237: -#line 741 "parse.y" -{ yygotominor.yy372 = OE_None; } -#line 3436 "parse.c" - break; - case 238: -#line 749 "parse.y" -{yygotominor.yy320 = 0;} -#line 3441 "parse.c" - break; - case 239: -#line 750 "parse.y" -{yygotominor.yy320 = yymsp[-1].minor.yy320;} -#line 3446 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 240: -#line 751 "parse.y" -{yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy298);} -#line 3453 "parse.c" - /* No destructor defined for COMMA */ - break; - case 241: -#line 752 "parse.y" -{yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy298);} -#line 3459 "parse.c" - break; - case 242: -#line 753 "parse.y" -{yygotominor.yy298 = yymsp[-1].minor.yy298;} -#line 3464 "parse.c" - /* No destructor defined for sortorder */ - break; - case 243: -#line 758 "parse.y" -{ - sqliteDropIndex(pParse, sqliteSrcListAppend(0,&yymsp[-1].minor.yy298,&yymsp[0].minor.yy298)); -} -#line 3472 "parse.c" - /* No destructor defined for DROP */ - /* No destructor defined for INDEX */ - break; - case 244: -#line 766 "parse.y" -{sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-6].minor.yy298,&yymsp[-5].minor.yy298),&yymsp[-3].minor.yy298,&yymsp[0].minor.yy0,yymsp[-7].minor.yy372);} -#line 3479 "parse.c" - /* No destructor defined for COPY */ - /* No destructor defined for FROM */ - /* No destructor defined for USING */ - /* No destructor defined for DELIMITERS */ - break; - case 245: -#line 768 "parse.y" -{sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-3].minor.yy298,&yymsp[-2].minor.yy298),&yymsp[0].minor.yy298,0,yymsp[-4].minor.yy372);} -#line 3488 "parse.c" - /* No destructor defined for COPY */ - /* No destructor defined for FROM */ - break; - case 246: -#line 772 "parse.y" -{sqliteVacuum(pParse,0);} -#line 3495 "parse.c" - /* No destructor defined for VACUUM */ - break; - case 247: -#line 773 "parse.y" -{sqliteVacuum(pParse,&yymsp[0].minor.yy298);} -#line 3501 "parse.c" - /* No destructor defined for VACUUM */ - break; - case 248: -#line 777 "parse.y" -{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,0);} -#line 3507 "parse.c" - /* No destructor defined for PRAGMA */ - /* No destructor defined for EQ */ - break; - case 249: -#line 778 "parse.y" -{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy0,0);} -#line 3514 "parse.c" - /* No destructor defined for PRAGMA */ - /* No destructor defined for EQ */ - break; - case 250: -#line 779 "parse.y" -{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,0);} -#line 3521 "parse.c" - /* No destructor defined for PRAGMA */ - /* No destructor defined for EQ */ - break; - case 251: -#line 780 "parse.y" -{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,1);} -#line 3528 "parse.c" - /* No destructor defined for PRAGMA */ - /* No destructor defined for EQ */ - break; - case 252: -#line 781 "parse.y" -{sqlitePragma(pParse,&yymsp[-3].minor.yy298,&yymsp[-1].minor.yy298,0);} -#line 3535 "parse.c" - /* No destructor defined for PRAGMA */ - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 253: -#line 782 "parse.y" -{sqlitePragma(pParse,&yymsp[0].minor.yy298,&yymsp[0].minor.yy298,0);} -#line 3543 "parse.c" - /* No destructor defined for PRAGMA */ - break; - case 254: -#line 783 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy298;} -#line 3549 "parse.c" - /* No destructor defined for plus_opt */ - break; - case 255: -#line 784 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy298;} -#line 3555 "parse.c" - /* No destructor defined for MINUS */ - break; - case 256: -#line 785 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy0;} -#line 3561 "parse.c" - break; - case 257: -#line 786 "parse.y" -{yygotominor.yy298 = yymsp[0].minor.yy0;} -#line 3566 "parse.c" - break; - case 258: - /* No destructor defined for PLUS */ - break; - case 259: - break; - case 260: -#line 792 "parse.y" -{ - Token all; - all.z = yymsp[-4].minor.yy0.z; - all.n = (yymsp[0].minor.yy0.z - yymsp[-4].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqliteFinishTrigger(pParse, yymsp[-1].minor.yy19, &all); -} -#line 3581 "parse.c" - /* No destructor defined for trigger_decl */ - /* No destructor defined for BEGIN */ - break; - case 261: -#line 800 "parse.y" -{ - SrcList *pTab = sqliteSrcListAppend(0, &yymsp[-3].minor.yy298, &yymsp[-2].minor.yy298); - sqliteBeginTrigger(pParse, &yymsp[-7].minor.yy298, yymsp[-6].minor.yy372, yymsp[-5].minor.yy290.a, yymsp[-5].minor.yy290.b, pTab, yymsp[-1].minor.yy372, yymsp[0].minor.yy182, yymsp[-9].minor.yy372); -} -#line 3591 "parse.c" - /* No destructor defined for TRIGGER */ - /* No destructor defined for ON */ - break; - case 262: -#line 806 "parse.y" -{ yygotominor.yy372 = TK_BEFORE; } -#line 3598 "parse.c" - /* No destructor defined for BEFORE */ - break; - case 263: -#line 807 "parse.y" -{ yygotominor.yy372 = TK_AFTER; } -#line 3604 "parse.c" - /* No destructor defined for AFTER */ - break; - case 264: -#line 808 "parse.y" -{ yygotominor.yy372 = TK_INSTEAD;} -#line 3610 "parse.c" - /* No destructor defined for INSTEAD */ - /* No destructor defined for OF */ - break; - case 265: -#line 809 "parse.y" -{ yygotominor.yy372 = TK_BEFORE; } -#line 3617 "parse.c" - break; - case 266: -#line 813 "parse.y" -{ yygotominor.yy290.a = TK_DELETE; yygotominor.yy290.b = 0; } -#line 3622 "parse.c" - /* No destructor defined for DELETE */ - break; - case 267: -#line 814 "parse.y" -{ yygotominor.yy290.a = TK_INSERT; yygotominor.yy290.b = 0; } -#line 3628 "parse.c" - /* No destructor defined for INSERT */ - break; - case 268: -#line 815 "parse.y" -{ yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = 0;} -#line 3634 "parse.c" - /* No destructor defined for UPDATE */ - break; - case 269: -#line 816 "parse.y" -{yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = yymsp[0].minor.yy320; } -#line 3640 "parse.c" - /* No destructor defined for UPDATE */ - /* No destructor defined for OF */ - break; - case 270: -#line 819 "parse.y" -{ yygotominor.yy372 = TK_ROW; } -#line 3647 "parse.c" - break; - case 271: -#line 820 "parse.y" -{ yygotominor.yy372 = TK_ROW; } -#line 3652 "parse.c" - /* No destructor defined for FOR */ - /* No destructor defined for EACH */ - /* No destructor defined for ROW */ - break; - case 272: -#line 821 "parse.y" -{ yygotominor.yy372 = TK_STATEMENT; } -#line 3660 "parse.c" - /* No destructor defined for FOR */ - /* No destructor defined for EACH */ - /* No destructor defined for STATEMENT */ - break; - case 273: -#line 824 "parse.y" -{ yygotominor.yy182 = 0; } -#line 3668 "parse.c" - break; - case 274: -#line 825 "parse.y" -{ yygotominor.yy182 = yymsp[0].minor.yy242; } -#line 3673 "parse.c" - /* No destructor defined for WHEN */ - break; - case 275: -#line 829 "parse.y" -{ - yymsp[-2].minor.yy19->pNext = yymsp[0].minor.yy19; - yygotominor.yy19 = yymsp[-2].minor.yy19; -} -#line 3682 "parse.c" - /* No destructor defined for SEMI */ - break; - case 276: -#line 833 "parse.y" -{ yygotominor.yy19 = 0; } -#line 3688 "parse.c" - break; - case 277: -#line 839 "parse.y" -{ yygotominor.yy19 = sqliteTriggerUpdateStep(&yymsp[-3].minor.yy298, yymsp[-1].minor.yy322, yymsp[0].minor.yy242, yymsp[-4].minor.yy372); } -#line 3693 "parse.c" - /* No destructor defined for UPDATE */ - /* No destructor defined for SET */ - break; - case 278: -#line 844 "parse.y" -{yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-5].minor.yy298, yymsp[-4].minor.yy320, yymsp[-1].minor.yy322, 0, yymsp[-7].minor.yy372);} -#line 3700 "parse.c" - /* No destructor defined for INTO */ - /* No destructor defined for VALUES */ - /* No destructor defined for LP */ - /* No destructor defined for RP */ - break; - case 279: -#line 847 "parse.y" -{yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-2].minor.yy298, yymsp[-1].minor.yy320, 0, yymsp[0].minor.yy179, yymsp[-4].minor.yy372);} -#line 3709 "parse.c" - /* No destructor defined for INTO */ - break; - case 280: -#line 851 "parse.y" -{yygotominor.yy19 = sqliteTriggerDeleteStep(&yymsp[-1].minor.yy298, yymsp[0].minor.yy242);} -#line 3715 "parse.c" - /* No destructor defined for DELETE */ - /* No destructor defined for FROM */ - break; - case 281: -#line 854 "parse.y" -{yygotominor.yy19 = sqliteTriggerSelectStep(yymsp[0].minor.yy179); } -#line 3722 "parse.c" - break; - case 282: -#line 857 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, 0); - yygotominor.yy242->iColumn = OE_Ignore; - sqliteExprSpan(yygotominor.yy242, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); -} -#line 3731 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for IGNORE */ - break; - case 283: -#line 862 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298); - yygotominor.yy242->iColumn = OE_Rollback; - sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); -} -#line 3742 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for ROLLBACK */ - /* No destructor defined for COMMA */ - break; - case 284: -#line 867 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298); - yygotominor.yy242->iColumn = OE_Abort; - sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); -} -#line 3754 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for ABORT */ - /* No destructor defined for COMMA */ - break; - case 285: -#line 872 "parse.y" -{ - yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298); - yygotominor.yy242->iColumn = OE_Fail; - sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); -} -#line 3766 "parse.c" - /* No destructor defined for LP */ - /* No destructor defined for FAIL */ - /* No destructor defined for COMMA */ - break; - case 286: -#line 879 "parse.y" -{ - sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&yymsp[-1].minor.yy298,&yymsp[0].minor.yy298)); -} -#line 3776 "parse.c" - /* No destructor defined for DROP */ - /* No destructor defined for TRIGGER */ - break; - case 287: -#line 884 "parse.y" -{ - sqliteAttach(pParse, &yymsp[-3].minor.yy298, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298); -} -#line 3785 "parse.c" - /* No destructor defined for ATTACH */ - /* No destructor defined for database_kw_opt */ - /* No destructor defined for AS */ - break; - case 288: -#line 888 "parse.y" -{ yygotominor.yy298 = yymsp[0].minor.yy298; } -#line 3793 "parse.c" - /* No destructor defined for USING */ - break; - case 289: -#line 889 "parse.y" -{ yygotominor.yy298.z = 0; yygotominor.yy298.n = 0; } -#line 3799 "parse.c" - break; - case 290: - /* No destructor defined for DATABASE */ - break; - case 291: - break; - case 292: -#line 895 "parse.y" -{ - sqliteDetach(pParse, &yymsp[0].minor.yy298); -} -#line 3811 "parse.c" - /* No destructor defined for DETACH */ - /* No destructor defined for database_kw_opt */ - break; - }; - yygoto = yyRuleInfo[yyruleno].lhs; - yysize = yyRuleInfo[yyruleno].nrhs; - yypParser->yyidx -= yysize; - yyact = yy_find_reduce_action(yypParser,yygoto); - if( yyact < YYNSTATE ){ - yy_shift(yypParser,yyact,yygoto,&yygotominor); - }else if( yyact == YYNSTATE + YYNRULE + 1 ){ - yy_accept(yypParser); - } -} - -/* -** The following code executes when the parse fails -*/ -static void yy_parse_failed( - yyParser *yypParser /* The parser */ -){ - sqliteParserARG_FETCH; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will be executed whenever the - ** parser fails */ - sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} - -/* -** The following code executes when a syntax error first occurs. -*/ -static void yy_syntax_error( - yyParser *yypParser, /* The parser */ - int yymajor, /* The major type of the error token */ - YYMINORTYPE yyminor /* The minor type of the error token */ -){ - sqliteParserARG_FETCH; -#define TOKEN (yyminor.yy0) -#line 23 "parse.y" - - if( pParse->zErrMsg==0 ){ - if( TOKEN.z[0] ){ - sqliteErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); - }else{ - sqliteErrorMsg(pParse, "incomplete SQL statement"); - } - } - -#line 3865 "parse.c" - sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} - -/* -** The following is executed when the parser accepts -*/ -static void yy_accept( - yyParser *yypParser /* The parser */ -){ - sqliteParserARG_FETCH; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will be executed whenever the - ** parser accepts */ - sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} - -/* The main parser program. -** The first argument is a pointer to a structure obtained from -** "sqliteParserAlloc" which describes the current state of the parser. -** The second argument is the major token number. The third is -** the minor token. The fourth optional argument is whatever the -** user wants (and specified in the grammar) and is available for -** use by the action routines. -** -** Inputs: -**
    -**
  • A pointer to the parser (an opaque structure.) -**
  • The major token number. -**
  • The minor token number. -**
  • An option argument of a grammar-specified type. -**
-** -** Outputs: -** None. -*/ -void sqliteParser( - void *yyp, /* The parser */ - int yymajor, /* The major token code number */ - sqliteParserTOKENTYPE yyminor /* The value for the token */ - sqliteParserARG_PDECL /* Optional %extra_argument parameter */ -){ - YYMINORTYPE yyminorunion; - int yyact; /* The parser action. */ - int yyendofinput; /* True if we are at the end of input */ - int yyerrorhit = 0; /* True if yymajor has invoked an error */ - yyParser *yypParser; /* The parser */ - - /* (re)initialize the parser, if necessary */ - yypParser = (yyParser*)yyp; - if( yypParser->yyidx<0 ){ - if( yymajor==0 ) return; - yypParser->yyidx = 0; - yypParser->yyerrcnt = -1; - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; - } - yyminorunion.yy0 = yyminor; - yyendofinput = (yymajor==0); - sqliteParserARG_STORE; - -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); - } -#endif - - do{ - yyact = yy_find_shift_action(yypParser,yymajor); - if( yyactyyerrcnt--; - if( yyendofinput && yypParser->yyidx>=0 ){ - yymajor = 0; - }else{ - yymajor = YYNOCODE; - } - }else if( yyact < YYNSTATE + YYNRULE ){ - yy_reduce(yypParser,yyact-YYNSTATE); - }else if( yyact == YY_ERROR_ACTION ){ - int yymx; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); - } -#endif -#ifdef YYERRORSYMBOL - /* A syntax error has occurred. - ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". - ** - ** This is what we do if the grammar does define ERROR: - ** - ** * Call the %syntax_error function. - ** - ** * Begin popping the stack until we enter a state where - ** it is legal to shift the error symbol, then shift - ** the error symbol. - ** - ** * Set the error count to three. - ** - ** * Begin accepting and shifting new tokens. No new error - ** processing will occur until three tokens have been - ** shifted successfully. - ** - */ - if( yypParser->yyerrcnt<0 ){ - yy_syntax_error(yypParser,yymajor,yyminorunion); - } - yymx = yypParser->yystack[yypParser->yyidx].major; - if( yymx==YYERRORSYMBOL || yyerrorhit ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sDiscard input token %s\n", - yyTracePrompt,yyTokenName[yymajor]); - } -#endif - yy_destructor(yymajor,&yyminorunion); - yymajor = YYNOCODE; - }else{ - while( - yypParser->yyidx >= 0 && - yymx != YYERRORSYMBOL && - (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE - ){ - yy_pop_parser_stack(yypParser); - } - if( yypParser->yyidx < 0 || yymajor==0 ){ - yy_destructor(yymajor,&yyminorunion); - yy_parse_failed(yypParser); - yymajor = YYNOCODE; - }else if( yymx!=YYERRORSYMBOL ){ - YYMINORTYPE u2; - u2.YYERRSYMDT = 0; - yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); - } - } - yypParser->yyerrcnt = 3; - yyerrorhit = 1; -#else /* YYERRORSYMBOL is not defined */ - /* This is what we do if the grammar does not define ERROR: - ** - ** * Report an error message, and throw away the input token. - ** - ** * If the input token is $, then fail the parse. - ** - ** As before, subsequent error messages are suppressed until - ** three input tokens have been successfully shifted. - */ - if( yypParser->yyerrcnt<=0 ){ - yy_syntax_error(yypParser,yymajor,yyminorunion); - } - yypParser->yyerrcnt = 3; - yy_destructor(yymajor,&yyminorunion); - if( yyendofinput ){ - yy_parse_failed(yypParser); - } - yymajor = YYNOCODE; -#endif - }else{ - yy_accept(yypParser); - yymajor = YYNOCODE; - } - }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); - return; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/parse.h b/dbLifeLog/DBD-SQLite2-0.33/parse.h deleted file mode 100644 index 188a336..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/parse.h +++ /dev/null @@ -1,130 +0,0 @@ -#define TK_END_OF_FILE 1 -#define TK_ILLEGAL 2 -#define TK_SPACE 3 -#define TK_UNCLOSED_STRING 4 -#define TK_COMMENT 5 -#define TK_FUNCTION 6 -#define TK_COLUMN 7 -#define TK_AGG_FUNCTION 8 -#define TK_SEMI 9 -#define TK_EXPLAIN 10 -#define TK_BEGIN 11 -#define TK_TRANSACTION 12 -#define TK_COMMIT 13 -#define TK_END 14 -#define TK_ROLLBACK 15 -#define TK_CREATE 16 -#define TK_TABLE 17 -#define TK_TEMP 18 -#define TK_LP 19 -#define TK_RP 20 -#define TK_AS 21 -#define TK_COMMA 22 -#define TK_ID 23 -#define TK_ABORT 24 -#define TK_AFTER 25 -#define TK_ASC 26 -#define TK_ATTACH 27 -#define TK_BEFORE 28 -#define TK_CASCADE 29 -#define TK_CLUSTER 30 -#define TK_CONFLICT 31 -#define TK_COPY 32 -#define TK_DATABASE 33 -#define TK_DEFERRED 34 -#define TK_DELIMITERS 35 -#define TK_DESC 36 -#define TK_DETACH 37 -#define TK_EACH 38 -#define TK_FAIL 39 -#define TK_FOR 40 -#define TK_GLOB 41 -#define TK_IGNORE 42 -#define TK_IMMEDIATE 43 -#define TK_INITIALLY 44 -#define TK_INSTEAD 45 -#define TK_LIKE 46 -#define TK_MATCH 47 -#define TK_KEY 48 -#define TK_OF 49 -#define TK_OFFSET 50 -#define TK_PRAGMA 51 -#define TK_RAISE 52 -#define TK_REPLACE 53 -#define TK_RESTRICT 54 -#define TK_ROW 55 -#define TK_STATEMENT 56 -#define TK_TRIGGER 57 -#define TK_VACUUM 58 -#define TK_VIEW 59 -#define TK_OR 60 -#define TK_AND 61 -#define TK_NOT 62 -#define TK_EQ 63 -#define TK_NE 64 -#define TK_ISNULL 65 -#define TK_NOTNULL 66 -#define TK_IS 67 -#define TK_BETWEEN 68 -#define TK_IN 69 -#define TK_GT 70 -#define TK_GE 71 -#define TK_LT 72 -#define TK_LE 73 -#define TK_BITAND 74 -#define TK_BITOR 75 -#define TK_LSHIFT 76 -#define TK_RSHIFT 77 -#define TK_PLUS 78 -#define TK_MINUS 79 -#define TK_STAR 80 -#define TK_SLASH 81 -#define TK_REM 82 -#define TK_CONCAT 83 -#define TK_UMINUS 84 -#define TK_UPLUS 85 -#define TK_BITNOT 86 -#define TK_STRING 87 -#define TK_JOIN_KW 88 -#define TK_INTEGER 89 -#define TK_CONSTRAINT 90 -#define TK_DEFAULT 91 -#define TK_FLOAT 92 -#define TK_NULL 93 -#define TK_PRIMARY 94 -#define TK_UNIQUE 95 -#define TK_CHECK 96 -#define TK_REFERENCES 97 -#define TK_COLLATE 98 -#define TK_ON 99 -#define TK_DELETE 100 -#define TK_UPDATE 101 -#define TK_INSERT 102 -#define TK_SET 103 -#define TK_DEFERRABLE 104 -#define TK_FOREIGN 105 -#define TK_DROP 106 -#define TK_UNION 107 -#define TK_ALL 108 -#define TK_INTERSECT 109 -#define TK_EXCEPT 110 -#define TK_SELECT 111 -#define TK_DISTINCT 112 -#define TK_DOT 113 -#define TK_FROM 114 -#define TK_JOIN 115 -#define TK_USING 116 -#define TK_ORDER 117 -#define TK_BY 118 -#define TK_GROUP 119 -#define TK_HAVING 120 -#define TK_LIMIT 121 -#define TK_WHERE 122 -#define TK_INTO 123 -#define TK_VALUES 124 -#define TK_VARIABLE 125 -#define TK_CASE 126 -#define TK_WHEN 127 -#define TK_THEN 128 -#define TK_ELSE 129 -#define TK_INDEX 130 diff --git a/dbLifeLog/DBD-SQLite2-0.33/parse.o b/dbLifeLog/DBD-SQLite2-0.33/parse.o deleted file mode 100644 index 995f015be2804868942cc8505b22fe59322e959b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41056 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 - -/* -** Interpret the given string as a boolean value. -*/ -static int getBoolean(const char *z){ - static char *azTrue[] = { "yes", "on", "true" }; - int i; - if( z[0]==0 ) return 0; - if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){ - return atoi(z); - } - for(i=0; i='0' && z[0]<='2' ){ - return z[0] - '0'; - }else if( sqliteStrICmp(z, "file")==0 ){ - return 1; - }else if( sqliteStrICmp(z, "memory")==0 ){ - return 2; - }else{ - return 0; - } -} - -/* -** If the TEMP database is open, close it and mark the database schema -** as needing reloading. This must be done when using the TEMP_STORE -** or DEFAULT_TEMP_STORE pragmas. -*/ -static int changeTempStorage(Parse *pParse, const char *zStorageType){ - int ts = getTempStore(zStorageType); - sqlite *db = pParse->db; - if( db->temp_store==ts ) return SQLITE_OK; - if( db->aDb[1].pBt!=0 ){ - if( db->flags & SQLITE_InTrans ){ - sqliteErrorMsg(pParse, "temporary storage cannot be changed " - "from within a transaction"); - return SQLITE_ERROR; - } - sqliteBtreeClose(db->aDb[1].pBt); - db->aDb[1].pBt = 0; - sqliteResetInternalSchema(db, 0); - } - db->temp_store = ts; - return SQLITE_OK; -} - -/* -** Check to see if zRight and zLeft refer to a pragma that queries -** or changes one of the flags in db->flags. Return 1 if so and 0 if not. -** Also, implement the pragma. -*/ -static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ - static const struct { - const char *zName; /* Name of the pragma */ - int mask; /* Mask for the db->flags value */ - } aPragma[] = { - { "vdbe_trace", SQLITE_VdbeTrace }, - { "full_column_names", SQLITE_FullColNames }, - { "short_column_names", SQLITE_ShortColNames }, - { "show_datatypes", SQLITE_ReportTypes }, - { "count_changes", SQLITE_CountRows }, - { "empty_result_callbacks", SQLITE_NullCallback }, - }; - int i; - for(i=0; idb; - Vdbe *v; - if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){ - sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC); - sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC); - sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0, - OP_Callback, 1, 0, - 0); - }else if( getBoolean(zRight) ){ - db->flags |= aPragma[i].mask; - }else{ - db->flags &= ~aPragma[i].mask; - } - return 1; - } - } - return 0; -} - -/* -** Process a pragma statement. -** -** Pragmas are of this form: -** -** PRAGMA id = value -** -** The identifier might also be a string. The value is a string, and -** identifier, or a number. If minusFlag is true, then the value is -** a number that was preceded by a minus sign. -*/ -void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ - char *zLeft = 0; - char *zRight = 0; - sqlite *db = pParse->db; - Vdbe *v = sqliteGetVdbe(pParse); - if( v==0 ) return; - - zLeft = sqliteStrNDup(pLeft->z, pLeft->n); - sqliteDequote(zLeft); - if( minusFlag ){ - zRight = 0; - sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0); - }else{ - zRight = sqliteStrNDup(pRight->z, pRight->n); - sqliteDequote(zRight); - } - if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){ - sqliteFree(zLeft); - sqliteFree(zRight); - return; - } - - /* - ** PRAGMA default_cache_size - ** PRAGMA default_cache_size=N - ** - ** The first form reports the current persistent setting for the - ** page cache size. The value returned is the maximum number of - ** pages in the page cache. The second form sets both the current - ** page cache size value and the persistent page cache size value - ** stored in the database file. - ** - ** The default cache size is stored in meta-value 2 of page 1 of the - ** database file. The cache size is actually the absolute value of - ** this memory location. The sign of meta-value 2 determines the - ** synchronous setting. A negative value means synchronous is off - ** and a positive value means synchronous is on. - */ - if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){ - static VdbeOpList getCacheSize[] = { - { OP_ReadCookie, 0, 2, 0}, - { OP_AbsValue, 0, 0, 0}, - { OP_Dup, 0, 0, 0}, - { OP_Integer, 0, 0, 0}, - { OP_Ne, 0, 6, 0}, - { OP_Integer, 0, 0, 0}, /* 5 */ - { OP_ColumnName, 0, 1, "cache_size"}, - { OP_Callback, 1, 0, 0}, - }; - int addr; - if( pRight->z==pLeft->z ){ - addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); - sqliteVdbeChangeP1(v, addr+5, MAX_PAGES); - }else{ - int size = atoi(zRight); - if( size<0 ) size = -size; - sqliteBeginWriteOperation(pParse, 0, 0); - sqliteVdbeAddOp(v, OP_Integer, size, 0); - sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2); - addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0); - sqliteVdbeAddOp(v, OP_Ge, 0, addr+3); - sqliteVdbeAddOp(v, OP_Negative, 0, 0); - sqliteVdbeAddOp(v, OP_SetCookie, 0, 2); - sqliteEndWriteOperation(pParse); - db->cache_size = db->cache_size<0 ? -size : size; - sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); - } - }else - - /* - ** PRAGMA cache_size - ** PRAGMA cache_size=N - ** - ** The first form reports the current local setting for the - ** page cache size. The local setting can be different from - ** the persistent cache size value that is stored in the database - ** file itself. The value returned is the maximum number of - ** pages in the page cache. The second form sets the local - ** page cache size value. It does not change the persistent - ** cache size stored on the disk so the cache size will revert - ** to its default value when the database is closed and reopened. - ** N should be a positive integer. - */ - if( sqliteStrICmp(zLeft,"cache_size")==0 ){ - static VdbeOpList getCacheSize[] = { - { OP_ColumnName, 0, 1, "cache_size"}, - { OP_Callback, 1, 0, 0}, - }; - if( pRight->z==pLeft->z ){ - int size = db->cache_size;; - if( size<0 ) size = -size; - sqliteVdbeAddOp(v, OP_Integer, size, 0); - sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); - }else{ - int size = atoi(zRight); - if( size<0 ) size = -size; - if( db->cache_size<0 ) size = -size; - db->cache_size = size; - sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); - } - }else - - /* - ** PRAGMA default_synchronous - ** PRAGMA default_synchronous=ON|OFF|NORMAL|FULL - ** - ** The first form returns the persistent value of the "synchronous" setting - ** that is stored in the database. This is the synchronous setting that - ** is used whenever the database is opened unless overridden by a separate - ** "synchronous" pragma. The second form changes the persistent and the - ** local synchronous setting to the value given. - ** - ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls - ** to make sure data is committed to disk. Write operations are very fast, - ** but a power failure can leave the database in an inconsistent state. - ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to - ** make sure data is being written to disk. The risk of corruption due to - ** a power loss in this mode is negligible but non-zero. If synchronous - ** is FULL, extra fsync()s occur to reduce the risk of corruption to near - ** zero, but with a write performance penalty. The default mode is NORMAL. - */ - if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){ - static VdbeOpList getSync[] = { - { OP_ColumnName, 0, 1, "synchronous"}, - { OP_ReadCookie, 0, 3, 0}, - { OP_Dup, 0, 0, 0}, - { OP_If, 0, 0, 0}, /* 3 */ - { OP_ReadCookie, 0, 2, 0}, - { OP_Integer, 0, 0, 0}, - { OP_Lt, 0, 5, 0}, - { OP_AddImm, 1, 0, 0}, - { OP_Callback, 1, 0, 0}, - { OP_Halt, 0, 0, 0}, - { OP_AddImm, -1, 0, 0}, /* 10 */ - { OP_Callback, 1, 0, 0} - }; - if( pRight->z==pLeft->z ){ - int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync); - sqliteVdbeChangeP2(v, addr+3, addr+10); - }else{ - int addr; - int size = db->cache_size; - if( size<0 ) size = -size; - sqliteBeginWriteOperation(pParse, 0, 0); - sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2); - sqliteVdbeAddOp(v, OP_Dup, 0, 0); - addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0); - sqliteVdbeAddOp(v, OP_Ne, 0, addr+3); - sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0); - sqliteVdbeAddOp(v, OP_AbsValue, 0, 0); - db->safety_level = getSafetyLevel(zRight)+1; - if( db->safety_level==1 ){ - sqliteVdbeAddOp(v, OP_Negative, 0, 0); - size = -size; - } - sqliteVdbeAddOp(v, OP_SetCookie, 0, 2); - sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0); - sqliteVdbeAddOp(v, OP_SetCookie, 0, 3); - sqliteEndWriteOperation(pParse); - db->cache_size = size; - sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); - sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); - } - }else - - /* - ** PRAGMA synchronous - ** PRAGMA synchronous=OFF|ON|NORMAL|FULL - ** - ** Return or set the local value of the synchronous flag. Changing - ** the local value does not make changes to the disk file and the - ** default value will be restored the next time the database is - ** opened. - */ - if( sqliteStrICmp(zLeft,"synchronous")==0 ){ - static VdbeOpList getSync[] = { - { OP_ColumnName, 0, 1, "synchronous"}, - { OP_Callback, 1, 0, 0}, - }; - if( pRight->z==pLeft->z ){ - sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0); - sqliteVdbeAddOpList(v, ArraySize(getSync), getSync); - }else{ - int size = db->cache_size; - if( size<0 ) size = -size; - db->safety_level = getSafetyLevel(zRight)+1; - if( db->safety_level==1 ) size = -size; - db->cache_size = size; - sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); - sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); - } - }else - -#ifndef NDEBUG - if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){ - if( getBoolean(zRight) ){ - always_code_trigger_setup = 1; - }else{ - always_code_trigger_setup = 0; - } - }else -#endif - - if( flagPragma(pParse, zLeft, zRight) ){ - /* The flagPragma() call also generates any necessary code */ - }else - - if( sqliteStrICmp(zLeft, "table_info")==0 ){ - Table *pTab; - pTab = sqliteFindTable(db, zRight, 0); - if( pTab ){ - static VdbeOpList tableInfoPreface[] = { - { OP_ColumnName, 0, 0, "cid"}, - { OP_ColumnName, 1, 0, "name"}, - { OP_ColumnName, 2, 0, "type"}, - { OP_ColumnName, 3, 0, "notnull"}, - { OP_ColumnName, 4, 0, "dflt_value"}, - { OP_ColumnName, 5, 1, "pk"}, - }; - int i; - sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); - sqliteViewGetColumnNames(pParse, pTab); - for(i=0; inCol; i++){ - sqliteVdbeAddOp(v, OP_Integer, i, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zName, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, - pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0); - sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, - pTab->aCol[i].zDflt, P3_STATIC); - sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0); - sqliteVdbeAddOp(v, OP_Callback, 6, 0); - } - } - }else - - if( sqliteStrICmp(zLeft, "index_info")==0 ){ - Index *pIdx; - Table *pTab; - pIdx = sqliteFindIndex(db, zRight, 0); - if( pIdx ){ - static VdbeOpList tableInfoPreface[] = { - { OP_ColumnName, 0, 0, "seqno"}, - { OP_ColumnName, 1, 0, "cid"}, - { OP_ColumnName, 2, 1, "name"}, - }; - int i; - pTab = pIdx->pTable; - sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); - for(i=0; inColumn; i++){ - int cnum = pIdx->aiColumn[i]; - sqliteVdbeAddOp(v, OP_Integer, i, 0); - sqliteVdbeAddOp(v, OP_Integer, cnum, 0); - assert( pTab->nCol>cnum ); - sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[cnum].zName, 0); - sqliteVdbeAddOp(v, OP_Callback, 3, 0); - } - } - }else - - if( sqliteStrICmp(zLeft, "index_list")==0 ){ - Index *pIdx; - Table *pTab; - pTab = sqliteFindTable(db, zRight, 0); - if( pTab ){ - v = sqliteGetVdbe(pParse); - pIdx = pTab->pIndex; - } - if( pTab && pIdx ){ - int i = 0; - static VdbeOpList indexListPreface[] = { - { OP_ColumnName, 0, 0, "seq"}, - { OP_ColumnName, 1, 0, "name"}, - { OP_ColumnName, 2, 1, "unique"}, - }; - - sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); - while(pIdx){ - sqliteVdbeAddOp(v, OP_Integer, i, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0); - sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0); - sqliteVdbeAddOp(v, OP_Callback, 3, 0); - ++i; - pIdx = pIdx->pNext; - } - } - }else - - if( sqliteStrICmp(zLeft, "foreign_key_list")==0 ){ - FKey *pFK; - Table *pTab; - pTab = sqliteFindTable(db, zRight, 0); - if( pTab ){ - v = sqliteGetVdbe(pParse); - pFK = pTab->pFKey; - } - if( pTab && pFK ){ - int i = 0; - static VdbeOpList indexListPreface[] = { - { OP_ColumnName, 0, 0, "id"}, - { OP_ColumnName, 1, 0, "seq"}, - { OP_ColumnName, 2, 0, "table"}, - { OP_ColumnName, 3, 0, "from"}, - { OP_ColumnName, 4, 1, "to"}, - }; - - sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); - while(pFK){ - int j; - for(j=0; jnCol; j++){ - sqliteVdbeAddOp(v, OP_Integer, i, 0); - sqliteVdbeAddOp(v, OP_Integer, j, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, pFK->zTo, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, - pTab->aCol[pFK->aCol[j].iFrom].zName, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, pFK->aCol[j].zCol, 0); - sqliteVdbeAddOp(v, OP_Callback, 5, 0); - } - ++i; - pFK = pFK->pNextFrom; - } - } - }else - - if( sqliteStrICmp(zLeft, "database_list")==0 ){ - int i; - static VdbeOpList indexListPreface[] = { - { OP_ColumnName, 0, 0, "seq"}, - { OP_ColumnName, 1, 0, "name"}, - { OP_ColumnName, 2, 1, "file"}, - }; - - sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); - for(i=0; inDb; i++){ - if( db->aDb[i].pBt==0 ) continue; - assert( db->aDb[i].zName!=0 ); - sqliteVdbeAddOp(v, OP_Integer, i, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, 0); - sqliteVdbeOp3(v, OP_String, 0, 0, - sqliteBtreeGetFilename(db->aDb[i].pBt), 0); - sqliteVdbeAddOp(v, OP_Callback, 3, 0); - } - }else - - - /* - ** PRAGMA temp_store - ** PRAGMA temp_store = "default"|"memory"|"file" - ** - ** Return or set the local value of the temp_store flag. Changing - ** the local value does not make changes to the disk file and the default - ** value will be restored the next time the database is opened. - ** - ** Note that it is possible for the library compile-time options to - ** override this setting - */ - if( sqliteStrICmp(zLeft, "temp_store")==0 ){ - static VdbeOpList getTmpDbLoc[] = { - { OP_ColumnName, 0, 1, "temp_store"}, - { OP_Callback, 1, 0, 0}, - }; - if( pRight->z==pLeft->z ){ - sqliteVdbeAddOp(v, OP_Integer, db->temp_store, 0); - sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc); - }else{ - changeTempStorage(pParse, zRight); - } - }else - - /* - ** PRAGMA default_temp_store - ** PRAGMA default_temp_store = "default"|"memory"|"file" - ** - ** Return or set the value of the persistent temp_store flag. Any - ** change does not take effect until the next time the database is - ** opened. - ** - ** Note that it is possible for the library compile-time options to - ** override this setting - */ - if( sqliteStrICmp(zLeft, "default_temp_store")==0 ){ - static VdbeOpList getTmpDbLoc[] = { - { OP_ColumnName, 0, 1, "temp_store"}, - { OP_ReadCookie, 0, 5, 0}, - { OP_Callback, 1, 0, 0}}; - if( pRight->z==pLeft->z ){ - sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc); - }else{ - sqliteBeginWriteOperation(pParse, 0, 0); - sqliteVdbeAddOp(v, OP_Integer, getTempStore(zRight), 0); - sqliteVdbeAddOp(v, OP_SetCookie, 0, 5); - sqliteEndWriteOperation(pParse); - } - }else - -#ifndef NDEBUG - if( sqliteStrICmp(zLeft, "parser_trace")==0 ){ - extern void sqliteParserTrace(FILE*, char *); - if( getBoolean(zRight) ){ - sqliteParserTrace(stdout, "parser: "); - }else{ - sqliteParserTrace(0, 0); - } - }else -#endif - - if( sqliteStrICmp(zLeft, "integrity_check")==0 ){ - int i, j, addr; - - /* Code that initializes the integrity check program. Set the - ** error count 0 - */ - static VdbeOpList initCode[] = { - { OP_Integer, 0, 0, 0}, - { OP_MemStore, 0, 1, 0}, - { OP_ColumnName, 0, 1, "integrity_check"}, - }; - - /* Code to do an BTree integrity check on a single database file. - */ - static VdbeOpList checkDb[] = { - { OP_SetInsert, 0, 0, "2"}, - { OP_Integer, 0, 0, 0}, /* 1 */ - { OP_OpenRead, 0, 2, 0}, - { OP_Rewind, 0, 7, 0}, /* 3 */ - { OP_Column, 0, 3, 0}, /* 4 */ - { OP_SetInsert, 0, 0, 0}, - { OP_Next, 0, 4, 0}, /* 6 */ - { OP_IntegrityCk, 0, 0, 0}, /* 7 */ - { OP_Dup, 0, 1, 0}, - { OP_String, 0, 0, "ok"}, - { OP_StrEq, 0, 12, 0}, /* 10 */ - { OP_MemIncr, 0, 0, 0}, - { OP_String, 0, 0, "*** in database "}, - { OP_String, 0, 0, 0}, /* 13 */ - { OP_String, 0, 0, " ***\n"}, - { OP_Pull, 3, 0, 0}, - { OP_Concat, 4, 1, 0}, - { OP_Callback, 1, 0, 0}, - }; - - /* Code that appears at the end of the integrity check. If no error - ** messages have been generated, output OK. Otherwise output the - ** error message - */ - static VdbeOpList endCode[] = { - { OP_MemLoad, 0, 0, 0}, - { OP_Integer, 0, 0, 0}, - { OP_Ne, 0, 0, 0}, /* 2 */ - { OP_String, 0, 0, "ok"}, - { OP_Callback, 1, 0, 0}, - }; - - /* Initialize the VDBE program */ - sqliteVdbeAddOpList(v, ArraySize(initCode), initCode); - - /* Do an integrity check on each database file */ - for(i=0; inDb; i++){ - HashElem *x; - - /* Do an integrity check of the B-Tree - */ - addr = sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb); - sqliteVdbeChangeP1(v, addr+1, i); - sqliteVdbeChangeP2(v, addr+3, addr+7); - sqliteVdbeChangeP2(v, addr+6, addr+4); - sqliteVdbeChangeP2(v, addr+7, i); - sqliteVdbeChangeP2(v, addr+10, addr+ArraySize(checkDb)); - sqliteVdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC); - - /* Make sure all the indices are constructed correctly. - */ - sqliteCodeVerifySchema(pParse, i); - for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - Index *pIdx; - int loopTop; - - if( pTab->pIndex==0 ) continue; - sqliteVdbeAddOp(v, OP_Integer, i, 0); - sqliteVdbeOp3(v, OP_OpenRead, 1, pTab->tnum, pTab->zName, 0); - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - if( pIdx->tnum==0 ) continue; - sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0); - sqliteVdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, pIdx->zName, 0); - } - sqliteVdbeAddOp(v, OP_Integer, 0, 0); - sqliteVdbeAddOp(v, OP_MemStore, 1, 1); - loopTop = sqliteVdbeAddOp(v, OP_Rewind, 1, 0); - sqliteVdbeAddOp(v, OP_MemIncr, 1, 0); - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - int k, jmp2; - static VdbeOpList idxErr[] = { - { OP_MemIncr, 0, 0, 0}, - { OP_String, 0, 0, "rowid "}, - { OP_Recno, 1, 0, 0}, - { OP_String, 0, 0, " missing from index "}, - { OP_String, 0, 0, 0}, /* 4 */ - { OP_Concat, 4, 0, 0}, - { OP_Callback, 1, 0, 0}, - }; - sqliteVdbeAddOp(v, OP_Recno, 1, 0); - for(k=0; knColumn; k++){ - int idx = pIdx->aiColumn[k]; - if( idx==pTab->iPKey ){ - sqliteVdbeAddOp(v, OP_Recno, 1, 0); - }else{ - sqliteVdbeAddOp(v, OP_Column, 1, idx); - } - } - sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); - if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx); - jmp2 = sqliteVdbeAddOp(v, OP_Found, j+2, 0); - addr = sqliteVdbeAddOpList(v, ArraySize(idxErr), idxErr); - sqliteVdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC); - sqliteVdbeChangeP2(v, jmp2, sqliteVdbeCurrentAddr(v)); - } - sqliteVdbeAddOp(v, OP_Next, 1, loopTop+1); - sqliteVdbeChangeP2(v, loopTop, sqliteVdbeCurrentAddr(v)); - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - static VdbeOpList cntIdx[] = { - { OP_Integer, 0, 0, 0}, - { OP_MemStore, 2, 1, 0}, - { OP_Rewind, 0, 0, 0}, /* 2 */ - { OP_MemIncr, 2, 0, 0}, - { OP_Next, 0, 0, 0}, /* 4 */ - { OP_MemLoad, 1, 0, 0}, - { OP_MemLoad, 2, 0, 0}, - { OP_Eq, 0, 0, 0}, /* 7 */ - { OP_MemIncr, 0, 0, 0}, - { OP_String, 0, 0, "wrong # of entries in index "}, - { OP_String, 0, 0, 0}, /* 10 */ - { OP_Concat, 2, 0, 0}, - { OP_Callback, 1, 0, 0}, - }; - if( pIdx->tnum==0 ) continue; - addr = sqliteVdbeAddOpList(v, ArraySize(cntIdx), cntIdx); - sqliteVdbeChangeP1(v, addr+2, j+2); - sqliteVdbeChangeP2(v, addr+2, addr+5); - sqliteVdbeChangeP1(v, addr+4, j+2); - sqliteVdbeChangeP2(v, addr+4, addr+3); - sqliteVdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx)); - sqliteVdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC); - } - } - } - addr = sqliteVdbeAddOpList(v, ArraySize(endCode), endCode); - sqliteVdbeChangeP2(v, addr+2, addr+ArraySize(endCode)); - }else - - {} - sqliteFree(zLeft); - sqliteFree(zRight); -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/pragma.o b/dbLifeLog/DBD-SQLite2-0.33/pragma.o deleted file mode 100644 index fc12312e5454ee6c6389b3945004707c7d5f7a1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17896 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 diff --git a/dbLifeLog/DBD-SQLite2-0.33/printf.c b/dbLifeLog/DBD-SQLite2-0.33/printf.c deleted file mode 100644 index f867d62..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/printf.c +++ /dev/null @@ -1,858 +0,0 @@ -/* -** The "printf" code that follows dates from the 1980's. It is in -** the public domain. The original comments are included here for -** completeness. They are very out-of-date but might be useful as -** an historical reference. Most of the "enhancements" have been backed -** out so that the functionality is now the same as standard printf(). -** -************************************************************************** -** -** The following modules is an enhanced replacement for the "printf" subroutines -** found in the standard C library. The following enhancements are -** supported: -** -** + Additional functions. The standard set of "printf" functions -** includes printf, fprintf, sprintf, vprintf, vfprintf, and -** vsprintf. This module adds the following: -** -** * snprintf -- Works like sprintf, but has an extra argument -** which is the size of the buffer written to. -** -** * mprintf -- Similar to sprintf. Writes output to memory -** obtained from malloc. -** -** * xprintf -- Calls a function to dispose of output. -** -** * nprintf -- No output, but returns the number of characters -** that would have been output by printf. -** -** * A v- version (ex: vsnprintf) of every function is also -** supplied. -** -** + A few extensions to the formatting notation are supported: -** -** * The "=" flag (similar to "-") causes the output to be -** be centered in the appropriately sized field. -** -** * The %b field outputs an integer in binary notation. -** -** * The %c field now accepts a precision. The character output -** is repeated by the number of times the precision specifies. -** -** * The %' field works like %c, but takes as its character the -** next character of the format string, instead of the next -** argument. For example, printf("%.78'-") prints 78 minus -** signs, the same as printf("%.78c",'-'). -** -** + When compiled using GCC on a SPARC, this version of printf is -** faster than the library printf for SUN OS 4.1. -** -** + All functions are fully reentrant. -** -*/ -#include "sqliteInt.h" - -/* -** Conversion types fall into various categories as defined by the -** following enumeration. -*/ -#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ -#define etFLOAT 2 /* Floating point. %f */ -#define etEXP 3 /* Exponentional notation. %e and %E */ -#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ -#define etSIZE 5 /* Return number of characters processed so far. %n */ -#define etSTRING 6 /* Strings. %s */ -#define etDYNSTRING 7 /* Dynamically allocated strings. %z */ -#define etPERCENT 8 /* Percent symbol. %% */ -#define etCHARX 9 /* Characters. %c */ -#define etERROR 10 /* Used to indicate no such conversion type */ -/* The rest are extensions, not normally found in printf() */ -#define etCHARLIT 11 /* Literal characters. %' */ -#define etSQLESCAPE 12 /* Strings with '\'' doubled. %q */ -#define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '', - NULL pointers replaced by SQL NULL. %Q */ -#define etTOKEN 14 /* a pointer to a Token structure */ -#define etSRCLIST 15 /* a pointer to a SrcList */ - - -/* -** An "etByte" is an 8-bit unsigned value. -*/ -typedef unsigned char etByte; - -/* -** Each builtin conversion character (ex: the 'd' in "%d") is described -** by an instance of the following structure -*/ -typedef struct et_info { /* Information about each format field */ - char fmttype; /* The format field code letter */ - etByte base; /* The base for radix conversion */ - etByte flags; /* One or more of FLAG_ constants below */ - etByte type; /* Conversion paradigm */ - char *charset; /* The character set for conversion */ - char *prefix; /* Prefix on non-zero values in alt format */ -} et_info; - -/* -** Allowed values for et_info.flags -*/ -#define FLAG_SIGNED 1 /* True if the value to convert is signed */ -#define FLAG_INTERN 2 /* True if for internal use only */ - - -/* -** The following table is searched linearly, so it is good to put the -** most frequently used conversion types first. -*/ -static et_info fmtinfo[] = { - { 'd', 10, 1, etRADIX, "0123456789", 0 }, - { 's', 0, 0, etSTRING, 0, 0 }, - { 'z', 0, 2, etDYNSTRING, 0, 0 }, - { 'q', 0, 0, etSQLESCAPE, 0, 0 }, - { 'Q', 0, 0, etSQLESCAPE2, 0, 0 }, - { 'c', 0, 0, etCHARX, 0, 0 }, - { 'o', 8, 0, etRADIX, "01234567", "0" }, - { 'u', 10, 0, etRADIX, "0123456789", 0 }, - { 'x', 16, 0, etRADIX, "0123456789abcdef", "x0" }, - { 'X', 16, 0, etRADIX, "0123456789ABCDEF", "X0" }, - { 'f', 0, 1, etFLOAT, 0, 0 }, - { 'e', 0, 1, etEXP, "e", 0 }, - { 'E', 0, 1, etEXP, "E", 0 }, - { 'g', 0, 1, etGENERIC, "e", 0 }, - { 'G', 0, 1, etGENERIC, "E", 0 }, - { 'i', 10, 1, etRADIX, "0123456789", 0 }, - { 'n', 0, 0, etSIZE, 0, 0 }, - { '%', 0, 0, etPERCENT, 0, 0 }, - { 'p', 10, 0, etRADIX, "0123456789", 0 }, - { 'T', 0, 2, etTOKEN, 0, 0 }, - { 'S', 0, 2, etSRCLIST, 0, 0 }, -}; -#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) - -/* -** If NOFLOATINGPOINT is defined, then none of the floating point -** conversions will work. -*/ -#ifndef etNOFLOATINGPOINT -/* -** "*val" is a double such that 0.1 <= *val < 10.0 -** Return the ascii code for the leading digit of *val, then -** multiply "*val" by 10.0 to renormalize. -** -** Example: -** input: *val = 3.14159 -** output: *val = 1.4159 function return = '3' -** -** The counter *cnt is incremented each time. After counter exceeds -** 16 (the number of significant digits in a 64-bit float) '0' is -** always returned. -*/ -static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ - int digit; - LONGDOUBLE_TYPE d; - if( (*cnt)++ >= 16 ) return '0'; - digit = (int)*val; - d = digit; - digit += '0'; - *val = (*val - d)*10.0; - return digit; -} -#endif - -#define etBUFSIZE 1000 /* Size of the output buffer */ - -/* -** The root program. All variations call this core. -** -** INPUTS: -** func This is a pointer to a function taking three arguments -** 1. A pointer to anything. Same as the "arg" parameter. -** 2. A pointer to the list of characters to be output -** (Note, this list is NOT null terminated.) -** 3. An integer number of characters to be output. -** (Note: This number might be zero.) -** -** arg This is the pointer to anything which will be passed as the -** first argument to "func". Use it for whatever you like. -** -** fmt This is the format string, as in the usual print. -** -** ap This is a pointer to a list of arguments. Same as in -** vfprint. -** -** OUTPUTS: -** The return value is the total number of characters sent to -** the function "func". Returns -1 on a error. -** -** Note that the order in which automatic variables are declared below -** seems to make a big difference in determining how fast this beast -** will run. -*/ -static int vxprintf( - void (*func)(void*,const char*,int), /* Consumer of text */ - void *arg, /* First argument to the consumer */ - int useExtended, /* Allow extended %-conversions */ - const char *fmt, /* Format string */ - va_list ap /* arguments */ -){ - int c; /* Next character in the format string */ - char *bufpt; /* Pointer to the conversion buffer */ - int precision; /* Precision of the current field */ - int length; /* Length of the field */ - int idx; /* A general purpose loop counter */ - int count; /* Total number of characters output */ - int width; /* Width of the current field */ - etByte flag_leftjustify; /* True if "-" flag is present */ - etByte flag_plussign; /* True if "+" flag is present */ - etByte flag_blanksign; /* True if " " flag is present */ - etByte flag_alternateform; /* True if "#" flag is present */ - etByte flag_zeropad; /* True if field width constant starts with zero */ - etByte flag_long; /* True if "l" flag is present */ - unsigned long longvalue; /* Value for integer types */ - LONGDOUBLE_TYPE realvalue; /* Value for real types */ - et_info *infop; /* Pointer to the appropriate info structure */ - char buf[etBUFSIZE]; /* Conversion buffer */ - char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ - etByte errorflag = 0; /* True if an error is encountered */ - etByte xtype; /* Conversion paradigm */ - char *zExtra; /* Extra memory used for etTCLESCAPE conversions */ - static char spaces[] = " "; -#define etSPACESIZE (sizeof(spaces)-1) -#ifndef etNOFLOATINGPOINT - int exp; /* exponent of real numbers */ - double rounder; /* Used for rounding floating point values */ - etByte flag_dp; /* True if decimal point should be shown */ - etByte flag_rtz; /* True if trailing zeros should be removed */ - etByte flag_exp; /* True to force display of the exponent */ - int nsd; /* Number of significant digits returned */ -#endif - - func(arg,"",0); - count = length = 0; - bufpt = 0; - for(; (c=(*fmt))!=0; ++fmt){ - if( c!='%' ){ - int amt; - bufpt = (char *)fmt; - amt = 1; - while( (c=(*++fmt))!='%' && c!=0 ) amt++; - (*func)(arg,bufpt,amt); - count += amt; - if( c==0 ) break; - } - if( (c=(*++fmt))==0 ){ - errorflag = 1; - (*func)(arg,"%",1); - count++; - break; - } - /* Find out what flags are present */ - flag_leftjustify = flag_plussign = flag_blanksign = - flag_alternateform = flag_zeropad = 0; - do{ - switch( c ){ - case '-': flag_leftjustify = 1; c = 0; break; - case '+': flag_plussign = 1; c = 0; break; - case ' ': flag_blanksign = 1; c = 0; break; - case '#': flag_alternateform = 1; c = 0; break; - case '0': flag_zeropad = 1; c = 0; break; - default: break; - } - }while( c==0 && (c=(*++fmt))!=0 ); - /* Get the field width */ - width = 0; - if( c=='*' ){ - width = va_arg(ap,int); - if( width<0 ){ - flag_leftjustify = 1; - width = -width; - } - c = *++fmt; - }else{ - while( c>='0' && c<='9' ){ - width = width*10 + c - '0'; - c = *++fmt; - } - } - if( width > etBUFSIZE-10 ){ - width = etBUFSIZE-10; - } - /* Get the precision */ - if( c=='.' ){ - precision = 0; - c = *++fmt; - if( c=='*' ){ - precision = va_arg(ap,int); - if( precision<0 ) precision = -precision; - c = *++fmt; - }else{ - while( c>='0' && c<='9' ){ - precision = precision*10 + c - '0'; - c = *++fmt; - } - } - /* Limit the precision to prevent overflowing buf[] during conversion */ - if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40; - }else{ - precision = -1; - } - /* Get the conversion type modifier */ - if( c=='l' ){ - flag_long = 1; - c = *++fmt; - }else{ - flag_long = 0; - } - /* Fetch the info entry for the field */ - infop = 0; - xtype = etERROR; - for(idx=0; idxflags & FLAG_INTERN)==0 ){ - xtype = infop->type; - } - break; - } - } - zExtra = 0; - - /* - ** At this point, variables are initialized as follows: - ** - ** flag_alternateform TRUE if a '#' is present. - ** flag_plussign TRUE if a '+' is present. - ** flag_leftjustify TRUE if a '-' is present or if the - ** field width was negative. - ** flag_zeropad TRUE if the width began with 0. - ** flag_long TRUE if the letter 'l' (ell) prefixed - ** the conversion character. - ** flag_blanksign TRUE if a ' ' is present. - ** width The specified field width. This is - ** always non-negative. Zero is the default. - ** precision The specified precision. The default - ** is -1. - ** xtype The class of the conversion. - ** infop Pointer to the appropriate info struct. - */ - switch( xtype ){ - case etRADIX: - if( flag_long ) longvalue = va_arg(ap,long); - else longvalue = va_arg(ap,int); -#if 1 - /* For the format %#x, the value zero is printed "0" not "0x0". - ** I think this is stupid. */ - if( longvalue==0 ) flag_alternateform = 0; -#else - /* More sensible: turn off the prefix for octal (to prevent "00"), - ** but leave the prefix for hex. */ - if( longvalue==0 && infop->base==8 ) flag_alternateform = 0; -#endif - if( infop->flags & FLAG_SIGNED ){ - if( *(long*)&longvalue<0 ){ - longvalue = -*(long*)&longvalue; - prefix = '-'; - }else if( flag_plussign ) prefix = '+'; - else if( flag_blanksign ) prefix = ' '; - else prefix = 0; - }else prefix = 0; - if( flag_zeropad && precisioncharset; - base = infop->base; - do{ /* Convert to ascii */ - *(--bufpt) = cset[longvalue%base]; - longvalue = longvalue/base; - }while( longvalue>0 ); - } - length = &buf[etBUFSIZE-1]-bufpt; - for(idx=precision-length; idx>0; idx--){ - *(--bufpt) = '0'; /* Zero pad */ - } - if( prefix ) *(--bufpt) = prefix; /* Add sign */ - if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ - char *pre, x; - pre = infop->prefix; - if( *bufpt!=pre[0] ){ - for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x; - } - } - length = &buf[etBUFSIZE-1]-bufpt; - break; - case etFLOAT: - case etEXP: - case etGENERIC: - realvalue = va_arg(ap,double); -#ifndef etNOFLOATINGPOINT - if( precision<0 ) precision = 6; /* Set default precision */ - if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10; - if( realvalue<0.0 ){ - realvalue = -realvalue; - prefix = '-'; - }else{ - if( flag_plussign ) prefix = '+'; - else if( flag_blanksign ) prefix = ' '; - else prefix = 0; - } - if( infop->type==etGENERIC && precision>0 ) precision--; - rounder = 0.0; -#if 0 - /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */ - for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); -#else - /* It makes more sense to use 0.5 */ - for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1); -#endif - if( infop->type==etFLOAT ) realvalue += rounder; - /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ - exp = 0; - if( realvalue>0.0 ){ - while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; } - while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; } - while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; } - while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; } - if( exp>350 || exp<-350 ){ - bufpt = "NaN"; - length = 3; - break; - } - } - bufpt = buf; - /* - ** If the field type is etGENERIC, then convert to either etEXP - ** or etFLOAT, as appropriate. - */ - flag_exp = xtype==etEXP; - if( xtype!=etFLOAT ){ - realvalue += rounder; - if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } - } - if( xtype==etGENERIC ){ - flag_rtz = !flag_alternateform; - if( exp<-4 || exp>precision ){ - xtype = etEXP; - }else{ - precision = precision - exp; - xtype = etFLOAT; - } - }else{ - flag_rtz = 0; - } - /* - ** The "exp+precision" test causes output to be of type etEXP if - ** the precision is too large to fit in buf[]. - */ - nsd = 0; - if( xtype==etFLOAT && exp+precision0 || flag_alternateform); - if( prefix ) *(bufpt++) = prefix; /* Sign */ - if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */ - else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd); - if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */ - for(exp++; exp<0 && precision>0; precision--, exp++){ - *(bufpt++) = '0'; - } - while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd); - *(bufpt--) = 0; /* Null terminate */ - if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */ - while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; - if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; - } - bufpt++; /* point to next free slot */ - }else{ /* etEXP or etGENERIC */ - flag_dp = (precision>0 || flag_alternateform); - if( prefix ) *(bufpt++) = prefix; /* Sign */ - *(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */ - if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */ - while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd); - bufpt--; /* point to last digit */ - if( flag_rtz && flag_dp ){ /* Remove tail zeros */ - while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; - if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; - } - bufpt++; /* point to next free slot */ - if( exp || flag_exp ){ - *(bufpt++) = infop->charset[0]; - if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */ - else { *(bufpt++) = '+'; } - if( exp>=100 ){ - *(bufpt++) = (exp/100)+'0'; /* 100's digit */ - exp %= 100; - } - *(bufpt++) = exp/10+'0'; /* 10's digit */ - *(bufpt++) = exp%10+'0'; /* 1's digit */ - } - } - /* The converted number is in buf[] and zero terminated. Output it. - ** Note that the number is in the usual order, not reversed as with - ** integer conversions. */ - length = bufpt-buf; - bufpt = buf; - - /* Special case: Add leading zeros if the flag_zeropad flag is - ** set and we are not left justified */ - if( flag_zeropad && !flag_leftjustify && length < width){ - int i; - int nPad = width - length; - for(i=width; i>=nPad; i--){ - bufpt[i] = bufpt[i-nPad]; - } - i = prefix!=0; - while( nPad-- ) bufpt[i++] = '0'; - length = width; - } -#endif - break; - case etSIZE: - *(va_arg(ap,int*)) = count; - length = width = 0; - break; - case etPERCENT: - buf[0] = '%'; - bufpt = buf; - length = 1; - break; - case etCHARLIT: - case etCHARX: - c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt); - if( precision>=0 ){ - for(idx=1; idx=0 && precisionetBUFSIZE ){ - bufpt = zExtra = sqliteMalloc( n ); - if( bufpt==0 ) return -1; - }else{ - bufpt = buf; - } - j = 0; - if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\''; - for(i=0; (c=arg[i])!=0; i++){ - bufpt[j++] = c; - if( c=='\'' ) bufpt[j++] = c; - } - if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\''; - bufpt[j] = 0; - length = j; - if( precision>=0 && precisionz, pToken->n); - length = width = 0; - break; - } - case etSRCLIST: { - SrcList *pSrc = va_arg(ap, SrcList*); - int k = va_arg(ap, int); - struct SrcList_item *pItem = &pSrc->a[k]; - assert( k>=0 && knSrc ); - if( pItem->zDatabase && pItem->zDatabase[0] ){ - (*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase)); - (*func)(arg, ".", 1); - } - (*func)(arg, pItem->zName, strlen(pItem->zName)); - length = width = 0; - break; - } - case etERROR: - buf[0] = '%'; - buf[1] = c; - errorflag = 0; - idx = 1+(c!=0); - (*func)(arg,"%",idx); - count += idx; - if( c==0 ) fmt--; - break; - }/* End switch over the format type */ - /* - ** The text of the conversion is pointed to by "bufpt" and is - ** "length" characters long. The field width is "width". Do - ** the output. - */ - if( !flag_leftjustify ){ - register int nspace; - nspace = width-length; - if( nspace>0 ){ - count += nspace; - while( nspace>=etSPACESIZE ){ - (*func)(arg,spaces,etSPACESIZE); - nspace -= etSPACESIZE; - } - if( nspace>0 ) (*func)(arg,spaces,nspace); - } - } - if( length>0 ){ - (*func)(arg,bufpt,length); - count += length; - } - if( flag_leftjustify ){ - register int nspace; - nspace = width-length; - if( nspace>0 ){ - count += nspace; - while( nspace>=etSPACESIZE ){ - (*func)(arg,spaces,etSPACESIZE); - nspace -= etSPACESIZE; - } - if( nspace>0 ) (*func)(arg,spaces,nspace); - } - } - if( zExtra ){ - sqliteFree(zExtra); - } - }/* End for loop over the format string */ - return errorflag ? -1 : count; -} /* End of function */ - - -/* This structure is used to store state information about the -** write to memory that is currently in progress. -*/ -struct sgMprintf { - char *zBase; /* A base allocation */ - char *zText; /* The string collected so far */ - int nChar; /* Length of the string so far */ - int nTotal; /* Output size if unconstrained */ - int nAlloc; /* Amount of space allocated in zText */ - void *(*xRealloc)(void*,int); /* Function used to realloc memory */ -}; - -/* -** This function implements the callback from vxprintf. -** -** This routine add nNewChar characters of text in zNewText to -** the sgMprintf structure pointed to by "arg". -*/ -static void mout(void *arg, const char *zNewText, int nNewChar){ - struct sgMprintf *pM = (struct sgMprintf*)arg; - pM->nTotal += nNewChar; - if( pM->nChar + nNewChar + 1 > pM->nAlloc ){ - if( pM->xRealloc==0 ){ - nNewChar = pM->nAlloc - pM->nChar - 1; - }else{ - pM->nAlloc = pM->nChar + nNewChar*2 + 1; - if( pM->zText==pM->zBase ){ - pM->zText = pM->xRealloc(0, pM->nAlloc); - if( pM->zText && pM->nChar ){ - memcpy(pM->zText, pM->zBase, pM->nChar); - } - }else{ - pM->zText = pM->xRealloc(pM->zText, pM->nAlloc); - } - } - } - if( pM->zText ){ - if( nNewChar>0 ){ - memcpy(&pM->zText[pM->nChar], zNewText, nNewChar); - pM->nChar += nNewChar; - } - pM->zText[pM->nChar] = 0; - } -} - -/* -** This routine is a wrapper around xprintf() that invokes mout() as -** the consumer. -*/ -static char *base_vprintf( - void *(*xRealloc)(void*,int), /* Routine to realloc memory. May be NULL */ - int useInternal, /* Use internal %-conversions if true */ - char *zInitBuf, /* Initially write here, before mallocing */ - int nInitBuf, /* Size of zInitBuf[] */ - const char *zFormat, /* format string */ - va_list ap /* arguments */ -){ - struct sgMprintf sM; - sM.zBase = sM.zText = zInitBuf; - sM.nChar = sM.nTotal = 0; - sM.nAlloc = nInitBuf; - sM.xRealloc = xRealloc; - vxprintf(mout, &sM, useInternal, zFormat, ap); - if( xRealloc ){ - if( sM.zText==sM.zBase ){ - sM.zText = xRealloc(0, sM.nChar+1); - memcpy(sM.zText, sM.zBase, sM.nChar+1); - }else if( sM.nAlloc>sM.nChar+10 ){ - sM.zText = xRealloc(sM.zText, sM.nChar+1); - } - } - return sM.zText; -} - -/* -** Realloc that is a real function, not a macro. -*/ -static void *printf_realloc(void *old, int size){ - return sqliteRealloc(old,size); -} - -/* -** Print into memory obtained from sqliteMalloc(). Use the internal -** %-conversion extensions. -*/ -char *sqliteVMPrintf(const char *zFormat, va_list ap){ - char zBase[1000]; - return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap); -} - -/* -** Print into memory obtained from sqliteMalloc(). Use the internal -** %-conversion extensions. -*/ -char *sqliteMPrintf(const char *zFormat, ...){ - va_list ap; - char *z; - char zBase[1000]; - va_start(ap, zFormat); - z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap); - va_end(ap); - return z; -} - -/* -** Print into memory obtained from malloc(). Do not use the internal -** %-conversion extensions. This routine is for use by external users. -*/ -char *sqlite_mprintf(const char *zFormat, ...){ - va_list ap; - char *z; - char zBuf[200]; - - va_start(ap,zFormat); - z = base_vprintf((void*(*)(void*,int))realloc, 0, - zBuf, sizeof(zBuf), zFormat, ap); - va_end(ap); - return z; -} - -/* This is the varargs version of sqlite_mprintf. -*/ -char *sqlite_vmprintf(const char *zFormat, va_list ap){ - char zBuf[200]; - return base_vprintf((void*(*)(void*,int))realloc, 0, - zBuf, sizeof(zBuf), zFormat, ap); -} - -/* -** sqlite_snprintf() works like snprintf() except that it ignores the -** current locale settings. This is important for SQLite because we -** are not able to use a "," as the decimal point in place of "." as -** specified by some locales. -*/ -char *sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){ - char *z; - va_list ap; - - va_start(ap,zFormat); - z = base_vprintf(0, 0, zBuf, n, zFormat, ap); - va_end(ap); - return z; -} - -/* -** The following four routines implement the varargs versions of the -** sqlite_exec() and sqlite_get_table() interfaces. See the sqlite.h -** header files for a more detailed description of how these interfaces -** work. -** -** These routines are all just simple wrappers. -*/ -int sqlite_exec_printf( - sqlite *db, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - sqlite_callback xCallback, /* Callback function */ - void *pArg, /* 1st argument to callback function */ - char **errmsg, /* Error msg written here */ - ... /* Arguments to the format string. */ -){ - va_list ap; - int rc; - - va_start(ap, errmsg); - rc = sqlite_exec_vprintf(db, sqlFormat, xCallback, pArg, errmsg, ap); - va_end(ap); - return rc; -} -int sqlite_exec_vprintf( - sqlite *db, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - sqlite_callback xCallback, /* Callback function */ - void *pArg, /* 1st argument to callback function */ - char **errmsg, /* Error msg written here */ - va_list ap /* Arguments to the format string. */ -){ - char *zSql; - int rc; - - zSql = sqlite_vmprintf(sqlFormat, ap); - rc = sqlite_exec(db, zSql, xCallback, pArg, errmsg); - free(zSql); - return rc; -} -int sqlite_get_table_printf( - sqlite *db, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncol, /* Number of result columns written here */ - char **errmsg, /* Error msg written here */ - ... /* Arguments to the format string */ -){ - va_list ap; - int rc; - - va_start(ap, errmsg); - rc = sqlite_get_table_vprintf(db, sqlFormat, resultp, nrow, ncol, errmsg, ap); - va_end(ap); - return rc; -} -int sqlite_get_table_vprintf( - sqlite *db, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg, /* Error msg written here */ - va_list ap /* Arguments to the format string */ -){ - char *zSql; - int rc; - - zSql = sqlite_vmprintf(sqlFormat, ap); - rc = sqlite_get_table(db, zSql, resultp, nrow, ncolumn, errmsg); - free(zSql); - return rc; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/printf.o b/dbLifeLog/DBD-SQLite2-0.33/printf.o deleted file mode 100644 index fe3dab2c5f9f4f0398ecc7fd7141b81c5945caa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15128 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 |e{UT02;V-KVtlqEgL_KK#qziNZyU{gh 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 diff --git a/dbLifeLog/DBD-SQLite2-0.33/random.c b/dbLifeLog/DBD-SQLite2-0.33/random.c deleted file mode 100644 index 4f2b73c..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/random.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code to implement a pseudo-random number -** generator (PRNG) for SQLite. -** -** Random numbers are used by some of the database backends in order -** to generate random integer keys for tables or random filenames. -** -** $Id: random.c,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ -*/ -#include "sqliteInt.h" -#include "os.h" - - -/* -** Get a single 8-bit random value from the RC4 PRNG. The Mutex -** must be held while executing this routine. -** -** Why not just use a library random generator like lrand48() for this? -** Because the OP_NewRecno opcode in the VDBE depends on having a very -** good source of random numbers. The lrand48() library function may -** well be good enough. But maybe not. Or maybe lrand48() has some -** subtle problems on some systems that could cause problems. It is hard -** to know. To minimize the risk of problems due to bad lrand48() -** implementations, SQLite uses this random number generator based -** on RC4, which we know works very well. -*/ -static int randomByte(){ - unsigned char t; - - /* All threads share a single random number generator. - ** This structure is the current state of the generator. - */ - static struct { - unsigned char isInit; /* True if initialized */ - unsigned char i, j; /* State variables */ - unsigned char s[256]; /* State variables */ - } prng; - - /* Initialize the state of the random number generator once, - ** the first time this routine is called. The seed value does - ** not need to contain a lot of randomness since we are not - ** trying to do secure encryption or anything like that... - ** - ** Nothing in this file or anywhere else in SQLite does any kind of - ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random - ** number generator) not as an encryption device. - */ - if( !prng.isInit ){ - int i; - char k[256]; - prng.j = 0; - prng.i = 0; - sqliteOsRandomSeed(k); - for(i=0; i<256; i++){ - prng.s[i] = i; - } - for(i=0; i<256; i++){ - prng.j += prng.s[i] + k[i]; - t = prng.s[prng.j]; - prng.s[prng.j] = prng.s[i]; - prng.s[i] = t; - } - prng.isInit = 1; - } - - /* Generate and return single random byte - */ - prng.i++; - t = prng.s[prng.i]; - prng.j += t; - prng.s[prng.i] = prng.s[prng.j]; - prng.s[prng.j] = t; - t += prng.s[prng.i]; - return prng.s[t]; -} - -/* -** Return N random bytes. -*/ -void sqliteRandomness(int N, void *pBuf){ - unsigned char *zBuf = pBuf; - sqliteOsEnterMutex(); - while( N-- ){ - *(zBuf++) = randomByte(); - } - sqliteOsLeaveMutex(); -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/random.o b/dbLifeLog/DBD-SQLite2-0.33/random.o deleted file mode 100644 index 8dc34154b0ec3cadc9a9072d421ca7e59093721a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2456 zcmbW2&2Jk;6u@V^ahrx_*Pup`C{x=mbC6y$Z{WG$RV#A3p+XOp%B2+uwTDVb1-9?)&N!Q4ec?s3^XB(H zcXm8^FISk2QA)T_@*>$?aZ1Rm`*!t=uV%;~86f&A`bxg}Kwn;2YCbf!{zyP@$+*%t zG73&cbLW|U0IAL$47q$$+4&RZ*0g7|#*i4z-wLe})aF}Goc_LeRcXg@sk8@iYQ0Pw zL&5q-rCk`3==BD(ca*jhmog1!NNN<~QVfjqlMj^k4@!GxP|_PYPubam(ERqd^wJdO zAnvC|^VWBMJYkdHm(lWTq&mt|q|ui!wma0A!d-Chvv!z=(fmbeAB|CC`zsjND7~k& z|C)h`N^N$UxV!Q?u6%gL5VBDPLzye!PdA5W9u8-tkY-o*Yz{{*{^*+ zzt267x#{T>$09&SlFIr%}KE|0z+*JW*cUtaFSq%k@mYru3l z2|nPPmHYL_SbWrkDf`HMFUlrGo-9Hn_=^$=GDV3*f^QhM4Zwni{3UFJiA45ub%!*ByJ&H&pFhE{E(&6oY`fG& z1>1Vt4!lgW?pVbQv$(clp10P^&>9)V2MB(tgE0Pv6OVENAxI1c+BnDahr&5OC`$qE z@_&Og-fIH?hw)+$UKcpe^O?XOvOJ#)oag^i;Jp71W^MREQ;hFQ7{jVuBi2k6~|g7YTc;?^BUJ`cG*(lI5IeZwwaBx-T9Qn9PxQr&cHb?)TKn13jU>POpa=J}dcvAgB|uabm7 zd^Pcxm;r{ue}BR1zrVr5V8Fe~a0fPL5Q2Qn_6_ecRQXLXj7E@WVIUW8rjJ-0`h-Qq zN5F_V#rRK{WB7i;JV|_nBn3LUito?kL$1Cm*3SS%ruo+02aiwhB46Y2e9i;qdf4^n zC>Y^;ma#o&57-SBe-8Ap@crlP6ev;O?*_a2`FFzahp{}K^T&aSdk=`*WASUa2#NSw ixE6ay_vabB!~*cn!~Z>E{R6VLuDWw3`utp5lx&tvoe diff --git a/dbLifeLog/DBD-SQLite2-0.33/select.c b/dbLifeLog/DBD-SQLite2-0.33/select.c deleted file mode 100644 index 4eb86b4..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/select.c +++ /dev/null @@ -1,2434 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle SELECT statements in SQLite. -** -** $Id: select.c,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ -*/ -#include "sqliteInt.h" - - -/* -** Allocate a new Select structure and return a pointer to that -** structure. -*/ -Select *sqliteSelectNew( - ExprList *pEList, /* which columns to include in the result */ - SrcList *pSrc, /* the FROM clause -- which tables to scan */ - Expr *pWhere, /* the WHERE clause */ - ExprList *pGroupBy, /* the GROUP BY clause */ - Expr *pHaving, /* the HAVING clause */ - ExprList *pOrderBy, /* the ORDER BY clause */ - int isDistinct, /* true if the DISTINCT keyword is present */ - int nLimit, /* LIMIT value. -1 means not used */ - int nOffset /* OFFSET value. 0 means no offset */ -){ - Select *pNew; - pNew = sqliteMalloc( sizeof(*pNew) ); - if( pNew==0 ){ - sqliteExprListDelete(pEList); - sqliteSrcListDelete(pSrc); - sqliteExprDelete(pWhere); - sqliteExprListDelete(pGroupBy); - sqliteExprDelete(pHaving); - sqliteExprListDelete(pOrderBy); - }else{ - if( pEList==0 ){ - pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL,0,0,0), 0); - } - pNew->pEList = pEList; - pNew->pSrc = pSrc; - pNew->pWhere = pWhere; - pNew->pGroupBy = pGroupBy; - pNew->pHaving = pHaving; - pNew->pOrderBy = pOrderBy; - pNew->isDistinct = isDistinct; - pNew->op = TK_SELECT; - pNew->nLimit = nLimit; - pNew->nOffset = nOffset; - pNew->iLimit = -1; - pNew->iOffset = -1; - } - return pNew; -} - -/* -** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the -** type of join. Return an integer constant that expresses that type -** in terms of the following bit values: -** -** JT_INNER -** JT_OUTER -** JT_NATURAL -** JT_LEFT -** JT_RIGHT -** -** A full outer join is the combination of JT_LEFT and JT_RIGHT. -** -** If an illegal or unsupported join type is seen, then still return -** a join type, but put an error in the pParse structure. -*/ -int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ - int jointype = 0; - Token *apAll[3]; - Token *p; - static struct { - const char *zKeyword; - int nChar; - int code; - } keywords[] = { - { "natural", 7, JT_NATURAL }, - { "left", 4, JT_LEFT|JT_OUTER }, - { "right", 5, JT_RIGHT|JT_OUTER }, - { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER }, - { "outer", 5, JT_OUTER }, - { "inner", 5, JT_INNER }, - { "cross", 5, JT_INNER }, - }; - int i, j; - apAll[0] = pA; - apAll[1] = pB; - apAll[2] = pC; - for(i=0; i<3 && apAll[i]; i++){ - p = apAll[i]; - for(j=0; jn==keywords[j].nChar - && sqliteStrNICmp(p->z, keywords[j].zKeyword, p->n)==0 ){ - jointype |= keywords[j].code; - break; - } - } - if( j>=sizeof(keywords)/sizeof(keywords[0]) ){ - jointype |= JT_ERROR; - break; - } - } - if( - (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || - (jointype & JT_ERROR)!=0 - ){ - static Token dummy = { 0, 0 }; - char *zSp1 = " ", *zSp2 = " "; - if( pB==0 ){ pB = &dummy; zSp1 = 0; } - if( pC==0 ){ pC = &dummy; zSp2 = 0; } - sqliteSetNString(&pParse->zErrMsg, "unknown or unsupported join type: ", 0, - pA->z, pA->n, zSp1, 1, pB->z, pB->n, zSp2, 1, pC->z, pC->n, 0); - pParse->nErr++; - jointype = JT_INNER; - }else if( jointype & JT_RIGHT ){ - sqliteErrorMsg(pParse, - "RIGHT and FULL OUTER JOINs are not currently supported"); - jointype = JT_INNER; - } - return jointype; -} - -/* -** Return the index of a column in a table. Return -1 if the column -** is not contained in the table. -*/ -static int columnIndex(Table *pTab, const char *zCol){ - int i; - for(i=0; inCol; i++){ - if( sqliteStrICmp(pTab->aCol[i].zName, zCol)==0 ) return i; - } - return -1; -} - -/* -** Add a term to the WHERE expression in *ppExpr that requires the -** zCol column to be equal in the two tables pTab1 and pTab2. -*/ -static void addWhereTerm( - const char *zCol, /* Name of the column */ - const Table *pTab1, /* First table */ - const Table *pTab2, /* Second table */ - Expr **ppExpr /* Add the equality term to this expression */ -){ - Token dummy; - Expr *pE1a, *pE1b, *pE1c; - Expr *pE2a, *pE2b, *pE2c; - Expr *pE; - - dummy.z = zCol; - dummy.n = strlen(zCol); - dummy.dyn = 0; - pE1a = sqliteExpr(TK_ID, 0, 0, &dummy); - pE2a = sqliteExpr(TK_ID, 0, 0, &dummy); - dummy.z = pTab1->zName; - dummy.n = strlen(dummy.z); - pE1b = sqliteExpr(TK_ID, 0, 0, &dummy); - dummy.z = pTab2->zName; - dummy.n = strlen(dummy.z); - pE2b = sqliteExpr(TK_ID, 0, 0, &dummy); - pE1c = sqliteExpr(TK_DOT, pE1b, pE1a, 0); - pE2c = sqliteExpr(TK_DOT, pE2b, pE2a, 0); - pE = sqliteExpr(TK_EQ, pE1c, pE2c, 0); - ExprSetProperty(pE, EP_FromJoin); - if( *ppExpr ){ - *ppExpr = sqliteExpr(TK_AND, *ppExpr, pE, 0); - }else{ - *ppExpr = pE; - } -} - -/* -** Set the EP_FromJoin property on all terms of the given expression. -** -** The EP_FromJoin property is used on terms of an expression to tell -** the LEFT OUTER JOIN processing logic that this term is part of the -** join restriction specified in the ON or USING clause and not a part -** of the more general WHERE clause. These terms are moved over to the -** WHERE clause during join processing but we need to remember that they -** originated in the ON or USING clause. -*/ -static void setJoinExpr(Expr *p){ - while( p ){ - ExprSetProperty(p, EP_FromJoin); - setJoinExpr(p->pLeft); - p = p->pRight; - } -} - -/* -** This routine processes the join information for a SELECT statement. -** ON and USING clauses are converted into extra terms of the WHERE clause. -** NATURAL joins also create extra WHERE clause terms. -** -** This routine returns the number of errors encountered. -*/ -static int sqliteProcessJoin(Parse *pParse, Select *p){ - SrcList *pSrc; - int i, j; - pSrc = p->pSrc; - for(i=0; inSrc-1; i++){ - struct SrcList_item *pTerm = &pSrc->a[i]; - struct SrcList_item *pOther = &pSrc->a[i+1]; - - if( pTerm->pTab==0 || pOther->pTab==0 ) continue; - - /* When the NATURAL keyword is present, add WHERE clause terms for - ** every column that the two tables have in common. - */ - if( pTerm->jointype & JT_NATURAL ){ - Table *pTab; - if( pTerm->pOn || pTerm->pUsing ){ - sqliteErrorMsg(pParse, "a NATURAL join may not have " - "an ON or USING clause", 0); - return 1; - } - pTab = pTerm->pTab; - for(j=0; jnCol; j++){ - if( columnIndex(pOther->pTab, pTab->aCol[j].zName)>=0 ){ - addWhereTerm(pTab->aCol[j].zName, pTab, pOther->pTab, &p->pWhere); - } - } - } - - /* Disallow both ON and USING clauses in the same join - */ - if( pTerm->pOn && pTerm->pUsing ){ - sqliteErrorMsg(pParse, "cannot have both ON and USING " - "clauses in the same join"); - return 1; - } - - /* Add the ON clause to the end of the WHERE clause, connected by - ** and AND operator. - */ - if( pTerm->pOn ){ - setJoinExpr(pTerm->pOn); - if( p->pWhere==0 ){ - p->pWhere = pTerm->pOn; - }else{ - p->pWhere = sqliteExpr(TK_AND, p->pWhere, pTerm->pOn, 0); - } - pTerm->pOn = 0; - } - - /* Create extra terms on the WHERE clause for each column named - ** in the USING clause. Example: If the two tables to be joined are - ** A and B and the USING clause names X, Y, and Z, then add this - ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z - ** Report an error if any column mentioned in the USING clause is - ** not contained in both tables to be joined. - */ - if( pTerm->pUsing ){ - IdList *pList; - int j; - assert( inSrc-1 ); - pList = pTerm->pUsing; - for(j=0; jnId; j++){ - if( columnIndex(pTerm->pTab, pList->a[j].zName)<0 || - columnIndex(pOther->pTab, pList->a[j].zName)<0 ){ - sqliteErrorMsg(pParse, "cannot join using column %s - column " - "not present in both tables", pList->a[j].zName); - return 1; - } - addWhereTerm(pList->a[j].zName, pTerm->pTab, pOther->pTab, &p->pWhere); - } - } - } - return 0; -} - -/* -** Delete the given Select structure and all of its substructures. -*/ -void sqliteSelectDelete(Select *p){ - if( p==0 ) return; - sqliteExprListDelete(p->pEList); - sqliteSrcListDelete(p->pSrc); - sqliteExprDelete(p->pWhere); - sqliteExprListDelete(p->pGroupBy); - sqliteExprDelete(p->pHaving); - sqliteExprListDelete(p->pOrderBy); - sqliteSelectDelete(p->pPrior); - sqliteFree(p->zSelect); - sqliteFree(p); -} - -/* -** Delete the aggregate information from the parse structure. -*/ -static void sqliteAggregateInfoReset(Parse *pParse){ - sqliteFree(pParse->aAgg); - pParse->aAgg = 0; - pParse->nAgg = 0; - pParse->useAgg = 0; -} - -/* -** Insert code into "v" that will push the record on the top of the -** stack into the sorter. -*/ -static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ - char *zSortOrder; - int i; - zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 ); - if( zSortOrder==0 ) return; - for(i=0; inExpr; i++){ - int order = pOrderBy->a[i].sortOrder; - int type; - int c; - if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ - type = SQLITE_SO_TEXT; - }else if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_NUM ){ - type = SQLITE_SO_NUM; - }else if( pParse->db->file_format>=4 ){ - type = sqliteExprType(pOrderBy->a[i].pExpr); - }else{ - type = SQLITE_SO_NUM; - } - if( (order & SQLITE_SO_DIRMASK)==SQLITE_SO_ASC ){ - c = type==SQLITE_SO_TEXT ? 'A' : '+'; - }else{ - c = type==SQLITE_SO_TEXT ? 'D' : '-'; - } - zSortOrder[i] = c; - sqliteExprCode(pParse, pOrderBy->a[i].pExpr); - } - zSortOrder[pOrderBy->nExpr] = 0; - sqliteVdbeOp3(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, P3_DYNAMIC); - sqliteVdbeAddOp(v, OP_SortPut, 0, 0); -} - -/* -** This routine adds a P3 argument to the last VDBE opcode that was -** inserted. The P3 argument added is a string suitable for the -** OP_MakeKey or OP_MakeIdxKey opcodes. The string consists of -** characters 't' or 'n' depending on whether or not the various -** fields of the key to be generated should be treated as numeric -** or as text. See the OP_MakeKey and OP_MakeIdxKey opcode -** documentation for additional information about the P3 string. -** See also the sqliteAddIdxKeyType() routine. -*/ -void sqliteAddKeyType(Vdbe *v, ExprList *pEList){ - int nColumn = pEList->nExpr; - char *zType = sqliteMalloc( nColumn+1 ); - int i; - if( zType==0 ) return; - for(i=0; ia[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't'; - } - zType[i] = 0; - sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC); -} - -/* -** Add code to implement the OFFSET and LIMIT -*/ -static void codeLimiter( - Vdbe *v, /* Generate code into this VM */ - Select *p, /* The SELECT statement being coded */ - int iContinue, /* Jump here to skip the current record */ - int iBreak, /* Jump here to end the loop */ - int nPop /* Number of times to pop stack when jumping */ -){ - if( p->iOffset>=0 ){ - int addr = sqliteVdbeCurrentAddr(v) + 2; - if( nPop>0 ) addr++; - sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr); - if( nPop>0 ){ - sqliteVdbeAddOp(v, OP_Pop, nPop, 0); - } - sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); - } - if( p->iLimit>=0 ){ - sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak); - } -} - -/* -** This routine generates the code for the inside of the inner loop -** of a SELECT. -** -** If srcTab and nColumn are both zero, then the pEList expressions -** are evaluated in order to get the data for this row. If nColumn>0 -** then data is pulled from srcTab and pEList is used only to get the -** datatypes for each column. -*/ -static int selectInnerLoop( - Parse *pParse, /* The parser context */ - Select *p, /* The complete select statement being coded */ - ExprList *pEList, /* List of values being extracted */ - int srcTab, /* Pull data from this table */ - int nColumn, /* Number of columns in the source table */ - ExprList *pOrderBy, /* If not NULL, sort results using this key */ - int distinct, /* If >=0, make sure results are distinct */ - int eDest, /* How to dispose of the results */ - int iParm, /* An argument to the disposal method */ - int iContinue, /* Jump here to continue with next row */ - int iBreak /* Jump here to break out of the inner loop */ -){ - Vdbe *v = pParse->pVdbe; - int i; - int hasDistinct; /* True if the DISTINCT keyword is present */ - - if( v==0 ) return 0; - assert( pEList!=0 ); - - /* If there was a LIMIT clause on the SELECT statement, then do the check - ** to see if this row should be output. - */ - hasDistinct = distinct>=0 && pEList && pEList->nExpr>0; - if( pOrderBy==0 && !hasDistinct ){ - codeLimiter(v, p, iContinue, iBreak, 0); - } - - /* Pull the requested columns. - */ - if( nColumn>0 ){ - for(i=0; inExpr; - for(i=0; inExpr; i++){ - sqliteExprCode(pParse, pEList->a[i].pExpr); - } - } - - /* If the DISTINCT keyword was present on the SELECT statement - ** and this row has been seen before, then do not make this row - ** part of the result. - */ - if( hasDistinct ){ -#if NULL_ALWAYS_DISTINCT - sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7); -#endif - sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); - if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pEList); - sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3); - sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0); - if( pOrderBy==0 ){ - codeLimiter(v, p, iContinue, iBreak, nColumn); - } - } - - switch( eDest ){ - /* In this mode, write each query result to the key of the temporary - ** table iParm. - */ - case SRT_Union: { - sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0); - break; - } - - /* Store the result as data using a unique key. - */ - case SRT_Table: - case SRT_TempTable: { - sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); - if( pOrderBy ){ - pushOntoSorter(pParse, v, pOrderBy); - }else{ - sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0); - sqliteVdbeAddOp(v, OP_Pull, 1, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0); - } - break; - } - - /* Construct a record from the query result, but instead of - ** saving that record, use it as a key to delete elements from - ** the temporary table iParm. - */ - case SRT_Except: { - int addr; - addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); - sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3); - sqliteVdbeAddOp(v, OP_Delete, iParm, 0); - break; - } - - /* If we are creating a set for an "expr IN (SELECT ...)" construct, - ** then there should be a single item on the stack. Write this - ** item into the set table with bogus data. - */ - case SRT_Set: { - int addr1 = sqliteVdbeCurrentAddr(v); - int addr2; - assert( nColumn==1 ); - sqliteVdbeAddOp(v, OP_NotNull, -1, addr1+3); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - addr2 = sqliteVdbeAddOp(v, OP_Goto, 0, 0); - if( pOrderBy ){ - pushOntoSorter(pParse, v, pOrderBy); - }else{ - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0); - } - sqliteVdbeChangeP2(v, addr2, sqliteVdbeCurrentAddr(v)); - break; - } - - /* If this is a scalar select that is part of an expression, then - ** store the results in the appropriate memory cell and break out - ** of the scan loop. - */ - case SRT_Mem: { - assert( nColumn==1 ); - if( pOrderBy ){ - pushOntoSorter(pParse, v, pOrderBy); - }else{ - sqliteVdbeAddOp(v, OP_MemStore, iParm, 1); - sqliteVdbeAddOp(v, OP_Goto, 0, iBreak); - } - break; - } - - /* Send the data to the callback function. - */ - case SRT_Callback: - case SRT_Sorter: { - if( pOrderBy ){ - sqliteVdbeAddOp(v, OP_SortMakeRec, nColumn, 0); - pushOntoSorter(pParse, v, pOrderBy); - }else{ - assert( eDest==SRT_Callback ); - sqliteVdbeAddOp(v, OP_Callback, nColumn, 0); - } - break; - } - - /* Invoke a subroutine to handle the results. The subroutine itself - ** is responsible for popping the results off of the stack. - */ - case SRT_Subroutine: { - if( pOrderBy ){ - sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); - pushOntoSorter(pParse, v, pOrderBy); - }else{ - sqliteVdbeAddOp(v, OP_Gosub, 0, iParm); - } - break; - } - - /* Discard the results. This is used for SELECT statements inside - ** the body of a TRIGGER. The purpose of such selects is to call - ** user-defined functions that have side effects. We do not care - ** about the actual results of the select. - */ - default: { - assert( eDest==SRT_Discard ); - sqliteVdbeAddOp(v, OP_Pop, nColumn, 0); - break; - } - } - return 0; -} - -/* -** If the inner loop was generated using a non-null pOrderBy argument, -** then the results were placed in a sorter. After the loop is terminated -** we need to run the sorter and output the results. The following -** routine generates the code needed to do that. -*/ -static void generateSortTail( - Select *p, /* The SELECT statement */ - Vdbe *v, /* Generate code into this VDBE */ - int nColumn, /* Number of columns of data */ - int eDest, /* Write the sorted results here */ - int iParm /* Optional parameter associated with eDest */ -){ - int end1 = sqliteVdbeMakeLabel(v); - int end2 = sqliteVdbeMakeLabel(v); - int addr; - if( eDest==SRT_Sorter ) return; - sqliteVdbeAddOp(v, OP_Sort, 0, 0); - addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1); - codeLimiter(v, p, addr, end2, 1); - switch( eDest ){ - case SRT_Callback: { - sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0); - break; - } - case SRT_Table: - case SRT_TempTable: { - sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0); - sqliteVdbeAddOp(v, OP_Pull, 1, 0); - sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0); - break; - } - case SRT_Set: { - assert( nColumn==1 ); - sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3); - sqliteVdbeAddOp(v, OP_Pop, 1, 0); - sqliteVdbeAddOp(v, OP_Goto, 0, sqliteVdbeCurrentAddr(v)+3); - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0); - break; - } - case SRT_Mem: { - assert( nColumn==1 ); - sqliteVdbeAddOp(v, OP_MemStore, iParm, 1); - sqliteVdbeAddOp(v, OP_Goto, 0, end1); - break; - } - case SRT_Subroutine: { - int i; - for(i=0; ipVdbe; - int i, j; - for(i=0; inExpr; i++){ - Expr *p = pEList->a[i].pExpr; - char *zType = 0; - if( p==0 ) continue; - if( p->op==TK_COLUMN && pTabList ){ - Table *pTab; - int iCol = p->iColumn; - for(j=0; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){} - assert( jnSrc ); - pTab = pTabList->a[j].pTab; - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==-1 || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zType = "INTEGER"; - }else{ - zType = pTab->aCol[iCol].zType; - } - }else{ - if( sqliteExprType(p)==SQLITE_SO_TEXT ){ - zType = "TEXT"; - }else{ - zType = "NUMERIC"; - } - } - sqliteVdbeOp3(v, OP_ColumnName, i + pEList->nExpr, 0, zType, 0); - } -} - -/* -** Generate code that will tell the VDBE the names of columns -** in the result set. This information is used to provide the -** azCol[] values in the callback. -*/ -static void generateColumnNames( - Parse *pParse, /* Parser context */ - SrcList *pTabList, /* List of tables */ - ExprList *pEList /* Expressions defining the result set */ -){ - Vdbe *v = pParse->pVdbe; - int i, j; - sqlite *db = pParse->db; - int fullNames, shortNames; - - assert( v!=0 ); - if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return; - pParse->colNamesSet = 1; - fullNames = (db->flags & SQLITE_FullColNames)!=0; - shortNames = (db->flags & SQLITE_ShortColNames)!=0; - for(i=0; inExpr; i++){ - Expr *p; - int p2 = i==pEList->nExpr-1; - p = pEList->a[i].pExpr; - if( p==0 ) continue; - if( pEList->a[i].zName ){ - char *zName = pEList->a[i].zName; - sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0); - continue; - } - if( p->op==TK_COLUMN && pTabList ){ - Table *pTab; - char *zCol; - int iCol = p->iColumn; - for(j=0; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){} - assert( jnSrc ); - pTab = pTabList->a[j].pTab; - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==-1 || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zCol = "_ROWID_"; - }else{ - zCol = pTab->aCol[iCol].zName; - } - if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ - int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n); - sqliteVdbeCompressSpace(v, addr); - }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ - char *zName = 0; - char *zTab; - - zTab = pTabList->a[j].zAlias; - if( fullNames || zTab==0 ) zTab = pTab->zName; - sqliteSetString(&zName, zTab, ".", zCol, 0); - sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, P3_DYNAMIC); - }else{ - sqliteVdbeOp3(v, OP_ColumnName, i, p2, zCol, 0); - } - }else if( p->span.z && p->span.z[0] ){ - int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n); - sqliteVdbeCompressSpace(v, addr); - }else{ - char zName[30]; - assert( p->op!=TK_COLUMN || pTabList==0 ); - sprintf(zName, "column%d", i+1); - sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0); - } - } -} - -/* -** Name of the connection operator, used for error messages. -*/ -static const char *selectOpName(int id){ - char *z; - switch( id ){ - case TK_ALL: z = "UNION ALL"; break; - case TK_INTERSECT: z = "INTERSECT"; break; - case TK_EXCEPT: z = "EXCEPT"; break; - default: z = "UNION"; break; - } - return z; -} - -/* -** Forward declaration -*/ -static int fillInColumnList(Parse*, Select*); - -/* -** Given a SELECT statement, generate a Table structure that describes -** the result set of that SELECT. -*/ -Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ - Table *pTab; - int i, j; - ExprList *pEList; - Column *aCol; - - if( fillInColumnList(pParse, pSelect) ){ - return 0; - } - pTab = sqliteMalloc( sizeof(Table) ); - if( pTab==0 ){ - return 0; - } - pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; - pEList = pSelect->pEList; - pTab->nCol = pEList->nExpr; - assert( pTab->nCol>0 ); - pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); - for(i=0; inCol; i++){ - Expr *p, *pR; - if( pEList->a[i].zName ){ - aCol[i].zName = sqliteStrDup(pEList->a[i].zName); - }else if( (p=pEList->a[i].pExpr)->op==TK_DOT - && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){ - int cnt; - sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0); - for(j=cnt=0; jtoken.z, pR->token.n, zBuf, n,0); - j = -1; - } - } - }else if( p->span.z && p->span.z[0] ){ - sqliteSetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0); - }else{ - char zBuf[30]; - sprintf(zBuf, "column%d", i+1); - aCol[i].zName = sqliteStrDup(zBuf); - } - sqliteDequote(aCol[i].zName); - } - pTab->iPKey = -1; - return pTab; -} - -/* -** For the given SELECT statement, do three things. -** -** (1) Fill in the pTabList->a[].pTab fields in the SrcList that -** defines the set of tables that should be scanned. For views, -** fill pTabList->a[].pSelect with a copy of the SELECT statement -** that implements the view. A copy is made of the view's SELECT -** statement so that we can freely modify or delete that statement -** without worrying about messing up the presistent representation -** of the view. -** -** (2) Add terms to the WHERE clause to accomodate the NATURAL keyword -** on joins and the ON and USING clause of joins. -** -** (3) Scan the list of columns in the result set (pEList) looking -** for instances of the "*" operator or the TABLE.* operator. -** If found, expand each "*" to be every column in every table -** and TABLE.* to be every column in TABLE. -** -** Return 0 on success. If there are problems, leave an error message -** in pParse and return non-zero. -*/ -static int fillInColumnList(Parse *pParse, Select *p){ - int i, j, k, rc; - SrcList *pTabList; - ExprList *pEList; - Table *pTab; - - if( p==0 || p->pSrc==0 ) return 1; - pTabList = p->pSrc; - pEList = p->pEList; - - /* Look up every table in the table list. - */ - for(i=0; inSrc; i++){ - if( pTabList->a[i].pTab ){ - /* This routine has run before! No need to continue */ - return 0; - } - if( pTabList->a[i].zName==0 ){ - /* A sub-query in the FROM clause of a SELECT */ - assert( pTabList->a[i].pSelect!=0 ); - if( pTabList->a[i].zAlias==0 ){ - char zFakeName[60]; - sprintf(zFakeName, "sqlite_subquery_%p_", - (void*)pTabList->a[i].pSelect); - sqliteSetString(&pTabList->a[i].zAlias, zFakeName, 0); - } - pTabList->a[i].pTab = pTab = - sqliteResultSetOfSelect(pParse, pTabList->a[i].zAlias, - pTabList->a[i].pSelect); - if( pTab==0 ){ - return 1; - } - /* The isTransient flag indicates that the Table structure has been - ** dynamically allocated and may be freed at any time. In other words, - ** pTab is not pointing to a persistent table structure that defines - ** part of the schema. */ - pTab->isTransient = 1; - }else{ - /* An ordinary table or view name in the FROM clause */ - pTabList->a[i].pTab = pTab = - sqliteLocateTable(pParse,pTabList->a[i].zName,pTabList->a[i].zDatabase); - if( pTab==0 ){ - return 1; - } - if( pTab->pSelect ){ - /* We reach here if the named table is a really a view */ - if( sqliteViewGetColumnNames(pParse, pTab) ){ - return 1; - } - /* If pTabList->a[i].pSelect!=0 it means we are dealing with a - ** view within a view. The SELECT structure has already been - ** copied by the outer view so we can skip the copy step here - ** in the inner view. - */ - if( pTabList->a[i].pSelect==0 ){ - pTabList->a[i].pSelect = sqliteSelectDup(pTab->pSelect); - } - } - } - } - - /* Process NATURAL keywords, and ON and USING clauses of joins. - */ - if( sqliteProcessJoin(pParse, p) ) return 1; - - /* For every "*" that occurs in the column list, insert the names of - ** all columns in all tables. And for every TABLE.* insert the names - ** of all columns in TABLE. The parser inserted a special expression - ** with the TK_ALL operator for each "*" that it found in the column list. - ** The following code just has to locate the TK_ALL expressions and expand - ** each one to the list of all columns in all tables. - ** - ** The first loop just checks to see if there are any "*" operators - ** that need expanding. - */ - for(k=0; knExpr; k++){ - Expr *pE = pEList->a[k].pExpr; - if( pE->op==TK_ALL ) break; - if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL - && pE->pLeft && pE->pLeft->op==TK_ID ) break; - } - rc = 0; - if( knExpr ){ - /* - ** If we get here it means the result set contains one or more "*" - ** operators that need to be expanded. Loop through each expression - ** in the result set and expand them one by one. - */ - struct ExprList_item *a = pEList->a; - ExprList *pNew = 0; - for(k=0; knExpr; k++){ - Expr *pE = a[k].pExpr; - if( pE->op!=TK_ALL && - (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){ - /* This particular expression does not need to be expanded. - */ - pNew = sqliteExprListAppend(pNew, a[k].pExpr, 0); - pNew->a[pNew->nExpr-1].zName = a[k].zName; - a[k].pExpr = 0; - a[k].zName = 0; - }else{ - /* This expression is a "*" or a "TABLE.*" and needs to be - ** expanded. */ - int tableSeen = 0; /* Set to 1 when TABLE matches */ - char *zTName; /* text of name of TABLE */ - if( pE->op==TK_DOT && pE->pLeft ){ - zTName = sqliteTableNameFromToken(&pE->pLeft->token); - }else{ - zTName = 0; - } - for(i=0; inSrc; i++){ - Table *pTab = pTabList->a[i].pTab; - char *zTabName = pTabList->a[i].zAlias; - if( zTabName==0 || zTabName[0]==0 ){ - zTabName = pTab->zName; - } - if( zTName && (zTabName==0 || zTabName[0]==0 || - sqliteStrICmp(zTName, zTabName)!=0) ){ - continue; - } - tableSeen = 1; - for(j=0; jnCol; j++){ - Expr *pExpr, *pLeft, *pRight; - char *zName = pTab->aCol[j].zName; - - if( i>0 && (pTabList->a[i-1].jointype & JT_NATURAL)!=0 && - columnIndex(pTabList->a[i-1].pTab, zName)>=0 ){ - /* In a NATURAL join, omit the join columns from the - ** table on the right */ - continue; - } - if( i>0 && sqliteIdListIndex(pTabList->a[i-1].pUsing, zName)>=0 ){ - /* In a join with a USING clause, omit columns in the - ** using clause from the table on the right. */ - continue; - } - pRight = sqliteExpr(TK_ID, 0, 0, 0); - if( pRight==0 ) break; - pRight->token.z = zName; - pRight->token.n = strlen(zName); - pRight->token.dyn = 0; - if( zTabName && pTabList->nSrc>1 ){ - pLeft = sqliteExpr(TK_ID, 0, 0, 0); - pExpr = sqliteExpr(TK_DOT, pLeft, pRight, 0); - if( pExpr==0 ) break; - pLeft->token.z = zTabName; - pLeft->token.n = strlen(zTabName); - pLeft->token.dyn = 0; - sqliteSetString((char**)&pExpr->span.z, zTabName, ".", zName, 0); - pExpr->span.n = strlen(pExpr->span.z); - pExpr->span.dyn = 1; - pExpr->token.z = 0; - pExpr->token.n = 0; - pExpr->token.dyn = 0; - }else{ - pExpr = pRight; - pExpr->span = pExpr->token; - } - pNew = sqliteExprListAppend(pNew, pExpr, 0); - } - } - if( !tableSeen ){ - if( zTName ){ - sqliteErrorMsg(pParse, "no such table: %s", zTName); - }else{ - sqliteErrorMsg(pParse, "no tables specified"); - } - rc = 1; - } - sqliteFree(zTName); - } - } - sqliteExprListDelete(pEList); - p->pEList = pNew; - } - return rc; -} - -/* -** This routine recursively unlinks the Select.pSrc.a[].pTab pointers -** in a select structure. It just sets the pointers to NULL. This -** routine is recursive in the sense that if the Select.pSrc.a[].pSelect -** pointer is not NULL, this routine is called recursively on that pointer. -** -** This routine is called on the Select structure that defines a -** VIEW in order to undo any bindings to tables. This is necessary -** because those tables might be DROPed by a subsequent SQL command. -** If the bindings are not removed, then the Select.pSrc->a[].pTab field -** will be left pointing to a deallocated Table structure after the -** DROP and a coredump will occur the next time the VIEW is used. -*/ -void sqliteSelectUnbind(Select *p){ - int i; - SrcList *pSrc = p->pSrc; - Table *pTab; - if( p==0 ) return; - for(i=0; inSrc; i++){ - if( (pTab = pSrc->a[i].pTab)!=0 ){ - if( pTab->isTransient ){ - sqliteDeleteTable(0, pTab); - } - pSrc->a[i].pTab = 0; - if( pSrc->a[i].pSelect ){ - sqliteSelectUnbind(pSrc->a[i].pSelect); - } - } - } -} - -/* -** This routine associates entries in an ORDER BY expression list with -** columns in a result. For each ORDER BY expression, the opcode of -** the top-level node is changed to TK_COLUMN and the iColumn value of -** the top-level node is filled in with column number and the iTable -** value of the top-level node is filled with iTable parameter. -** -** If there are prior SELECT clauses, they are processed first. A match -** in an earlier SELECT takes precedence over a later SELECT. -** -** Any entry that does not match is flagged as an error. The number -** of errors is returned. -** -** This routine does NOT correctly initialize the Expr.dataType field -** of the ORDER BY expressions. The multiSelectSortOrder() routine -** must be called to do that after the individual select statements -** have all been analyzed. This routine is unable to compute Expr.dataType -** because it must be called before the individual select statements -** have been analyzed. -*/ -static int matchOrderbyToColumn( - Parse *pParse, /* A place to leave error messages */ - Select *pSelect, /* Match to result columns of this SELECT */ - ExprList *pOrderBy, /* The ORDER BY values to match against columns */ - int iTable, /* Insert this value in iTable */ - int mustComplete /* If TRUE all ORDER BYs must match */ -){ - int nErr = 0; - int i, j; - ExprList *pEList; - - if( pSelect==0 || pOrderBy==0 ) return 1; - if( mustComplete ){ - for(i=0; inExpr; i++){ pOrderBy->a[i].done = 0; } - } - if( fillInColumnList(pParse, pSelect) ){ - return 1; - } - if( pSelect->pPrior ){ - if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){ - return 1; - } - } - pEList = pSelect->pEList; - for(i=0; inExpr; i++){ - Expr *pE = pOrderBy->a[i].pExpr; - int iCol = -1; - if( pOrderBy->a[i].done ) continue; - if( sqliteExprIsInteger(pE, &iCol) ){ - if( iCol<=0 || iCol>pEList->nExpr ){ - sqliteErrorMsg(pParse, - "ORDER BY position %d should be between 1 and %d", - iCol, pEList->nExpr); - nErr++; - break; - } - if( !mustComplete ) continue; - iCol--; - } - for(j=0; iCol<0 && jnExpr; j++){ - if( pEList->a[j].zName && (pE->op==TK_ID || pE->op==TK_STRING) ){ - char *zName, *zLabel; - zName = pEList->a[j].zName; - assert( pE->token.z ); - zLabel = sqliteStrNDup(pE->token.z, pE->token.n); - sqliteDequote(zLabel); - if( sqliteStrICmp(zName, zLabel)==0 ){ - iCol = j; - } - sqliteFree(zLabel); - } - if( iCol<0 && sqliteExprCompare(pE, pEList->a[j].pExpr) ){ - iCol = j; - } - } - if( iCol>=0 ){ - pE->op = TK_COLUMN; - pE->iColumn = iCol; - pE->iTable = iTable; - pOrderBy->a[i].done = 1; - } - if( iCol<0 && mustComplete ){ - sqliteErrorMsg(pParse, - "ORDER BY term number %d does not match any result column", i+1); - nErr++; - break; - } - } - return nErr; -} - -/* -** Get a VDBE for the given parser context. Create a new one if necessary. -** If an error occurs, return NULL and leave a message in pParse. -*/ -Vdbe *sqliteGetVdbe(Parse *pParse){ - Vdbe *v = pParse->pVdbe; - if( v==0 ){ - v = pParse->pVdbe = sqliteVdbeCreate(pParse->db); - } - return v; -} - -/* -** This routine sets the Expr.dataType field on all elements of -** the pOrderBy expression list. The pOrderBy list will have been -** set up by matchOrderbyToColumn(). Hence each expression has -** a TK_COLUMN as its root node. The Expr.iColumn refers to a -** column in the result set. The datatype is set to SQLITE_SO_TEXT -** if the corresponding column in p and every SELECT to the left of -** p has a datatype of SQLITE_SO_TEXT. If the cooressponding column -** in p or any of the left SELECTs is SQLITE_SO_NUM, then the datatype -** of the order-by expression is set to SQLITE_SO_NUM. -** -** Examples: -** -** CREATE TABLE one(a INTEGER, b TEXT); -** CREATE TABLE two(c VARCHAR(5), d FLOAT); -** -** SELECT b, b FROM one UNION SELECT d, c FROM two ORDER BY 1, 2; -** -** The primary sort key will use SQLITE_SO_NUM because the "d" in -** the second SELECT is numeric. The 1st column of the first SELECT -** is text but that does not matter because a numeric always overrides -** a text. -** -** The secondary key will use the SQLITE_SO_TEXT sort order because -** both the (second) "b" in the first SELECT and the "c" in the second -** SELECT have a datatype of text. -*/ -static void multiSelectSortOrder(Select *p, ExprList *pOrderBy){ - int i; - ExprList *pEList; - if( pOrderBy==0 ) return; - if( p==0 ){ - for(i=0; inExpr; i++){ - pOrderBy->a[i].pExpr->dataType = SQLITE_SO_TEXT; - } - return; - } - multiSelectSortOrder(p->pPrior, pOrderBy); - pEList = p->pEList; - for(i=0; inExpr; i++){ - Expr *pE = pOrderBy->a[i].pExpr; - if( pE->dataType==SQLITE_SO_NUM ) continue; - assert( pE->iColumn>=0 ); - if( pEList->nExpr>pE->iColumn ){ - pE->dataType = sqliteExprType(pEList->a[pE->iColumn].pExpr); - } - } -} - -/* -** Compute the iLimit and iOffset fields of the SELECT based on the -** nLimit and nOffset fields. nLimit and nOffset hold the integers -** that appear in the original SQL statement after the LIMIT and OFFSET -** keywords. Or that hold -1 and 0 if those keywords are omitted. -** iLimit and iOffset are the integer memory register numbers for -** counters used to compute the limit and offset. If there is no -** limit and/or offset, then iLimit and iOffset are negative. -** -** This routine changes the values if iLimit and iOffset only if -** a limit or offset is defined by nLimit and nOffset. iLimit and -** iOffset should have been preset to appropriate default values -** (usually but not always -1) prior to calling this routine. -** Only if nLimit>=0 or nOffset>0 do the limit registers get -** redefined. The UNION ALL operator uses this property to force -** the reuse of the same limit and offset registers across multiple -** SELECT statements. -*/ -static void computeLimitRegisters(Parse *pParse, Select *p){ - /* - ** If the comparison is p->nLimit>0 then "LIMIT 0" shows - ** all rows. It is the same as no limit. If the comparision is - ** p->nLimit>=0 then "LIMIT 0" show no rows at all. - ** "LIMIT -1" always shows all rows. There is some - ** contraversy about what the correct behavior should be. - ** The current implementation interprets "LIMIT 0" to mean - ** no rows. - */ - if( p->nLimit>=0 ){ - int iMem = pParse->nMem++; - Vdbe *v = sqliteGetVdbe(pParse); - if( v==0 ) return; - sqliteVdbeAddOp(v, OP_Integer, -p->nLimit, 0); - sqliteVdbeAddOp(v, OP_MemStore, iMem, 1); - p->iLimit = iMem; - } - if( p->nOffset>0 ){ - int iMem = pParse->nMem++; - Vdbe *v = sqliteGetVdbe(pParse); - if( v==0 ) return; - sqliteVdbeAddOp(v, OP_Integer, -p->nOffset, 0); - sqliteVdbeAddOp(v, OP_MemStore, iMem, 1); - p->iOffset = iMem; - } -} - -/* -** This routine is called to process a query that is really the union -** or intersection of two or more separate queries. -** -** "p" points to the right-most of the two queries. the query on the -** left is p->pPrior. The left query could also be a compound query -** in which case this routine will be called recursively. -** -** The results of the total query are to be written into a destination -** of type eDest with parameter iParm. -** -** Example 1: Consider a three-way compound SQL statement. -** -** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3 -** -** This statement is parsed up as follows: -** -** SELECT c FROM t3 -** | -** `-----> SELECT b FROM t2 -** | -** `------> SELECT a FROM t1 -** -** The arrows in the diagram above represent the Select.pPrior pointer. -** So if this routine is called with p equal to the t3 query, then -** pPrior will be the t2 query. p->op will be TK_UNION in this case. -** -** Notice that because of the way SQLite parses compound SELECTs, the -** individual selects always group from left to right. -*/ -static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){ - int rc; /* Success code from a subroutine */ - Select *pPrior; /* Another SELECT immediately to our left */ - Vdbe *v; /* Generate code to this VDBE */ - - /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only - ** the last SELECT in the series may have an ORDER BY or LIMIT. - */ - if( p==0 || p->pPrior==0 ) return 1; - pPrior = p->pPrior; - if( pPrior->pOrderBy ){ - sqliteErrorMsg(pParse,"ORDER BY clause should come after %s not before", - selectOpName(p->op)); - return 1; - } - if( pPrior->nLimit>=0 || pPrior->nOffset>0 ){ - sqliteErrorMsg(pParse,"LIMIT clause should come after %s not before", - selectOpName(p->op)); - return 1; - } - - /* Make sure we have a valid query engine. If not, create a new one. - */ - v = sqliteGetVdbe(pParse); - if( v==0 ) return 1; - - /* Create the destination temporary table if necessary - */ - if( eDest==SRT_TempTable ){ - sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0); - eDest = SRT_Table; - } - - /* Generate code for the left and right SELECT statements. - */ - switch( p->op ){ - case TK_ALL: { - if( p->pOrderBy==0 ){ - pPrior->nLimit = p->nLimit; - pPrior->nOffset = p->nOffset; - rc = sqliteSelect(pParse, pPrior, eDest, iParm, 0, 0, 0); - if( rc ) return rc; - p->pPrior = 0; - p->iLimit = pPrior->iLimit; - p->iOffset = pPrior->iOffset; - p->nLimit = -1; - p->nOffset = 0; - rc = sqliteSelect(pParse, p, eDest, iParm, 0, 0, 0); - p->pPrior = pPrior; - if( rc ) return rc; - break; - } - /* For UNION ALL ... ORDER BY fall through to the next case */ - } - case TK_EXCEPT: - case TK_UNION: { - int unionTab; /* Cursor number of the temporary table holding result */ - int op; /* One of the SRT_ operations to apply to self */ - int priorOp; /* The SRT_ operation to apply to prior selects */ - int nLimit, nOffset; /* Saved values of p->nLimit and p->nOffset */ - ExprList *pOrderBy; /* The ORDER BY clause for the right SELECT */ - - priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union; - if( eDest==priorOp && p->pOrderBy==0 && p->nLimit<0 && p->nOffset==0 ){ - /* We can reuse a temporary table generated by a SELECT to our - ** right. - */ - unionTab = iParm; - }else{ - /* We will need to create our own temporary table to hold the - ** intermediate results. - */ - unionTab = pParse->nTab++; - if( p->pOrderBy - && matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){ - return 1; - } - if( p->op!=TK_ALL ){ - sqliteVdbeAddOp(v, OP_OpenTemp, unionTab, 1); - sqliteVdbeAddOp(v, OP_KeyAsData, unionTab, 1); - }else{ - sqliteVdbeAddOp(v, OP_OpenTemp, unionTab, 0); - } - } - - /* Code the SELECT statements to our left - */ - rc = sqliteSelect(pParse, pPrior, priorOp, unionTab, 0, 0, 0); - if( rc ) return rc; - - /* Code the current SELECT statement - */ - switch( p->op ){ - case TK_EXCEPT: op = SRT_Except; break; - case TK_UNION: op = SRT_Union; break; - case TK_ALL: op = SRT_Table; break; - } - p->pPrior = 0; - pOrderBy = p->pOrderBy; - p->pOrderBy = 0; - nLimit = p->nLimit; - p->nLimit = -1; - nOffset = p->nOffset; - p->nOffset = 0; - rc = sqliteSelect(pParse, p, op, unionTab, 0, 0, 0); - p->pPrior = pPrior; - p->pOrderBy = pOrderBy; - p->nLimit = nLimit; - p->nOffset = nOffset; - if( rc ) return rc; - - /* Convert the data in the temporary table into whatever form - ** it is that we currently need. - */ - if( eDest!=priorOp || unionTab!=iParm ){ - int iCont, iBreak, iStart; - assert( p->pEList ); - if( eDest==SRT_Callback ){ - generateColumnNames(pParse, 0, p->pEList); - generateColumnTypes(pParse, p->pSrc, p->pEList); - } - iBreak = sqliteVdbeMakeLabel(v); - iCont = sqliteVdbeMakeLabel(v); - sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak); - computeLimitRegisters(pParse, p); - iStart = sqliteVdbeCurrentAddr(v); - multiSelectSortOrder(p, p->pOrderBy); - rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, - p->pOrderBy, -1, eDest, iParm, - iCont, iBreak); - if( rc ) return 1; - sqliteVdbeResolveLabel(v, iCont); - sqliteVdbeAddOp(v, OP_Next, unionTab, iStart); - sqliteVdbeResolveLabel(v, iBreak); - sqliteVdbeAddOp(v, OP_Close, unionTab, 0); - if( p->pOrderBy ){ - generateSortTail(p, v, p->pEList->nExpr, eDest, iParm); - } - } - break; - } - case TK_INTERSECT: { - int tab1, tab2; - int iCont, iBreak, iStart; - int nLimit, nOffset; - - /* INTERSECT is different from the others since it requires - ** two temporary tables. Hence it has its own case. Begin - ** by allocating the tables we will need. - */ - tab1 = pParse->nTab++; - tab2 = pParse->nTab++; - if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){ - return 1; - } - sqliteVdbeAddOp(v, OP_OpenTemp, tab1, 1); - sqliteVdbeAddOp(v, OP_KeyAsData, tab1, 1); - - /* Code the SELECTs to our left into temporary table "tab1". - */ - rc = sqliteSelect(pParse, pPrior, SRT_Union, tab1, 0, 0, 0); - if( rc ) return rc; - - /* Code the current SELECT into temporary table "tab2" - */ - sqliteVdbeAddOp(v, OP_OpenTemp, tab2, 1); - sqliteVdbeAddOp(v, OP_KeyAsData, tab2, 1); - p->pPrior = 0; - nLimit = p->nLimit; - p->nLimit = -1; - nOffset = p->nOffset; - p->nOffset = 0; - rc = sqliteSelect(pParse, p, SRT_Union, tab2, 0, 0, 0); - p->pPrior = pPrior; - p->nLimit = nLimit; - p->nOffset = nOffset; - if( rc ) return rc; - - /* Generate code to take the intersection of the two temporary - ** tables. - */ - assert( p->pEList ); - if( eDest==SRT_Callback ){ - generateColumnNames(pParse, 0, p->pEList); - generateColumnTypes(pParse, p->pSrc, p->pEList); - } - iBreak = sqliteVdbeMakeLabel(v); - iCont = sqliteVdbeMakeLabel(v); - sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak); - computeLimitRegisters(pParse, p); - iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0); - sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont); - multiSelectSortOrder(p, p->pOrderBy); - rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, - p->pOrderBy, -1, eDest, iParm, - iCont, iBreak); - if( rc ) return 1; - sqliteVdbeResolveLabel(v, iCont); - sqliteVdbeAddOp(v, OP_Next, tab1, iStart); - sqliteVdbeResolveLabel(v, iBreak); - sqliteVdbeAddOp(v, OP_Close, tab2, 0); - sqliteVdbeAddOp(v, OP_Close, tab1, 0); - if( p->pOrderBy ){ - generateSortTail(p, v, p->pEList->nExpr, eDest, iParm); - } - break; - } - } - assert( p->pEList && pPrior->pEList ); - if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ - sqliteErrorMsg(pParse, "SELECTs to the left and right of %s" - " do not have the same number of result columns", selectOpName(p->op)); - return 1; - } - return 0; -} - -/* -** Scan through the expression pExpr. Replace every reference to -** a column in table number iTable with a copy of the iColumn-th -** entry in pEList. (But leave references to the ROWID column -** unchanged.) -** -** This routine is part of the flattening procedure. A subquery -** whose result set is defined by pEList appears as entry in the -** FROM clause of a SELECT such that the VDBE cursor assigned to that -** FORM clause entry is iTable. This routine make the necessary -** changes to pExpr so that it refers directly to the source table -** of the subquery rather the result set of the subquery. -*/ -static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */ -static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){ - if( pExpr==0 ) return; - if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ - if( pExpr->iColumn<0 ){ - pExpr->op = TK_NULL; - }else{ - Expr *pNew; - assert( pEList!=0 && pExpr->iColumnnExpr ); - assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 ); - pNew = pEList->a[pExpr->iColumn].pExpr; - assert( pNew!=0 ); - pExpr->op = pNew->op; - pExpr->dataType = pNew->dataType; - assert( pExpr->pLeft==0 ); - pExpr->pLeft = sqliteExprDup(pNew->pLeft); - assert( pExpr->pRight==0 ); - pExpr->pRight = sqliteExprDup(pNew->pRight); - assert( pExpr->pList==0 ); - pExpr->pList = sqliteExprListDup(pNew->pList); - pExpr->iTable = pNew->iTable; - pExpr->iColumn = pNew->iColumn; - pExpr->iAgg = pNew->iAgg; - sqliteTokenCopy(&pExpr->token, &pNew->token); - sqliteTokenCopy(&pExpr->span, &pNew->span); - } - }else{ - substExpr(pExpr->pLeft, iTable, pEList); - substExpr(pExpr->pRight, iTable, pEList); - substExprList(pExpr->pList, iTable, pEList); - } -} -static void -substExprList(ExprList *pList, int iTable, ExprList *pEList){ - int i; - if( pList==0 ) return; - for(i=0; inExpr; i++){ - substExpr(pList->a[i].pExpr, iTable, pEList); - } -} - -/* -** This routine attempts to flatten subqueries in order to speed -** execution. It returns 1 if it makes changes and 0 if no flattening -** occurs. -** -** To understand the concept of flattening, consider the following -** query: -** -** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5 -** -** The default way of implementing this query is to execute the -** subquery first and store the results in a temporary table, then -** run the outer query on that temporary table. This requires two -** passes over the data. Furthermore, because the temporary table -** has no indices, the WHERE clause on the outer query cannot be -** optimized. -** -** This routine attempts to rewrite queries such as the above into -** a single flat select, like this: -** -** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 -** -** The code generated for this simpification gives the same result -** but only has to scan the data once. And because indices might -** exist on the table t1, a complete scan of the data might be -** avoided. -** -** Flattening is only attempted if all of the following are true: -** -** (1) The subquery and the outer query do not both use aggregates. -** -** (2) The subquery is not an aggregate or the outer query is not a join. -** -** (3) The subquery is not the right operand of a left outer join, or -** the subquery is not itself a join. (Ticket #306) -** -** (4) The subquery is not DISTINCT or the outer query is not a join. -** -** (5) The subquery is not DISTINCT or the outer query does not use -** aggregates. -** -** (6) The subquery does not use aggregates or the outer query is not -** DISTINCT. -** -** (7) The subquery has a FROM clause. -** -** (8) The subquery does not use LIMIT or the outer query is not a join. -** -** (9) The subquery does not use LIMIT or the outer query does not use -** aggregates. -** -** (10) The subquery does not use aggregates or the outer query does not -** use LIMIT. -** -** (11) The subquery and the outer query do not both have ORDER BY clauses. -** -** (12) The subquery is not the right term of a LEFT OUTER JOIN or the -** subquery has no WHERE clause. (added by ticket #350) -** -** In this routine, the "p" parameter is a pointer to the outer query. -** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query -** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. -** -** If flattening is not attempted, this routine is a no-op and returns 0. -** If flattening is attempted this routine returns 1. -** -** All of the expression analysis must occur on both the outer query and -** the subquery before this routine runs. -*/ -static int flattenSubquery( - Parse *pParse, /* The parsing context */ - Select *p, /* The parent or outer SELECT statement */ - int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ - int isAgg, /* True if outer SELECT uses aggregate functions */ - int subqueryIsAgg /* True if the subquery uses aggregate functions */ -){ - Select *pSub; /* The inner query or "subquery" */ - SrcList *pSrc; /* The FROM clause of the outer query */ - SrcList *pSubSrc; /* The FROM clause of the subquery */ - ExprList *pList; /* The result set of the outer query */ - int iParent; /* VDBE cursor number of the pSub result set temp table */ - int i; - Expr *pWhere; - - /* Check to see if flattening is permitted. Return 0 if not. - */ - if( p==0 ) return 0; - pSrc = p->pSrc; - assert( pSrc && iFrom>=0 && iFromnSrc ); - pSub = pSrc->a[iFrom].pSelect; - assert( pSub!=0 ); - if( isAgg && subqueryIsAgg ) return 0; - if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; - pSubSrc = pSub->pSrc; - assert( pSubSrc ); - if( pSubSrc->nSrc==0 ) return 0; - if( (pSub->isDistinct || pSub->nLimit>=0) && (pSrc->nSrc>1 || isAgg) ){ - return 0; - } - if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0; - if( p->pOrderBy && pSub->pOrderBy ) return 0; - - /* Restriction 3: If the subquery is a join, make sure the subquery is - ** not used as the right operand of an outer join. Examples of why this - ** is not allowed: - ** - ** t1 LEFT OUTER JOIN (t2 JOIN t3) - ** - ** If we flatten the above, we would get - ** - ** (t1 LEFT OUTER JOIN t2) JOIN t3 - ** - ** which is not at all the same thing. - */ - if( pSubSrc->nSrc>1 && iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0 ){ - return 0; - } - - /* Restriction 12: If the subquery is the right operand of a left outer - ** join, make sure the subquery has no WHERE clause. - ** An examples of why this is not allowed: - ** - ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0) - ** - ** If we flatten the above, we would get - ** - ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0 - ** - ** But the t2.x>0 test will always fail on a NULL row of t2, which - ** effectively converts the OUTER JOIN into an INNER JOIN. - */ - if( iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0 - && pSub->pWhere!=0 ){ - return 0; - } - - /* If we reach this point, it means flattening is permitted for the - ** iFrom-th entry of the FROM clause in the outer query. - */ - - /* Move all of the FROM elements of the subquery into the - ** the FROM clause of the outer query. Before doing this, remember - ** the cursor number for the original outer query FROM element in - ** iParent. The iParent cursor will never be used. Subsequent code - ** will scan expressions looking for iParent references and replace - ** those references with expressions that resolve to the subquery FROM - ** elements we are now copying in. - */ - iParent = pSrc->a[iFrom].iCursor; - { - int nSubSrc = pSubSrc->nSrc; - int jointype = pSrc->a[iFrom].jointype; - - if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){ - sqliteDeleteTable(0, pSrc->a[iFrom].pTab); - } - sqliteFree(pSrc->a[iFrom].zDatabase); - sqliteFree(pSrc->a[iFrom].zName); - sqliteFree(pSrc->a[iFrom].zAlias); - if( nSubSrc>1 ){ - int extra = nSubSrc - 1; - for(i=1; ipSrc = pSrc; - for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){ - pSrc->a[i] = pSrc->a[i-extra]; - } - } - for(i=0; ia[i+iFrom] = pSubSrc->a[i]; - memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); - } - pSrc->a[iFrom+nSubSrc-1].jointype = jointype; - } - - /* Now begin substituting subquery result set expressions for - ** references to the iParent in the outer query. - ** - ** Example: - ** - ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; - ** \ \_____________ subquery __________/ / - ** \_____________________ outer query ______________________________/ - ** - ** We look at every expression in the outer query and every place we see - ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". - */ - substExprList(p->pEList, iParent, pSub->pEList); - pList = p->pEList; - for(i=0; inExpr; i++){ - Expr *pExpr; - if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ - pList->a[i].zName = sqliteStrNDup(pExpr->span.z, pExpr->span.n); - } - } - if( isAgg ){ - substExprList(p->pGroupBy, iParent, pSub->pEList); - substExpr(p->pHaving, iParent, pSub->pEList); - } - if( pSub->pOrderBy ){ - assert( p->pOrderBy==0 ); - p->pOrderBy = pSub->pOrderBy; - pSub->pOrderBy = 0; - }else if( p->pOrderBy ){ - substExprList(p->pOrderBy, iParent, pSub->pEList); - } - if( pSub->pWhere ){ - pWhere = sqliteExprDup(pSub->pWhere); - }else{ - pWhere = 0; - } - if( subqueryIsAgg ){ - assert( p->pHaving==0 ); - p->pHaving = p->pWhere; - p->pWhere = pWhere; - substExpr(p->pHaving, iParent, pSub->pEList); - if( pSub->pHaving ){ - Expr *pHaving = sqliteExprDup(pSub->pHaving); - if( p->pHaving ){ - p->pHaving = sqliteExpr(TK_AND, p->pHaving, pHaving, 0); - }else{ - p->pHaving = pHaving; - } - } - assert( p->pGroupBy==0 ); - p->pGroupBy = sqliteExprListDup(pSub->pGroupBy); - }else if( p->pWhere==0 ){ - p->pWhere = pWhere; - }else{ - substExpr(p->pWhere, iParent, pSub->pEList); - if( pWhere ){ - p->pWhere = sqliteExpr(TK_AND, p->pWhere, pWhere, 0); - } - } - - /* The flattened query is distinct if either the inner or the - ** outer query is distinct. - */ - p->isDistinct = p->isDistinct || pSub->isDistinct; - - /* Transfer the limit expression from the subquery to the outer - ** query. - */ - if( pSub->nLimit>=0 ){ - if( p->nLimit<0 ){ - p->nLimit = pSub->nLimit; - }else if( p->nLimit+p->nOffset > pSub->nLimit+pSub->nOffset ){ - p->nLimit = pSub->nLimit + pSub->nOffset - p->nOffset; - } - } - p->nOffset += pSub->nOffset; - - /* Finially, delete what is left of the subquery and return - ** success. - */ - sqliteSelectDelete(pSub); - return 1; -} - -/* -** Analyze the SELECT statement passed in as an argument to see if it -** is a simple min() or max() query. If it is and this query can be -** satisfied using a single seek to the beginning or end of an index, -** then generate the code for this SELECT and return 1. If this is not a -** simple min() or max() query, then return 0; -** -** A simply min() or max() query looks like this: -** -** SELECT min(a) FROM table; -** SELECT max(a) FROM table; -** -** The query may have only a single table in its FROM argument. There -** can be no GROUP BY or HAVING or WHERE clauses. The result set must -** be the min() or max() of a single column of the table. The column -** in the min() or max() function must be indexed. -** -** The parameters to this routine are the same as for sqliteSelect(). -** See the header comment on that routine for additional information. -*/ -static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ - Expr *pExpr; - int iCol; - Table *pTab; - Index *pIdx; - int base; - Vdbe *v; - int seekOp; - int cont; - ExprList *pEList, *pList, eList; - struct ExprList_item eListItem; - SrcList *pSrc; - - - /* Check to see if this query is a simple min() or max() query. Return - ** zero if it is not. - */ - if( p->pGroupBy || p->pHaving || p->pWhere ) return 0; - pSrc = p->pSrc; - if( pSrc->nSrc!=1 ) return 0; - pEList = p->pEList; - if( pEList->nExpr!=1 ) return 0; - pExpr = pEList->a[0].pExpr; - if( pExpr->op!=TK_AGG_FUNCTION ) return 0; - pList = pExpr->pList; - if( pList==0 || pList->nExpr!=1 ) return 0; - if( pExpr->token.n!=3 ) return 0; - if( sqliteStrNICmp(pExpr->token.z,"min",3)==0 ){ - seekOp = OP_Rewind; - }else if( sqliteStrNICmp(pExpr->token.z,"max",3)==0 ){ - seekOp = OP_Last; - }else{ - return 0; - } - pExpr = pList->a[0].pExpr; - if( pExpr->op!=TK_COLUMN ) return 0; - iCol = pExpr->iColumn; - pTab = pSrc->a[0].pTab; - - /* If we get to here, it means the query is of the correct form. - ** Check to make sure we have an index and make pIdx point to the - ** appropriate index. If the min() or max() is on an INTEGER PRIMARY - ** key column, no index is necessary so set pIdx to NULL. If no - ** usable index is found, return 0. - */ - if( iCol<0 ){ - pIdx = 0; - }else{ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->nColumn>=1 ); - if( pIdx->aiColumn[0]==iCol ) break; - } - if( pIdx==0 ) return 0; - } - - /* Identify column types if we will be using the callback. This - ** step is skipped if the output is going to a table or a memory cell. - ** The column names have already been generated in the calling function. - */ - v = sqliteGetVdbe(pParse); - if( v==0 ) return 0; - if( eDest==SRT_Callback ){ - generateColumnTypes(pParse, p->pSrc, p->pEList); - } - - /* If the output is destined for a temporary table, open that table. - */ - if( eDest==SRT_TempTable ){ - sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0); - } - - /* Generating code to find the min or the max. Basically all we have - ** to do is find the first or the last entry in the chosen index. If - ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first - ** or last entry in the main table. - */ - sqliteCodeVerifySchema(pParse, pTab->iDb); - base = pSrc->a[0].iCursor; - computeLimitRegisters(pParse, p); - if( pSrc->a[0].pSelect==0 ){ - sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqliteVdbeOp3(v, OP_OpenRead, base, pTab->tnum, pTab->zName, 0); - } - cont = sqliteVdbeMakeLabel(v); - if( pIdx==0 ){ - sqliteVdbeAddOp(v, seekOp, base, 0); - }else{ - sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0); - sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC); - if( seekOp==OP_Rewind ){ - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_MakeKey, 1, 0); - sqliteVdbeAddOp(v, OP_IncrKey, 0, 0); - seekOp = OP_MoveTo; - } - sqliteVdbeAddOp(v, seekOp, base+1, 0); - sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0); - sqliteVdbeAddOp(v, OP_Close, base+1, 0); - sqliteVdbeAddOp(v, OP_MoveTo, base, 0); - } - eList.nExpr = 1; - memset(&eListItem, 0, sizeof(eListItem)); - eList.a = &eListItem; - eList.a[0].pExpr = pExpr; - selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont); - sqliteVdbeResolveLabel(v, cont); - sqliteVdbeAddOp(v, OP_Close, base, 0); - - return 1; -} - -/* -** Generate code for the given SELECT statement. -** -** The results are distributed in various ways depending on the -** value of eDest and iParm. -** -** eDest Value Result -** ------------ ------------------------------------------- -** SRT_Callback Invoke the callback for each row of the result. -** -** SRT_Mem Store first result in memory cell iParm -** -** SRT_Set Store results as keys of a table with cursor iParm -** -** SRT_Union Store results as a key in a temporary table iParm -** -** SRT_Except Remove results from the temporary table iParm. -** -** SRT_Table Store results in temporary table iParm -** -** The table above is incomplete. Additional eDist value have be added -** since this comment was written. See the selectInnerLoop() function for -** a complete listing of the allowed values of eDest and their meanings. -** -** This routine returns the number of errors. If any errors are -** encountered, then an appropriate error message is left in -** pParse->zErrMsg. -** -** This routine does NOT free the Select structure passed in. The -** calling function needs to do that. -** -** The pParent, parentTab, and *pParentAgg fields are filled in if this -** SELECT is a subquery. This routine may try to combine this SELECT -** with its parent to form a single flat query. In so doing, it might -** change the parent query from a non-aggregate to an aggregate query. -** For that reason, the pParentAgg flag is passed as a pointer, so it -** can be changed. -** -** Example 1: The meaning of the pParent parameter. -** -** SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3; -** \ \_______ subquery _______/ / -** \ / -** \____________________ outer query ___________________/ -** -** This routine is called for the outer query first. For that call, -** pParent will be NULL. During the processing of the outer query, this -** routine is called recursively to handle the subquery. For the recursive -** call, pParent will point to the outer query. Because the subquery is -** the second element in a three-way join, the parentTab parameter will -** be 1 (the 2nd value of a 0-indexed array.) -*/ -int sqliteSelect( - Parse *pParse, /* The parser context */ - Select *p, /* The SELECT statement being coded. */ - int eDest, /* How to dispose of the results */ - int iParm, /* A parameter used by the eDest disposal method */ - Select *pParent, /* Another SELECT for which this is a sub-query */ - int parentTab, /* Index in pParent->pSrc of this query */ - int *pParentAgg /* True if pParent uses aggregate functions */ -){ - int i; - WhereInfo *pWInfo; - Vdbe *v; - int isAgg = 0; /* True for select lists like "count(*)" */ - ExprList *pEList; /* List of columns to extract. */ - SrcList *pTabList; /* List of tables to select from */ - Expr *pWhere; /* The WHERE clause. May be NULL */ - ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ - ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ - Expr *pHaving; /* The HAVING clause. May be NULL */ - int isDistinct; /* True if the DISTINCT keyword is present */ - int distinct; /* Table to use for the distinct set */ - int rc = 1; /* Value to return from this function */ - - if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1; - if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; - - /* If there is are a sequence of queries, do the earlier ones first. - */ - if( p->pPrior ){ - return multiSelect(pParse, p, eDest, iParm); - } - - /* Make local copies of the parameters for this query. - */ - pTabList = p->pSrc; - pWhere = p->pWhere; - pOrderBy = p->pOrderBy; - pGroupBy = p->pGroupBy; - pHaving = p->pHaving; - isDistinct = p->isDistinct; - - /* Allocate VDBE cursors for each table in the FROM clause - */ - sqliteSrcListAssignCursors(pParse, pTabList); - - /* - ** Do not even attempt to generate any code if we have already seen - ** errors before this routine starts. - */ - if( pParse->nErr>0 ) goto select_end; - - /* Expand any "*" terms in the result set. (For example the "*" in - ** "SELECT * FROM t1") The fillInColumnlist() routine also does some - ** other housekeeping - see the header comment for details. - */ - if( fillInColumnList(pParse, p) ){ - goto select_end; - } - pWhere = p->pWhere; - pEList = p->pEList; - if( pEList==0 ) goto select_end; - - /* If writing to memory or generating a set - ** only a single column may be output. - */ - if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){ - sqliteErrorMsg(pParse, "only a single result allowed for " - "a SELECT that is part of an expression"); - goto select_end; - } - - /* ORDER BY is ignored for some destinations. - */ - switch( eDest ){ - case SRT_Union: - case SRT_Except: - case SRT_Discard: - pOrderBy = 0; - break; - default: - break; - } - - /* At this point, we should have allocated all the cursors that we - ** need to handle subquerys and temporary tables. - ** - ** Resolve the column names and do a semantics check on all the expressions. - */ - for(i=0; inExpr; i++){ - if( sqliteExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){ - goto select_end; - } - if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){ - goto select_end; - } - } - if( pWhere ){ - if( sqliteExprResolveIds(pParse, pTabList, pEList, pWhere) ){ - goto select_end; - } - if( sqliteExprCheck(pParse, pWhere, 0, 0) ){ - goto select_end; - } - } - if( pHaving ){ - if( pGroupBy==0 ){ - sqliteErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); - goto select_end; - } - if( sqliteExprResolveIds(pParse, pTabList, pEList, pHaving) ){ - goto select_end; - } - if( sqliteExprCheck(pParse, pHaving, 1, &isAgg) ){ - goto select_end; - } - } - if( pOrderBy ){ - for(i=0; inExpr; i++){ - int iCol; - Expr *pE = pOrderBy->a[i].pExpr; - if( sqliteExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){ - sqliteExprDelete(pE); - pE = pOrderBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr); - } - if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){ - goto select_end; - } - if( sqliteExprCheck(pParse, pE, isAgg, 0) ){ - goto select_end; - } - if( sqliteExprIsConstant(pE) ){ - if( sqliteExprIsInteger(pE, &iCol)==0 ){ - sqliteErrorMsg(pParse, - "ORDER BY terms must not be non-integer constants"); - goto select_end; - }else if( iCol<=0 || iCol>pEList->nExpr ){ - sqliteErrorMsg(pParse, - "ORDER BY column number %d out of range - should be " - "between 1 and %d", iCol, pEList->nExpr); - goto select_end; - } - } - } - } - if( pGroupBy ){ - for(i=0; inExpr; i++){ - int iCol; - Expr *pE = pGroupBy->a[i].pExpr; - if( sqliteExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){ - sqliteExprDelete(pE); - pE = pGroupBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr); - } - if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){ - goto select_end; - } - if( sqliteExprCheck(pParse, pE, isAgg, 0) ){ - goto select_end; - } - if( sqliteExprIsConstant(pE) ){ - if( sqliteExprIsInteger(pE, &iCol)==0 ){ - sqliteErrorMsg(pParse, - "GROUP BY terms must not be non-integer constants"); - goto select_end; - }else if( iCol<=0 || iCol>pEList->nExpr ){ - sqliteErrorMsg(pParse, - "GROUP BY column number %d out of range - should be " - "between 1 and %d", iCol, pEList->nExpr); - goto select_end; - } - } - } - } - - /* Begin generating code. - */ - v = sqliteGetVdbe(pParse); - if( v==0 ) goto select_end; - - /* Identify column names if we will be using them in a callback. This - ** step is skipped if the output is going to some other destination. - */ - if( eDest==SRT_Callback ){ - generateColumnNames(pParse, pTabList, pEList); - } - - /* Generate code for all sub-queries in the FROM clause - */ - for(i=0; inSrc; i++){ - const char *zSavedAuthContext; - int needRestoreContext; - - if( pTabList->a[i].pSelect==0 ) continue; - if( pTabList->a[i].zName!=0 ){ - zSavedAuthContext = pParse->zAuthContext; - pParse->zAuthContext = pTabList->a[i].zName; - needRestoreContext = 1; - }else{ - needRestoreContext = 0; - } - sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable, - pTabList->a[i].iCursor, p, i, &isAgg); - if( needRestoreContext ){ - pParse->zAuthContext = zSavedAuthContext; - } - pTabList = p->pSrc; - pWhere = p->pWhere; - if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){ - pOrderBy = p->pOrderBy; - } - pGroupBy = p->pGroupBy; - pHaving = p->pHaving; - isDistinct = p->isDistinct; - } - - /* Check for the special case of a min() or max() function by itself - ** in the result set. - */ - if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){ - rc = 0; - goto select_end; - } - - /* Check to see if this is a subquery that can be "flattened" into its parent. - ** If flattening is a possiblity, do so and return immediately. - */ - if( pParent && pParentAgg && - flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ - if( isAgg ) *pParentAgg = 1; - return rc; - } - - /* Set the limiter. - */ - computeLimitRegisters(pParse, p); - - /* Identify column types if we will be using a callback. This - ** step is skipped if the output is going to a destination other - ** than a callback. - ** - ** We have to do this separately from the creation of column names - ** above because if the pTabList contains views then they will not - ** have been resolved and we will not know the column types until - ** now. - */ - if( eDest==SRT_Callback ){ - generateColumnTypes(pParse, pTabList, pEList); - } - - /* If the output is destined for a temporary table, open that table. - */ - if( eDest==SRT_TempTable ){ - sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0); - } - - /* Do an analysis of aggregate expressions. - */ - sqliteAggregateInfoReset(pParse); - if( isAgg || pGroupBy ){ - assert( pParse->nAgg==0 ); - isAgg = 1; - for(i=0; inExpr; i++){ - if( sqliteExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){ - goto select_end; - } - } - if( pGroupBy ){ - for(i=0; inExpr; i++){ - if( sqliteExprAnalyzeAggregates(pParse, pGroupBy->a[i].pExpr) ){ - goto select_end; - } - } - } - if( pHaving && sqliteExprAnalyzeAggregates(pParse, pHaving) ){ - goto select_end; - } - if( pOrderBy ){ - for(i=0; inExpr; i++){ - if( sqliteExprAnalyzeAggregates(pParse, pOrderBy->a[i].pExpr) ){ - goto select_end; - } - } - } - } - - /* Reset the aggregator - */ - if( isAgg ){ - sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg); - for(i=0; inAgg; i++){ - FuncDef *pFunc; - if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){ - sqliteVdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_POINTER); - } - } - if( pGroupBy==0 ){ - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_AggFocus, 0, 0); - } - } - - /* Initialize the memory cell to NULL - */ - if( eDest==SRT_Mem ){ - sqliteVdbeAddOp(v, OP_String, 0, 0); - sqliteVdbeAddOp(v, OP_MemStore, iParm, 1); - } - - /* Open a temporary table to use for the distinct set. - */ - if( isDistinct ){ - distinct = pParse->nTab++; - sqliteVdbeAddOp(v, OP_OpenTemp, distinct, 1); - }else{ - distinct = -1; - } - - /* Begin the database scan - */ - pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0, - pGroupBy ? 0 : &pOrderBy); - if( pWInfo==0 ) goto select_end; - - /* Use the standard inner loop if we are not dealing with - ** aggregates - */ - if( !isAgg ){ - if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, - iParm, pWInfo->iContinue, pWInfo->iBreak) ){ - goto select_end; - } - } - - /* If we are dealing with aggregates, then do the special aggregate - ** processing. - */ - else{ - AggExpr *pAgg; - if( pGroupBy ){ - int lbl1; - for(i=0; inExpr; i++){ - sqliteExprCode(pParse, pGroupBy->a[i].pExpr); - } - sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0); - if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pGroupBy); - lbl1 = sqliteVdbeMakeLabel(v); - sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1); - for(i=0, pAgg=pParse->aAgg; inAgg; i++, pAgg++){ - if( pAgg->isAgg ) continue; - sqliteExprCode(pParse, pAgg->pExpr); - sqliteVdbeAddOp(v, OP_AggSet, 0, i); - } - sqliteVdbeResolveLabel(v, lbl1); - } - for(i=0, pAgg=pParse->aAgg; inAgg; i++, pAgg++){ - Expr *pE; - int nExpr; - FuncDef *pDef; - if( !pAgg->isAgg ) continue; - assert( pAgg->pFunc!=0 ); - assert( pAgg->pFunc->xStep!=0 ); - pDef = pAgg->pFunc; - pE = pAgg->pExpr; - assert( pE!=0 ); - assert( pE->op==TK_AGG_FUNCTION ); - nExpr = sqliteExprCodeExprList(pParse, pE->pList, pDef->includeTypes); - sqliteVdbeAddOp(v, OP_Integer, i, 0); - sqliteVdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER); - } - } - - /* End the database scan loop. - */ - sqliteWhereEnd(pWInfo); - - /* If we are processing aggregates, we need to set up a second loop - ** over all of the aggregate values and process them. - */ - if( isAgg ){ - int endagg = sqliteVdbeMakeLabel(v); - int startagg; - startagg = sqliteVdbeAddOp(v, OP_AggNext, 0, endagg); - pParse->useAgg = 1; - if( pHaving ){ - sqliteExprIfFalse(pParse, pHaving, startagg, 1); - } - if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, - iParm, startagg, endagg) ){ - goto select_end; - } - sqliteVdbeAddOp(v, OP_Goto, 0, startagg); - sqliteVdbeResolveLabel(v, endagg); - sqliteVdbeAddOp(v, OP_Noop, 0, 0); - pParse->useAgg = 0; - } - - /* If there is an ORDER BY clause, then we need to sort the results - ** and send them to the callback one by one. - */ - if( pOrderBy ){ - generateSortTail(p, v, pEList->nExpr, eDest, iParm); - } - - /* If this was a subquery, we have now converted the subquery into a - ** temporary table. So delete the subquery structure from the parent - ** to prevent this subquery from being evaluated again and to force the - ** the use of the temporary table. - */ - if( pParent ){ - assert( pParent->pSrc->nSrc>parentTab ); - assert( pParent->pSrc->a[parentTab].pSelect==p ); - sqliteSelectDelete(p); - pParent->pSrc->a[parentTab].pSelect = 0; - } - - /* The SELECT was successfully coded. Set the return code to 0 - ** to indicate no errors. - */ - rc = 0; - - /* Control jumps to here if an error is encountered above, or upon - ** successful coding of the SELECT. - */ -select_end: - sqliteAggregateInfoReset(pParse); - return rc; -} diff --git a/dbLifeLog/DBD-SQLite2-0.33/select.o b/dbLifeLog/DBD-SQLite2-0.33/select.o deleted file mode 100644 index a6a158669cc9f6ade00dc7a20a1bbe0fb5a61dac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36376 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 diff --git a/dbLifeLog/DBD-SQLite2-0.33/sqlite.h b/dbLifeLog/DBD-SQLite2-0.33/sqlite.h deleted file mode 100644 index 86f6e03..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/sqlite.h +++ /dev/null @@ -1,868 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the SQLite library -** presents to client programs. -** -** @(#) $Id: sqlite.h,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ -*/ -#ifndef _SQLITE_H_ -#define _SQLITE_H_ -#include /* Needed for the definition of va_list */ - -/* -** Make sure we can call this stuff from C++. -*/ -#ifdef __cplusplus -extern "C" { -#endif - -/* -** The version of the SQLite library. -*/ -#define SQLITE_VERSION "2.8.15" - -/* -** The version string is also compiled into the library so that a program -** can check to make sure that the lib*.a file and the *.h file are from -** the same version. -*/ -extern const char sqlite_version[]; - -/* -** The SQLITE_UTF8 macro is defined if the library expects to see -** UTF-8 encoded data. The SQLITE_ISO8859 macro is defined if the -** iso8859 encoded should be used. -*/ -#define SQLITE_UTF8 1 - -/* -** The following constant holds one of two strings, "UTF-8" or "iso8859", -** depending on which character encoding the SQLite library expects to -** see. The character encoding makes a difference for the LIKE and GLOB -** operators and for the LENGTH() and SUBSTR() functions. -*/ -extern const char sqlite_encoding[]; - -/* -** Each open sqlite database is represented by an instance of the -** following opaque structure. -*/ -typedef struct sqlite sqlite; - -/* -** A function to open a new sqlite database. -** -** If the database does not exist and mode indicates write -** permission, then a new database is created. If the database -** does not exist and mode does not indicate write permission, -** then the open fails, an error message generated (if errmsg!=0) -** and the function returns 0. -** -** If mode does not indicates user write permission, then the -** database is opened read-only. -** -** The Truth: As currently implemented, all databases are opened -** for writing all the time. Maybe someday we will provide the -** ability to open a database readonly. The mode parameters is -** provided in anticipation of that enhancement. -*/ -sqlite *sqlite_open(const char *filename, int mode, char **errmsg); - -/* -** A function to close the database. -** -** Call this function with a pointer to a structure that was previously -** returned from sqlite_open() and the corresponding database will by closed. -*/ -void sqlite_close(sqlite *); - -/* -** The type for a callback function. -*/ -typedef int (*sqlite_callback)(void*,int,char**, char**); - -/* -** A function to executes one or more statements of SQL. -** -** If one or more of the SQL statements are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. This callback -** should normally return 0. If the callback returns a non-zero -** value then the query is aborted, all subsequent SQL statements -** are skipped and the sqlite_exec() function returns the SQLITE_ABORT. -** -** The 4th parameter is an arbitrary pointer that is passed -** to the callback function as its first parameter. -** -** The 2nd parameter to the callback function is the number of -** columns in the query result. The 3rd parameter to the callback -** is an array of strings holding the values for each column. -** The 4th parameter to the callback is an array of strings holding -** the names of each column. -** -** The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** If an error occurs while parsing or evaluating the SQL (but -** not while executing the callback) then an appropriate error -** message is written into memory obtained from malloc() and -** *errmsg is made to point to that message. The calling function -** is responsible for freeing the memory that holds the error -** message. Use sqlite_freemem() for this. If errmsg==NULL, -** then no error message is ever written. -** -** The return value is is SQLITE_OK if there are no errors and -** some other return code if there is an error. The particular -** return value depends on the type of error. -** -** If the query could not be executed because a database file is -** locked or busy, then this function returns SQLITE_BUSY. (This -** behavior can be modified somewhat using the sqlite_busy_handler() -** and sqlite_busy_timeout() functions below.) -*/ -int sqlite_exec( - sqlite*, /* An open database */ - const char *sql, /* SQL to be executed */ - sqlite_callback, /* Callback function */ - void *, /* 1st argument to callback function */ - char **errmsg /* Error msg written here */ -); - -/* -** Return values for sqlite_exec() and sqlite_step() -*/ -#define SQLITE_OK 0 /* Successful result */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ -#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ -#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite_step() has finished executing */ - -/* -** Each entry in an SQLite table has a unique integer key. (The key is -** the value of the INTEGER PRIMARY KEY column if there is such a column, -** otherwise the key is generated at random. The unique key is always -** available as the ROWID, OID, or _ROWID_ column.) The following routine -** returns the integer key of the most recent insert in the database. -** -** This function is similar to the mysql_insert_id() function from MySQL. -*/ -int sqlite_last_insert_rowid(sqlite*); - -/* -** This function returns the number of database rows that were changed -** (or inserted or deleted) by the most recent called sqlite_exec(). -** -** All changes are counted, even if they were later undone by a -** ROLLBACK or ABORT. Except, changes associated with creating and -** dropping tables are not counted. -** -** If a callback invokes sqlite_exec() recursively, then the changes -** in the inner, recursive call are counted together with the changes -** in the outer call. -** -** SQLite implements the command "DELETE FROM table" without a WHERE clause -** by dropping and recreating the table. (This is much faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -*/ -int sqlite_changes(sqlite*); - -/* -** This function returns the number of database rows that were changed -** by the last INSERT, UPDATE, or DELETE statment executed by sqlite_exec(), -** or by the last VM to run to completion. The change count is not updated -** by SQL statements other than INSERT, UPDATE or DELETE. -** -** Changes are counted, even if they are later undone by a ROLLBACK or -** ABORT. Changes associated with trigger programs that execute as a -** result of the INSERT, UPDATE, or DELETE statement are not counted. -** -** If a callback invokes sqlite_exec() recursively, then the changes -** in the inner, recursive call are counted together with the changes -** in the outer call. -** -** SQLite implements the command "DELETE FROM table" without a WHERE clause -** by dropping and recreating the table. (This is much faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** -*/ -int sqlite_last_statement_changes(sqlite*); - -/* If the parameter to this routine is one of the return value constants -** defined above, then this routine returns a constant text string which -** descripts (in English) the meaning of the return value. -*/ -const char *sqlite_error_string(int); -#define sqliteErrStr sqlite_error_string /* Legacy. Do not use in new code. */ - -/* This function causes any pending database operation to abort and -** return at its earliest opportunity. This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -*/ -void sqlite_interrupt(sqlite*); - - -/* This function returns true if the given input string comprises -** one or more complete SQL statements. -** -** The algorithm is simple. If the last token other than spaces -** and comments is a semicolon, then return true. otherwise return -** false. -*/ -int sqlite_complete(const char *sql); - -/* -** This routine identifies a callback function that is invoked -** whenever an attempt is made to open a database table that is -** currently locked by another process or thread. If the busy callback -** is NULL, then sqlite_exec() returns SQLITE_BUSY immediately if -** it finds a locked table. If the busy callback is not NULL, then -** sqlite_exec() invokes the callback with three arguments. The -** second argument is the name of the locked table and the third -** argument is the number of times the table has been busy. If the -** busy callback returns 0, then sqlite_exec() immediately returns -** SQLITE_BUSY. If the callback returns non-zero, then sqlite_exec() -** tries to open the table again and the cycle repeats. -** -** The default busy callback is NULL. -** -** Sqlite is re-entrant, so the busy handler may start a new query. -** (It is not clear why anyone would every want to do this, but it -** is allowed, in theory.) But the busy handler may not close the -** database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a coredump. -*/ -void sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*); - -/* -** This routine sets a busy handler that sleeps for a while when a -** table is locked. The handler will sleep multiple times until -** at least "ms" milleseconds of sleeping have been done. After -** "ms" milleseconds of sleeping, the handler returns 0 which -** causes sqlite_exec() to return SQLITE_BUSY. -** -** Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -*/ -void sqlite_busy_timeout(sqlite*, int ms); - -/* -** This next routine is really just a wrapper around sqlite_exec(). -** Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from malloc(), then returns all of the result after the -** query has finished. -** -** As an example, suppose the query result where this table: -** -** Name | Age -** ----------------------- -** Alice | 43 -** Bob | 28 -** Cindy | 21 -** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -** azResult[0] = "Name"; -** azResult[1] = "Age"; -** azResult[2] = "Alice"; -** azResult[3] = "43"; -** azResult[4] = "Bob"; -** azResult[5] = "28"; -** azResult[6] = "Cindy"; -** azResult[7] = "21"; -** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** After the calling function has finished using the result, it should -** pass the result data pointer to sqlite_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** malloc() happens, the calling function must not try to call -** malloc() directly. Only sqlite_free_table() is able to release -** the memory properly and safely. -** -** The return value of this routine is the same as from sqlite_exec(). -*/ -int sqlite_get_table( - sqlite*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); - -/* -** Call this routine to free the memory that sqlite_get_table() allocated. -*/ -void sqlite_free_table(char **result); - -/* -** The following routines are wrappers around sqlite_exec() and -** sqlite_get_table(). The only difference between the routines that -** follow and the originals is that the second argument to the -** routines that follow is really a printf()-style format -** string describing the SQL to be executed. Arguments to the format -** string appear at the end of the argument list. -** -** All of the usual printf formatting options apply. In addition, there -** is a "%q" option. %q works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -** char *zText = "It's a happy day!"; -** -** We can use this text in an SQL statement as follows: -** -** sqlite_exec_printf(db, "INSERT INTO table VALUES('%q')", -** callback1, 0, 0, zText); -** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -** INSERT INTO table1 VALUES('It''s a happy day!') -** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -** INSERT INTO table1 VALUES('It's a happy day!'); -** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -*/ -int sqlite_exec_printf( - sqlite*, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - sqlite_callback, /* Callback function */ - void *, /* 1st argument to callback function */ - char **errmsg, /* Error msg written here */ - ... /* Arguments to the format string. */ -); -int sqlite_exec_vprintf( - sqlite*, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - sqlite_callback, /* Callback function */ - void *, /* 1st argument to callback function */ - char **errmsg, /* Error msg written here */ - va_list ap /* Arguments to the format string. */ -); -int sqlite_get_table_printf( - sqlite*, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg, /* Error msg written here */ - ... /* Arguments to the format string */ -); -int sqlite_get_table_vprintf( - sqlite*, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg, /* Error msg written here */ - va_list ap /* Arguments to the format string */ -); -char *sqlite_mprintf(const char*,...); -char *sqlite_vmprintf(const char*, va_list); - -/* -** Windows systems should call this routine to free memory that -** is returned in the in the errmsg parameter of sqlite_open() when -** SQLite is a DLL. For some reason, it does not work to call free() -** directly. -*/ -void sqlite_freemem(void *p); - -/* -** Windows systems need functions to call to return the sqlite_version -** and sqlite_encoding strings. -*/ -const char *sqlite_libversion(void); -const char *sqlite_libencoding(void); - -/* -** A pointer to the following structure is used to communicate with -** the implementations of user-defined functions. -*/ -typedef struct sqlite_func sqlite_func; - -/* -** Use the following routines to create new user-defined functions. See -** the documentation for details. -*/ -int sqlite_create_function( - sqlite*, /* Database where the new function is registered */ - const char *zName, /* Name of the new function */ - int nArg, /* Number of arguments. -1 means any number */ - void (*xFunc)(sqlite_func*,int,const char**), /* C code to implement */ - void *pUserData /* Available via the sqlite_user_data() call */ -); -int sqlite_create_aggregate( - sqlite*, /* Database where the new function is registered */ - const char *zName, /* Name of the function */ - int nArg, /* Number of arguments */ - void (*xStep)(sqlite_func*,int,const char**), /* Called for each row */ - void (*xFinalize)(sqlite_func*), /* Called once to get final result */ - void *pUserData /* Available via the sqlite_user_data() call */ -); - -/* -** Use the following routine to define the datatype returned by a -** user-defined function. The second argument can be one of the -** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it -** can be an integer greater than or equal to zero. When the datatype -** parameter is non-negative, the type of the result will be the -** same as the datatype-th argument. If datatype==SQLITE_NUMERIC -** then the result is always numeric. If datatype==SQLITE_TEXT then -** the result is always text. If datatype==SQLITE_ARGS then the result -** is numeric if any argument is numeric and is text otherwise. -*/ -int sqlite_function_type( - sqlite *db, /* The database there the function is registered */ - const char *zName, /* Name of the function */ - int datatype /* The datatype for this function */ -); -#define SQLITE_NUMERIC (-1) -#define SQLITE_TEXT (-2) -#define SQLITE_ARGS (-3) - -/* -** The user function implementations call one of the following four routines -** in order to return their results. The first parameter to each of these -** routines is a copy of the first argument to xFunc() or xFinialize(). -** The second parameter to these routines is the result to be returned. -** A NULL can be passed as the second parameter to sqlite_set_result_string() -** in order to return a NULL result. -** -** The 3rd argument to _string and _error is the number of characters to -** take from the string. If this argument is negative, then all characters -** up to and including the first '\000' are used. -** -** The sqlite_set_result_string() function allocates a buffer to hold the -** result and returns a pointer to this buffer. The calling routine -** (that is, the implmentation of a user function) can alter the content -** of this buffer if desired. -*/ -char *sqlite_set_result_string(sqlite_func*,const char*,int); -void sqlite_set_result_int(sqlite_func*,int); -void sqlite_set_result_double(sqlite_func*,double); -void sqlite_set_result_error(sqlite_func*,const char*,int); - -/* -** The pUserData parameter to the sqlite_create_function() and -** sqlite_create_aggregate() routines used to register user functions -** is available to the implementation of the function using this -** call. -*/ -void *sqlite_user_data(sqlite_func*); - -/* -** Aggregate functions use the following routine to allocate -** a structure for storing their state. The first time this routine -** is called for a particular aggregate, a new structure of size nBytes -** is allocated, zeroed, and returned. On subsequent calls (for the -** same aggregate instance) the same buffer is returned. The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** The buffer allocated is freed automatically be SQLite. -*/ -void *sqlite_aggregate_context(sqlite_func*, int nBytes); - -/* -** The next routine returns the number of calls to xStep for a particular -** aggregate function instance. The current call to xStep counts so this -** routine always returns at least 1. -*/ -int sqlite_aggregate_count(sqlite_func*); - -/* -** This routine registers a callback with the SQLite library. The -** callback is invoked (at compile-time, not at run-time) for each -** attempt to access a column of a table in the database. The callback -** returns SQLITE_OK if access is allowed, SQLITE_DENY if the entire -** SQL statement should be aborted with an error and SQLITE_IGNORE -** if the column should be treated as a NULL value. -*/ -int sqlite_set_authorizer( - sqlite*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** The second parameter to the access authorization function above will -** be one of the values below. These values signify what kind of operation -** is to be authorized. The 3rd and 4th parameters to the authorization -** function will be parameters or NULL depending on which of the following -** codes is used as the second parameter. The 5th parameter is the name -** of the database ("main", "temp", etc.) if applicable. The 6th parameter -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** input SQL code. -** -** Arg-3 Arg-4 -*/ -#define SQLITE_COPY 0 /* Table Name File Name */ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ - - -/* -** The return value of the authorization function should be one of the -** following constants: -*/ -/* #define SQLITE_OK 0 // Allow access (This is actually defined above) */ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** Register a function that is called at every invocation of sqlite_exec() -** or sqlite_compile(). This function can be used (for example) to generate -** a log file of all SQL executed against a database. -*/ -void *sqlite_trace(sqlite*, void(*xTrace)(void*,const char*), void*); - -/*** The Callback-Free API -** -** The following routines implement a new way to access SQLite that does not -** involve the use of callbacks. -** -** An sqlite_vm is an opaque object that represents a single SQL statement -** that is ready to be executed. -*/ -typedef struct sqlite_vm sqlite_vm; - -/* -** To execute an SQLite query without the use of callbacks, you first have -** to compile the SQL using this routine. The 1st parameter "db" is a pointer -** to an sqlite object obtained from sqlite_open(). The 2nd parameter -** "zSql" is the text of the SQL to be compiled. The remaining parameters -** are all outputs. -** -** *pzTail is made to point to the first character past the end of the first -** SQL statement in zSql. This routine only compiles the first statement -** in zSql, so *pzTail is left pointing to what remains uncompiled. -** -** *ppVm is left pointing to a "virtual machine" that can be used to execute -** the compiled statement. Or if there is an error, *ppVm may be set to NULL. -** If the input text contained no SQL (if the input is and empty string or -** a comment) then *ppVm is set to NULL. -** -** If any errors are detected during compilation, an error message is written -** into space obtained from malloc() and *pzErrMsg is made to point to that -** error message. The calling routine is responsible for freeing the text -** of this message when it has finished with it. Use sqlite_freemem() to -** free the message. pzErrMsg may be NULL in which case no error message -** will be generated. -** -** On success, SQLITE_OK is returned. Otherwise and error code is returned. -*/ -int sqlite_compile( - sqlite *db, /* The open database */ - const char *zSql, /* SQL statement to be compiled */ - const char **pzTail, /* OUT: uncompiled tail of zSql */ - sqlite_vm **ppVm, /* OUT: the virtual machine to execute zSql */ - char **pzErrmsg /* OUT: Error message. */ -); - -/* -** After an SQL statement has been compiled, it is handed to this routine -** to be executed. This routine executes the statement as far as it can -** go then returns. The return value will be one of SQLITE_DONE, -** SQLITE_ERROR, SQLITE_BUSY, SQLITE_ROW, or SQLITE_MISUSE. -** -** SQLITE_DONE means that the execute of the SQL statement is complete -** an no errors have occurred. sqlite_step() should not be called again -** for the same virtual machine. *pN is set to the number of columns in -** the result set and *pazColName is set to an array of strings that -** describe the column names and datatypes. The name of the i-th column -** is (*pazColName)[i] and the datatype of the i-th column is -** (*pazColName)[i+*pN]. *pazValue is set to NULL. -** -** SQLITE_ERROR means that the virtual machine encountered a run-time -** error. sqlite_step() should not be called again for the same -** virtual machine. *pN is set to 0 and *pazColName and *pazValue are set -** to NULL. Use sqlite_finalize() to obtain the specific error code -** and the error message text for the error. -** -** SQLITE_BUSY means that an attempt to open the database failed because -** another thread or process is holding a lock. The calling routine -** can try again to open the database by calling sqlite_step() again. -** The return code will only be SQLITE_BUSY if no busy handler is registered -** using the sqlite_busy_handler() or sqlite_busy_timeout() routines. If -** a busy handler callback has been registered but returns 0, then this -** routine will return SQLITE_ERROR and sqltie_finalize() will return -** SQLITE_BUSY when it is called. -** -** SQLITE_ROW means that a single row of the result is now available. -** The data is contained in *pazValue. The value of the i-th column is -** (*azValue)[i]. *pN and *pazColName are set as described in SQLITE_DONE. -** Invoke sqlite_step() again to advance to the next row. -** -** SQLITE_MISUSE is returned if sqlite_step() is called incorrectly. -** For example, if you call sqlite_step() after the virtual machine -** has halted (after a prior call to sqlite_step() has returned SQLITE_DONE) -** or if you call sqlite_step() with an incorrectly initialized virtual -** machine or a virtual machine that has been deleted or that is associated -** with an sqlite structure that has been closed. -*/ -int sqlite_step( - sqlite_vm *pVm, /* The virtual machine to execute */ - int *pN, /* OUT: Number of columns in result */ - const char ***pazValue, /* OUT: Column data */ - const char ***pazColName /* OUT: Column names and datatypes */ -); - -/* -** This routine is called to delete a virtual machine after it has finished -** executing. The return value is the result code. SQLITE_OK is returned -** if the statement executed successfully and some other value is returned if -** there was any kind of error. If an error occurred and pzErrMsg is not -** NULL, then an error message is written into memory obtained from malloc() -** and *pzErrMsg is made to point to that error message. The calling routine -** should use sqlite_freemem() to delete this message when it has finished -** with it. -** -** This routine can be called at any point during the execution of the -** virtual machine. If the virtual machine has not completed execution -** when this routine is called, that is like encountering an error or -** an interrupt. (See sqlite_interrupt().) Incomplete updates may be -** rolled back and transactions cancelled, depending on the circumstances, -** and the result code returned will be SQLITE_ABORT. -*/ -int sqlite_finalize(sqlite_vm*, char **pzErrMsg); - -/* -** This routine deletes the virtual machine, writes any error message to -** *pzErrMsg and returns an SQLite return code in the same way as the -** sqlite_finalize() function. -** -** Additionally, if ppVm is not NULL, *ppVm is left pointing to a new virtual -** machine loaded with the compiled version of the original query ready for -** execution. -** -** If sqlite_reset() returns SQLITE_SCHEMA, then *ppVm is set to NULL. -** -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** -*/ -int sqlite_reset(sqlite_vm*, char **pzErrMsg); - -/* -** If the SQL that was handed to sqlite_compile contains variables that -** are represeted in the SQL text by a question mark ('?'). This routine -** is used to assign values to those variables. -** -** The first parameter is a virtual machine obtained from sqlite_compile(). -** The 2nd "idx" parameter determines which variable in the SQL statement -** to bind the value to. The left most '?' is 1. The 3rd parameter is -** the value to assign to that variable. The 4th parameter is the number -** of bytes in the value, including the terminating \000 for strings. -** Finally, the 5th "copy" parameter is TRUE if SQLite should make its -** own private copy of this value, or false if the space that the 3rd -** parameter points to will be unchanging and can be used directly by -** SQLite. -** -** Unbound variables are treated as having a value of NULL. To explicitly -** set a variable to NULL, call this routine with the 3rd parameter as a -** NULL pointer. -** -** If the 4th "len" parameter is -1, then strlen() is used to find the -** length. -** -** This routine can only be called immediately after sqlite_compile() -** or sqlite_reset() and before any calls to sqlite_step(). -** -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** -*/ -int sqlite_bind(sqlite_vm*, int idx, const char *value, int len, int copy); - -/* -** This routine configures a callback function - the progress callback - that -** is invoked periodically during long running calls to sqlite_exec(), -** sqlite_step() and sqlite_get_table(). An example use for this API is to keep -** a GUI updated during a large query. -** -** The progress callback is invoked once for every N virtual machine opcodes, -** where N is the second argument to this function. The progress callback -** itself is identified by the third argument to this function. The fourth -** argument to this function is a void pointer passed to the progress callback -** function each time it is invoked. -** -** If a call to sqlite_exec(), sqlite_step() or sqlite_get_table() results -** in less than N opcodes being executed, then the progress callback is not -** invoked. -** -** Calling this routine overwrites any previously installed progress callback. -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. -** -** If the progress callback returns a result other than 0, then the current -** query is immediately terminated and any database changes rolled back. If the -** query was part of a larger transaction, then the transaction is not rolled -** back and remains active. The sqlite_exec() call returns SQLITE_ABORT. -** -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** -*/ -void sqlite_progress_handler(sqlite*, int, int(*)(void*), void*); - -/* -** Register a callback function to be invoked whenever a new transaction -** is committed. The pArg argument is passed through to the callback. -** callback. If the callback function returns non-zero, then the commit -** is converted into a rollback. -** -** If another function was previously registered, its pArg value is returned. -** Otherwise NULL is returned. -** -** Registering a NULL function disables the callback. -** -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** -*/ -void *sqlite_commit_hook(sqlite*, int(*)(void*), void*); - -/* -** Open an encrypted SQLite database. If pKey==0 or nKey==0, this routine -** is the same as sqlite_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -sqlite *sqlite_open_encrypted( - const char *zFilename, /* Name of the encrypted database */ - const void *pKey, /* Pointer to the key */ - int nKey, /* Number of bytes in the key */ - int *pErrcode, /* Write error code here */ - char **pzErrmsg /* Write error message here */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite_rekey( - sqlite *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** Encode a binary buffer "in" of size n bytes so that it contains -** no instances of characters '\'' or '\000'. The output is -** null-terminated and can be used as a string value in an INSERT -** or UPDATE statement. Use sqlite_decode_binary() to convert the -** string back into its original binary. -** -** The result is written into a preallocated output buffer "out". -** "out" must be able to hold at least 2 +(257*n)/254 bytes. -** In other words, the output will be expanded by as much as 3 -** bytes for every 254 bytes of input plus 2 bytes of fixed overhead. -** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.) -** -** The return value is the number of characters in the encoded -** string, excluding the "\000" terminator. -** -** If out==NULL then no output is generated but the routine still returns -** the number of characters that would have been generated if out had -** not been NULL. -*/ -int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out); - -/* -** Decode the string "in" into binary data and write it into "out". -** This routine reverses the encoding created by sqlite_encode_binary(). -** The output will always be a few bytes less than the input. The number -** of bytes of output is returned. If the input is not a well-formed -** encoding, -1 is returned. -** -** The "in" and "out" parameters may point to the same buffer in order -** to decode a string in place. -*/ -int sqlite_decode_binary(const unsigned char *in, unsigned char *out); - -#ifdef __cplusplus -} /* End of the 'extern "C"' block */ -#endif - -#endif /* _SQLITE_H_ */ diff --git a/dbLifeLog/DBD-SQLite2-0.33/sqliteInt.h b/dbLifeLog/DBD-SQLite2-0.33/sqliteInt.h deleted file mode 100644 index b38aa86..0000000 --- a/dbLifeLog/DBD-SQLite2-0.33/sqliteInt.h +++ /dev/null @@ -1,1270 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Internal interface definitions for SQLite. -** -** @(#) $Id: sqliteInt.h,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ -*/ -#include "config.h" -#include "sqlite.h" -#include "hash.h" -#include "parse.h" -#include "btree.h" -#include -#include -#include -#include - -/* -** The maximum number of in-memory pages to use for the main database -** table and for temporary tables. -*/ -#define MAX_PAGES 2000 -#define TEMP_PAGES 500 - -/* -** If the following macro is set to 1, then NULL values are considered -** distinct for the SELECT DISTINCT statement and for UNION or EXCEPT -** compound queries. No other SQL database engine (among those tested) -** works this way except for OCELOT. But the SQL92 spec implies that -** this is how things should work. -** -** If the following macro is set to 0, then NULLs are indistinct for -** SELECT DISTINCT and for UNION. -*/ -#define NULL_ALWAYS_DISTINCT 0 - -/* -** If the following macro is set to 1, then NULL values are considered -** distinct when determining whether or not two entries are the same -** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, -** OCELOT, and Firebird all work. The SQL92 spec explicitly says this -** is the way things are suppose to work. -** -** If the following macro is set to 0, the NULLs are indistinct for -** a UNIQUE index. In this mode, you can only have a single NULL entry -** for a column declared UNIQUE. This is the way Informix and SQL Server -** work. -*/ -#define NULL_DISTINCT_FOR_UNIQUE 1 - -/* -** The maximum number of attached databases. This must be at least 2 -** in order to support the main database file (0) and the file used to -** hold temporary tables (1). And it must be less than 256 because -** an unsigned character is used to stored the database index. -*/ -#define MAX_ATTACHED 10 - -/* -** The next macro is used to determine where TEMP tables and indices -** are stored. Possible values: -** -** 0 Always use a temporary files -** 1 Use a file unless overridden by "PRAGMA temp_store" -** 2 Use memory unless overridden by "PRAGMA temp_store" -** 3 Always use memory -*/ -#ifndef TEMP_STORE -# define TEMP_STORE 1 -#endif - -/* -** When building SQLite for embedded systems where memory is scarce, -** you can define one or more of the following macros to omit extra -** features of the library and thus keep the size of the library to -** a minimum. -*/ -/* #define SQLITE_OMIT_AUTHORIZATION 1 */ -/* #define SQLITE_OMIT_INMEMORYDB 1 */ -/* #define SQLITE_OMIT_VACUUM 1 */ -/* #define SQLITE_OMIT_DATETIME_FUNCS 1 */ -/* #define SQLITE_OMIT_PROGRESS_CALLBACK 1 */ - -/* -** Integers of known sizes. These typedefs might change for architectures -** where the sizes very. Preprocessor macros are available so that the -** types can be conveniently redefined at compile-type. Like this: -** -** cc '-DUINTPTR_TYPE=long long int' ... -*/ -#ifndef UINT32_TYPE -# define UINT32_TYPE unsigned int -#endif -#ifndef UINT16_TYPE -# define UINT16_TYPE unsigned short int -#endif -#ifndef INT16_TYPE -# define INT16_TYPE short int -#endif -#ifndef UINT8_TYPE -# define UINT8_TYPE unsigned char -#endif -#ifndef INT8_TYPE -# define INT8_TYPE signed char -#endif -#ifndef INTPTR_TYPE -# if SQLITE_PTR_SZ==4 -# define INTPTR_TYPE int -# else -# define INTPTR_TYPE long long -# endif -#endif -typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ -typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ -typedef INT16_TYPE i16; /* 2-byte signed integer */ -typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ -typedef UINT8_TYPE i8; /* 1-byte signed integer */ -typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */ -typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */ - -/* -** Defer sourcing vdbe.h until after the "u8" typedef is defined. -*/ -#include "vdbe.h" - -/* -** Most C compilers these days recognize "long double", don't they? -** Just in case we encounter one that does not, we will create a macro -** for long double so that it can be easily changed to just "double". -*/ -#ifndef LONGDOUBLE_TYPE -# define LONGDOUBLE_TYPE long double -#endif - -/* -** This macro casts a pointer to an integer. Useful for doing -** pointer arithmetic. -*/ -#define Addr(X) ((uptr)X) - -/* -** The maximum number of bytes of data that can be put into a single -** row of a single table. The upper bound on this limit is 16777215 -** bytes (or 16MB-1). We have arbitrarily set the limit to just 1MB -** here because the overflow page chain is inefficient for really big -** records and we want to discourage people from thinking that -** multi-megabyte records are OK. If your needs are different, you can -** change this define and recompile to increase or decrease the record -** size. -** -** The 16777198 is computed as follows: 238 bytes of payload on the -** original pages plus 16448 overflow pages each holding 1020 bytes of -** data. -*/ -#define MAX_BYTES_PER_ROW 1048576 -/* #define MAX_BYTES_PER_ROW 16777198 */ - -/* -** If memory allocation problems are found, recompile with -** -** -DMEMORY_DEBUG=1 -** -** to enable some sanity checking on malloc() and free(). To -** check for memory leaks, recompile with -** -** -DMEMORY_DEBUG=2 -** -** and a line of text will be written to standard error for -** each malloc() and free(). This output can be analyzed -** by an AWK script to determine if there are any leaks. -*/ -#ifdef MEMORY_DEBUG -# define sqliteMalloc(X) sqliteMalloc_(X,1,__FILE__,__LINE__) -# define sqliteMallocRaw(X) sqliteMalloc_(X,0,__FILE__,__LINE__) -# define sqliteFree(X) sqliteFree_(X,__FILE__,__LINE__) -# define sqliteRealloc(X,Y) sqliteRealloc_(X,Y,__FILE__,__LINE__) -# define sqliteStrDup(X) sqliteStrDup_(X,__FILE__,__LINE__) -# define sqliteStrNDup(X,Y) sqliteStrNDup_(X,Y,__FILE__,__LINE__) - void sqliteStrRealloc(char**); -#else -# define sqliteRealloc_(X,Y) sqliteRealloc(X,Y) -# define sqliteStrRealloc(X) -#endif - -/* -** This variable gets set if malloc() ever fails. After it gets set, -** the SQLite library shuts down permanently. -*/ -extern int sqlite_malloc_failed; - -/* -** The following global variables are used for testing and debugging -** only. They only work if MEMORY_DEBUG is defined. -*/ -#ifdef MEMORY_DEBUG -extern int sqlite_nMalloc; /* Number of sqliteMalloc() calls */ -extern int sqlite_nFree; /* Number of sqliteFree() calls */ -extern int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */ -#endif - -/* -** Name of the master database table. The master database table -** is a special table that holds the names and attributes of all -** user tables and indices. -*/ -#define MASTER_NAME "sqlite_master" -#define TEMP_MASTER_NAME "sqlite_temp_master" - -/* -** The name of the schema table. -*/ -#define SCHEMA_TABLE(x) (x?TEMP_MASTER_NAME:MASTER_NAME) - -/* -** A convenience macro that returns the number of elements in -** an array. -*/ -#define ArraySize(X) (sizeof(X)/sizeof(X[0])) - -/* -** Forward references to structures -*/ -typedef struct Column Column; -typedef struct Table Table; -typedef struct Index Index; -typedef struct Instruction Instruction; -typedef struct Expr Expr; -typedef struct ExprList ExprList; -typedef struct Parse Parse; -typedef struct Token Token; -typedef struct IdList IdList; -typedef struct SrcList SrcList; -typedef struct WhereInfo WhereInfo; -typedef struct WhereLevel WhereLevel; -typedef struct Select Select; -typedef struct AggExpr AggExpr; -typedef struct FuncDef FuncDef; -typedef struct Trigger Trigger; -typedef struct TriggerStep TriggerStep; -typedef struct TriggerStack TriggerStack; -typedef struct FKey FKey; -typedef struct Db Db; -typedef struct AuthContext AuthContext; - -/* -** Each database file to be accessed by the system is an instance -** of the following structure. There are normally two of these structures -** in the sqlite.aDb[] array. aDb[0] is the main database file and -** aDb[1] is the database file used to hold temporary tables. Additional -** databases may be attached. -*/ -struct Db { - char *zName; /* Name of this database */ - Btree *pBt; /* The B*Tree structure for this database file */ - int schema_cookie; /* Database schema version number for this file */ - Hash tblHash; /* All tables indexed by name */ - Hash idxHash; /* All (named) indices indexed by name */ - Hash trigHash; /* All triggers indexed by name */ - Hash aFKey; /* Foreign keys indexed by to-table */ - u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ - u16 flags; /* Flags associated with this database */ - void *pAux; /* Auxiliary data. Usually NULL */ - void (*xFreeAux)(void*); /* Routine to free pAux */ -}; - -/* -** These macros can be used to test, set, or clear bits in the -** Db.flags field. -*/ -#define DbHasProperty(D,I,P) (((D)->aDb[I].flags&(P))==(P)) -#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].flags&(P))!=0) -#define DbSetProperty(D,I,P) (D)->aDb[I].flags|=(P) -#define DbClearProperty(D,I,P) (D)->aDb[I].flags&=~(P) - -/* -** Allowed values for the DB.flags field. -** -** The DB_Locked flag is set when the first OP_Transaction or OP_Checkpoint -** opcode is emitted for a database. This prevents multiple occurances -** of those opcodes for the same database in the same program. Similarly, -** the DB_Cookie flag is set when the OP_VerifyCookie opcode is emitted, -** and prevents duplicate OP_VerifyCookies from taking up space and slowing -** down execution. -** -** The DB_SchemaLoaded flag is set after the database schema has been -** read into internal hash tables. -** -** DB_UnresetViews means that one or more views have column names that -** have been filled out. If the schema changes, these column names might -** changes and so the view will need to be reset. -*/ -#define DB_Locked 0x0001 /* OP_Transaction opcode has been emitted */ -#define DB_Cookie 0x0002 /* OP_VerifyCookie opcode has been emiited */ -#define DB_SchemaLoaded 0x0004 /* The schema has been loaded */ -#define DB_UnresetViews 0x0008 /* Some views have defined column names */ - - -/* -** Each database is an instance of the following structure. -** -** The sqlite.file_format is initialized by the database file -** and helps determines how the data in the database file is -** represented. This field allows newer versions of the library -** to read and write older databases. The various file formats -** are as follows: -** -** file_format==1 Version 2.1.0. -** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. -** file_format==3 Version 2.6.0. Fix empty-string index bug. -** file_format==4 Version 2.7.0. Add support for separate numeric and -** text datatypes. -** -** The sqlite.temp_store determines where temporary database files -** are stored. If 1, then a file is created to hold those tables. If -** 2, then they are held in memory. 0 means use the default value in -** the TEMP_STORE macro. -** -** The sqlite.lastRowid records the last insert rowid generated by an -** insert statement. Inserts on views do not affect its value. Each -** trigger has its own context, so that lastRowid can be updated inside -** triggers as usual. The previous value will be restored once the trigger -** exits. Upon entering a before or instead of trigger, lastRowid is no -** longer (since after version 2.8.12) reset to -1. -** -** The sqlite.nChange does not count changes within triggers and keeps no -** context. It is reset at start of sqlite_exec. -** The sqlite.lsChange represents the number of changes made by the last -** insert, update, or delete statement. It remains constant throughout the -** length of a statement and is then updated by OP_SetCounts. It keeps a -** context stack just like lastRowid so that the count of changes -** within a trigger is not seen outside the trigger. Changes to views do not -** affect the value of lsChange. -** The sqlite.csChange keeps track of the number of current changes (since -** the last statement) and is used to update sqlite_lsChange. -*/ -struct sqlite { - int nDb; /* Number of backends currently in use */ - Db *aDb; /* All backends */ - Db aDbStatic[2]; /* Static space for the 2 default backends */ - int flags; /* Miscellanous flags. See below */ - u8 file_format; /* What file format version is this database? */ - u8 safety_level; /* How aggressive at synching data to disk */ - u8 want_to_close; /* Close after all VDBEs are deallocated */ - u8 temp_store; /* 1=file, 2=memory, 0=compile-time default */ - u8 onError; /* Default conflict algorithm */ - int next_cookie; /* Next value of aDb[0].schema_cookie */ - int cache_size; /* Number of pages to use in the cache */ - int nTable; /* Number of tables in the database */ - void *pBusyArg; /* 1st Argument to the busy callback */ - int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ - void *pCommitArg; /* Argument to xCommitCallback() */ - int (*xCommitCallback)(void*);/* Invoked at every commit. */ - Hash aFunc; /* All functions that can be in SQL exprs */ - int lastRowid; /* ROWID of most recent insert (see above) */ - int priorNewRowid; /* Last randomly generated ROWID */ - int magic; /* Magic number for detect library misuse */ - int nChange; /* Number of rows changed (see above) */ - int lsChange; /* Last statement change count (see above) */ - int csChange; /* Current statement change count (see above) */ - struct sqliteInitInfo { /* Information used during initialization */ - int iDb; /* When back is being initialized */ - int newTnum; /* Rootpage of table being initialized */ - u8 busy; /* TRUE if currently initializing */ - } init; - struct Vdbe *pVdbe; /* List of active virtual machines */ - void (*xTrace)(void*,const char*); /* Trace function */ - void *pTraceArg; /* Argument to the trace function */ -#ifndef SQLITE_OMIT_AUTHORIZATION - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); - /* Access authorization function */ - void *pAuthArg; /* 1st argument to the access auth function */ -#endif -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - int (*xProgress)(void *); /* The progress callback */ - void *pProgressArg; /* Argument to the progress callback */ - int nProgressOps; /* Number of opcodes for progress callback */ -#endif -}; - -/* -** Possible values for the sqlite.flags and or Db.flags fields. -** -** On sqlite.flags, the SQLITE_InTrans value means that we have -** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement -** transaction is active on that particular database file. -*/ -#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ -#define SQLITE_Initialized 0x00000002 /* True after initialization */ -#define SQLITE_Interrupt 0x00000004 /* Cancel current operation */ -#define SQLITE_InTrans 0x00000008 /* True if in a transaction */ -#define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ -#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ -#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ -#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ - /* DELETE, or UPDATE and return */ - /* the count using a callback. */ -#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ - /* result set is empty */ -#define SQLITE_ReportTypes 0x00000200 /* Include information on datatypes */ - /* in 4th argument of callback */ - -/* -** Possible values for the sqlite.magic field. -** The numbers are obtained at random and have no special meaning, other -** than being distinct from one another. -*/ -#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ -#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ -#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ -#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ - -/* -** Each SQL function is defined by an instance of the following -** structure. A pointer to this structure is stored in the sqlite.aFunc -** hash table. When multiple functions have the same name, the hash table -** points to a linked list of these structures. -*/ -struct FuncDef { - void (*xFunc)(sqlite_func*,int,const char**); /* Regular function */ - void (*xStep)(sqlite_func*,int,const char**); /* Aggregate function step */ - void (*xFinalize)(sqlite_func*); /* Aggregate function finializer */ - signed char nArg; /* Number of arguments. -1 means unlimited */ - signed char dataType; /* Arg that determines datatype. -1=NUMERIC, */ - /* -2=TEXT. -3=SQLITE_ARGS */ - u8 includeTypes; /* Add datatypes to args of xFunc and xStep */ - void *pUserData; /* User data parameter */ - FuncDef *pNext; /* Next function with same name */ -}; - -/* -** information about each column of an SQL table is held in an instance -** of this structure. -*/ -struct Column { - char *zName; /* Name of this column */ - char *zDflt; /* Default value of this column */ - char *zType; /* Data type for this column */ - u8 notNull; /* True if there is a NOT NULL constraint */ - u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ - u8 sortOrder; /* Some combination of SQLITE_SO_... values */ - u8 dottedName; /* True if zName contains a "." character */ -}; - -/* -** The allowed sort orders. -** -** The TEXT and NUM values use bits that do not overlap with DESC and ASC. -** That way the two can be combined into a single number. -*/ -#define SQLITE_SO_UNK 0 /* Use the default collating type. (SCT_NUM) */ -#define SQLITE_SO_TEXT 2 /* Sort using memcmp() */ -#define SQLITE_SO_NUM 4 /* Sort using sqliteCompare() */ -#define SQLITE_SO_TYPEMASK 6 /* Mask to extract the collating sequence */ -#define SQLITE_SO_ASC 0 /* Sort in ascending order */ -#define SQLITE_SO_DESC 1 /* Sort in descending order */ -#define SQLITE_SO_DIRMASK 1 /* Mask to extract the sort direction */ - -/* -** Each SQL table is represented in memory by an instance of the -** following structure. -** -** Table.zName is the name of the table. The case of the original -** CREATE TABLE statement is stored, but case is not significant for -** comparisons. -** -** Table.nCol is the number of columns in this table. Table.aCol is a -** pointer to an array of Column structures, one for each column. -** -** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of -** the column that is that key. Otherwise Table.iPKey is negative. Note -** that the datatype of the PRIMARY KEY must be INTEGER for this field to -** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of -** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid -** is generated for each row of the table. Table.hasPrimKey is true if -** the table has any PRIMARY KEY, INTEGER or otherwise. -** -** Table.tnum is the page number for the root BTree page of the table in the -** database file. If Table.iDb is the index of the database table backend -** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that -** holds temporary tables and indices. If Table.isTransient -** is true, then the table is stored in a file that is automatically deleted -** when the VDBE cursor to the table is closed. In this case Table.tnum -** refers VDBE cursor number that holds the table open, not to the root -** page number. Transient tables are used to hold the results of a -** sub-query that appears instead of a real table name in the FROM clause -** of a SELECT statement. -*/ -struct Table { - char *zName; /* Name of the table */ - int nCol; /* Number of columns in this table */ - Column *aCol; /* Information about each column */ - int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ - Index *pIndex; /* List of SQL indexes on this table. */ - int tnum; /* Root BTree node for this table (see note above) */ - Select *pSelect; /* NULL for tables. Points to definition if a view. */ - u8 readOnly; /* True if this table should not be written by the user */ - u8 iDb; /* Index into sqlite.aDb[] of the backend for this table */ - u8 isTransient; /* True if automatically deleted when VDBE finishes */ - u8 hasPrimKey; /* True if there exists a primary key */ - u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ - Trigger *pTrigger; /* List of SQL triggers on this table */ - FKey *pFKey; /* Linked list of all foreign keys in this table */ -}; - -/* -** Each foreign key constraint is an instance of the following structure. -** -** A foreign key is associated with two tables. The "from" table is -** the table that contains the REFERENCES clause that creates the foreign -** key. The "to" table is the table that is named in the REFERENCES clause. -** Consider this example: -** -** CREATE TABLE ex1( -** a INTEGER PRIMARY KEY, -** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) -** ); -** -** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". -** -** Each REFERENCES clause generates an instance of the following structure -** which is attached to the from-table. The to-table need not exist when -** the from-table is created. The existance of the to-table is not checked -** until an attempt is made to insert data into the from-table. -** -** The sqlite.aFKey hash table stores pointers to this structure -** given the name of a to-table. For each to-table, all foreign keys -** associated with that table are on a linked list using the FKey.pNextTo -** field. -*/ -struct FKey { - Table *pFrom; /* The table that constains the REFERENCES clause */ - FKey *pNextFrom; /* Next foreign key in pFrom */ - char *zTo; /* Name of table that the key points to */ - FKey *pNextTo; /* Next foreign key that points to zTo */ - int nCol; /* Number of columns in this key */ - struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ - int iFrom; /* Index of column in pFrom */ - char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ - } *aCol; /* One entry for each of nCol column s */ - u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ - u8 updateConf; /* How to resolve conflicts that occur on UPDATE */ - u8 deleteConf; /* How to resolve conflicts that occur on DELETE */ - u8 insertConf; /* How to resolve conflicts that occur on INSERT */ -}; - -/* -** SQLite supports many different ways to resolve a contraint -** error. ROLLBACK processing means that a constraint violation -** causes the operation in process to fail and for the current transaction -** to be rolled back. ABORT processing means the operation in process -** fails and any prior changes from that one operation are backed out, -** but the transaction is not rolled back. FAIL processing means that -** the operation in progress stops and returns an error code. But prior -** changes due to the same operation are not backed out and no rollback -** occurs. IGNORE means that the particular row that caused the constraint -** error is not inserted or updated. Processing continues and no error -** is returned. REPLACE means that preexisting database rows that caused -** a UNIQUE constraint violation are removed so that the new insert or -** update can proceed. Processing continues and no error is reported. -** -** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. -** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the -** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign -** key is set to NULL. CASCADE means that a DELETE or UPDATE of the -** referenced table row is propagated into the row that holds the -** foreign key. -** -** The following symbolic values are used to record which type -** of action to take. -*/ -#define OE_None 0 /* There is no constraint to check */ -#define OE_Rollback 1 /* Fail the operation and rollback the transaction */ -#define OE_Abort 2 /* Back out changes but do no rollback transaction */ -#define OE_Fail 3 /* Stop the operation but leave all prior changes */ -#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ -#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ - -#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ -#define OE_SetNull 7 /* Set the foreign key value to NULL */ -#define OE_SetDflt 8 /* Set the foreign key value to its default */ -#define OE_Cascade 9 /* Cascade the changes */ - -#define OE_Default 99 /* Do whatever the default action is */ - -/* -** Each SQL index is represented in memory by an -** instance of the following structure. -** -** The columns of the table that are to be indexed are described -** by the aiColumn[] field of this structure. For example, suppose -** we have the following table and index: -** -** CREATE TABLE Ex1(c1 int, c2 int, c3 text); -** CREATE INDEX Ex2 ON Ex1(c3,c1); -** -** In the Table structure describing Ex1, nCol==3 because there are -** three columns in the table. In the Index structure describing -** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. -** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the -** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. -** The second column to be indexed (c1) has an index of 0 in -** Ex1.aCol[], hence Ex2.aiColumn[1]==0. -** -** The Index.onError field determines whether or not the indexed columns -** must be unique and what to do if they are not. When Index.onError=OE_None, -** it means this is not a unique index. Otherwise it is a unique index -** and the value of Index.onError indicate the which conflict resolution -** algorithm to employ whenever an attempt is made to insert a non-unique -** element. -*/ -struct Index { - char *zName; /* Name of this index */ - int nColumn; /* Number of columns in the table used by this index */ - int *aiColumn; /* Which columns are used by this index. 1st is 0 */ - Table *pTable; /* The SQL table being indexed */ - int tnum; /* Page containing root of this index in database file */ - u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ - u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ - u8 iDb; /* Index in sqlite.aDb[] of where this index is stored */ - Index *pNext; /* The next index associated with the same table */ -}; - -/* -** Each token coming out of the lexer is an instance of -** this structure. Tokens are also used as part of an expression. -** -** Note if Token.z==0 then Token.dyn and Token.n are undefined and -** may contain random values. Do not make any assuptions about Token.dyn -** and Token.n when Token.z==0. -*/ -struct Token { - const char *z; /* Text of the token. Not NULL-terminated! */ - unsigned dyn : 1; /* True for malloced memory, false for static */ - unsigned n : 31; /* Number of characters in this token */ -}; - -/* -** Each node of an expression in the parse tree is an instance -** of this structure. -** -** Expr.op is the opcode. The integer parser token codes are reused -** as opcodes here. For example, the parser defines TK_GE to be an integer -** code representing the ">=" operator. This same integer code is reused -** to represent the greater-than-or-equal-to operator in the expression -** tree. -** -** Expr.pRight and Expr.pLeft are subexpressions. Expr.pList is a list -** of argument if the expression is a function. -** -** Expr.token is the operator token for this node. For some expressions -** that have subexpressions, Expr.token can be the complete text that gave -** rise to the Expr. In the latter case, the token is marked as being -** a compound token. -** -** An expression of the form ID or ID.ID refers to a column in a table. -** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is -** the integer cursor number of a VDBE cursor pointing to that table and -** Expr.iColumn is the column number for the specific column. If the -** expression is used as a result in an aggregate SELECT, then the -** value is also stored in the Expr.iAgg column in the aggregate so that -** it can be accessed after all aggregates are computed. -** -** If the expression is a function, the Expr.iTable is an integer code -** representing which function. If the expression is an unbound variable -** marker (a question mark character '?' in the original SQL) then the -** Expr.iTable holds the index number for that variable. -** -** The Expr.pSelect field points to a SELECT statement. The SELECT might -** be the right operand of an IN operator. Or, if a scalar SELECT appears -** in an expression the opcode is TK_SELECT and Expr.pSelect is the only -** operand. -*/ -struct Expr { - u8 op; /* Operation performed by this node */ - u8 dataType; /* Either SQLITE_SO_TEXT or SQLITE_SO_NUM */ - u8 iDb; /* Database referenced by this expression */ - u8 flags; /* Various flags. See below */ - Expr *pLeft, *pRight; /* Left and right subnodes */ - ExprList *pList; /* A list of expressions used as function arguments - ** or in " IN (useAgg==TRUE, pull - ** result from the iAgg-th element of the aggregator */ - Select *pSelect; /* When the expression is a sub-select. Also the - ** right side of " IN ( statement is: - - prepare, - execute, fetch, fetch, ... - execute, fetch, fetch, ... - execute, fetch, fetch, ... - -for example: - - $sth = $dbh->prepare("SELECT foo, bar FROM table WHERE baz=?"); - - $sth->execute( $baz ); - - while ( @row = $sth->fetchrow_array ) { - print "@row\n"; - } - -The typical method call sequence for a I-C statement -(or with drivers that don't support placeholders): - - $rows_affected = $dbh->do("UPDATE your_table SET foo = foo + 1"); - -To commit your changes to the database (when L is off): - - $dbh->commit; # or call $dbh->rollback; to undo changes - -Finally, when you have finished working with the data source, you should -L from it: - - $dbh->disconnect; - - -=head2 General Interface Rules & Caveats - -The DBI does not have a concept of a "current session". Every session -has a handle object (i.e., a C<$dbh>) returned from the C method. -That handle object is used to invoke database related methods. - -Most data is returned to the Perl script as strings. (Null values are -returned as C.) This allows arbitrary precision numeric data to be -handled without loss of accuracy. Beware that Perl may not preserve -the same accuracy when the string is used as a number. - -Dates and times are returned as character strings in the current -default format of the corresponding database engine. Time zone effects -are database/driver dependent. - -Perl supports binary data in Perl strings, and the DBI will pass binary -data to and from the driver without change. It is up to the driver -implementors to decide how they wish to handle such binary data. - -Perl supports two kinds of strings: Unicode (utf8 internally) and non-Unicode -(defaults to iso-8859-1 if forced to assume an encoding). Drivers should -accept both kinds of strings and, if required, convert them to the character -set of the database being used. Similarly, when fetching from the database -character data that isn't iso-8859-1 the driver should convert it into utf8. - -Multiple SQL statements may not be combined in a single statement -handle (C<$sth>), although some databases and drivers do support this -(notably Sybase and SQL Server). - -Non-sequential record reads are not supported in this version of the DBI. -In other words, records can only be fetched in the order that the -database returned them, and once fetched they are forgotten. - -Positioned updates and deletes are not directly supported by the DBI. -See the description of the C attribute for an alternative. - -Individual driver implementors are free to provide any private -functions and/or handle attributes that they feel are useful. -Private driver functions can be invoked using the DBI C method. -Private driver attributes are accessed just like standard attributes. - -Many methods have an optional C<\%attr> parameter which can be used to -pass information to the driver implementing the method. Except where -specifically documented, the C<\%attr> parameter can only be used to pass -driver specific hints. In general, you can ignore C<\%attr> parameters -or pass it as C. - - -=head2 Naming Conventions and Name Space - -The DBI package and all packages below it (C) are reserved for -use by the DBI. Extensions and related modules use the C -namespace (see L). -Package names beginning with C are reserved for use -by DBI database drivers. All environment variables used by the DBI -or by individual DBDs begin with "C" or "C". - -The letter case used for attribute names is significant and plays an -important part in the portability of DBI scripts. The case of the -attribute name is used to signify who defined the meaning of that name -and its values. - - Case of name Has a meaning defined by - ------------ ------------------------ - UPPER_CASE Standards, e.g., X/Open, ISO SQL92 etc (portable) - MixedCase DBI API (portable), underscores are not used. - lower_case Driver or database engine specific (non-portable) - -It is of the utmost importance that Driver developers only use -lowercase attribute names when defining private attributes. Private -attribute names must be prefixed with the driver name or suitable -abbreviation (e.g., "C" for Oracle, "C" for Ingres, etc). - - -=head2 SQL - A Query Language - -Most DBI drivers require applications to use a dialect of SQL -(Structured Query Language) to interact with the database engine. -The L section provides links -to useful information about SQL. - -The DBI itself does not mandate or require any particular language to -be used; it is language independent. In ODBC terms, the DBI is in -"pass-thru" mode, although individual drivers might not be. The only requirement -is that queries and other statements must be expressed as a single -string of characters passed as the first argument to the L or -L methods. - -For an interesting diversion on the I history of RDBMS and SQL, -from the people who made it happen, see: - - http://www.mcjones.org/System_R/SQL_Reunion_95/sqlr95.html - -Follow the "Full Contents" then "Intergalactic dataspeak" links for the -SQL history. - -=head2 Placeholders and Bind Values - -Some drivers support placeholders and bind values. -I, also called parameter markers, are used to indicate -values in a database statement that will be supplied later, -before the prepared statement is executed. For example, an application -might use the following to insert a row of data into the SALES table: - - INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?) - -or the following, to select the description for a product: - - SELECT description FROM products WHERE product_code = ? - -The C characters are the placeholders. The association of actual -values with placeholders is known as I, and the values are -referred to as I. -Note that the C is not enclosed in quotation marks, even when the -placeholder represents a string. - -Some drivers also allow placeholders like C<:>I and C<:>I (e.g., -C<:1>, C<:2>, and so on) in addition to C, but their use is not portable. - -If the C<:>I form of placeholder is supported by the driver you're using, -then you should be able to use either L or L to bind -values. Check your driver documentation. - -Some drivers allow you to prevent the recognition of a placeholder by placing a -single backslash character (C<\>) immediately before it. The driver will remove -the backslash character and ignore the placeholder, passing it unchanged to the -backend. If the driver supports this then L(9000) will return true. - -With most drivers, placeholders can't be used for any element of a -statement that would prevent the database server from validating the -statement and creating a query execution plan for it. For example: - - "SELECT name, age FROM ?" # wrong (will probably fail) - "SELECT name, ? FROM people" # wrong (but may not 'fail') - -Also, placeholders can only represent single scalar values. -For example, the following -statement won't work as expected for more than one value: - - "SELECT name, age FROM people WHERE name IN (?)" # wrong - "SELECT name, age FROM people WHERE name IN (?,?)" # two names - -When using placeholders with the SQL C qualifier, you must -remember that the placeholder substitutes for the whole string. -So you should use "C<... LIKE ? ...>" and include any wildcard -characters in the value that you bind to the placeholder. - -B - -Undefined values, or C, are used to indicate NULL values. -You can insert and update columns with a NULL value as you would a -non-NULL value. These examples insert and update the column -C with a NULL value: - - $sth = $dbh->prepare(qq{ - INSERT INTO people (fullname, age) VALUES (?, ?) - }); - $sth->execute("Joe Bloggs", undef); - - $sth = $dbh->prepare(qq{ - UPDATE people SET age = ? WHERE fullname = ? - }); - $sth->execute(undef, "Joe Bloggs"); - -However, care must be taken when trying to use NULL values in a -C clause. Consider: - - SELECT fullname FROM people WHERE age = ? - -Binding an C (NULL) to the placeholder will I select rows -which have a NULL C! At least for database engines that -conform to the SQL standard. Refer to the SQL manual for your database -engine or any SQL book for the reasons for this. To explicitly select -NULLs you have to say "C". - -A common issue is to have a code fragment handle a value that could be -either C or C (non-NULL or NULL) at runtime. -A simple technique is to prepare the appropriate statement as needed, -and substitute the placeholder for non-NULL cases: - - $sql_clause = defined $age? "age = ?" : "age IS NULL"; - $sth = $dbh->prepare(qq{ - SELECT fullname FROM people WHERE $sql_clause - }); - $sth->execute(defined $age ? $age : ()); - -The following technique illustrates qualifying a C clause with -several columns, whose associated values (C or C) are -in a hash %h: - - for my $col ("age", "phone", "email") { - if (defined $h{$col}) { - push @sql_qual, "$col = ?"; - push @sql_bind, $h{$col}; - } - else { - push @sql_qual, "$col IS NULL"; - } - } - $sql_clause = join(" AND ", @sql_qual); - $sth = $dbh->prepare(qq{ - SELECT fullname FROM people WHERE $sql_clause - }); - $sth->execute(@sql_bind); - -The techniques above call prepare for the SQL statement with each call to -execute. Because calls to prepare() can be expensive, performance -can suffer when an application iterates many times over statements -like the above. - -A better solution is a single C clause that supports both -NULL and non-NULL comparisons. Its SQL statement would need to be -prepared only once for all cases, thus improving performance. -Several examples of C clauses that support this are presented -below. But each example lacks portability, robustness, or simplicity. -Whether an example is supported on your database engine depends on -what SQL extensions it provides, and where it supports the C -placeholder in a statement. - - 0) age = ? - 1) NVL(age, xx) = NVL(?, xx) - 2) ISNULL(age, xx) = ISNULL(?, xx) - 3) DECODE(age, ?, 1, 0) = 1 - 4) age = ? OR (age IS NULL AND ? IS NULL) - 5) age = ? OR (age IS NULL AND SP_ISNULL(?) = 1) - 6) age = ? OR (age IS NULL AND ? = 1) - -Statements formed with the above C clauses require execute -statements as follows. The arguments are required, whether their -values are C or C. - - 0,1,2,3) $sth->execute($age); - 4,5) $sth->execute($age, $age); - 6) $sth->execute($age, defined($age) ? 0 : 1); - -Example 0 should not work (as mentioned earlier), but may work on -a few database engines anyway (e.g. Sybase). Example 0 is part -of examples 4, 5, and 6, so if example 0 works, these other -examples may work, even if the engine does not properly support -the right hand side of the C expression. - -Examples 1 and 2 are not robust: they require that you provide a -valid column value xx (e.g. '~') which is not present in any row. -That means you must have some notion of what data won't be stored -in the column, and expect clients to adhere to that. - -Example 5 requires that you provide a stored procedure (SP_ISNULL -in this example) that acts as a function: it checks whether a value -is null, and returns 1 if it is, or 0 if not. - -Example 6, the least simple, is probably the most portable, i.e., it -should work with most, if not all, database engines. - -Here is a table that indicates which examples above are known to -work on various database engines: - - -----Examples------ - 0 1 2 3 4 5 6 - - - - - - - - - Oracle 9 N Y N Y Y ? Y - Informix IDS 9 N N N Y N Y Y - MS SQL N N Y N Y ? Y - Sybase Y N N N N N Y - AnyData,DBM,CSV Y N N N Y Y* Y - SQLite 3.3 N N N N Y N N - MSAccess N N N N Y N Y - -* Works only because Example 0 works. - -DBI provides a sample perl script that will test the examples above -on your database engine and tell you which ones work. It is located -in the F subdirectory of the DBI source distribution, or here: -L -Please use the script to help us fill-in and maintain this table. - -B - -Without using placeholders, the insert statement shown previously would have to -contain the literal values to be inserted and would have to be -re-prepared and re-executed for each row. With placeholders, the insert -statement only needs to be prepared once. The bind values for each row -can be given to the C method each time it's called. By avoiding -the need to re-prepare the statement for each row, the application -typically runs many times faster. Here's an example: - - my $sth = $dbh->prepare(q{ - INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?) - }) or die $dbh->errstr; - while (<>) { - chomp; - my ($product_code, $qty, $price) = split /,/; - $sth->execute($product_code, $qty, $price) or die $dbh->errstr; - } - $dbh->commit or die $dbh->errstr; - -See L and L for more details. - -The C style quoting used in this example avoids clashing with -quotes that may be used in the SQL statement. Use the double-quote like -C operator if you want to interpolate variables into the string. -See L for more details. - -See also the L method, which is used to associate Perl -variables with the output columns of a C -that may have more data to fetch. (Fetching all the data or calling C<$sth-Efinish> -sets C off.) - -=head3 C - -Type: boolean - -The C attribute is true if the handle object has been "executed". -Currently only the $dbh do() method and the $sth execute(), execute_array(), -and execute_for_fetch() methods set the C attribute. - -When it's set on a handle it is also set on the parent handle at the -same time. So calling execute() on a $sth also sets the C -attribute on the parent $dbh. - -The C attribute for a database handle is cleared by the commit() and -rollback() methods (even if they fail). The C attribute of a -statement handle is not cleared by the DBI under any circumstances and so acts -as a permanent record of whether the statement handle was ever used. - -The C attribute was added in DBI 1.41. - -=head3 C - -Type: integer, read-only - -For a driver handle, C is the number of currently existing database -handles that were created from that driver handle. For a database -handle, C is the number of currently existing statement handles that -were created from that database handle. -For a statement handle, the value is zero. - -=head3 C - -Type: integer, read-only - -Like C, but only counting those that are C (as above). - -=head3 C - -Type: hash ref - -For a database handle, C returns a reference to the cache (hash) of -statement handles created by the L method. For a -driver handle, returns a reference to the cache (hash) of -database handles created by the L method. - -=head3 C - -Type: scalar, read-only - -The C attribute identifies the type of a DBI handle. Returns -"dr" for driver handles, "db" for database handles and "st" for -statement handles. - -=head3 C - -Type: array ref - -The ChildHandles attribute contains a reference to an array of all the -handles created by this handle which are still accessible. The -contents of the array are weak-refs and will become undef when the -handle goes out of scope. (They're cleared out occasionally.) - -C returns undef if your perl version does not support weak -references (check the L module). The referenced -array returned should be treated as read-only. - -For example, to enumerate all driver handles, database handles and -statement handles: - - sub show_child_handles { - my ($h, $level) = @_; - printf "%sh %s %s\n", $h->{Type}, "\t" x $level, $h; - show_child_handles($_, $level + 1) - for (grep { defined } @{$h->{ChildHandles}}); - } - - my %drivers = DBI->installed_drivers(); - show_child_handles($_, 0) for (values %drivers); - -=head3 C - -Type: boolean, inherited - -The C attribute is used by emulation layers (such as -Oraperl) to enable compatible behaviour in the underlying driver -(e.g., DBD::Oracle) for this handle. Not normally set by application code. - -It also has the effect of disabling the 'quick FETCH' of attribute -values from the handles attribute cache. So all attribute values -are handled by the drivers own FETCH method. This makes them slightly -slower but is useful for special-purpose drivers like DBD::Multiplex. - -=head3 C - -Type: boolean - -The default value, false, means a handle will be fully destroyed -as normal when the last reference to it is removed, just as you'd expect. - -If set true then the handle will be treated by the DESTROY as if it was no -longer Active, and so the I related effects of DESTROYing a -handle will be skipped. Think of the name as meaning 'treat the handle as -not-Active in the DESTROY method'. - -For a database handle, this attribute does not disable an I -call to the disconnect method, only the implicit call from DESTROY -that happens if the handle is still marked as C. - -This attribute is specifically designed for use in Unix applications -that "fork" child processes. For some drivers, when the child process exits -the destruction of inherited handles cause the corresponding handles in the -parent process to cease working. - -Either the parent or the child process, but not both, should set -C true on all their shared handles. Alternatively, and -preferably, the L can be set in the parent on connect. - -To help tracing applications using fork the process id is shown in -the trace log whenever a DBI or handle trace() method is called. -The process id also shown for I method call if the DBI trace -level (not handle trace level) is set high enough to show the trace -from the DBI's method dispatcher, e.g. >= 9. - -=head3 C - -Type: boolean, inherited - -The L attribute, described above, needs to be explicitly set -in the child process after a fork(), on every active database and statement handle. -This is a problem if the code that performs the fork() is not under your -control, perhaps in a third-party module. Use C to get -around this situation. - -If set true, the DESTROY method will check the process id of the handle and, if -different from the current process id, it will set the I attribute. -It is strongly recommended that C is enabled on all new code -(it's only not enabled by default to avoid backwards compatibility problems). - -This is the example it's designed to deal with: - - my $dbh = DBI->connect(...); - some_code_that_forks(); # Perhaps without your knowledge - # Child process dies, destroying the inherited dbh - $dbh->do(...); # Breaks because parent $dbh is now broken - -The C attribute was added in DBI 1.614. - -=head3 C - -Type: boolean, inherited - -The C attribute controls the printing of warnings recorded -by the driver. When set to a true value (the default) the DBI will check method -calls to see if a warning condition has been set. If so, the DBI -will effectively do a C -where C<$class> is the driver class and C<$method> is the name of -the method which failed. E.g., - - DBD::Oracle::db execute warning: ... warning text here ... - -If desired, the warnings can be caught and processed using a C<$SIG{__WARN__}> -handler or modules like CGI::Carp and CGI::ErrorWrap. - -See also L for how warnings are recorded and L -for how to influence it. - -Fetching the full details of warnings can require an extra round-trip -to the database server for some drivers. In which case the driver -may opt to only fetch the full details of warnings if the C -attribute is true. If C is false then these drivers should -still indicate the fact that there were warnings by setting the -warning string to, for example: "3 warnings". - -=head3 C - -Type: boolean, inherited - -The C attribute can be used to force errors to generate warnings (using -C) in addition to returning error codes in the normal way. When set -"on", any method which results in an error occurring will cause the DBI to -effectively do a C where C<$class> -is the driver class and C<$method> is the name of the method which failed. E.g., - - DBD::Oracle::db prepare failed: ... error text here ... - -By default, Cconnect> sets C "on". - -If desired, the warnings can be caught and processed using a C<$SIG{__WARN__}> -handler or modules like CGI::Carp and CGI::ErrorWrap. - -=head3 C - -Type: boolean, inherited - -The C attribute can be used to force errors to raise exceptions rather -than simply return error codes in the normal way. It is "off" by default. -When set "on", any method which results in an error will cause -the DBI to effectively do a C, -where C<$class> is the driver class and C<$method> is the name of the method -that failed. E.g., - - DBD::Oracle::db prepare failed: ... error text here ... - -If you turn C on then you'd normally turn C off. -If C is also on, then the C is done first (naturally). - -Typically C is used in conjunction with C, -or a module like L or L, -to catch the exception that's been thrown and handle it. -For example: - - use Try::Tiny; - - try { - ... - $sth->execute(); - ... - } catch { - # $sth->err and $DBI::err will be true if error was from DBI - warn $_; # print the error (which Try::Tiny puts into $_) - ... # do whatever you need to deal with the error - }; - -In the catch block the $DBI::lasth variable can be useful for -diagnosis and reporting if you can't be sure which handle triggered -the error. For example, $DBI::lasth->{Type} and $DBI::lasth->{Statement}. - -See also L. - -If you want to temporarily turn C off (inside a library function -that is likely to fail, for example), the recommended way is like this: - - { - local $h->{RaiseError}; # localize and turn off for this block - ... - } - -The original value will automatically and reliably be restored by Perl, -regardless of how the block is exited. -The same logic applies to other attributes, including C. - -=head3 C - -Type: code ref, inherited - -The C attribute can be used to provide your own alternative behaviour -in case of errors. If set to a reference to a subroutine then that -subroutine is called when an error is detected (at the same point that -C and C are handled). - -The subroutine is called with three parameters: the error message -string that C and C would use, -the DBI handle being used, and the first value being returned by -the method that failed (typically undef). - -If the subroutine returns a false value then the C -and/or C attributes are checked and acted upon as normal. - -For example, to C with a full stack trace for any error: - - use Carp; - $h->{HandleError} = sub { confess(shift) }; - -Or to turn errors into exceptions: - - use Exception; # or your own favourite exception module - $h->{HandleError} = sub { Exception->new('DBI')->raise($_[0]) }; - -It is possible to 'stack' multiple HandleError handlers by using -closures: - - sub your_subroutine { - my $previous_handler = $h->{HandleError}; - $h->{HandleError} = sub { - return 1 if $previous_handler and &$previous_handler(@_); - ... your code here ... - }; - } - -Using a C inside a subroutine to store the previous C -value is important. See L and L for more information -about I. - -It is possible for C to alter the error message that -will be used by C and C if it returns false. -It can do that by altering the value of $_[0]. This example appends -a stack trace to all errors and, unlike the previous example using -Carp::confess, this will work C as well as C: - - $h->{HandleError} = sub { $_[0]=Carp::longmess($_[0]); 0; }; - -It is also possible for C to hide an error, to a limited -degree, by using L to reset $DBI::err and $DBI::errstr, -and altering the return value of the failed method. For example: - - $h->{HandleError} = sub { - return 0 unless $_[0] =~ /^\S+ fetchrow_arrayref failed:/; - return 0 unless $_[1]->err == 1234; # the error to 'hide' - $h->set_err(undef,undef); # turn off the error - $_[2] = [ ... ]; # supply alternative return value - return 1; - }; - -This only works for methods which return a single value and is hard -to make reliable (avoiding infinite loops, for example) and so isn't -recommended for general use! If you find a I use for it then -please let me know. - -=head3 C - -Type: code ref, inherited - -The C attribute can be used to intercept -the setting of handle C, C, and C values. -If set to a reference to a subroutine then that subroutine is called -whenever set_err() is called, typically by the driver or a subclass. - -The subroutine is called with five arguments, the first five that -were passed to set_err(): the handle, the C, C, and -C values being set, and the method name. These can be altered -by changing the values in the @_ array. The return value affects -set_err() behaviour, see L for details. - -It is possible to 'stack' multiple HandleSetErr handlers by using -closures. See L for an example. - -The C and C subroutines differ in subtle -but significant ways. HandleError is only invoked at the point where -the DBI is about to return to the application with C set true. -It's not invoked by the failure of a method that's been called by -another DBI method. HandleSetErr, on the other hand, is called -whenever set_err() is called with a defined C value, even if false. -So it's not just for errors, despite the name, but also warn and info states. -The set_err() method, and thus HandleSetErr, may be called multiple -times within a method and is usually invoked from deep within driver code. - -In theory a driver can use the return value from HandleSetErr via -set_err() to decide whether to continue or not. If set_err() returns -an empty list, indicating that the HandleSetErr code has 'handled' -the 'error', the driver could then continue instead of failing (if -that's a reasonable thing to do). This isn't excepted to be -common and any such cases should be clearly marked in the driver -documentation and discussed on the dbi-dev mailing list. - -The C attribute was added in DBI 1.41. - -=head3 C - -Type: unsigned integer - -The C attribute is incremented whenever the set_err() -method records an error. It isn't incremented by warnings or -information states. It is not reset by the DBI at any time. - -The C attribute was added in DBI 1.41. Older drivers may -not have been updated to use set_err() to record errors and so this -attribute may not be incremented when using them. - - -=head3 C - -Type: boolean, inherited - -The C attribute can be used to cause the relevant -Statement text to be appended to the error messages generated by -the C, C, and C attributes. -Only applies to errors on statement handles -plus the prepare(), do(), and the various C database handle methods. -(The exact format of the appended text is subject to change.) - -If C<$h-E{ParamValues}> returns a hash reference of parameter -(placeholder) values then those are formatted and appended to the -end of the Statement text in the error message. - -=head3 C - -Type: integer, inherited - -The C attribute can be used as an alternative to the -L method to set the DBI trace level and trace flags for a -specific handle. See L for more details. - -The C attribute is especially useful combined with -C to alter the trace settings for just a single block of code. - -=head3 C - -Type: string, inherited - -The C attribute is used to specify whether the fetchrow_hashref() -method should perform case conversion on the field names used for -the hash keys. For historical reasons it defaults to 'C' but -it is recommended to set it to 'C' (convert to lower case) -or 'C' (convert to upper case) according to your preference. -It can only be set for driver and database handles. For statement -handles the value is frozen when prepare() is called. - - -=head3 C - -Type: boolean, inherited - -The C attribute can be used to control the trimming of trailing space -characters from fixed width character (CHAR) fields. No other field -types are affected, even where field values have trailing spaces. - -The default is false (although it is possible that the default may change). -Applications that need specific behaviour should set the attribute as -needed. - -Drivers are not required to support this attribute, but any driver which -does not support it must arrange to return C as the attribute value. - - -=head3 C - -Type: unsigned integer, inherited - -The C attribute may be used to control the maximum -length of 'long' type fields (LONG, BLOB, CLOB, MEMO, etc.) which the driver will -read from the database automatically when it fetches each row of data. - -The C attribute only relates to fetching and reading -long values; it is not involved in inserting or updating them. - -A value of 0 means not to automatically fetch any long data. -Drivers may return undef or an empty string for long fields when -C is 0. - -The default is typically 0 (zero) or 80 bytes but may vary between drivers. -Applications fetching long fields should set this value to slightly -larger than the longest long field value to be fetched. - -Some databases return some long types encoded as pairs of hex digits. -For these types, C relates to the underlying data -length and not the doubled-up length of the encoded string. - -Changing the value of C for a statement handle after it -has been C'd will typically have no effect, so it's common to -set C on the C<$dbh> before calling C. - -For most drivers the value used here has a direct effect on the -memory used by the statement handle while it's active, so don't be -too generous. If you can't be sure what value to use you could -execute an extra select statement to determine the longest value. -For example: - - $dbh->{LongReadLen} = $dbh->selectrow_array(qq{ - SELECT MAX(OCTET_LENGTH(long_column_name)) - FROM table WHERE ... - }); - $sth = $dbh->prepare(qq{ - SELECT long_column_name, ... FROM table WHERE ... - }); - -You may need to take extra care if the table can be modified between -the first select and the second being executed. You may also need to -use a different function if OCTET_LENGTH() does not work for long -types in your database. For example, for Sybase use DATALENGTH() and -for Oracle use LENGTHB(). - -See also L for information on truncation of long types. - -=head3 C - -Type: boolean, inherited - -The C attribute may be used to control the effect of -fetching a long field value which has been truncated (typically -because it's longer than the value of the C attribute). - -By default, C is false and so fetching a long value that -needs to be truncated will cause the fetch to fail. -(Applications should always be sure to -check for errors after a fetch loop in case an error, such as a divide -by zero or long field truncation, caused the fetch to terminate -prematurely.) - -If a fetch fails due to a long field truncation when C is -false, many drivers will allow you to continue fetching further rows. - -See also L. - -=head3 C - -Type: boolean, inherited - -If the C attribute is set to a true value I Perl is running in -taint mode (e.g., started with the C<-T> option), then all the arguments -to most DBI method calls are checked for being tainted. I - -The attribute defaults to off, even if Perl is in taint mode. -See L for more about taint mode. If Perl is not -running in taint mode, this attribute has no effect. - -When fetching data that you trust you can turn off the TaintIn attribute, -for that statement handle, for the duration of the fetch loop. - -The C attribute was added in DBI 1.31. - -=head3 C - -Type: boolean, inherited - -If the C attribute is set to a true value I Perl is running in -taint mode (e.g., started with the C<-T> option), then most data fetched -from the database is considered tainted. I - -The attribute defaults to off, even if Perl is in taint mode. -See L for more about taint mode. If Perl is not -running in taint mode, this attribute has no effect. - -When fetching data that you trust you can turn off the TaintOut attribute, -for that statement handle, for the duration of the fetch loop. - -Currently only fetched data is tainted. It is possible that the results -of other DBI method calls, and the value of fetched attributes, may -also be tainted in future versions. That change may well break your -applications unless you take great care now. If you use DBI Taint mode, -please report your experience and any suggestions for changes. - -The C attribute was added in DBI 1.31. - -=head3 C - -Type: boolean, inherited - -The C attribute is a shortcut for L and L (it is also present -for backwards compatibility). - -Setting this attribute sets both L and L, and retrieving -it returns a true value if and only if L and L are -both set to true values. - -=head3 C - -Type: inherited - -The C attribute enables the collection and reporting of -method call timing statistics. See the L module -documentation for I more detail. - -The C attribute was added in DBI 1.24. - -=head3 C - -Type: boolean, inherited - -An application can set the C attribute of a handle to a true value to -indicate that it will not be attempting to make any changes using that handle -or any children of it. - -Note that the exact definition of 'read only' is rather fuzzy. -For more details see the documentation for the driver you're using. - -If the driver can make the handle truly read-only then it should -(unless doing so would have unpleasant side effect, like changing the -consistency level from per-statement to per-session). -Otherwise the attribute is simply advisory. - -A driver can set the C attribute itself to indicate that the data it -is connected to cannot be changed for some reason. - -If the driver cannot ensure the C attribute is adhered to it -will record a warning. In this case reading the C attribute -back after it is set true will return true even if the underlying -driver cannot ensure this (so any application knows the application -declared itself ReadOnly). - -Library modules and proxy drivers can use the attribute to influence -their behavior. For example, the DBD::Gofer driver considers the -C attribute when making a decision about whether to retry an -operation that failed. - -The attribute should be set to 1 or 0 (or undef). Other values are reserved. - -=head3 C - -Type: hash ref - -The DBI callback mechanism lets you intercept, and optionally replace, any -method call on a DBI handle. At the extreme, it lets you become a puppet -master, deceiving the application in any way you want. - -The C attribute is a hash reference where the keys are DBI method -names and the values are code references. For each key naming a method, the -DBI will execute the associated code reference before executing the method. - -The arguments to the code reference will be the same as to the method, -including the invocant (a database handle or statement handle). For example, -say that to callback to some code on a call to C: - - $dbh->{Callbacks} = { - prepare => sub { - my ($dbh, $query, $attrs) = @_; - print "Preparing q{$query}\n" - }, - }; - -The callback would then be executed when you called the C method: - - $dbh->prepare('SELECT 1'); - -And the output of course would be: - - Preparing q{SELECT 1} - -Because callbacks are executed I the methods -they're associated with, you can modify the arguments before they're passed on -to the method call. For example, to make sure that all calls to C -are immediately prepared by L, add a callback that makes sure that -the C attribute is always set: - - my $dbh = DBI->connect($dsn, $username, $auth, { - Callbacks => { - prepare => sub { - $_[2] ||= {}; - $_[2]->{pg_prepare_now} = 1; - return; # must return nothing - }, - } - }); - -Note that we are editing the contents of C<@_> directly. In this case we've -created the attributes hash if it's not passed to the C call. - -You can also prevent the associated method from ever executing. While a -callback executes, C<$_> holds the method name. (This allows multiple callbacks -to share the same code reference and still know what method was called.) -To prevent the method from -executing, simply C. For example, if you wanted to disable calls to -C, you could do this: - - $dbh->{Callbacks} = { - ping => sub { - # tell dispatch to not call the method: - undef $_; - # return this value instead: - return "42 bells"; - } - }; - -As with other attributes, Callbacks can be specified on a handle or via the -attributes to C. Callbacks can also be applied to a statement -methods on a statement handle. For example: - - $sth->{Callbacks} = { - execute => sub { - print "Executing ", shift->{Statement}, "\n"; - } - }; - -The C attribute of a database handle isn't copied to any statement -handles it creates. So setting callbacks for a statement handle requires you to -set the C attribute on the statement handle yourself, as in the -example above, or use the special C key described below. - -B - -In addition to DBI handle method names, the C hash reference -supports four additional keys. - -The first is the C key. When a statement handle is created from -a database handle the C key of the database handle's -C attribute, if any, becomes the new C attribute of the -statement handle. -This allows you to define callbacks for all statement handles created from a -database handle. For example, if you wanted to count how many times C -was called in your application, you could write: - - my $exec_count = 0; - my $dbh = DBI->connect( $dsn, $username, $auth, { - Callbacks => { - ChildCallbacks => { - execute => sub { $exec_count++; return; } - } - } - }); - - END { - print "The execute method was called $exec_count times\n"; - } - -The other three special keys are C, -C, and C. These keys define -callbacks that are called when C is called, but allow -different behaviors depending on whether a new handle is created or a handle -is returned. The callback is invoked with these arguments: -C<$dbh, $dsn, $user, $auth, $attr>. - -For example, some applications uses C to connect with -C enabled and then disable C temporarily for -transactions. If C is called during a transaction, perhaps in -a utility method, then it might select the same cached handle and then force -C on, forcing a commit of the transaction. See the L -documentation for one way to deal with that. Here we'll describe an alternative -approach using a callback. - -Because the C and C callbacks are -invoked before C has applied the connect attributes, you can -use them to edit the attributes that will be applied. To prevent a cached -handle from having its transactions committed before it's returned, you can -eliminate the C attribute in a C callback, -like so: - - my $cb = { - 'connect_cached.reused' => sub { delete $_[4]->{AutoCommit} }, - }; - - sub dbh { - my $self = shift; - DBI->connect_cached( $dsn, $username, $auth, { - PrintError => 0, - RaiseError => 1, - AutoCommit => 1, - Callbacks => $cb, - }); - } - -The upshot is that new database handles are created with C -enabled, while cached database handles are left in whatever transaction state -they happened to be in when retrieved from the cache. - -Note that we've also used a lexical for the callbacks hash reference. This is -because C returns a new database handle if any of the -attributes passed to is have changed. If we used an inline hash reference, -C would return a new database handle every time. Which would -rather defeat the purpose. - -A more common application for callbacks is setting connection state only when -a new connection is made (by connect() or connect_cached()). Adding a callback -to the connected method (when using C) or via -C (when useing connect_cached()>) makes this easy. -The connected() method is a no-op by default (unless you subclass the DBI and -change it). The DBI calls it to indicate that a new connection has been made -and the connection attributes have all been set. You can give it a bit of -added functionality by applying a callback to it. For example, to make sure -that MySQL understands your application's ANSI-compliant SQL, set it up like -so: - - my $dbh = DBI->connect($dsn, $username, $auth, { - Callbacks => { - connected => sub { - shift->do(q{ - SET SESSION sql_mode='ansi,strict_trans_tables,no_auto_value_on_zero'; - }); - return; - }, - } - }); - -If you're using C, use the C -callback, instead. This is because C is called for both new and -reused database handles, but you want to execute a callback only the when a -new database handle is returned. For example, to set the time zone on -connection to a PostgreSQL database, try this: - - my $cb = { - 'connect_cached.connected' => sub { - shift->do('SET timezone = UTC'); - } - }; - - sub dbh { - my $self = shift; - DBI->connect_cached( $dsn, $username, $auth, { Callbacks => $cb }); - } - -One significant limitation with callbacks is that there can only be one per -method per handle. This means it's easy for one use of callbacks to interfere -with, or typically simply overwrite, another use of callbacks. For this reason -modules using callbacks should document the fact clearly so application authors -can tell if use of callbacks by the module will clash with use of callbacks by -the application. - -You might be able to work around this issue by taking a copy of the original -callback and calling it within your own. For example: - - my $prev_cb = $h->{Callbacks}{method_name}; - $h->{Callbacks}{method_name} = sub { - if ($prev_cb) { - my @result = $prev_cb->(@_); - return @result if not $_; # $prev_cb vetoed call - } - ... your callback logic here ... - }; - -=head3 C - -The DBI provides a way to store extra information in a DBI handle as -"private" attributes. The DBI will allow you to store and retrieve any -attribute which has a name starting with "C". - -It is I recommended that you use just I private -attribute (e.g., use a hash ref) I give it a long and unambiguous -name that includes the module or application name that the attribute -relates to (e.g., "C"). - -Because of the way the Perl tie mechanism works you cannot reliably -use the C<||=> operator directly to initialise the attribute, like this: - - my $foo = $dbh->{private_yourmodname_foo} ||= { ... }; # WRONG - -you should use a two step approach like this: - - my $foo = $dbh->{private_yourmodname_foo}; - $foo ||= $dbh->{private_yourmodname_foo} = { ... }; - -This attribute is primarily of interest to people sub-classing DBI, -or for applications to piggy-back extra information onto DBI handles. - -=head1 DBI DATABASE HANDLE OBJECTS - -This section covers the methods and attributes associated with -database handles. - -=head2 Database Handle Methods - -The following methods are specified for DBI database handles: - -=head3 C - - $new_dbh = $dbh->clone(\%attr); - -The C method duplicates the $dbh connection by connecting -with the same parameters ($dsn, $user, $password) as originally used. - -The attributes for the cloned connect are the same as those used -for the I connect, with any other attributes in C<\%attr> -merged over them. Effectively the same as doing: - - %attributes_used = ( %original_attributes, %attr ); - -If \%attr is not given then it defaults to a hash containing all -the attributes in the attribute cache of $dbh excluding any non-code -references, plus the main boolean attributes (RaiseError, PrintError, -AutoCommit, etc.). I - -The clone method can be used even if the database handle is disconnected. - -The C method was added in DBI 1.33. - -=head3 C - - @ary = $dbh->data_sources(); - @ary = $dbh->data_sources(\%attr); - -Returns a list of data sources (databases) available via the $dbh -driver's data_sources() method, plus any extra data sources that -the driver can discover via the connected $dbh. Typically the extra -data sources are other databases managed by the same server process -that the $dbh is connected to. - -Data sources are returned in a form suitable for passing to the -L method (that is, they will include the "C" prefix). - -The data_sources() method, for a $dbh, was added in DBI 1.38. - -=head3 C - - $rows = $dbh->do($statement) or die $dbh->errstr; - $rows = $dbh->do($statement, \%attr) or die $dbh->errstr; - $rows = $dbh->do($statement, \%attr, @bind_values) or die ... - -Prepare and execute a single statement. Returns the number of rows -affected or C on error. A return value of C<-1> means the -number of rows is not known, not applicable, or not available. - -This method is typically most useful for I-C statements because it does not return a statement -handle (so you can't fetch any data). - -The default C method is logically similar to: - - sub do { - my($dbh, $statement, $attr, @bind_values) = @_; - my $sth = $dbh->prepare($statement, $attr) or return undef; - $sth->execute(@bind_values) or return undef; - my $rows = $sth->rows; - ($rows == 0) ? "0E0" : $rows; # always return true if no error - } - -For example: - - my $rows_deleted = $dbh->do(q{ - DELETE FROM table - WHERE status = ? - }, undef, 'DONE') or die $dbh->errstr; - -Using placeholders and C<@bind_values> with the C method can be -useful because it avoids the need to correctly quote any variables -in the C<$statement>. But if you'll be executing the statement many -times then it's more efficient to C it once and call -C many times instead. - -The C style quoting used in this example avoids clashing with -quotes that may be used in the SQL statement. Use the double-quote-like -C operator if you want to interpolate variables into the string. -See L for more details. - -Note drivers are free to avoid the overhead of creating an DBI -statement handle for do(), especially if there are no parameters. In -this case error handlers, if invoked during do(), will be passed the -database handle. - -=head3 C - - $rv = $dbh->last_insert_id($catalog, $schema, $table, $field); - $rv = $dbh->last_insert_id($catalog, $schema, $table, $field, \%attr); - -Returns a value 'identifying' the row just inserted, if possible. -Typically this would be a value assigned by the database server -to a column with an I or I type. -Returns undef if the driver does not support the method or can't -determine the value. - -The $catalog, $schema, $table, and $field parameters may be required -for some drivers (see below). If you don't know the parameter values -and your driver does not need them, then use C for each. - -There are several caveats to be aware of with this method if you want -to use it for portable applications: - -B<*> For some drivers the value may only available immediately after -the insert statement has executed (e.g., mysql, Informix). - -B<*> For some drivers the $catalog, $schema, $table, and $field parameters -are required, for others they are ignored (e.g., mysql). - -B<*> Drivers may return an indeterminate value if no insert has -been performed yet. - -B<*> For some drivers the value may only be available if placeholders -have I been used (e.g., Sybase, MS SQL). In this case the value -returned would be from the last non-placeholder insert statement. - -B<*> Some drivers may need driver-specific hints about how to get -the value. For example, being told the name of the database 'sequence' -object that holds the value. Any such hints are passed as driver-specific -attributes in the \%attr parameter. - -B<*> If the underlying database offers nothing better, then some -drivers may attempt to implement this method by executing -"C statements. -If a row cache is not implemented, then setting C is ignored -and getting the value returns C. - -Some C values have special meaning, as follows: - - 0 - Automatically determine a reasonable cache size for each C. - -Note that large cache sizes may require a very large amount of memory -(I). Also, a large cache will cause -a longer delay not only for the first fetch, but also whenever the -cache needs refilling. - -See also the L statement handle attribute. - -=head3 C - -Type: string - -Returns the username used to connect to the database. - - -=head1 DBI STATEMENT HANDLE OBJECTS - -This section lists the methods and attributes associated with DBI -statement handles. - -=head2 Statement Handle Methods - -The DBI defines the following methods for use on DBI statement handles: - -=head3 C - - $sth->bind_param($p_num, $bind_value) - $sth->bind_param($p_num, $bind_value, \%attr) - $sth->bind_param($p_num, $bind_value, $bind_type) - -The C method takes a copy of $bind_value and associates it -(binds it) with a placeholder, identified by $p_num, embedded in -the prepared statement. Placeholders are indicated with question -mark character (C). For example: - - $dbh->{RaiseError} = 1; # save having to check each method call - $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE ?"); - $sth->bind_param(1, "John%"); # placeholders are numbered from 1 - $sth->execute; - DBI::dump_results($sth); - -See L for more information. - - -B - -The C<\%attr> parameter can be used to hint at the data type the -placeholder should have. This is rarely needed. Typically, the driver is only -interested in knowing if the placeholder should be bound as a number or a string. - - $sth->bind_param(1, $value, { TYPE => SQL_INTEGER }); - -As a short-cut for the common case, the data type can be passed -directly, in place of the C<\%attr> hash reference. This example is -equivalent to the one above: - - $sth->bind_param(1, $value, SQL_INTEGER); - -The C value indicates the standard (non-driver-specific) type for -this parameter. To specify the driver-specific type, the driver may -support a driver-specific attribute, such as C<{ ora_type =E 97 }>. - -The SQL_INTEGER and other related constants can be imported using - - use DBI qw(:sql_types); - -See L for more information. - -The data type is 'sticky' in that bind values passed to execute() are bound -with the data type specified by earlier bind_param() calls, if any. -Portable applications should not rely on being able to change the data type -after the first C call. - -Perl only has string and number scalar data types. All database types -that aren't numbers are bound as strings and must be in a format the -database will understand except where the bind_param() TYPE attribute -specifies a type that implies a particular format. For example, given: - - $sth->bind_param(1, $value, SQL_DATETIME); - -the driver should expect $value to be in the ODBC standard SQL_DATETIME -format, which is 'YYYY-MM-DD HH:MM:SS'. Similarly for SQL_DATE, SQL_TIME etc. - -As an alternative to specifying the data type in the C call, -you can let the driver pass the value as the default type (C). -You can then use an SQL function to convert the type within the statement. -For example: - - INSERT INTO price(code, price) VALUES (?, CONVERT(MONEY,?)) - -The C function used here is just an example. The actual function -and syntax will vary between different databases and is non-portable. - -See also L for more information. - - -=head3 C - - $rc = $sth->bind_param_inout($p_num, \$bind_value, $max_len) or die $sth->errstr; - $rv = $sth->bind_param_inout($p_num, \$bind_value, $max_len, \%attr) or ... - $rv = $sth->bind_param_inout($p_num, \$bind_value, $max_len, $bind_type) or ... - -This method acts like L, but also enables values to be -updated by the statement. The statement is typically -a call to a stored procedure. The C<$bind_value> must be passed as a -reference to the actual value to be used. - -Note that unlike L, the C<$bind_value> variable is not -copied when C is called. Instead, the value in the -variable is read at the time L is called. - -The additional C<$max_len> parameter specifies the minimum amount of -memory to allocate to C<$bind_value> for the new value. If the value -returned from the database is too -big to fit, then the execution should fail. If unsure what value to use, -pick a generous length, i.e., a length larger than the longest value that would ever be -returned. The only cost of using a larger value than needed is wasted memory. - -Undefined values or C are used to indicate null values. -See also L for more information. - - -=head3 C - - $rc = $sth->bind_param_array($p_num, $array_ref_or_value) - $rc = $sth->bind_param_array($p_num, $array_ref_or_value, \%attr) - $rc = $sth->bind_param_array($p_num, $array_ref_or_value, $bind_type) - -The C method is used to bind an array of values -to a placeholder embedded in the prepared statement which is to be executed -with L. For example: - - $dbh->{RaiseError} = 1; # save having to check each method call - $sth = $dbh->prepare("INSERT INTO staff (first_name, last_name, dept) VALUES(?, ?, ?)"); - $sth->bind_param_array(1, [ 'John', 'Mary', 'Tim' ]); - $sth->bind_param_array(2, [ 'Booth', 'Todd', 'Robinson' ]); - $sth->bind_param_array(3, "SALES"); # scalar will be reused for each row - $sth->execute_array( { ArrayTupleStatus => \my @tuple_status } ); - -The C<%attr> ($bind_type) argument is the same as defined for L. -Refer to L for general details on using placeholders. - -(Note that bind_param_array() can I be used to expand a -placeholder into a list of values for a statement like "SELECT foo -WHERE bar IN (?)". A placeholder can only ever represent one value -per execution.) - -Scalar values, including C, may also be bound by -C. In which case the same value will be used for each -L call. Driver-specific implementations may behave -differently, e.g., when binding to a stored procedure call, some -databases may permit mixing scalars and arrays as arguments. - -The default implementation provided by DBI (for drivers that have -not implemented array binding) is to iteratively call L for -each parameter tuple provided in the bound arrays. Drivers may -provide more optimized implementations using whatever bulk operation -support the database API provides. The default driver behaviour should -match the default DBI behaviour, but always consult your driver -documentation as there may be driver specific issues to consider. - -Note that the default implementation currently only supports non-data -returning statements (INSERT, UPDATE, but not SELECT). Also, -C and L cannot be mixed in the same -statement execution, and C must be used with -L; using C will have no effect -for L. - -The C method was added in DBI 1.22. - -=head3 C - - $rv = $sth->execute or die $sth->errstr; - $rv = $sth->execute(@bind_values) or die $sth->errstr; - -Perform whatever processing is necessary to execute the prepared -statement. An C is returned if an error occurs. A successful -C always returns true regardless of the number of rows affected, -even if it's zero (see below). It is always important to check the -return status of C (and most other DBI methods) for errors -if you're not using L. - -For a I-C statements, execute simply "starts" the query within the -database engine. Use one of the fetch methods to retrieve the data after -calling C. The C method does I return the number of -rows that will be returned by the query (because most databases can't -tell in advance), it simply returns a true value. - -You can tell if the statement was a C" -will return only a single key from C. In these cases use -column aliases or C. Note that it is the database server -(and not the DBD implementation) which provides the I for fields -containing functions like "C" or "C" and they may clash -with existing column names (most databases don't care about duplicate column -names in a result-set). If you want these to return as unique names that are -the same across databases, use I, as in "C" depending on the syntax your database -supports. - -Because of the extra work C and Perl have to perform, it -is not as efficient as C or C. - -By default a reference to a new hash is returned for each row. -It is likely that a future version of the DBI will support an -attribute which will enable the same hash to be reused for each -row. This will give a significant performance boost, but it won't -be enabled by default because of the risk of breaking old code. - - -=head3 C - - $tbl_ary_ref = $sth->fetchall_arrayref; - $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); - $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); - -The C method can be used to fetch all the data to be -returned from a prepared and executed statement handle. It returns a -reference to an array that contains one reference per row. - -If called on an I statement handle, C returns undef. - -If there are no rows left to return from an I statement handle, C returns a reference -to an empty array. If an error occurs, C returns the -data fetched thus far, which may be none. You should check C<$sth-Eerr> -afterwards (or use the C attribute) to discover if the data is -complete or was truncated due to an error. - -If $slice is an array reference, C uses L -to fetch each row as an array ref. If the $slice array is not empty -then it is used as a slice to select individual columns by perl array -index number (starting at 0, unlike column and parameter numbers which -start at 1). - -With no parameters, or if $slice is undefined, C -acts as if passed an empty array ref. - -For example, to fetch just the first column of every row: - - $tbl_ary_ref = $sth->fetchall_arrayref([0]); - -To fetch the second to last and last column of every row: - - $tbl_ary_ref = $sth->fetchall_arrayref([-2,-1]); - -Those two examples both return a reference to an array of array refs. - -If $slice is a hash reference, C fetches each row as a hash -reference. If the $slice hash is empty then the keys in the hashes have -whatever name lettercase is returned by default. (See L -attribute.) If the $slice hash is I empty, then it is used as a slice to -select individual columns by name. The values of the hash should be set to 1. -The key names of the returned hashes match the letter case of the names in the -parameter hash, regardless of the L attribute. - -For example, to fetch all fields of every row as a hash ref: - - $tbl_ary_ref = $sth->fetchall_arrayref({}); - -To fetch only the fields called "foo" and "bar" of every row as a hash ref -(with keys named "foo" and "BAR", regardless of the original capitalization): - - $tbl_ary_ref = $sth->fetchall_arrayref({ foo=>1, BAR=>1 }); - -Those two examples both return a reference to an array of hash refs. - -If $slice is a I, that hash is used to select -and rename columns. The keys are 0-based column index numbers and the values -are the corresponding keys for the returned row hashes. - -For example, to fetch only the first and second columns of every row as a hash -ref (with keys named "k" and "v" regardless of their original names): - - $tbl_ary_ref = $sth->fetchall_arrayref( \{ 0 => 'k', 1 => 'v' } ); - -If $max_rows is defined and greater than or equal to zero then it -is used to limit the number of rows fetched before returning. -fetchall_arrayref() can then be called again to fetch more rows. -This is especially useful when you need the better performance of -fetchall_arrayref() but don't have enough memory to fetch and return -all the rows in one go. - -Here's an example (assumes RaiseError is enabled): - - my $rows = []; # cache for batches of rows - while( my $row = ( shift(@$rows) || # get row from cache, or reload cache: - shift(@{$rows=$sth->fetchall_arrayref(undef,10_000)||[]}) ) - ) { - ... - } - -That I be the fastest way to fetch and process lots of rows using the DBI, -but it depends on the relative cost of method calls vs memory allocation. - -A standard C loop with column binding is often faster because -the cost of allocating memory for the batch of rows is greater than -the saving by reducing method calls. It's possible that the DBI may -provide a way to reuse the memory of a previous batch in future, which -would then shift the balance back towards fetchall_arrayref(). - - -=head3 C - - $hash_ref = $sth->fetchall_hashref($key_field); - -The C method can be used to fetch all the data to be -returned from a prepared and executed statement handle. It returns a reference -to a hash containing a key for each distinct value of the $key_field column -that was fetched. For each key the corresponding value is a reference to a hash -containing all the selected columns and their values, as returned by -C. - -If there are no rows to return, C returns a reference -to an empty hash. If an error occurs, C returns the -data fetched thus far, which may be none. You should check -C<$sth-Eerr> afterwards (or use the C attribute) to -discover if the data is complete or was truncated due to an error. - -The $key_field parameter provides the name of the field that holds the -value to be used for the key for the returned hash. For example: - - $dbh->{FetchHashKeyName} = 'NAME_lc'; - $sth = $dbh->prepare("SELECT FOO, BAR, ID, NAME, BAZ FROM TABLE"); - $sth->execute; - $hash_ref = $sth->fetchall_hashref('id'); - print "Name for id 42 is $hash_ref->{42}->{name}\n"; - -The $key_field parameter can also be specified as an integer column -number (counting from 1). If $key_field doesn't match any column in -the statement, as a name first then as a number, then an error is -returned. - -For queries returning more than one 'key' column, you can specify -multiple column names by passing $key_field as a reference to an -array containing one or more key column names (or index numbers). -For example: - - $sth = $dbh->prepare("SELECT foo, bar, baz FROM table"); - $sth->execute; - $hash_ref = $sth->fetchall_hashref( [ qw(foo bar) ] ); - print "For foo 42 and bar 38, baz is $hash_ref->{42}->{38}->{baz}\n"; - -The fetchall_hashref() method is normally used only where the key -fields values for each row are unique. If multiple rows are returned -with the same values for the key fields then later rows overwrite -earlier ones. - -=head3 C - - $rc = $sth->finish; - -Indicate that no more data will be fetched from this statement handle -before it is either executed again or destroyed. You almost certainly -do I need to call this method. - -Adding calls to C after loop that fetches all rows is a common mistake, -don't do it, it can mask genuine problems like uncaught fetch errors. - -When all the data has been fetched from a C -C (for some specific operations like C and C), or -after fetching all the rows of a C statements, it is generally not possible to know how many -rows will be returned except by fetching them all. Some drivers will -return the number of rows the application has fetched so far, but -others may return -1 until all rows have been fetched. So use of the -C method or C<$DBI::rows> with C is to execute a -"SELECT COUNT(*) FROM ..." SQL statement with the same "..." as your -query and then fetch the row count from that. - - -=head3 C - - $rc = $sth->bind_col($column_number, \$var_to_bind); - $rc = $sth->bind_col($column_number, \$var_to_bind, \%attr ); - $rc = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); - -Binds a Perl variable and/or some attributes to an output column -(field) of a C statement. - -The list of references should have the same number of elements as the number of -columns in the C statements, then -this attribute holds the number of un-fetched rows in the cache. If the -driver doesn't, then it returns C. Note that some drivers pre-fetch -rows on execute, whereas others wait till the first fetch. - -See also the L database handle attribute. - -=head1 FURTHER INFORMATION - -=head2 Catalog Methods - -An application can retrieve metadata information from the DBMS by issuing -appropriate queries on the views of the Information Schema. Unfortunately, -C views are seldom supported by the DBMS. -Special methods (catalog methods) are available to return result sets -for a small but important portion of that metadata: - - column_info - foreign_key_info - primary_key_info - table_info - statistics_info - -All catalog methods accept arguments in order to restrict the result sets. -Passing C to an optional argument does not constrain the search for -that argument. -However, an empty string ('') is treated as a regular search criteria -and will only match an empty value. - -B: SQL/CLI and ODBC differ in the handling of empty strings. An -empty string will not restrict the result set in SQL/CLI. - -Most arguments in the catalog methods accept only I, e.g. -the arguments of C. -Such arguments are treated as a literal string, i.e. the case is significant -and quote characters are taken literally. - -Some arguments in the catalog methods accept I (strings -containing '_' and/or '%'), e.g. the C<$table> argument of C. -Passing '%' is equivalent to leaving the argument C. - -B: The underscore ('_') is valid and often used in SQL identifiers. -Passing such a value to a search pattern argument may return more rows than -expected! -To include pattern characters as literals, they must be preceded by an -escape character which can be achieved with - - $esc = $dbh->get_info( 14 ); # SQL_SEARCH_PATTERN_ESCAPE - $search_pattern =~ s/([_%])/$esc$1/g; - -The ODBC and SQL/CLI specifications define a way to change the default -behaviour described above: All arguments (except I) -are treated as I if the C attribute is -set to C. -I are very similar to I, i.e. their -body (the string within the quotes) is interpreted literally. -I are compared in UPPERCASE. - -The DBI (currently) does not support the C attribute, -i.e. it behaves like an ODBC driver where C is set to -C. - - -=head2 Transactions - -Transactions are a fundamental part of any robust database system. They -protect against errors and database corruption by ensuring that sets of -related changes to the database take place in atomic (indivisible, -all-or-nothing) units. - -This section applies to databases that support transactions and where -C is off. See L for details of using C -with various types of databases. - -The recommended way to implement robust transactions in Perl -applications is to enable L and catch the error that's 'thrown' as -an exception. For example, using L: - - use Try::Tiny; - $dbh->{AutoCommit} = 0; # enable transactions, if possible - $dbh->{RaiseError} = 1; - try { - foo(...) # do lots of work here - bar(...) # including inserts - baz(...) # and updates - $dbh->commit; # commit the changes if we get this far - } catch { - warn "Transaction aborted because $_"; # Try::Tiny copies $@ into $_ - # now rollback to undo the incomplete changes - # but do it in an eval{} as it may also fail - eval { $dbh->rollback }; - # add other application on-error-clean-up code here - }; - -If the C attribute is not set, then DBI calls would need to be -manually checked for errors, typically like this: - - $h->method(@args) or die $h->errstr; - -With C set, the DBI will automatically C if any DBI method -call on that handle (or a child handle) fails, so you don't have to -test the return value of each method call. See L for more -details. - -A major advantage of the C approach is that the transaction will be -properly rolled back if I code (not just DBI calls) in the inner -application dies for any reason. The major advantage of using the -C<$h-E{RaiseError}> attribute is that all DBI calls will be checked -automatically. Both techniques are strongly recommended. - -After calling C or C many drivers will not let you -fetch from a previously active C statements. - -See L and L for other important information -about transactions. - - -=head2 Handling BLOB / LONG / Memo Fields - -Many databases support "blob" (binary large objects), "long", or similar -datatypes for holding very long strings or large amounts of binary -data in a single field. Some databases support variable length long -values over 2,000,000,000 bytes in length. - -Since values of that size can't usually be held in memory, and because -databases can't usually know in advance the length of the longest long -that will be returned from a C
m4D7w99AA#c`3D_HGGX4!@ZtZ!N84EyX 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 diff --git a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/DBIXS.h b/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/DBIXS.h deleted file mode 100644 index 9860bd5..0000000 --- a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/DBIXS.h +++ /dev/null @@ -1,573 +0,0 @@ -/* vim: ts=8:sw=4:expandtab - * - * $Id$ - * - * Copyright (c) 1994-2010 Tim Bunce Ireland - * - * See COPYRIGHT section in DBI.pm for usage and distribution rights. - */ - -/* DBI Interface Definitions for DBD Modules */ - -#ifndef DBIXS_VERSION /* prevent multiple inclusion */ - -#ifndef DBIS -#define DBIS dbis /* default name for dbistate_t variable */ -#endif - -/* Here for backwards compat. PERL_POLLUTE was removed in perl 5.13.3 */ -#define PERL_POLLUTE - -/* first pull in the standard Perl header files for extensions */ -#include -#include -#include - -#ifdef debug /* causes problems with DBIS->debug */ -#undef debug -#endif - -#ifdef std /* causes problems with STLport */ -#undef std -#endif - -/* define DBIXS_REVISION */ -#include "dbixs_rev.h" - -/* Perl backwards compatibility definitions */ -#include "dbipport.h" - -/* DBI SQL_* type definitions */ -#include "dbi_sql.h" - - -#define DBIXS_VERSION 93 /* superseded by DBIXS_REVISION */ - -#ifdef NEED_DBIXS_VERSION -#if NEED_DBIXS_VERSION > DBIXS_VERSION -error You_need_to_upgrade_your_DBI_module_before_building_this_driver -#endif -#else -#define NEED_DBIXS_VERSION DBIXS_VERSION -#endif - - -#define DBI_LOCK -#define DBI_UNLOCK - -#ifndef DBI_NO_THREADS -#ifdef USE_ITHREADS -#define DBI_USE_THREADS -#endif /* USE_ITHREADS */ -#endif /* DBI_NO_THREADS */ - - -/* forward struct declarations */ - -typedef struct dbistate_st dbistate_t; -/* implementor needs to define actual struct { dbih_??c_t com; ... }*/ -typedef struct imp_drh_st imp_drh_t; /* driver */ -typedef struct imp_dbh_st imp_dbh_t; /* database */ -typedef struct imp_sth_st imp_sth_t; /* statement */ -typedef struct imp_fdh_st imp_fdh_t; /* field descriptor */ -typedef struct imp_xxh_st imp_xxh_t; /* any (defined below) */ -#define DBI_imp_data_ imp_xxh_t /* friendly for take_imp_data */ - - - -/* --- DBI Handle Common Data Structure (all handles have one) --- */ - -/* Handle types. Code currently assumes child = parent + 1. */ -#define DBIt_DR 1 -#define DBIt_DB 2 -#define DBIt_ST 3 -#define DBIt_FD 4 - -/* component structures */ - -typedef struct dbih_com_std_st { - U32 flags; - int call_depth; /* used by DBI to track nested calls (int) */ - U16 type; /* DBIt_DR, DBIt_DB, DBIt_ST */ - HV *my_h; /* copy of outer handle HV (not refcounted) */ - SV *parent_h; /* parent inner handle (ref to hv) (r.c.inc) */ - imp_xxh_t *parent_com; /* parent com struct shortcut */ - PerlInterpreter * thr_user; /* thread that owns the handle */ - - HV *imp_stash; /* who is the implementor for this handle */ - SV *imp_data; /* optional implementors data (for perl imp's) */ - - I32 kids; /* count of db's for dr's, st's for db's etc */ - I32 active_kids; /* kids which are currently DBIc_ACTIVE */ - U32 pid; /* pid of process that created handle */ - dbistate_t *dbistate; -} dbih_com_std_t; - -typedef struct dbih_com_attr_st { - /* These are copies of the Hash values (ref.cnt.inc'd) */ - /* Many of the hash values are themselves references */ - SV *TraceLevel; - SV *State; /* Standard SQLSTATE, 5 char string */ - SV *Err; /* Native engine error code */ - SV *Errstr; /* Native engine error message */ - UV ErrCount; - U32 LongReadLen; /* auto read length for long/blob types */ - SV *FetchHashKeyName; /* for fetchrow_hashref */ - /* (NEW FIELDS?... DON'T FORGET TO UPDATE dbih_clearcom()!) */ -} dbih_com_attr_t; - - -struct dbih_com_st { /* complete core structure (typedef'd above) */ - dbih_com_std_t std; - dbih_com_attr_t attr; -}; - -/* This 'implementors' type the DBI defines by default as a way to */ -/* refer to the imp_??h data of a handle without considering its type. */ -struct imp_xxh_st { struct dbih_com_st com; }; - -/* Define handle-type specific structures for implementors to include */ -/* at the start of their private structures. */ - -typedef struct { /* -- DRIVER -- */ - dbih_com_std_t std; - dbih_com_attr_t attr; - HV *_old_cached_kids; /* not used, here for binary compat */ -} dbih_drc_t; - -typedef struct { /* -- DATABASE -- */ - dbih_com_std_t std; /* \__ standard structure */ - dbih_com_attr_t attr; /* / plus... (nothing else right now) */ - HV *_old_cached_kids; /* not used, here for binary compat */ -} dbih_dbc_t; - -typedef struct { /* -- STATEMENT -- */ - dbih_com_std_t std; /* \__ standard structure */ - dbih_com_attr_t attr; /* / plus ... */ - - int num_params; /* number of placeholders */ - int num_fields; /* NUM_OF_FIELDS, must be set */ - AV *fields_svav; /* special row buffer (inc bind_cols) */ - IV row_count; /* incremented by get_fbav() */ - - AV *fields_fdav; /* not used yet, may change */ - - I32 spare1; - void *spare2; -} dbih_stc_t; - - -/* XXX THIS STRUCTURE SHOULD NOT BE USED */ -typedef struct { /* -- FIELD DESCRIPTOR -- */ - dbih_com_std_t std; /* standard structure (not fully setup) */ - - /* core attributes (from DescribeCol in ODBC) */ - char *col_name; /* see dbih_make_fdsv */ - I16 col_name_len; - I16 col_sql_type; - I16 col_precision; - I16 col_scale; - I16 col_nullable; - - /* additional attributes (from ColAttributes in ODBC) */ - I32 col_length; - I32 col_disp_size; - - I32 spare1; - void *spare2; -} dbih_fdc_t; - - -#define _imp2com(p,f) ((p)->com.f) /* private */ - -#define DBIc_FLAGS(imp) _imp2com(imp, std.flags) -#define DBIc_TYPE(imp) _imp2com(imp, std.type) -#define DBIc_CALL_DEPTH(imp) _imp2com(imp, std.call_depth) -#define DBIc_MY_H(imp) _imp2com(imp, std.my_h) -#define DBIc_PARENT_H(imp) _imp2com(imp, std.parent_h) -#define DBIc_PARENT_COM(imp) _imp2com(imp, std.parent_com) -#define DBIc_THR_COND(imp) _imp2com(imp, std.thr_cond) -#define DBIc_THR_USER(imp) _imp2com(imp, std.thr_user) -#define DBIc_THR_USER_NONE (0xFFFF) -#define DBIc_IMP_STASH(imp) _imp2com(imp, std.imp_stash) -#define DBIc_IMP_DATA(imp) _imp2com(imp, std.imp_data) -#define DBIc_DBISTATE(imp) _imp2com(imp, std.dbistate) -#define DBIc_LOGPIO(imp) DBIc_DBISTATE(imp)->logfp -#define DBIc_KIDS(imp) _imp2com(imp, std.kids) -#define DBIc_ACTIVE_KIDS(imp) _imp2com(imp, std.active_kids) -#define DBIc_LAST_METHOD(imp) _imp2com(imp, std.last_method) - -/* d = DBD flags, l = DBD level (needs to be shifted down) - * D - DBI flags, r = reserved, L = DBI trace level - * Trace level bit allocation: 0xddlDDDrL */ -#define DBIc_TRACE_LEVEL_MASK 0x0000000F -#define DBIc_TRACE_FLAGS_MASK 0xFF0FFF00 /* includes DBD flag bits for DBIc_TRACE */ -#define DBIc_TRACE_SETTINGS(imp) (DBIc_DBISTATE(imp)->debug) -#define DBIc_TRACE_LEVEL(imp) (DBIc_TRACE_SETTINGS(imp) & DBIc_TRACE_LEVEL_MASK) -#define DBIc_TRACE_FLAGS(imp) (DBIc_TRACE_SETTINGS(imp) & DBIc_TRACE_FLAGS_MASK) -/* DBI defined trace flags */ -#define DBIf_TRACE_SQL 0x00000100 -#define DBIf_TRACE_CON 0x00000200 -#define DBIf_TRACE_ENC 0x00000400 -#define DBIf_TRACE_DBD 0x00000800 -#define DBIf_TRACE_TXN 0x00001000 - -#define DBDc_TRACE_LEVEL_MASK 0x00F00000 -#define DBDc_TRACE_LEVEL_SHIFT 20 -#define DBDc_TRACE_LEVEL(imp) ( (DBIc_TRACE_SETTINGS(imp) & DBDc_TRACE_LEVEL_MASK) >> DBDc_TRACE_LEVEL_SHIFT ) -#define DBDc_TRACE_LEVEL_set(imp, l) ( DBIc_TRACE_SETTINGS(imp) |= (((l) << DBDc_TRACE_LEVEL_SHIFT) & DBDc_TRACE_LEVEL_MASK )) - -/* DBIc_TRACE_MATCHES(this, crnt): true if this 'matches' (is within) crnt - DBIc_TRACE_MATCHES(foo, DBIc_TRACE_SETTINGS(imp)) -*/ -#define DBIc_TRACE_MATCHES(this, crnt) \ - ( ((crnt & DBIc_TRACE_LEVEL_MASK) >= (this & DBIc_TRACE_LEVEL_MASK)) \ - || ((crnt & DBIc_TRACE_FLAGS_MASK) & (this & DBIc_TRACE_FLAGS_MASK)) ) - -/* DBIc_TRACE(imp, flags, flag_level, fallback_level) - True if flags match the handle trace flags & handle trace level >= flag_level, - OR if handle trace_level > fallback_level (typically > flag_level). - This is the main trace testing macro to be used by drivers. - (Drivers should define their own DBDf_TRACE_* macros for the top 8 bits: 0xFF000000) - DBIc_TRACE(imp, 0, 0, 4) = if trace level >= 4 - DBIc_TRACE(imp, DBDf_TRACE_FOO, 2, 4) = if tracing DBDf_FOO & level>=2 or level>=4 - DBIc_TRACE(imp, DBDf_TRACE_FOO, 2, 0) = as above but never trace just due to level - e.g. - if (DBIc_TRACE(imp_xxh, DBIf_TRACE_SQL|DBIf_TRACE_xxx, 2, 0)) { - PerlIO_printf(DBIc_LOGPIO(imp_sth), "\tThe %s wibbled the %s\n", ...); - } -*/ -#define DBIc_TRACE(imp, flags, flaglevel, level) \ - ( (flags && (DBIc_TRACE_FLAGS(imp) & flags) && (DBIc_TRACE_LEVEL(imp) >= flaglevel)) \ - || (level && DBIc_TRACE_LEVEL(imp) >= level) ) - -#define DBIc_DEBUG(imp) (_imp2com(imp, attr.TraceLevel)) /* deprecated */ -#define DBIc_DEBUGIV(imp) SvIV(DBIc_DEBUG(imp)) /* deprecated */ -#define DBIc_STATE(imp) SvRV(_imp2com(imp, attr.State)) -#define DBIc_ERR(imp) SvRV(_imp2com(imp, attr.Err)) -#define DBIc_ERRSTR(imp) SvRV(_imp2com(imp, attr.Errstr)) -#define DBIc_ErrCount(imp) _imp2com(imp, attr.ErrCount) -#define DBIc_LongReadLen(imp) _imp2com(imp, attr.LongReadLen) -#define DBIc_LongReadLen_init 80 /* may change */ -#define DBIc_FetchHashKeyName(imp) (_imp2com(imp, attr.FetchHashKeyName)) - -/* handle sub-type specific fields */ -/* dbh & drh */ -#define DBIc_CACHED_KIDS(imp) Nullhv /* no longer used, here for src compat */ -/* sth */ -#define DBIc_NUM_FIELDS(imp) _imp2com(imp, num_fields) -#define DBIc_NUM_PARAMS(imp) _imp2com(imp, num_params) -#define DBIc_NUM_PARAMS_AT_EXECUTE -9 /* see Driver.xst */ -#define DBIc_ROW_COUNT(imp) _imp2com(imp, row_count) -#define DBIc_FIELDS_AV(imp) _imp2com(imp, fields_svav) -#define DBIc_FDESC_AV(imp) _imp2com(imp, fields_fdav) -#define DBIc_FDESC(imp, i) ((imp_fdh_t*)(void*)SvPVX(AvARRAY(DBIc_FDESC_AV(imp))[i])) - -/* XXX --- DO NOT CHANGE THESE VALUES AS THEY ARE COMPILED INTO DRIVERS --- XXX */ -#define DBIcf_COMSET 0x000001 /* needs to be clear'd before free'd */ -#define DBIcf_IMPSET 0x000002 /* has implementor data to be clear'd */ -#define DBIcf_ACTIVE 0x000004 /* needs finish/disconnect before clear */ -#define DBIcf_IADESTROY 0x000008 /* do DBIc_ACTIVE_off before DESTROY */ -#define DBIcf_WARN 0x000010 /* warn about poor practice etc */ -#define DBIcf_COMPAT 0x000020 /* compat/emulation mode (eg oraperl) */ -#define DBIcf_ChopBlanks 0x000040 /* rtrim spaces from fetch char columns */ -#define DBIcf_RaiseError 0x000080 /* throw exception (croak) on error */ -#define DBIcf_PrintError 0x000100 /* warn() on error */ -#define DBIcf_AutoCommit 0x000200 /* dbh only. used by drivers */ -#define DBIcf_LongTruncOk 0x000400 /* truncation to LongReadLen is okay */ -#define DBIcf_MultiThread 0x000800 /* allow multiple threads to enter */ -#define DBIcf_HandleSetErr 0x001000 /* has coderef HandleSetErr attribute */ -#define DBIcf_ShowErrorStatement 0x002000 /* include Statement in error */ -#define DBIcf_BegunWork 0x004000 /* between begin_work & commit/rollback */ -#define DBIcf_HandleError 0x008000 /* has coderef in HandleError attribute */ -#define DBIcf_Profile 0x010000 /* profile activity on this handle */ -#define DBIcf_TaintIn 0x020000 /* check inputs for taintedness */ -#define DBIcf_TaintOut 0x040000 /* taint outgoing data */ -#define DBIcf_Executed 0x080000 /* do/execute called since commit/rollb */ -#define DBIcf_PrintWarn 0x100000 /* warn() on warning (err="0") */ -#define DBIcf_Callbacks 0x200000 /* has Callbacks attribute hash */ -#define DBIcf_AIADESTROY 0x400000 /* auto DBIcf_IADESTROY if pid changes */ -/* NOTE: new flags may require clone() to be updated */ - -#define DBIcf_INHERITMASK /* what NOT to pass on to children */ \ - (U32)( DBIcf_COMSET | DBIcf_IMPSET | DBIcf_ACTIVE | DBIcf_IADESTROY \ - | DBIcf_AutoCommit | DBIcf_BegunWork | DBIcf_Executed | DBIcf_Callbacks ) - -/* general purpose bit setting and testing macros */ -#define DBIbf_is( bitset,flag) ((bitset) & (flag)) -#define DBIbf_has(bitset,flag) DBIbf_is(bitset, flag) /* alias for _is */ -#define DBIbf_on( bitset,flag) ((bitset) |= (flag)) -#define DBIbf_off(bitset,flag) ((bitset) &= ~(flag)) -#define DBIbf_set(bitset,flag,on) ((on) ? DBIbf_on(bitset, flag) : DBIbf_off(bitset,flag)) - -/* as above, but specifically for DBIc_FLAGS imp flags (except ACTIVE) */ -#define DBIc_is(imp, flag) DBIbf_is( DBIc_FLAGS(imp), flag) -#define DBIc_has(imp,flag) DBIc_is(imp, flag) /* alias for DBIc_is */ -#define DBIc_on(imp, flag) DBIbf_on( DBIc_FLAGS(imp), flag) -#define DBIc_off(imp,flag) DBIbf_off(DBIc_FLAGS(imp), flag) -#define DBIc_set(imp,flag,on) DBIbf_set(DBIc_FLAGS(imp), flag, on) - -#define DBIc_COMSET(imp) DBIc_is(imp, DBIcf_COMSET) -#define DBIc_COMSET_on(imp) DBIc_on(imp, DBIcf_COMSET) -#define DBIc_COMSET_off(imp) DBIc_off(imp,DBIcf_COMSET) - -#define DBIc_IMPSET(imp) DBIc_is(imp, DBIcf_IMPSET) -#define DBIc_IMPSET_on(imp) DBIc_on(imp, DBIcf_IMPSET) -#define DBIc_IMPSET_off(imp) DBIc_off(imp,DBIcf_IMPSET) - -#define DBIc_ACTIVE(imp) (DBIc_FLAGS(imp) & DBIcf_ACTIVE) -#define DBIc_ACTIVE_on(imp) /* adjust parent's active kid count */ \ - do { \ - imp_xxh_t *ph_com = DBIc_PARENT_COM(imp); \ - if (!DBIc_ACTIVE(imp) && ph_com && !PL_dirty \ - && ++DBIc_ACTIVE_KIDS(ph_com) > DBIc_KIDS(ph_com)) \ - croak("panic: DBI active kids (%ld) > kids (%ld)", \ - (long)DBIc_ACTIVE_KIDS(ph_com), \ - (long)DBIc_KIDS(ph_com)); \ - DBIc_FLAGS(imp) |= DBIcf_ACTIVE; \ - } while(0) -#define DBIc_ACTIVE_off(imp) /* adjust parent's active kid count */ \ - do { \ - imp_xxh_t *ph_com = DBIc_PARENT_COM(imp); \ - if (DBIc_ACTIVE(imp) && ph_com && !PL_dirty \ - && (--DBIc_ACTIVE_KIDS(ph_com) > DBIc_KIDS(ph_com) \ - || DBIc_ACTIVE_KIDS(ph_com) < 0) ) \ - croak("panic: DBI active kids (%ld) < 0 or > kids (%ld)", \ - (long)DBIc_ACTIVE_KIDS(ph_com), \ - (long)DBIc_KIDS(ph_com)); \ - DBIc_FLAGS(imp) &= ~DBIcf_ACTIVE; \ - } while(0) - -#define DBIc_IADESTROY(imp) (DBIc_FLAGS(imp) & DBIcf_IADESTROY) -#define DBIc_IADESTROY_on(imp) (DBIc_FLAGS(imp) |= DBIcf_IADESTROY) -#define DBIc_IADESTROY_off(imp) (DBIc_FLAGS(imp) &= ~DBIcf_IADESTROY) - -#define DBIc_AIADESTROY(imp) (DBIc_FLAGS(imp) & DBIcf_AIADESTROY) -#define DBIc_AIADESTROY_on(imp) (DBIc_FLAGS(imp) |= DBIcf_AIADESTROY) -#define DBIc_AIADESTROY_off(imp) (DBIc_FLAGS(imp) &= ~DBIcf_AIADESTROY) - -#define DBIc_WARN(imp) (DBIc_FLAGS(imp) & DBIcf_WARN) -#define DBIc_WARN_on(imp) (DBIc_FLAGS(imp) |= DBIcf_WARN) -#define DBIc_WARN_off(imp) (DBIc_FLAGS(imp) &= ~DBIcf_WARN) - -#define DBIc_COMPAT(imp) (DBIc_FLAGS(imp) & DBIcf_COMPAT) -#define DBIc_COMPAT_on(imp) (DBIc_FLAGS(imp) |= DBIcf_COMPAT) -#define DBIc_COMPAT_off(imp) (DBIc_FLAGS(imp) &= ~DBIcf_COMPAT) - - -#ifdef IN_DBI_XS /* get Handle Common Data Structure */ -#define DBIh_COM(h) (dbih_getcom2(aTHX_ h, 0)) -#else -#define DBIh_COM(h) (DBIS->getcom(h)) -#define neatsvpv(sv,len) (DBIS->neat_svpv(sv,len)) -#endif - -/* --- For sql_type_cast_svpv() --- */ - -#define DBIstcf_DISCARD_STRING 0x0001 -#define DBIstcf_STRICT 0x0002 - -/* --- Implementors Private Data Support --- */ - -#define D_impdata(name,type,h) type *name = (type*)(DBIh_COM(h)) -#define D_imp_drh(h) D_impdata(imp_drh, imp_drh_t, h) -#define D_imp_dbh(h) D_impdata(imp_dbh, imp_dbh_t, h) -#define D_imp_sth(h) D_impdata(imp_sth, imp_sth_t, h) -#define D_imp_xxh(h) D_impdata(imp_xxh, imp_xxh_t, h) - -#define D_imp_from_child(name,type,child) \ - type *name = (type*)(DBIc_PARENT_COM(child)) -#define D_imp_drh_from_dbh D_imp_from_child(imp_drh, imp_drh_t, imp_dbh) -#define D_imp_dbh_from_sth D_imp_from_child(imp_dbh, imp_dbh_t, imp_sth) - -#define DBI_IMP_SIZE(n,s) sv_setiv(get_sv((n), GV_ADDMULTI), (s)) /* XXX */ - - - -/* --- Event Support (VERY LIABLE TO CHANGE) --- */ - -#define DBIh_EVENTx(h,t,a1,a2) /* deprecated XXX */ &PL_sv_no -#define DBIh_EVENT0(h,t) DBIh_EVENTx((h), (t), &PL_sv_undef, &PL_sv_undef) -#define DBIh_EVENT1(h,t, a1) DBIh_EVENTx((h), (t), (a1), &PL_sv_undef) -#define DBIh_EVENT2(h,t, a1,a2) DBIh_EVENTx((h), (t), (a1), (a2)) - -#define ERROR_event "ERROR" -#define WARN_event "WARN" -#define MSG_event "MESSAGE" -#define DBEVENT_event "DBEVENT" -#define UNKNOWN_event "UNKNOWN" - -#define DBIh_SET_ERR_SV(h,i, err, errstr, state, method) \ - (DBIc_DBISTATE(i)->set_err_sv(h,i, err, errstr, state, method)) -#define DBIh_SET_ERR_CHAR(h,i, err_c, err_i, errstr, state, method) \ - (DBIc_DBISTATE(i)->set_err_char(h,i, err_c, err_i, errstr, state, method)) - - -/* --- Handy Macros --- */ - -#define DBIh_CLEAR_ERROR(imp_xxh) (void)( \ - (void)SvOK_off(DBIc_ERR(imp_xxh)), \ - (void)SvOK_off(DBIc_ERRSTR(imp_xxh)), \ - (void)SvOK_off(DBIc_STATE(imp_xxh)) \ - ) - - -/* --- DBI State Structure --- */ - -struct dbistate_st { - -/* DBISTATE_VERSION is checked at runtime via DBISTATE_INIT and check_version. - * It should be incremented on incompatible changes to dbistate_t structure. - * Additional function pointers being assigned from spare padding, where the - * size of the structure doesn't change, doesn't require an increment. - * Incrementing forces all XS drivers to need to be recompiled. - * (See also DBIXS_REVISION as a driver source compatibility tool.) - */ -#define DBISTATE_VERSION 94 /* ++ on incompatible dbistate_t changes */ - - /* this must be the first member in structure */ - void (*check_version) _((const char *name, - int dbis_cv, int dbis_cs, int need_dbixs_cv, - int drc_s, int dbc_s, int stc_s, int fdc_s)); - - /* version and size are used to check for DBI/DBD version mis-match */ - U16 version; /* version of this structure */ - U16 size; - U16 xs_version; /* version of the overall DBIXS / DBD interface */ - U16 spare_pad; - - I32 debug; - PerlIO *logfp; - - /* pointers to DBI functions which the DBD's will want to use */ - char * (*neat_svpv) _((SV *sv, STRLEN maxlen)); - imp_xxh_t * (*getcom) _((SV *h)); /* see DBIh_COM macro */ - void (*clearcom) _((imp_xxh_t *imp_xxh)); - SV * (*event) _((SV *h, const char *name, SV*, SV*)); - int (*set_attr_k) _((SV *h, SV *keysv, int dbikey, SV *valuesv)); - SV * (*get_attr_k) _((SV *h, SV *keysv, int dbikey)); - AV * (*get_fbav) _((imp_sth_t *imp_sth)); - SV * (*make_fdsv) _((SV *sth, const char *imp_class, STRLEN imp_size, const char *col_name)); - int (*bind_as_num) _((int sql_type, int p, int s, int *t, void *v)); /* XXX deprecated */ - I32 (*hash) _((const char *string, long i)); - SV * (*preparse) _((SV *sth, char *statement, IV ps_return, IV ps_accept, void *foo)); - - SV *neatsvpvlen; /* only show dbgpvlen chars when debugging pv's */ - - PerlInterpreter * thr_owner; /* thread that owns this dbistate */ - - int (*logmsg) _((imp_xxh_t *imp_xxh, const char *fmt, ...)); - int (*set_err_sv) _((SV *h, imp_xxh_t *imp_xxh, SV *err, SV *errstr, SV *state, SV *method)); - int (*set_err_char) _((SV *h, imp_xxh_t *imp_xxh, const char *err, IV err_i, const char *errstr, const char *state, const char *method)); - int (*bind_col) _((SV *sth, SV *col, SV *ref, SV *attribs)); - - IO *logfp_ref; /* keep ptr to filehandle for refcounting */ - - int (*sql_type_cast_svpv) _((pTHX_ SV *sv, int sql_type, U32 flags, void *v)); - - /* WARNING: Only add new structure members here, and reduce pad2 to keep */ - /* the memory footprint exactly the same */ - void *pad2[3]; -}; - -/* macros for backwards compatibility */ -#define set_attr(h, k, v) set_attr_k(h, k, 0, v) -#define get_attr(h, k) get_attr_k(h, k, 0) - -#define DBILOGFP (DBIS->logfp) -#ifdef IN_DBI_XS -#define DBILOGMSG (dbih_logmsg) -#else -#define DBILOGMSG (DBIS->logmsg) -#endif - -/* --- perl object (ActiveState) / multiplicity hooks and hoops --- */ -/* note that USE_ITHREADS implies MULTIPLICITY */ - -typedef dbistate_t** (*_dbi_state_lval_t)(pTHX); - -# define _DBISTATE_DECLARE_COMMON \ - static _dbi_state_lval_t dbi_state_lval_p = 0; \ - static dbistate_t** dbi_get_state(pTHX) { \ - if (!dbi_state_lval_p) { \ - CV *cv = get_cv("DBI::_dbi_state_lval", 0); \ - if (!cv) \ - croak("Unable to get DBI state function. DBI not loaded."); \ - dbi_state_lval_p = (_dbi_state_lval_t)CvXSUB(cv); \ - } \ - return dbi_state_lval_p(aTHX); \ - } \ - typedef int dummy_dbistate /* keep semicolon from feeling lonely */ - -#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || defined(PERL_CAPI) - -# define DBISTATE_DECLARE _DBISTATE_DECLARE_COMMON -# define _DBISTATE_INIT_DBIS -# undef DBIS -# define DBIS (*dbi_get_state(aTHX)) -# define dbis DBIS /* temp for old drivers using 'dbis' instead of 'DBIS' */ - -#else /* plain and simple non perl object / multiplicity case */ - -# define DBISTATE_DECLARE \ - static dbistate_t *DBIS; \ - _DBISTATE_DECLARE_COMMON - -# define _DBISTATE_INIT_DBIS DBIS = *dbi_get_state(aTHX); -#endif - -# define DBISTATE_INIT { /* typically use in BOOT: of XS file */ \ - _DBISTATE_INIT_DBIS \ - if (DBIS == NULL) \ - croak("Unable to get DBI state. DBI not loaded."); \ - DBIS->check_version(__FILE__, DBISTATE_VERSION, sizeof(*DBIS), NEED_DBIXS_VERSION, \ - sizeof(dbih_drc_t), sizeof(dbih_dbc_t), sizeof(dbih_stc_t), sizeof(dbih_fdc_t) \ - ); \ -} - - -/* --- Assorted Utility Macros --- */ - -#define DBD_ATTRIB_OK(attribs) /* is this a usable attrib value */ \ - (attribs && SvROK(attribs) && SvTYPE(SvRV(attribs))==SVt_PVHV) - -/* If attribs value supplied then croak if it's not a hash ref. */ -/* Also map undef to Null. Should always be called to pre-process the */ -/* attribs value. One day we may add some extra magic in here. */ -#define DBD_ATTRIBS_CHECK(func, h, attribs) \ - if ((attribs) && SvOK(attribs)) { \ - if (!SvROK(attribs) || SvTYPE(SvRV(attribs))!=SVt_PVHV) \ - croak("%s->%s(...): attribute parameter '%s' is not a hash ref", \ - SvPV_nolen(h), func, SvPV_nolen(attribs)); \ - } else (attribs) = Nullsv - -#define DBD_ATTRIB_GET_SVP(attribs, key,klen) \ - (DBD_ATTRIB_OK(attribs) \ - ? hv_fetch((HV*)SvRV(attribs), key,klen, 0) \ - : (SV **)Nullsv) - -#define DBD_ATTRIB_GET_IV(attribs, key,klen, svp, var) \ - if ((svp=DBD_ATTRIB_GET_SVP(attribs, key,klen)) != NULL) \ - var = SvIV(*svp) - -#define DBD_ATTRIB_GET_UV(attribs, key,klen, svp, var) \ - if ((svp=DBD_ATTRIB_GET_SVP(attribs, key,klen)) != NULL) \ - var = SvUV(*svp) - -#define DBD_ATTRIB_GET_BOOL(attribs, key,klen, svp, var) \ - if ((svp=DBD_ATTRIB_GET_SVP(attribs, key,klen)) != NULL) \ - var = SvTRUE(*svp) - -#define DBD_ATTRIB_TRUE(attribs, key,klen, svp) \ - ( ((svp=DBD_ATTRIB_GET_SVP(attribs, key,klen)) != NULL) \ - ? SvTRUE(*svp) : 0 ) - -#define DBD_ATTRIB_GET_PV(attribs, key,klen, svp, dflt) \ - (((svp=DBD_ATTRIB_GET_SVP(attribs, key,klen)) != NULL) \ - ? SvPV_nolen(*svp) : (dflt)) - -#define DBD_ATTRIB_DELETE(attribs, key, klen) \ - hv_delete((HV*)SvRV(attribs), key, klen, G_DISCARD) - -#endif /* DBIXS_VERSION */ -/* end of DBIXS.h */ diff --git a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/Driver.xst b/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/Driver.xst deleted file mode 100644 index 6afe80e..0000000 --- a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/Driver.xst +++ /dev/null @@ -1,804 +0,0 @@ -# $Id$ -# Copyright (c) 1997-2002 Tim Bunce Ireland -# Copyright (c) 2002 Jonathan Leffler -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - -#include "Driver_xst.h" - -# Historically dbd_db_do4, dbd_st_execute, and dbd_st_rows returned an 'int' type. -# That's only 32 bits (31+sign) so isn't sufficient for very large row counts -# So now instead of defining those macros, drivers can define dbd_db_do4_iv, -# dbd_st_execute_iv, and dbd_st_rows_iv to be the names of functions that -# return an 'IV' type. They could also set DBIc_ROW_COUNT(imp_sth). -# -# To save a mess of #ifdef's we arrange for dbd_st_execute (etc) to work -# as dbd_st_execute_iv if that's defined -# -#if defined(dbd_st_execute_iv) -#undef dbd_st_execute -#define dbd_st_execute dbd_st_execute_iv -#endif -#if defined(dbd_st_rows_iv) -#undef dbd_st_rows -#define dbd_st_rows dbd_st_rows_iv -#endif -#if defined(dbd_db_do4_iv) -#undef dbd_db_do4 -#define dbd_db_do4 dbd_db_do4_iv -#endif - -MODULE = DBD::~DRIVER~ PACKAGE = DBD::~DRIVER~ - -REQUIRE: 1.929 -PROTOTYPES: DISABLE - -BOOT: - PERL_UNUSED_VAR(items); - DBISTATE_INIT; - /* XXX this interface will change: */ - DBI_IMP_SIZE("DBD::~DRIVER~::dr::imp_data_size", sizeof(imp_drh_t)); - DBI_IMP_SIZE("DBD::~DRIVER~::db::imp_data_size", sizeof(imp_dbh_t)); - DBI_IMP_SIZE("DBD::~DRIVER~::st::imp_data_size", sizeof(imp_sth_t)); - dbd_init(DBIS); - - -# ------------------------------------------------------------ -# driver level interface -# ------------------------------------------------------------ -MODULE = DBD::~DRIVER~ PACKAGE = DBD::~DRIVER~::dr - - -void -dbixs_revision(...) - PPCODE: - ST(0) = sv_2mortal(newSViv(DBIXS_REVISION)); - - -#ifdef dbd_discon_all - -# disconnect_all renamed and ALIAS'd to avoid length clash on VMS :-( -void -discon_all_(drh) - SV * drh - ALIAS: - disconnect_all = 1 - CODE: - D_imp_drh(drh); - PERL_UNUSED_VAR(ix); - ST(0) = dbd_discon_all(drh, imp_drh) ? &PL_sv_yes : &PL_sv_no; - -#endif /* dbd_discon_all */ - - -#ifdef dbd_dr_data_sources - -void -data_sources(drh, attr = Nullsv) - SV *drh - SV *attr - PPCODE: - { - D_imp_drh(drh); - AV *av = dbd_dr_data_sources(drh, imp_drh, attr); - if (av) { - int i; - int n = AvFILL(av)+1; - EXTEND(sp, n); - for (i = 0; i < n; ++i) { - PUSHs(AvARRAY(av)[i]); - } - } - } - -#endif - - -# ------------------------------------------------------------ -# database level interface -# ------------------------------------------------------------ -MODULE = DBD::~DRIVER~ PACKAGE = DBD::~DRIVER~::db - - -void -_login(dbh, dbname, username, password, attribs=Nullsv) - SV * dbh - SV * dbname - SV * username - SV * password - SV * attribs - CODE: - { - D_imp_dbh(dbh); -#if !defined(dbd_db_login6_sv) - STRLEN lna; - char *u = (SvOK(username)) ? SvPV(username,lna) : (char*)""; - char *p = (SvOK(password)) ? SvPV(password,lna) : (char*)""; -#endif -#ifdef dbd_db_login6_sv - ST(0) = dbd_db_login6_sv(dbh, imp_dbh, dbname, username, password, attribs) ? &PL_sv_yes : &PL_sv_no; -#elif defined(dbd_db_login6) - ST(0) = dbd_db_login6(dbh, imp_dbh, SvPV_nolen(dbname), u, p, attribs) ? &PL_sv_yes : &PL_sv_no; -#else - PERL_UNUSED_ARG(attribs); - ST(0) = dbd_db_login( dbh, imp_dbh, SvPV_nolen(dbname), u, p) ? &PL_sv_yes : &PL_sv_no; -#endif - } - - -void -selectall_arrayref(...) - PREINIT: - SV *sth; - SV **maxrows_svp; - SV **tmp_svp; - SV *tmp_sv; - SV *attr = &PL_sv_undef; - imp_sth_t *imp_sth; - CODE: - if (items > 2) { - attr = ST(2); - if (SvROK(attr) && - (DBD_ATTRIB_TRUE(attr,"Slice",5,tmp_svp) || DBD_ATTRIB_TRUE(attr,"Columns",7,tmp_svp)) - ) { - /* fallback to perl implementation */ - SV *tmp =dbixst_bounce_method("DBD::~DRIVER~::db::SUPER::selectall_arrayref", items); - SPAGAIN; - ST(0) = tmp; - XSRETURN(1); - } - } - /* --- prepare --- */ - if (SvROK(ST(1))) { - MAGIC *mg; - sth = ST(1); - /* switch to inner handle if not already */ - if ( (mg = mg_find(SvRV(sth),'P')) ) - sth = mg->mg_obj; - } - else { - sth = dbixst_bounce_method("prepare", 3); - SPAGAIN; SP -= items; /* because stack might have been realloc'd */ - if (!SvROK(sth)) - XSRETURN_UNDEF; - /* switch to inner handle */ - sth = mg_find(SvRV(sth),'P')->mg_obj; - } - imp_sth = (imp_sth_t*)(DBIh_COM(sth)); - /* --- bind_param --- */ - if (items > 3) { /* need to bind params before execute */ - if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) { - XSRETURN_UNDEF; - } - } - /* --- execute --- */ - DBIc_ROW_COUNT(imp_sth) = 0; - if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */ - XSRETURN_UNDEF; - } - /* --- fetchall --- */ - maxrows_svp = DBD_ATTRIB_GET_SVP(attr, "MaxRows", 7); - tmp_sv = dbdxst_fetchall_arrayref(sth, &PL_sv_undef, (maxrows_svp) ? *maxrows_svp : &PL_sv_undef); - SPAGAIN; - ST(0) = tmp_sv; - - -void -selectrow_arrayref(...) - ALIAS: - selectrow_array = 1 - PREINIT: - int is_selectrow_array = (ix == 1); - imp_sth_t *imp_sth; - SV *sth; - AV *row_av; - PPCODE: - if (SvROK(ST(1))) { - MAGIC *mg; - sth = ST(1); - /* switch to inner handle if not already */ - if ( (mg = mg_find(SvRV(sth),'P')) ) - sth = mg->mg_obj; - } - else { - /* --- prepare --- */ - sth = dbixst_bounce_method("prepare", 3); - SPAGAIN; SP -= items; /* because stack might have been realloc'd */ - if (!SvROK(sth)) { - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - /* switch to inner handle */ - sth = mg_find(SvRV(sth),'P')->mg_obj; - } - imp_sth = (imp_sth_t*)(DBIh_COM(sth)); - /* --- bind_param --- */ - if (items > 3) { /* need to bind params before execute */ - if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2) ) { - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - } - /* --- execute --- */ - DBIc_ROW_COUNT(imp_sth) = 0; - if ( dbd_st_execute(sth, imp_sth) <= -2 ) { /* -2 == error */ - if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; } - } - /* --- fetchrow_arrayref --- */ - row_av = dbd_st_fetch(sth, imp_sth); - if (!row_av) { - if (GIMME == G_SCALAR) - PUSHs(&PL_sv_undef); - } - else if (is_selectrow_array) { - int i; - int num_fields = AvFILL(row_av)+1; - if (GIMME == G_SCALAR) - num_fields = 1; /* return just first field */ - EXTEND(sp, num_fields); - for(i=0; i < num_fields; ++i) { - PUSHs(AvARRAY(row_av)[i]); - } - } - else { - PUSHs( sv_2mortal(newRV((SV *)row_av)) ); - } - /* --- finish --- */ -#ifdef dbd_st_finish3 - dbd_st_finish3(sth, imp_sth, 0); -#else - dbd_st_finish(sth, imp_sth); -#endif - - -#ifdef dbd_db_do4 /* deebeedee-deebee-doo, deebee-doobee-dah? */ - -void -do(dbh, statement, params = Nullsv) - SV * dbh - char * statement - SV * params - CODE: - { - D_imp_dbh(dbh); - IV retval; - retval = dbd_db_do4(dbh, imp_dbh, statement, params); /* might be dbd_db_do4_iv via macro */ - /* remember that dbd_db_do4 must return <= -2 for error */ - if (retval == 0) /* ok with no rows affected */ - XST_mPV(0, "0E0"); /* (true but zero) */ - else if (retval < -1) /* -1 == unknown number of rows */ - XST_mUNDEF(0); /* <= -2 means error */ - else - XST_mIV(0, retval); /* typically 1, rowcount or -1 */ - } - -#endif - - -#ifdef dbd_db_last_insert_id - -void -last_insert_id(dbh, catalog, schema, table, field, attr=Nullsv) - SV * dbh - SV * catalog - SV * schema - SV * table - SV * field - SV * attr - CODE: - { - D_imp_dbh(dbh); - ST(0) = dbd_db_last_insert_id(dbh, imp_dbh, catalog, schema, table, field, attr); - } - -#endif - - -void -commit(dbh) - SV * dbh - CODE: - D_imp_dbh(dbh); - if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh)) - warn("commit ineffective with AutoCommit enabled"); - ST(0) = dbd_db_commit(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; - - -void -rollback(dbh) - SV * dbh - CODE: - D_imp_dbh(dbh); - if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh)) - warn("rollback ineffective with AutoCommit enabled"); - ST(0) = dbd_db_rollback(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; - - -void -disconnect(dbh) - SV * dbh - CODE: - D_imp_dbh(dbh); - if ( !DBIc_ACTIVE(imp_dbh) ) { - XSRETURN_YES; - } - /* Check for disconnect() being called whilst refs to cursors */ - /* still exists. This possibly needs some more thought. */ - if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !PL_dirty) { - STRLEN lna; - char *plural = (DBIc_ACTIVE_KIDS(imp_dbh)==1) ? (char*)"" : (char*)"s"; - warn("%s->disconnect invalidates %d active statement handle%s %s", - SvPV(dbh,lna), (int)DBIc_ACTIVE_KIDS(imp_dbh), plural, - "(either destroy statement handles or call finish on them before disconnecting)"); - } - ST(0) = dbd_db_disconnect(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no; - DBIc_ACTIVE_off(imp_dbh); /* ensure it's off, regardless */ - - -void -STORE(dbh, keysv, valuesv) - SV * dbh - SV * keysv - SV * valuesv - CODE: - D_imp_dbh(dbh); - if (SvGMAGICAL(valuesv)) - mg_get(valuesv); - ST(0) = &PL_sv_yes; - if (!dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv)) - if (!DBIc_DBISTATE(imp_dbh)->set_attr(dbh, keysv, valuesv)) - ST(0) = &PL_sv_no; - - -void -FETCH(dbh, keysv) - SV * dbh - SV * keysv - CODE: - D_imp_dbh(dbh); - SV *valuesv = dbd_db_FETCH_attrib(dbh, imp_dbh, keysv); - if (!valuesv) - valuesv = DBIc_DBISTATE(imp_dbh)->get_attr(dbh, keysv); - ST(0) = valuesv; /* dbd_db_FETCH_attrib did sv_2mortal */ - - -void -DESTROY(dbh) - SV * dbh - PPCODE: - /* keep in sync with default DESTROY in DBI.xs */ - D_imp_dbh(dbh); - ST(0) = &PL_sv_yes; - if (!DBIc_IMPSET(imp_dbh)) { /* was never fully set up */ - STRLEN lna; - if (DBIc_WARN(imp_dbh) && !PL_dirty && DBIc_DBISTATE(imp_dbh)->debug >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), - " DESTROY for %s ignored - handle not initialised\n", - SvPV(dbh,lna)); - } - else { - if (DBIc_IADESTROY(imp_dbh)) { /* wants ineffective destroy */ - DBIc_ACTIVE_off(imp_dbh); - if (DBIc_DBISTATE(imp_dbh)->debug) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), " DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(dbh)); - } - if (DBIc_ACTIVE(imp_dbh)) { - if (!DBIc_has(imp_dbh,DBIcf_AutoCommit)) { - /* Application is using transactions and hasn't explicitly disconnected. - Some databases will automatically commit on graceful disconnect. - Since we're about to gracefully disconnect as part of the DESTROY - we want to be sure we're not about to implicitly commit changes - that are incomplete and should be rolled back. (The DESTROY may - be due to a RaiseError, for example.) So we rollback here. - This will be harmless if the application has issued a commit, - XXX Could add an attribute flag to indicate that the driver - doesn't have this problem. Patches welcome. - */ - if (DBIc_WARN(imp_dbh) /* only warn if likely to be useful... */ - && DBIc_is(imp_dbh, DBIcf_Executed) /* has not just called commit/rollback */ - /* && !DBIc_is(imp_dbh, DBIcf_ReadOnly) -- is not read only */ - && (!PL_dirty || DBIc_DBISTATE(imp_dbh)->debug >= 3) - ) { - warn("Issuing rollback() due to DESTROY without explicit disconnect() of %s handle %s", - SvPV_nolen(*hv_fetch((HV*)SvRV(dbh), "ImplementorClass", 16, 1)), - SvPV_nolen(*hv_fetch((HV*)SvRV(dbh), "Name", 4, 1)) - ); - } - dbd_db_rollback(dbh, imp_dbh); /* ROLLBACK! */ - } - dbd_db_disconnect(dbh, imp_dbh); - DBIc_ACTIVE_off(imp_dbh); /* ensure it's off, regardless */ - } - dbd_db_destroy(dbh, imp_dbh); - } - - -#ifdef dbd_take_imp_data - -void -take_imp_data(h) - SV * h - CODE: - D_imp_xxh(h); - /* dbd_take_imp_data() returns &sv_no (or other defined but false value) - * to indicate "preparations complete, now call SUPER::take_imp_data" for me. - * Anything else is returned to the caller via sv_2mortal(sv), typically that - * would be &sv_undef for error or an SV holding the imp_data. - */ - SV *sv = dbd_take_imp_data(h, imp_xxh, NULL); - if (SvOK(sv) && !SvTRUE(sv)) { - SV *tmp = dbixst_bounce_method("DBD::~DRIVER~::db::SUPER::take_imp_data", items); - SPAGAIN; - ST(0) = tmp; - } else { - ST(0) = sv_2mortal(sv); - } - -#endif - -#ifdef dbd_db_data_sources - -void -data_sources(dbh, attr = Nullsv) - SV *dbh - SV *attr - PPCODE: - { - D_imp_dbh(dbh); - AV *av = dbd_db_data_sources(dbh, imp_dbh, attr); - if (av) { - int i; - int n = AvFILL(av)+1; - EXTEND(sp, n); - for (i = 0; i < n; ++i) { - PUSHs(AvARRAY(av)[i]); - } - } - } - -#endif - -# -- end of DBD::~DRIVER~::db - -# ------------------------------------------------------------ -# statement interface -# ------------------------------------------------------------ -MODULE = DBD::~DRIVER~ PACKAGE = DBD::~DRIVER~::st - - -void -_prepare(sth, statement, attribs=Nullsv) - SV * sth - SV * statement - SV * attribs - CODE: - { - D_imp_sth(sth); - DBD_ATTRIBS_CHECK("_prepare", sth, attribs); -#ifdef dbd_st_prepare_sv - ST(0) = dbd_st_prepare_sv(sth, imp_sth, statement, attribs) ? &PL_sv_yes : &PL_sv_no; -#else - ST(0) = dbd_st_prepare(sth, imp_sth, SvPV_nolen(statement), attribs) ? &PL_sv_yes : &PL_sv_no; -#endif - } - - -#ifdef dbd_st_rows - -void -rows(sth) - SV * sth - CODE: - D_imp_sth(sth); - XST_mIV(0, dbd_st_rows(sth, imp_sth)); - -#endif /* dbd_st_rows */ - - -#ifdef dbd_st_bind_col - -void -bind_col(sth, col, ref, attribs=Nullsv) - SV * sth - SV * col - SV * ref - SV * attribs - CODE: - { - IV sql_type = 0; - D_imp_sth(sth); - if (SvGMAGICAL(ref)) - mg_get(ref); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_col", sth, attribs); - /* XXX we should perhaps complain if TYPE is not SvNIOK */ - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - switch(dbd_st_bind_col(sth, imp_sth, col, ref, sql_type, attribs)) { - case 2: ST(0) = &PL_sv_yes; /* job done completely */ - break; - case 1: /* fallback to DBI default */ - ST(0) = (DBIc_DBISTATE(imp_sth)->bind_col(sth, col, ref, attribs)) - ? &PL_sv_yes : &PL_sv_no; - break; - default: ST(0) = &PL_sv_no; /* dbd_st_bind_col has called set_err */ - break; - } - } - -#endif /* dbd_st_bind_col */ - -void -bind_param(sth, param, value, attribs=Nullsv) - SV * sth - SV * param - SV * value - SV * attribs - CODE: - { - IV sql_type = 0; - D_imp_sth(sth); - if (SvGMAGICAL(value)) - mg_get(value); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_param", sth, attribs); - /* XXX we should perhaps complain if TYPE is not SvNIOK */ - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - ST(0) = dbd_bind_ph(sth, imp_sth, param, value, sql_type, attribs, FALSE, 0) - ? &PL_sv_yes : &PL_sv_no; - } - - -void -bind_param_inout(sth, param, value_ref, maxlen, attribs=Nullsv) - SV * sth - SV * param - SV * value_ref - IV maxlen - SV * attribs - CODE: - { - IV sql_type = 0; - D_imp_sth(sth); - SV *value; - if (!SvROK(value_ref) || SvTYPE(SvRV(value_ref)) > SVt_PVMG) - croak("bind_param_inout needs a reference to a scalar value"); - value = SvRV(value_ref); - if (SvREADONLY(value)) - croak("Modification of a read-only value attempted"); - if (SvGMAGICAL(value)) - mg_get(value); - if (attribs) { - if (SvNIOK(attribs)) { - sql_type = SvIV(attribs); - attribs = Nullsv; - } - else { - SV **svp; - DBD_ATTRIBS_CHECK("bind_param", sth, attribs); - DBD_ATTRIB_GET_IV(attribs, "TYPE",4, svp, sql_type); - } - } - ST(0) = dbd_bind_ph(sth, imp_sth, param, value, sql_type, attribs, TRUE, maxlen) - ? &PL_sv_yes : &PL_sv_no; - } - - -void -execute(sth, ...) - SV * sth - CODE: - D_imp_sth(sth); - IV retval; - if (items > 1) { /* need to bind params */ - if (!dbdxst_bind_params(sth, imp_sth, items, ax) ) { - XSRETURN_UNDEF; - } - } - /* XXX this code is duplicated in selectrow_arrayref above */ - DBIc_ROW_COUNT(imp_sth) = 0; - retval = dbd_st_execute(sth, imp_sth); /* might be dbd_st_execute_iv via macro */ - /* remember that dbd_st_execute must return <= -2 for error */ - if (retval == 0) /* ok with no rows affected */ - XST_mPV(0, "0E0"); /* (true but zero) */ - else if (retval < -1) /* -1 == unknown number of rows */ - XST_mUNDEF(0); /* <= -2 means error */ - else - XST_mIV(0, retval); /* typically 1, rowcount or -1 */ - - -#ifdef dbd_st_execute_for_fetch - -void -execute_for_fetch(sth, fetch_tuple_sub, tuple_status = Nullsv) - SV * sth - SV * fetch_tuple_sub - SV * tuple_status - CODE: - { - D_imp_sth(sth); - ST(0) = dbd_st_execute_for_fetch(sth, imp_sth, fetch_tuple_sub, tuple_status); - } - -#endif - - - -void -fetchrow_arrayref(sth) - SV * sth - ALIAS: - fetch = 1 - CODE: - D_imp_sth(sth); - AV *av; - PERL_UNUSED_VAR(ix); - av = dbd_st_fetch(sth, imp_sth); - ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef; - - -void -fetchrow_array(sth) - SV * sth - ALIAS: - fetchrow = 1 - PPCODE: - D_imp_sth(sth); - AV *av; - av = dbd_st_fetch(sth, imp_sth); - if (av) { - int i; - int num_fields = AvFILL(av)+1; - EXTEND(sp, num_fields); - for(i=0; i < num_fields; ++i) { - PUSHs(AvARRAY(av)[i]); - } - PERL_UNUSED_VAR(ix); - } - - -void -fetchall_arrayref(sth, slice=&PL_sv_undef, batch_row_count=&PL_sv_undef) - SV * sth - SV * slice - SV * batch_row_count - CODE: - if (SvOK(slice)) { /* fallback to perl implementation */ - SV *tmp = dbixst_bounce_method("DBD::~DRIVER~::st::SUPER::fetchall_arrayref", 3); - SPAGAIN; - ST(0) = tmp; - } - else { - SV *tmp = dbdxst_fetchall_arrayref(sth, slice, batch_row_count); - SPAGAIN; - ST(0) = tmp; - } - - -void -finish(sth) - SV * sth - CODE: - D_imp_sth(sth); - D_imp_dbh_from_sth; - if (!DBIc_ACTIVE(imp_sth)) { - /* No active statement to finish */ - XSRETURN_YES; - } - if (!DBIc_ACTIVE(imp_dbh)) { - /* Either an explicit disconnect() or global destruction */ - /* has disconnected us from the database. Finish is meaningless */ - DBIc_ACTIVE_off(imp_sth); - XSRETURN_YES; - } -#ifdef dbd_st_finish3 - ST(0) = dbd_st_finish3(sth, imp_sth, 0) ? &PL_sv_yes : &PL_sv_no; -#else - ST(0) = dbd_st_finish(sth, imp_sth) ? &PL_sv_yes : &PL_sv_no; -#endif - - -void -blob_read(sth, field, offset, len, destrv=Nullsv, destoffset=0) - SV * sth - int field - long offset - long len - SV * destrv - long destoffset - CODE: - { - D_imp_sth(sth); - if (!destrv) - destrv = sv_2mortal(newRV(sv_2mortal(newSV(0)))); - if (dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset)) - ST(0) = SvRV(destrv); - else ST(0) = &PL_sv_undef; - } - - -void -STORE(sth, keysv, valuesv) - SV * sth - SV * keysv - SV * valuesv - CODE: - D_imp_sth(sth); - if (SvGMAGICAL(valuesv)) - mg_get(valuesv); - ST(0) = &PL_sv_yes; - if (!dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv)) - if (!DBIc_DBISTATE(imp_sth)->set_attr(sth, keysv, valuesv)) - ST(0) = &PL_sv_no; - - -# FETCH renamed and ALIAS'd to avoid case clash on VMS :-( -void -FETCH_attrib(sth, keysv) - SV * sth - SV * keysv - ALIAS: - FETCH = 1 - CODE: - D_imp_sth(sth); - SV *valuesv; - PERL_UNUSED_VAR(ix); - valuesv = dbd_st_FETCH_attrib(sth, imp_sth, keysv); - if (!valuesv) - valuesv = DBIc_DBISTATE(imp_sth)->get_attr(sth, keysv); - ST(0) = valuesv; /* dbd_st_FETCH_attrib did sv_2mortal */ - - -void -DESTROY(sth) - SV * sth - PPCODE: - /* keep in sync with default DESTROY in DBI.xs */ - D_imp_sth(sth); - ST(0) = &PL_sv_yes; - if (!DBIc_IMPSET(imp_sth)) { /* was never fully set up */ - STRLEN lna; - if (DBIc_WARN(imp_sth) && !PL_dirty && DBIc_DBISTATE(imp_sth)->debug >= 2) - PerlIO_printf(DBIc_LOGPIO(imp_sth), - " DESTROY for %s ignored - handle not initialised\n", - SvPV(sth,lna)); - } - else { - if (DBIc_IADESTROY(imp_sth)) { /* wants ineffective destroy */ - DBIc_ACTIVE_off(imp_sth); - if (DBIc_DBISTATE(imp_sth)->debug) - PerlIO_printf(DBIc_LOGPIO(imp_sth), " DESTROY %s skipped due to InactiveDestroy\n", SvPV_nolen(sth)); - } - if (DBIc_ACTIVE(imp_sth)) { - D_imp_dbh_from_sth; - if (!PL_dirty && DBIc_ACTIVE(imp_dbh)) { -#ifdef dbd_st_finish3 - dbd_st_finish3(sth, imp_sth, 1); -#else - dbd_st_finish(sth, imp_sth); -#endif - } - else { - DBIc_ACTIVE_off(imp_sth); - } - } - dbd_st_destroy(sth, imp_sth); - } - -# end of ~DRIVER~.xst -# vim:ts=8:sw=4:et diff --git a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/Driver_xst.h b/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/Driver_xst.h deleted file mode 100644 index ffde459..0000000 --- a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/Driver_xst.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -# $Id$ -# Copyright (c) 2002 Tim Bunce Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. -*/ - - -/* This is really just a workaround for SUPER:: not working right for XS code. - * It would be better if we setup perl's context so SUPER:: did the right thing - * (borrowing the relevant magic from pp_entersub in perl pp_hot.c). - * Then we could just use call_method("SUPER::foo") instead. - * XXX remember to call SPAGAIN in the calling code after calling this! - */ -static SV * -dbixst_bounce_method(char *methname, int params) -{ - dTHX; - /* XXX this 'magic' undoes the dMARK embedded in the dXSARGS of our caller */ - /* so that the dXSARGS below can set things up as they were for our caller */ - void *xxx = PL_markstack_ptr++; - dXSARGS; /* declares sp, ax, mark, items */ - int i; - SV *sv; - int debug = 0; - D_imp_xxh(ST(0)); - if (debug >= 3) { - PerlIO_printf(DBIc_LOGPIO(imp_xxh), - " -> %s (trampoline call with %d (%ld) params)\n", methname, params, (long)items); - PERL_UNUSED_VAR(xxx); - } - EXTEND(SP, params); - PUSHMARK(SP); - for (i=0; i < params; ++i) { - sv = (i >= items) ? &PL_sv_undef : ST(i); - PUSHs(sv); - } - PUTBACK; - i = call_method(methname, G_SCALAR); - SPAGAIN; - sv = (i) ? POPs : &PL_sv_undef; - PUTBACK; - if (debug >= 3) - PerlIO_printf(DBIc_LOGPIO(imp_xxh), - " <- %s= %s (trampoline call return)\n", methname, neatsvpv(sv,0)); - return sv; -} - - -static int -dbdxst_bind_params(SV *sth, imp_sth_t *imp_sth, I32 items, I32 ax) -{ - /* Handle binding supplied values to placeholders. */ - /* items = one greater than the number of params */ - /* ax = ax from calling sub, maybe adjusted to match items */ - dTHX; - int i; - SV *idx; - if (items-1 != DBIc_NUM_PARAMS(imp_sth) - && DBIc_NUM_PARAMS(imp_sth) != DBIc_NUM_PARAMS_AT_EXECUTE - ) { - char errmsg[99]; - /* clear any previous ParamValues before error is generated */ - SV **svp = hv_fetch((HV*)DBIc_MY_H(imp_sth),"ParamValues",11,FALSE); - if (svp && SvROK(*svp) && SvTYPE(SvRV(*svp)) == SVt_PVHV) { - HV *hv = (HV*)SvRV(*svp); - hv_clear(hv); - } - sprintf(errmsg,"called with %d bind variables when %d are needed", - (int)items-1, DBIc_NUM_PARAMS(imp_sth)); - DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, "-1", -1, errmsg, Nullch, Nullch); - return 0; - } - idx = sv_2mortal(newSViv(0)); - for(i=1; i < items ; ++i) { - SV* value = ST(i); - if (SvGMAGICAL(value)) - mg_get(value); /* trigger magic to FETCH the value */ - sv_setiv(idx, i); - if (!dbd_bind_ph(sth, imp_sth, idx, value, 0, Nullsv, FALSE, 0)) { - return 0; /* dbd_bind_ph already registered error */ - } - } - return 1; -} - -#ifndef dbd_fetchall_arrayref -static SV * -dbdxst_fetchall_arrayref(SV *sth, SV *slice, SV *batch_row_count) -{ - dTHX; - D_imp_sth(sth); - SV *rows_rvav; - if (SvOK(slice)) { /* should never get here */ - char errmsg[99]; - sprintf(errmsg,"slice param not supported by XS version of fetchall_arrayref"); - DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, "-1", -1, errmsg, Nullch, Nullch); - return &PL_sv_undef; - } - else { - IV maxrows = SvOK(batch_row_count) ? SvIV(batch_row_count) : -1; - AV *fetched_av; - AV *rows_av = newAV(); - if ( !DBIc_ACTIVE(imp_sth) && maxrows>0 ) { - /* to simplify application logic we return undef without an error */ - /* if we've fetched all the rows and called with a batch_row_count */ - return &PL_sv_undef; - } - av_extend(rows_av, (maxrows>0) ? maxrows : 31); - while ( (maxrows < 0 || maxrows-- > 0) - && (fetched_av = dbd_st_fetch(sth, imp_sth)) - ) { - AV *copy_row_av = av_make(AvFILL(fetched_av)+1, AvARRAY(fetched_av)); - av_push(rows_av, newRV_noinc((SV*)copy_row_av)); - } - rows_rvav = sv_2mortal(newRV_noinc((SV *)rows_av)); - } - return rows_rvav; -} -#endif - diff --git a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbd_xsh.h b/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbd_xsh.h deleted file mode 100644 index 2c7f2d6..0000000 --- a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbd_xsh.h +++ /dev/null @@ -1,61 +0,0 @@ -/* @(#)$Id$ - * - * Copyright 2000-2002 Tim Bunce - * Copyright 2002 Jonathan Leffler - * - * These prototypes are for dbdimp.c funcs used in the XS file. - * These names are #defined to driver specific names by the - * dbdimp.h file in the driver source. - */ - -#ifndef DBI_DBD_XSH_H -#define DBI_DBD_XSH_H - -void dbd_init _((dbistate_t *dbistate)); - -int dbd_discon_all _((SV *drh, imp_drh_t *imp_drh)); -SV *dbd_take_imp_data _((SV *h, imp_xxh_t *imp_xxh, void *foo)); - -/* Support for dbd_dr_data_sources and dbd_db_do added to Driver.xst in DBI v1.33 */ -/* dbd_dr_data_sources: optional: defined by a driver that calls a C */ -/* function to get the list of data sources */ -AV *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attrs); - -int dbd_db_login6_sv _((SV *dbh, imp_dbh_t *imp_dbh, SV *dbname, SV *uid, SV *pwd, SV*attribs)); -int dbd_db_login6 _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, SV*attribs)); -int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd)); /* deprecated */ -/* Note: interface of dbd_db_do changed in v1.33 */ -/* Old prototype: dbd_db_do _((SV *sv, char *statement)); */ -/* dbd_db_do: optional: defined by a driver if the DBI default version is too slow */ -int dbd_db_do4 _((SV *dbh, imp_dbh_t *imp_dbh, char *statement, SV *params)); -IV dbd_db_do4_iv _((SV *dbh, imp_dbh_t *imp_dbh, char *statement, SV *params)); -int dbd_db_commit _((SV *dbh, imp_dbh_t *imp_dbh)); -int dbd_db_rollback _((SV *dbh, imp_dbh_t *imp_dbh)); -int dbd_db_disconnect _((SV *dbh, imp_dbh_t *imp_dbh)); -void dbd_db_destroy _((SV *dbh, imp_dbh_t *imp_dbh)); -int dbd_db_STORE_attrib _((SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)); -SV *dbd_db_FETCH_attrib _((SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)); -SV *dbd_db_last_insert_id _((SV *dbh, imp_dbh_t *imp_dbh, SV *catalog, SV *schema, SV *table, SV *field, SV *attr)); -AV *dbd_db_data_sources _((SV *dbh, imp_dbh_t *imp_dbh, SV *attr)); - -int dbd_st_prepare _((SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs)); -int dbd_st_prepare_sv _((SV *sth, imp_sth_t *imp_sth, SV *statement, SV *attribs)); -int dbd_st_rows _((SV *sth, imp_sth_t *imp_sth)); -IV dbd_st_rows_iv _((SV *sth, imp_sth_t *imp_sth)); -int dbd_st_execute _((SV *sth, imp_sth_t *imp_sth)); -IV dbd_st_execute_iv _((SV *sth, imp_sth_t *imp_sth)); -AV *dbd_st_fetch _((SV *sth, imp_sth_t *imp_sth)); -int dbd_st_finish3 _((SV *sth, imp_sth_t *imp_sth, int from_destroy)); -int dbd_st_finish _((SV *sth, imp_sth_t *imp_sth)); /* deprecated */ -void dbd_st_destroy _((SV *sth, imp_sth_t *imp_sth)); -int dbd_st_blob_read _((SV *sth, imp_sth_t *imp_sth, - int field, long offset, long len, SV *destrv, long destoffset)); -int dbd_st_STORE_attrib _((SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)); -SV *dbd_st_FETCH_attrib _((SV *sth, imp_sth_t *imp_sth, SV *keysv)); -SV *dbd_st_execute_for_fetch _((SV *sth, imp_sth_t *imp_sth, SV *fetch_tuple_sub, SV *tuple_status)); - -int dbd_bind_ph _((SV *sth, imp_sth_t *imp_sth, - SV *param, SV *value, IV sql_type, SV *attribs, - int is_inout, IV maxlen)); - -#endif /* end of dbd_xsh.h */ diff --git a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbi_sql.h b/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbi_sql.h deleted file mode 100644 index 22b5b77..0000000 --- a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbi_sql.h +++ /dev/null @@ -1,96 +0,0 @@ -/* $Id$ - * - * Copyright (c) 1997,1998,1999 Tim Bunce England - * - * See COPYRIGHT section in DBI.pm for usage and distribution rights. - */ - - -/* Some core SQL CLI standard (ODBC) declarations */ -#ifndef SQL_SUCCESS /* don't clash with ODBC based drivers */ - -/* SQL datatype codes */ -#define SQL_GUID (-11) -#define SQL_WLONGVARCHAR (-10) -#define SQL_WVARCHAR (-9) -#define SQL_WCHAR (-8) -#define SQL_BIT (-7) -#define SQL_TINYINT (-6) -#define SQL_BIGINT (-5) -#define SQL_LONGVARBINARY (-4) -#define SQL_VARBINARY (-3) -#define SQL_BINARY (-2) -#define SQL_LONGVARCHAR (-1) -#define SQL_UNKNOWN_TYPE 0 -#define SQL_ALL_TYPES 0 -#define SQL_CHAR 1 -#define SQL_NUMERIC 2 -#define SQL_DECIMAL 3 -#define SQL_INTEGER 4 -#define SQL_SMALLINT 5 -#define SQL_FLOAT 6 -#define SQL_REAL 7 -#define SQL_DOUBLE 8 -#define SQL_DATETIME 9 -#define SQL_DATE 9 -#define SQL_INTERVAL 10 -#define SQL_TIME 10 -#define SQL_TIMESTAMP 11 -#define SQL_VARCHAR 12 -#define SQL_BOOLEAN 16 -#define SQL_UDT 17 -#define SQL_UDT_LOCATOR 18 -#define SQL_ROW 19 -#define SQL_REF 20 -#define SQL_BLOB 30 -#define SQL_BLOB_LOCATOR 31 -#define SQL_CLOB 40 -#define SQL_CLOB_LOCATOR 41 -#define SQL_ARRAY 50 -#define SQL_ARRAY_LOCATOR 51 -#define SQL_MULTISET 55 -#define SQL_MULTISET_LOCATOR 56 -#define SQL_TYPE_DATE 91 -#define SQL_TYPE_TIME 92 -#define SQL_TYPE_TIMESTAMP 93 -#define SQL_TYPE_TIME_WITH_TIMEZONE 94 -#define SQL_TYPE_TIMESTAMP_WITH_TIMEZONE 95 -#define SQL_INTERVAL_YEAR 101 -#define SQL_INTERVAL_MONTH 102 -#define SQL_INTERVAL_DAY 103 -#define SQL_INTERVAL_HOUR 104 -#define SQL_INTERVAL_MINUTE 105 -#define SQL_INTERVAL_SECOND 106 -#define SQL_INTERVAL_YEAR_TO_MONTH 107 -#define SQL_INTERVAL_DAY_TO_HOUR 108 -#define SQL_INTERVAL_DAY_TO_MINUTE 109 -#define SQL_INTERVAL_DAY_TO_SECOND 110 -#define SQL_INTERVAL_HOUR_TO_MINUTE 111 -#define SQL_INTERVAL_HOUR_TO_SECOND 112 -#define SQL_INTERVAL_MINUTE_TO_SECOND 113 - - -/* Main return codes */ -#define SQL_ERROR (-1) -#define SQL_SUCCESS 0 -#define SQL_SUCCESS_WITH_INFO 1 -#define SQL_NO_DATA_FOUND 100 - -/* - * for ODBC SQL Cursor Types - */ -#define SQL_CURSOR_FORWARD_ONLY 0UL -#define SQL_CURSOR_KEYSET_DRIVEN 1UL -#define SQL_CURSOR_DYNAMIC 2UL -#define SQL_CURSOR_STATIC 3UL -#define SQL_CURSOR_TYPE_DEFAULT SQL_CURSOR_FORWARD_ONLY - -#endif /* SQL_SUCCESS */ - -/* Handy macro for testing for success and success with info. */ -/* BEWARE that this macro can have side effects since rc appears twice! */ -/* So DONT use it as if(SQL_ok(func(...))) { ... } */ -#define SQL_ok(rc) ((rc)==SQL_SUCCESS || (rc)==SQL_SUCCESS_WITH_INFO) - - -/* end of dbi_sql.h */ diff --git a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbipport.h b/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbipport.h deleted file mode 100644 index 858612e..0000000 --- a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbipport.h +++ /dev/null @@ -1,7748 +0,0 @@ -#if 0 -<<'SKIP'; -#endif -/* ----------------------------------------------------------------------- - - ppport.h -- Perl/Pollution/Portability Version 3.32 - - Automatically created by Devel::PPPort running under perl 5.018002. - - Do NOT edit this file directly! -- Edit PPPort_pm.PL and the - includes in parts/inc/ instead. - - Use 'perldoc ppport.h' to view the documentation below. - ----------------------------------------------------------------------- - -SKIP - -=pod - -=head1 NAME - -ppport.h - Perl/Pollution/Portability version 3.32 - -=head1 SYNOPSIS - - perl ppport.h [options] [source files] - - Searches current directory for files if no [source files] are given - - --help show short help - - --version show version - - --patch=file write one patch file with changes - --copy=suffix write changed copies with suffix - --diff=program use diff program and options - - --compat-version=version provide compatibility with Perl version - --cplusplus accept C++ comments - - --quiet don't output anything except fatal errors - --nodiag don't show diagnostics - --nohints don't show hints - --nochanges don't suggest changes - --nofilter don't filter input files - - --strip strip all script and doc functionality from - ppport.h - - --list-provided list provided API - --list-unsupported list unsupported API - --api-info=name show Perl API portability information - -=head1 COMPATIBILITY - -This version of F is designed to support operation with Perl -installations back to 5.003, and has been tested up to 5.20. - -=head1 OPTIONS - -=head2 --help - -Display a brief usage summary. - -=head2 --version - -Display the version of F. - -=head2 --patch=I - -If this option is given, a single patch file will be created if -any changes are suggested. This requires a working diff program -to be installed on your system. - -=head2 --copy=I - -If this option is given, a copy of each file will be saved with -the given suffix that contains the suggested changes. This does -not require any external programs. Note that this does not -automagically add a dot between the original filename and the -suffix. If you want the dot, you have to include it in the option -argument. - -If neither C<--patch> or C<--copy> are given, the default is to -simply print the diffs for each file. This requires either -C or a C program to be installed. - -=head2 --diff=I - -Manually set the diff program and options to use. The default -is to use C, when installed, and output unified -context diffs. - -=head2 --compat-version=I - -Tell F to check for compatibility with the given -Perl version. The default is to check for compatibility with Perl -version 5.003. You can use this option to reduce the output -of F if you intend to be backward compatible only -down to a certain Perl version. - -=head2 --cplusplus - -Usually, F will detect C++ style comments and -replace them with C style comments for portability reasons. -Using this option instructs F to leave C++ -comments untouched. - -=head2 --quiet - -Be quiet. Don't print anything except fatal errors. - -=head2 --nodiag - -Don't output any diagnostic messages. Only portability -alerts will be printed. - -=head2 --nohints - -Don't output any hints. Hints often contain useful portability -notes. Warnings will still be displayed. - -=head2 --nochanges - -Don't suggest any changes. Only give diagnostic output and hints -unless these are also deactivated. - -=head2 --nofilter - -Don't filter the list of input files. By default, files not looking -like source code (i.e. not *.xs, *.c, *.cc, *.cpp or *.h) are skipped. - -=head2 --strip - -Strip all script and documentation functionality from F. -This reduces the size of F dramatically and may be useful -if you want to include F in smaller modules without -increasing their distribution size too much. - -The stripped F will have a C<--unstrip> option that allows -you to undo the stripping, but only if an appropriate C -module is installed. - -=head2 --list-provided - -Lists the API elements for which compatibility is provided by -F. Also lists if it must be explicitly requested, -if it has dependencies, and if there are hints or warnings for it. - -=head2 --list-unsupported - -Lists the API elements that are known not to be supported by -F and below which version of Perl they probably -won't be available or work. - -=head2 --api-info=I - -Show portability information for API elements matching I. -If I is surrounded by slashes, it is interpreted as a regular -expression. - -=head1 DESCRIPTION - -In order for a Perl extension (XS) module to be as portable as possible -across differing versions of Perl itself, certain steps need to be taken. - -=over 4 - -=item * - -Including this header is the first major one. This alone will give you -access to a large part of the Perl API that hasn't been available in -earlier Perl releases. Use - - perl ppport.h --list-provided - -to see which API elements are provided by ppport.h. - -=item * - -You should avoid using deprecated parts of the API. For example, using -global Perl variables without the C prefix is deprecated. Also, -some API functions used to have a C prefix. Using this form is -also deprecated. You can safely use the supported API, as F -will provide wrappers for older Perl versions. - -=item * - -If you use one of a few functions or variables that were not present in -earlier versions of Perl, and that can't be provided using a macro, you -have to explicitly request support for these functions by adding one or -more C<#define>s in your source code before the inclusion of F. - -These functions or variables will be marked C in the list shown -by C<--list-provided>. - -Depending on whether you module has a single or multiple files that -use such functions or variables, you want either C or global -variants. - -For a C function or variable (used only in a single source -file), use: - - #define NEED_function - #define NEED_variable - -For a global function or variable (used in multiple source files), -use: - - #define NEED_function_GLOBAL - #define NEED_variable_GLOBAL - -Note that you mustn't have more than one global request for the -same function or variable in your project. - - Function / Variable Static Request Global Request - ----------------------------------------------------------------------------------------- - PL_parser NEED_PL_parser NEED_PL_parser_GLOBAL - PL_signals NEED_PL_signals NEED_PL_signals_GLOBAL - caller_cx() NEED_caller_cx NEED_caller_cx_GLOBAL - eval_pv() NEED_eval_pv NEED_eval_pv_GLOBAL - grok_bin() NEED_grok_bin NEED_grok_bin_GLOBAL - grok_hex() NEED_grok_hex NEED_grok_hex_GLOBAL - grok_number() NEED_grok_number NEED_grok_number_GLOBAL - grok_numeric_radix() NEED_grok_numeric_radix NEED_grok_numeric_radix_GLOBAL - grok_oct() NEED_grok_oct NEED_grok_oct_GLOBAL - load_module() NEED_load_module NEED_load_module_GLOBAL - mg_findext() NEED_mg_findext NEED_mg_findext_GLOBAL - my_snprintf() NEED_my_snprintf NEED_my_snprintf_GLOBAL - my_sprintf() NEED_my_sprintf NEED_my_sprintf_GLOBAL - my_strlcat() NEED_my_strlcat NEED_my_strlcat_GLOBAL - my_strlcpy() NEED_my_strlcpy NEED_my_strlcpy_GLOBAL - newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL - newRV_noinc() NEED_newRV_noinc NEED_newRV_noinc_GLOBAL - newSV_type() NEED_newSV_type NEED_newSV_type_GLOBAL - newSVpvn_flags() NEED_newSVpvn_flags NEED_newSVpvn_flags_GLOBAL - newSVpvn_share() NEED_newSVpvn_share NEED_newSVpvn_share_GLOBAL - pv_display() NEED_pv_display NEED_pv_display_GLOBAL - pv_escape() NEED_pv_escape NEED_pv_escape_GLOBAL - pv_pretty() NEED_pv_pretty NEED_pv_pretty_GLOBAL - sv_2pv_flags() NEED_sv_2pv_flags NEED_sv_2pv_flags_GLOBAL - sv_2pvbyte() NEED_sv_2pvbyte NEED_sv_2pvbyte_GLOBAL - sv_catpvf_mg() NEED_sv_catpvf_mg NEED_sv_catpvf_mg_GLOBAL - sv_catpvf_mg_nocontext() NEED_sv_catpvf_mg_nocontext NEED_sv_catpvf_mg_nocontext_GLOBAL - sv_pvn_force_flags() NEED_sv_pvn_force_flags NEED_sv_pvn_force_flags_GLOBAL - sv_setpvf_mg() NEED_sv_setpvf_mg NEED_sv_setpvf_mg_GLOBAL - sv_setpvf_mg_nocontext() NEED_sv_setpvf_mg_nocontext NEED_sv_setpvf_mg_nocontext_GLOBAL - sv_unmagicext() NEED_sv_unmagicext NEED_sv_unmagicext_GLOBAL - vload_module() NEED_vload_module NEED_vload_module_GLOBAL - vnewSVpvf() NEED_vnewSVpvf NEED_vnewSVpvf_GLOBAL - warner() NEED_warner NEED_warner_GLOBAL - -To avoid namespace conflicts, you can change the namespace of the -explicitly exported functions / variables using the C -macro. Just C<#define> the macro before including C: - - #define DPPP_NAMESPACE MyOwnNamespace_ - #include "ppport.h" - -The default namespace is C. - -=back - -The good thing is that most of the above can be checked by running -F on your source code. See the next section for -details. - -=head1 EXAMPLES - -To verify whether F is needed for your module, whether you -should make any changes to your code, and whether any special defines -should be used, F can be run as a Perl script to check your -source code. Simply say: - - perl ppport.h - -The result will usually be a list of patches suggesting changes -that should at least be acceptable, if not necessarily the most -efficient solution, or a fix for all possible problems. - -If you know that your XS module uses features only available in -newer Perl releases, if you're aware that it uses C++ comments, -and if you want all suggestions as a single patch file, you could -use something like this: - - perl ppport.h --compat-version=5.6.0 --cplusplus --patch=test.diff - -If you only want your code to be scanned without any suggestions -for changes, use: - - perl ppport.h --nochanges - -You can specify a different C program or options, using -the C<--diff> option: - - perl ppport.h --diff='diff -C 10' - -This would output context diffs with 10 lines of context. - -If you want to create patched copies of your files instead, use: - - perl ppport.h --copy=.new - -To display portability information for the C function, -use: - - perl ppport.h --api-info=newSVpvn - -Since the argument to C<--api-info> can be a regular expression, -you can use - - perl ppport.h --api-info=/_nomg$/ - -to display portability information for all C<_nomg> functions or - - perl ppport.h --api-info=/./ - -to display information for all known API elements. - -=head1 BUGS - -If this version of F is causing failure during -the compilation of this module, please check if newer versions -of either this module or C are available on CPAN -before sending a bug report. - -If F was generated using the latest version of -C and is causing failure of this module, please -file a bug report here: L - -Please include the following information: - -=over 4 - -=item 1. - -The complete output from running "perl -V" - -=item 2. - -This file. - -=item 3. - -The name and version of the module you were trying to build. - -=item 4. - -A full log of the build that failed. - -=item 5. - -Any other information that you think could be relevant. - -=back - -For the latest version of this code, please get the C -module from CPAN. - -=head1 COPYRIGHT - -Version 3.x, Copyright (c) 2004-2013, Marcus Holland-Moritz. - -Version 2.x, Copyright (C) 2001, Paul Marquess. - -Version 1.x, Copyright (C) 1999, Kenneth Albanowski. - -This program is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -See L. - -=cut - -use strict; - -# Disable broken TRIE-optimization -BEGIN { eval '${^RE_TRIE_MAXBUF} = -1' if $] >= 5.009004 && $] <= 5.009005 } - -my $VERSION = 3.32; - -my %opt = ( - quiet => 0, - diag => 1, - hints => 1, - changes => 1, - cplusplus => 0, - filter => 1, - strip => 0, - version => 0, -); - -my($ppport) = $0 =~ /([\w.]+)$/; -my $LF = '(?:\r\n|[\r\n])'; # line feed -my $HS = "[ \t]"; # horizontal whitespace - -# Never use C comments in this file! -my $ccs = '/'.'*'; -my $cce = '*'.'/'; -my $rccs = quotemeta $ccs; -my $rcce = quotemeta $cce; - -eval { - require Getopt::Long; - Getopt::Long::GetOptions(\%opt, qw( - help quiet diag! filter! hints! changes! cplusplus strip version - patch=s copy=s diff=s compat-version=s - list-provided list-unsupported api-info=s - )) or usage(); -}; - -if ($@ and grep /^-/, @ARGV) { - usage() if "@ARGV" =~ /^--?h(?:elp)?$/; - die "Getopt::Long not found. Please don't use any options.\n"; -} - -if ($opt{version}) { - print "This is $0 $VERSION.\n"; - exit 0; -} - -usage() if $opt{help}; -strip() if $opt{strip}; - -if (exists $opt{'compat-version'}) { - my($r,$v,$s) = eval { parse_version($opt{'compat-version'}) }; - if ($@) { - die "Invalid version number format: '$opt{'compat-version'}'\n"; - } - die "Only Perl 5 is supported\n" if $r != 5; - die "Invalid version number: $opt{'compat-version'}\n" if $v >= 1000 || $s >= 1000; - $opt{'compat-version'} = sprintf "%d.%03d%03d", $r, $v, $s; -} -else { - $opt{'compat-version'} = 5; -} - -my %API = map { /^(\w+)\|([^|]*)\|([^|]*)\|(\w*)$/ - ? ( $1 => { - ($2 ? ( base => $2 ) : ()), - ($3 ? ( todo => $3 ) : ()), - (index($4, 'v') >= 0 ? ( varargs => 1 ) : ()), - (index($4, 'p') >= 0 ? ( provided => 1 ) : ()), - (index($4, 'n') >= 0 ? ( nothxarg => 1 ) : ()), - } ) - : die "invalid spec: $_" } qw( -ASCII_TO_NEED||5.007001|n -AvFILLp|5.004050||p -AvFILL||| -BhkDISABLE||5.021008| -BhkENABLE||5.021008| -BhkENTRY_set||5.021008| -BhkENTRY||| -BhkFLAGS||| -CALL_BLOCK_HOOKS||| -CLASS|||n -CPERLscope|5.005000||p -CX_CURPAD_SAVE||| -CX_CURPAD_SV||| -CopFILEAV|5.006000||p -CopFILEGV_set|5.006000||p -CopFILEGV|5.006000||p -CopFILESV|5.006000||p -CopFILE_set|5.006000||p -CopFILE|5.006000||p -CopSTASHPV_set|5.006000||p -CopSTASHPV|5.006000||p -CopSTASH_eq|5.006000||p -CopSTASH_set|5.006000||p -CopSTASH|5.006000||p -CopyD|5.009002|5.004050|p -Copy||| -CvPADLIST||5.008001| -CvSTASH||| -CvWEAKOUTSIDE||| -DEFSV_set|5.010001||p -DEFSV|5.004050||p -END_EXTERN_C|5.005000||p -ENTER||| -ERRSV|5.004050||p -EXTEND||| -EXTERN_C|5.005000||p -F0convert|||n -FREETMPS||| -GIMME_V||5.004000|n -GIMME|||n -GROK_NUMERIC_RADIX|5.007002||p -G_ARRAY||| -G_DISCARD||| -G_EVAL||| -G_METHOD|5.006001||p -G_NOARGS||| -G_SCALAR||| -G_VOID||5.004000| -GetVars||| -GvAV||| -GvCV||| -GvHV||| -GvSVn|5.009003||p -GvSV||| -Gv_AMupdate||5.011000| -HEf_SVKEY|5.003070||p -HeHASH||5.003070| -HeKEY||5.003070| -HeKLEN||5.003070| -HePV||5.004000| -HeSVKEY_force||5.003070| -HeSVKEY_set||5.004000| -HeSVKEY||5.003070| -HeUTF8|5.010001|5.008000|p -HeVAL||5.003070| -HvENAMELEN||5.015004| -HvENAMEUTF8||5.015004| -HvENAME||5.013007| -HvNAMELEN_get|5.009003||p -HvNAMELEN||5.015004| -HvNAMEUTF8||5.015004| -HvNAME_get|5.009003||p -HvNAME||| -INT2PTR|5.006000||p -IN_LOCALE_COMPILETIME|5.007002||p -IN_LOCALE_RUNTIME|5.007002||p -IN_LOCALE|5.007002||p -IN_PERL_COMPILETIME|5.008001||p -IS_NUMBER_GREATER_THAN_UV_MAX|5.007002||p -IS_NUMBER_INFINITY|5.007002||p -IS_NUMBER_IN_UV|5.007002||p -IS_NUMBER_NAN|5.007003||p -IS_NUMBER_NEG|5.007002||p -IS_NUMBER_NOT_INT|5.007002||p -IVSIZE|5.006000||p -IVTYPE|5.006000||p -IVdf|5.006000||p -LEAVE||| -LINKLIST||5.013006| -LVRET||| -MARK||| -MULTICALL||5.021008| -MUTABLE_PTR|5.010001||p -MUTABLE_SV|5.010001||p -MY_CXT_CLONE|5.009002||p -MY_CXT_INIT|5.007003||p -MY_CXT|5.007003||p -MoveD|5.009002|5.004050|p -Move||| -NATIVE_TO_NEED||5.007001|n -NOOP|5.005000||p -NUM2PTR|5.006000||p -NVTYPE|5.006000||p -NVef|5.006001||p -NVff|5.006001||p -NVgf|5.006001||p -Newxc|5.009003||p -Newxz|5.009003||p -Newx|5.009003||p -Nullav||| -Nullch||| -Nullcv||| -Nullhv||| -Nullsv||| -OP_CLASS||5.013007| -OP_DESC||5.007003| -OP_NAME||5.007003| -OP_TYPE_IS_OR_WAS||5.019010| -OP_TYPE_IS||5.019007| -ORIGMARK||| -OpHAS_SIBLING||5.021007| -OpSIBLING_set||5.021007| -OpSIBLING||5.021007| -PAD_BASE_SV||| -PAD_CLONE_VARS||| -PAD_COMPNAME_FLAGS||| -PAD_COMPNAME_GEN_set||| -PAD_COMPNAME_GEN||| -PAD_COMPNAME_OURSTASH||| -PAD_COMPNAME_PV||| -PAD_COMPNAME_TYPE||| -PAD_RESTORE_LOCAL||| -PAD_SAVE_LOCAL||| -PAD_SAVE_SETNULLPAD||| -PAD_SETSV||| -PAD_SET_CUR_NOSAVE||| -PAD_SET_CUR||| -PAD_SVl||| -PAD_SV||| -PERLIO_FUNCS_CAST|5.009003||p -PERLIO_FUNCS_DECL|5.009003||p -PERL_ABS|5.008001||p -PERL_BCDVERSION|5.021008||p -PERL_GCC_BRACE_GROUPS_FORBIDDEN|5.008001||p -PERL_HASH|5.003070||p -PERL_INT_MAX|5.003070||p -PERL_INT_MIN|5.003070||p -PERL_LONG_MAX|5.003070||p -PERL_LONG_MIN|5.003070||p -PERL_MAGIC_arylen|5.007002||p -PERL_MAGIC_backref|5.007002||p -PERL_MAGIC_bm|5.007002||p -PERL_MAGIC_collxfrm|5.007002||p -PERL_MAGIC_dbfile|5.007002||p -PERL_MAGIC_dbline|5.007002||p -PERL_MAGIC_defelem|5.007002||p -PERL_MAGIC_envelem|5.007002||p -PERL_MAGIC_env|5.007002||p -PERL_MAGIC_ext|5.007002||p -PERL_MAGIC_fm|5.007002||p -PERL_MAGIC_glob|5.021008||p -PERL_MAGIC_isaelem|5.007002||p -PERL_MAGIC_isa|5.007002||p -PERL_MAGIC_mutex|5.021008||p -PERL_MAGIC_nkeys|5.007002||p -PERL_MAGIC_overload_elem|5.021008||p -PERL_MAGIC_overload_table|5.007002||p -PERL_MAGIC_overload|5.021008||p -PERL_MAGIC_pos|5.007002||p -PERL_MAGIC_qr|5.007002||p -PERL_MAGIC_regdata|5.007002||p -PERL_MAGIC_regdatum|5.007002||p -PERL_MAGIC_regex_global|5.007002||p -PERL_MAGIC_shared_scalar|5.007003||p -PERL_MAGIC_shared|5.007003||p -PERL_MAGIC_sigelem|5.007002||p -PERL_MAGIC_sig|5.007002||p -PERL_MAGIC_substr|5.007002||p -PERL_MAGIC_sv|5.007002||p -PERL_MAGIC_taint|5.007002||p -PERL_MAGIC_tiedelem|5.007002||p -PERL_MAGIC_tiedscalar|5.007002||p -PERL_MAGIC_tied|5.007002||p -PERL_MAGIC_utf8|5.008001||p -PERL_MAGIC_uvar_elem|5.007003||p -PERL_MAGIC_uvar|5.007002||p -PERL_MAGIC_vec|5.007002||p -PERL_MAGIC_vstring|5.008001||p -PERL_PV_ESCAPE_ALL|5.009004||p -PERL_PV_ESCAPE_FIRSTCHAR|5.009004||p -PERL_PV_ESCAPE_NOBACKSLASH|5.009004||p -PERL_PV_ESCAPE_NOCLEAR|5.009004||p -PERL_PV_ESCAPE_QUOTE|5.009004||p -PERL_PV_ESCAPE_RE|5.009005||p -PERL_PV_ESCAPE_UNI_DETECT|5.009004||p -PERL_PV_ESCAPE_UNI|5.009004||p -PERL_PV_PRETTY_DUMP|5.009004||p -PERL_PV_PRETTY_ELLIPSES|5.010000||p -PERL_PV_PRETTY_LTGT|5.009004||p -PERL_PV_PRETTY_NOCLEAR|5.010000||p -PERL_PV_PRETTY_QUOTE|5.009004||p -PERL_PV_PRETTY_REGPROP|5.009004||p -PERL_QUAD_MAX|5.003070||p -PERL_QUAD_MIN|5.003070||p -PERL_REVISION|5.006000||p -PERL_SCAN_ALLOW_UNDERSCORES|5.007003||p -PERL_SCAN_DISALLOW_PREFIX|5.007003||p -PERL_SCAN_GREATER_THAN_UV_MAX|5.007003||p -PERL_SCAN_SILENT_ILLDIGIT|5.008001||p -PERL_SHORT_MAX|5.003070||p -PERL_SHORT_MIN|5.003070||p -PERL_SIGNALS_UNSAFE_FLAG|5.008001||p -PERL_SUBVERSION|5.006000||p -PERL_SYS_INIT3||5.006000| -PERL_SYS_INIT||| -PERL_SYS_TERM||5.021008| -PERL_UCHAR_MAX|5.003070||p -PERL_UCHAR_MIN|5.003070||p -PERL_UINT_MAX|5.003070||p -PERL_UINT_MIN|5.003070||p -PERL_ULONG_MAX|5.003070||p -PERL_ULONG_MIN|5.003070||p -PERL_UNUSED_ARG|5.009003||p -PERL_UNUSED_CONTEXT|5.009004||p -PERL_UNUSED_DECL|5.007002||p -PERL_UNUSED_VAR|5.007002||p -PERL_UQUAD_MAX|5.003070||p -PERL_UQUAD_MIN|5.003070||p -PERL_USE_GCC_BRACE_GROUPS|5.009004||p -PERL_USHORT_MAX|5.003070||p -PERL_USHORT_MIN|5.003070||p -PERL_VERSION|5.006000||p -PL_DBsignal|5.005000||p -PL_DBsingle|||pn -PL_DBsub|||pn -PL_DBtrace|||pn -PL_Sv|5.005000||p -PL_bufend|5.021008||p -PL_bufptr|5.021008||p -PL_check||5.006000| -PL_compiling|5.004050||p -PL_comppad_name||5.017004| -PL_comppad||5.008001| -PL_copline|5.021008||p -PL_curcop|5.004050||p -PL_curpad||5.005000| -PL_curstash|5.004050||p -PL_debstash|5.004050||p -PL_defgv|5.004050||p -PL_diehook|5.004050||p -PL_dirty|5.004050||p -PL_dowarn|||pn -PL_errgv|5.004050||p -PL_error_count|5.021008||p -PL_expect|5.021008||p -PL_hexdigit|5.005000||p -PL_hints|5.005000||p -PL_in_my_stash|5.021008||p -PL_in_my|5.021008||p -PL_keyword_plugin||5.011002| -PL_last_in_gv|||n -PL_laststatval|5.005000||p -PL_lex_state|5.021008||p -PL_lex_stuff|5.021008||p -PL_linestr|5.021008||p -PL_modglobal||5.005000|n -PL_na|5.004050||pn -PL_no_modify|5.006000||p -PL_ofsgv|||n -PL_opfreehook||5.011000|n -PL_parser|5.009005||p -PL_peepp||5.007003|n -PL_perl_destruct_level|5.004050||p -PL_perldb|5.004050||p -PL_ppaddr|5.006000||p -PL_rpeepp||5.013005|n -PL_rsfp_filters|5.021008||p -PL_rsfp|5.021008||p -PL_rs|||n -PL_signals|5.008001||p -PL_stack_base|5.004050||p -PL_stack_sp|5.004050||p -PL_statcache|5.005000||p -PL_stdingv|5.004050||p -PL_sv_arenaroot|5.004050||p -PL_sv_no|5.004050||pn -PL_sv_undef|5.004050||pn -PL_sv_yes|5.004050||pn -PL_tainted|5.004050||p -PL_tainting|5.004050||p -PL_tokenbuf|5.021008||p -POP_MULTICALL||5.021008| -POPi|||n -POPl|||n -POPn|||n -POPpbytex||5.007001|n -POPpx||5.005030|n -POPp|||n -POPs|||n -PTR2IV|5.006000||p -PTR2NV|5.006000||p -PTR2UV|5.006000||p -PTR2nat|5.009003||p -PTR2ul|5.007001||p -PTRV|5.006000||p -PUSHMARK||| -PUSH_MULTICALL||5.021008| -PUSHi||| -PUSHmortal|5.009002||p -PUSHn||| -PUSHp||| -PUSHs||| -PUSHu|5.004000||p -PUTBACK||| -PadARRAY||5.021008| -PadMAX||5.021008| -PadlistARRAY||5.021008| -PadlistMAX||5.021008| -PadlistNAMESARRAY||5.021008| -PadlistNAMESMAX||5.021008| -PadlistNAMES||5.021008| -PadlistREFCNT||5.017004| -PadnameIsOUR||| -PadnameIsSTATE||| -PadnameLEN||5.021008| -PadnameOURSTASH||| -PadnameOUTER||| -PadnamePV||5.021008| -PadnameREFCNT_dec||5.021008| -PadnameREFCNT||5.021008| -PadnameSV||5.021008| -PadnameTYPE||| -PadnameUTF8||5.021007| -PadnamelistARRAY||5.021008| -PadnamelistMAX||5.021008| -PadnamelistREFCNT_dec||5.021008| -PadnamelistREFCNT||5.021008| -PerlIO_clearerr||5.007003| -PerlIO_close||5.007003| -PerlIO_context_layers||5.009004| -PerlIO_eof||5.007003| -PerlIO_error||5.007003| -PerlIO_fileno||5.007003| -PerlIO_fill||5.007003| -PerlIO_flush||5.007003| -PerlIO_get_base||5.007003| -PerlIO_get_bufsiz||5.007003| -PerlIO_get_cnt||5.007003| -PerlIO_get_ptr||5.007003| -PerlIO_read||5.007003| -PerlIO_restore_errno||| -PerlIO_save_errno||| -PerlIO_seek||5.007003| -PerlIO_set_cnt||5.007003| -PerlIO_set_ptrcnt||5.007003| -PerlIO_setlinebuf||5.007003| -PerlIO_stderr||5.007003| -PerlIO_stdin||5.007003| -PerlIO_stdout||5.007003| -PerlIO_tell||5.007003| -PerlIO_unread||5.007003| -PerlIO_write||5.007003| -Perl_signbit||5.009005|n -PoisonFree|5.009004||p -PoisonNew|5.009004||p -PoisonWith|5.009004||p -Poison|5.008000||p -READ_XDIGIT||5.017006| -RETVAL|||n -Renewc||| -Renew||| -SAVECLEARSV||| -SAVECOMPPAD||| -SAVEPADSV||| -SAVETMPS||| -SAVE_DEFSV|5.004050||p -SPAGAIN||| -SP||| -START_EXTERN_C|5.005000||p -START_MY_CXT|5.007003||p -STMT_END|||p -STMT_START|||p -STR_WITH_LEN|5.009003||p -ST||| -SV_CONST_RETURN|5.009003||p -SV_COW_DROP_PV|5.008001||p -SV_COW_SHARED_HASH_KEYS|5.009005||p -SV_GMAGIC|5.007002||p -SV_HAS_TRAILING_NUL|5.009004||p -SV_IMMEDIATE_UNREF|5.007001||p -SV_MUTABLE_RETURN|5.009003||p -SV_NOSTEAL|5.009002||p -SV_SMAGIC|5.009003||p -SV_UTF8_NO_ENCODING|5.008001||p -SVfARG|5.009005||p -SVf_UTF8|5.006000||p -SVf|5.006000||p -SVt_INVLIST||5.019002| -SVt_IV||| -SVt_NULL||| -SVt_NV||| -SVt_PVAV||| -SVt_PVCV||| -SVt_PVFM||| -SVt_PVGV||| -SVt_PVHV||| -SVt_PVIO||| -SVt_PVIV||| -SVt_PVLV||| -SVt_PVMG||| -SVt_PVNV||| -SVt_PV||| -SVt_REGEXP||5.011000| -Safefree||| -Slab_Alloc||| -Slab_Free||| -Slab_to_ro||| -Slab_to_rw||| -StructCopy||| -SvCUR_set||| -SvCUR||| -SvEND||| -SvGAMAGIC||5.006001| -SvGETMAGIC|5.004050||p -SvGROW||| -SvIOK_UV||5.006000| -SvIOK_notUV||5.006000| -SvIOK_off||| -SvIOK_only_UV||5.006000| -SvIOK_only||| -SvIOK_on||| -SvIOKp||| -SvIOK||| -SvIVX||| -SvIV_nomg|5.009001||p -SvIV_set||| -SvIVx||| -SvIV||| -SvIsCOW_shared_hash||5.008003| -SvIsCOW||5.008003| -SvLEN_set||| -SvLEN||| -SvLOCK||5.007003| -SvMAGIC_set|5.009003||p -SvNIOK_off||| -SvNIOKp||| -SvNIOK||| -SvNOK_off||| -SvNOK_only||| -SvNOK_on||| -SvNOKp||| -SvNOK||| -SvNVX||| -SvNV_nomg||5.013002| -SvNV_set||| -SvNVx||| -SvNV||| -SvOK||| -SvOOK_offset||5.011000| -SvOOK||| -SvPOK_off||| -SvPOK_only_UTF8||5.006000| -SvPOK_only||| -SvPOK_on||| -SvPOKp||| -SvPOK||| -SvPVX_const|5.009003||p -SvPVX_mutable|5.009003||p -SvPVX||| -SvPV_const|5.009003||p -SvPV_flags_const_nolen|5.009003||p -SvPV_flags_const|5.009003||p -SvPV_flags_mutable|5.009003||p -SvPV_flags|5.007002||p -SvPV_force_flags_mutable|5.009003||p -SvPV_force_flags_nolen|5.009003||p -SvPV_force_flags|5.007002||p -SvPV_force_mutable|5.009003||p -SvPV_force_nolen|5.009003||p -SvPV_force_nomg_nolen|5.009003||p -SvPV_force_nomg|5.007002||p -SvPV_force|||p -SvPV_mutable|5.009003||p -SvPV_nolen_const|5.009003||p -SvPV_nolen|5.006000||p -SvPV_nomg_const_nolen|5.009003||p -SvPV_nomg_const|5.009003||p -SvPV_nomg_nolen|5.013007||p -SvPV_nomg|5.007002||p -SvPV_renew|5.009003||p -SvPV_set||| -SvPVbyte_force||5.009002| -SvPVbyte_nolen||5.006000| -SvPVbytex_force||5.006000| -SvPVbytex||5.006000| -SvPVbyte|5.006000||p -SvPVutf8_force||5.006000| -SvPVutf8_nolen||5.006000| -SvPVutf8x_force||5.006000| -SvPVutf8x||5.006000| -SvPVutf8||5.006000| -SvPVx||| -SvPV||| -SvREFCNT_dec_NN||5.017007| -SvREFCNT_dec||| -SvREFCNT_inc_NN|5.009004||p -SvREFCNT_inc_simple_NN|5.009004||p -SvREFCNT_inc_simple_void_NN|5.009004||p -SvREFCNT_inc_simple_void|5.009004||p -SvREFCNT_inc_simple|5.009004||p -SvREFCNT_inc_void_NN|5.009004||p -SvREFCNT_inc_void|5.009004||p -SvREFCNT_inc|||p -SvREFCNT||| -SvROK_off||| -SvROK_on||| -SvROK||| -SvRV_set|5.009003||p -SvRV||| -SvRXOK||5.009005| -SvRX||5.009005| -SvSETMAGIC||| -SvSHARED_HASH|5.009003||p -SvSHARE||5.007003| -SvSTASH_set|5.009003||p -SvSTASH||| -SvSetMagicSV_nosteal||5.004000| -SvSetMagicSV||5.004000| -SvSetSV_nosteal||5.004000| -SvSetSV||| -SvTAINTED_off||5.004000| -SvTAINTED_on||5.004000| -SvTAINTED||5.004000| -SvTAINT||| -SvTHINKFIRST||| -SvTRUE_nomg||5.013006| -SvTRUE||| -SvTYPE||| -SvUNLOCK||5.007003| -SvUOK|5.007001|5.006000|p -SvUPGRADE||| -SvUTF8_off||5.006000| -SvUTF8_on||5.006000| -SvUTF8||5.006000| -SvUVXx|5.004000||p -SvUVX|5.004000||p -SvUV_nomg|5.009001||p -SvUV_set|5.009003||p -SvUVx|5.004000||p -SvUV|5.004000||p -SvVOK||5.008001| -SvVSTRING_mg|5.009004||p -THIS|||n -UNDERBAR|5.009002||p -UTF8_MAXBYTES|5.009002||p -UVSIZE|5.006000||p -UVTYPE|5.006000||p -UVXf|5.007001||p -UVof|5.006000||p -UVuf|5.006000||p -UVxf|5.006000||p -WARN_ALL|5.006000||p -WARN_AMBIGUOUS|5.006000||p -WARN_ASSERTIONS|5.021008||p -WARN_BAREWORD|5.006000||p -WARN_CLOSED|5.006000||p -WARN_CLOSURE|5.006000||p -WARN_DEBUGGING|5.006000||p -WARN_DEPRECATED|5.006000||p -WARN_DIGIT|5.006000||p -WARN_EXEC|5.006000||p -WARN_EXITING|5.006000||p -WARN_GLOB|5.006000||p -WARN_INPLACE|5.006000||p -WARN_INTERNAL|5.006000||p -WARN_IO|5.006000||p -WARN_LAYER|5.008000||p -WARN_MALLOC|5.006000||p -WARN_MISC|5.006000||p -WARN_NEWLINE|5.006000||p -WARN_NUMERIC|5.006000||p -WARN_ONCE|5.006000||p -WARN_OVERFLOW|5.006000||p -WARN_PACK|5.006000||p -WARN_PARENTHESIS|5.006000||p -WARN_PIPE|5.006000||p -WARN_PORTABLE|5.006000||p -WARN_PRECEDENCE|5.006000||p -WARN_PRINTF|5.006000||p -WARN_PROTOTYPE|5.006000||p -WARN_QW|5.006000||p -WARN_RECURSION|5.006000||p -WARN_REDEFINE|5.006000||p -WARN_REGEXP|5.006000||p -WARN_RESERVED|5.006000||p -WARN_SEMICOLON|5.006000||p -WARN_SEVERE|5.006000||p -WARN_SIGNAL|5.006000||p -WARN_SUBSTR|5.006000||p -WARN_SYNTAX|5.006000||p -WARN_TAINT|5.006000||p -WARN_THREADS|5.008000||p -WARN_UNINITIALIZED|5.006000||p -WARN_UNOPENED|5.006000||p -WARN_UNPACK|5.006000||p -WARN_UNTIE|5.006000||p -WARN_UTF8|5.006000||p -WARN_VOID|5.006000||p -WIDEST_UTYPE|5.015004||p -XCPT_CATCH|5.009002||p -XCPT_RETHROW|5.009002||p -XCPT_TRY_END|5.009002||p -XCPT_TRY_START|5.009002||p -XPUSHi||| -XPUSHmortal|5.009002||p -XPUSHn||| -XPUSHp||| -XPUSHs||| -XPUSHu|5.004000||p -XSPROTO|5.010000||p -XSRETURN_EMPTY||| -XSRETURN_IV||| -XSRETURN_NO||| -XSRETURN_NV||| -XSRETURN_PV||| -XSRETURN_UNDEF||| -XSRETURN_UV|5.008001||p -XSRETURN_YES||| -XSRETURN|||p -XST_mIV||| -XST_mNO||| -XST_mNV||| -XST_mPV||| -XST_mUNDEF||| -XST_mUV|5.008001||p -XST_mYES||| -XS_APIVERSION_BOOTCHECK||5.021008| -XS_EXTERNAL||5.021008| -XS_INTERNAL||5.021008| -XS_VERSION_BOOTCHECK||5.021008| -XS_VERSION||| -XSprePUSH|5.006000||p -XS||| -XopDISABLE||5.021008| -XopENABLE||5.021008| -XopENTRYCUSTOM||5.021008| -XopENTRY_set||5.021008| -XopENTRY||5.021008| -XopFLAGS||5.013007| -ZeroD|5.009002||p -Zero||| -_aMY_CXT|5.007003||p -_add_range_to_invlist||| -_append_range_to_invlist||| -_core_swash_init||| -_get_encoding||| -_get_regclass_nonbitmap_data||| -_get_swash_invlist||| -_invlist_array_init|||n -_invlist_contains_cp|||n -_invlist_contents||| -_invlist_dump||| -_invlist_intersection_maybe_complement_2nd||| -_invlist_intersection||| -_invlist_invert||| -_invlist_len|||n -_invlist_populate_swatch|||n -_invlist_search|||n -_invlist_subtract||| -_invlist_union_maybe_complement_2nd||| -_invlist_union||| -_is_cur_LC_category_utf8||| -_is_in_locale_category||5.021001| -_is_uni_FOO||5.017008| -_is_uni_perl_idcont||5.017008| -_is_uni_perl_idstart||5.017007| -_is_utf8_FOO||5.017008| -_is_utf8_char_slow||5.021001|n -_is_utf8_idcont||5.021001| -_is_utf8_idstart||5.021001| -_is_utf8_mark||5.017008| -_is_utf8_perl_idcont||5.017008| -_is_utf8_perl_idstart||5.017007| -_is_utf8_xidcont||5.021001| -_is_utf8_xidstart||5.021001| -_load_PL_utf8_foldclosures||| -_make_exactf_invlist||| -_new_invlist_C_array||| -_new_invlist||| -_pMY_CXT|5.007003||p -_setup_canned_invlist||| -_swash_inversion_hash||| -_swash_to_invlist||| -_to_fold_latin1||| -_to_uni_fold_flags||5.014000| -_to_upper_title_latin1||| -_to_utf8_fold_flags||5.019009| -_to_utf8_lower_flags||5.019009| -_to_utf8_title_flags||5.019009| -_to_utf8_upper_flags||5.019009| -_warn_problematic_locale|||n -aMY_CXT_|5.007003||p -aMY_CXT|5.007003||p -aTHXR_|5.021008||p -aTHXR|5.021008||p -aTHX_|5.006000||p -aTHX|5.006000||p -aassign_common_vars||| -add_above_Latin1_folds||| -add_cp_to_invlist||| -add_data|||n -add_multi_match||| -add_utf16_textfilter||| -adjust_size_and_find_bucket|||n -advance_one_SB||| -advance_one_WB||| -alloc_maybe_populate_EXACT||| -alloccopstash||| -allocmy||| -amagic_call||| -amagic_cmp_locale||| -amagic_cmp||| -amagic_deref_call||5.013007| -amagic_i_ncmp||| -amagic_is_enabled||| -amagic_ncmp||| -anonymise_cv_maybe||| -any_dup||| -ao||| -append_utf8_from_native_byte||5.019004|n -apply_attrs_my||| -apply_attrs_string||5.006001| -apply_attrs||| -apply||| -assert_uft8_cache_coherent||| -assignment_type||| -atfork_lock||5.007003|n -atfork_unlock||5.007003|n -av_arylen_p||5.009003| -av_clear||| -av_create_and_push||5.009005| -av_create_and_unshift_one||5.009005| -av_delete||5.006000| -av_exists||5.006000| -av_extend_guts||| -av_extend||| -av_fetch||| -av_fill||| -av_iter_p||5.011000| -av_len||| -av_make||| -av_pop||| -av_push||| -av_reify||| -av_shift||| -av_store||| -av_tindex||5.017009| -av_top_index||5.017009| -av_undef||| -av_unshift||| -ax|||n -backup_one_SB||| -backup_one_WB||| -bad_type_gv||| -bad_type_pv||| -bind_match||| -block_end||5.004000| -block_gimme||5.004000| -block_start||5.004000| -blockhook_register||5.013003| -boolSV|5.004000||p -boot_core_PerlIO||| -boot_core_UNIVERSAL||| -boot_core_mro||| -bytes_cmp_utf8||5.013007| -bytes_from_utf8||5.007001| -bytes_to_utf8||5.006001| -call_argv|5.006000||p -call_atexit||5.006000| -call_list||5.004000| -call_method|5.006000||p -call_pv|5.006000||p -call_sv|5.006000||p -caller_cx|5.013005|5.006000|p -calloc||5.007002|n -cando||| -cast_i32||5.006000|n -cast_iv||5.006000|n -cast_ulong||5.006000|n -cast_uv||5.006000|n -check_locale_boundary_crossing||| -check_type_and_open||| -check_uni||| -check_utf8_print||| -checkcomma||| -ckWARN|5.006000||p -ck_entersub_args_core||| -ck_entersub_args_list||5.013006| -ck_entersub_args_proto_or_list||5.013006| -ck_entersub_args_proto||5.013006| -ck_warner_d||5.011001|v -ck_warner||5.011001|v -ckwarn_common||| -ckwarn_d||5.009003| -ckwarn||5.009003| -clear_placeholders||| -clear_special_blocks||| -clone_params_del|||n -clone_params_new|||n -closest_cop||| -cntrl_to_mnemonic|||n -compute_EXACTish|||n -construct_ahocorasick_from_trie||| -cop_fetch_label||5.015001| -cop_free||| -cop_hints_2hv||5.013007| -cop_hints_fetch_pvn||5.013007| -cop_hints_fetch_pvs||5.013007| -cop_hints_fetch_pv||5.013007| -cop_hints_fetch_sv||5.013007| -cop_store_label||5.015001| -cophh_2hv||5.013007| -cophh_copy||5.013007| -cophh_delete_pvn||5.013007| -cophh_delete_pvs||5.013007| -cophh_delete_pv||5.013007| -cophh_delete_sv||5.013007| -cophh_fetch_pvn||5.013007| -cophh_fetch_pvs||5.013007| -cophh_fetch_pv||5.013007| -cophh_fetch_sv||5.013007| -cophh_free||5.013007| -cophh_new_empty||5.021008| -cophh_store_pvn||5.013007| -cophh_store_pvs||5.013007| -cophh_store_pv||5.013007| -cophh_store_sv||5.013007| -core_prototype||| -coresub_op||| -could_it_be_a_POSIX_class|||n -cr_textfilter||| -create_eval_scope||| -croak_memory_wrap||5.019003|n -croak_no_mem|||n -croak_no_modify||5.013003|n -croak_nocontext|||vn -croak_popstack|||n -croak_sv||5.013001| -croak_xs_usage||5.010001|n -croak|||v -csighandler||5.009003|n -current_re_engine||| -curse||| -custom_op_desc||5.007003| -custom_op_get_field||| -custom_op_name||5.007003| -custom_op_register||5.013007| -custom_op_xop||5.013007| -cv_ckproto_len_flags||| -cv_clone_into||| -cv_clone||| -cv_const_sv_or_av|||n -cv_const_sv||5.003070|n -cv_dump||| -cv_forget_slab||| -cv_get_call_checker||5.013006| -cv_name||5.021005| -cv_set_call_checker_flags||5.021004| -cv_set_call_checker||5.013006| -cv_undef_flags||| -cv_undef||| -cvgv_from_hek||| -cvgv_set||| -cvstash_set||| -cx_dump||5.005000| -cx_dup||| -cxinc||| -dAXMARK|5.009003||p -dAX|5.007002||p -dITEMS|5.007002||p -dMARK||| -dMULTICALL||5.009003| -dMY_CXT_SV|5.007003||p -dMY_CXT|5.007003||p -dNOOP|5.006000||p -dORIGMARK||| -dSP||| -dTHR|5.004050||p -dTHXR|5.021008||p -dTHXa|5.006000||p -dTHXoa|5.006000||p -dTHX|5.006000||p -dUNDERBAR|5.009002||p -dVAR|5.009003||p -dXCPT|5.009002||p -dXSARGS||| -dXSI32||| -dXSTARG|5.006000||p -deb_curcv||| -deb_nocontext|||vn -deb_stack_all||| -deb_stack_n||| -debop||5.005000| -debprofdump||5.005000| -debprof||| -debstackptrs||5.007003| -debstack||5.007003| -debug_start_match||| -deb||5.007003|v -defelem_target||| -del_sv||| -delete_eval_scope||| -delimcpy||5.004000|n -deprecate_commaless_var_list||| -despatch_signals||5.007001| -destroy_matcher||| -die_nocontext|||vn -die_sv||5.013001| -die_unwind||| -die|||v -dirp_dup||| -div128||| -djSP||| -do_aexec5||| -do_aexec||| -do_aspawn||| -do_binmode||5.004050| -do_chomp||| -do_close||| -do_delete_local||| -do_dump_pad||| -do_eof||| -do_exec3||| -do_execfree||| -do_exec||| -do_gv_dump||5.006000| -do_gvgv_dump||5.006000| -do_hv_dump||5.006000| -do_ipcctl||| -do_ipcget||| -do_join||| -do_magic_dump||5.006000| -do_msgrcv||| -do_msgsnd||| -do_ncmp||| -do_oddball||| -do_op_dump||5.006000| -do_open6||| -do_open9||5.006000| -do_open_raw||| -do_openn||5.007001| -do_open||5.003070| -do_pmop_dump||5.006000| -do_print||| -do_readline||| -do_seek||| -do_semop||| -do_shmio||| -do_smartmatch||| -do_spawn_nowait||| -do_spawn||| -do_sprintf||| -do_sv_dump||5.006000| -do_sysseek||| -do_tell||| -do_trans_complex_utf8||| -do_trans_complex||| -do_trans_count_utf8||| -do_trans_count||| -do_trans_simple_utf8||| -do_trans_simple||| -do_trans||| -do_vecget||| -do_vecset||| -do_vop||| -docatch||| -doeval||| -dofile||| -dofindlabel||| -doform||| -doing_taint||5.008001|n -dooneliner||| -doopen_pm||| -doparseform||| -dopoptoeval||| -dopoptogiven||| -dopoptolabel||| -dopoptoloop||| -dopoptosub_at||| -dopoptowhen||| -doref||5.009003| -dounwind||| -dowantarray||| -drand48_init_r|||n -drand48_r|||n -dump_all_perl||| -dump_all||5.006000| -dump_c_backtrace||| -dump_eval||5.006000| -dump_exec_pos||| -dump_form||5.006000| -dump_indent||5.006000|v -dump_mstats||| -dump_packsubs_perl||| -dump_packsubs||5.006000| -dump_sub_perl||| -dump_sub||5.006000| -dump_sv_child||| -dump_trie_interim_list||| -dump_trie_interim_table||| -dump_trie||| -dump_vindent||5.006000| -dumpuntil||| -dup_attrlist||| -emulate_cop_io||| -eval_pv|5.006000||p -eval_sv|5.006000||p -exec_failed||| -expect_number||| -fbm_compile||5.005000| -fbm_instr||5.005000| -feature_is_enabled||| -filter_add||| -filter_del||| -filter_gets||| -filter_read||| -finalize_optree||| -finalize_op||| -find_and_forget_pmops||| -find_array_subscript||| -find_beginning||| -find_byclass||| -find_default_stash||| -find_hash_subscript||| -find_in_my_stash||| -find_lexical_cv||| -find_runcv_where||| -find_runcv||5.008001| -find_rundefsv2||| -find_rundefsvoffset||5.009002| -find_rundefsv||5.013002| -find_script||| -find_uninit_var||| -first_symbol|||n -fixup_errno_string||| -foldEQ_latin1||5.013008|n -foldEQ_locale||5.013002|n -foldEQ_utf8_flags||5.013010| -foldEQ_utf8||5.013002| -foldEQ||5.013002|n -fold_constants||| -forbid_setid||| -force_ident_maybe_lex||| -force_ident||| -force_list||| -force_next||| -force_strict_version||| -force_version||| -force_word||| -forget_pmop||| -form_nocontext|||vn -form_short_octal_warning||| -form||5.004000|v -fp_dup||| -fprintf_nocontext|||vn -free_c_backtrace||| -free_global_struct||| -free_tied_hv_pool||| -free_tmps||| -gen_constant_list||| -get_ANYOF_cp_list_for_ssc||| -get_and_check_backslash_N_name||| -get_aux_mg||| -get_av|5.006000||p -get_c_backtrace_dump||| -get_c_backtrace||| -get_context||5.006000|n -get_cvn_flags|5.009005||p -get_cvs|5.011000||p -get_cv|5.006000||p -get_db_sub||| -get_debug_opts||| -get_hash_seed||| -get_hv|5.006000||p -get_invlist_iter_addr|||n -get_invlist_offset_addr|||n -get_invlist_previous_index_addr|||n -get_mstats||| -get_no_modify||| -get_num||| -get_op_descs||5.005000| -get_op_names||5.005000| -get_opargs||| -get_ppaddr||5.006000| -get_re_arg||| -get_sv|5.006000||p -get_vtbl||5.005030| -getcwd_sv||5.007002| -getenv_len||| -glob_2number||| -glob_assign_glob||| -gp_dup||| -gp_free||| -gp_ref||| -grok_atoUV|||n -grok_bin|5.007003||p -grok_bslash_N||| -grok_bslash_c||| -grok_bslash_o||| -grok_bslash_x||| -grok_hex|5.007003||p -grok_infnan||5.021004| -grok_number_flags||5.021002| -grok_number|5.007002||p -grok_numeric_radix|5.007002||p -grok_oct|5.007003||p -group_end||| -gv_AVadd||| -gv_HVadd||| -gv_IOadd||| -gv_SVadd||| -gv_add_by_type||5.011000| -gv_autoload4||5.004000| -gv_autoload_pvn||5.015004| -gv_autoload_pv||5.015004| -gv_autoload_sv||5.015004| -gv_check||| -gv_const_sv||5.009003| -gv_dump||5.006000| -gv_efullname3||5.003070| -gv_efullname4||5.006001| -gv_efullname||| -gv_fetchfile_flags||5.009005| -gv_fetchfile||| -gv_fetchmeth_autoload||5.007003| -gv_fetchmeth_internal||| -gv_fetchmeth_pv_autoload||5.015004| -gv_fetchmeth_pvn_autoload||5.015004| -gv_fetchmeth_pvn||5.015004| -gv_fetchmeth_pv||5.015004| -gv_fetchmeth_sv_autoload||5.015004| -gv_fetchmeth_sv||5.015004| -gv_fetchmethod_autoload||5.004000| -gv_fetchmethod_pv_flags||5.015004| -gv_fetchmethod_pvn_flags||5.015004| -gv_fetchmethod_sv_flags||5.015004| -gv_fetchmethod||| -gv_fetchmeth||| -gv_fetchpvn_flags|5.009002||p -gv_fetchpvs|5.009004||p -gv_fetchpv||| -gv_fetchsv|5.009002||p -gv_fullname3||5.003070| -gv_fullname4||5.006001| -gv_fullname||| -gv_handler||5.007001| -gv_init_pvn||5.015004| -gv_init_pv||5.015004| -gv_init_svtype||| -gv_init_sv||5.015004| -gv_init||| -gv_is_in_main||| -gv_magicalize_isa||| -gv_magicalize||| -gv_name_set||5.009004| -gv_override||| -gv_setref||| -gv_stashpvn_internal||| -gv_stashpvn|5.003070||p -gv_stashpvs|5.009003||p -gv_stashpv||| -gv_stashsvpvn_cached||| -gv_stashsv||| -gv_try_downgrade||| -handle_regex_sets||| -he_dup||| -hek_dup||| -hfree_next_entry||| -hfreeentries||| -hsplit||| -hv_assert||| -hv_auxinit_internal|||n -hv_auxinit||| -hv_backreferences_p||| -hv_clear_placeholders||5.009001| -hv_clear||| -hv_common_key_len||5.010000| -hv_common||5.010000| -hv_copy_hints_hv||5.009004| -hv_delayfree_ent||5.004000| -hv_delete_common||| -hv_delete_ent||5.003070| -hv_delete||| -hv_eiter_p||5.009003| -hv_eiter_set||5.009003| -hv_ename_add||| -hv_ename_delete||| -hv_exists_ent||5.003070| -hv_exists||| -hv_fetch_ent||5.003070| -hv_fetchs|5.009003||p -hv_fetch||| -hv_fill||5.013002| -hv_free_ent_ret||| -hv_free_ent||5.004000| -hv_iterinit||| -hv_iterkeysv||5.003070| -hv_iterkey||| -hv_iternext_flags||5.008000| -hv_iternextsv||| -hv_iternext||| -hv_iterval||| -hv_kill_backrefs||| -hv_ksplit||5.003070| -hv_magic_check|||n -hv_magic||| -hv_name_set||5.009003| -hv_notallowed||| -hv_placeholders_get||5.009003| -hv_placeholders_p||| -hv_placeholders_set||5.009003| -hv_rand_set||5.018000| -hv_riter_p||5.009003| -hv_riter_set||5.009003| -hv_scalar||5.009001| -hv_store_ent||5.003070| -hv_store_flags||5.008000| -hv_stores|5.009004||p -hv_store||| -hv_undef_flags||| -hv_undef||| -ibcmp_locale||5.004000| -ibcmp_utf8||5.007003| -ibcmp||| -incline||| -incpush_if_exists||| -incpush_use_sep||| -incpush||| -ingroup||| -init_argv_symbols||| -init_constants||| -init_dbargs||| -init_debugger||| -init_global_struct||| -init_i18nl10n||5.006000| -init_i18nl14n||5.006000| -init_ids||| -init_interp||| -init_main_stash||| -init_perllib||| -init_postdump_symbols||| -init_predump_symbols||| -init_stacks||5.005000| -init_tm||5.007002| -inplace_aassign||| -instr|||n -intro_my||5.004000| -intuit_method||| -intuit_more||| -invert||| -invlist_array|||n -invlist_clone||| -invlist_extend||| -invlist_highest|||n -invlist_is_iterating|||n -invlist_iterfinish|||n -invlist_iterinit|||n -invlist_iternext|||n -invlist_max|||n -invlist_previous_index|||n -invlist_set_len||| -invlist_set_previous_index|||n -invlist_trim|||n -invoke_exception_hook||| -io_close||| -isALNUMC|5.006000||p -isALNUM_lazy||5.021001| -isALPHANUMERIC||5.017008| -isALPHA||| -isASCII|5.006000||p -isBLANK|5.006001||p -isCNTRL|5.006000||p -isDIGIT||| -isFOO_lc||| -isFOO_utf8_lc||| -isGCB|||n -isGRAPH|5.006000||p -isGV_with_GP|5.009004||p -isIDCONT||5.017008| -isIDFIRST_lazy||5.021001| -isIDFIRST||| -isLOWER||| -isOCTAL||5.013005| -isPRINT|5.004000||p -isPSXSPC|5.006001||p -isPUNCT|5.006000||p -isSB||| -isSPACE||| -isUPPER||| -isUTF8_CHAR||5.021001| -isWB||| -isWORDCHAR||5.013006| -isXDIGIT|5.006000||p -is_an_int||| -is_ascii_string||5.011000| -is_handle_constructor|||n -is_invariant_string||5.021007|n -is_lvalue_sub||5.007001| -is_safe_syscall||5.019004| -is_ssc_worth_it|||n -is_uni_alnum_lc||5.006000| -is_uni_alnumc_lc||5.017007| -is_uni_alnumc||5.017007| -is_uni_alnum||5.006000| -is_uni_alpha_lc||5.006000| -is_uni_alpha||5.006000| -is_uni_ascii_lc||5.006000| -is_uni_ascii||5.006000| -is_uni_blank_lc||5.017002| -is_uni_blank||5.017002| -is_uni_cntrl_lc||5.006000| -is_uni_cntrl||5.006000| -is_uni_digit_lc||5.006000| -is_uni_digit||5.006000| -is_uni_graph_lc||5.006000| -is_uni_graph||5.006000| -is_uni_idfirst_lc||5.006000| -is_uni_idfirst||5.006000| -is_uni_lower_lc||5.006000| -is_uni_lower||5.006000| -is_uni_print_lc||5.006000| -is_uni_print||5.006000| -is_uni_punct_lc||5.006000| -is_uni_punct||5.006000| -is_uni_space_lc||5.006000| -is_uni_space||5.006000| -is_uni_upper_lc||5.006000| -is_uni_upper||5.006000| -is_uni_xdigit_lc||5.006000| -is_uni_xdigit||5.006000| -is_utf8_alnumc||5.017007| -is_utf8_alnum||5.006000| -is_utf8_alpha||5.006000| -is_utf8_ascii||5.006000| -is_utf8_blank||5.017002| -is_utf8_char_buf||5.015008|n -is_utf8_char||5.006000|n -is_utf8_cntrl||5.006000| -is_utf8_common||| -is_utf8_digit||5.006000| -is_utf8_graph||5.006000| -is_utf8_idcont||5.008000| -is_utf8_idfirst||5.006000| -is_utf8_lower||5.006000| -is_utf8_mark||5.006000| -is_utf8_perl_space||5.011001| -is_utf8_perl_word||5.011001| -is_utf8_posix_digit||5.011001| -is_utf8_print||5.006000| -is_utf8_punct||5.006000| -is_utf8_space||5.006000| -is_utf8_string_loclen||5.009003|n -is_utf8_string_loc||5.008001|n -is_utf8_string||5.006001|n -is_utf8_upper||5.006000| -is_utf8_xdigit||5.006000| -is_utf8_xidcont||5.013010| -is_utf8_xidfirst||5.013010| -isa_lookup||| -isinfnansv||| -isinfnan||5.021004|n -items|||n -ix|||n -jmaybe||| -join_exact||| -keyword_plugin_standard||| -keyword||| -leave_common||| -leave_scope||| -lex_bufutf8||5.011002| -lex_discard_to||5.011002| -lex_grow_linestr||5.011002| -lex_next_chunk||5.011002| -lex_peek_unichar||5.011002| -lex_read_space||5.011002| -lex_read_to||5.011002| -lex_read_unichar||5.011002| -lex_start||5.009005| -lex_stuff_pvn||5.011002| -lex_stuff_pvs||5.013005| -lex_stuff_pv||5.013006| -lex_stuff_sv||5.011002| -lex_unstuff||5.011002| -listkids||| -list||| -load_module_nocontext|||vn -load_module|5.006000||pv -localize||| -looks_like_bool||| -looks_like_number||| -lop||| -mPUSHi|5.009002||p -mPUSHn|5.009002||p -mPUSHp|5.009002||p -mPUSHs|5.010001||p -mPUSHu|5.009002||p -mXPUSHi|5.009002||p -mXPUSHn|5.009002||p -mXPUSHp|5.009002||p -mXPUSHs|5.010001||p -mXPUSHu|5.009002||p -magic_clear_all_env||| -magic_cleararylen_p||| -magic_clearenv||| -magic_clearhints||| -magic_clearhint||| -magic_clearisa||| -magic_clearpack||| -magic_clearsig||| -magic_copycallchecker||| -magic_dump||5.006000| -magic_existspack||| -magic_freearylen_p||| -magic_freeovrld||| -magic_getarylen||| -magic_getdebugvar||| -magic_getdefelem||| -magic_getnkeys||| -magic_getpack||| -magic_getpos||| -magic_getsig||| -magic_getsubstr||| -magic_gettaint||| -magic_getuvar||| -magic_getvec||| -magic_get||| -magic_killbackrefs||| -magic_methcall1||| -magic_methcall|||v -magic_methpack||| -magic_nextpack||| -magic_regdata_cnt||| -magic_regdatum_get||| -magic_regdatum_set||| -magic_scalarpack||| -magic_set_all_env||| -magic_setarylen||| -magic_setcollxfrm||| -magic_setdbline||| -magic_setdebugvar||| -magic_setdefelem||| -magic_setenv||| -magic_sethint||| -magic_setisa||| -magic_setlvref||| -magic_setmglob||| -magic_setnkeys||| -magic_setpack||| -magic_setpos||| -magic_setregexp||| -magic_setsig||| -magic_setsubstr||| -magic_settaint||| -magic_setutf8||| -magic_setuvar||| -magic_setvec||| -magic_set||| -magic_sizepack||| -magic_wipepack||| -make_matcher||| -make_trie||| -malloc_good_size|||n -malloced_size|||n -malloc||5.007002|n -markstack_grow||5.021001| -matcher_matches_sv||| -maybe_multimagic_gv||| -mayberelocate||| -measure_struct||| -memEQs|5.009005||p -memEQ|5.004000||p -memNEs|5.009005||p -memNE|5.004000||p -mem_collxfrm||| -mem_log_common|||n -mess_alloc||| -mess_nocontext|||vn -mess_sv||5.013001| -mess||5.006000|v -mfree||5.007002|n -mg_clear||| -mg_copy||| -mg_dup||| -mg_find_mglob||| -mg_findext|5.013008||pn -mg_find|||n -mg_free_type||5.013006| -mg_free||| -mg_get||| -mg_length||5.005000| -mg_localize||| -mg_magical|||n -mg_set||| -mg_size||5.005000| -mini_mktime||5.007002|n -minus_v||| -missingterm||| -mode_from_discipline||| -modkids||| -more_bodies||| -more_sv||| -moreswitches||| -move_proto_attr||| -mro_clean_isarev||| -mro_gather_and_rename||| -mro_get_from_name||5.010001| -mro_get_linear_isa_dfs||| -mro_get_linear_isa||5.009005| -mro_get_private_data||5.010001| -mro_isa_changed_in||| -mro_meta_dup||| -mro_meta_init||| -mro_method_changed_in||5.009005| -mro_package_moved||| -mro_register||5.010001| -mro_set_mro||5.010001| -mro_set_private_data||5.010001| -mul128||| -mulexp10|||n -multideref_stringify||| -my_atof2||5.007002| -my_atof||5.006000| -my_attrs||| -my_bcopy|||n -my_bytes_to_utf8|||n -my_bzero|||n -my_chsize||| -my_clearenv||| -my_cxt_index||| -my_cxt_init||| -my_dirfd||5.009005|n -my_exit_jump||| -my_exit||| -my_failure_exit||5.004000| -my_fflush_all||5.006000| -my_fork||5.007003|n -my_kid||| -my_lstat_flags||| -my_lstat||5.021008| -my_memcmp|||n -my_memset|||n -my_pclose||5.003070| -my_popen_list||5.007001| -my_popen||5.003070| -my_setenv||| -my_setlocale||| -my_snprintf|5.009004||pvn -my_socketpair||5.007003|n -my_sprintf|5.009003||pvn -my_stat_flags||| -my_stat||5.021008| -my_strerror||5.021001| -my_strftime||5.007002| -my_strlcat|5.009004||pn -my_strlcpy|5.009004||pn -my_unexec||| -my_vsnprintf||5.009004|n -need_utf8|||n -newANONATTRSUB||5.006000| -newANONHASH||| -newANONLIST||| -newANONSUB||| -newASSIGNOP||| -newATTRSUB_x||| -newATTRSUB||5.006000| -newAVREF||| -newAV||| -newBINOP||| -newCONDOP||| -newCONSTSUB_flags||5.015006| -newCONSTSUB|5.004050||p -newCVREF||| -newDEFSVOP||5.021006| -newFORM||| -newFOROP||5.013007| -newGIVENOP||5.009003| -newGIVWHENOP||| -newGP||| -newGVOP||| -newGVREF||| -newGVgen_flags||5.015004| -newGVgen||| -newHVREF||| -newHVhv||5.005000| -newHV||| -newIO||| -newLISTOP||| -newLOGOP||| -newLOOPEX||| -newLOOPOP||| -newMETHOP_internal||| -newMETHOP_named||5.021005| -newMETHOP||5.021005| -newMYSUB||5.017004| -newNULLLIST||| -newOP||| -newPADNAMELIST||5.021007|n -newPADNAMEouter||5.021007|n -newPADNAMEpvn||5.021007|n -newPADOP||| -newPMOP||| -newPROG||| -newPVOP||| -newRANGE||| -newRV_inc|5.004000||p -newRV_noinc|5.004000||p -newRV||| -newSLICEOP||| -newSTATEOP||| -newSTUB||| -newSUB||| -newSVOP||| -newSVREF||| -newSV_type|5.009005||p -newSVavdefelem||| -newSVhek||5.009003| -newSViv||| -newSVnv||| -newSVpadname||5.017004| -newSVpv_share||5.013006| -newSVpvf_nocontext|||vn -newSVpvf||5.004000|v -newSVpvn_flags|5.010001||p -newSVpvn_share|5.007001||p -newSVpvn_utf8|5.010001||p -newSVpvn|5.004050||p -newSVpvs_flags|5.010001||p -newSVpvs_share|5.009003||p -newSVpvs|5.009003||p -newSVpv||| -newSVrv||| -newSVsv||| -newSVuv|5.006000||p -newSV||| -newUNOP_AUX||5.021007| -newUNOP||| -newWHENOP||5.009003| -newWHILEOP||5.013007| -newXS_deffile||| -newXS_flags||5.009004| -newXS_len_flags||| -newXSproto||5.006000| -newXS||5.006000| -new_collate||5.006000| -new_constant||| -new_ctype||5.006000| -new_he||| -new_logop||| -new_numeric||5.006000| -new_stackinfo||5.005000| -new_version||5.009000| -new_warnings_bitfield||| -next_symbol||| -nextargv||| -nextchar||| -ninstr|||n -no_bareword_allowed||| -no_fh_allowed||| -no_op||| -noperl_die|||vn -not_a_number||| -not_incrementable||| -nothreadhook||5.008000| -nuke_stacks||| -num_overflow|||n -oopsAV||| -oopsHV||| -op_append_elem||5.013006| -op_append_list||5.013006| -op_clear||| -op_contextualize||5.013006| -op_convert_list||5.021006| -op_dump||5.006000| -op_free||| -op_integerize||| -op_linklist||5.013006| -op_lvalue_flags||| -op_lvalue||5.013007| -op_null||5.007002| -op_parent||5.021002|n -op_prepend_elem||5.013006| -op_refcnt_dec||| -op_refcnt_inc||| -op_refcnt_lock||5.009002| -op_refcnt_unlock||5.009002| -op_relocate_sv||| -op_scope||5.013007| -op_sibling_splice||5.021002|n -op_std_init||| -op_unscope||| -open_script||| -openn_cleanup||| -openn_setup||| -opmethod_stash||| -opslab_force_free||| -opslab_free_nopad||| -opslab_free||| -pMY_CXT_|5.007003||p -pMY_CXT|5.007003||p -pTHX_|5.006000||p -pTHX|5.006000||p -packWARN|5.007003||p -pack_cat||5.007003| -pack_rec||| -package_version||| -package||| -packlist||5.008001| -pad_add_anon||5.008001| -pad_add_name_pvn||5.015001| -pad_add_name_pvs||5.015001| -pad_add_name_pv||5.015001| -pad_add_name_sv||5.015001| -pad_add_weakref||| -pad_alloc_name||| -pad_alloc||| -pad_block_start||| -pad_check_dup||| -pad_compname_type||5.009003| -pad_findlex||| -pad_findmy_pvn||5.015001| -pad_findmy_pvs||5.015001| -pad_findmy_pv||5.015001| -pad_findmy_sv||5.015001| -pad_fixup_inner_anons||| -pad_free||| -pad_leavemy||| -pad_new||5.008001| -pad_push||| -pad_reset||| -pad_setsv||| -pad_sv||| -pad_swipe||| -pad_tidy||5.008001| -padlist_dup||| -padlist_store||| -padname_dup||| -padname_free||| -padnamelist_dup||| -padnamelist_fetch||5.021007|n -padnamelist_free||| -padnamelist_store||5.021007| -parse_arithexpr||5.013008| -parse_barestmt||5.013007| -parse_block||5.013007| -parse_body||| -parse_fullexpr||5.013008| -parse_fullstmt||5.013005| -parse_gv_stash_name||| -parse_ident||| -parse_label||5.013007| -parse_listexpr||5.013008| -parse_lparen_question_flags||| -parse_stmtseq||5.013006| -parse_subsignature||| -parse_termexpr||5.013008| -parse_unicode_opts||| -parser_dup||| -parser_free_nexttoke_ops||| -parser_free||| -path_is_searchable|||n -peep||| -pending_ident||| -perl_alloc_using|||n -perl_alloc|||n -perl_clone_using|||n -perl_clone|||n -perl_construct|||n -perl_destruct||5.007003|n -perl_free|||n -perl_parse||5.006000|n -perl_run|||n -pidgone||| -pm_description||| -pmop_dump||5.006000| -pmruntime||| -pmtrans||| -pop_scope||| -populate_ANYOF_from_invlist||| -populate_isa|||v -pregcomp||5.009005| -pregexec||| -pregfree2||5.011000| -pregfree||| -prescan_version||5.011004| -printbuf||| -printf_nocontext|||vn -process_special_blocks||| -ptr_hash|||n -ptr_table_clear||5.009005| -ptr_table_fetch||5.009005| -ptr_table_find|||n -ptr_table_free||5.009005| -ptr_table_new||5.009005| -ptr_table_split||5.009005| -ptr_table_store||5.009005| -push_scope||| -put_charclass_bitmap_innards||| -put_code_point||| -put_range||| -pv_display|5.006000||p -pv_escape|5.009004||p -pv_pretty|5.009004||p -pv_uni_display||5.007003| -qerror||| -qsortsvu||| -quadmath_format_needed|||n -quadmath_format_single|||n -re_compile||5.009005| -re_croak2||| -re_dup_guts||| -re_intuit_start||5.019001| -re_intuit_string||5.006000| -re_op_compile||| -realloc||5.007002|n -reentrant_free||5.021008| -reentrant_init||5.021008| -reentrant_retry||5.021008|vn -reentrant_size||5.021008| -ref_array_or_hash||| -refcounted_he_chain_2hv||| -refcounted_he_fetch_pvn||| -refcounted_he_fetch_pvs||| -refcounted_he_fetch_pv||| -refcounted_he_fetch_sv||| -refcounted_he_free||| -refcounted_he_inc||| -refcounted_he_new_pvn||| -refcounted_he_new_pvs||| -refcounted_he_new_pv||| -refcounted_he_new_sv||| -refcounted_he_value||| -refkids||| -refto||| -ref||5.021008| -reg2Lanode||| -reg_check_named_buff_matched|||n -reg_named_buff_all||5.009005| -reg_named_buff_exists||5.009005| -reg_named_buff_fetch||5.009005| -reg_named_buff_firstkey||5.009005| -reg_named_buff_iter||| -reg_named_buff_nextkey||5.009005| -reg_named_buff_scalar||5.009005| -reg_named_buff||| -reg_node||| -reg_numbered_buff_fetch||| -reg_numbered_buff_length||| -reg_numbered_buff_store||| -reg_qr_package||| -reg_recode||| -reg_scan_name||| -reg_skipcomment|||n -reg_temp_copy||| -reganode||| -regatom||| -regbranch||| -regclass_swash||5.009004| -regclass||| -regcppop||| -regcppush||| -regcurly|||n -regdump_extflags||| -regdump_intflags||| -regdump||5.005000| -regdupe_internal||| -regexec_flags||5.005000| -regfree_internal||5.009005| -reghop3|||n -reghop4|||n -reghopmaybe3|||n -reginclass||| -reginitcolors||5.006000| -reginsert||| -regmatch||| -regnext||5.005000| -regnode_guts||| -regpatws|||n -regpiece||| -regpposixcc||| -regprop||| -regrepeat||| -regtail_study||| -regtail||| -regtry||| -reg||| -repeatcpy|||n -report_evil_fh||| -report_redefined_cv||| -report_uninit||| -report_wrongway_fh||| -require_pv||5.006000| -require_tie_mod||| -restore_magic||| -rninstr|||n -rpeep||| -rsignal_restore||| -rsignal_save||| -rsignal_state||5.004000| -rsignal||5.004000| -run_body||| -run_user_filter||| -runops_debug||5.005000| -runops_standard||5.005000| -rv2cv_op_cv||5.013006| -rvpv_dup||| -rxres_free||| -rxres_restore||| -rxres_save||| -safesyscalloc||5.006000|n -safesysfree||5.006000|n -safesysmalloc||5.006000|n -safesysrealloc||5.006000|n -same_dirent||| -save_I16||5.004000| -save_I32||| -save_I8||5.006000| -save_adelete||5.011000| -save_aelem_flags||5.011000| -save_aelem||5.004050| -save_aliased_sv||| -save_alloc||5.006000| -save_aptr||| -save_ary||| -save_bool||5.008001| -save_clearsv||| -save_delete||| -save_destructor_x||5.006000| -save_destructor||5.006000| -save_freeop||| -save_freepv||| -save_freesv||| -save_generic_pvref||5.006001| -save_generic_svref||5.005030| -save_gp||5.004000| -save_hash||| -save_hdelete||5.011000| -save_hek_flags|||n -save_helem_flags||5.011000| -save_helem||5.004050| -save_hints||5.010001| -save_hptr||| -save_int||| -save_item||| -save_iv||5.005000| -save_lines||| -save_list||| -save_long||| -save_magic_flags||| -save_mortalizesv||5.007001| -save_nogv||| -save_op||5.005000| -save_padsv_and_mortalize||5.010001| -save_pptr||| -save_pushi32ptr||5.010001| -save_pushptri32ptr||| -save_pushptrptr||5.010001| -save_pushptr||5.010001| -save_re_context||5.006000| -save_scalar_at||| -save_scalar||| -save_set_svflags||5.009000| -save_shared_pvref||5.007003| -save_sptr||| -save_strlen||| -save_svref||| -save_vptr||5.006000| -savepvn||| -savepvs||5.009003| -savepv||| -savesharedpvn||5.009005| -savesharedpvs||5.013006| -savesharedpv||5.007003| -savesharedsvpv||5.013006| -savestack_grow_cnt||5.008001| -savestack_grow||| -savesvpv||5.009002| -sawparens||| -scalar_mod_type|||n -scalarboolean||| -scalarkids||| -scalarseq||| -scalarvoid||| -scalar||| -scan_bin||5.006000| -scan_commit||| -scan_const||| -scan_formline||| -scan_heredoc||| -scan_hex||| -scan_ident||| -scan_inputsymbol||| -scan_num||5.007001| -scan_oct||| -scan_pat||| -scan_str||| -scan_subst||| -scan_trans||| -scan_version||5.009001| -scan_vstring||5.009005| -scan_word||| -search_const||| -seed||5.008001| -sequence_num||| -set_ANYOF_arg||| -set_caret_X||| -set_context||5.006000|n -set_numeric_local||5.006000| -set_numeric_radix||5.006000| -set_numeric_standard||5.006000| -set_padlist|||n -setdefout||| -share_hek_flags||| -share_hek||5.004000| -should_warn_nl|||n -si_dup||| -sighandler|||n -simplify_sort||| -skipspace_flags||| -softref2xv||| -sortcv_stacked||| -sortcv_xsub||| -sortcv||| -sortsv_flags||5.009003| -sortsv||5.007003| -space_join_names_mortal||| -ss_dup||| -ssc_add_range||| -ssc_and||| -ssc_anything||| -ssc_clear_locale|||n -ssc_cp_and||| -ssc_finalize||| -ssc_init||| -ssc_intersection||| -ssc_is_anything|||n -ssc_is_cp_posixl_init|||n -ssc_or||| -ssc_union||| -stack_grow||| -start_glob||| -start_subparse||5.004000| -stdize_locale||| -strEQ||| -strGE||| -strGT||| -strLE||| -strLT||| -strNE||| -str_to_version||5.006000| -strip_return||| -strnEQ||| -strnNE||| -study_chunk||| -sub_crush_depth||| -sublex_done||| -sublex_push||| -sublex_start||| -sv_2bool_flags||5.013006| -sv_2bool||| -sv_2cv||| -sv_2io||| -sv_2iuv_common||| -sv_2iuv_non_preserve||| -sv_2iv_flags||5.009001| -sv_2iv||| -sv_2mortal||| -sv_2num||| -sv_2nv_flags||5.013001| -sv_2pv_flags|5.007002||p -sv_2pv_nolen|5.006000||p -sv_2pvbyte_nolen|5.006000||p -sv_2pvbyte|5.006000||p -sv_2pvutf8_nolen||5.006000| -sv_2pvutf8||5.006000| -sv_2pv||| -sv_2uv_flags||5.009001| -sv_2uv|5.004000||p -sv_add_arena||| -sv_add_backref||| -sv_backoff|||n -sv_bless||| -sv_buf_to_ro||| -sv_buf_to_rw||| -sv_cat_decode||5.008001| -sv_catpv_flags||5.013006| -sv_catpv_mg|5.004050||p -sv_catpv_nomg||5.013006| -sv_catpvf_mg_nocontext|||pvn -sv_catpvf_mg|5.006000|5.004000|pv -sv_catpvf_nocontext|||vn -sv_catpvf||5.004000|v -sv_catpvn_flags||5.007002| -sv_catpvn_mg|5.004050||p -sv_catpvn_nomg|5.007002||p -sv_catpvn||| -sv_catpvs_flags||5.013006| -sv_catpvs_mg||5.013006| -sv_catpvs_nomg||5.013006| -sv_catpvs|5.009003||p -sv_catpv||| -sv_catsv_flags||5.007002| -sv_catsv_mg|5.004050||p -sv_catsv_nomg|5.007002||p -sv_catsv||| -sv_chop||| -sv_clean_all||| -sv_clean_objs||| -sv_clear||| -sv_cmp_flags||5.013006| -sv_cmp_locale_flags||5.013006| -sv_cmp_locale||5.004000| -sv_cmp||| -sv_collxfrm_flags||5.013006| -sv_collxfrm||| -sv_copypv_flags||5.017002| -sv_copypv_nomg||5.017002| -sv_copypv||| -sv_dec_nomg||5.013002| -sv_dec||| -sv_del_backref||| -sv_derived_from_pvn||5.015004| -sv_derived_from_pv||5.015004| -sv_derived_from_sv||5.015004| -sv_derived_from||5.004000| -sv_destroyable||5.010000| -sv_display||| -sv_does_pvn||5.015004| -sv_does_pv||5.015004| -sv_does_sv||5.015004| -sv_does||5.009004| -sv_dump||| -sv_dup_common||| -sv_dup_inc_multiple||| -sv_dup_inc||| -sv_dup||| -sv_eq_flags||5.013006| -sv_eq||| -sv_exp_grow||| -sv_force_normal_flags||5.007001| -sv_force_normal||5.006000| -sv_free2||| -sv_free_arenas||| -sv_free||| -sv_get_backrefs||5.021008|n -sv_gets||5.003070| -sv_grow||| -sv_i_ncmp||| -sv_inc_nomg||5.013002| -sv_inc||| -sv_insert_flags||5.010001| -sv_insert||| -sv_isa||| -sv_isobject||| -sv_iv||5.005000| -sv_kill_backrefs||| -sv_len_utf8_nomg||| -sv_len_utf8||5.006000| -sv_len||| -sv_magic_portable|5.021008|5.004000|p -sv_magicext_mglob||| -sv_magicext||5.007003| -sv_magic||| -sv_mortalcopy_flags||| -sv_mortalcopy||| -sv_ncmp||| -sv_newmortal||| -sv_newref||| -sv_nolocking||5.007003| -sv_nosharing||5.007003| -sv_nounlocking||| -sv_nv||5.005000| -sv_only_taint_gmagic|||n -sv_or_pv_pos_u2b||| -sv_peek||5.005000| -sv_pos_b2u_flags||5.019003| -sv_pos_b2u_midway||| -sv_pos_b2u||5.006000| -sv_pos_u2b_cached||| -sv_pos_u2b_flags||5.011005| -sv_pos_u2b_forwards|||n -sv_pos_u2b_midway|||n -sv_pos_u2b||5.006000| -sv_pvbyten_force||5.006000| -sv_pvbyten||5.006000| -sv_pvbyte||5.006000| -sv_pvn_force_flags|5.007002||p -sv_pvn_force||| -sv_pvn_nomg|5.007003|5.005000|p -sv_pvn||5.005000| -sv_pvutf8n_force||5.006000| -sv_pvutf8n||5.006000| -sv_pvutf8||5.006000| -sv_pv||5.006000| -sv_recode_to_utf8||5.007003| -sv_reftype||| -sv_ref||| -sv_release_COW||| -sv_replace||| -sv_report_used||| -sv_resetpvn||| -sv_reset||| -sv_rvweaken||5.006000| -sv_sethek||| -sv_setiv_mg|5.004050||p -sv_setiv||| -sv_setnv_mg|5.006000||p -sv_setnv||| -sv_setpv_mg|5.004050||p -sv_setpvf_mg_nocontext|||pvn -sv_setpvf_mg|5.006000|5.004000|pv -sv_setpvf_nocontext|||vn -sv_setpvf||5.004000|v -sv_setpviv_mg||5.008001| -sv_setpviv||5.008001| -sv_setpvn_mg|5.004050||p -sv_setpvn||| -sv_setpvs_mg||5.013006| -sv_setpvs|5.009004||p -sv_setpv||| -sv_setref_iv||| -sv_setref_nv||| -sv_setref_pvn||| -sv_setref_pvs||5.021008| -sv_setref_pv||| -sv_setref_uv||5.007001| -sv_setsv_cow||| -sv_setsv_flags||5.007002| -sv_setsv_mg|5.004050||p -sv_setsv_nomg|5.007002||p -sv_setsv||| -sv_setuv_mg|5.004050||p -sv_setuv|5.004000||p -sv_tainted||5.004000| -sv_taint||5.004000| -sv_true||5.005000| -sv_unglob||| -sv_uni_display||5.007003| -sv_unmagicext|5.013008||p -sv_unmagic||| -sv_unref_flags||5.007001| -sv_unref||| -sv_untaint||5.004000| -sv_upgrade||| -sv_usepvn_flags||5.009004| -sv_usepvn_mg|5.004050||p -sv_usepvn||| -sv_utf8_decode||5.006000| -sv_utf8_downgrade||5.006000| -sv_utf8_encode||5.006000| -sv_utf8_upgrade_flags_grow||5.011000| -sv_utf8_upgrade_flags||5.007002| -sv_utf8_upgrade_nomg||5.007002| -sv_utf8_upgrade||5.007001| -sv_uv|5.005000||p -sv_vcatpvf_mg|5.006000|5.004000|p -sv_vcatpvfn_flags||5.017002| -sv_vcatpvfn||5.004000| -sv_vcatpvf|5.006000|5.004000|p -sv_vsetpvf_mg|5.006000|5.004000|p -sv_vsetpvfn||5.004000| -sv_vsetpvf|5.006000|5.004000|p -svtype||| -swallow_bom||| -swash_fetch||5.007002| -swash_init||5.006000| -swash_scan_list_line||| -swatch_get||| -sync_locale||5.021004| -sys_init3||5.010000|n -sys_init||5.010000|n -sys_intern_clear||| -sys_intern_dup||| -sys_intern_init||| -sys_term||5.010000|n -taint_env||| -taint_proper||| -tied_method|||v -tmps_grow_p||| -toFOLD_uni||5.007003| -toFOLD_utf8||5.019001| -toFOLD||5.019001| -toLOWER_L1||5.019001| -toLOWER_LC||5.004000| -toLOWER_uni||5.007003| -toLOWER_utf8||5.015007| -toLOWER||| -toTITLE_uni||5.007003| -toTITLE_utf8||5.015007| -toTITLE||5.019001| -toUPPER_uni||5.007003| -toUPPER_utf8||5.015007| -toUPPER||| -to_byte_substr||| -to_lower_latin1|||n -to_uni_fold||5.007003| -to_uni_lower_lc||5.006000| -to_uni_lower||5.007003| -to_uni_title_lc||5.006000| -to_uni_title||5.007003| -to_uni_upper_lc||5.006000| -to_uni_upper||5.007003| -to_utf8_case||5.007003| -to_utf8_fold||5.015007| -to_utf8_lower||5.015007| -to_utf8_substr||| -to_utf8_title||5.015007| -to_utf8_upper||5.015007| -tokenize_use||| -tokeq||| -tokereport||| -too_few_arguments_pv||| -too_many_arguments_pv||| -translate_substr_offsets|||n -try_amagic_bin||| -try_amagic_un||| -uiv_2buf|||n -unlnk||| -unpack_rec||| -unpack_str||5.007003| -unpackstring||5.008001| -unreferenced_to_tmp_stack||| -unshare_hek_or_pvn||| -unshare_hek||| -unsharepvn||5.003070| -unwind_handler_stack||| -update_debugger_info||| -upg_version||5.009005| -usage||| -utf16_textfilter||| -utf16_to_utf8_reversed||5.006001| -utf16_to_utf8||5.006001| -utf8_distance||5.006000| -utf8_hop||5.006000|n -utf8_length||5.007001| -utf8_mg_len_cache_update||| -utf8_mg_pos_cache_update||| -utf8_to_bytes||5.006001| -utf8_to_uvchr_buf||5.015009| -utf8_to_uvchr||5.007001| -utf8_to_uvuni_buf||5.015009| -utf8_to_uvuni||5.007001| -utf8n_to_uvchr||5.007001| -utf8n_to_uvuni||5.007001| -utilize||| -uvchr_to_utf8_flags||5.007003| -uvchr_to_utf8||5.007001| -uvoffuni_to_utf8_flags||5.019004| -uvuni_to_utf8_flags||5.007003| -uvuni_to_utf8||5.007001| -valid_utf8_to_uvchr||5.015009| -valid_utf8_to_uvuni||5.015009| -validate_proto||| -validate_suid||| -varname||| -vcmp||5.009000| -vcroak||5.006000| -vdeb||5.007003| -vform||5.006000| -visit||| -vivify_defelem||| -vivify_ref||| -vload_module|5.006000||p -vmess||5.006000| -vnewSVpvf|5.006000|5.004000|p -vnormal||5.009002| -vnumify||5.009000| -vstringify||5.009000| -vverify||5.009003| -vwarner||5.006000| -vwarn||5.006000| -wait4pid||| -warn_nocontext|||vn -warn_sv||5.013001| -warner_nocontext|||vn -warner|5.006000|5.004000|pv -warn|||v -was_lvalue_sub||| -watch||| -whichsig_pvn||5.015004| -whichsig_pv||5.015004| -whichsig_sv||5.015004| -whichsig||| -win32_croak_not_implemented|||n -with_queued_errors||| -wrap_op_checker||5.015008| -write_to_stderr||| -xs_boot_epilog||| -xs_handshake|||vn -xs_version_bootcheck||| -yyerror_pvn||| -yyerror_pv||| -yyerror||| -yylex||| -yyparse||| -yyunlex||| -yywarn||| -); - -if (exists $opt{'list-unsupported'}) { - my $f; - for $f (sort { lc $a cmp lc $b } keys %API) { - next unless $API{$f}{todo}; - print "$f ", '.'x(40-length($f)), " ", format_version($API{$f}{todo}), "\n"; - } - exit 0; -} - -# Scan for possible replacement candidates - -my(%replace, %need, %hints, %warnings, %depends); -my $replace = 0; -my($hint, $define, $function); - -sub find_api -{ - my $code = shift; - $code =~ s{ - / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*) - | "[^"\\]*(?:\\.[^"\\]*)*" - | '[^'\\]*(?:\\.[^'\\]*)*' }{}egsx; - grep { exists $API{$_} } $code =~ /(\w+)/mg; -} - -while () { - if ($hint) { - my $h = $hint->[0] eq 'Hint' ? \%hints : \%warnings; - if (m{^\s*\*\s(.*?)\s*$}) { - for (@{$hint->[1]}) { - $h->{$_} ||= ''; # suppress warning with older perls - $h->{$_} .= "$1\n"; - } - } - else { undef $hint } - } - - $hint = [$1, [split /,?\s+/, $2]] - if m{^\s*$rccs\s+(Hint|Warning):\s+(\w+(?:,?\s+\w+)*)\s*$}; - - if ($define) { - if ($define->[1] =~ /\\$/) { - $define->[1] .= $_; - } - else { - if (exists $API{$define->[0]} && $define->[1] !~ /^DPPP_\(/) { - my @n = find_api($define->[1]); - push @{$depends{$define->[0]}}, @n if @n - } - undef $define; - } - } - - $define = [$1, $2] if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(.*)}; - - if ($function) { - if (/^}/) { - if (exists $API{$function->[0]}) { - my @n = find_api($function->[1]); - push @{$depends{$function->[0]}}, @n if @n - } - undef $function; - } - else { - $function->[1] .= $_; - } - } - - $function = [$1, ''] if m{^DPPP_\(my_(\w+)\)}; - - $replace = $1 if m{^\s*$rccs\s+Replace:\s+(\d+)\s+$rcce\s*$}; - $replace{$2} = $1 if $replace and m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+)}; - $replace{$2} = $1 if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+).*$rccs\s+Replace\s+$rcce}; - $replace{$1} = $2 if m{^\s*$rccs\s+Replace (\w+) with (\w+)\s+$rcce\s*$}; - - if (m{^\s*$rccs\s+(\w+(\s*,\s*\w+)*)\s+depends\s+on\s+(\w+(\s*,\s*\w+)*)\s+$rcce\s*$}) { - my @deps = map { s/\s+//g; $_ } split /,/, $3; - my $d; - for $d (map { s/\s+//g; $_ } split /,/, $1) { - push @{$depends{$d}}, @deps; - } - } - - $need{$1} = 1 if m{^#if\s+defined\(NEED_(\w+)(?:_GLOBAL)?\)}; -} - -for (values %depends) { - my %s; - $_ = [sort grep !$s{$_}++, @$_]; -} - -if (exists $opt{'api-info'}) { - my $f; - my $count = 0; - my $match = $opt{'api-info'} =~ m!^/(.*)/$! ? $1 : "^\Q$opt{'api-info'}\E\$"; - for $f (sort { lc $a cmp lc $b } keys %API) { - next unless $f =~ /$match/; - print "\n=== $f ===\n\n"; - my $info = 0; - if ($API{$f}{base} || $API{$f}{todo}) { - my $base = format_version($API{$f}{base} || $API{$f}{todo}); - print "Supported at least starting from perl-$base.\n"; - $info++; - } - if ($API{$f}{provided}) { - my $todo = $API{$f}{todo} ? format_version($API{$f}{todo}) : "5.003"; - print "Support by $ppport provided back to perl-$todo.\n"; - print "Support needs to be explicitly requested by NEED_$f.\n" if exists $need{$f}; - print "Depends on: ", join(', ', @{$depends{$f}}), ".\n" if exists $depends{$f}; - print "\n$hints{$f}" if exists $hints{$f}; - print "\nWARNING:\n$warnings{$f}" if exists $warnings{$f}; - $info++; - } - print "No portability information available.\n" unless $info; - $count++; - } - $count or print "Found no API matching '$opt{'api-info'}'."; - print "\n"; - exit 0; -} - -if (exists $opt{'list-provided'}) { - my $f; - for $f (sort { lc $a cmp lc $b } keys %API) { - next unless $API{$f}{provided}; - my @flags; - push @flags, 'explicit' if exists $need{$f}; - push @flags, 'depend' if exists $depends{$f}; - push @flags, 'hint' if exists $hints{$f}; - push @flags, 'warning' if exists $warnings{$f}; - my $flags = @flags ? ' ['.join(', ', @flags).']' : ''; - print "$f$flags\n"; - } - exit 0; -} - -my @files; -my @srcext = qw( .xs .c .h .cc .cpp -c.inc -xs.inc ); -my $srcext = join '|', map { quotemeta $_ } @srcext; - -if (@ARGV) { - my %seen; - for (@ARGV) { - if (-e) { - if (-f) { - push @files, $_ unless $seen{$_}++; - } - else { warn "'$_' is not a file.\n" } - } - else { - my @new = grep { -f } glob $_ - or warn "'$_' does not exist.\n"; - push @files, grep { !$seen{$_}++ } @new; - } - } -} -else { - eval { - require File::Find; - File::Find::find(sub { - $File::Find::name =~ /($srcext)$/i - and push @files, $File::Find::name; - }, '.'); - }; - if ($@) { - @files = map { glob "*$_" } @srcext; - } -} - -if (!@ARGV || $opt{filter}) { - my(@in, @out); - my %xsc = map { /(.*)\.xs$/ ? ("$1.c" => 1, "$1.cc" => 1) : () } @files; - for (@files) { - my $out = exists $xsc{$_} || /\b\Q$ppport\E$/i || !/($srcext)$/i; - push @{ $out ? \@out : \@in }, $_; - } - if (@ARGV && @out) { - warning("Skipping the following files (use --nofilter to avoid this):\n| ", join "\n| ", @out); - } - @files = @in; -} - -die "No input files given!\n" unless @files; - -my(%files, %global, %revreplace); -%revreplace = reverse %replace; -my $filename; -my $patch_opened = 0; - -for $filename (@files) { - unless (open IN, "<$filename") { - warn "Unable to read from $filename: $!\n"; - next; - } - - info("Scanning $filename ..."); - - my $c = do { local $/; }; - close IN; - - my %file = (orig => $c, changes => 0); - - # Temporarily remove C/XS comments and strings from the code - my @ccom; - - $c =~ s{ - ( ^$HS*\#$HS*include\b[^\r\n]+\b(?:\Q$ppport\E|XSUB\.h)\b[^\r\n]* - | ^$HS*\#$HS*(?:define|elif|if(?:def)?)\b[^\r\n]* ) - | ( ^$HS*\#[^\r\n]* - | "[^"\\]*(?:\\.[^"\\]*)*" - | '[^'\\]*(?:\\.[^'\\]*)*' - | / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]* ) ) - }{ defined $2 and push @ccom, $2; - defined $1 ? $1 : "$ccs$#ccom$cce" }mgsex; - - $file{ccom} = \@ccom; - $file{code} = $c; - $file{has_inc_ppport} = $c =~ /^$HS*#$HS*include[^\r\n]+\b\Q$ppport\E\b/m; - - my $func; - - for $func (keys %API) { - my $match = $func; - $match .= "|$revreplace{$func}" if exists $revreplace{$func}; - if ($c =~ /\b(?:Perl_)?($match)\b/) { - $file{uses_replace}{$1}++ if exists $revreplace{$func} && $1 eq $revreplace{$func}; - $file{uses_Perl}{$func}++ if $c =~ /\bPerl_$func\b/; - if (exists $API{$func}{provided}) { - $file{uses_provided}{$func}++; - if (!exists $API{$func}{base} || $API{$func}{base} > $opt{'compat-version'}) { - $file{uses}{$func}++; - my @deps = rec_depend($func); - if (@deps) { - $file{uses_deps}{$func} = \@deps; - for (@deps) { - $file{uses}{$_} = 0 unless exists $file{uses}{$_}; - } - } - for ($func, @deps) { - $file{needs}{$_} = 'static' if exists $need{$_}; - } - } - } - if (exists $API{$func}{todo} && $API{$func}{todo} > $opt{'compat-version'}) { - if ($c =~ /\b$func\b/) { - $file{uses_todo}{$func}++; - } - } - } - } - - while ($c =~ /^$HS*#$HS*define$HS+(NEED_(\w+?)(_GLOBAL)?)\b/mg) { - if (exists $need{$2}) { - $file{defined $3 ? 'needed_global' : 'needed_static'}{$2}++; - } - else { warning("Possibly wrong #define $1 in $filename") } - } - - for (qw(uses needs uses_todo needed_global needed_static)) { - for $func (keys %{$file{$_}}) { - push @{$global{$_}{$func}}, $filename; - } - } - - $files{$filename} = \%file; -} - -# Globally resolve NEED_'s -my $need; -for $need (keys %{$global{needs}}) { - if (@{$global{needs}{$need}} > 1) { - my @targets = @{$global{needs}{$need}}; - my @t = grep $files{$_}{needed_global}{$need}, @targets; - @targets = @t if @t; - @t = grep /\.xs$/i, @targets; - @targets = @t if @t; - my $target = shift @targets; - $files{$target}{needs}{$need} = 'global'; - for (@{$global{needs}{$need}}) { - $files{$_}{needs}{$need} = 'extern' if $_ ne $target; - } - } -} - -for $filename (@files) { - exists $files{$filename} or next; - - info("=== Analyzing $filename ==="); - - my %file = %{$files{$filename}}; - my $func; - my $c = $file{code}; - my $warnings = 0; - - for $func (sort keys %{$file{uses_Perl}}) { - if ($API{$func}{varargs}) { - unless ($API{$func}{nothxarg}) { - my $changes = ($c =~ s{\b(Perl_$func\s*\(\s*)(?!aTHX_?)(\)|[^\s)]*\))} - { $1 . ($2 eq ')' ? 'aTHX' : 'aTHX_ ') . $2 }ge); - if ($changes) { - warning("Doesn't pass interpreter argument aTHX to Perl_$func"); - $file{changes} += $changes; - } - } - } - else { - warning("Uses Perl_$func instead of $func"); - $file{changes} += ($c =~ s{\bPerl_$func(\s*)\((\s*aTHX_?)?\s*} - {$func$1(}g); - } - } - - for $func (sort keys %{$file{uses_replace}}) { - warning("Uses $func instead of $replace{$func}"); - $file{changes} += ($c =~ s/\b$func\b/$replace{$func}/g); - } - - for $func (sort keys %{$file{uses_provided}}) { - if ($file{uses}{$func}) { - if (exists $file{uses_deps}{$func}) { - diag("Uses $func, which depends on ", join(', ', @{$file{uses_deps}{$func}})); - } - else { - diag("Uses $func"); - } - } - $warnings += hint($func); - } - - unless ($opt{quiet}) { - for $func (sort keys %{$file{uses_todo}}) { - print "*** WARNING: Uses $func, which may not be portable below perl ", - format_version($API{$func}{todo}), ", even with '$ppport'\n"; - $warnings++; - } - } - - for $func (sort keys %{$file{needed_static}}) { - my $message = ''; - if (not exists $file{uses}{$func}) { - $message = "No need to define NEED_$func if $func is never used"; - } - elsif (exists $file{needs}{$func} && $file{needs}{$func} ne 'static') { - $message = "No need to define NEED_$func when already needed globally"; - } - if ($message) { - diag($message); - $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_$func\b.*$LF//mg); - } - } - - for $func (sort keys %{$file{needed_global}}) { - my $message = ''; - if (not exists $global{uses}{$func}) { - $message = "No need to define NEED_${func}_GLOBAL if $func is never used"; - } - elsif (exists $file{needs}{$func}) { - if ($file{needs}{$func} eq 'extern') { - $message = "No need to define NEED_${func}_GLOBAL when already needed globally"; - } - elsif ($file{needs}{$func} eq 'static') { - $message = "No need to define NEED_${func}_GLOBAL when only used in this file"; - } - } - if ($message) { - diag($message); - $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_${func}_GLOBAL\b.*$LF//mg); - } - } - - $file{needs_inc_ppport} = keys %{$file{uses}}; - - if ($file{needs_inc_ppport}) { - my $pp = ''; - - for $func (sort keys %{$file{needs}}) { - my $type = $file{needs}{$func}; - next if $type eq 'extern'; - my $suffix = $type eq 'global' ? '_GLOBAL' : ''; - unless (exists $file{"needed_$type"}{$func}) { - if ($type eq 'global') { - diag("Files [@{$global{needs}{$func}}] need $func, adding global request"); - } - else { - diag("File needs $func, adding static request"); - } - $pp .= "#define NEED_$func$suffix\n"; - } - } - - if ($pp && ($c =~ s/^(?=$HS*#$HS*define$HS+NEED_\w+)/$pp/m)) { - $pp = ''; - $file{changes}++; - } - - unless ($file{has_inc_ppport}) { - diag("Needs to include '$ppport'"); - $pp .= qq(#include "$ppport"\n) - } - - if ($pp) { - $file{changes} += ($c =~ s/^($HS*#$HS*define$HS+NEED_\w+.*?)^/$1$pp/ms) - || ($c =~ s/^(?=$HS*#$HS*include.*\Q$ppport\E)/$pp/m) - || ($c =~ s/^($HS*#$HS*include.*XSUB.*\s*?)^/$1$pp/m) - || ($c =~ s/^/$pp/); - } - } - else { - if ($file{has_inc_ppport}) { - diag("No need to include '$ppport'"); - $file{changes} += ($c =~ s/^$HS*?#$HS*include.*\Q$ppport\E.*?$LF//m); - } - } - - # put back in our C comments - my $ix; - my $cppc = 0; - my @ccom = @{$file{ccom}}; - for $ix (0 .. $#ccom) { - if (!$opt{cplusplus} && $ccom[$ix] =~ s!^//!!) { - $cppc++; - $file{changes} += $c =~ s/$rccs$ix$rcce/$ccs$ccom[$ix] $cce/; - } - else { - $c =~ s/$rccs$ix$rcce/$ccom[$ix]/; - } - } - - if ($cppc) { - my $s = $cppc != 1 ? 's' : ''; - warning("Uses $cppc C++ style comment$s, which is not portable"); - } - - my $s = $warnings != 1 ? 's' : ''; - my $warn = $warnings ? " ($warnings warning$s)" : ''; - info("Analysis completed$warn"); - - if ($file{changes}) { - if (exists $opt{copy}) { - my $newfile = "$filename$opt{copy}"; - if (-e $newfile) { - error("'$newfile' already exists, refusing to write copy of '$filename'"); - } - else { - local *F; - if (open F, ">$newfile") { - info("Writing copy of '$filename' with changes to '$newfile'"); - print F $c; - close F; - } - else { - error("Cannot open '$newfile' for writing: $!"); - } - } - } - elsif (exists $opt{patch} || $opt{changes}) { - if (exists $opt{patch}) { - unless ($patch_opened) { - if (open PATCH, ">$opt{patch}") { - $patch_opened = 1; - } - else { - error("Cannot open '$opt{patch}' for writing: $!"); - delete $opt{patch}; - $opt{changes} = 1; - goto fallback; - } - } - mydiff(\*PATCH, $filename, $c); - } - else { -fallback: - info("Suggested changes:"); - mydiff(\*STDOUT, $filename, $c); - } - } - else { - my $s = $file{changes} == 1 ? '' : 's'; - info("$file{changes} potentially required change$s detected"); - } - } - else { - info("Looks good"); - } -} - -close PATCH if $patch_opened; - -exit 0; - - -sub try_use { eval "use @_;"; return $@ eq '' } - -sub mydiff -{ - local *F = shift; - my($file, $str) = @_; - my $diff; - - if (exists $opt{diff}) { - $diff = run_diff($opt{diff}, $file, $str); - } - - if (!defined $diff and try_use('Text::Diff')) { - $diff = Text::Diff::diff($file, \$str, { STYLE => 'Unified' }); - $diff = <
$tmp") { - print F $str; - close F; - - if (open F, "$prog $file $tmp |") { - while () { - s/\Q$tmp\E/$file.patched/; - $diff .= $_; - } - close F; - unlink $tmp; - return $diff; - } - - unlink $tmp; - } - else { - error("Cannot open '$tmp' for writing: $!"); - } - - return undef; -} - -sub rec_depend -{ - my($func, $seen) = @_; - return () unless exists $depends{$func}; - $seen = {%{$seen||{}}}; - return () if $seen->{$func}++; - my %s; - grep !$s{$_}++, map { ($_, rec_depend($_, $seen)) } @{$depends{$func}}; -} - -sub parse_version -{ - my $ver = shift; - - if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) { - return ($1, $2, $3); - } - elsif ($ver !~ /^\d+\.[\d_]+$/) { - die "cannot parse version '$ver'\n"; - } - - $ver =~ s/_//g; - $ver =~ s/$/000000/; - - my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/; - - $v = int $v; - $s = int $s; - - if ($r < 5 || ($r == 5 && $v < 6)) { - if ($s % 10) { - die "cannot parse version '$ver'\n"; - } - } - - return ($r, $v, $s); -} - -sub format_version -{ - my $ver = shift; - - $ver =~ s/$/000000/; - my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/; - - $v = int $v; - $s = int $s; - - if ($r < 5 || ($r == 5 && $v < 6)) { - if ($s % 10) { - die "invalid version '$ver'\n"; - } - $s /= 10; - - $ver = sprintf "%d.%03d", $r, $v; - $s > 0 and $ver .= sprintf "_%02d", $s; - - return $ver; - } - - return sprintf "%d.%d.%d", $r, $v, $s; -} - -sub info -{ - $opt{quiet} and return; - print @_, "\n"; -} - -sub diag -{ - $opt{quiet} and return; - $opt{diag} and print @_, "\n"; -} - -sub warning -{ - $opt{quiet} and return; - print "*** ", @_, "\n"; -} - -sub error -{ - print "*** ERROR: ", @_, "\n"; -} - -my %given_hints; -my %given_warnings; -sub hint -{ - $opt{quiet} and return; - my $func = shift; - my $rv = 0; - if (exists $warnings{$func} && !$given_warnings{$func}++) { - my $warn = $warnings{$func}; - $warn =~ s!^!*** !mg; - print "*** WARNING: $func\n", $warn; - $rv++; - } - if ($opt{hints} && exists $hints{$func} && !$given_hints{$func}++) { - my $hint = $hints{$func}; - $hint =~ s/^/ /mg; - print " --- hint for $func ---\n", $hint; - } - $rv; -} - -sub usage -{ - my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms; - my %M = ( 'I' => '*' ); - $usage =~ s/^\s*perl\s+\S+/$^X $0/; - $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g; - - print < }; - my($copy) = $self =~ /^=head\d\s+COPYRIGHT\s*^(.*?)^=\w+/ms; - $copy =~ s/^(?=\S+)/ /gms; - $self =~ s/^$HS+Do NOT edit.*?(?=^-)/$copy/ms; - $self =~ s/^SKIP.*(?=^__DATA__)/SKIP -if (\@ARGV && \$ARGV[0] eq '--unstrip') { - eval { require Devel::PPPort }; - \$@ and die "Cannot require Devel::PPPort, please install.\\n"; - if (eval \$Devel::PPPort::VERSION < $VERSION) { - die "$0 was originally generated with Devel::PPPort $VERSION.\\n" - . "Your Devel::PPPort is only version \$Devel::PPPort::VERSION.\\n" - . "Please install a newer version, or --unstrip will not work.\\n"; - } - Devel::PPPort::WriteFile(\$0); - exit 0; -} -print <$0" or die "cannot strip $0: $!\n"; - print OUT "$pl$c\n"; - - exit 0; -} - -__DATA__ -*/ - -#ifndef _P_P_PORTABILITY_H_ -#define _P_P_PORTABILITY_H_ - -#ifndef DPPP_NAMESPACE -# define DPPP_NAMESPACE DPPP_ -#endif - -#define DPPP_CAT2(x,y) CAT2(x,y) -#define DPPP_(name) DPPP_CAT2(DPPP_NAMESPACE, name) - -#ifndef PERL_REVISION -# if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION)) -# define PERL_PATCHLEVEL_H_IMPLICIT -# include -# endif -# if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL))) -# include -# endif -# ifndef PERL_REVISION -# define PERL_REVISION (5) - /* Replace: 1 */ -# define PERL_VERSION PATCHLEVEL -# define PERL_SUBVERSION SUBVERSION - /* Replace PERL_PATCHLEVEL with PERL_VERSION */ - /* Replace: 0 */ -# endif -#endif - -#define _dpppDEC2BCD(dec) ((((dec)/100)<<8)|((((dec)%100)/10)<<4)|((dec)%10)) -#define PERL_BCDVERSION ((_dpppDEC2BCD(PERL_REVISION)<<24)|(_dpppDEC2BCD(PERL_VERSION)<<12)|_dpppDEC2BCD(PERL_SUBVERSION)) - -/* It is very unlikely that anyone will try to use this with Perl 6 - (or greater), but who knows. - */ -#if PERL_REVISION != 5 -# error ppport.h only works with Perl version 5 -#endif /* PERL_REVISION != 5 */ -#ifndef dTHR -# define dTHR dNOOP -#endif -#ifndef dTHX -# define dTHX dNOOP -#endif - -#ifndef dTHXa -# define dTHXa(x) dNOOP -#endif -#ifndef pTHX -# define pTHX void -#endif - -#ifndef pTHX_ -# define pTHX_ -#endif - -#ifndef aTHX -# define aTHX -#endif - -#ifndef aTHX_ -# define aTHX_ -#endif - -#if (PERL_BCDVERSION < 0x5006000) -# ifdef USE_THREADS -# define aTHXR thr -# define aTHXR_ thr, -# else -# define aTHXR -# define aTHXR_ -# endif -# define dTHXR dTHR -#else -# define aTHXR aTHX -# define aTHXR_ aTHX_ -# define dTHXR dTHX -#endif -#ifndef dTHXoa -# define dTHXoa(x) dTHXa(x) -#endif - -#ifdef I_LIMITS -# include -#endif - -#ifndef PERL_UCHAR_MIN -# define PERL_UCHAR_MIN ((unsigned char)0) -#endif - -#ifndef PERL_UCHAR_MAX -# ifdef UCHAR_MAX -# define PERL_UCHAR_MAX ((unsigned char)UCHAR_MAX) -# else -# ifdef MAXUCHAR -# define PERL_UCHAR_MAX ((unsigned char)MAXUCHAR) -# else -# define PERL_UCHAR_MAX ((unsigned char)~(unsigned)0) -# endif -# endif -#endif - -#ifndef PERL_USHORT_MIN -# define PERL_USHORT_MIN ((unsigned short)0) -#endif - -#ifndef PERL_USHORT_MAX -# ifdef USHORT_MAX -# define PERL_USHORT_MAX ((unsigned short)USHORT_MAX) -# else -# ifdef MAXUSHORT -# define PERL_USHORT_MAX ((unsigned short)MAXUSHORT) -# else -# ifdef USHRT_MAX -# define PERL_USHORT_MAX ((unsigned short)USHRT_MAX) -# else -# define PERL_USHORT_MAX ((unsigned short)~(unsigned)0) -# endif -# endif -# endif -#endif - -#ifndef PERL_SHORT_MAX -# ifdef SHORT_MAX -# define PERL_SHORT_MAX ((short)SHORT_MAX) -# else -# ifdef MAXSHORT /* Often used in */ -# define PERL_SHORT_MAX ((short)MAXSHORT) -# else -# ifdef SHRT_MAX -# define PERL_SHORT_MAX ((short)SHRT_MAX) -# else -# define PERL_SHORT_MAX ((short) (PERL_USHORT_MAX >> 1)) -# endif -# endif -# endif -#endif - -#ifndef PERL_SHORT_MIN -# ifdef SHORT_MIN -# define PERL_SHORT_MIN ((short)SHORT_MIN) -# else -# ifdef MINSHORT -# define PERL_SHORT_MIN ((short)MINSHORT) -# else -# ifdef SHRT_MIN -# define PERL_SHORT_MIN ((short)SHRT_MIN) -# else -# define PERL_SHORT_MIN (-PERL_SHORT_MAX - ((3 & -1) == 3)) -# endif -# endif -# endif -#endif - -#ifndef PERL_UINT_MAX -# ifdef UINT_MAX -# define PERL_UINT_MAX ((unsigned int)UINT_MAX) -# else -# ifdef MAXUINT -# define PERL_UINT_MAX ((unsigned int)MAXUINT) -# else -# define PERL_UINT_MAX (~(unsigned int)0) -# endif -# endif -#endif - -#ifndef PERL_UINT_MIN -# define PERL_UINT_MIN ((unsigned int)0) -#endif - -#ifndef PERL_INT_MAX -# ifdef INT_MAX -# define PERL_INT_MAX ((int)INT_MAX) -# else -# ifdef MAXINT /* Often used in */ -# define PERL_INT_MAX ((int)MAXINT) -# else -# define PERL_INT_MAX ((int)(PERL_UINT_MAX >> 1)) -# endif -# endif -#endif - -#ifndef PERL_INT_MIN -# ifdef INT_MIN -# define PERL_INT_MIN ((int)INT_MIN) -# else -# ifdef MININT -# define PERL_INT_MIN ((int)MININT) -# else -# define PERL_INT_MIN (-PERL_INT_MAX - ((3 & -1) == 3)) -# endif -# endif -#endif - -#ifndef PERL_ULONG_MAX -# ifdef ULONG_MAX -# define PERL_ULONG_MAX ((unsigned long)ULONG_MAX) -# else -# ifdef MAXULONG -# define PERL_ULONG_MAX ((unsigned long)MAXULONG) -# else -# define PERL_ULONG_MAX (~(unsigned long)0) -# endif -# endif -#endif - -#ifndef PERL_ULONG_MIN -# define PERL_ULONG_MIN ((unsigned long)0L) -#endif - -#ifndef PERL_LONG_MAX -# ifdef LONG_MAX -# define PERL_LONG_MAX ((long)LONG_MAX) -# else -# ifdef MAXLONG -# define PERL_LONG_MAX ((long)MAXLONG) -# else -# define PERL_LONG_MAX ((long) (PERL_ULONG_MAX >> 1)) -# endif -# endif -#endif - -#ifndef PERL_LONG_MIN -# ifdef LONG_MIN -# define PERL_LONG_MIN ((long)LONG_MIN) -# else -# ifdef MINLONG -# define PERL_LONG_MIN ((long)MINLONG) -# else -# define PERL_LONG_MIN (-PERL_LONG_MAX - ((3 & -1) == 3)) -# endif -# endif -#endif - -#if defined(HAS_QUAD) && (defined(convex) || defined(uts)) -# ifndef PERL_UQUAD_MAX -# ifdef ULONGLONG_MAX -# define PERL_UQUAD_MAX ((unsigned long long)ULONGLONG_MAX) -# else -# ifdef MAXULONGLONG -# define PERL_UQUAD_MAX ((unsigned long long)MAXULONGLONG) -# else -# define PERL_UQUAD_MAX (~(unsigned long long)0) -# endif -# endif -# endif - -# ifndef PERL_UQUAD_MIN -# define PERL_UQUAD_MIN ((unsigned long long)0L) -# endif - -# ifndef PERL_QUAD_MAX -# ifdef LONGLONG_MAX -# define PERL_QUAD_MAX ((long long)LONGLONG_MAX) -# else -# ifdef MAXLONGLONG -# define PERL_QUAD_MAX ((long long)MAXLONGLONG) -# else -# define PERL_QUAD_MAX ((long long) (PERL_UQUAD_MAX >> 1)) -# endif -# endif -# endif - -# ifndef PERL_QUAD_MIN -# ifdef LONGLONG_MIN -# define PERL_QUAD_MIN ((long long)LONGLONG_MIN) -# else -# ifdef MINLONGLONG -# define PERL_QUAD_MIN ((long long)MINLONGLONG) -# else -# define PERL_QUAD_MIN (-PERL_QUAD_MAX - ((3 & -1) == 3)) -# endif -# endif -# endif -#endif - -/* This is based on code from 5.003 perl.h */ -#ifdef HAS_QUAD -# ifdef cray -#ifndef IVTYPE -# define IVTYPE int -#endif - -#ifndef IV_MIN -# define IV_MIN PERL_INT_MIN -#endif - -#ifndef IV_MAX -# define IV_MAX PERL_INT_MAX -#endif - -#ifndef UV_MIN -# define UV_MIN PERL_UINT_MIN -#endif - -#ifndef UV_MAX -# define UV_MAX PERL_UINT_MAX -#endif - -# ifdef INTSIZE -#ifndef IVSIZE -# define IVSIZE INTSIZE -#endif - -# endif -# else -# if defined(convex) || defined(uts) -#ifndef IVTYPE -# define IVTYPE long long -#endif - -#ifndef IV_MIN -# define IV_MIN PERL_QUAD_MIN -#endif - -#ifndef IV_MAX -# define IV_MAX PERL_QUAD_MAX -#endif - -#ifndef UV_MIN -# define UV_MIN PERL_UQUAD_MIN -#endif - -#ifndef UV_MAX -# define UV_MAX PERL_UQUAD_MAX -#endif - -# ifdef LONGLONGSIZE -#ifndef IVSIZE -# define IVSIZE LONGLONGSIZE -#endif - -# endif -# else -#ifndef IVTYPE -# define IVTYPE long -#endif - -#ifndef IV_MIN -# define IV_MIN PERL_LONG_MIN -#endif - -#ifndef IV_MAX -# define IV_MAX PERL_LONG_MAX -#endif - -#ifndef UV_MIN -# define UV_MIN PERL_ULONG_MIN -#endif - -#ifndef UV_MAX -# define UV_MAX PERL_ULONG_MAX -#endif - -# ifdef LONGSIZE -#ifndef IVSIZE -# define IVSIZE LONGSIZE -#endif - -# endif -# endif -# endif -#ifndef IVSIZE -# define IVSIZE 8 -#endif - -#ifndef LONGSIZE -# define LONGSIZE 8 -#endif - -#ifndef PERL_QUAD_MIN -# define PERL_QUAD_MIN IV_MIN -#endif - -#ifndef PERL_QUAD_MAX -# define PERL_QUAD_MAX IV_MAX -#endif - -#ifndef PERL_UQUAD_MIN -# define PERL_UQUAD_MIN UV_MIN -#endif - -#ifndef PERL_UQUAD_MAX -# define PERL_UQUAD_MAX UV_MAX -#endif - -#else -#ifndef IVTYPE -# define IVTYPE long -#endif - -#ifndef LONGSIZE -# define LONGSIZE 4 -#endif - -#ifndef IV_MIN -# define IV_MIN PERL_LONG_MIN -#endif - -#ifndef IV_MAX -# define IV_MAX PERL_LONG_MAX -#endif - -#ifndef UV_MIN -# define UV_MIN PERL_ULONG_MIN -#endif - -#ifndef UV_MAX -# define UV_MAX PERL_ULONG_MAX -#endif - -#endif - -#ifndef IVSIZE -# ifdef LONGSIZE -# define IVSIZE LONGSIZE -# else -# define IVSIZE 4 /* A bold guess, but the best we can make. */ -# endif -#endif -#ifndef UVTYPE -# define UVTYPE unsigned IVTYPE -#endif - -#ifndef UVSIZE -# define UVSIZE IVSIZE -#endif -#ifndef sv_setuv -# define sv_setuv(sv, uv) \ - STMT_START { \ - UV TeMpUv = uv; \ - if (TeMpUv <= IV_MAX) \ - sv_setiv(sv, TeMpUv); \ - else \ - sv_setnv(sv, (double)TeMpUv); \ - } STMT_END -#endif -#ifndef newSVuv -# define newSVuv(uv) ((uv) <= IV_MAX ? newSViv((IV)uv) : newSVnv((NV)uv)) -#endif -#ifndef sv_2uv -# define sv_2uv(sv) ((PL_Sv = (sv)), (UV) (SvNOK(PL_Sv) ? SvNV(PL_Sv) : sv_2nv(PL_Sv))) -#endif - -#ifndef SvUVX -# define SvUVX(sv) ((UV)SvIVX(sv)) -#endif - -#ifndef SvUVXx -# define SvUVXx(sv) SvUVX(sv) -#endif - -#ifndef SvUV -# define SvUV(sv) (SvIOK(sv) ? SvUVX(sv) : sv_2uv(sv)) -#endif - -#ifndef SvUVx -# define SvUVx(sv) ((PL_Sv = (sv)), SvUV(PL_Sv)) -#endif - -/* Hint: sv_uv - * Always use the SvUVx() macro instead of sv_uv(). - */ -#ifndef sv_uv -# define sv_uv(sv) SvUVx(sv) -#endif - -#if !defined(SvUOK) && defined(SvIOK_UV) -# define SvUOK(sv) SvIOK_UV(sv) -#endif -#ifndef XST_mUV -# define XST_mUV(i,v) (ST(i) = sv_2mortal(newSVuv(v)) ) -#endif - -#ifndef XSRETURN_UV -# define XSRETURN_UV(v) STMT_START { XST_mUV(0,v); XSRETURN(1); } STMT_END -#endif -#ifndef PUSHu -# define PUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG; } STMT_END -#endif - -#ifndef XPUSHu -# define XPUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); XPUSHTARG; } STMT_END -#endif - -#ifdef HAS_MEMCMP -#ifndef memNE -# define memNE(s1,s2,l) (memcmp(s1,s2,l)) -#endif - -#ifndef memEQ -# define memEQ(s1,s2,l) (!memcmp(s1,s2,l)) -#endif - -#else -#ifndef memNE -# define memNE(s1,s2,l) (bcmp(s1,s2,l)) -#endif - -#ifndef memEQ -# define memEQ(s1,s2,l) (!bcmp(s1,s2,l)) -#endif - -#endif -#ifndef memEQs -# define memEQs(s1, l, s2) \ - (sizeof(s2)-1 == l && memEQ(s1, (s2 ""), (sizeof(s2)-1))) -#endif - -#ifndef memNEs -# define memNEs(s1, l, s2) !memEQs(s1, l, s2) -#endif -#ifndef MoveD -# define MoveD(s,d,n,t) memmove((char*)(d),(char*)(s), (n) * sizeof(t)) -#endif - -#ifndef CopyD -# define CopyD(s,d,n,t) memcpy((char*)(d),(char*)(s), (n) * sizeof(t)) -#endif - -#ifdef HAS_MEMSET -#ifndef ZeroD -# define ZeroD(d,n,t) memzero((char*)(d), (n) * sizeof(t)) -#endif - -#else -#ifndef ZeroD -# define ZeroD(d,n,t) ((void)memzero((char*)(d), (n) * sizeof(t)), d) -#endif - -#endif -#ifndef PoisonWith -# define PoisonWith(d,n,t,b) (void)memset((char*)(d), (U8)(b), (n) * sizeof(t)) -#endif - -#ifndef PoisonNew -# define PoisonNew(d,n,t) PoisonWith(d,n,t,0xAB) -#endif - -#ifndef PoisonFree -# define PoisonFree(d,n,t) PoisonWith(d,n,t,0xEF) -#endif - -#ifndef Poison -# define Poison(d,n,t) PoisonFree(d,n,t) -#endif -#ifndef Newx -# define Newx(v,n,t) New(0,v,n,t) -#endif - -#ifndef Newxc -# define Newxc(v,n,t,c) Newc(0,v,n,t,c) -#endif - -#ifndef Newxz -# define Newxz(v,n,t) Newz(0,v,n,t) -#endif - -#ifndef PERL_UNUSED_DECL -# ifdef HASATTRIBUTE -# if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER) -# define PERL_UNUSED_DECL -# else -# define PERL_UNUSED_DECL __attribute__((unused)) -# endif -# else -# define PERL_UNUSED_DECL -# endif -#endif - -#ifndef PERL_UNUSED_ARG -# if defined(lint) && defined(S_SPLINT_S) /* www.splint.org */ -# include -# define PERL_UNUSED_ARG(x) NOTE(ARGUNUSED(x)) -# else -# define PERL_UNUSED_ARG(x) ((void)x) -# endif -#endif - -#ifndef PERL_UNUSED_VAR -# define PERL_UNUSED_VAR(x) ((void)x) -#endif - -#ifndef PERL_UNUSED_CONTEXT -# ifdef USE_ITHREADS -# define PERL_UNUSED_CONTEXT PERL_UNUSED_ARG(my_perl) -# else -# define PERL_UNUSED_CONTEXT -# endif -#endif -#ifndef NOOP -# define NOOP /*EMPTY*/(void)0 -#endif - -#ifndef dNOOP -# define dNOOP extern int /*@unused@*/ Perl___notused PERL_UNUSED_DECL -#endif - -#ifndef NVTYPE -# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) -# define NVTYPE long double -# else -# define NVTYPE double -# endif -typedef NVTYPE NV; -#endif - -#ifndef INT2PTR -# if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE) -# define PTRV UV -# define INT2PTR(any,d) (any)(d) -# else -# if PTRSIZE == LONGSIZE -# define PTRV unsigned long -# else -# define PTRV unsigned -# endif -# define INT2PTR(any,d) (any)(PTRV)(d) -# endif -#endif - -#ifndef PTR2ul -# if PTRSIZE == LONGSIZE -# define PTR2ul(p) (unsigned long)(p) -# else -# define PTR2ul(p) INT2PTR(unsigned long,p) -# endif -#endif -#ifndef PTR2nat -# define PTR2nat(p) (PTRV)(p) -#endif - -#ifndef NUM2PTR -# define NUM2PTR(any,d) (any)PTR2nat(d) -#endif - -#ifndef PTR2IV -# define PTR2IV(p) INT2PTR(IV,p) -#endif - -#ifndef PTR2UV -# define PTR2UV(p) INT2PTR(UV,p) -#endif - -#ifndef PTR2NV -# define PTR2NV(p) NUM2PTR(NV,p) -#endif - -#undef START_EXTERN_C -#undef END_EXTERN_C -#undef EXTERN_C -#ifdef __cplusplus -# define START_EXTERN_C extern "C" { -# define END_EXTERN_C } -# define EXTERN_C extern "C" -#else -# define START_EXTERN_C -# define END_EXTERN_C -# define EXTERN_C extern -#endif - -#if defined(PERL_GCC_PEDANTIC) -# ifndef PERL_GCC_BRACE_GROUPS_FORBIDDEN -# define PERL_GCC_BRACE_GROUPS_FORBIDDEN -# endif -#endif - -#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) && !defined(__cplusplus) -# ifndef PERL_USE_GCC_BRACE_GROUPS -# define PERL_USE_GCC_BRACE_GROUPS -# endif -#endif - -#undef STMT_START -#undef STMT_END -#ifdef PERL_USE_GCC_BRACE_GROUPS -# define STMT_START (void)( /* gcc supports ``({ STATEMENTS; })'' */ -# define STMT_END ) -#else -# if defined(VOIDFLAGS) && (VOIDFLAGS) && (defined(sun) || defined(__sun__)) && !defined(__GNUC__) -# define STMT_START if (1) -# define STMT_END else (void)0 -# else -# define STMT_START do -# define STMT_END while (0) -# endif -#endif -#ifndef boolSV -# define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no) -#endif - -/* DEFSV appears first in 5.004_56 */ -#ifndef DEFSV -# define DEFSV GvSV(PL_defgv) -#endif - -#ifndef SAVE_DEFSV -# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv)) -#endif - -#ifndef DEFSV_set -# define DEFSV_set(sv) (DEFSV = (sv)) -#endif - -/* Older perls (<=5.003) lack AvFILLp */ -#ifndef AvFILLp -# define AvFILLp AvFILL -#endif -#ifndef ERRSV -# define ERRSV get_sv("@",FALSE) -#endif - -/* Hint: gv_stashpvn - * This function's backport doesn't support the length parameter, but - * rather ignores it. Portability can only be ensured if the length - * parameter is used for speed reasons, but the length can always be - * correctly computed from the string argument. - */ -#ifndef gv_stashpvn -# define gv_stashpvn(str,len,create) gv_stashpv(str,create) -#endif - -/* Replace: 1 */ -#ifndef get_cv -# define get_cv perl_get_cv -#endif - -#ifndef get_sv -# define get_sv perl_get_sv -#endif - -#ifndef get_av -# define get_av perl_get_av -#endif - -#ifndef get_hv -# define get_hv perl_get_hv -#endif - -/* Replace: 0 */ -#ifndef dUNDERBAR -# define dUNDERBAR dNOOP -#endif - -#ifndef UNDERBAR -# define UNDERBAR DEFSV -#endif -#ifndef dAX -# define dAX I32 ax = MARK - PL_stack_base + 1 -#endif - -#ifndef dITEMS -# define dITEMS I32 items = SP - MARK -#endif -#ifndef dXSTARG -# define dXSTARG SV * targ = sv_newmortal() -#endif -#ifndef dAXMARK -# define dAXMARK I32 ax = POPMARK; \ - register SV ** const mark = PL_stack_base + ax++ -#endif -#ifndef XSprePUSH -# define XSprePUSH (sp = PL_stack_base + ax - 1) -#endif - -#if (PERL_BCDVERSION < 0x5005000) -# undef XSRETURN -# define XSRETURN(off) \ - STMT_START { \ - PL_stack_sp = PL_stack_base + ax + ((off) - 1); \ - return; \ - } STMT_END -#endif -#ifndef XSPROTO -# define XSPROTO(name) void name(pTHX_ CV* cv) -#endif - -#ifndef SVfARG -# define SVfARG(p) ((void*)(p)) -#endif -#ifndef PERL_ABS -# define PERL_ABS(x) ((x) < 0 ? -(x) : (x)) -#endif -#ifndef dVAR -# define dVAR dNOOP -#endif -#ifndef SVf -# define SVf "_" -#endif -#ifndef UTF8_MAXBYTES -# define UTF8_MAXBYTES UTF8_MAXLEN -#endif -#ifndef CPERLscope -# define CPERLscope(x) x -#endif -#ifndef PERL_HASH -# define PERL_HASH(hash,str,len) \ - STMT_START { \ - const char *s_PeRlHaSh = str; \ - I32 i_PeRlHaSh = len; \ - U32 hash_PeRlHaSh = 0; \ - while (i_PeRlHaSh--) \ - hash_PeRlHaSh = hash_PeRlHaSh * 33 + *s_PeRlHaSh++; \ - (hash) = hash_PeRlHaSh; \ - } STMT_END -#endif - -#ifndef PERLIO_FUNCS_DECL -# ifdef PERLIO_FUNCS_CONST -# define PERLIO_FUNCS_DECL(funcs) const PerlIO_funcs funcs -# define PERLIO_FUNCS_CAST(funcs) (PerlIO_funcs*)(funcs) -# else -# define PERLIO_FUNCS_DECL(funcs) PerlIO_funcs funcs -# define PERLIO_FUNCS_CAST(funcs) (funcs) -# endif -#endif - -/* provide these typedefs for older perls */ -#if (PERL_BCDVERSION < 0x5009003) - -# ifdef ARGSproto -typedef OP* (CPERLscope(*Perl_ppaddr_t))(ARGSproto); -# else -typedef OP* (CPERLscope(*Perl_ppaddr_t))(pTHX); -# endif - -typedef OP* (CPERLscope(*Perl_check_t)) (pTHX_ OP*); - -#endif -#ifndef isPSXSPC -# define isPSXSPC(c) (isSPACE(c) || (c) == '\v') -#endif - -#ifndef isBLANK -# define isBLANK(c) ((c) == ' ' || (c) == '\t') -#endif - -#ifdef EBCDIC -#ifndef isALNUMC -# define isALNUMC(c) isalnum(c) -#endif - -#ifndef isASCII -# define isASCII(c) isascii(c) -#endif - -#ifndef isCNTRL -# define isCNTRL(c) iscntrl(c) -#endif - -#ifndef isGRAPH -# define isGRAPH(c) isgraph(c) -#endif - -#ifndef isPRINT -# define isPRINT(c) isprint(c) -#endif - -#ifndef isPUNCT -# define isPUNCT(c) ispunct(c) -#endif - -#ifndef isXDIGIT -# define isXDIGIT(c) isxdigit(c) -#endif - -#else -# if (PERL_BCDVERSION < 0x5010000) -/* Hint: isPRINT - * The implementation in older perl versions includes all of the - * isSPACE() characters, which is wrong. The version provided by - * Devel::PPPort always overrides a present buggy version. - */ -# undef isPRINT -# endif - -#ifdef HAS_QUAD -# ifdef U64TYPE -# define WIDEST_UTYPE U64TYPE -# else -# define WIDEST_UTYPE Quad_t -# endif -#else -# define WIDEST_UTYPE U32 -#endif -#ifndef isALNUMC -# define isALNUMC(c) (isALPHA(c) || isDIGIT(c)) -#endif - -#ifndef isASCII -# define isASCII(c) ((WIDEST_UTYPE) (c) <= 127) -#endif - -#ifndef isCNTRL -# define isCNTRL(c) ((WIDEST_UTYPE) (c) < ' ' || (c) == 127) -#endif - -#ifndef isGRAPH -# define isGRAPH(c) (isALNUM(c) || isPUNCT(c)) -#endif - -#ifndef isPRINT -# define isPRINT(c) (((c) >= 32 && (c) < 127)) -#endif - -#ifndef isPUNCT -# define isPUNCT(c) (((c) >= 33 && (c) <= 47) || ((c) >= 58 && (c) <= 64) || ((c) >= 91 && (c) <= 96) || ((c) >= 123 && (c) <= 126)) -#endif - -#ifndef isXDIGIT -# define isXDIGIT(c) (isDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#endif - -#endif - -/* Until we figure out how to support this in older perls... */ -#if (PERL_BCDVERSION >= 0x5008000) -#ifndef HeUTF8 -# define HeUTF8(he) ((HeKLEN(he) == HEf_SVKEY) ? \ - SvUTF8(HeKEY_sv(he)) : \ - (U32)HeKUTF8(he)) -#endif - -#endif - -#ifndef PERL_SIGNALS_UNSAFE_FLAG - -#define PERL_SIGNALS_UNSAFE_FLAG 0x0001 - -#if (PERL_BCDVERSION < 0x5008000) -# define D_PPP_PERL_SIGNALS_INIT PERL_SIGNALS_UNSAFE_FLAG -#else -# define D_PPP_PERL_SIGNALS_INIT 0 -#endif - -#if defined(NEED_PL_signals) -static U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT; -#elif defined(NEED_PL_signals_GLOBAL) -U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT; -#else -extern U32 DPPP_(my_PL_signals); -#endif -#define PL_signals DPPP_(my_PL_signals) - -#endif - -/* Hint: PL_ppaddr - * Calling an op via PL_ppaddr requires passing a context argument - * for threaded builds. Since the context argument is different for - * 5.005 perls, you can use aTHXR (supplied by ppport.h), which will - * automatically be defined as the correct argument. - */ - -#if (PERL_BCDVERSION <= 0x5005005) -/* Replace: 1 */ -# define PL_ppaddr ppaddr -# define PL_no_modify no_modify -/* Replace: 0 */ -#endif - -#if (PERL_BCDVERSION <= 0x5004005) -/* Replace: 1 */ -# define PL_DBsignal DBsignal -# define PL_DBsingle DBsingle -# define PL_DBsub DBsub -# define PL_DBtrace DBtrace -# define PL_Sv Sv -# define PL_bufend bufend -# define PL_bufptr bufptr -# define PL_compiling compiling -# define PL_copline copline -# define PL_curcop curcop -# define PL_curstash curstash -# define PL_debstash debstash -# define PL_defgv defgv -# define PL_diehook diehook -# define PL_dirty dirty -# define PL_dowarn dowarn -# define PL_errgv errgv -# define PL_error_count error_count -# define PL_expect expect -# define PL_hexdigit hexdigit -# define PL_hints hints -# define PL_in_my in_my -# define PL_laststatval laststatval -# define PL_lex_state lex_state -# define PL_lex_stuff lex_stuff -# define PL_linestr linestr -# define PL_na na -# define PL_perl_destruct_level perl_destruct_level -# define PL_perldb perldb -# define PL_rsfp_filters rsfp_filters -# define PL_rsfp rsfp -# define PL_stack_base stack_base -# define PL_stack_sp stack_sp -# define PL_statcache statcache -# define PL_stdingv stdingv -# define PL_sv_arenaroot sv_arenaroot -# define PL_sv_no sv_no -# define PL_sv_undef sv_undef -# define PL_sv_yes sv_yes -# define PL_tainted tainted -# define PL_tainting tainting -# define PL_tokenbuf tokenbuf -/* Replace: 0 */ -#endif - -/* Warning: PL_parser - * For perl versions earlier than 5.9.5, this is an always - * non-NULL dummy. Also, it cannot be dereferenced. Don't - * use it if you can avoid is and unless you absolutely know - * what you're doing. - * If you always check that PL_parser is non-NULL, you can - * define DPPP_PL_parser_NO_DUMMY to avoid the creation of - * a dummy parser structure. - */ - -#if (PERL_BCDVERSION >= 0x5009005) -# ifdef DPPP_PL_parser_NO_DUMMY -# define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \ - (croak("panic: PL_parser == NULL in %s:%d", \ - __FILE__, __LINE__), (yy_parser *) NULL))->var) -# else -# ifdef DPPP_PL_parser_NO_DUMMY_WARNING -# define D_PPP_parser_dummy_warning(var) -# else -# define D_PPP_parser_dummy_warning(var) \ - warn("warning: dummy PL_" #var " used in %s:%d", __FILE__, __LINE__), -# endif -# define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \ - (D_PPP_parser_dummy_warning(var) &DPPP_(dummy_PL_parser)))->var) -#if defined(NEED_PL_parser) -static yy_parser DPPP_(dummy_PL_parser); -#elif defined(NEED_PL_parser_GLOBAL) -yy_parser DPPP_(dummy_PL_parser); -#else -extern yy_parser DPPP_(dummy_PL_parser); -#endif - -# endif - -/* PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf depends on PL_parser */ -/* Warning: PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf - * Do not use this variable unless you know exactly what you're - * doint. It is internal to the perl parser and may change or even - * be removed in the future. As of perl 5.9.5, you have to check - * for (PL_parser != NULL) for this variable to have any effect. - * An always non-NULL PL_parser dummy is provided for earlier - * perl versions. - * If PL_parser is NULL when you try to access this variable, a - * dummy is being accessed instead and a warning is issued unless - * you define DPPP_PL_parser_NO_DUMMY_WARNING. - * If DPPP_PL_parser_NO_DUMMY is defined, the code trying to access - * this variable will croak with a panic message. - */ - -# define PL_expect D_PPP_my_PL_parser_var(expect) -# define PL_copline D_PPP_my_PL_parser_var(copline) -# define PL_rsfp D_PPP_my_PL_parser_var(rsfp) -# define PL_rsfp_filters D_PPP_my_PL_parser_var(rsfp_filters) -# define PL_linestr D_PPP_my_PL_parser_var(linestr) -# define PL_bufptr D_PPP_my_PL_parser_var(bufptr) -# define PL_bufend D_PPP_my_PL_parser_var(bufend) -# define PL_lex_state D_PPP_my_PL_parser_var(lex_state) -# define PL_lex_stuff D_PPP_my_PL_parser_var(lex_stuff) -# define PL_tokenbuf D_PPP_my_PL_parser_var(tokenbuf) -# define PL_in_my D_PPP_my_PL_parser_var(in_my) -# define PL_in_my_stash D_PPP_my_PL_parser_var(in_my_stash) -# define PL_error_count D_PPP_my_PL_parser_var(error_count) - - -#else - -/* ensure that PL_parser != NULL and cannot be dereferenced */ -# define PL_parser ((void *) 1) - -#endif -#ifndef mPUSHs -# define mPUSHs(s) PUSHs(sv_2mortal(s)) -#endif - -#ifndef PUSHmortal -# define PUSHmortal PUSHs(sv_newmortal()) -#endif - -#ifndef mPUSHp -# define mPUSHp(p,l) sv_setpvn(PUSHmortal, (p), (l)) -#endif - -#ifndef mPUSHn -# define mPUSHn(n) sv_setnv(PUSHmortal, (NV)(n)) -#endif - -#ifndef mPUSHi -# define mPUSHi(i) sv_setiv(PUSHmortal, (IV)(i)) -#endif - -#ifndef mPUSHu -# define mPUSHu(u) sv_setuv(PUSHmortal, (UV)(u)) -#endif -#ifndef mXPUSHs -# define mXPUSHs(s) XPUSHs(sv_2mortal(s)) -#endif - -#ifndef XPUSHmortal -# define XPUSHmortal XPUSHs(sv_newmortal()) -#endif - -#ifndef mXPUSHp -# define mXPUSHp(p,l) STMT_START { EXTEND(sp,1); sv_setpvn(PUSHmortal, (p), (l)); } STMT_END -#endif - -#ifndef mXPUSHn -# define mXPUSHn(n) STMT_START { EXTEND(sp,1); sv_setnv(PUSHmortal, (NV)(n)); } STMT_END -#endif - -#ifndef mXPUSHi -# define mXPUSHi(i) STMT_START { EXTEND(sp,1); sv_setiv(PUSHmortal, (IV)(i)); } STMT_END -#endif - -#ifndef mXPUSHu -# define mXPUSHu(u) STMT_START { EXTEND(sp,1); sv_setuv(PUSHmortal, (UV)(u)); } STMT_END -#endif - -/* Replace: 1 */ -#ifndef call_sv -# define call_sv perl_call_sv -#endif - -#ifndef call_pv -# define call_pv perl_call_pv -#endif - -#ifndef call_argv -# define call_argv perl_call_argv -#endif - -#ifndef call_method -# define call_method perl_call_method -#endif -#ifndef eval_sv -# define eval_sv perl_eval_sv -#endif - -/* Replace: 0 */ -#ifndef PERL_LOADMOD_DENY -# define PERL_LOADMOD_DENY 0x1 -#endif - -#ifndef PERL_LOADMOD_NOIMPORT -# define PERL_LOADMOD_NOIMPORT 0x2 -#endif - -#ifndef PERL_LOADMOD_IMPORT_OPS -# define PERL_LOADMOD_IMPORT_OPS 0x4 -#endif - -#ifndef G_METHOD -# define G_METHOD 64 -# ifdef call_sv -# undef call_sv -# endif -# if (PERL_BCDVERSION < 0x5006000) -# define call_sv(sv, flags) ((flags) & G_METHOD ? perl_call_method((char *) SvPV_nolen_const(sv), \ - (flags) & ~G_METHOD) : perl_call_sv(sv, flags)) -# else -# define call_sv(sv, flags) ((flags) & G_METHOD ? Perl_call_method(aTHX_ (char *) SvPV_nolen_const(sv), \ - (flags) & ~G_METHOD) : Perl_call_sv(aTHX_ sv, flags)) -# endif -#endif - -/* Replace perl_eval_pv with eval_pv */ - -#ifndef eval_pv -#if defined(NEED_eval_pv) -static SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error); -static -#else -extern SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error); -#endif - -#ifdef eval_pv -# undef eval_pv -#endif -#define eval_pv(a,b) DPPP_(my_eval_pv)(aTHX_ a,b) -#define Perl_eval_pv DPPP_(my_eval_pv) - -#if defined(NEED_eval_pv) || defined(NEED_eval_pv_GLOBAL) - -SV* -DPPP_(my_eval_pv)(char *p, I32 croak_on_error) -{ - dSP; - SV* sv = newSVpv(p, 0); - - PUSHMARK(sp); - eval_sv(sv, G_SCALAR); - SvREFCNT_dec(sv); - - SPAGAIN; - sv = POPs; - PUTBACK; - - if (croak_on_error && SvTRUE(GvSV(errgv))) - croak("%s", SvPVx(GvSV(errgv), na)); - - return sv; -} - -#endif -#endif - -#ifndef vload_module -#if defined(NEED_vload_module) -static void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args); -static -#else -extern void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args); -#endif - -#ifdef vload_module -# undef vload_module -#endif -#define vload_module(a,b,c,d) DPPP_(my_vload_module)(aTHX_ a,b,c,d) -#define Perl_vload_module DPPP_(my_vload_module) - -#if defined(NEED_vload_module) || defined(NEED_vload_module_GLOBAL) - -void -DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args) -{ - dTHR; - dVAR; - OP *veop, *imop; - - OP * const modname = newSVOP(OP_CONST, 0, name); - /* 5.005 has a somewhat hacky force_normal that doesn't croak on - SvREADONLY() if PL_compling is true. Current perls take care in - ck_require() to correctly turn off SvREADONLY before calling - force_normal_flags(). This seems a better fix than fudging PL_compling - */ - SvREADONLY_off(((SVOP*)modname)->op_sv); - modname->op_private |= OPpCONST_BARE; - if (ver) { - veop = newSVOP(OP_CONST, 0, ver); - } - else - veop = NULL; - if (flags & PERL_LOADMOD_NOIMPORT) { - imop = sawparens(newNULLLIST()); - } - else if (flags & PERL_LOADMOD_IMPORT_OPS) { - imop = va_arg(*args, OP*); - } - else { - SV *sv; - imop = NULL; - sv = va_arg(*args, SV*); - while (sv) { - imop = append_elem(OP_LIST, imop, newSVOP(OP_CONST, 0, sv)); - sv = va_arg(*args, SV*); - } - } - { - const line_t ocopline = PL_copline; - COP * const ocurcop = PL_curcop; - const int oexpect = PL_expect; - -#if (PERL_BCDVERSION >= 0x5004000) - utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0), - veop, modname, imop); -#elif (PERL_BCDVERSION > 0x5003000) - utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(), - veop, modname, imop); -#else - utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(), - modname, imop); -#endif - PL_expect = oexpect; - PL_copline = ocopline; - PL_curcop = ocurcop; - } -} - -#endif -#endif - -#ifndef load_module -#if defined(NEED_load_module) -static void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...); -static -#else -extern void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...); -#endif - -#ifdef load_module -# undef load_module -#endif -#define load_module DPPP_(my_load_module) -#define Perl_load_module DPPP_(my_load_module) - -#if defined(NEED_load_module) || defined(NEED_load_module_GLOBAL) - -void -DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...) -{ - va_list args; - va_start(args, ver); - vload_module(flags, name, ver, &args); - va_end(args); -} - -#endif -#endif -#ifndef newRV_inc -# define newRV_inc(sv) newRV(sv) /* Replace */ -#endif - -#ifndef newRV_noinc -#if defined(NEED_newRV_noinc) -static SV * DPPP_(my_newRV_noinc)(SV *sv); -static -#else -extern SV * DPPP_(my_newRV_noinc)(SV *sv); -#endif - -#ifdef newRV_noinc -# undef newRV_noinc -#endif -#define newRV_noinc(a) DPPP_(my_newRV_noinc)(aTHX_ a) -#define Perl_newRV_noinc DPPP_(my_newRV_noinc) - -#if defined(NEED_newRV_noinc) || defined(NEED_newRV_noinc_GLOBAL) -SV * -DPPP_(my_newRV_noinc)(SV *sv) -{ - SV *rv = (SV *)newRV(sv); - SvREFCNT_dec(sv); - return rv; -} -#endif -#endif - -/* Hint: newCONSTSUB - * Returns a CV* as of perl-5.7.1. This return value is not supported - * by Devel::PPPort. - */ - -/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */ -#if (PERL_BCDVERSION < 0x5004063) && (PERL_BCDVERSION != 0x5004005) -#if defined(NEED_newCONSTSUB) -static void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv); -static -#else -extern void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv); -#endif - -#ifdef newCONSTSUB -# undef newCONSTSUB -#endif -#define newCONSTSUB(a,b,c) DPPP_(my_newCONSTSUB)(aTHX_ a,b,c) -#define Perl_newCONSTSUB DPPP_(my_newCONSTSUB) - -#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL) - -/* This is just a trick to avoid a dependency of newCONSTSUB on PL_parser */ -/* (There's no PL_parser in perl < 5.005, so this is completely safe) */ -#define D_PPP_PL_copline PL_copline - -void -DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv) -{ - U32 oldhints = PL_hints; - HV *old_cop_stash = PL_curcop->cop_stash; - HV *old_curstash = PL_curstash; - line_t oldline = PL_curcop->cop_line; - PL_curcop->cop_line = D_PPP_PL_copline; - - PL_hints &= ~HINT_BLOCK_SCOPE; - if (stash) - PL_curstash = PL_curcop->cop_stash = stash; - - newSUB( - -#if (PERL_BCDVERSION < 0x5003022) - start_subparse(), -#elif (PERL_BCDVERSION == 0x5003022) - start_subparse(0), -#else /* 5.003_23 onwards */ - start_subparse(FALSE, 0), -#endif - - newSVOP(OP_CONST, 0, newSVpv((char *) name, 0)), - newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */ - newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv)) - ); - - PL_hints = oldhints; - PL_curcop->cop_stash = old_cop_stash; - PL_curstash = old_curstash; - PL_curcop->cop_line = oldline; -} -#endif -#endif - -/* - * Boilerplate macros for initializing and accessing interpreter-local - * data from C. All statics in extensions should be reworked to use - * this, if you want to make the extension thread-safe. See ext/re/re.xs - * for an example of the use of these macros. - * - * Code that uses these macros is responsible for the following: - * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts" - * 2. Declare a typedef named my_cxt_t that is a structure that contains - * all the data that needs to be interpreter-local. - * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t. - * 4. Use the MY_CXT_INIT macro such that it is called exactly once - * (typically put in the BOOT: section). - * 5. Use the members of the my_cxt_t structure everywhere as - * MY_CXT.member. - * 6. Use the dMY_CXT macro (a declaration) in all the functions that - * access MY_CXT. - */ - -#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \ - defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT) - -#ifndef START_MY_CXT - -/* This must appear in all extensions that define a my_cxt_t structure, - * right after the definition (i.e. at file scope). The non-threads - * case below uses it to declare the data as static. */ -#define START_MY_CXT - -#if (PERL_BCDVERSION < 0x5004068) -/* Fetches the SV that keeps the per-interpreter data. */ -#define dMY_CXT_SV \ - SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE) -#else /* >= perl5.004_68 */ -#define dMY_CXT_SV \ - SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \ - sizeof(MY_CXT_KEY)-1, TRUE) -#endif /* < perl5.004_68 */ - -/* This declaration should be used within all functions that use the - * interpreter-local data. */ -#define dMY_CXT \ - dMY_CXT_SV; \ - my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv)) - -/* Creates and zeroes the per-interpreter data. - * (We allocate my_cxtp in a Perl SV so that it will be released when - * the interpreter goes away.) */ -#define MY_CXT_INIT \ - dMY_CXT_SV; \ - /* newSV() allocates one more than needed */ \ - my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ - Zero(my_cxtp, 1, my_cxt_t); \ - sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) - -/* This macro must be used to access members of the my_cxt_t structure. - * e.g. MYCXT.some_data */ -#define MY_CXT (*my_cxtp) - -/* Judicious use of these macros can reduce the number of times dMY_CXT - * is used. Use is similar to pTHX, aTHX etc. */ -#define pMY_CXT my_cxt_t *my_cxtp -#define pMY_CXT_ pMY_CXT, -#define _pMY_CXT ,pMY_CXT -#define aMY_CXT my_cxtp -#define aMY_CXT_ aMY_CXT, -#define _aMY_CXT ,aMY_CXT - -#endif /* START_MY_CXT */ - -#ifndef MY_CXT_CLONE -/* Clones the per-interpreter data. */ -#define MY_CXT_CLONE \ - dMY_CXT_SV; \ - my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ - Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\ - sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) -#endif - -#else /* single interpreter */ - -#ifndef START_MY_CXT - -#define START_MY_CXT static my_cxt_t my_cxt; -#define dMY_CXT_SV dNOOP -#define dMY_CXT dNOOP -#define MY_CXT_INIT NOOP -#define MY_CXT my_cxt - -#define pMY_CXT void -#define pMY_CXT_ -#define _pMY_CXT -#define aMY_CXT -#define aMY_CXT_ -#define _aMY_CXT - -#endif /* START_MY_CXT */ - -#ifndef MY_CXT_CLONE -#define MY_CXT_CLONE NOOP -#endif - -#endif - -#ifndef IVdf -# if IVSIZE == LONGSIZE -# define IVdf "ld" -# define UVuf "lu" -# define UVof "lo" -# define UVxf "lx" -# define UVXf "lX" -# elif IVSIZE == INTSIZE -# define IVdf "d" -# define UVuf "u" -# define UVof "o" -# define UVxf "x" -# define UVXf "X" -# else -# error "cannot define IV/UV formats" -# endif -#endif - -#ifndef NVef -# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \ - defined(PERL_PRIfldbl) && (PERL_BCDVERSION != 0x5006000) - /* Not very likely, but let's try anyway. */ -# define NVef PERL_PRIeldbl -# define NVff PERL_PRIfldbl -# define NVgf PERL_PRIgldbl -# else -# define NVef "e" -# define NVff "f" -# define NVgf "g" -# endif -#endif - -#ifndef SvREFCNT_inc -# ifdef PERL_USE_GCC_BRACE_GROUPS -# define SvREFCNT_inc(sv) \ - ({ \ - SV * const _sv = (SV*)(sv); \ - if (_sv) \ - (SvREFCNT(_sv))++; \ - _sv; \ - }) -# else -# define SvREFCNT_inc(sv) \ - ((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL) -# endif -#endif - -#ifndef SvREFCNT_inc_simple -# ifdef PERL_USE_GCC_BRACE_GROUPS -# define SvREFCNT_inc_simple(sv) \ - ({ \ - if (sv) \ - (SvREFCNT(sv))++; \ - (SV *)(sv); \ - }) -# else -# define SvREFCNT_inc_simple(sv) \ - ((sv) ? (SvREFCNT(sv)++,(SV*)(sv)) : NULL) -# endif -#endif - -#ifndef SvREFCNT_inc_NN -# ifdef PERL_USE_GCC_BRACE_GROUPS -# define SvREFCNT_inc_NN(sv) \ - ({ \ - SV * const _sv = (SV*)(sv); \ - SvREFCNT(_sv)++; \ - _sv; \ - }) -# else -# define SvREFCNT_inc_NN(sv) \ - (PL_Sv=(SV*)(sv),++(SvREFCNT(PL_Sv)),PL_Sv) -# endif -#endif - -#ifndef SvREFCNT_inc_void -# ifdef PERL_USE_GCC_BRACE_GROUPS -# define SvREFCNT_inc_void(sv) \ - ({ \ - SV * const _sv = (SV*)(sv); \ - if (_sv) \ - (void)(SvREFCNT(_sv)++); \ - }) -# else -# define SvREFCNT_inc_void(sv) \ - (void)((PL_Sv=(SV*)(sv)) ? ++(SvREFCNT(PL_Sv)) : 0) -# endif -#endif -#ifndef SvREFCNT_inc_simple_void -# define SvREFCNT_inc_simple_void(sv) STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END -#endif - -#ifndef SvREFCNT_inc_simple_NN -# define SvREFCNT_inc_simple_NN(sv) (++SvREFCNT(sv), (SV*)(sv)) -#endif - -#ifndef SvREFCNT_inc_void_NN -# define SvREFCNT_inc_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) -#endif - -#ifndef SvREFCNT_inc_simple_void_NN -# define SvREFCNT_inc_simple_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) -#endif - -#ifndef newSV_type - -#if defined(NEED_newSV_type) -static SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); -static -#else -extern SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); -#endif - -#ifdef newSV_type -# undef newSV_type -#endif -#define newSV_type(a) DPPP_(my_newSV_type)(aTHX_ a) -#define Perl_newSV_type DPPP_(my_newSV_type) - -#if defined(NEED_newSV_type) || defined(NEED_newSV_type_GLOBAL) - -SV* -DPPP_(my_newSV_type)(pTHX_ svtype const t) -{ - SV* const sv = newSV(0); - sv_upgrade(sv, t); - return sv; -} - -#endif - -#endif - -#if (PERL_BCDVERSION < 0x5006000) -# define D_PPP_CONSTPV_ARG(x) ((char *) (x)) -#else -# define D_PPP_CONSTPV_ARG(x) (x) -#endif -#ifndef newSVpvn -# define newSVpvn(data,len) ((data) \ - ? ((len) ? newSVpv((data), (len)) : newSVpv("", 0)) \ - : newSV(0)) -#endif -#ifndef newSVpvn_utf8 -# define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0) -#endif -#ifndef SVf_UTF8 -# define SVf_UTF8 0 -#endif - -#ifndef newSVpvn_flags - -#if defined(NEED_newSVpvn_flags) -static SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags); -static -#else -extern SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags); -#endif - -#ifdef newSVpvn_flags -# undef newSVpvn_flags -#endif -#define newSVpvn_flags(a,b,c) DPPP_(my_newSVpvn_flags)(aTHX_ a,b,c) -#define Perl_newSVpvn_flags DPPP_(my_newSVpvn_flags) - -#if defined(NEED_newSVpvn_flags) || defined(NEED_newSVpvn_flags_GLOBAL) - -SV * -DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags) -{ - SV *sv = newSVpvn(D_PPP_CONSTPV_ARG(s), len); - SvFLAGS(sv) |= (flags & SVf_UTF8); - return (flags & SVs_TEMP) ? sv_2mortal(sv) : sv; -} - -#endif - -#endif - -/* Backwards compatibility stuff... :-( */ -#if !defined(NEED_sv_2pv_flags) && defined(NEED_sv_2pv_nolen) -# define NEED_sv_2pv_flags -#endif -#if !defined(NEED_sv_2pv_flags_GLOBAL) && defined(NEED_sv_2pv_nolen_GLOBAL) -# define NEED_sv_2pv_flags_GLOBAL -#endif - -/* Hint: sv_2pv_nolen - * Use the SvPV_nolen() or SvPV_nolen_const() macros instead of sv_2pv_nolen(). - */ -#ifndef sv_2pv_nolen -# define sv_2pv_nolen(sv) SvPV_nolen(sv) -#endif - -#ifdef SvPVbyte - -/* Hint: SvPVbyte - * Does not work in perl-5.6.1, ppport.h implements a version - * borrowed from perl-5.7.3. - */ - -#if (PERL_BCDVERSION < 0x5007000) - -#if defined(NEED_sv_2pvbyte) -static char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp); -static -#else -extern char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp); -#endif - -#ifdef sv_2pvbyte -# undef sv_2pvbyte -#endif -#define sv_2pvbyte(a,b) DPPP_(my_sv_2pvbyte)(aTHX_ a,b) -#define Perl_sv_2pvbyte DPPP_(my_sv_2pvbyte) - -#if defined(NEED_sv_2pvbyte) || defined(NEED_sv_2pvbyte_GLOBAL) - -char * -DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp) -{ - sv_utf8_downgrade(sv,0); - return SvPV(sv,*lp); -} - -#endif - -/* Hint: sv_2pvbyte - * Use the SvPVbyte() macro instead of sv_2pvbyte(). - */ - -#undef SvPVbyte - -#define SvPVbyte(sv, lp) \ - ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \ - ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvbyte(sv, &lp)) - -#endif - -#else - -# define SvPVbyte SvPV -# define sv_2pvbyte sv_2pv - -#endif -#ifndef sv_2pvbyte_nolen -# define sv_2pvbyte_nolen(sv) sv_2pv_nolen(sv) -#endif - -/* Hint: sv_pvn - * Always use the SvPV() macro instead of sv_pvn(). - */ - -/* Hint: sv_pvn_force - * Always use the SvPV_force() macro instead of sv_pvn_force(). - */ - -/* If these are undefined, they're not handled by the core anyway */ -#ifndef SV_IMMEDIATE_UNREF -# define SV_IMMEDIATE_UNREF 0 -#endif - -#ifndef SV_GMAGIC -# define SV_GMAGIC 0 -#endif - -#ifndef SV_COW_DROP_PV -# define SV_COW_DROP_PV 0 -#endif - -#ifndef SV_UTF8_NO_ENCODING -# define SV_UTF8_NO_ENCODING 0 -#endif - -#ifndef SV_NOSTEAL -# define SV_NOSTEAL 0 -#endif - -#ifndef SV_CONST_RETURN -# define SV_CONST_RETURN 0 -#endif - -#ifndef SV_MUTABLE_RETURN -# define SV_MUTABLE_RETURN 0 -#endif - -#ifndef SV_SMAGIC -# define SV_SMAGIC 0 -#endif - -#ifndef SV_HAS_TRAILING_NUL -# define SV_HAS_TRAILING_NUL 0 -#endif - -#ifndef SV_COW_SHARED_HASH_KEYS -# define SV_COW_SHARED_HASH_KEYS 0 -#endif - -#if (PERL_BCDVERSION < 0x5007002) - -#if defined(NEED_sv_2pv_flags) -static char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); -static -#else -extern char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); -#endif - -#ifdef sv_2pv_flags -# undef sv_2pv_flags -#endif -#define sv_2pv_flags(a,b,c) DPPP_(my_sv_2pv_flags)(aTHX_ a,b,c) -#define Perl_sv_2pv_flags DPPP_(my_sv_2pv_flags) - -#if defined(NEED_sv_2pv_flags) || defined(NEED_sv_2pv_flags_GLOBAL) - -char * -DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags) -{ - STRLEN n_a = (STRLEN) flags; - return sv_2pv(sv, lp ? lp : &n_a); -} - -#endif - -#if defined(NEED_sv_pvn_force_flags) -static char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); -static -#else -extern char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); -#endif - -#ifdef sv_pvn_force_flags -# undef sv_pvn_force_flags -#endif -#define sv_pvn_force_flags(a,b,c) DPPP_(my_sv_pvn_force_flags)(aTHX_ a,b,c) -#define Perl_sv_pvn_force_flags DPPP_(my_sv_pvn_force_flags) - -#if defined(NEED_sv_pvn_force_flags) || defined(NEED_sv_pvn_force_flags_GLOBAL) - -char * -DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags) -{ - STRLEN n_a = (STRLEN) flags; - return sv_pvn_force(sv, lp ? lp : &n_a); -} - -#endif - -#endif - -#if (PERL_BCDVERSION < 0x5008008) || ( (PERL_BCDVERSION >= 0x5009000) && (PERL_BCDVERSION < 0x5009003) ) -# define DPPP_SVPV_NOLEN_LP_ARG &PL_na -#else -# define DPPP_SVPV_NOLEN_LP_ARG 0 -#endif -#ifndef SvPV_const -# define SvPV_const(sv, lp) SvPV_flags_const(sv, lp, SV_GMAGIC) -#endif - -#ifndef SvPV_mutable -# define SvPV_mutable(sv, lp) SvPV_flags_mutable(sv, lp, SV_GMAGIC) -#endif -#ifndef SvPV_flags -# define SvPV_flags(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pv_flags(sv, &lp, flags)) -#endif -#ifndef SvPV_flags_const -# define SvPV_flags_const(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX_const(sv)) : \ - (const char*) sv_2pv_flags(sv, &lp, flags|SV_CONST_RETURN)) -#endif -#ifndef SvPV_flags_const_nolen -# define SvPV_flags_const_nolen(sv, flags) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? SvPVX_const(sv) : \ - (const char*) sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, flags|SV_CONST_RETURN)) -#endif -#ifndef SvPV_flags_mutable -# define SvPV_flags_mutable(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) : \ - sv_2pv_flags(sv, &lp, flags|SV_MUTABLE_RETURN)) -#endif -#ifndef SvPV_force -# define SvPV_force(sv, lp) SvPV_force_flags(sv, lp, SV_GMAGIC) -#endif - -#ifndef SvPV_force_nolen -# define SvPV_force_nolen(sv) SvPV_force_flags_nolen(sv, SV_GMAGIC) -#endif - -#ifndef SvPV_force_mutable -# define SvPV_force_mutable(sv, lp) SvPV_force_flags_mutable(sv, lp, SV_GMAGIC) -#endif - -#ifndef SvPV_force_nomg -# define SvPV_force_nomg(sv, lp) SvPV_force_flags(sv, lp, 0) -#endif - -#ifndef SvPV_force_nomg_nolen -# define SvPV_force_nomg_nolen(sv) SvPV_force_flags_nolen(sv, 0) -#endif -#ifndef SvPV_force_flags -# define SvPV_force_flags(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvn_force_flags(sv, &lp, flags)) -#endif -#ifndef SvPV_force_flags_nolen -# define SvPV_force_flags_nolen(sv, flags) \ - ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ - ? SvPVX(sv) : sv_pvn_force_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, flags)) -#endif -#ifndef SvPV_force_flags_mutable -# define SvPV_force_flags_mutable(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) \ - : sv_pvn_force_flags(sv, &lp, flags|SV_MUTABLE_RETURN)) -#endif -#ifndef SvPV_nolen -# define SvPV_nolen(sv) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? SvPVX(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC)) -#endif -#ifndef SvPV_nolen_const -# define SvPV_nolen_const(sv) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? SvPVX_const(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC|SV_CONST_RETURN)) -#endif -#ifndef SvPV_nomg -# define SvPV_nomg(sv, lp) SvPV_flags(sv, lp, 0) -#endif - -#ifndef SvPV_nomg_const -# define SvPV_nomg_const(sv, lp) SvPV_flags_const(sv, lp, 0) -#endif - -#ifndef SvPV_nomg_const_nolen -# define SvPV_nomg_const_nolen(sv) SvPV_flags_const_nolen(sv, 0) -#endif - -#ifndef SvPV_nomg_nolen -# define SvPV_nomg_nolen(sv) ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? SvPVX(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, 0)) -#endif -#ifndef SvPV_renew -# define SvPV_renew(sv,n) STMT_START { SvLEN_set(sv, n); \ - SvPV_set((sv), (char *) saferealloc( \ - (Malloc_t)SvPVX(sv), (MEM_SIZE)((n)))); \ - } STMT_END -#endif -#ifndef SvMAGIC_set -# define SvMAGIC_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \ - (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END -#endif - -#if (PERL_BCDVERSION < 0x5009003) -#ifndef SvPVX_const -# define SvPVX_const(sv) ((const char*) (0 + SvPVX(sv))) -#endif - -#ifndef SvPVX_mutable -# define SvPVX_mutable(sv) (0 + SvPVX(sv)) -#endif -#ifndef SvRV_set -# define SvRV_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) >= SVt_RV); \ - (((XRV*) SvANY(sv))->xrv_rv = (val)); } STMT_END -#endif - -#else -#ifndef SvPVX_const -# define SvPVX_const(sv) ((const char*)((sv)->sv_u.svu_pv)) -#endif - -#ifndef SvPVX_mutable -# define SvPVX_mutable(sv) ((sv)->sv_u.svu_pv) -#endif -#ifndef SvRV_set -# define SvRV_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) >= SVt_RV); \ - ((sv)->sv_u.svu_rv = (val)); } STMT_END -#endif - -#endif -#ifndef SvSTASH_set -# define SvSTASH_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \ - (((XPVMG*) SvANY(sv))->xmg_stash = (val)); } STMT_END -#endif - -#if (PERL_BCDVERSION < 0x5004000) -#ifndef SvUV_set -# define SvUV_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \ - (((XPVIV*) SvANY(sv))->xiv_iv = (IV) (val)); } STMT_END -#endif - -#else -#ifndef SvUV_set -# define SvUV_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \ - (((XPVUV*) SvANY(sv))->xuv_uv = (val)); } STMT_END -#endif - -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(vnewSVpvf) -#if defined(NEED_vnewSVpvf) -static SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args); -static -#else -extern SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args); -#endif - -#ifdef vnewSVpvf -# undef vnewSVpvf -#endif -#define vnewSVpvf(a,b) DPPP_(my_vnewSVpvf)(aTHX_ a,b) -#define Perl_vnewSVpvf DPPP_(my_vnewSVpvf) - -#if defined(NEED_vnewSVpvf) || defined(NEED_vnewSVpvf_GLOBAL) - -SV * -DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args) -{ - register SV *sv = newSV(0); - sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); - return sv; -} - -#endif -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf) -# define sv_vcatpvf(sv, pat, args) sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)) -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf) -# define sv_vsetpvf(sv, pat, args) sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)) -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg) -#if defined(NEED_sv_catpvf_mg) -static void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...); -static -#else -extern void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...); -#endif - -#define Perl_sv_catpvf_mg DPPP_(my_sv_catpvf_mg) - -#if defined(NEED_sv_catpvf_mg) || defined(NEED_sv_catpvf_mg_GLOBAL) - -void -DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...) -{ - va_list args; - va_start(args, pat); - sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); - va_end(args); -} - -#endif -#endif - -#ifdef PERL_IMPLICIT_CONTEXT -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg_nocontext) -#if defined(NEED_sv_catpvf_mg_nocontext) -static void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...); -static -#else -extern void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...); -#endif - -#define sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext) -#define Perl_sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext) - -#if defined(NEED_sv_catpvf_mg_nocontext) || defined(NEED_sv_catpvf_mg_nocontext_GLOBAL) - -void -DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...) -{ - dTHX; - va_list args; - va_start(args, pat); - sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); - va_end(args); -} - -#endif -#endif -#endif - -/* sv_catpvf_mg depends on sv_catpvf_mg_nocontext */ -#ifndef sv_catpvf_mg -# ifdef PERL_IMPLICIT_CONTEXT -# define sv_catpvf_mg Perl_sv_catpvf_mg_nocontext -# else -# define sv_catpvf_mg Perl_sv_catpvf_mg -# endif -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf_mg) -# define sv_vcatpvf_mg(sv, pat, args) \ - STMT_START { \ - sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \ - SvSETMAGIC(sv); \ - } STMT_END -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg) -#if defined(NEED_sv_setpvf_mg) -static void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...); -static -#else -extern void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...); -#endif - -#define Perl_sv_setpvf_mg DPPP_(my_sv_setpvf_mg) - -#if defined(NEED_sv_setpvf_mg) || defined(NEED_sv_setpvf_mg_GLOBAL) - -void -DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...) -{ - va_list args; - va_start(args, pat); - sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); - va_end(args); -} - -#endif -#endif - -#ifdef PERL_IMPLICIT_CONTEXT -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg_nocontext) -#if defined(NEED_sv_setpvf_mg_nocontext) -static void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...); -static -#else -extern void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...); -#endif - -#define sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext) -#define Perl_sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext) - -#if defined(NEED_sv_setpvf_mg_nocontext) || defined(NEED_sv_setpvf_mg_nocontext_GLOBAL) - -void -DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...) -{ - dTHX; - va_list args; - va_start(args, pat); - sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); - va_end(args); -} - -#endif -#endif -#endif - -/* sv_setpvf_mg depends on sv_setpvf_mg_nocontext */ -#ifndef sv_setpvf_mg -# ifdef PERL_IMPLICIT_CONTEXT -# define sv_setpvf_mg Perl_sv_setpvf_mg_nocontext -# else -# define sv_setpvf_mg Perl_sv_setpvf_mg -# endif -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf_mg) -# define sv_vsetpvf_mg(sv, pat, args) \ - STMT_START { \ - sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \ - SvSETMAGIC(sv); \ - } STMT_END -#endif - -/* Hint: newSVpvn_share - * The SVs created by this function only mimic the behaviour of - * shared PVs without really being shared. Only use if you know - * what you're doing. - */ - -#ifndef newSVpvn_share - -#if defined(NEED_newSVpvn_share) -static SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash); -static -#else -extern SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash); -#endif - -#ifdef newSVpvn_share -# undef newSVpvn_share -#endif -#define newSVpvn_share(a,b,c) DPPP_(my_newSVpvn_share)(aTHX_ a,b,c) -#define Perl_newSVpvn_share DPPP_(my_newSVpvn_share) - -#if defined(NEED_newSVpvn_share) || defined(NEED_newSVpvn_share_GLOBAL) - -SV * -DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash) -{ - SV *sv; - if (len < 0) - len = -len; - if (!hash) - PERL_HASH(hash, (char*) src, len); - sv = newSVpvn((char *) src, len); - sv_upgrade(sv, SVt_PVIV); - SvIVX(sv) = hash; - SvREADONLY_on(sv); - SvPOK_on(sv); - return sv; -} - -#endif - -#endif -#ifndef SvSHARED_HASH -# define SvSHARED_HASH(sv) (0 + SvUVX(sv)) -#endif -#ifndef HvNAME_get -# define HvNAME_get(hv) HvNAME(hv) -#endif -#ifndef HvNAMELEN_get -# define HvNAMELEN_get(hv) (HvNAME_get(hv) ? (I32)strlen(HvNAME_get(hv)) : 0) -#endif -#ifndef GvSVn -# define GvSVn(gv) GvSV(gv) -#endif - -#ifndef isGV_with_GP -# define isGV_with_GP(gv) isGV(gv) -#endif - -#ifndef gv_fetchpvn_flags -# define gv_fetchpvn_flags(name, len, flags, svt) gv_fetchpv(name, flags, svt) -#endif - -#ifndef gv_fetchsv -# define gv_fetchsv(name, flags, svt) gv_fetchpv(SvPV_nolen_const(name), flags, svt) -#endif -#ifndef get_cvn_flags -# define get_cvn_flags(name, namelen, flags) get_cv(name, flags) -#endif -#ifndef WARN_ALL -# define WARN_ALL 0 -#endif - -#ifndef WARN_CLOSURE -# define WARN_CLOSURE 1 -#endif - -#ifndef WARN_DEPRECATED -# define WARN_DEPRECATED 2 -#endif - -#ifndef WARN_EXITING -# define WARN_EXITING 3 -#endif - -#ifndef WARN_GLOB -# define WARN_GLOB 4 -#endif - -#ifndef WARN_IO -# define WARN_IO 5 -#endif - -#ifndef WARN_CLOSED -# define WARN_CLOSED 6 -#endif - -#ifndef WARN_EXEC -# define WARN_EXEC 7 -#endif - -#ifndef WARN_LAYER -# define WARN_LAYER 8 -#endif - -#ifndef WARN_NEWLINE -# define WARN_NEWLINE 9 -#endif - -#ifndef WARN_PIPE -# define WARN_PIPE 10 -#endif - -#ifndef WARN_UNOPENED -# define WARN_UNOPENED 11 -#endif - -#ifndef WARN_MISC -# define WARN_MISC 12 -#endif - -#ifndef WARN_NUMERIC -# define WARN_NUMERIC 13 -#endif - -#ifndef WARN_ONCE -# define WARN_ONCE 14 -#endif - -#ifndef WARN_OVERFLOW -# define WARN_OVERFLOW 15 -#endif - -#ifndef WARN_PACK -# define WARN_PACK 16 -#endif - -#ifndef WARN_PORTABLE -# define WARN_PORTABLE 17 -#endif - -#ifndef WARN_RECURSION -# define WARN_RECURSION 18 -#endif - -#ifndef WARN_REDEFINE -# define WARN_REDEFINE 19 -#endif - -#ifndef WARN_REGEXP -# define WARN_REGEXP 20 -#endif - -#ifndef WARN_SEVERE -# define WARN_SEVERE 21 -#endif - -#ifndef WARN_DEBUGGING -# define WARN_DEBUGGING 22 -#endif - -#ifndef WARN_INPLACE -# define WARN_INPLACE 23 -#endif - -#ifndef WARN_INTERNAL -# define WARN_INTERNAL 24 -#endif - -#ifndef WARN_MALLOC -# define WARN_MALLOC 25 -#endif - -#ifndef WARN_SIGNAL -# define WARN_SIGNAL 26 -#endif - -#ifndef WARN_SUBSTR -# define WARN_SUBSTR 27 -#endif - -#ifndef WARN_SYNTAX -# define WARN_SYNTAX 28 -#endif - -#ifndef WARN_AMBIGUOUS -# define WARN_AMBIGUOUS 29 -#endif - -#ifndef WARN_BAREWORD -# define WARN_BAREWORD 30 -#endif - -#ifndef WARN_DIGIT -# define WARN_DIGIT 31 -#endif - -#ifndef WARN_PARENTHESIS -# define WARN_PARENTHESIS 32 -#endif - -#ifndef WARN_PRECEDENCE -# define WARN_PRECEDENCE 33 -#endif - -#ifndef WARN_PRINTF -# define WARN_PRINTF 34 -#endif - -#ifndef WARN_PROTOTYPE -# define WARN_PROTOTYPE 35 -#endif - -#ifndef WARN_QW -# define WARN_QW 36 -#endif - -#ifndef WARN_RESERVED -# define WARN_RESERVED 37 -#endif - -#ifndef WARN_SEMICOLON -# define WARN_SEMICOLON 38 -#endif - -#ifndef WARN_TAINT -# define WARN_TAINT 39 -#endif - -#ifndef WARN_THREADS -# define WARN_THREADS 40 -#endif - -#ifndef WARN_UNINITIALIZED -# define WARN_UNINITIALIZED 41 -#endif - -#ifndef WARN_UNPACK -# define WARN_UNPACK 42 -#endif - -#ifndef WARN_UNTIE -# define WARN_UNTIE 43 -#endif - -#ifndef WARN_UTF8 -# define WARN_UTF8 44 -#endif - -#ifndef WARN_VOID -# define WARN_VOID 45 -#endif - -#ifndef WARN_ASSERTIONS -# define WARN_ASSERTIONS 46 -#endif -#ifndef packWARN -# define packWARN(a) (a) -#endif - -#ifndef ckWARN -# ifdef G_WARN_ON -# define ckWARN(a) (PL_dowarn & G_WARN_ON) -# else -# define ckWARN(a) PL_dowarn -# endif -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(warner) -#if defined(NEED_warner) -static void DPPP_(my_warner)(U32 err, const char *pat, ...); -static -#else -extern void DPPP_(my_warner)(U32 err, const char *pat, ...); -#endif - -#define Perl_warner DPPP_(my_warner) - -#if defined(NEED_warner) || defined(NEED_warner_GLOBAL) - -void -DPPP_(my_warner)(U32 err, const char *pat, ...) -{ - SV *sv; - va_list args; - - PERL_UNUSED_ARG(err); - - va_start(args, pat); - sv = vnewSVpvf(pat, &args); - va_end(args); - sv_2mortal(sv); - warn("%s", SvPV_nolen(sv)); -} - -#define warner Perl_warner - -#define Perl_warner_nocontext Perl_warner - -#endif -#endif - -/* concatenating with "" ensures that only literal strings are accepted as argument - * note that STR_WITH_LEN() can't be used as argument to macros or functions that - * under some configurations might be macros - */ -#ifndef STR_WITH_LEN -# define STR_WITH_LEN(s) (s ""), (sizeof(s)-1) -#endif -#ifndef newSVpvs -# define newSVpvs(str) newSVpvn(str "", sizeof(str) - 1) -#endif - -#ifndef newSVpvs_flags -# define newSVpvs_flags(str, flags) newSVpvn_flags(str "", sizeof(str) - 1, flags) -#endif - -#ifndef newSVpvs_share -# define newSVpvs_share(str) newSVpvn_share(str "", sizeof(str) - 1, 0) -#endif - -#ifndef sv_catpvs -# define sv_catpvs(sv, str) sv_catpvn(sv, str "", sizeof(str) - 1) -#endif - -#ifndef sv_setpvs -# define sv_setpvs(sv, str) sv_setpvn(sv, str "", sizeof(str) - 1) -#endif - -#ifndef hv_fetchs -# define hv_fetchs(hv, key, lval) hv_fetch(hv, key "", sizeof(key) - 1, lval) -#endif - -#ifndef hv_stores -# define hv_stores(hv, key, val) hv_store(hv, key "", sizeof(key) - 1, val, 0) -#endif -#ifndef gv_fetchpvs -# define gv_fetchpvs(name, flags, svt) gv_fetchpvn_flags(name "", sizeof(name) - 1, flags, svt) -#endif - -#ifndef gv_stashpvs -# define gv_stashpvs(name, flags) gv_stashpvn(name "", sizeof(name) - 1, flags) -#endif -#ifndef get_cvs -# define get_cvs(name, flags) get_cvn_flags(name "", sizeof(name)-1, flags) -#endif -#ifndef SvGETMAGIC -# define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END -#endif - -/* Some random bits for sv_unmagicext. These should probably be pulled in for - real and organized at some point */ -#ifndef HEf_SVKEY -# define HEf_SVKEY -2 -#endif - -#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) -# define MUTABLE_PTR(p) ({ void *_p = (p); _p; }) -#else -# define MUTABLE_PTR(p) ((void *) (p)) -#endif - -#define MUTABLE_SV(p) ((SV *)MUTABLE_PTR(p)) - -/* end of random bits */ -#ifndef PERL_MAGIC_sv -# define PERL_MAGIC_sv '\0' -#endif - -#ifndef PERL_MAGIC_overload -# define PERL_MAGIC_overload 'A' -#endif - -#ifndef PERL_MAGIC_overload_elem -# define PERL_MAGIC_overload_elem 'a' -#endif - -#ifndef PERL_MAGIC_overload_table -# define PERL_MAGIC_overload_table 'c' -#endif - -#ifndef PERL_MAGIC_bm -# define PERL_MAGIC_bm 'B' -#endif - -#ifndef PERL_MAGIC_regdata -# define PERL_MAGIC_regdata 'D' -#endif - -#ifndef PERL_MAGIC_regdatum -# define PERL_MAGIC_regdatum 'd' -#endif - -#ifndef PERL_MAGIC_env -# define PERL_MAGIC_env 'E' -#endif - -#ifndef PERL_MAGIC_envelem -# define PERL_MAGIC_envelem 'e' -#endif - -#ifndef PERL_MAGIC_fm -# define PERL_MAGIC_fm 'f' -#endif - -#ifndef PERL_MAGIC_regex_global -# define PERL_MAGIC_regex_global 'g' -#endif - -#ifndef PERL_MAGIC_isa -# define PERL_MAGIC_isa 'I' -#endif - -#ifndef PERL_MAGIC_isaelem -# define PERL_MAGIC_isaelem 'i' -#endif - -#ifndef PERL_MAGIC_nkeys -# define PERL_MAGIC_nkeys 'k' -#endif - -#ifndef PERL_MAGIC_dbfile -# define PERL_MAGIC_dbfile 'L' -#endif - -#ifndef PERL_MAGIC_dbline -# define PERL_MAGIC_dbline 'l' -#endif - -#ifndef PERL_MAGIC_mutex -# define PERL_MAGIC_mutex 'm' -#endif - -#ifndef PERL_MAGIC_shared -# define PERL_MAGIC_shared 'N' -#endif - -#ifndef PERL_MAGIC_shared_scalar -# define PERL_MAGIC_shared_scalar 'n' -#endif - -#ifndef PERL_MAGIC_collxfrm -# define PERL_MAGIC_collxfrm 'o' -#endif - -#ifndef PERL_MAGIC_tied -# define PERL_MAGIC_tied 'P' -#endif - -#ifndef PERL_MAGIC_tiedelem -# define PERL_MAGIC_tiedelem 'p' -#endif - -#ifndef PERL_MAGIC_tiedscalar -# define PERL_MAGIC_tiedscalar 'q' -#endif - -#ifndef PERL_MAGIC_qr -# define PERL_MAGIC_qr 'r' -#endif - -#ifndef PERL_MAGIC_sig -# define PERL_MAGIC_sig 'S' -#endif - -#ifndef PERL_MAGIC_sigelem -# define PERL_MAGIC_sigelem 's' -#endif - -#ifndef PERL_MAGIC_taint -# define PERL_MAGIC_taint 't' -#endif - -#ifndef PERL_MAGIC_uvar -# define PERL_MAGIC_uvar 'U' -#endif - -#ifndef PERL_MAGIC_uvar_elem -# define PERL_MAGIC_uvar_elem 'u' -#endif - -#ifndef PERL_MAGIC_vstring -# define PERL_MAGIC_vstring 'V' -#endif - -#ifndef PERL_MAGIC_vec -# define PERL_MAGIC_vec 'v' -#endif - -#ifndef PERL_MAGIC_utf8 -# define PERL_MAGIC_utf8 'w' -#endif - -#ifndef PERL_MAGIC_substr -# define PERL_MAGIC_substr 'x' -#endif - -#ifndef PERL_MAGIC_defelem -# define PERL_MAGIC_defelem 'y' -#endif - -#ifndef PERL_MAGIC_glob -# define PERL_MAGIC_glob '*' -#endif - -#ifndef PERL_MAGIC_arylen -# define PERL_MAGIC_arylen '#' -#endif - -#ifndef PERL_MAGIC_pos -# define PERL_MAGIC_pos '.' -#endif - -#ifndef PERL_MAGIC_backref -# define PERL_MAGIC_backref '<' -#endif - -#ifndef PERL_MAGIC_ext -# define PERL_MAGIC_ext '~' -#endif - -/* That's the best we can do... */ -#ifndef sv_catpvn_nomg -# define sv_catpvn_nomg sv_catpvn -#endif - -#ifndef sv_catsv_nomg -# define sv_catsv_nomg sv_catsv -#endif - -#ifndef sv_setsv_nomg -# define sv_setsv_nomg sv_setsv -#endif - -#ifndef sv_pvn_nomg -# define sv_pvn_nomg sv_pvn -#endif - -#ifndef SvIV_nomg -# define SvIV_nomg SvIV -#endif - -#ifndef SvUV_nomg -# define SvUV_nomg SvUV -#endif - -#ifndef sv_catpv_mg -# define sv_catpv_mg(sv, ptr) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_catpv(TeMpSv,ptr); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_catpvn_mg -# define sv_catpvn_mg(sv, ptr, len) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_catpvn(TeMpSv,ptr,len); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_catsv_mg -# define sv_catsv_mg(dsv, ssv) \ - STMT_START { \ - SV *TeMpSv = dsv; \ - sv_catsv(TeMpSv,ssv); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setiv_mg -# define sv_setiv_mg(sv, i) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setiv(TeMpSv,i); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setnv_mg -# define sv_setnv_mg(sv, num) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setnv(TeMpSv,num); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setpv_mg -# define sv_setpv_mg(sv, ptr) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setpv(TeMpSv,ptr); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setpvn_mg -# define sv_setpvn_mg(sv, ptr, len) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setpvn(TeMpSv,ptr,len); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setsv_mg -# define sv_setsv_mg(dsv, ssv) \ - STMT_START { \ - SV *TeMpSv = dsv; \ - sv_setsv(TeMpSv,ssv); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setuv_mg -# define sv_setuv_mg(sv, i) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setuv(TeMpSv,i); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_usepvn_mg -# define sv_usepvn_mg(sv, ptr, len) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_usepvn(TeMpSv,ptr,len); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif -#ifndef SvVSTRING_mg -# define SvVSTRING_mg(sv) (SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_vstring) : NULL) -#endif - -/* Hint: sv_magic_portable - * This is a compatibility function that is only available with - * Devel::PPPort. It is NOT in the perl core. - * Its purpose is to mimic the 5.8.0 behaviour of sv_magic() when - * it is being passed a name pointer with namlen == 0. In that - * case, perl 5.8.0 and later store the pointer, not a copy of it. - * The compatibility can be provided back to perl 5.004. With - * earlier versions, the code will not compile. - */ - -#if (PERL_BCDVERSION < 0x5004000) - - /* code that uses sv_magic_portable will not compile */ - -#elif (PERL_BCDVERSION < 0x5008000) - -# define sv_magic_portable(sv, obj, how, name, namlen) \ - STMT_START { \ - SV *SvMp_sv = (sv); \ - char *SvMp_name = (char *) (name); \ - I32 SvMp_namlen = (namlen); \ - if (SvMp_name && SvMp_namlen == 0) \ - { \ - MAGIC *mg; \ - sv_magic(SvMp_sv, obj, how, 0, 0); \ - mg = SvMAGIC(SvMp_sv); \ - mg->mg_len = -42; /* XXX: this is the tricky part */ \ - mg->mg_ptr = SvMp_name; \ - } \ - else \ - { \ - sv_magic(SvMp_sv, obj, how, SvMp_name, SvMp_namlen); \ - } \ - } STMT_END - -#else - -# define sv_magic_portable(a, b, c, d, e) sv_magic(a, b, c, d, e) - -#endif - -#if !defined(mg_findext) -#if defined(NEED_mg_findext) -static MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl); -static -#else -extern MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl); -#endif - -#define mg_findext DPPP_(my_mg_findext) -#define Perl_mg_findext DPPP_(my_mg_findext) - -#if defined(NEED_mg_findext) || defined(NEED_mg_findext_GLOBAL) - -MAGIC * -DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl) { - if (sv) { - MAGIC *mg; - -#ifdef AvPAD_NAMELIST - assert(!(SvTYPE(sv) == SVt_PVAV && AvPAD_NAMELIST(sv))); -#endif - - for (mg = SvMAGIC (sv); mg; mg = mg->mg_moremagic) { - if (mg->mg_type == type && mg->mg_virtual == vtbl) - return mg; - } - } - - return NULL; -} - -#endif -#endif - -#if !defined(sv_unmagicext) -#if defined(NEED_sv_unmagicext) -static int DPPP_(my_sv_unmagicext)(pTHX_ SV * const sv, const int type, MGVTBL * vtbl); -static -#else -extern int DPPP_(my_sv_unmagicext)(pTHX_ SV * const sv, const int type, MGVTBL * vtbl); -#endif - -#ifdef sv_unmagicext -# undef sv_unmagicext -#endif -#define sv_unmagicext(a,b,c) DPPP_(my_sv_unmagicext)(aTHX_ a,b,c) -#define Perl_sv_unmagicext DPPP_(my_sv_unmagicext) - -#if defined(NEED_sv_unmagicext) || defined(NEED_sv_unmagicext_GLOBAL) - -int -DPPP_(my_sv_unmagicext)(pTHX_ SV *const sv, const int type, MGVTBL *vtbl) -{ - MAGIC* mg; - MAGIC** mgp; - - if (SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv)) - return 0; - mgp = &(SvMAGIC(sv)); - for (mg = *mgp; mg; mg = *mgp) { - const MGVTBL* const virt = mg->mg_virtual; - if (mg->mg_type == type && virt == vtbl) { - *mgp = mg->mg_moremagic; - if (virt && virt->svt_free) - virt->svt_free(aTHX_ sv, mg); - if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) { - if (mg->mg_len > 0) - Safefree(mg->mg_ptr); - else if (mg->mg_len == HEf_SVKEY) /* Questionable on older perls... */ - SvREFCNT_dec(MUTABLE_SV(mg->mg_ptr)); - else if (mg->mg_type == PERL_MAGIC_utf8) - Safefree(mg->mg_ptr); - } - if (mg->mg_flags & MGf_REFCOUNTED) - SvREFCNT_dec(mg->mg_obj); - Safefree(mg); - } - else - mgp = &mg->mg_moremagic; - } - if (SvMAGIC(sv)) { - if (SvMAGICAL(sv)) /* if we're under save_magic, wait for restore_magic; */ - mg_magical(sv); /* else fix the flags now */ - } - else { - SvMAGICAL_off(sv); - SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; - } - return 0; -} - -#endif -#endif - -#ifdef USE_ITHREADS -#ifndef CopFILE -# define CopFILE(c) ((c)->cop_file) -#endif - -#ifndef CopFILEGV -# define CopFILEGV(c) (CopFILE(c) ? gv_fetchfile(CopFILE(c)) : Nullgv) -#endif - -#ifndef CopFILE_set -# define CopFILE_set(c,pv) ((c)->cop_file = savepv(pv)) -#endif - -#ifndef CopFILESV -# define CopFILESV(c) (CopFILE(c) ? GvSV(gv_fetchfile(CopFILE(c))) : Nullsv) -#endif - -#ifndef CopFILEAV -# define CopFILEAV(c) (CopFILE(c) ? GvAV(gv_fetchfile(CopFILE(c))) : Nullav) -#endif - -#ifndef CopSTASHPV -# define CopSTASHPV(c) ((c)->cop_stashpv) -#endif - -#ifndef CopSTASHPV_set -# define CopSTASHPV_set(c,pv) ((c)->cop_stashpv = ((pv) ? savepv(pv) : Nullch)) -#endif - -#ifndef CopSTASH -# define CopSTASH(c) (CopSTASHPV(c) ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv) -#endif - -#ifndef CopSTASH_set -# define CopSTASH_set(c,hv) CopSTASHPV_set(c, (hv) ? HvNAME(hv) : Nullch) -#endif - -#ifndef CopSTASH_eq -# define CopSTASH_eq(c,hv) ((hv) && (CopSTASHPV(c) == HvNAME(hv) \ - || (CopSTASHPV(c) && HvNAME(hv) \ - && strEQ(CopSTASHPV(c), HvNAME(hv))))) -#endif - -#else -#ifndef CopFILEGV -# define CopFILEGV(c) ((c)->cop_filegv) -#endif - -#ifndef CopFILEGV_set -# define CopFILEGV_set(c,gv) ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv)) -#endif - -#ifndef CopFILE_set -# define CopFILE_set(c,pv) CopFILEGV_set((c), gv_fetchfile(pv)) -#endif - -#ifndef CopFILESV -# define CopFILESV(c) (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : Nullsv) -#endif - -#ifndef CopFILEAV -# define CopFILEAV(c) (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : Nullav) -#endif - -#ifndef CopFILE -# define CopFILE(c) (CopFILESV(c) ? SvPVX(CopFILESV(c)) : Nullch) -#endif - -#ifndef CopSTASH -# define CopSTASH(c) ((c)->cop_stash) -#endif - -#ifndef CopSTASH_set -# define CopSTASH_set(c,hv) ((c)->cop_stash = (hv)) -#endif - -#ifndef CopSTASHPV -# define CopSTASHPV(c) (CopSTASH(c) ? HvNAME(CopSTASH(c)) : Nullch) -#endif - -#ifndef CopSTASHPV_set -# define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD)) -#endif - -#ifndef CopSTASH_eq -# define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv)) -#endif - -#endif /* USE_ITHREADS */ - -#if (PERL_BCDVERSION >= 0x5006000) -#ifndef caller_cx - -# if defined(NEED_caller_cx) || defined(NEED_caller_cx_GLOBAL) -static I32 -DPPP_dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock) -{ - I32 i; - - for (i = startingblock; i >= 0; i--) { - register const PERL_CONTEXT * const cx = &cxstk[i]; - switch (CxTYPE(cx)) { - default: - continue; - case CXt_EVAL: - case CXt_SUB: - case CXt_FORMAT: - return i; - } - } - return i; -} -# endif - -# if defined(NEED_caller_cx) -static const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp); -static -#else -extern const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp); -#endif - -#ifdef caller_cx -# undef caller_cx -#endif -#define caller_cx(a,b) DPPP_(my_caller_cx)(aTHX_ a,b) -#define Perl_caller_cx DPPP_(my_caller_cx) - -#if defined(NEED_caller_cx) || defined(NEED_caller_cx_GLOBAL) - -const PERL_CONTEXT * -DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp) -{ - register I32 cxix = DPPP_dopoptosub_at(cxstack, cxstack_ix); - register const PERL_CONTEXT *cx; - register const PERL_CONTEXT *ccstack = cxstack; - const PERL_SI *top_si = PL_curstackinfo; - - for (;;) { - /* we may be in a higher stacklevel, so dig down deeper */ - while (cxix < 0 && top_si->si_type != PERLSI_MAIN) { - top_si = top_si->si_prev; - ccstack = top_si->si_cxstack; - cxix = DPPP_dopoptosub_at(ccstack, top_si->si_cxix); - } - if (cxix < 0) - return NULL; - /* caller() should not report the automatic calls to &DB::sub */ - if (PL_DBsub && GvCV(PL_DBsub) && cxix >= 0 && - ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub)) - count++; - if (!count--) - break; - cxix = DPPP_dopoptosub_at(ccstack, cxix - 1); - } - - cx = &ccstack[cxix]; - if (dbcxp) *dbcxp = cx; - - if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { - const I32 dbcxix = DPPP_dopoptosub_at(ccstack, cxix - 1); - /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the - field below is defined for any cx. */ - /* caller() should not report the automatic calls to &DB::sub */ - if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) - cx = &ccstack[dbcxix]; - } - - return cx; -} - -# endif -#endif /* caller_cx */ -#endif /* 5.6.0 */ -#ifndef IN_PERL_COMPILETIME -# define IN_PERL_COMPILETIME (PL_curcop == &PL_compiling) -#endif - -#ifndef IN_LOCALE_RUNTIME -# define IN_LOCALE_RUNTIME (PL_curcop->op_private & HINT_LOCALE) -#endif - -#ifndef IN_LOCALE_COMPILETIME -# define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE) -#endif - -#ifndef IN_LOCALE -# define IN_LOCALE (IN_PERL_COMPILETIME ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME) -#endif -#ifndef IS_NUMBER_IN_UV -# define IS_NUMBER_IN_UV 0x01 -#endif - -#ifndef IS_NUMBER_GREATER_THAN_UV_MAX -# define IS_NUMBER_GREATER_THAN_UV_MAX 0x02 -#endif - -#ifndef IS_NUMBER_NOT_INT -# define IS_NUMBER_NOT_INT 0x04 -#endif - -#ifndef IS_NUMBER_NEG -# define IS_NUMBER_NEG 0x08 -#endif - -#ifndef IS_NUMBER_INFINITY -# define IS_NUMBER_INFINITY 0x10 -#endif - -#ifndef IS_NUMBER_NAN -# define IS_NUMBER_NAN 0x20 -#endif -#ifndef GROK_NUMERIC_RADIX -# define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(sp, send) -#endif -#ifndef PERL_SCAN_GREATER_THAN_UV_MAX -# define PERL_SCAN_GREATER_THAN_UV_MAX 0x02 -#endif - -#ifndef PERL_SCAN_SILENT_ILLDIGIT -# define PERL_SCAN_SILENT_ILLDIGIT 0x04 -#endif - -#ifndef PERL_SCAN_ALLOW_UNDERSCORES -# define PERL_SCAN_ALLOW_UNDERSCORES 0x01 -#endif - -#ifndef PERL_SCAN_DISALLOW_PREFIX -# define PERL_SCAN_DISALLOW_PREFIX 0x02 -#endif - -#ifndef grok_numeric_radix -#if defined(NEED_grok_numeric_radix) -static bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send); -static -#else -extern bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send); -#endif - -#ifdef grok_numeric_radix -# undef grok_numeric_radix -#endif -#define grok_numeric_radix(a,b) DPPP_(my_grok_numeric_radix)(aTHX_ a,b) -#define Perl_grok_numeric_radix DPPP_(my_grok_numeric_radix) - -#if defined(NEED_grok_numeric_radix) || defined(NEED_grok_numeric_radix_GLOBAL) -bool -DPPP_(my_grok_numeric_radix)(pTHX_ const char **sp, const char *send) -{ -#ifdef USE_LOCALE_NUMERIC -#ifdef PL_numeric_radix_sv - if (PL_numeric_radix_sv && IN_LOCALE) { - STRLEN len; - char* radix = SvPV(PL_numeric_radix_sv, len); - if (*sp + len <= send && memEQ(*sp, radix, len)) { - *sp += len; - return TRUE; - } - } -#else - /* older perls don't have PL_numeric_radix_sv so the radix - * must manually be requested from locale.h - */ -#include - dTHR; /* needed for older threaded perls */ - struct lconv *lc = localeconv(); - char *radix = lc->decimal_point; - if (radix && IN_LOCALE) { - STRLEN len = strlen(radix); - if (*sp + len <= send && memEQ(*sp, radix, len)) { - *sp += len; - return TRUE; - } - } -#endif -#endif /* USE_LOCALE_NUMERIC */ - /* always try "." if numeric radix didn't match because - * we may have data from different locales mixed */ - if (*sp < send && **sp == '.') { - ++*sp; - return TRUE; - } - return FALSE; -} -#endif -#endif - -#ifndef grok_number -#if defined(NEED_grok_number) -static int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep); -static -#else -extern int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep); -#endif - -#ifdef grok_number -# undef grok_number -#endif -#define grok_number(a,b,c) DPPP_(my_grok_number)(aTHX_ a,b,c) -#define Perl_grok_number DPPP_(my_grok_number) - -#if defined(NEED_grok_number) || defined(NEED_grok_number_GLOBAL) -int -DPPP_(my_grok_number)(pTHX_ const char *pv, STRLEN len, UV *valuep) -{ - const char *s = pv; - const char *send = pv + len; - const UV max_div_10 = UV_MAX / 10; - const char max_mod_10 = UV_MAX % 10; - int numtype = 0; - int sawinf = 0; - int sawnan = 0; - - while (s < send && isSPACE(*s)) - s++; - if (s == send) { - return 0; - } else if (*s == '-') { - s++; - numtype = IS_NUMBER_NEG; - } - else if (*s == '+') - s++; - - if (s == send) - return 0; - - /* next must be digit or the radix separator or beginning of infinity */ - if (isDIGIT(*s)) { - /* UVs are at least 32 bits, so the first 9 decimal digits cannot - overflow. */ - UV value = *s - '0'; - /* This construction seems to be more optimiser friendly. - (without it gcc does the isDIGIT test and the *s - '0' separately) - With it gcc on arm is managing 6 instructions (6 cycles) per digit. - In theory the optimiser could deduce how far to unroll the loop - before checking for overflow. */ - if (++s < send) { - int digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - /* Now got 9 digits, so need to check - each time for overflow. */ - digit = *s - '0'; - while (digit >= 0 && digit <= 9 - && (value < max_div_10 - || (value == max_div_10 - && digit <= max_mod_10))) { - value = value * 10 + digit; - if (++s < send) - digit = *s - '0'; - else - break; - } - if (digit >= 0 && digit <= 9 - && (s < send)) { - /* value overflowed. - skip the remaining digits, don't - worry about setting *valuep. */ - do { - s++; - } while (s < send && isDIGIT(*s)); - numtype |= - IS_NUMBER_GREATER_THAN_UV_MAX; - goto skip_value; - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - numtype |= IS_NUMBER_IN_UV; - if (valuep) - *valuep = value; - - skip_value: - if (GROK_NUMERIC_RADIX(&s, send)) { - numtype |= IS_NUMBER_NOT_INT; - while (s < send && isDIGIT(*s)) /* optional digits after the radix */ - s++; - } - } - else if (GROK_NUMERIC_RADIX(&s, send)) { - numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */ - /* no digits before the radix means we need digits after it */ - if (s < send && isDIGIT(*s)) { - do { - s++; - } while (s < send && isDIGIT(*s)); - if (valuep) { - /* integer approximation is valid - it's 0. */ - *valuep = 0; - } - } - else - return 0; - } else if (*s == 'I' || *s == 'i') { - s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; - s++; if (s == send || (*s != 'F' && *s != 'f')) return 0; - s++; if (s < send && (*s == 'I' || *s == 'i')) { - s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; - s++; if (s == send || (*s != 'I' && *s != 'i')) return 0; - s++; if (s == send || (*s != 'T' && *s != 't')) return 0; - s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0; - s++; - } - sawinf = 1; - } else if (*s == 'N' || *s == 'n') { - /* XXX TODO: There are signaling NaNs and quiet NaNs. */ - s++; if (s == send || (*s != 'A' && *s != 'a')) return 0; - s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; - s++; - sawnan = 1; - } else - return 0; - - if (sawinf) { - numtype &= IS_NUMBER_NEG; /* Keep track of sign */ - numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT; - } else if (sawnan) { - numtype &= IS_NUMBER_NEG; /* Keep track of sign */ - numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT; - } else if (s < send) { - /* we can have an optional exponent part */ - if (*s == 'e' || *s == 'E') { - /* The only flag we keep is sign. Blow away any "it's UV" */ - numtype &= IS_NUMBER_NEG; - numtype |= IS_NUMBER_NOT_INT; - s++; - if (s < send && (*s == '-' || *s == '+')) - s++; - if (s < send && isDIGIT(*s)) { - do { - s++; - } while (s < send && isDIGIT(*s)); - } - else - return 0; - } - } - while (s < send && isSPACE(*s)) - s++; - if (s >= send) - return numtype; - if (len == 10 && memEQ(pv, "0 but true", 10)) { - if (valuep) - *valuep = 0; - return IS_NUMBER_IN_UV; - } - return 0; -} -#endif -#endif - -/* - * The grok_* routines have been modified to use warn() instead of - * Perl_warner(). Also, 'hexdigit' was the former name of PL_hexdigit, - * which is why the stack variable has been renamed to 'xdigit'. - */ - -#ifndef grok_bin -#if defined(NEED_grok_bin) -static UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -static -#else -extern UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -#endif - -#ifdef grok_bin -# undef grok_bin -#endif -#define grok_bin(a,b,c,d) DPPP_(my_grok_bin)(aTHX_ a,b,c,d) -#define Perl_grok_bin DPPP_(my_grok_bin) - -#if defined(NEED_grok_bin) || defined(NEED_grok_bin_GLOBAL) -UV -DPPP_(my_grok_bin)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) -{ - const char *s = start; - STRLEN len = *len_p; - UV value = 0; - NV value_nv = 0; - - const UV max_div_2 = UV_MAX / 2; - bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; - bool overflowed = FALSE; - - if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) { - /* strip off leading b or 0b. - for compatibility silently suffer "b" and "0b" as valid binary - numbers. */ - if (len >= 1) { - if (s[0] == 'b') { - s++; - len--; - } - else if (len >= 2 && s[0] == '0' && s[1] == 'b') { - s+=2; - len-=2; - } - } - } - - for (; len-- && *s; s++) { - char bit = *s; - if (bit == '0' || bit == '1') { - /* Write it in this wonky order with a goto to attempt to get the - compiler to make the common case integer-only loop pretty tight. - With gcc seems to be much straighter code than old scan_bin. */ - redo: - if (!overflowed) { - if (value <= max_div_2) { - value = (value << 1) | (bit - '0'); - continue; - } - /* Bah. We're just overflowed. */ - warn("Integer overflow in binary number"); - overflowed = TRUE; - value_nv = (NV) value; - } - value_nv *= 2.0; - /* If an NV has not enough bits in its mantissa to - * represent a UV this summing of small low-order numbers - * is a waste of time (because the NV cannot preserve - * the low-order bits anyway): we could just remember when - * did we overflow and in the end just multiply value_nv by the - * right amount. */ - value_nv += (NV)(bit - '0'); - continue; - } - if (bit == '_' && len && allow_underscores && (bit = s[1]) - && (bit == '0' || bit == '1')) - { - --len; - ++s; - goto redo; - } - if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) - warn("Illegal binary digit '%c' ignored", *s); - break; - } - - if ( ( overflowed && value_nv > 4294967295.0) -#if UVSIZE > 4 - || (!overflowed && value > 0xffffffff ) -#endif - ) { - warn("Binary number > 0b11111111111111111111111111111111 non-portable"); - } - *len_p = s - start; - if (!overflowed) { - *flags = 0; - return value; - } - *flags = PERL_SCAN_GREATER_THAN_UV_MAX; - if (result) - *result = value_nv; - return UV_MAX; -} -#endif -#endif - -#ifndef grok_hex -#if defined(NEED_grok_hex) -static UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -static -#else -extern UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -#endif - -#ifdef grok_hex -# undef grok_hex -#endif -#define grok_hex(a,b,c,d) DPPP_(my_grok_hex)(aTHX_ a,b,c,d) -#define Perl_grok_hex DPPP_(my_grok_hex) - -#if defined(NEED_grok_hex) || defined(NEED_grok_hex_GLOBAL) -UV -DPPP_(my_grok_hex)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) -{ - const char *s = start; - STRLEN len = *len_p; - UV value = 0; - NV value_nv = 0; - - const UV max_div_16 = UV_MAX / 16; - bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; - bool overflowed = FALSE; - const char *xdigit; - - if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) { - /* strip off leading x or 0x. - for compatibility silently suffer "x" and "0x" as valid hex numbers. - */ - if (len >= 1) { - if (s[0] == 'x') { - s++; - len--; - } - else if (len >= 2 && s[0] == '0' && s[1] == 'x') { - s+=2; - len-=2; - } - } - } - - for (; len-- && *s; s++) { - xdigit = strchr((char *) PL_hexdigit, *s); - if (xdigit) { - /* Write it in this wonky order with a goto to attempt to get the - compiler to make the common case integer-only loop pretty tight. - With gcc seems to be much straighter code than old scan_hex. */ - redo: - if (!overflowed) { - if (value <= max_div_16) { - value = (value << 4) | ((xdigit - PL_hexdigit) & 15); - continue; - } - warn("Integer overflow in hexadecimal number"); - overflowed = TRUE; - value_nv = (NV) value; - } - value_nv *= 16.0; - /* If an NV has not enough bits in its mantissa to - * represent a UV this summing of small low-order numbers - * is a waste of time (because the NV cannot preserve - * the low-order bits anyway): we could just remember when - * did we overflow and in the end just multiply value_nv by the - * right amount of 16-tuples. */ - value_nv += (NV)((xdigit - PL_hexdigit) & 15); - continue; - } - if (*s == '_' && len && allow_underscores && s[1] - && (xdigit = strchr((char *) PL_hexdigit, s[1]))) - { - --len; - ++s; - goto redo; - } - if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) - warn("Illegal hexadecimal digit '%c' ignored", *s); - break; - } - - if ( ( overflowed && value_nv > 4294967295.0) -#if UVSIZE > 4 - || (!overflowed && value > 0xffffffff ) -#endif - ) { - warn("Hexadecimal number > 0xffffffff non-portable"); - } - *len_p = s - start; - if (!overflowed) { - *flags = 0; - return value; - } - *flags = PERL_SCAN_GREATER_THAN_UV_MAX; - if (result) - *result = value_nv; - return UV_MAX; -} -#endif -#endif - -#ifndef grok_oct -#if defined(NEED_grok_oct) -static UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -static -#else -extern UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -#endif - -#ifdef grok_oct -# undef grok_oct -#endif -#define grok_oct(a,b,c,d) DPPP_(my_grok_oct)(aTHX_ a,b,c,d) -#define Perl_grok_oct DPPP_(my_grok_oct) - -#if defined(NEED_grok_oct) || defined(NEED_grok_oct_GLOBAL) -UV -DPPP_(my_grok_oct)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) -{ - const char *s = start; - STRLEN len = *len_p; - UV value = 0; - NV value_nv = 0; - - const UV max_div_8 = UV_MAX / 8; - bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; - bool overflowed = FALSE; - - for (; len-- && *s; s++) { - /* gcc 2.95 optimiser not smart enough to figure that this subtraction - out front allows slicker code. */ - int digit = *s - '0'; - if (digit >= 0 && digit <= 7) { - /* Write it in this wonky order with a goto to attempt to get the - compiler to make the common case integer-only loop pretty tight. - */ - redo: - if (!overflowed) { - if (value <= max_div_8) { - value = (value << 3) | digit; - continue; - } - /* Bah. We're just overflowed. */ - warn("Integer overflow in octal number"); - overflowed = TRUE; - value_nv = (NV) value; - } - value_nv *= 8.0; - /* If an NV has not enough bits in its mantissa to - * represent a UV this summing of small low-order numbers - * is a waste of time (because the NV cannot preserve - * the low-order bits anyway): we could just remember when - * did we overflow and in the end just multiply value_nv by the - * right amount of 8-tuples. */ - value_nv += (NV)digit; - continue; - } - if (digit == ('_' - '0') && len && allow_underscores - && (digit = s[1] - '0') && (digit >= 0 && digit <= 7)) - { - --len; - ++s; - goto redo; - } - /* Allow \octal to work the DWIM way (that is, stop scanning - * as soon as non-octal characters are seen, complain only iff - * someone seems to want to use the digits eight and nine). */ - if (digit == 8 || digit == 9) { - if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) - warn("Illegal octal digit '%c' ignored", *s); - } - break; - } - - if ( ( overflowed && value_nv > 4294967295.0) -#if UVSIZE > 4 - || (!overflowed && value > 0xffffffff ) -#endif - ) { - warn("Octal number > 037777777777 non-portable"); - } - *len_p = s - start; - if (!overflowed) { - *flags = 0; - return value; - } - *flags = PERL_SCAN_GREATER_THAN_UV_MAX; - if (result) - *result = value_nv; - return UV_MAX; -} -#endif -#endif - -#if !defined(my_snprintf) -#if defined(NEED_my_snprintf) -static int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...); -static -#else -extern int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...); -#endif - -#define my_snprintf DPPP_(my_my_snprintf) -#define Perl_my_snprintf DPPP_(my_my_snprintf) - -#if defined(NEED_my_snprintf) || defined(NEED_my_snprintf_GLOBAL) - -int -DPPP_(my_my_snprintf)(char *buffer, const Size_t len, const char *format, ...) -{ - dTHX; - int retval; - va_list ap; - va_start(ap, format); -#ifdef HAS_VSNPRINTF - retval = vsnprintf(buffer, len, format, ap); -#else - retval = vsprintf(buffer, format, ap); -#endif - va_end(ap); - if (retval < 0 || (len > 0 && (Size_t)retval >= len)) - Perl_croak(aTHX_ "panic: my_snprintf buffer overflow"); - return retval; -} - -#endif -#endif - -#if !defined(my_sprintf) -#if defined(NEED_my_sprintf) -static int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...); -static -#else -extern int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...); -#endif - -#define my_sprintf DPPP_(my_my_sprintf) -#define Perl_my_sprintf DPPP_(my_my_sprintf) - -#if defined(NEED_my_sprintf) || defined(NEED_my_sprintf_GLOBAL) - -int -DPPP_(my_my_sprintf)(char *buffer, const char* pat, ...) -{ - va_list args; - va_start(args, pat); - vsprintf(buffer, pat, args); - va_end(args); - return strlen(buffer); -} - -#endif -#endif - -#ifdef NO_XSLOCKS -# ifdef dJMPENV -# define dXCPT dJMPENV; int rEtV = 0 -# define XCPT_TRY_START JMPENV_PUSH(rEtV); if (rEtV == 0) -# define XCPT_TRY_END JMPENV_POP; -# define XCPT_CATCH if (rEtV != 0) -# define XCPT_RETHROW JMPENV_JUMP(rEtV) -# else -# define dXCPT Sigjmp_buf oldTOP; int rEtV = 0 -# define XCPT_TRY_START Copy(top_env, oldTOP, 1, Sigjmp_buf); rEtV = Sigsetjmp(top_env, 1); if (rEtV == 0) -# define XCPT_TRY_END Copy(oldTOP, top_env, 1, Sigjmp_buf); -# define XCPT_CATCH if (rEtV != 0) -# define XCPT_RETHROW Siglongjmp(top_env, rEtV) -# endif -#endif - -#if !defined(my_strlcat) -#if defined(NEED_my_strlcat) -static Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size); -static -#else -extern Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size); -#endif - -#define my_strlcat DPPP_(my_my_strlcat) -#define Perl_my_strlcat DPPP_(my_my_strlcat) - -#if defined(NEED_my_strlcat) || defined(NEED_my_strlcat_GLOBAL) - -Size_t -DPPP_(my_my_strlcat)(char *dst, const char *src, Size_t size) -{ - Size_t used, length, copy; - - used = strlen(dst); - length = strlen(src); - if (size > 0 && used < size - 1) { - copy = (length >= size - used) ? size - used - 1 : length; - memcpy(dst + used, src, copy); - dst[used + copy] = '\0'; - } - return used + length; -} -#endif -#endif - -#if !defined(my_strlcpy) -#if defined(NEED_my_strlcpy) -static Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size); -static -#else -extern Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size); -#endif - -#define my_strlcpy DPPP_(my_my_strlcpy) -#define Perl_my_strlcpy DPPP_(my_my_strlcpy) - -#if defined(NEED_my_strlcpy) || defined(NEED_my_strlcpy_GLOBAL) - -Size_t -DPPP_(my_my_strlcpy)(char *dst, const char *src, Size_t size) -{ - Size_t length, copy; - - length = strlen(src); - if (size > 0) { - copy = (length >= size) ? size - 1 : length; - memcpy(dst, src, copy); - dst[copy] = '\0'; - } - return length; -} - -#endif -#endif -#ifndef PERL_PV_ESCAPE_QUOTE -# define PERL_PV_ESCAPE_QUOTE 0x0001 -#endif - -#ifndef PERL_PV_PRETTY_QUOTE -# define PERL_PV_PRETTY_QUOTE PERL_PV_ESCAPE_QUOTE -#endif - -#ifndef PERL_PV_PRETTY_ELLIPSES -# define PERL_PV_PRETTY_ELLIPSES 0x0002 -#endif - -#ifndef PERL_PV_PRETTY_LTGT -# define PERL_PV_PRETTY_LTGT 0x0004 -#endif - -#ifndef PERL_PV_ESCAPE_FIRSTCHAR -# define PERL_PV_ESCAPE_FIRSTCHAR 0x0008 -#endif - -#ifndef PERL_PV_ESCAPE_UNI -# define PERL_PV_ESCAPE_UNI 0x0100 -#endif - -#ifndef PERL_PV_ESCAPE_UNI_DETECT -# define PERL_PV_ESCAPE_UNI_DETECT 0x0200 -#endif - -#ifndef PERL_PV_ESCAPE_ALL -# define PERL_PV_ESCAPE_ALL 0x1000 -#endif - -#ifndef PERL_PV_ESCAPE_NOBACKSLASH -# define PERL_PV_ESCAPE_NOBACKSLASH 0x2000 -#endif - -#ifndef PERL_PV_ESCAPE_NOCLEAR -# define PERL_PV_ESCAPE_NOCLEAR 0x4000 -#endif - -#ifndef PERL_PV_ESCAPE_RE -# define PERL_PV_ESCAPE_RE 0x8000 -#endif - -#ifndef PERL_PV_PRETTY_NOCLEAR -# define PERL_PV_PRETTY_NOCLEAR PERL_PV_ESCAPE_NOCLEAR -#endif -#ifndef PERL_PV_PRETTY_DUMP -# define PERL_PV_PRETTY_DUMP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_QUOTE -#endif - -#ifndef PERL_PV_PRETTY_REGPROP -# define PERL_PV_PRETTY_REGPROP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_LTGT|PERL_PV_ESCAPE_RE -#endif - -/* Hint: pv_escape - * Note that unicode functionality is only backported to - * those perl versions that support it. For older perl - * versions, the implementation will fall back to bytes. - */ - -#ifndef pv_escape -#if defined(NEED_pv_escape) -static char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags); -static -#else -extern char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags); -#endif - -#ifdef pv_escape -# undef pv_escape -#endif -#define pv_escape(a,b,c,d,e,f) DPPP_(my_pv_escape)(aTHX_ a,b,c,d,e,f) -#define Perl_pv_escape DPPP_(my_pv_escape) - -#if defined(NEED_pv_escape) || defined(NEED_pv_escape_GLOBAL) - -char * -DPPP_(my_pv_escape)(pTHX_ SV *dsv, char const * const str, - const STRLEN count, const STRLEN max, - STRLEN * const escaped, const U32 flags) -{ - const char esc = flags & PERL_PV_ESCAPE_RE ? '%' : '\\'; - const char dq = flags & PERL_PV_ESCAPE_QUOTE ? '"' : esc; - char octbuf[32] = "%123456789ABCDF"; - STRLEN wrote = 0; - STRLEN chsize = 0; - STRLEN readsize = 1; -#if defined(is_utf8_string) && defined(utf8_to_uvchr) - bool isuni = flags & PERL_PV_ESCAPE_UNI ? 1 : 0; -#endif - const char *pv = str; - const char * const end = pv + count; - octbuf[0] = esc; - - if (!(flags & PERL_PV_ESCAPE_NOCLEAR)) - sv_setpvs(dsv, ""); - -#if defined(is_utf8_string) && defined(utf8_to_uvchr) - if ((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count)) - isuni = 1; -#endif - - for (; pv < end && (!max || wrote < max) ; pv += readsize) { - const UV u = -#if defined(is_utf8_string) && defined(utf8_to_uvchr) - isuni ? utf8_to_uvchr((U8*)pv, &readsize) : -#endif - (U8)*pv; - const U8 c = (U8)u & 0xFF; - - if (u > 255 || (flags & PERL_PV_ESCAPE_ALL)) { - if (flags & PERL_PV_ESCAPE_FIRSTCHAR) - chsize = my_snprintf(octbuf, sizeof octbuf, - "%" UVxf, u); - else - chsize = my_snprintf(octbuf, sizeof octbuf, - "%cx{%" UVxf "}", esc, u); - } else if (flags & PERL_PV_ESCAPE_NOBACKSLASH) { - chsize = 1; - } else { - if (c == dq || c == esc || !isPRINT(c)) { - chsize = 2; - switch (c) { - case '\\' : /* fallthrough */ - case '%' : if (c == esc) - octbuf[1] = esc; - else - chsize = 1; - break; - case '\v' : octbuf[1] = 'v'; break; - case '\t' : octbuf[1] = 't'; break; - case '\r' : octbuf[1] = 'r'; break; - case '\n' : octbuf[1] = 'n'; break; - case '\f' : octbuf[1] = 'f'; break; - case '"' : if (dq == '"') - octbuf[1] = '"'; - else - chsize = 1; - break; - default: chsize = my_snprintf(octbuf, sizeof octbuf, - pv < end && isDIGIT((U8)*(pv+readsize)) - ? "%c%03o" : "%c%o", esc, c); - } - } else { - chsize = 1; - } - } - if (max && wrote + chsize > max) { - break; - } else if (chsize > 1) { - sv_catpvn(dsv, octbuf, chsize); - wrote += chsize; - } else { - char tmp[2]; - my_snprintf(tmp, sizeof tmp, "%c", c); - sv_catpvn(dsv, tmp, 1); - wrote++; - } - if (flags & PERL_PV_ESCAPE_FIRSTCHAR) - break; - } - if (escaped != NULL) - *escaped= pv - str; - return SvPVX(dsv); -} - -#endif -#endif - -#ifndef pv_pretty -#if defined(NEED_pv_pretty) -static char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags); -static -#else -extern char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags); -#endif - -#ifdef pv_pretty -# undef pv_pretty -#endif -#define pv_pretty(a,b,c,d,e,f,g) DPPP_(my_pv_pretty)(aTHX_ a,b,c,d,e,f,g) -#define Perl_pv_pretty DPPP_(my_pv_pretty) - -#if defined(NEED_pv_pretty) || defined(NEED_pv_pretty_GLOBAL) - -char * -DPPP_(my_pv_pretty)(pTHX_ SV *dsv, char const * const str, const STRLEN count, - const STRLEN max, char const * const start_color, char const * const end_color, - const U32 flags) -{ - const U8 dq = (flags & PERL_PV_PRETTY_QUOTE) ? '"' : '%'; - STRLEN escaped; - - if (!(flags & PERL_PV_PRETTY_NOCLEAR)) - sv_setpvs(dsv, ""); - - if (dq == '"') - sv_catpvs(dsv, "\""); - else if (flags & PERL_PV_PRETTY_LTGT) - sv_catpvs(dsv, "<"); - - if (start_color != NULL) - sv_catpv(dsv, D_PPP_CONSTPV_ARG(start_color)); - - pv_escape(dsv, str, count, max, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR); - - if (end_color != NULL) - sv_catpv(dsv, D_PPP_CONSTPV_ARG(end_color)); - - if (dq == '"') - sv_catpvs(dsv, "\""); - else if (flags & PERL_PV_PRETTY_LTGT) - sv_catpvs(dsv, ">"); - - if ((flags & PERL_PV_PRETTY_ELLIPSES) && escaped < count) - sv_catpvs(dsv, "..."); - - return SvPVX(dsv); -} - -#endif -#endif - -#ifndef pv_display -#if defined(NEED_pv_display) -static char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim); -static -#else -extern char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim); -#endif - -#ifdef pv_display -# undef pv_display -#endif -#define pv_display(a,b,c,d,e) DPPP_(my_pv_display)(aTHX_ a,b,c,d,e) -#define Perl_pv_display DPPP_(my_pv_display) - -#if defined(NEED_pv_display) || defined(NEED_pv_display_GLOBAL) - -char * -DPPP_(my_pv_display)(pTHX_ SV *dsv, const char *pv, STRLEN cur, STRLEN len, STRLEN pvlim) -{ - pv_pretty(dsv, pv, cur, pvlim, NULL, NULL, PERL_PV_PRETTY_DUMP); - if (len > cur && pv[cur] == '\0') - sv_catpvs(dsv, "\\0"); - return SvPVX(dsv); -} - -#endif -#endif - -#endif /* _P_P_PORTABILITY_H_ */ - -/* End of File ppport.h */ diff --git a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbivport.h b/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbivport.h deleted file mode 100644 index 77dd96b..0000000 --- a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbivport.h +++ /dev/null @@ -1,52 +0,0 @@ -/* dbivport.h - - Provides macros that enable greater portability between DBI versions. - - This file should be *copied* and included in driver distributions - and #included into the source, after #include DBIXS.h - - New driver releases should include an updated copy of dbivport.h - from the most recent DBI release. -*/ - -#ifndef DBI_VPORT_H -#define DBI_VPORT_H - -#ifndef DBIh_SET_ERR_CHAR -/* Emulate DBIh_SET_ERR_CHAR - Only uses the err_i, errstr and state parameters. -*/ -#define DBIh_SET_ERR_CHAR(h, imp_xxh, err_c, err_i, errstr, state, method) \ - sv_setiv(DBIc_ERR(imp_xxh), err_i); \ - (state) ? (void)sv_setpv(DBIc_STATE(imp_xxh), state) : (void)SvOK_off(DBIc_STATE(imp_xxh)); \ - sv_setpv(DBIc_ERRSTR(imp_xxh), errstr) -#endif - -#ifndef DBIcf_Executed -#define DBIcf_Executed 0x080000 -#endif - -#ifndef DBIc_TRACE_LEVEL_MASK -#define DBIc_TRACE_LEVEL_MASK 0x0000000F -#define DBIc_TRACE_FLAGS_MASK 0xFFFFFF00 -#define DBIc_TRACE_SETTINGS(imp) (DBIc_DBISTATE(imp)->debug) -#define DBIc_TRACE_LEVEL(imp) (DBIc_TRACE_SETTINGS(imp) & DBIc_TRACE_LEVEL_MASK) -#define DBIc_TRACE_FLAGS(imp) (DBIc_TRACE_SETTINGS(imp) & DBIc_TRACE_FLAGS_MASK) -/* DBIc_TRACE_MATCHES - true if s1 'matches' s2 (c.f. trace_msg()) - DBIc_TRACE_MATCHES(foo, DBIc_TRACE_SETTINGS(imp)) -*/ -#define DBIc_TRACE_MATCHES(s1, s2) \ - ( ((s1 & DBIc_TRACE_LEVEL_MASK) >= (s2 & DBIc_TRACE_LEVEL_MASK)) \ - || ((s1 & DBIc_TRACE_FLAGS_MASK) & (s2 & DBIc_TRACE_FLAGS_MASK)) ) -/* DBIc_TRACE - true if flags match & DBI level>=flaglevel, or if DBI level>level - DBIc_TRACE(imp, 0, 0, 4) = if level >= 4 - DBIc_TRACE(imp, DBDtf_FOO, 2, 4) = if tracing DBDtf_FOO & level>=2 or level>=4 - DBIc_TRACE(imp, DBDtf_FOO, 2, 0) = as above but never trace just due to level -*/ -#define DBIc_TRACE(imp, flags, flaglevel, level) \ - ( (flags && (DBIc_TRACE_FLAGS(imp) & flags) && (DBIc_TRACE_LEVEL(imp) >= flaglevel)) \ - || (level && DBIc_TRACE_LEVEL(imp) >= level) ) -#endif - - -#endif /* !DBI_VPORT_H */ diff --git a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbixs_rev.h b/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbixs_rev.h deleted file mode 100644 index 83ff5dc..0000000 --- a/dbLifeLog/DBI-1.641/blib/arch/auto/DBI/dbixs_rev.h +++ /dev/null @@ -1,3 +0,0 @@ -/* Fri Jul 13 13:32:02 2012 */ -/* Mixed revision working copy (15349:15353) */ -#define DBIXS_REVISION 15349 diff --git a/dbLifeLog/DBI-1.641/blib/bin/.exists b/dbLifeLog/DBI-1.641/blib/bin/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBI-1.641/blib/lib/.exists b/dbLifeLog/DBI-1.641/blib/lib/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBI-1.641/blib/lib/Bundle/DBI.pm b/dbLifeLog/DBI-1.641/blib/lib/Bundle/DBI.pm deleted file mode 100644 index 08bff92..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/Bundle/DBI.pm +++ /dev/null @@ -1,52 +0,0 @@ -# -*- perl -*- - -package Bundle::DBI; - -use strict; -our $VERSION = "12.008696"; - -1; - -__END__ - -=head1 NAME - -Bundle::DBI - A bundle to install DBI and required modules. - -=head1 SYNOPSIS - - perl -MCPAN -e 'install Bundle::DBI' - -=head1 CONTENTS - -DBI - for to get to know thyself - -DBI::Shell 11.91 - the DBI command line shell - -Storable 2.06 - for DBD::Proxy, DBI::ProxyServer, DBD::Forward - -Net::Daemon 0.37 - for DBD::Proxy and DBI::ProxyServer - -RPC::PlServer 0.2016 - for DBD::Proxy and DBI::ProxyServer - -DBD::Multiplex 1.19 - treat multiple db handles as one - -=head1 DESCRIPTION - -This bundle includes all the modules used by the Perl Database -Interface (DBI) module, created by Tim Bunce. - -A I is a module that simply defines a collection of other -modules. It is used by the L module to automate the fetching, -building and installing of modules from the CPAN ftp archive sites. - -This bundle does not deal with the various database drivers (e.g. -DBD::Informix, DBD::Oracle etc), most of which require software from -sources other than CPAN. You'll need to fetch and build those drivers -yourself. - -=head1 AUTHORS - -Jonathan Leffler, Jochen Wiedmann and Tim Bunce. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/DBM.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/DBM.pm deleted file mode 100644 index a8fe8b9..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/DBM.pm +++ /dev/null @@ -1,1454 +0,0 @@ -####################################################################### -# -# DBD::DBM - a DBI driver for DBM files -# -# Copyright (c) 2004 by Jeff Zucker < jzucker AT cpan.org > -# Copyright (c) 2010-2013 by Jens Rehsack & H.Merijn Brand -# -# All rights reserved. -# -# You may freely distribute and/or modify this module under the terms -# of either the GNU General Public License (GPL) or the Artistic License, -# as specified in the Perl README file. -# -# USERS - see the pod at the bottom of this file -# -# DBD AUTHORS - see the comments in the code -# -####################################################################### -require 5.008; -use strict; - -################# -package DBD::DBM; -################# -use base qw( DBD::File ); -use vars qw($VERSION $ATTRIBUTION $drh $methods_already_installed); -$VERSION = '0.08'; -$ATTRIBUTION = 'DBD::DBM by Jens Rehsack'; - -# no need to have driver() unless you need private methods -# -sub driver ($;$) -{ - my ( $class, $attr ) = @_; - return $drh if ($drh); - - # do the real work in DBD::File - # - $attr->{Attribution} = 'DBD::DBM by Jens Rehsack'; - $drh = $class->SUPER::driver($attr); - - # install private methods - # - # this requires that dbm_ (or foo_) be a registered prefix - # but you can write private methods before official registration - # by hacking the $dbd_prefix_registry in a private copy of DBI.pm - # - unless ( $methods_already_installed++ ) - { - DBD::DBM::st->install_method('dbm_schema'); - } - - return $drh; -} - -sub CLONE -{ - undef $drh; -} - -##################### -package DBD::DBM::dr; -##################### -$DBD::DBM::dr::imp_data_size = 0; -@DBD::DBM::dr::ISA = qw(DBD::File::dr); - -# you could put some :dr private methods here - -# you may need to over-ride some DBD::File::dr methods here -# but you can probably get away with just letting it do the work -# in most cases - -##################### -package DBD::DBM::db; -##################### -$DBD::DBM::db::imp_data_size = 0; -@DBD::DBM::db::ISA = qw(DBD::File::db); - -use Carp qw/carp/; - -sub validate_STORE_attr -{ - my ( $dbh, $attrib, $value ) = @_; - - if ( $attrib eq "dbm_ext" or $attrib eq "dbm_lockfile" ) - { - ( my $newattrib = $attrib ) =~ s/^dbm_/f_/g; - carp "Attribute '$attrib' is depreciated, use '$newattrib' instead" if ($^W); - $attrib = $newattrib; - } - - return $dbh->SUPER::validate_STORE_attr( $attrib, $value ); -} - -sub validate_FETCH_attr -{ - my ( $dbh, $attrib ) = @_; - - if ( $attrib eq "dbm_ext" or $attrib eq "dbm_lockfile" ) - { - ( my $newattrib = $attrib ) =~ s/^dbm_/f_/g; - carp "Attribute '$attrib' is depreciated, use '$newattrib' instead" if ($^W); - $attrib = $newattrib; - } - - return $dbh->SUPER::validate_FETCH_attr($attrib); -} - -sub set_versions -{ - my $this = $_[0]; - $this->{dbm_version} = $DBD::DBM::VERSION; - return $this->SUPER::set_versions(); -} - -sub init_valid_attributes -{ - my $dbh = shift; - - # define valid private attributes - # - # attempts to set non-valid attrs in connect() or - # with $dbh->{attr} will throw errors - # - # the attrs here *must* start with dbm_ or foo_ - # - # see the STORE methods below for how to check these attrs - # - $dbh->{dbm_valid_attrs} = { - dbm_type => 1, # the global DBM type e.g. SDBM_File - dbm_mldbm => 1, # the global MLDBM serializer - dbm_cols => 1, # the global column names - dbm_version => 1, # verbose DBD::DBM version - dbm_store_metadata => 1, # column names, etc. - dbm_berkeley_flags => 1, # for BerkeleyDB - dbm_valid_attrs => 1, # DBD::DBM::db valid attrs - dbm_readonly_attrs => 1, # DBD::DBM::db r/o attrs - dbm_meta => 1, # DBD::DBM public access for f_meta - dbm_tables => 1, # DBD::DBM public access for f_meta - }; - $dbh->{dbm_readonly_attrs} = { - dbm_version => 1, # verbose DBD::DBM version - dbm_valid_attrs => 1, # DBD::DBM::db valid attrs - dbm_readonly_attrs => 1, # DBD::DBM::db r/o attrs - dbm_meta => 1, # DBD::DBM public access for f_meta - }; - - $dbh->{dbm_meta} = "dbm_tables"; - - return $dbh->SUPER::init_valid_attributes(); -} - -sub init_default_attributes -{ - my ( $dbh, $phase ) = @_; - - $dbh->SUPER::init_default_attributes($phase); - $dbh->{f_lockfile} = '.lck'; - - return $dbh; -} - -sub get_dbm_versions -{ - my ( $dbh, $table ) = @_; - $table ||= ''; - - my $meta; - my $class = $dbh->{ImplementorClass}; - $class =~ s/::db$/::Table/; - $table and ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); - $meta or ( $meta = {} and $class->bootstrap_table_meta( $dbh, $meta, $table ) ); - - my $dver; - my $dtype = $meta->{dbm_type}; - eval { - $dver = $meta->{dbm_type}->VERSION(); - - # *) when we're still alive here, everything went ok - no need to check for $@ - $dtype .= " ($dver)"; - }; - if ( $meta->{dbm_mldbm} ) - { - $dtype .= ' + MLDBM'; - eval { - $dver = MLDBM->VERSION(); - $dtype .= " ($dver)"; # (*) - }; - eval { - my $ser_class = "MLDBM::Serializer::" . $meta->{dbm_mldbm}; - my $ser_mod = $ser_class; - $ser_mod =~ s|::|/|g; - $ser_mod .= ".pm"; - require $ser_mod; - $dver = $ser_class->VERSION(); - $dtype .= ' + ' . $ser_class; # (*) - $dver and $dtype .= " ($dver)"; # (*) - }; - } - return sprintf( "%s using %s", $dbh->{dbm_version}, $dtype ); -} - -# you may need to over-ride some DBD::File::db methods here -# but you can probably get away with just letting it do the work -# in most cases - -##################### -package DBD::DBM::st; -##################### -$DBD::DBM::st::imp_data_size = 0; -@DBD::DBM::st::ISA = qw(DBD::File::st); - -sub FETCH -{ - my ( $sth, $attr ) = @_; - - if ( $attr eq "NULLABLE" ) - { - my @colnames = $sth->sql_get_colnames(); - - # XXX only BerkeleyDB fails having NULL values for non-MLDBM databases, - # none accept it for key - but it requires more knowledge between - # queries and tables storage to return fully correct information - $attr eq "NULLABLE" and return [ map { 0 } @colnames ]; - } - - return $sth->SUPER::FETCH($attr); -} # FETCH - -sub dbm_schema -{ - my ( $sth, $tname ) = @_; - return $sth->set_err( $DBI::stderr, 'No table name supplied!' ) unless $tname; - my $tbl_meta = $sth->{Database}->func( $tname, "f_schema", "get_sql_engine_meta" ) - or return $sth->set_err( $sth->{Database}->err(), $sth->{Database}->errstr() ); - return $tbl_meta->{$tname}->{f_schema}; -} -# you could put some :st private methods here - -# you may need to over-ride some DBD::File::st methods here -# but you can probably get away with just letting it do the work -# in most cases - -############################ -package DBD::DBM::Statement; -############################ - -@DBD::DBM::Statement::ISA = qw(DBD::File::Statement); - -######################## -package DBD::DBM::Table; -######################## -use Carp; -use Fcntl; - -@DBD::DBM::Table::ISA = qw(DBD::File::Table); - -my $dirfext = $^O eq 'VMS' ? '.sdbm_dir' : '.dir'; - -my %reset_on_modify = ( - dbm_type => "dbm_tietype", - dbm_mldbm => "dbm_tietype", - ); -__PACKAGE__->register_reset_on_modify( \%reset_on_modify ); - -my %compat_map = ( - ( map { $_ => "dbm_$_" } qw(type mldbm store_metadata) ), - dbm_ext => 'f_ext', - dbm_file => 'f_file', - dbm_lockfile => ' f_lockfile', - ); -__PACKAGE__->register_compat_map( \%compat_map ); - -sub bootstrap_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_; - - $meta->{dbm_type} ||= $dbh->{dbm_type} || 'SDBM_File'; - $meta->{dbm_mldbm} ||= $dbh->{dbm_mldbm} if ( $dbh->{dbm_mldbm} ); - $meta->{dbm_berkeley_flags} ||= $dbh->{dbm_berkeley_flags}; - - defined $meta->{f_ext} - or $meta->{f_ext} = $dbh->{f_ext}; - unless ( defined( $meta->{f_ext} ) ) - { - my $ext; - if ( $meta->{dbm_type} eq 'SDBM_File' or $meta->{dbm_type} eq 'ODBM_File' ) - { - $ext = '.pag/r'; - } - elsif ( $meta->{dbm_type} eq 'NDBM_File' ) - { - # XXX NDBM_File on FreeBSD (and elsewhere?) may actually be Berkeley - # behind the scenes and so create a single .db file. - if ( $^O =~ /bsd/i or lc($^O) eq 'darwin' ) - { - $ext = '.db/r'; - } - elsif ( $^O eq 'SunOS' or $^O eq 'Solaris' or $^O eq 'AIX' ) - { - $ext = '.pag/r'; # here it's implemented like dbm - just a bit improved - } - # else wrapped GDBM - } - defined($ext) and $meta->{f_ext} = $ext; - } - - $self->SUPER::bootstrap_table_meta( $dbh, $meta, $table ); -} - -sub init_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_; - - $meta->{f_dontopen} = 1; - - unless ( defined( $meta->{dbm_tietype} ) ) - { - my $tie_type = $meta->{dbm_type}; - $INC{"$tie_type.pm"} or require "$tie_type.pm"; - $tie_type eq 'BerkeleyDB' and $tie_type = 'BerkeleyDB::Hash'; - - if ( $meta->{dbm_mldbm} ) - { - $INC{"MLDBM.pm"} or require "MLDBM.pm"; - $meta->{dbm_usedb} = $tie_type; - $tie_type = 'MLDBM'; - } - - $meta->{dbm_tietype} = $tie_type; - } - - unless ( defined( $meta->{dbm_store_metadata} ) ) - { - my $store = $dbh->{dbm_store_metadata}; - defined($store) or $store = 1; - $meta->{dbm_store_metadata} = $store; - } - - unless ( defined( $meta->{col_names} ) ) - { - defined( $dbh->{dbm_cols} ) and $meta->{col_names} = $dbh->{dbm_cols}; - } - - $self->SUPER::init_table_meta( $dbh, $meta, $table ); -} - -sub open_data -{ - my ( $className, $meta, $attrs, $flags ) = @_; - $className->SUPER::open_data( $meta, $attrs, $flags ); - - unless ( $flags->{dropMode} ) - { - # TIEING - # - # XXX allow users to pass in a pre-created tied object - # - my @tie_args; - if ( $meta->{dbm_type} eq 'BerkeleyDB' ) - { - my $DB_CREATE = BerkeleyDB::DB_CREATE(); - my $DB_RDONLY = BerkeleyDB::DB_RDONLY(); - my %tie_flags; - if ( my $f = $meta->{dbm_berkeley_flags} ) - { - defined( $f->{DB_CREATE} ) and $DB_CREATE = delete $f->{DB_CREATE}; - defined( $f->{DB_RDONLY} ) and $DB_RDONLY = delete $f->{DB_RDONLY}; - %tie_flags = %$f; - } - my $open_mode = $flags->{lockMode} || $flags->{createMode} ? $DB_CREATE : $DB_RDONLY; - @tie_args = ( - -Filename => $meta->{f_fqbn}, - -Flags => $open_mode, - %tie_flags - ); - } - else - { - my $open_mode = O_RDONLY; - $flags->{lockMode} and $open_mode = O_RDWR; - $flags->{createMode} and $open_mode = O_RDWR | O_CREAT | O_TRUNC; - - @tie_args = ( $meta->{f_fqbn}, $open_mode, 0666 ); - } - - if ( $meta->{dbm_mldbm} ) - { - $MLDBM::UseDB = $meta->{dbm_usedb}; - $MLDBM::Serializer = $meta->{dbm_mldbm}; - } - - $meta->{hash} = {}; - my $tie_class = $meta->{dbm_tietype}; - eval { tie %{ $meta->{hash} }, $tie_class, @tie_args }; - $@ and croak "Cannot tie(\%h $tie_class @tie_args): $@"; - -f $meta->{f_fqfn} or croak( "No such file: '" . $meta->{f_fqfn} . "'" ); - } - - unless ( $flags->{createMode} ) - { - my ( $meta_data, $schema, $col_names ); - if ( $meta->{dbm_store_metadata} ) - { - $meta_data = $col_names = $meta->{hash}->{"_metadata \0"}; - if ( $meta_data and $meta_data =~ m~(.+)~is ) - { - $schema = $col_names = $1; - $schema =~ s~.*(.+).*~$1~is; - $col_names =~ s~.*(.+).*~$1~is; - } - } - $col_names ||= $meta->{col_names} || [ 'k', 'v' ]; - $col_names = [ split /,/, $col_names ] if ( ref $col_names ne 'ARRAY' ); - if ( $meta->{dbm_store_metadata} and not $meta->{hash}->{"_metadata \0"} ) - { - $schema or $schema = ''; - $meta->{hash}->{"_metadata \0"} = - "" - . "$schema" - . "" - . join( ",", @{$col_names} ) - . "" - . ""; - } - - $meta->{schema} = $schema; - $meta->{col_names} = $col_names; - } -} - -# you must define drop -# it is called from execute of a SQL DROP statement -# -sub drop ($$) -{ - my ( $self, $data ) = @_; - my $meta = $self->{meta}; - $meta->{hash} and untie %{ $meta->{hash} }; - $self->SUPER::drop($data); - # XXX extra_files - -f $meta->{f_fqbn} . $dirfext - and $meta->{f_ext} eq '.pag/r' - and unlink( $meta->{f_fqbn} . $dirfext ); - return 1; -} - -# you must define fetch_row, it is called on all fetches; -# it MUST return undef when no rows are left to fetch; -# checking for $ary[0] is specific to hashes so you'll -# probably need some other kind of check for nothing-left. -# as Janis might say: "undef's just another word for -# nothing left to fetch" :-) -# -sub fetch_row ($$) -{ - my ( $self, $data ) = @_; - my $meta = $self->{meta}; - # fetch with %each - # - my @ary = each %{ $meta->{hash} }; - $meta->{dbm_store_metadata} - and $ary[0] - and $ary[0] eq "_metadata \0" - and @ary = each %{ $meta->{hash} }; - - my ( $key, $val ) = @ary; - unless ($key) - { - delete $self->{row}; - return; - } - my @row = ( ref($val) eq 'ARRAY' ) ? ( $key, @$val ) : ( $key, $val ); - $self->{row} = @row ? \@row : undef; - return wantarray ? @row : \@row; -} - -# you must define push_row except insert_new_row and update_specific_row is defined -# it is called on inserts and updates as primitive -# -sub insert_new_row ($$$) -{ - my ( $self, $data, $row_aryref ) = @_; - my $meta = $self->{meta}; - my $ncols = scalar( @{ $meta->{col_names} } ); - my $nitems = scalar( @{$row_aryref} ); - $ncols == $nitems - or croak "You tried to insert $nitems, but table is created with $ncols columns"; - - my $key = shift @$row_aryref; - my $exists; - eval { $exists = exists( $meta->{hash}->{$key} ); }; - $exists and croak "Row with PK '$key' already exists"; - - $meta->{hash}->{$key} = $meta->{dbm_mldbm} ? $row_aryref : $row_aryref->[0]; - - return 1; -} - -# this is where you grab the column names from a CREATE statement -# if you don't need to do that, it must be defined but can be empty -# -sub push_names ($$$) -{ - my ( $self, $data, $row_aryref ) = @_; - my $meta = $self->{meta}; - - # some sanity checks ... - my $ncols = scalar(@$row_aryref); - $ncols < 2 and croak "At least 2 columns are required for DBD::DBM tables ..."; - !$meta->{dbm_mldbm} - and $ncols > 2 - and croak "Without serializing with MLDBM only 2 columns are supported, you give $ncols"; - $meta->{col_names} = $row_aryref; - return unless $meta->{dbm_store_metadata}; - - my $stmt = $data->{sql_stmt}; - my $col_names = join( ',', @{$row_aryref} ); - my $schema = $data->{Database}->{Statement}; - $schema =~ s/^[^\(]+\((.+)\)$/$1/s; - $schema = $stmt->schema_str() if ( $stmt->can('schema_str') ); - $meta->{hash}->{"_metadata \0"} = - "" - . "$schema" - . "$col_names" - . ""; -} - -# fetch_one_row, delete_one_row, update_one_row -# are optimized for hash-style lookup without looping; -# if you don't need them, omit them, they're optional -# but, in that case you may need to define -# truncate() and seek(), see below -# -sub fetch_one_row ($$;$) -{ - my ( $self, $key_only, $key ) = @_; - my $meta = $self->{meta}; - $key_only and return $meta->{col_names}->[0]; - exists $meta->{hash}->{$key} or return; - my $val = $meta->{hash}->{$key}; - $val = ( ref($val) eq 'ARRAY' ) ? $val : [$val]; - my $row = [ $key, @$val ]; - return wantarray ? @{$row} : $row; -} - -sub delete_one_row ($$$) -{ - my ( $self, $data, $aryref ) = @_; - my $meta = $self->{meta}; - delete $meta->{hash}->{ $aryref->[0] }; -} - -sub update_one_row ($$$) -{ - my ( $self, $data, $aryref ) = @_; - my $meta = $self->{meta}; - my $key = shift @$aryref; - defined $key or return; - my $row = ( ref($aryref) eq 'ARRAY' ) ? $aryref : [$aryref]; - $meta->{hash}->{$key} = $meta->{dbm_mldbm} ? $row : $row->[0]; -} - -sub update_specific_row ($$$$) -{ - my ( $self, $data, $aryref, $origary ) = @_; - my $meta = $self->{meta}; - my $key = shift @$origary; - my $newkey = shift @$aryref; - return unless ( defined $key ); - $key eq $newkey or delete $meta->{hash}->{$key}; - my $row = ( ref($aryref) eq 'ARRAY' ) ? $aryref : [$aryref]; - $meta->{hash}->{$newkey} = $meta->{dbm_mldbm} ? $row : $row->[0]; -} - -# you may not need to explicitly DESTROY the ::Table -# put cleanup code to run when the execute is done -# -sub DESTROY ($) -{ - my $self = shift; - my $meta = $self->{meta}; - $meta->{hash} and untie %{ $meta->{hash} }; - - $self->SUPER::DESTROY(); -} - -# truncate() and seek() must be defined to satisfy DBI::SQL::Nano -# *IF* you define the *_one_row methods above, truncate() and -# seek() can be empty or you can use them without actually -# truncating or seeking anything but if you don't define the -# *_one_row methods, you may need to define these - -# if you need to do something after a series of -# deletes or updates, you can put it in truncate() -# which is called at the end of executing -# -sub truncate ($$) -{ - # my ( $self, $data ) = @_; - return 1; -} - -# seek() is only needed if you use IO::File -# though it could be used for other non-file operations -# that you need to do before "writes" or truncate() -# -sub seek ($$$$) -{ - # my ( $self, $data, $pos, $whence ) = @_; - return 1; -} - -# Th, th, th, that's all folks! See DBD::File and DBD::CSV for other -# examples of creating pure perl DBDs. I hope this helped. -# Now it's time to go forth and create your own DBD! -# Remember to check in with dbi-dev@perl.org before you get too far. -# We may be able to make suggestions or point you to other related -# projects. - -1; -__END__ - -=pod - -=head1 NAME - -DBD::DBM - a DBI driver for DBM & MLDBM files - -=head1 SYNOPSIS - - use DBI; - $dbh = DBI->connect('dbi:DBM:'); # defaults to SDBM_File - $dbh = DBI->connect('DBI:DBM(RaiseError=1):'); # defaults to SDBM_File - $dbh = DBI->connect('dbi:DBM:dbm_type=DB_File'); # defaults to DB_File - $dbh = DBI->connect('dbi:DBM:dbm_mldbm=Storable'); # MLDBM with SDBM_File - - # or - $dbh = DBI->connect('dbi:DBM:', undef, undef); - $dbh = DBI->connect('dbi:DBM:', undef, undef, { - f_ext => '.db/r', - f_dir => '/path/to/dbfiles/', - f_lockfile => '.lck', - dbm_type => 'BerkeleyDB', - dbm_mldbm => 'FreezeThaw', - dbm_store_metadata => 1, - dbm_berkeley_flags => { - '-Cachesize' => 1000, # set a ::Hash flag - }, - }); - -and other variations on connect() as shown in the L docs, -L and L -shown below. - -Use standard DBI prepare, execute, fetch, placeholders, etc., -see L for an example. - -=head1 DESCRIPTION - -DBD::DBM is a database management system that works right out of the -box. If you have a standard installation of Perl and DBI you can -begin creating, accessing, and modifying simple database tables -without any further modules. You can add other modules (e.g., -SQL::Statement, DB_File etc) for improved functionality. - -The module uses a DBM file storage layer. DBM file storage is common on -many platforms and files can be created with it in many programming -languages using different APIs. That means, in addition to creating -files with DBI/SQL, you can also use DBI/SQL to access and modify files -created by other DBM modules and programs and vice versa. B that -in those cases it might be necessary to use a common subset of the -provided features. - -DBM files are stored in binary format optimized for quick retrieval -when using a key field. That optimization can be used advantageously -to make DBD::DBM SQL operations that use key fields very fast. There -are several different "flavors" of DBM which use different storage -formats supported by perl modules such as SDBM_File and MLDBM. This -module supports all of the flavors that perl supports and, when used -with MLDBM, supports tables with any number of columns and insertion -of Perl objects into tables. - -DBD::DBM has been tested with the following DBM types: SDBM_File, -NDBM_File, ODBM_File, GDBM_File, DB_File, BerkeleyDB. Each type was -tested both with and without MLDBM and with the Data::Dumper, -Storable, FreezeThaw, YAML and JSON serializers using the DBI::SQL::Nano -or the SQL::Statement engines. - -=head1 QUICK START - -DBD::DBM operates like all other DBD drivers - it's basic syntax and -operation is specified by DBI. If you're not familiar with DBI, you should -start by reading L and the documents it points to and then come back -and read this file. If you are familiar with DBI, you already know most of -what you need to know to operate this module. Just jump in and create a -test script something like the one shown below. - -You should be aware that there are several options for the SQL engine -underlying DBD::DBM, see L. There are also many -options for DBM support, see especially the section on L. - -But here's a sample to get you started. - - use DBI; - my $dbh = DBI->connect('dbi:DBM:'); - $dbh->{RaiseError} = 1; - for my $sql( split /;\n+/," - CREATE TABLE user ( user_name TEXT, phone TEXT ); - INSERT INTO user VALUES ('Fred Bloggs','233-7777'); - INSERT INTO user VALUES ('Sanjay Patel','777-3333'); - INSERT INTO user VALUES ('Junk','xxx-xxxx'); - DELETE FROM user WHERE user_name = 'Junk'; - UPDATE user SET phone = '999-4444' WHERE user_name = 'Sanjay Patel'; - SELECT * FROM user - "){ - my $sth = $dbh->prepare($sql); - $sth->execute; - $sth->dump_results if $sth->{NUM_OF_FIELDS}; - } - $dbh->disconnect; - -=head1 USAGE - -This section will explain some usage cases in more detail. To get an -overview about the available attributes, see L. - -=head2 Specifying Files and Directories - -DBD::DBM will automatically supply an appropriate file extension for the -type of DBM you are using. For example, if you use SDBM_File, a table -called "fruit" will be stored in two files called "fruit.pag" and -"fruit.dir". You should B specify the file extensions in your SQL -statements. - -DBD::DBM recognizes following default extensions for following types: - -=over 4 - -=item .pag/r - -Chosen for dbm_type C<< SDBM_File >>, C<< ODBM_File >> and C<< NDBM_File >> -when an implementation is detected which wraps C<< -ldbm >> for -C<< NDBM_File >> (e.g. Solaris, AIX, ...). - -For those types, the C<< .dir >> extension is recognized, too (for being -deleted when dropping a table). - -=item .db/r - -Chosen for dbm_type C<< NDBM_File >> when an implementation is detected -which wraps BerkeleyDB 1.x for C<< NDBM_File >> (typically BSD's, Darwin). - -=back - -C<< GDBM_File >>, C<< DB_File >> and C<< BerkeleyDB >> don't usually -use a file extension. - -If your DBM type uses an extension other than one of the recognized -types of extensions, you should set the I attribute to the -extension B file a bug report as described in DBI with the name -of the implementation and extension so we can add it to DBD::DBM. -Thanks in advance for that :-). - - $dbh = DBI->connect('dbi:DBM:f_ext=.db'); # .db extension is used - $dbh = DBI->connect('dbi:DBM:f_ext='); # no extension is used - - # or - $dbh->{f_ext}='.db'; # global setting - $dbh->{f_meta}->{'qux'}->{f_ext}='.db'; # setting for table 'qux' - -By default files are assumed to be in the current working directory. -To use other directories specify the I attribute in either the -connect string or by setting the database handle attribute. - -For example, this will look for the file /foo/bar/fruit (or -/foo/bar/fruit.pag for DBM types that use that extension) - - my $dbh = DBI->connect('dbi:DBM:f_dir=/foo/bar'); - # and this will too: - my $dbh = DBI->connect('dbi:DBM:'); - $dbh->{f_dir} = '/foo/bar'; - # but this is recommended - my $dbh = DBI->connect('dbi:DBM:', undef, undef, { f_dir => '/foo/bar' } ); - - # now you can do - my $ary = $dbh->selectall_arrayref(q{ SELECT x FROM fruit }); - -You can also use delimited identifiers to specify paths directly in SQL -statements. This looks in the same place as the two examples above but -without setting I: - - my $dbh = DBI->connect('dbi:DBM:'); - my $ary = $dbh->selectall_arrayref(q{ - SELECT x FROM "/foo/bar/fruit" - }); - -You can also tell DBD::DBM to use a specified path for a specific table: - - $dbh->{dbm_tables}->{f}->{file} = q(/foo/bar/fruit); - -Please be aware that you cannot specify this during connection. - -If you have SQL::Statement installed, you can use table aliases: - - my $dbh = DBI->connect('dbi:DBM:'); - my $ary = $dbh->selectall_arrayref(q{ - SELECT f.x FROM "/foo/bar/fruit" AS f - }); - -See the L for using DROP on tables. - -=head2 Table locking and flock() - -Table locking is accomplished using a lockfile which has the same -basename as the table's file but with the file extension '.lck' (or a -lockfile extension that you supply, see below). This lock file is -created with the table during a CREATE and removed during a DROP. -Every time the table itself is opened, the lockfile is flocked(). For -SELECT, this is a shared lock. For all other operations, it is an -exclusive lock (except when you specify something different using the -I attribute). - -Since the locking depends on flock(), it only works on operating -systems that support flock(). In cases where flock() is not -implemented, DBD::DBM will simply behave as if the flock() had -occurred although no actual locking will happen. Read the -documentation for flock() for more information. - -Even on those systems that do support flock(), locking is only -advisory - as is always the case with flock(). This means that if -another program tries to access the table file while DBD::DBM has the -table locked, that other program will *succeed* at opening unless -it is also using flock on the '.lck' file. As a result DBD::DBM's -locking only really applies to other programs using DBD::DBM or other -program written to cooperate with DBD::DBM locking. - -=head2 Specifying the DBM type - -Each "flavor" of DBM stores its files in a different format and has -different capabilities and limitations. See L for a -comparison of DBM types. - -By default, DBD::DBM uses the C<< SDBM_File >> type of storage since -C<< SDBM_File >> comes with Perl itself. If you have other types of -DBM storage available, you can use any of them with DBD::DBM. It is -strongly recommended to use at least C<< DB_File >>, because C<< -SDBM_File >> has quirks and limitations and C<< ODBM_file >>, C<< -NDBM_File >> and C<< GDBM_File >> are not always available. - -You can specify the DBM type using the I attribute which can -be set in the connection string or with C<< $dbh->{dbm_type} >> and -C<< $dbh->{f_meta}->{$table_name}->{type} >> for per-table settings in -cases where a single script is accessing more than one kind of DBM -file. - -In the connection string, just set C<< dbm_type=TYPENAME >> where -C<< TYPENAME >> is any DBM type such as GDBM_File, DB_File, etc. Do I -use MLDBM as your I as that is set differently, see below. - - my $dbh=DBI->connect('dbi:DBM:'); # uses the default SDBM_File - my $dbh=DBI->connect('dbi:DBM:dbm_type=GDBM_File'); # uses the GDBM_File - - # You can also use $dbh->{dbm_type} to set the DBM type for the connection: - $dbh->{dbm_type} = 'DB_File'; # set the global DBM type - print $dbh->{dbm_type}; # display the global DBM type - -If you have several tables in your script that use different DBM -types, you can use the $dbh->{dbm_tables} hash to store different -settings for the various tables. You can even use this to perform -joins on files that have completely different storage mechanisms. - - # sets global default of GDBM_File - my $dbh->('dbi:DBM:type=GDBM_File'); - - # overrides the global setting, but only for the tables called - # I and I - my $dbh->{f_meta}->{foo}->{dbm_type} = 'DB_File'; - my $dbh->{f_meta}->{bar}->{dbm_type} = 'BerkeleyDB'; - - # prints the dbm_type for the table "foo" - print $dbh->{f_meta}->{foo}->{dbm_type}; - -B that you must change the I of a table before you access -it for first time. - -=head2 Adding multi-column support with MLDBM - -Most of the DBM types only support two columns and even if it would -support more, DBD::DBM would only use two. However a CPAN module -called MLDBM overcomes this limitation by allowing more than two -columns. MLDBM does this by serializing the data - basically it puts -a reference to an array into the second column. It can also put almost -any kind of Perl object or even B into columns. - -If you want more than two columns, you B install MLDBM. It's available -for many platforms and is easy to install. - -MLDBM is by default distributed with three serializers - Data::Dumper, -Storable, and FreezeThaw. Data::Dumper is the default and Storable is the -fastest. MLDBM can also make use of user-defined serialization methods or -other serialization modules (e.g. L or -L. You select the serializer using the -I attribute. - -Some examples: - - $dbh=DBI->connect('dbi:DBM:dbm_mldbm=Storable'); # use MLDBM with Storable - $dbh=DBI->connect( - 'dbi:DBM:dbm_mldbm=MySerializer' # use MLDBM with a user defined module - ); - $dbh=DBI->connect('dbi::dbm:', undef, - undef, { dbm_mldbm => 'YAML' }); # use 3rd party serializer - $dbh->{dbm_mldbm} = 'YAML'; # same as above - print $dbh->{dbm_mldbm} # show the MLDBM serializer - $dbh->{f_meta}->{foo}->{dbm_mldbm}='Data::Dumper'; # set Data::Dumper for table "foo" - print $dbh->{f_meta}->{foo}->{mldbm}; # show serializer for table "foo" - -MLDBM works on top of other DBM modules so you can also set a DBM type -along with setting dbm_mldbm. The examples above would default to using -SDBM_File with MLDBM. If you wanted GDBM_File instead, here's how: - - # uses DB_File with MLDBM and Storable - $dbh = DBI->connect('dbi:DBM:', undef, undef, { - dbm_type => 'DB_File', - dbm_mldbm => 'Storable', - }); - -SDBM_File, the default I is quite limited, so if you are going to -use MLDBM, you should probably use a different type, see L. - -See below for some L about MLDBM. - -=head2 Support for Berkeley DB - -The Berkeley DB storage type is supported through two different Perl -modules - DB_File (which supports only features in old versions of Berkeley -DB) and BerkeleyDB (which supports all versions). DBD::DBM supports -specifying either "DB_File" or "BerkeleyDB" as a I, with or -without MLDBM support. - -The "BerkeleyDB" dbm_type is experimental and it's interface is likely to -change. It currently defaults to BerkeleyDB::Hash and does not currently -support ::Btree or ::Recno. - -With BerkeleyDB, you can specify initialization flags by setting them in -your script like this: - - use BerkeleyDB; - my $env = new BerkeleyDB::Env -Home => $dir; # and/or other Env flags - $dbh = DBI->connect('dbi:DBM:', undef, undef, { - dbm_type => 'BerkeleyDB', - dbm_mldbm => 'Storable', - dbm_berkeley_flags => { - 'DB_CREATE' => DB_CREATE, # pass in constants - 'DB_RDONLY' => DB_RDONLY, # pass in constants - '-Cachesize' => 1000, # set a ::Hash flag - '-Env' => $env, # pass in an environment - }, - }); - -Do I set the -Flags or -Filename flags as those are determined and -overwritten by the SQL (e.g. -Flags => DB_RDONLY is set automatically -when you issue a SELECT statement). - -Time has not permitted us to provide support in this release of DBD::DBM -for further Berkeley DB features such as transactions, concurrency, -locking, etc. We will be working on these in the future and would value -suggestions, patches, etc. - -See L and L for further details. - -=head2 Optimizing the use of key fields - -Most "flavors" of DBM have only two physical columns (but can contain -multiple logical columns as explained above in -L). They work similarly to a -Perl hash with the first column serving as the key. Like a Perl hash, DBM -files permit you to do quick lookups by specifying the key and thus avoid -looping through all records (supported by DBI::SQL::Nano only). Also like -a Perl hash, the keys must be unique. It is impossible to create two -records with the same key. To put this more simply and in SQL terms, -the key column functions as the I or UNIQUE INDEX. - -In DBD::DBM, you can take advantage of the speed of keyed lookups by using -DBI::SQL::Nano and a WHERE clause with a single equal comparison on the key -field. For example, the following SQL statements are optimized for keyed -lookup: - - CREATE TABLE user ( user_name TEXT, phone TEXT); - INSERT INTO user VALUES ('Fred Bloggs','233-7777'); - # ... many more inserts - SELECT phone FROM user WHERE user_name='Fred Bloggs'; - -The "user_name" column is the key column since it is the first -column. The SELECT statement uses the key column in a single equal -comparison - "user_name='Fred Bloggs'" - so the search will find it -very quickly without having to loop through all the names which were -inserted into the table. - -In contrast, these searches on the same table are not optimized: - - 1. SELECT phone FROM user WHERE user_name < 'Fred'; - 2. SELECT user_name FROM user WHERE phone = '233-7777'; - -In #1, the operation uses a less-than (<) comparison rather than an equals -comparison, so it will not be optimized for key searching. In #2, the key -field "user_name" is not specified in the WHERE clause, and therefore the -search will need to loop through all rows to find the requested row(s). - -B that the underlying DBM storage needs to loop over all I -pairs when the optimized fetch is used. SQL::Statement has a massively -improved where clause evaluation which costs around 15% of the evaluation -in DBI::SQL::Nano - combined with the loop in the DBM storage the speed -improvement isn't so impressive. - -Even if lookups are faster by around 50%, DBI::SQL::Nano and -SQL::Statement can benefit from the key field optimizations on -updating and deleting rows - and here the improved where clause -evaluation of SQL::Statement might beat DBI::SQL::Nano every time the -where clause contains not only the key field (or more than one). - -=head2 Supported SQL syntax - -DBD::DBM uses a subset of SQL. The robustness of that subset depends on -what other modules you have installed. Both options support basic SQL -operations including CREATE TABLE, DROP TABLE, INSERT, DELETE, UPDATE, and -SELECT. - -B
for gotchas and -warnings about the use of flock(). - -=head1 BUGS AND LIMITATIONS - -This module uses hash interfaces of two column file databases. While -none of supported SQL engines have support for indices, the following -statements really do the same (even if they mean something completely -different) for each dbm type which lacks C support: - - $sth->do( "insert into foo values (1, 'hello')" ); - - # this statement does ... - $sth->do( "update foo set v='world' where k=1" ); - # ... the same as this statement - $sth->do( "insert into foo values (1, 'world')" ); - -This is considered to be a bug and might change in a future release. - -Known affected dbm types are C and C. We highly -recommended you use a more modern dbm type such as C. - -=head1 GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS - -If you need help installing or using DBD::DBM, please write to the DBI -users mailing list at dbi-users@perl.org or to the -comp.lang.perl.modules newsgroup on usenet. I cannot always answer -every question quickly but there are many on the mailing list or in -the newsgroup who can. - -DBD developers for DBD's which rely on DBD::File or DBD::DBM or use -one of them as an example are suggested to join the DBI developers -mailing list at dbi-dev@perl.org and strongly encouraged to join our -IRC channel at L. - -If you have suggestions, ideas for improvements, or bugs to report, please -report a bug as described in DBI. Do not mail any of the authors directly, -you might not get an answer. - -When reporting bugs, please send the output of $dbh->dbm_versions($table) -for a table that exhibits the bug and as small a sample as you can make of -the code that produces the bug. And of course, patches are welcome, too -:-). - -If you need enhancements quickly, you can get commercial support as -described at L or you can contact Jens Rehsack -at rehsack@cpan.org for commercial support in Germany. - -Please don't bother Jochen Wiedmann or Jeff Zucker for support - they -handed over further maintenance to H.Merijn Brand and Jens Rehsack. - -=head1 ACKNOWLEDGEMENTS - -Many, many thanks to Tim Bunce for prodding me to write this, and for -copious, wise, and patient suggestions all along the way. (Jeff Zucker) - -I send my thanks and acknowledgements to H.Merijn Brand for his -initial refactoring of DBD::File and his strong and ongoing support of -SQL::Statement. Without him, the current progress would never have -been made. And I have to name Martin J. Evans for each laugh (and -correction) of all those funny word creations I (as non-native -speaker) made to the documentation. And - of course - I have to thank -all those unnamed contributors and testers from the Perl -community. (Jens Rehsack) - -=head1 AUTHOR AND COPYRIGHT - -This module is written by Jeff Zucker < jzucker AT cpan.org >, who also -maintained it till 2007. After that, in 2010, Jens Rehsack & H.Merijn Brand -took over maintenance. - - Copyright (c) 2004 by Jeff Zucker, all rights reserved. - Copyright (c) 2010-2013 by Jens Rehsack & H.Merijn Brand, all rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=head1 SEE ALSO - -L, -L, L, -L, L, L, -L, L, L - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/ExampleP.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/ExampleP.pm deleted file mode 100644 index ed5414f..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/ExampleP.pm +++ /dev/null @@ -1,435 +0,0 @@ -{ - package DBD::ExampleP; - - use strict; - use Symbol; - - use DBI qw(:sql_types); - - require File::Spec; - - our (@EXPORT,$VERSION,@statnames,%statnames,@stattypes,%stattypes, - @statprec,%statprec,$drh,); - - @EXPORT = qw(); # Do NOT @EXPORT anything. - $VERSION = "12.014311"; - -# $Id: ExampleP.pm 14310 2010-08-02 06:35:25Z Jens $ -# -# Copyright (c) 1994,1997,1998 Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - @statnames = qw(dev ino mode nlink - uid gid rdev size - atime mtime ctime - blksize blocks name); - @statnames{@statnames} = (0 .. @statnames-1); - - @stattypes = (SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, - SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, - SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, - SQL_INTEGER, SQL_INTEGER, SQL_VARCHAR); - @stattypes{@statnames} = @stattypes; - @statprec = ((10) x (@statnames-1), 1024); - @statprec{@statnames} = @statprec; - die unless @statnames == @stattypes; - die unless @statprec == @stattypes; - - $drh = undef; # holds driver handle once initialised - #$gensym = "SYM000"; # used by st::execute() for filehandles - - sub driver{ - return $drh if $drh; - my($class, $attr) = @_; - $class .= "::dr"; - ($drh) = DBI::_new_drh($class, { - 'Name' => 'ExampleP', - 'Version' => $VERSION, - 'Attribution' => 'DBD Example Perl stub by Tim Bunce', - }, ['example implementors private data '.__PACKAGE__]); - $drh; - } - - sub CLONE { - undef $drh; - } -} - - -{ package DBD::ExampleP::dr; # ====== DRIVER ====== - $imp_data_size = 0; - use strict; - - sub connect { # normally overridden, but a handy default - my($drh, $dbname, $user, $auth)= @_; - my ($outer, $dbh) = DBI::_new_dbh($drh, { - Name => $dbname, - examplep_private_dbh_attrib => 42, # an example, for testing - }); - $dbh->{examplep_get_info} = { - 29 => '"', # SQL_IDENTIFIER_QUOTE_CHAR - 41 => '.', # SQL_CATALOG_NAME_SEPARATOR - 114 => 1, # SQL_CATALOG_LOCATION - }; - #$dbh->{Name} = $dbname; - $dbh->STORE('Active', 1); - return $outer; - } - - sub data_sources { - return ("dbi:ExampleP:dir=."); # possibly usefully meaningless - } - -} - - -{ package DBD::ExampleP::db; # ====== DATABASE ====== - $imp_data_size = 0; - use strict; - - sub prepare { - my($dbh, $statement)= @_; - my @fields; - my($fields, $dir) = $statement =~ m/^\s*select\s+(.*?)\s+from\s+(\S*)/i; - - if (defined $fields and defined $dir) { - @fields = ($fields eq '*') - ? keys %DBD::ExampleP::statnames - : split(/\s*,\s*/, $fields); - } - else { - return $dbh->set_err($DBI::stderr, "Syntax error in select statement (\"$statement\")") - unless $statement =~ m/^\s*set\s+/; - # the SET syntax is just a hack so the ExampleP driver can - # be used to test non-select statements. - # Now we have DBI::DBM etc., ExampleP should be deprecated - } - - my ($outer, $sth) = DBI::_new_sth($dbh, { - 'Statement' => $statement, - examplep_private_sth_attrib => 24, # an example, for testing - }, ['example implementors private data '.__PACKAGE__]); - - my @bad = map { - defined $DBD::ExampleP::statnames{$_} ? () : $_ - } @fields; - return $dbh->set_err($DBI::stderr, "Unknown field names: @bad") - if @bad; - - $outer->STORE('NUM_OF_FIELDS' => scalar(@fields)); - - $sth->{examplep_ex_dir} = $dir if defined($dir) && $dir !~ /\?/; - $outer->STORE('NUM_OF_PARAMS' => ($dir) ? $dir =~ tr/?/?/ : 0); - - if (@fields) { - $outer->STORE('NAME' => \@fields); - $outer->STORE('NULLABLE' => [ (0) x @fields ]); - $outer->STORE('SCALE' => [ (0) x @fields ]); - } - - $outer; - } - - - sub table_info { - my $dbh = shift; - my ($catalog, $schema, $table, $type) = @_; - - my @types = split(/["']*,["']/, $type || 'TABLE'); - my %types = map { $_=>$_ } @types; - - # Return a list of all subdirectories - my $dh = Symbol::gensym(); # "DBD::ExampleP::".++$DBD::ExampleP::gensym; - my $dir = $catalog || File::Spec->curdir(); - my @list; - if ($types{VIEW}) { # for use by test harness - push @list, [ undef, "schema", "table", 'VIEW', undef ]; - push @list, [ undef, "sch-ema", "table", 'VIEW', undef ]; - push @list, [ undef, "schema", "ta-ble", 'VIEW', undef ]; - push @list, [ undef, "sch ema", "table", 'VIEW', undef ]; - push @list, [ undef, "schema", "ta ble", 'VIEW', undef ]; - } - if ($types{TABLE}) { - no strict 'refs'; - opendir($dh, $dir) - or return $dbh->set_err(int($!), "Failed to open directory $dir: $!"); - while (defined(my $item = readdir($dh))) { - if ($^O eq 'VMS') { - # if on VMS then avoid warnings from catdir if you use a file - # (not a dir) as the item below - next if $item !~ /\.dir$/oi; - } - my $file = File::Spec->catdir($dir,$item); - next unless -d $file; - my($dev, $ino, $mode, $nlink, $uid) = lstat($file); - my $pwnam = undef; # eval { scalar(getpwnam($uid)) } || $uid; - push @list, [ $dir, $pwnam, $item, 'TABLE', undef ]; - } - close($dh); - } - # We would like to simply do a DBI->connect() here. However, - # this is wrong if we are in a subclass like DBI::ProxyServer. - $dbh->{'dbd_sponge_dbh'} ||= DBI->connect("DBI:Sponge:", '','') - or return $dbh->set_err($DBI::err, - "Failed to connect to DBI::Sponge: $DBI::errstr"); - - my $attr = { - 'rows' => \@list, - 'NUM_OF_FIELDS' => 5, - 'NAME' => ['TABLE_CAT', 'TABLE_SCHEM', 'TABLE_NAME', - 'TABLE_TYPE', 'REMARKS'], - 'TYPE' => [DBI::SQL_VARCHAR(), DBI::SQL_VARCHAR(), - DBI::SQL_VARCHAR(), DBI::SQL_VARCHAR(), DBI::SQL_VARCHAR() ], - 'NULLABLE' => [1, 1, 1, 1, 1] - }; - my $sdbh = $dbh->{'dbd_sponge_dbh'}; - my $sth = $sdbh->prepare("SHOW TABLES FROM $dir", $attr) - or return $dbh->set_err($sdbh->err(), $sdbh->errstr()); - $sth; - } - - - sub type_info_all { - my ($dbh) = @_; - my $ti = [ - { TYPE_NAME => 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE=> 9, - FIXED_PREC_SCALE=> 10, - AUTO_UNIQUE_VALUE => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - }, - [ 'VARCHAR', DBI::SQL_VARCHAR, 1024, "'","'", undef, 0, 1, 1, 0, 0,0,undef,0,0 ], - [ 'INTEGER', DBI::SQL_INTEGER, 10, "","", undef, 0, 0, 1, 0, 0,0,undef,0,0 ], - ]; - return $ti; - } - - - sub ping { - (shift->FETCH('Active')) ? 2 : 0; # the value 2 is checked for by t/80proxy.t - } - - - sub disconnect { - shift->STORE(Active => 0); - return 1; - } - - - sub get_info { - my ($dbh, $info_type) = @_; - return $dbh->{examplep_get_info}->{$info_type}; - } - - - sub FETCH { - my ($dbh, $attrib) = @_; - # In reality this would interrogate the database engine to - # either return dynamic values that cannot be precomputed - # or fetch and cache attribute values too expensive to prefetch. - # else pass up to DBI to handle - return $INC{"DBD/ExampleP.pm"} if $attrib eq 'example_driver_path'; - return $dbh->SUPER::FETCH($attrib); - } - - - sub STORE { - my ($dbh, $attrib, $value) = @_; - # store only known attributes else pass up to DBI to handle - if ($attrib eq 'examplep_set_err') { - # a fake attribute to enable a test case where STORE issues a warning - $dbh->set_err($value, $value); - return; - } - if ($attrib eq 'AutoCommit') { - # convert AutoCommit values to magic ones to let DBI - # know that the driver has 'handled' the AutoCommit attribute - $value = ($value) ? -901 : -900; - } - return $dbh->{$attrib} = $value if $attrib =~ /^examplep_/; - return $dbh->SUPER::STORE($attrib, $value); - } - - sub DESTROY { - my $dbh = shift; - $dbh->disconnect if $dbh->FETCH('Active'); - undef - } - - - # This is an example to demonstrate the use of driver-specific - # methods via $dbh->func(). - # Use it as follows: - # my @tables = $dbh->func($re, 'examplep_tables'); - # - # Returns all the tables that match the regular expression $re. - sub examplep_tables { - my $dbh = shift; my $re = shift; - grep { $_ =~ /$re/ } $dbh->tables(); - } - - sub parse_trace_flag { - my ($h, $name) = @_; - return 0x01000000 if $name eq 'foo'; - return 0x02000000 if $name eq 'bar'; - return 0x04000000 if $name eq 'baz'; - return 0x08000000 if $name eq 'boo'; - return 0x10000000 if $name eq 'bop'; - return $h->SUPER::parse_trace_flag($name); - } - - sub private_attribute_info { - return { example_driver_path => undef }; - } -} - - -{ package DBD::ExampleP::st; # ====== STATEMENT ====== - $imp_data_size = 0; - use strict; no strict 'refs'; # cause problems with filehandles - - sub bind_param { - my($sth, $param, $value, $attribs) = @_; - $sth->{'dbd_param'}->[$param-1] = $value; - return 1; - } - - - sub execute { - my($sth, @dir) = @_; - my $dir; - - if (@dir) { - $sth->bind_param($_, $dir[$_-1]) or return - foreach (1..@dir); - } - - my $dbd_param = $sth->{'dbd_param'} || []; - return $sth->set_err(2, @$dbd_param." values bound when $sth->{NUM_OF_PARAMS} expected") - unless @$dbd_param == $sth->{NUM_OF_PARAMS}; - - return 0 unless $sth->{NUM_OF_FIELDS}; # not a select - - $dir = $dbd_param->[0] || $sth->{examplep_ex_dir}; - return $sth->set_err(2, "No bind parameter supplied") - unless defined $dir; - - $sth->finish; - - # - # If the users asks for directory "long_list_4532", then we fake a - # directory with files "file4351", "file4350", ..., "file0". - # This is a special case used for testing, especially DBD::Proxy. - # - if ($dir =~ /^long_list_(\d+)$/) { - $sth->{dbd_dir} = [ $1 ]; # array ref indicates special mode - $sth->{dbd_datahandle} = undef; - } - else { - $sth->{dbd_dir} = $dir; - my $sym = Symbol::gensym(); # "DBD::ExampleP::".++$DBD::ExampleP::gensym; - opendir($sym, $dir) - or return $sth->set_err(2, "opendir($dir): $!"); - $sth->{dbd_datahandle} = $sym; - } - $sth->STORE(Active => 1); - return 1; - } - - - sub fetch { - my $sth = shift; - my $dir = $sth->{dbd_dir}; - my %s; - - if (ref $dir) { # special fake-data test mode - my $num = $dir->[0]--; - unless ($num > 0) { - $sth->finish(); - return; - } - my $time = time; - @s{@DBD::ExampleP::statnames} = - ( 2051, 1000+$num, 0644, 2, $>, $), 0, 1024, - $time, $time, $time, 512, 2, "file$num") - } - else { # normal mode - my $dh = $sth->{dbd_datahandle} - or return $sth->set_err($DBI::stderr, "fetch without successful execute"); - my $f = readdir($dh); - unless ($f) { - $sth->finish; - return; - } - # untaint $f so that we can use this for DBI taint tests - ($f) = ($f =~ m/^(.*)$/); - my $file = File::Spec->catfile($dir, $f); - # put in all the data fields - @s{ @DBD::ExampleP::statnames } = (lstat($file), $f); - } - - # return just what fields the query asks for - my @new = @s{ @{$sth->{NAME}} }; - - return $sth->_set_fbav(\@new); - } - *fetchrow_arrayref = \&fetch; - - - sub finish { - my $sth = shift; - closedir($sth->{dbd_datahandle}) if $sth->{dbd_datahandle}; - $sth->{dbd_datahandle} = undef; - $sth->{dbd_dir} = undef; - $sth->SUPER::finish(); - return 1; - } - - - sub FETCH { - my ($sth, $attrib) = @_; - # In reality this would interrogate the database engine to - # either return dynamic values that cannot be precomputed - # or fetch and cache attribute values too expensive to prefetch. - if ($attrib eq 'TYPE'){ - return [ @DBD::ExampleP::stattypes{ @{ $sth->FETCH(q{NAME_lc}) } } ]; - } - elsif ($attrib eq 'PRECISION'){ - return [ @DBD::ExampleP::statprec{ @{ $sth->FETCH(q{NAME_lc}) } } ]; - } - elsif ($attrib eq 'ParamValues') { - my $dbd_param = $sth->{dbd_param} || []; - my %pv = map { $_ => $dbd_param->[$_-1] } 1..@$dbd_param; - return \%pv; - } - # else pass up to DBI to handle - return $sth->SUPER::FETCH($attrib); - } - - - sub STORE { - my ($sth, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - return $sth->{$attrib} = $value - if $attrib eq 'NAME' or $attrib eq 'NULLABLE' or $attrib eq 'SCALE' or $attrib eq 'PRECISION'; - return $sth->SUPER::STORE($attrib, $value); - } - - *parse_trace_flag = \&DBD::ExampleP::db::parse_trace_flag; -} - -1; -# vim: sw=4:ts=8 diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/File.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/File.pm deleted file mode 100644 index dd4312b..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/File.pm +++ /dev/null @@ -1,1449 +0,0 @@ -# -*- perl -*- -# -# DBD::File - A base class for implementing DBI drivers that -# act on plain files -# -# This module is currently maintained by -# -# H.Merijn Brand & Jens Rehsack -# -# The original author is Jochen Wiedmann. -# -# Copyright (C) 2009-2013 by H.Merijn Brand & Jens Rehsack -# Copyright (C) 2004 by Jeff Zucker -# Copyright (C) 1998 by Jochen Wiedmann -# -# All rights reserved. -# -# You may distribute this module under the terms of either the GNU -# General Public License or the Artistic License, as specified in -# the Perl README file. - -require 5.008; - -use strict; -use warnings; - -use DBI (); - -package DBD::File; - -use strict; -use warnings; - -use base qw( DBI::DBD::SqlEngine ); -use Carp; -use vars qw( @ISA $VERSION $drh ); - -$VERSION = "0.44"; - -$drh = undef; # holds driver handle(s) once initialized - -sub driver ($;$) -{ - my ($class, $attr) = @_; - - # Drivers typically use a singleton object for the $drh - # We use a hash here to have one singleton per subclass. - # (Otherwise DBD::CSV and DBD::DBM, for example, would - # share the same driver object which would cause problems.) - # An alternative would be to not cache the $drh here at all - # and require that subclasses do that. Subclasses should do - # their own caching, so caching here just provides extra safety. - $drh->{$class} and return $drh->{$class}; - - $attr ||= {}; - { no strict "refs"; - unless ($attr->{Attribution}) { - $class eq "DBD::File" and - $attr->{Attribution} = "$class by Jeff Zucker"; - $attr->{Attribution} ||= ${$class . "::ATTRIBUTION"} || - "oops the author of $class forgot to define this"; - } - $attr->{Version} ||= ${$class . "::VERSION"}; - $attr->{Name} or ($attr->{Name} = $class) =~ s/^DBD\:\://; - } - - $drh->{$class} = $class->SUPER::driver ($attr); - - # XXX inject DBD::XXX::Statement unless exists - - return $drh->{$class}; - } # driver - -sub CLONE -{ - undef $drh; - } # CLONE - -# ====== DRIVER ================================================================ - -package DBD::File::dr; - -use strict; -use warnings; - -use vars qw( @ISA $imp_data_size ); - -use Carp; - -@DBD::File::dr::ISA = qw( DBI::DBD::SqlEngine::dr ); -$DBD::File::dr::imp_data_size = 0; - -sub dsn_quote -{ - my $str = shift; - ref $str and return ""; - defined $str or return ""; - $str =~ s/([;:\\])/\\$1/g; - return $str; - } # dsn_quote - -# XXX rewrite using TableConfig ... -sub default_table_source { "DBD::File::TableSource::FileSystem" } - -sub connect -{ - my ($drh, $dbname, $user, $auth, $attr) = @_; - - # We do not (yet) care about conflicting attributes here - # my $dbh = DBI->connect ("dbi:CSV:f_dir=test", undef, undef, { f_dir => "text" }); - # will test here that both test and text should exist - if (my $attr_hash = (DBI->parse_dsn ($dbname))[3]) { - if (defined $attr_hash->{f_dir} && ! -d $attr_hash->{f_dir}) { - my $msg = "No such directory '$attr_hash->{f_dir}"; - $drh->set_err (2, $msg); - $attr_hash->{RaiseError} and croak $msg; - return; - } - } - if ($attr and defined $attr->{f_dir} && ! -d $attr->{f_dir}) { - my $msg = "No such directory '$attr->{f_dir}"; - $drh->set_err (2, $msg); - $attr->{RaiseError} and croak $msg; - return; - } - - return $drh->SUPER::connect ($dbname, $user, $auth, $attr); - } # connect - -sub disconnect_all -{ - } # disconnect_all - -sub DESTROY -{ - undef; - } # DESTROY - -# ====== DATABASE ============================================================== - -package DBD::File::db; - -use strict; -use warnings; - -use vars qw( @ISA $imp_data_size ); - -use Carp; -require File::Spec; -require Cwd; -use Scalar::Util qw( refaddr ); # in CORE since 5.7.3 - -@DBD::File::db::ISA = qw( DBI::DBD::SqlEngine::db ); -$DBD::File::db::imp_data_size = 0; - -sub data_sources -{ - my ($dbh, $attr, @other) = @_; - ref ($attr) eq "HASH" or $attr = {}; - exists $attr->{f_dir} or $attr->{f_dir} = $dbh->{f_dir}; - exists $attr->{f_dir_search} or $attr->{f_dir_search} = $dbh->{f_dir_search}; - return $dbh->SUPER::data_sources ($attr, @other); - } # data_source - -sub set_versions -{ - my $dbh = shift; - $dbh->{f_version} = $DBD::File::VERSION; - - return $dbh->SUPER::set_versions (); - } # set_versions - -sub init_valid_attributes -{ - my $dbh = shift; - - $dbh->{f_valid_attrs} = { - f_version => 1, # DBD::File version - f_dir => 1, # base directory - f_dir_search => 1, # extended search directories - f_ext => 1, # file extension - f_schema => 1, # schema name - f_lock => 1, # Table locking mode - f_lockfile => 1, # Table lockfile extension - f_encoding => 1, # Encoding of the file - f_valid_attrs => 1, # File valid attributes - f_readonly_attrs => 1, # File readonly attributes - }; - $dbh->{f_readonly_attrs} = { - f_version => 1, # DBD::File version - f_valid_attrs => 1, # File valid attributes - f_readonly_attrs => 1, # File readonly attributes - }; - - return $dbh->SUPER::init_valid_attributes (); - } # init_valid_attributes - -sub init_default_attributes -{ - my ($dbh, $phase) = @_; - - # must be done first, because setting flags implicitly calls $dbdname::db->STORE - $dbh->SUPER::init_default_attributes ($phase); - - # DBI::BD::SqlEngine::dr::connect will detect old-style drivers and - # don't call twice - unless (defined $phase) { - # we have an "old" driver here - $phase = defined $dbh->{sql_init_phase}; - $phase and $phase = $dbh->{sql_init_phase}; - } - - if (0 == $phase) { - # f_ext should not be initialized - # f_map is deprecated (but might return) - $dbh->{f_dir} = Cwd::abs_path (File::Spec->curdir ()); - - push @{$dbh->{sql_init_order}{90}}, "f_meta"; - - # complete derived attributes, if required - (my $drv_class = $dbh->{ImplementorClass}) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix ($drv_class); - if (exists $dbh->{$drv_prefix . "meta"} and !$dbh->{sql_engine_in_gofer}) { - my $attr = $dbh->{$drv_prefix . "meta"}; - defined $dbh->{f_valid_attrs}{f_meta} - and $dbh->{f_valid_attrs}{f_meta} = 1; - - $dbh->{f_meta} = $dbh->{$attr}; - } - } - - return $dbh; - } # init_default_attributes - -sub validate_FETCH_attr -{ - my ($dbh, $attrib) = @_; - - $attrib eq "f_meta" and $dbh->{sql_engine_in_gofer} and $attrib = "sql_meta"; - - return $dbh->SUPER::validate_FETCH_attr ($attrib); - } # validate_FETCH_attr - -sub validate_STORE_attr -{ - my ($dbh, $attrib, $value) = @_; - - if ($attrib eq "f_dir" && defined $value) { - -d $value or - return $dbh->set_err ($DBI::stderr, "No such directory '$value'"); - File::Spec->file_name_is_absolute ($value) or - $value = Cwd::abs_path ($value); - } - - if ($attrib eq "f_ext") { - $value eq "" || $value =~ m{^\.\w+(?:/[rR]*)?$} or - carp "'$value' doesn't look like a valid file extension attribute\n"; - } - - $attrib eq "f_meta" and $dbh->{sql_engine_in_gofer} and $attrib = "sql_meta"; - - return $dbh->SUPER::validate_STORE_attr ($attrib, $value); - } # validate_STORE_attr - -sub get_f_versions -{ - my ($dbh, $table) = @_; - - my $class = $dbh->{ImplementorClass}; - $class =~ s/::db$/::Table/; - my $dver; - my $dtype = "IO::File"; - eval { - $dver = IO::File->VERSION (); - - # when we're still alive here, everything went ok - no need to check for $@ - $dtype .= " ($dver)"; - }; - - my $f_encoding; - if ($table) { - my $meta; - $table and (undef, $meta) = $class->get_table_meta ($dbh, $table, 1); - $meta and $meta->{f_encoding} and $f_encoding = $meta->{f_encoding}; - } # if ($table) - $f_encoding ||= $dbh->{f_encoding}; - - $f_encoding and $dtype .= " + " . $f_encoding . " encoding"; - - return sprintf "%s using %s", $dbh->{f_version}, $dtype; - } # get_f_versions - -# ====== STATEMENT ============================================================= - -package DBD::File::st; - -use strict; -use warnings; - -use vars qw( @ISA $imp_data_size ); - -@DBD::File::st::ISA = qw( DBI::DBD::SqlEngine::st ); -$DBD::File::st::imp_data_size = 0; - -my %supported_attrs = ( - TYPE => 1, - PRECISION => 1, - NULLABLE => 1, - ); - -sub FETCH -{ - my ($sth, $attr) = @_; - - if ($supported_attrs{$attr}) { - my $stmt = $sth->{sql_stmt}; - - if (exists $sth->{ImplementorClass} && - exists $sth->{sql_stmt} && - $sth->{sql_stmt}->isa ("SQL::Statement")) { - - # fill overall_defs unless we know - unless (exists $sth->{f_overall_defs} && ref $sth->{f_overall_defs}) { - my $types = $sth->{Database}{Types}; - unless ($types) { # Fetch types only once per database - if (my $t = $sth->{Database}->type_info_all ()) { - foreach my $i (1 .. $#$t) { - $types->{uc $t->[$i][0]} = $t->[$i][1]; - $types->{$t->[$i][1]} ||= uc $t->[$i][0]; - } - } - # sane defaults - for ([ 0, "" ], - [ 1, "CHAR" ], - [ 4, "INTEGER" ], - [ 12, "VARCHAR" ], - ) { - $types->{$_->[0]} ||= $_->[1]; - $types->{$_->[1]} ||= $_->[0]; - } - $sth->{Database}{Types} = $types; - } - my $all_meta = - $sth->{Database}->func ("*", "table_defs", "get_sql_engine_meta"); - foreach my $tbl (keys %$all_meta) { - my $meta = $all_meta->{$tbl}; - exists $meta->{table_defs} && ref $meta->{table_defs} or next; - foreach (keys %{$meta->{table_defs}{columns}}) { - my $field_info = $meta->{table_defs}{columns}{$_}; - if (defined $field_info->{data_type} && - $field_info->{data_type} !~ m/^[0-9]+$/) { - $field_info->{type_name} = uc $field_info->{data_type}; - $field_info->{data_type} = $types->{$field_info->{type_name}} || 0; - } - $field_info->{type_name} ||= $types->{$field_info->{data_type}} || "CHAR"; - $sth->{f_overall_defs}{$_} = $field_info; - } - } - } - - my @colnames = $sth->sql_get_colnames (); - - $attr eq "TYPE" and - return [ map { $sth->{f_overall_defs}{$_}{data_type} || 12 } - @colnames ]; - - $attr eq "TYPE_NAME" and - return [ map { $sth->{f_overall_defs}{$_}{type_name} || "VARCHAR" } - @colnames ]; - - $attr eq "PRECISION" and - return [ map { $sth->{f_overall_defs}{$_}{data_length} || 0 } - @colnames ]; - - $attr eq "NULLABLE" and - return [ map { ( grep { $_ eq "NOT NULL" } - @{ $sth->{f_overall_defs}{$_}{constraints} || [] }) - ? 0 : 1 } - @colnames ]; - } - } - - return $sth->SUPER::FETCH ($attr); - } # FETCH - -# ====== TableSource =========================================================== - -package DBD::File::TableSource::FileSystem; - -use strict; -use warnings; - -use IO::Dir; - -@DBD::File::TableSource::FileSystem::ISA = "DBI::DBD::SqlEngine::TableSource"; - -sub data_sources -{ - my ($class, $drh, $attr) = @_; - my $dir = $attr && exists $attr->{f_dir} - ? $attr->{f_dir} - : File::Spec->curdir (); - defined $dir or return; # Stream-based databases do not have f_dir - unless (-d $dir && -r $dir && -x $dir) { - $drh->set_err ($DBI::stderr, "Cannot use directory $dir from f_dir"); - return; - } - my %attrs; - $attr and %attrs = %$attr; - delete $attrs{f_dir}; - my $dsn_quote = $drh->{ImplementorClass}->can ("dsn_quote"); - my $dsnextra = join ";", map { $_ . "=" . &{$dsn_quote} ($attrs{$_}) } keys %attrs; - my @dir = ($dir); - $attr->{f_dir_search} && ref $attr->{f_dir_search} eq "ARRAY" and - push @dir, grep { -d $_ } @{$attr->{f_dir_search}}; - my @dsns; - foreach $dir (@dir) { - my $dirh = IO::Dir->new ($dir); - unless (defined $dirh) { - $drh->set_err ($DBI::stderr, "Cannot open directory $dir: $!"); - return; - } - - my ($file, %names, $driver); - $driver = $drh->{ImplementorClass} =~ m/^dbd\:\:([^\:]+)\:\:/i ? $1 : "File"; - - while (defined ($file = $dirh->read ())) { - my $d = File::Spec->catdir ($dir, $file); - # allow current dir ... it can be a data_source too - $file ne File::Spec->updir () && -d $d and - push @dsns, "DBI:$driver:f_dir=" . &{$dsn_quote} ($d) . ($dsnextra ? ";$dsnextra" : ""); - } - } - return @dsns; - } # data_sources - -sub avail_tables -{ - my ($self, $dbh) = @_; - - my $dir = $dbh->{f_dir}; - defined $dir or return; # Stream based db's cannot be queried for tables - - my %seen; - my @tables; - my @dir = ($dir); - $dbh->{f_dir_search} && ref $dbh->{f_dir_search} eq "ARRAY" and - push @dir, grep { -d $_ } @{$dbh->{f_dir_search}}; - foreach $dir (@dir) { - my $dirh = IO::Dir->new ($dir); - - unless (defined $dirh) { - $dbh->set_err ($DBI::stderr, "Cannot open directory $dir: $!"); - return; - } - - my $class = $dbh->FETCH ("ImplementorClass"); - $class =~ s/::db$/::Table/; - my ($file, %names); - my $schema = exists $dbh->{f_schema} - ? defined $dbh->{f_schema} && $dbh->{f_schema} ne "" - ? $dbh->{f_schema} : undef - : eval { getpwuid ((stat $dir)[4]) }; # XXX Win32::pwent - while (defined ($file = $dirh->read ())) { - my ($tbl, $meta) = $class->get_table_meta ($dbh, $file, 0, 0) or next; # XXX - # $tbl && $meta && -f $meta->{f_fqfn} or next; - $seen{defined $schema ? $schema : "\0"}{$dir}{$tbl}++ or - push @tables, [ undef, $schema, $tbl, "TABLE", "FILE" ]; - } - $dirh->close () or - $dbh->set_err ($DBI::stderr, "Cannot close directory $dir: $!"); - } - - return @tables; - } # avail_tables - -# ====== DataSource ============================================================ - -package DBD::File::DataSource::Stream; - -use strict; -use warnings; - -use Carp; - -@DBD::File::DataSource::Stream::ISA = "DBI::DBD::SqlEngine::DataSource"; - -# We may have a working flock () built-in but that doesn't mean that locking -# will work on NFS (flock () may hang hard) -my $locking = eval { - my $fh; - my $nulldevice = File::Spec->devnull (); - open $fh, ">", $nulldevice or croak "Can't open $nulldevice: $!"; - flock $fh, 0; - close $fh; - 1; - }; - -sub complete_table_name -{ - my ($self, $meta, $file, $respect_case) = @_; - - my $tbl = $file; - if (!$respect_case and $meta->{sql_identifier_case} == 1) { # XXX SQL_IC_UPPER - $tbl = uc $tbl; - } - elsif (!$respect_case and $meta->{sql_identifier_case} == 2) { # XXX SQL_IC_LOWER - $tbl = lc $tbl; - } - - $meta->{f_fqfn} = undef; - $meta->{f_fqbn} = undef; - $meta->{f_fqln} = undef; - - $meta->{table_name} = $tbl; - - return $tbl; - } # complete_table_name - -sub apply_encoding -{ - my ($self, $meta, $fn) = @_; - defined $fn or $fn = "file handle " . fileno ($meta->{fh}); - if (my $enc = $meta->{f_encoding}) { - binmode $meta->{fh}, ":encoding($enc)" or - croak "Failed to set encoding layer '$enc' on $fn: $!"; - } - else { - binmode $meta->{fh} or croak "Failed to set binary mode on $fn: $!"; - } - } # apply_encoding - -sub open_data -{ - my ($self, $meta, $attrs, $flags) = @_; - - $flags->{dropMode} and croak "Can't drop a table in stream"; - my $fn = "file handle " . fileno ($meta->{f_file}); - - if ($flags->{createMode} || $flags->{lockMode}) { - $meta->{fh} = IO::Handle->new_from_fd (fileno ($meta->{f_file}), "w+") or - croak "Cannot open $fn for writing: $! (" . ($!+0) . ")"; - } - else { - $meta->{fh} = IO::Handle->new_from_fd (fileno ($meta->{f_file}), "r") or - croak "Cannot open $fn for reading: $! (" . ($!+0) . ")"; - } - - if ($meta->{fh}) { - $self->apply_encoding ($meta, $fn); - } # have $meta->{$fh} - - if ($self->can_flock && $meta->{fh}) { - my $lm = defined $flags->{f_lock} - && $flags->{f_lock} =~ m/^[012]$/ - ? $flags->{f_lock} - : $flags->{lockMode} ? 2 : 1; - if ($lm == 2) { - flock $meta->{fh}, 2 or croak "Cannot obtain exclusive lock on $fn: $!"; - } - elsif ($lm == 1) { - flock $meta->{fh}, 1 or croak "Cannot obtain shared lock on $fn: $!"; - } - # $lm = 0 is forced no locking at all - } - } # open_data - -sub can_flock { $locking } - -package DBD::File::DataSource::File; - -use strict; -use warnings; - -@DBD::File::DataSource::File::ISA = "DBD::File::DataSource::Stream"; - -use Carp; - -my $fn_any_ext_regex = qr/\.[^.]*/; - -sub complete_table_name -{ - my ($self, $meta, $file, $respect_case, $file_is_table) = @_; - - $file eq "." || $file eq ".." and return; # XXX would break a possible DBD::Dir - - # XXX now called without proving f_fqfn first ... - my ($ext, $req) = ("", 0); - if ($meta->{f_ext}) { - ($ext, my $opt) = split m{/}, $meta->{f_ext}; - if ($ext && $opt) { - $opt =~ m/r/i and $req = 1; - } - } - - # (my $tbl = $file) =~ s/\Q$ext\E$//i; - my ($tbl, $basename, $dir, $fn_ext, $user_spec_file, $searchdir); - if ($file_is_table and defined $meta->{f_file}) { - $tbl = $file; - ($basename, $dir, $fn_ext) = File::Basename::fileparse ($meta->{f_file}, $fn_any_ext_regex); - $file = $basename . $fn_ext; - $user_spec_file = 1; - } - else { - ($basename, $dir, undef) = File::Basename::fileparse ($file, qr{\Q$ext\E}); - # $dir is returned with trailing (back)slash. We just need to check - # if it is ".", "./", or ".\" or "[]" (VMS) - if ($dir =~ m{^(?:[.][/\\]?|\[\])$} && ref $meta->{f_dir_search} eq "ARRAY") { - foreach my $d ($meta->{f_dir}, @{$meta->{f_dir_search}}) { - my $f = File::Spec->catdir ($d, $file); - -f $f or next; - $searchdir = Cwd::abs_path ($d); - $dir = ""; - last; - } - } - $file = $tbl = $basename; - $user_spec_file = 0; - } - - if (!$respect_case and $meta->{sql_identifier_case} == 1) { # XXX SQL_IC_UPPER - $basename = uc $basename; - $tbl = uc $tbl; - } - elsif (!$respect_case and $meta->{sql_identifier_case} == 2) { # XXX SQL_IC_LOWER - $basename = lc $basename; - $tbl = lc $tbl; - } - - unless (defined $searchdir) { - $searchdir = File::Spec->file_name_is_absolute ($dir) - ? ($dir =~ s{/$}{}, $dir) - : Cwd::abs_path (File::Spec->catdir ($meta->{f_dir}, $dir)); - } - -d $searchdir or - croak "-d $searchdir: $!"; - - $searchdir eq $meta->{f_dir} and - $dir = ""; - - unless ($user_spec_file) { - $file_is_table and $file = "$basename$ext"; - - # Fully Qualified File Name - my $cmpsub; - if ($respect_case) { - $cmpsub = sub { - my ($fn, undef, $sfx) = File::Basename::fileparse ($_, $fn_any_ext_regex); - $^O eq "VMS" && $sfx eq "." and - $sfx = ""; # no extension turns up as a dot - $fn eq $basename and - return (lc $sfx eq lc $ext or !$req && !$sfx); - return 0; - } - } - else { - $cmpsub = sub { - my ($fn, undef, $sfx) = File::Basename::fileparse ($_, $fn_any_ext_regex); - $^O eq "VMS" && $sfx eq "." and - $sfx = ""; # no extension turns up as a dot - lc $fn eq lc $basename and - return (lc $sfx eq lc $ext or !$req && !$sfx); - return 0; - } - } - - my @f; - { my $dh = IO::Dir->new ($searchdir) or croak "Can't open '$searchdir': $!"; - @f = sort { length $b <=> length $a } - grep { &$cmpsub ($_) } - $dh->read (); - $dh->close () or croak "Can't close '$searchdir': $!"; - } - @f > 0 && @f <= 2 and $file = $f[0]; - !$respect_case && $meta->{sql_identifier_case} == 4 and # XXX SQL_IC_MIXED - ($tbl = $file) =~ s/\Q$ext\E$//i; - - my $tmpfn = $file; - if ($ext && $req) { - # File extension required - $tmpfn =~ s/\Q$ext\E$//i or return; - } - } - - my $fqfn = File::Spec->catfile ($searchdir, $file); - my $fqbn = File::Spec->catfile ($searchdir, $basename); - - $meta->{f_fqfn} = $fqfn; - $meta->{f_fqbn} = $fqbn; - defined $meta->{f_lockfile} && $meta->{f_lockfile} and - $meta->{f_fqln} = $meta->{f_fqbn} . $meta->{f_lockfile}; - - $dir && !$user_spec_file and $tbl = File::Spec->catfile ($dir, $tbl); - $meta->{table_name} = $tbl; - - return $tbl; - } # complete_table_name - -sub open_data -{ - my ($self, $meta, $attrs, $flags) = @_; - - defined $meta->{f_fqfn} && $meta->{f_fqfn} ne "" or croak "No filename given"; - - my ($fh, $fn); - unless ($meta->{f_dontopen}) { - $fn = $meta->{f_fqfn}; - if ($flags->{createMode}) { - -f $meta->{f_fqfn} and - croak "Cannot create table $attrs->{table}: Already exists"; - $fh = IO::File->new ($fn, "a+") or - croak "Cannot open $fn for writing: $! (" . ($!+0) . ")"; - } - else { - unless ($fh = IO::File->new ($fn, ($flags->{lockMode} ? "r+" : "r"))) { - croak "Cannot open $fn: $! (" . ($!+0) . ")"; - } - } - - $meta->{fh} = $fh; - - if ($fh) { - $fh->seek (0, 0) or - croak "Error while seeking back: $!"; - - $self->apply_encoding ($meta); - } - } - if ($meta->{f_fqln}) { - $fn = $meta->{f_fqln}; - if ($flags->{createMode}) { - -f $fn and - croak "Cannot create table lock at '$fn' for $attrs->{table}: Already exists"; - $fh = IO::File->new ($fn, "a+") or - croak "Cannot open $fn for writing: $! (" . ($!+0) . ")"; - } - else { - unless ($fh = IO::File->new ($fn, ($flags->{lockMode} ? "r+" : "r"))) { - croak "Cannot open $fn: $! (" . ($!+0) . ")"; - } - } - - $meta->{lockfh} = $fh; - } - - if ($self->can_flock && $fh) { - my $lm = defined $flags->{f_lock} - && $flags->{f_lock} =~ m/^[012]$/ - ? $flags->{f_lock} - : $flags->{lockMode} ? 2 : 1; - if ($lm == 2) { - flock $fh, 2 or croak "Cannot obtain exclusive lock on $fn: $!"; - } - elsif ($lm == 1) { - flock $fh, 1 or croak "Cannot obtain shared lock on $fn: $!"; - } - # $lm = 0 is forced no locking at all - } - } # open_data - -# ====== SQL::STATEMENT ======================================================== - -package DBD::File::Statement; - -use strict; -use warnings; - -@DBD::File::Statement::ISA = qw( DBI::DBD::SqlEngine::Statement ); - -# ====== SQL::TABLE ============================================================ - -package DBD::File::Table; - -use strict; -use warnings; - -use Carp; -require IO::File; -require File::Basename; -require File::Spec; -require Cwd; -require Scalar::Util; - -@DBD::File::Table::ISA = qw( DBI::DBD::SqlEngine::Table ); - -# ====== UTILITIES ============================================================ - -if (eval { require Params::Util; }) { - Params::Util->import ("_HANDLE"); - } -else { - # taken but modified from Params::Util ... - *_HANDLE = sub { - # It has to be defined, of course - defined $_[0] or return; - - # Normal globs are considered to be file handles - ref $_[0] eq "GLOB" and return $_[0]; - - # Check for a normal tied filehandle - # Side Note: 5.5.4's tied () and can () doesn't like getting undef - tied ($_[0]) and tied ($_[0])->can ("TIEHANDLE") and return $_[0]; - - # There are no other non-object handles that we support - Scalar::Util::blessed ($_[0]) or return; - - # Check for a common base classes for conventional IO::Handle object - $_[0]->isa ("IO::Handle") and return $_[0]; - - # Check for tied file handles using Tie::Handle - $_[0]->isa ("Tie::Handle") and return $_[0]; - - # IO::Scalar is not a proper seekable, but it is valid is a - # regular file handle - $_[0]->isa ("IO::Scalar") and return $_[0]; - - # Yet another special case for IO::String, which refuses (for now - # anyway) to become a subclass of IO::Handle. - $_[0]->isa ("IO::String") and return $_[0]; - - # This is not any sort of object we know about - return; - }; - } - -# ====== FLYWEIGHT SUPPORT ===================================================== - -# Flyweight support for table_info -# The functions file2table, init_table_meta, default_table_meta and -# get_table_meta are using $self arguments for polymorphism only. The -# must not rely on an instantiated DBD::File::Table -sub file2table -{ - my ($self, $meta, $file, $file_is_table, $respect_case) = @_; - - return $meta->{sql_data_source}->complete_table_name ($meta, $file, $respect_case, $file_is_table); - } # file2table - -sub bootstrap_table_meta -{ - my ($self, $dbh, $meta, $table, @other) = @_; - - $self->SUPER::bootstrap_table_meta ($dbh, $meta, $table, @other); - - exists $meta->{f_dir} or $meta->{f_dir} = $dbh->{f_dir}; - exists $meta->{f_dir_search} or $meta->{f_dir_search} = $dbh->{f_dir_search}; - defined $meta->{f_ext} or $meta->{f_ext} = $dbh->{f_ext}; - defined $meta->{f_encoding} or $meta->{f_encoding} = $dbh->{f_encoding}; - exists $meta->{f_lock} or $meta->{f_lock} = $dbh->{f_lock}; - exists $meta->{f_lockfile} or $meta->{f_lockfile} = $dbh->{f_lockfile}; - defined $meta->{f_schema} or $meta->{f_schema} = $dbh->{f_schema}; - - defined $meta->{f_open_file_needed} or - $meta->{f_open_file_needed} = $self->can ("open_file") != DBD::File::Table->can ("open_file"); - - defined ($meta->{sql_data_source}) or - $meta->{sql_data_source} = _HANDLE ($meta->{f_file}) - ? "DBD::File::DataSource::Stream" - : "DBD::File::DataSource::File"; - } # bootstrap_table_meta - -sub get_table_meta ($$$$;$) -{ - my ($self, $dbh, $table, $file_is_table, $respect_case) = @_; - - my $meta = $self->SUPER::get_table_meta ($dbh, $table, $respect_case, $file_is_table); - $table = $meta->{table_name}; - return unless $table; - - return ($table, $meta); - } # get_table_meta - -my %reset_on_modify = ( - f_file => [ "f_fqfn", "sql_data_source" ], - f_dir => "f_fqfn", - f_dir_search => [], - f_ext => "f_fqfn", - f_lockfile => "f_fqfn", # forces new file2table call - ); - -__PACKAGE__->register_reset_on_modify (\%reset_on_modify); - -my %compat_map = map { $_ => "f_$_" } qw( file ext lock lockfile ); - -__PACKAGE__->register_compat_map (\%compat_map); - -# ====== DBD::File <= 0.40 compat stuff ======================================== - -# compat to 0.38 .. 0.40 API -sub open_file -{ - my ($className, $meta, $attrs, $flags) = @_; - - return $className->SUPER::open_data ($meta, $attrs, $flags); - } # open_file - -sub open_data -{ - my ($className, $meta, $attrs, $flags) = @_; - - # compat to 0.38 .. 0.40 API - $meta->{f_open_file_needed} - ? $className->open_file ($meta, $attrs, $flags) - : $className->SUPER::open_data ($meta, $attrs, $flags); - - return; - } # open_data - -# ====== SQL::Eval API ========================================================= - -sub drop ($) -{ - my ($self, $data) = @_; - my $meta = $self->{meta}; - # We have to close the file before unlinking it: Some OS'es will - # refuse the unlink otherwise. - $meta->{fh} and $meta->{fh}->close (); - $meta->{lockfh} and $meta->{lockfh}->close (); - undef $meta->{fh}; - undef $meta->{lockfh}; - $meta->{f_fqfn} and unlink $meta->{f_fqfn}; # XXX ==> sql_data_source - $meta->{f_fqln} and unlink $meta->{f_fqln}; # XXX ==> sql_data_source - delete $data->{Database}{sql_meta}{$self->{table}}; - return 1; - } # drop - -sub seek ($$$$) -{ - my ($self, $data, $pos, $whence) = @_; - my $meta = $self->{meta}; - if ($whence == 0 && $pos == 0) { - $pos = defined $meta->{first_row_pos} ? $meta->{first_row_pos} : 0; - } - elsif ($whence != 2 || $pos != 0) { - croak "Illegal seek position: pos = $pos, whence = $whence"; - } - - $meta->{fh}->seek ($pos, $whence) or - croak "Error while seeking in " . $meta->{f_fqfn} . ": $!"; - } # seek - -sub truncate ($$) -{ - my ($self, $data) = @_; - my $meta = $self->{meta}; - $meta->{fh}->truncate ($meta->{fh}->tell ()) or - croak "Error while truncating " . $meta->{f_fqfn} . ": $!"; - return 1; - } # truncate - -sub DESTROY -{ - my $self = shift; - my $meta = $self->{meta}; - $meta->{fh} and $meta->{fh}->close (); - $meta->{lockfh} and $meta->{lockfh}->close (); - undef $meta->{fh}; - undef $meta->{lockfh}; - - $self->SUPER::DESTROY(); - } # DESTROY - -1; - -__END__ - -=head1 NAME - -DBD::File - Base class for writing file based DBI drivers - -=head1 SYNOPSIS - -This module is a base class for writing other Ls. -It is not intended to function as a DBD itself (though it is possible). -If you want to access flat files, use L, or -L (both of which are subclasses of DBD::File). - -=head1 DESCRIPTION - -The DBD::File module is not a true L driver, but an abstract -base class for deriving concrete DBI drivers from it. The implication -is, that these drivers work with plain files, for example CSV files or -INI files. The module is based on the L -module, a simple SQL engine. - -See L for details on DBI, L for -details on SQL::Statement and L, L -or L for example drivers. - -=head2 Metadata - -The following attributes are handled by DBI itself and not by DBD::File, -thus they all work as expected: - - Active - ActiveKids - CachedKids - CompatMode (Not used) - InactiveDestroy - AutoInactiveDestroy - Kids - PrintError - RaiseError - Warn (Not used) - -=head3 The following DBI attributes are handled by DBD::File: - -=head4 AutoCommit - -Always on. - -=head4 ChopBlanks - -Works. - -=head4 NUM_OF_FIELDS - -Valid after C<< $sth->execute >>. - -=head4 NUM_OF_PARAMS - -Valid after C<< $sth->prepare >>. - -=head4 NAME - -Valid after C<< $sth->execute >>; undef for Non-Select statements. - -=head4 NULLABLE - -Not really working, always returns an array ref of ones, except the -affected table has been created in this session. Valid after -C<< $sth->execute >>; undef for non-select statements. - -=head3 Unsupported DBI attributes and methods - -=head4 bind_param_inout - -=head4 CursorName - -=head4 LongReadLen - -=head4 LongTruncOk - -=head3 DBD::File specific attributes - -In addition to the DBI attributes, you can use the following dbh -attributes: - -=head4 f_dir - -This attribute is used for setting the directory where the files are -opened and it defaults to the current directory (F<.>). Usually you set -it on the dbh but it may be overridden per table (see L). - -When the value for C is a relative path, it is converted into -the appropriate absolute path name (based on the current working -directory) when the dbh attribute is set. - - f_dir => "/data/foo/csv", - -See L. - -=head4 f_dir_search - -This optional attribute can be set to pass a list of folders to also -find existing tables. It will B be used to create new files. - - f_dir_search => [ "/data/bar/csv", "/dump/blargh/data" ], - -=head4 f_ext - -This attribute is used for setting the file extension. The format is: - - extension{/flag} - -where the /flag is optional and the extension is case-insensitive. -C allows you to specify an extension which: - - f_ext => ".csv/r", - -=over - -=item * - -makes DBD::File prefer F over F
. - -=item * - -makes the table name the filename minus the extension. - -=back - - DBI:CSV:f_dir=data;f_ext=.csv - -In the above example and when C contains both F and -F
, DBD::File will open F and the table will be -named "table". If F does not exist but F
does -that file is opened and the table is also called "table". - -If C is not specified and F exists it will be opened -and the table will be called "table.csv" which is probably not what -you want. - -NOTE: even though extensions are case-insensitive, table names are -not. - - DBI:CSV:f_dir=data;f_ext=.csv/r - -The C flag means the file extension is required and any filename -that does not match the extension is ignored. - -Usually you set it on the dbh but it may be overridden per table -(see L). - -=head4 f_schema - -This will set the schema name and defaults to the owner of the -directory in which the table file resides. You can set C to -C. - - my $dbh = DBI->connect ("dbi:CSV:", "", "", { - f_schema => undef, - f_dir => "data", - f_ext => ".csv/r", - }) or die $DBI::errstr; - -By setting the schema you affect the results from the tables call: - - my @tables = $dbh->tables (); - - # no f_schema - "merijn".foo - "merijn".bar - - # f_schema => "dbi" - "dbi".foo - "dbi".bar - - # f_schema => undef - foo - bar - -Defining C to the empty string is equal to setting it to C -so the DSN can be C<"dbi:CSV:f_schema=;f_dir=.">. - -=head4 f_lock - -The C attribute is used to set the locking mode on the opened -table files. Note that not all platforms support locking. By default, -tables are opened with a shared lock for reading, and with an -exclusive lock for writing. The supported modes are: - - 0: No locking at all. - - 1: Shared locks will be used. - - 2: Exclusive locks will be used. - -But see L below. - -=head4 f_lockfile - -If you wish to use a lockfile extension other than C<.lck>, simply specify -the C attribute: - - $dbh = DBI->connect ("dbi:DBM:f_lockfile=.foo"); - $dbh->{f_lockfile} = ".foo"; - $dbh->{dbm_tables}{qux}{f_lockfile} = ".foo"; - -If you wish to disable locking, set the C to C<0>. - - $dbh = DBI->connect ("dbi:DBM:f_lockfile=0"); - $dbh->{f_lockfile} = 0; - $dbh->{dbm_tables}{qux}{f_lockfile} = 0; - -=head4 f_encoding - -With this attribute, you can set the encoding in which the file is opened. -This is implemented using C<< binmode $fh, ":encoding()" >>. - -=head4 f_meta - -Private data area aliasing L which -contains information about the tables this module handles. Table meta -data might not be available until the table has been accessed for the -first time e.g., by issuing a select on it however it is possible to -pre-initialize attributes for each table you use. - -DBD::File recognizes the (public) attributes C, C, -C, C, C, C, C, -in addition to the attributes L already -supports. Be very careful when modifying attributes you do not know, -the consequence might be a destroyed or corrupted table. - -C is an attribute applicable to table meta data only and you -will not find a corresponding attribute in the dbh. Whilst it may be -reasonable to have several tables with the same column names, it is -not for the same file name. If you need access to the same file using -different table names, use C as the SQL engine and the -C keyword: - - SELECT * FROM tbl AS t1, tbl AS t2 WHERE t1.id = t2.id - -C can be an absolute path name or a relative path name but if -it is relative, it is interpreted as being relative to the C -attribute of the table meta data. When C is set DBD::File will -use C as specified and will not attempt to work out an -alternative for C using the C
and C -attribute. - -While C is a private and readonly attribute (which means, you -cannot modify it's values), derived drivers might provide restricted -write access through another attribute. Well known accessors are -C for L, C for L and -C for L. - -=head3 New opportunities for attributes from DBI::DBD::SqlEngine - -=head4 sql_table_source - -C<< $dbh->{sql_table_source} >> can be set to -I (and is the default setting -of DBD::File). This provides usual behaviour of previous DBD::File -releases on - - @ary = DBI->data_sources ($driver); - @ary = DBI->data_sources ($driver, \%attr); - - @ary = $dbh->data_sources (); - @ary = $dbh->data_sources (\%attr); - - @names = $dbh->tables ($catalog, $schema, $table, $type); - - $sth = $dbh->table_info ($catalog, $schema, $table, $type); - $sth = $dbh->table_info ($catalog, $schema, $table, $type, \%attr); - - $dbh->func ("list_tables"); - -=head4 sql_data_source - -C<< $dbh->{sql_data_source} >> can be set to either -I, which is default and provides the -well known behavior of DBD::File releases prior to 0.41, or -I, which reuses already opened -file-handle for operations. - -=head3 Internally private attributes to deal with SQL backends - -Do not modify any of these private attributes unless you understand -the implications of doing so. The behavior of DBD::File and derived -DBDs might be unpredictable when one or more of those attributes are -modified. - -=head4 sql_nano_version - -Contains the version of loaded DBI::SQL::Nano. - -=head4 sql_statement_version - -Contains the version of loaded SQL::Statement. - -=head4 sql_handler - -Contains either the text 'SQL::Statement' or 'DBI::SQL::Nano'. - -=head4 sql_ram_tables - -Contains optionally temporary tables. - -=head4 sql_flags - -Contains optional flags to instantiate the SQL::Parser parsing engine -when SQL::Statement is used as SQL engine. See L for valid -flags. - -=head2 Driver private methods - -=head3 Default DBI methods - -=head4 data_sources - -The C method returns a list of subdirectories of the current -directory in the form "dbi:CSV:f_dir=$dirname". - -If you want to read the subdirectories of another directory, use - - my ($drh) = DBI->install_driver ("CSV"); - my (@list) = $drh->data_sources (f_dir => "/usr/local/csv_data"); - -=head3 Additional methods - -The following methods are only available via their documented name when -DBD::File is used directly. Because this is only reasonable for testing -purposes, the real names must be used instead. Those names can be computed -by replacing the C in the method name with the driver prefix. - -=head4 f_versions - -Signature: - - sub f_versions (;$) - { - my ($table_name) = @_; - $table_name ||= "."; - ... - } - -Returns the versions of the driver, including the DBI version, the Perl -version, DBI::PurePerl version (if DBI::PurePerl is active) and the version -of the SQL engine in use. - - my $dbh = DBI->connect ("dbi:File:"); - my $f_versions = $dbh->func ("f_versions"); - print "$f_versions\n"; - __END__ - # DBD::File 0.41 using IO::File (1.16) - # DBI::DBD::SqlEngine 0.05 using SQL::Statement 1.406 - # DBI 1.623 - # OS darwin (12.2.1) - # Perl 5.017006 (darwin-thread-multi-ld-2level) - -Called in list context, f_versions will return an array containing each -line as single entry. - -Some drivers might use the optional (table name) argument and modify -version information related to the table (e.g. DBD::DBM provides storage -backend information for the requested table, when it has a table name). - -=head1 KNOWN BUGS AND LIMITATIONS - -=over 4 - -=item * - -This module uses flock () internally but flock is not available on all -platforms. On MacOS and Windows 95 there is no locking at all (perhaps -not so important on MacOS and Windows 95, as there is only a single -user). - -=item * - -The module stores details about the handled tables in a private area -of the driver handle (C<$drh>). This data area is not shared between -different driver instances, so several C<< DBI->connect () >> calls will -cause different table instances and private data areas. - -This data area is filled for the first time when a table is accessed, -either via an SQL statement or via C and is not -destroyed until the table is dropped or the driver handle is released. -Manual destruction is possible via L. - -The following attributes are preserved in the data area and will -evaluated instead of driver globals: - -=over 8 - -=item f_ext - -=item f_dir - -=item f_dir_search - -=item f_lock - -=item f_lockfile - -=item f_encoding - -=item f_schema - -=item col_names - -=item sql_identifier_case - -=back - -The following attributes are preserved in the data area only and -cannot be set globally. - -=over 8 - -=item f_file - -=back - -The following attributes are preserved in the data area only and are -computed when initializing the data area: - -=over 8 - -=item f_fqfn - -=item f_fqbn - -=item f_fqln - -=item table_name - -=back - -For DBD::CSV tables this means, once opened "foo.csv" as table named "foo", -another table named "foo" accessing the file "foo.txt" cannot be opened. -Accessing "foo" will always access the file "foo.csv" in memorized -C, locking C via memorized C. - -You can use L or the C attribute for a specific table -to work around this. - -=item * - -When used with SQL::Statement and temporary tables e.g., - - CREATE TEMP TABLE ... - -the table data processing bypasses DBD::File::Table. No file system -calls will be made and there are no clashes with existing (file based) -tables with the same name. Temporary tables are chosen over file -tables, but they will not covered by C. - -=back - -=head1 AUTHOR - -This module is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -The original author is Jochen Wiedmann. - -=head1 COPYRIGHT AND LICENSE - - Copyright (C) 2009-2013 by H.Merijn Brand & Jens Rehsack - Copyright (C) 2004-2009 by Jeff Zucker - Copyright (C) 1998-2004 by Jochen Wiedmann - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=head1 SEE ALSO - -L, L, L, L, -L, L, and -L - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/File/Developers.pod b/dbLifeLog/DBI-1.641/blib/lib/DBD/File/Developers.pod deleted file mode 100644 index 1c1b21b..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/File/Developers.pod +++ /dev/null @@ -1,665 +0,0 @@ -=head1 NAME - -DBD::File::Developers - Developers documentation for DBD::File - -=head1 SYNOPSIS - - package DBD::myDriver; - - use base qw( DBD::File ); - - sub driver - { - ... - my $drh = $proto->SUPER::driver ($attr); - ... - return $drh->{class}; - } - - sub CLONE { ... } - - package DBD::myDriver::dr; - - @ISA = qw( DBD::File::dr ); - - sub data_sources { ... } - ... - - package DBD::myDriver::db; - - @ISA = qw( DBD::File::db ); - - sub init_valid_attributes { ... } - sub init_default_attributes { ... } - sub set_versions { ... } - sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } - sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } - sub get_myd_versions { ... } - - package DBD::myDriver::st; - - @ISA = qw( DBD::File::st ); - - sub FETCH { ... } - sub STORE { ... } - - package DBD::myDriver::Statement; - - @ISA = qw( DBD::File::Statement ); - - package DBD::myDriver::Table; - - @ISA = qw( DBD::File::Table ); - - my %reset_on_modify = ( - myd_abc => "myd_foo", - myd_mno => "myd_bar", - ); - __PACKAGE__->register_reset_on_modify (\%reset_on_modify); - my %compat_map = ( - abc => 'foo_abc', - xyz => 'foo_xyz', - ); - __PACKAGE__->register_compat_map (\%compat_map); - - sub bootstrap_table_meta { ... } - sub init_table_meta { ... } - sub table_meta_attr_changed { ... } - sub open_data { ... } - - sub fetch_row { ... } - sub push_row { ... } - sub push_names { ... } - - # optimize the SQL engine by add one or more of - sub update_current_row { ... } - # or - sub update_specific_row { ... } - # or - sub update_one_row { ... } - # or - sub insert_new_row { ... } - # or - sub delete_current_row { ... } - # or - sub delete_one_row { ... } - -=head1 DESCRIPTION - -This document describes how DBD developers can write DBD::File based DBI -drivers. It supplements L and L, -which you should read first. - -=head1 CLASSES - -Each DBI driver must provide a package global C method and three -DBI related classes: - -=over 4 - -=item DBD::File::dr - -Driver package, contains the methods DBI calls indirectly via DBI -interface: - - DBI->connect ('DBI:DBM:', undef, undef, {}) - - # invokes - package DBD::DBM::dr; - @DBD::DBM::dr::ISA = qw( DBD::File::dr ); - - sub connect ($$;$$$) - { - ... - } - -Similar for C<< data_sources >> and C<< disconnect_all >>. - -Pure Perl DBI drivers derived from DBD::File do not usually need to -override any of the methods provided through the DBD::XXX::dr package -however if you need additional initialization in the connect method -you may need to. - -=item DBD::File::db - -Contains the methods which are called through DBI database handles -(C<< $dbh >>). e.g., - - $sth = $dbh->prepare ("select * from foo"); - # returns the f_encoding setting for table foo - $dbh->csv_get_meta ("foo", "f_encoding"); - -DBD::File provides the typical methods required here. Developers who -write DBI drivers based on DBD::File need to override the methods C<< -set_versions >> and C<< init_valid_attributes >>. - -=item DBD::File::st - -Contains the methods to deal with prepared statement handles. e.g., - - $sth->execute () or die $sth->errstr; - -=back - -=head2 DBD::File - -This is the main package containing the routines to initialize -DBD::File based DBI drivers. Primarily the C<< DBD::File::driver >> -method is invoked, either directly from DBI when the driver is -initialized or from the derived class. - - package DBD::DBM; - - use base qw( DBD::File ); - - sub driver - { - my ($class, $attr) = @_; - ... - my $drh = $class->SUPER::driver ($attr); - ... - return $drh; - } - -It is not necessary to implement your own driver method as long as -additional initialization (e.g. installing more private driver -methods) is not required. You do not need to call C<< setup_driver >> -as DBD::File takes care of it. - -=head2 DBD::File::dr - -The driver package contains the methods DBI calls indirectly via the DBI -interface (see L). - -DBD::File based DBI drivers usually do not need to implement anything here, -it is enough to do the basic initialization: - - package DBD:XXX::dr; - - @DBD::XXX::dr::ISA = qw (DBD::File::dr); - $DBD::XXX::dr::imp_data_size = 0; - $DBD::XXX::dr::data_sources_attr = undef; - $DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann"; - -=head2 DBD::File::db - -This package defines the database methods, which are called via the DBI -database handle C<< $dbh >>. - -Methods provided by DBD::File: - -=over 4 - -=item ping - -Simply returns the content of the C<< Active >> attribute. Override -when your driver needs more complicated actions here. - -=item prepare - -Prepares a new SQL statement to execute. Returns a statement handle, -C<< $sth >> - instance of the DBD:XXX::st. It is neither required nor -recommended to override this method. - -=item FETCH - -Fetches an attribute of a DBI database object. Private handle attributes -must have a prefix (this is mandatory). If a requested attribute is -detected as a private attribute without a valid prefix, the driver prefix -(written as C<$drv_prefix>) is added. - -The driver prefix is extracted from the attribute name and verified against -C<< $dbh->{$drv_prefix . "valid_attrs"} >> (when it exists). If the -requested attribute value is not listed as a valid attribute, this method -croaks. If the attribute is valid and readonly (listed in C<< $dbh->{ -$drv_prefix . "readonly_attrs" } >> when it exists), a real copy of the -attribute value is returned. So it's not possible to modify -C from outside of DBD::File::db or a derived class. - -=item STORE - -Stores a database private attribute. Private handle attributes must have a -prefix (this is mandatory). If a requested attribute is detected as a private -attribute without a valid prefix, the driver prefix (written as -C<$drv_prefix>) is added. If the database handle has an attribute -C<${drv_prefix}_valid_attrs> - for attribute names which are not listed in -that hash, this method croaks. If the database handle has an attribute -C<${drv_prefix}_readonly_attrs>, only attributes which are not listed there -can be stored (once they are initialized). Trying to overwrite such an -immutable attribute forces this method to croak. - -An example of a valid attributes list can be found in -C<< DBD::File::db::init_valid_attributes >>. - -=item set_versions - -This method sets the attribute C with the version of DBD::File. - -This method is called at the begin of the C phase. - -When overriding this method, do not forget to invoke the superior one. - -=item init_valid_attributes - -This method is called after the database handle is instantiated as the -first attribute initialization. - -C<< DBD::File::db::init_valid_attributes >> initializes the attributes -C and C. - -When overriding this method, do not forget to invoke the superior one, -preferably before doing anything else. Compatibility table attribute -access must be initialized here to allow DBD::File to instantiate the -map tie: - - # for DBD::CSV - $dbh->{csv_meta} = "csv_tables"; - # for DBD::DBM - $dbh->{dbm_meta} = "dbm_tables"; - # for DBD::AnyData - $dbh->{ad_meta} = "ad_tables"; - -=item init_default_attributes - -This method is called after the database handle is instantiated to -initialize the default attributes. - -C<< DBD::File::db::init_default_attributes >> initializes the attributes -C, C, C, C. - -When the derived implementor class provides the attribute to validate -attributes (e.g. C<< $dbh->{dbm_valid_attrs} = {...}; >>) or the attribute -containing the immutable attributes (e.g. -C<< $dbh->{dbm_readonly_attrs} = {...}; >>), the attributes -C, C, C and C -are added (when available) to the list of valid and immutable attributes -(where C is interpreted as the driver prefix). - -If C is set, an attribute with the name in C is -initialized providing restricted read/write access to the meta data of the -tables using C in the first (table) level and -C for the meta attribute level. C -uses C to initialize the second level -tied hash on FETCH/STORE. The C class uses -C to FETCH attribute values and -C to STORE attribute values. This -allows it to map meta attributes for compatibility reasons. - -=item get_single_table_meta - -=item get_file_meta - -Retrieve an attribute from a table's meta information. The method -signature is C<< get_file_meta ($dbh, $table, $attr) >>. This method -is called by the injected db handle method C<< ${drv_prefix}get_meta >>. - -While get_file_meta allows C<$table> or C<$attr> to be a list of tables or -attributes to retrieve, get_single_table_meta allows only one table name -and only one attribute name. A table name of C<'.'> (single dot) is -interpreted as the default table and this will retrieve the appropriate -attribute globally from the dbh. This has the same restrictions as -C<< $dbh->{$attrib} >>. - -get_file_meta allows C<'+'> and C<'*'> as wildcards for table names and -C<$table> being a regular expression matching against the table names -(evaluated without the default table). The table name C<'*'> is -I. The table -name C<'+'> is I (/^[_A-Za-z0-9]+$/). - -The table meta information is retrieved using the get_table_meta and -get_table_meta_attr methods of the table class of the implementation. - -=item set_single_table_meta - -=item set_file_meta - -Sets an attribute in a table's meta information. The method signature is -C<< set_file_meta ($dbh, $table, $attr, $value) >>. This method is called -by the injected db handle method C<< ${drv_prefix}set_meta >>. - -While set_file_meta allows C<$table> to be a list of tables and C<$attr> -to be a hash of several attributes to set, set_single_table_meta allows -only one table name and only one attribute name/value pair. - -The wildcard characters for the table name are the same as for -get_file_meta. - -The table meta information is updated using the get_table_meta and -set_table_meta_attr methods of the table class of the implementation. - -=item clear_file_meta - -Clears all meta information cached about a table. The method signature is -C<< clear_file_meta ($dbh, $table) >>. This method is called -by the injected db handle method C<< ${drv_prefix}clear_meta >>. - -=back - -=head2 DBD::File::st - -Contains the methods to deal with prepared statement handles: - -=over 4 - -=item FETCH - -Fetches statement handle attributes. Supported attributes (for full overview -see L) are C, C, C -and C in case that SQL::Statement is used as SQL execution engine -and a statement is successful prepared. When SQL::Statement has additional -information about a table, those information are returned. Otherwise, the -same defaults as in L are used. - -This method usually requires extending in a derived implementation. -See L or L for some example. - -=back - -=head2 DBD::File::TableSource::FileSystem - -Provides data sources and table information on database driver and database -handle level. - - package DBD::File::TableSource::FileSystem; - - sub data_sources ($;$) - { - my ($class, $drh, $attrs) = @_; - ... - } - - sub avail_tables - { - my ($class, $drh) = @_; - ... - } - -The C method is called when the user invokes any of the -following: - - @ary = DBI->data_sources ($driver); - @ary = DBI->data_sources ($driver, \%attr); - - @ary = $dbh->data_sources (); - @ary = $dbh->data_sources (\%attr); - -The C method is called when the user invokes any of the -following: - - @names = $dbh->tables ($catalog, $schema, $table, $type); - - $sth = $dbh->table_info ($catalog, $schema, $table, $type); - $sth = $dbh->table_info ($catalog, $schema, $table, $type, \%attr); - - $dbh->func ("list_tables"); - -Every time where an C<\%attr> argument can be specified, this C<\%attr> -object's C attribute is preferred over the C<$dbh> -attribute or the driver default. - -=head2 DBD::File::DataSource::Stream - - package DBD::File::DataSource::Stream; - - @DBD::File::DataSource::Stream::ISA = 'DBI::DBD::SqlEngine::DataSource'; - - sub complete_table_name - { - my ($self, $meta, $file, $respect_case) = @_; - ... - } - -Clears all meta attributes identifying a file: C, C and -C. The table name is set according to C<$respect_case> and -C<< $meta->{sql_identifier_case} >> (SQL_IC_LOWER, SQL_IC_UPPER). - - package DBD::File::DataSource::Stream; - - sub apply_encoding - { - my ($self, $meta, $fn) = @_; - ... - } - -Applies the encoding from I (C<< $meta->{f_encoding} >>) -to the file handled opened in C. - - package DBD::File::DataSource::Stream; - - sub open_data - { - my ($self, $meta, $attrs, $flags) = @_; - ... - } - -Opens (C) the file handle provided in C<< $meta->{f_file} >>. - - package DBD::File::DataSource::Stream; - - sub can_flock { ... } - -Returns whether C is available or not (avoids retesting in -subclasses). - -=head2 DBD::File::DataSource::File - - package DBD::File::DataSource::File; - - sub complete_table_name ($$;$) - { - my ($self, $meta, $table, $respect_case) = @_; - ... - } - -The method C tries to map a filename to the associated -table name. It is called with a partially filled meta structure for the -resulting table containing at least the following attributes: -C<< f_ext >>, C<< f_dir >>, C<< f_lockfile >> and C<< sql_identifier_case >>. - -If a file/table map can be found then this method sets the C<< f_fqfn ->>, C<< f_fqbn >>, C<< f_fqln >> and C<< table_name >> attributes in -the meta structure. If a map cannot be found the table name will be -undef. - - package DBD::File::DataSource::File; - - sub open_data ($) - { - my ($self, $meta, $attrs, $flags) = @_; - ... - } - -Depending on the attributes set in the table's meta data, the -following steps are performed. Unless C<< f_dontopen >> is set to a -true value, C<< f_fqfn >> must contain the full qualified file name -for the table to work on (file2table ensures this). The encoding in -C<< f_encoding >> is applied if set and the file is opened. If -C<> (full qualified lock name) is set, this file is opened, -too. Depending on the value in C<< f_lock >>, the appropriate lock is -set on the opened data file or lock file. - -=head2 DBD::File::Statement - -Derives from DBI::SQL::Nano::Statement to provide following method: - -=over 4 - -=item open_table - -Implements the open_table method required by L and -L. All the work for opening the file(s) belonging to the -table is handled and parametrized in DBD::File::Table. Unless you intend -to add anything to the following implementation, an empty DBD::XXX::Statement -package satisfies DBD::File. - - sub open_table ($$$$$) - { - my ($self, $data, $table, $createMode, $lockMode) = @_; - - my $class = ref $self; - $class =~ s/::Statement/::Table/; - - my $flags = { - createMode => $createMode, - lockMode => $lockMode, - }; - $self->{command} eq "DROP" and $flags->{dropMode} = 1; - - return $class->new ($data, { table => $table }, $flags); - } # open_table - -=back - -=head2 DBD::File::Table - -Derives from DBI::SQL::Nano::Table and provides physical file access for -the table data which are stored in the files. - -=over 4 - -=item bootstrap_table_meta - -Initializes a table meta structure. Can be safely overridden in a -derived class, as long as the C<< SUPER >> method is called at the end -of the overridden method. - -It copies the following attributes from the database into the table meta data -C<< f_dir >>, C<< f_ext >>, C<< f_encoding >>, C<< f_lock >>, C<< f_schema >> -and C<< f_lockfile >> and makes them sticky to the table. - -This method should be called before you attempt to map between file -name and table name to ensure the correct directory, extension etc. are -used. - -=item init_table_meta - -Initializes more attributes of the table meta data - usually more -expensive ones (e.g. those which require class instantiations) - when -the file name and the table name could mapped. - -=item get_table_meta - -Returns the table meta data. If there are none for the required -table, a new one is initialized. When it fails, nothing is -returned. On success, the name of the table and the meta data -structure is returned. - -=item get_table_meta_attr - -Returns a single attribute from the table meta data. If the attribute -name appears in C<%compat_map>, the attribute name is updated from -there. - -=item set_table_meta_attr - -Sets a single attribute in the table meta data. If the attribute -name appears in C<%compat_map>, the attribute name is updated from -there. - -=item table_meta_attr_changed - -Called when an attribute of the meta data is modified. - -If the modified attribute requires to reset a calculated attribute, the -calculated attribute is reset (deleted from meta data structure) and -the I flag is removed, too. The decision is made based on -C<%register_reset_on_modify>. - -=item register_reset_on_modify - -Allows C to reset meta attributes when special -attributes are modified. For DBD::File, modifying one of C, C, -C or C will reset C. DBD::DBM extends the -list for C and C to reset the value of C. - -If your DBD has calculated values in the meta data area, then call -C: - - my %reset_on_modify = (xxx_foo => "xxx_bar"); - __PACKAGE__->register_reset_on_modify (\%reset_on_modify); - -=item register_compat_map - -Allows C and C to update the -attribute name to the current favored one: - - # from DBD::DBM - my %compat_map = (dbm_ext => "f_ext"); - __PACKAGE__->register_compat_map (\%compat_map); - -=item open_file - -Called to open the table's data file. - -Depending on the attributes set in the table's meta data, the -following steps are performed. Unless C<< f_dontopen >> is set to a -true value, C<< f_fqfn >> must contain the full qualified file name -for the table to work on (file2table ensures this). The encoding in -C<< f_encoding >> is applied if set and the file is opened. If -C<> (full qualified lock name) is set, this file is opened, -too. Depending on the value in C<< f_lock >>, the appropriate lock is -set on the opened data file or lock file. - -After this is done, a derived class might add more steps in an overridden -C<< open_file >> method. - -=item new - -Instantiates the table. This is done in 3 steps: - - 1. get the table meta data - 2. open the data file - 3. bless the table data structure using inherited constructor new - -It is not recommended to override the constructor of the table class. -Find a reasonable place to add you extensions in one of the above four -methods. - -=item drop - -Implements the abstract table method for the C<< DROP >> -command. Discards table meta data after all files belonging to the -table are closed and unlinked. - -Overriding this method might be reasonable in very rare cases. - -=item seek - -Implements the abstract table method used when accessing the table from the -engine. C<< seek >> is called every time the engine uses dumb algorithms -for iterating over the table content. - -=item truncate - -Implements the abstract table method used when dumb table algorithms -for C<< UPDATE >> or C<< DELETE >> need to truncate the table storage -after the last written row. - -=back - -You should consult the documentation of C<< SQL::Eval::Table >> (see -L) to get more information about the abstract methods of the -table's base class you have to override and a description of the table -meta information expected by the SQL engines. - -=head1 AUTHOR - -The module DBD::File is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -The original author is Jochen Wiedmann. - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2010-2013 by H.Merijn Brand & Jens Rehsack - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/File/HowTo.pod b/dbLifeLog/DBI-1.641/blib/lib/DBD/File/HowTo.pod deleted file mode 100644 index 9531b22..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/File/HowTo.pod +++ /dev/null @@ -1,191 +0,0 @@ -=head1 NAME - -DBD::File::HowTo - Guide to create DBD::File based driver - -=head1 SYNOPSIS - - perldoc DBD::File::HowTo - perldoc DBI - perldoc DBI::DBD - perldoc DBD::File::Developers - perldoc DBI::DBD::SqlEngine::Developers - perldoc DBI::DBD::SqlEngine - perldoc SQL::Eval - perldoc DBI::DBD::SqlEngine::HowTo - perldoc SQL::Statement::Embed - perldoc DBD::File - perldoc DBD::File::HowTo - perldoc DBD::File::Developers - -=head1 DESCRIPTION - -This document provides a step-by-step guide, how to create a new -C based DBD. It expects that you carefully read the L -documentation and that you're familiar with L and had read and -understood L. - -This document addresses experienced developers who are really sure that -they need to invest time when writing a new DBI Driver. Writing a DBI -Driver is neither a weekend project nor an easy job for hobby coders -after work. Expect one or two man-month of time for the first start. - -Those who are still reading, should be able to sing the rules of -L. - -Of course, DBD::File is a DBI::DBD::SqlEngine and you surely read -L before continuing here. - -=head1 CREATING DRIVER CLASSES - -Do you have an entry in DBI's DBD registry? For this guide, a prefix of -C is assumed. - -=head2 Sample Skeleton - - package DBD::Foo; - - use strict; - use warnings; - use vars qw(@ISA $VERSION); - use base qw(DBD::File); - - use DBI (); - - $VERSION = "0.001"; - - package DBD::Foo::dr; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBD::File::dr); - $imp_data_size = 0; - - package DBD::Foo::db; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBD::File::db); - $imp_data_size = 0; - - package DBD::Foo::st; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBD::File::st); - $imp_data_size = 0; - - package DBD::Foo::Statement; - - use vars qw(@ISA); - - @ISA = qw(DBD::File::Statement); - - package DBD::Foo::Table; - - use vars qw(@ISA); - - @ISA = qw(DBD::File::Table); - - 1; - -Tiny, eh? And all you have now is a DBD named foo which will is able to -deal with temporary tables, as long as you use L. In -L environments, this DBD can do nothing. - -=head2 Start over - -Based on L, we're now having a driver which -could do basic things. Of course, it should now derive from DBD::File -instead of DBI::DBD::SqlEngine, shouldn't it? - -DBD::File extends DBI::DBD::SqlEngine to deal with any kind of files. -In principle, the only extensions required are to the table class: - - package DBD::Foo::Table; - - sub bootstrap_table_meta - { - my ( $self, $dbh, $meta, $table ) = @_; - - # initialize all $meta attributes which might be relevant for - # file2table - - return $self->SUPER::bootstrap_table_meta($dbh, $meta, $table); - } - - sub init_table_meta - { - my ( $self, $dbh, $meta, $table ) = @_; - - # called after $meta contains the results from file2table - # initialize all missing $meta attributes - - $self->SUPER::init_table_meta( $dbh, $meta, $table ); - } - -In case C doesn't open the files as the driver -needs that, override it! - - sub open_file - { - my ( $self, $meta, $attrs, $flags ) = @_; - # ensure that $meta->{f_dontopen} is set - $self->SUPER::open_file( $meta, $attrs, $flags ); - # now do what ever needs to be done - } - -Combined with the methods implemented using the L -guide, the table is full working and you could try a start over. - -=head2 User comfort - -C since C<0.39> consolidates all persistent meta data of a table -into a single structure stored in C<< $dbh->{f_meta} >>. With C -version C<0.41> and C version C<0.05>, this -consolidation moves to L. It's still the -C<< $dbh->{$drv_prefix . "_meta"} >> attribute which cares, so what you -learned at this place before, is still valid. - - sub init_valid_attributes - { - my $dbh = $_[0]; - - $dbh->SUPER::init_valid_attributes (); - - $dbh->{foo_valid_attrs} = { ... }; - $dbh->{foo_readonly_attrs} = { ... }; - - $dbh->{foo_meta} = "foo_tables"; - - return $dbh; - } - -See updates at L. - -=head2 Testing - -Now you should have your own DBD::File based driver. Was easy, wasn't it? -But does it work well? Prove it by writing tests and remember to use -dbd_edit_mm_attribs from L to ensure testing even rare cases. - -=head1 AUTHOR - -This guide is written by Jens Rehsack. DBD::File is written by Jochen -Wiedmann and Jeff Zucker. - -The module DBD::File is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/File/Roadmap.pod b/dbLifeLog/DBI-1.641/blib/lib/DBD/File/Roadmap.pod deleted file mode 100644 index ec91712..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/File/Roadmap.pod +++ /dev/null @@ -1,176 +0,0 @@ -=head1 NAME - -DBD::File::Roadmap - Planned Enhancements for DBD::File and pure Perl DBD's - -Jens Rehsack - May 2010 - -=head1 SYNOPSIS - -This document gives a high level overview of the future of the DBD::File DBI -driver and groundwork for pure Perl DBI drivers. - -The planned enhancements cover features, testing, performance, reliability, -extensibility and more. - -=head1 CHANGES AND ENHANCEMENTS - -=head2 Features - -There are some features missing we would like to add, but there is -no time plan: - -=over 4 - -=item LOCK TABLE - -The newly implemented internal common table meta storage area would allow -us to implement LOCK TABLE support based on file system C -support. - -=item Transaction support - -While DBD::AnyData recommends explicitly committing by importing and -exporting tables, DBD::File might be enhanced in a future version to allow -transparent transactions using the temporary tables of SQL::Statement as -shadow (dirty) tables. - -Transaction support will heavily rely on lock table support. - -=item Data Dictionary Persistence - -SQL::Statement provides dictionary information when a "CREATE TABLE ..." -statement is executed. This dictionary is preserved for some statement -handle attribute fetches (as C or C). - -It is planned to extend DBD::File to support data dictionaries to work -on the tables in it. It is not planned to support one table in different -dictionaries, but you can have several dictionaries in one directory. - -=item SQL Engine selecting on connect - -Currently the SQL engine selected is chosen during the loading of the module -L. Ideally end users should be able to select the engine -used in C<< DBI->connect () >> with a special DBD::File attribute. - -=back - -Other points of view to the planned features (and more features for the -SQL::Statement engine) are shown in L. - -=head2 Testing - -DBD::File and the dependent DBD::DBM requires a lot more automated tests -covering API stability and compatibility with optional modules -like SQL::Statement. - -=head2 Performance - -Several arguments for support of features like indexes on columns -and cursors are made for DBD::CSV (which is a DBD::File based driver, -too). Similar arguments could be made for DBD::DBM, DBD::AnyData, -DBD::RAM or DBD::PO etc. - -To improve the performance of the underlying SQL engines, a clean -re-implementation seems to be required. Currently both engines are -prematurely optimized and therefore it is not trivial to provide -further optimization without the risk of breaking existing features. - -Join the DBI developers IRC channel at L to -participate or post to the DBI Developers Mailing List. - -=head2 Reliability - -DBD::File currently lacks the following points: - -=over 4 - -=item duplicate table names - -It is currently possible to access a table quoted with a relative path -(a) and additionally using an absolute path (b). If (a) and (b) are -the same file that is not recognized (except for -flock protection handled by the Operating System) and two independent -tables are handled. - -=item invalid table names - -The current implementation does not prevent someone choosing a -directory name as a physical file name for the table to open. - -=back - -=head2 Extensibility - -I (Jens Rehsack) have some (partially for example only) DBD's in mind: - -=over 4 - -=item DBD::Sys - -Derive DBD::Sys from a common code base shared with DBD::File which handles -all the emulation DBI needs (as getinfo, SQL engine handling, ...) - -=item DBD::Dir - -Provide a DBD::File derived to work with fixed table definitions through the -file system to demonstrate how DBI / Pure Perl DBDs could handle databases -with hierarchical structures. - -=item DBD::Join - -Provide a DBI driver which is able to manage multiple connections to other -Databases (as DBD::Multiplex), but allow them to point to different data -sources and allow joins between the tables of them: - - # Example - # Let table 'lsof' being a table in DBD::Sys giving a list of open files using lsof utility - # Let table 'dir' being a atable from DBD::Dir - $sth = $dbh->prepare( "select * from dir,lsof where path='/documents' and dir.entry = lsof.filename" ) - $sth->execute(); # gives all open files in '/documents' - ... - - # Let table 'filesys' a DBD::Sys table of known file systems on current host - # Let table 'applications' a table of your Configuration Management Database - # where current applications (relocatable, with mountpoints for filesystems) - # are stored - $sth = dbh->prepare( "select * from applications,filesys where " . - "application.mountpoint = filesys.mountpoint and ". - "filesys.mounted is true" ); - $sth->execute(); # gives all currently mounted applications on this host - -=back - -=head1 PRIORITIES - -Our priorities are focused on current issues. Initially many new test -cases for DBD::File and DBD::DBM should be added to the DBI test -suite. After that some additional documentation on how to use the -DBD::File API will be provided. - -Any additional priorities will come later and can be modified by (paying) -users. - -=head1 RESOURCES AND CONTRIBUTIONS - -See L for I. - -If your company has benefited from DBI, please consider if -it could make a donation to The Perl Foundation "DBI Development" -fund at L to secure future development. - -Alternatively, if your company would benefit from a specific new -DBI feature, please consider sponsoring it's development through -the options listed in the section "Commercial Support from the Author" -on L. - -Using such targeted financing allows you to contribute to DBI -development and rapidly get something specific and directly valuable -to you in return. - -My company also offers annual support contracts for the DBI, which -provide another way to support the DBI and get something specific -in return. Contact me for details. - -Thank you. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer.pm deleted file mode 100644 index 681ed02..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer.pm +++ /dev/null @@ -1,1292 +0,0 @@ -{ - package DBD::Gofer; - - use strict; - - require DBI; - require DBI::Gofer::Request; - require DBI::Gofer::Response; - require Carp; - - our $VERSION = "0.015327"; - -# $Id: Gofer.pm 15326 2012-06-06 16:32:38Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - - - # attributes we'll allow local STORE - our %xxh_local_store_attrib = map { $_=>1 } qw( - Active - CachedKids - Callbacks - DbTypeSubclass - ErrCount Executed - FetchHashKeyName - HandleError HandleSetErr - InactiveDestroy - AutoInactiveDestroy - PrintError PrintWarn - Profile - RaiseError - RootClass - ShowErrorStatement - Taint TaintIn TaintOut - TraceLevel - Warn - dbi_quote_identifier_cache - dbi_connect_closure - dbi_go_execute_unique - ); - our %xxh_local_store_attrib_if_same_value = map { $_=>1 } qw( - Username - dbi_connect_method - ); - - our $drh = undef; # holds driver handle once initialized - our $methods_already_installed; - - sub driver{ - return $drh if $drh; - - DBI->setup_driver('DBD::Gofer'); - - unless ($methods_already_installed++) { - my $opts = { O=> 0x0004 }; # IMA_KEEP_ERR - DBD::Gofer::db->install_method('go_dbh_method', $opts); - DBD::Gofer::st->install_method('go_sth_method', $opts); - DBD::Gofer::st->install_method('go_clone_sth', $opts); - DBD::Gofer::db->install_method('go_cache', $opts); - DBD::Gofer::st->install_method('go_cache', $opts); - } - - my($class, $attr) = @_; - $class .= "::dr"; - ($drh) = DBI::_new_drh($class, { - 'Name' => 'Gofer', - 'Version' => $VERSION, - 'Attribution' => 'DBD Gofer by Tim Bunce', - }); - - $drh; - } - - - sub CLONE { - undef $drh; - } - - - sub go_cache { - my $h = shift; - $h->{go_cache} = shift if @_; - # return handle's override go_cache, if it has one - return $h->{go_cache} if defined $h->{go_cache}; - # or else the transports default go_cache - return $h->{go_transport}->{go_cache}; - } - - - sub set_err_from_response { # set error/warn/info and propagate warnings - my $h = shift; - my $response = shift; - if (my $warnings = $response->warnings) { - warn $_ for @$warnings; - } - my ($err, $errstr, $state) = $response->err_errstr_state; - # Only set_err() if there's an error else leave the current values - # (The current values will normally be set undef by the DBI dispatcher - # except for methods marked KEEPERR such as ping.) - $h->set_err($err, $errstr, $state) if defined $err; - return undef; - } - - - sub install_methods_proxy { - my ($installed_methods) = @_; - while ( my ($full_method, $attr) = each %$installed_methods ) { - # need to install both a DBI dispatch stub and a proxy stub - # (the dispatch stub may be already here due to local driver use) - - DBI->_install_method($full_method, "", $attr||{}) - unless defined &{$full_method}; - - # now install proxy stubs on the driver side - $full_method =~ m/^DBI::(\w\w)::(\w+)$/ - or die "Invalid method name '$full_method' for install_method"; - my ($type, $method) = ($1, $2); - my $driver_method = "DBD::Gofer::${type}::${method}"; - next if defined &{$driver_method}; - my $sub; - if ($type eq 'db') { - $sub = sub { return shift->go_dbh_method(undef, $method, @_) }; - } - else { - $sub = sub { shift->set_err($DBI::stderr, "Can't call \$${type}h->$method when using DBD::Gofer"); return; }; - } - no strict 'refs'; - *$driver_method = $sub; - } - } -} - - -{ package DBD::Gofer::dr; # ====== DRIVER ====== - - $imp_data_size = 0; - use strict; - - sub connect_cached { - my ($drh, $dsn, $user, $auth, $attr)= @_; - $attr ||= {}; - return $drh->SUPER::connect_cached($dsn, $user, $auth, { - (%$attr), - go_connect_method => $attr->{go_connect_method} || 'connect_cached', - }); - } - - - sub connect { - my($drh, $dsn, $user, $auth, $attr)= @_; - my $orig_dsn = $dsn; - - # first remove dsn= and everything after it - my $remote_dsn = ($dsn =~ s/;?\bdsn=(.*)$// && $1) - or return $drh->set_err($DBI::stderr, "No dsn= argument in '$orig_dsn'"); - - if ($attr->{go_bypass}) { # don't use DBD::Gofer for this connection - # useful for testing with DBI_AUTOPROXY, e.g., t/03handle.t - return DBI->connect($remote_dsn, $user, $auth, $attr); - } - - my %go_attr; - # extract any go_ attributes from the connect() attr arg - for my $k (grep { /^go_/ } keys %$attr) { - $go_attr{$k} = delete $attr->{$k}; - } - # then override those with any attributes embedded in our dsn (not remote_dsn) - for my $kv (grep /=/, split /;/, $dsn, -1) { - my ($k, $v) = split /=/, $kv, 2; - $go_attr{ "go_$k" } = $v; - } - - if (not ref $go_attr{go_policy}) { # if not a policy object already - my $policy_class = $go_attr{go_policy} || 'classic'; - $policy_class = "DBD::Gofer::Policy::$policy_class" - unless $policy_class =~ /::/; - _load_class($policy_class) - or return $drh->set_err($DBI::stderr, "Can't load $policy_class: $@"); - # replace policy name in %go_attr with policy object - $go_attr{go_policy} = eval { $policy_class->new(\%go_attr) } - or return $drh->set_err($DBI::stderr, "Can't instanciate $policy_class: $@"); - } - # policy object is left in $go_attr{go_policy} so transport can see it - my $go_policy = $go_attr{go_policy}; - - if ($go_attr{go_cache} and not ref $go_attr{go_cache}) { # if not a cache object already - my $cache_class = $go_attr{go_cache}; - $cache_class = "DBI::Util::CacheMemory" if $cache_class eq '1'; - _load_class($cache_class) - or return $drh->set_err($DBI::stderr, "Can't load $cache_class $@"); - $go_attr{go_cache} = eval { $cache_class->new() } - or $drh->set_err(0, "Can't instanciate $cache_class: $@"); # warning - } - - # delete any other attributes that don't apply to transport - my $go_connect_method = delete $go_attr{go_connect_method}; - - my $transport_class = delete $go_attr{go_transport} - or return $drh->set_err($DBI::stderr, "No transport= argument in '$orig_dsn'"); - $transport_class = "DBD::Gofer::Transport::$transport_class" - unless $transport_class =~ /::/; - _load_class($transport_class) - or return $drh->set_err($DBI::stderr, "Can't load $transport_class: $@"); - my $go_transport = eval { $transport_class->new(\%go_attr) } - or return $drh->set_err($DBI::stderr, "Can't instanciate $transport_class: $@"); - - my $request_class = "DBI::Gofer::Request"; - my $go_request = eval { - my $go_attr = { %$attr }; - # XXX user/pass of fwd server vs db server ? also impact of autoproxy - if ($user) { - $go_attr->{Username} = $user; - $go_attr->{Password} = $auth; - } - # delete any attributes we can't serialize (or don't want to) - delete @{$go_attr}{qw(Profile HandleError HandleSetErr Callbacks)}; - # delete any attributes that should only apply to the client-side - delete @{$go_attr}{qw(RootClass DbTypeSubclass)}; - - $go_connect_method ||= $go_policy->connect_method($remote_dsn, $go_attr) || 'connect'; - $request_class->new({ - dbh_connect_call => [ $go_connect_method, $remote_dsn, $user, $auth, $go_attr ], - }) - } or return $drh->set_err($DBI::stderr, "Can't instanciate $request_class: $@"); - - my ($dbh, $dbh_inner) = DBI::_new_dbh($drh, { - 'Name' => $dsn, - 'USER' => $user, - go_transport => $go_transport, - go_request => $go_request, - go_policy => $go_policy, - }); - - # mark as inactive temporarily for STORE. Active not set until connected() called. - $dbh->STORE(Active => 0); - - # should we ping to check the connection - # and fetch dbh attributes - my $skip_connect_check = $go_policy->skip_connect_check($attr, $dbh); - if (not $skip_connect_check) { - if (not $dbh->go_dbh_method(undef, 'ping')) { - return undef if $dbh->err; # error already recorded, typically - return $dbh->set_err($DBI::stderr, "ping failed"); - } - } - - return $dbh; - } - - sub _load_class { # return true or false+$@ - my $class = shift; - (my $pm = $class) =~ s{::}{/}g; - $pm .= ".pm"; - return 1 if eval { require $pm }; - delete $INC{$pm}; # shouldn't be needed (perl bug?) and assigning undef isn't enough - undef; # error in $@ - } - -} - - -{ package DBD::Gofer::db; # ====== DATABASE ====== - $imp_data_size = 0; - use strict; - use Carp qw(carp croak); - - my %dbh_local_store_attrib = %DBD::Gofer::xxh_local_store_attrib; - - sub connected { - shift->STORE(Active => 1); - } - - sub go_dbh_method { - my $dbh = shift; - my $meta = shift; - # @_ now contains ($method_name, @args) - - my $request = $dbh->{go_request}; - $request->init_request([ wantarray, @_ ], $dbh); - ++$dbh->{go_request_count}; - - my $go_policy = $dbh->{go_policy}; - my $dbh_attribute_update = $go_policy->dbh_attribute_update(); - $request->dbh_attributes( $go_policy->dbh_attribute_list() ) - if $dbh_attribute_update eq 'every' - or $dbh->{go_request_count}==1; - - $request->dbh_last_insert_id_args($meta->{go_last_insert_id_args}) - if $meta->{go_last_insert_id_args}; - - my $transport = $dbh->{go_transport} - or return $dbh->set_err($DBI::stderr, "Not connected (no transport)"); - - local $transport->{go_cache} = $dbh->{go_cache} - if defined $dbh->{go_cache}; - - my ($response, $retransmit_sub) = $transport->transmit_request($request); - $response ||= $transport->receive_response($request, $retransmit_sub); - $dbh->{go_response} = $response - or die "No response object returned by $transport"; - - die "response '$response' returned by $transport is not a response object" - unless UNIVERSAL::isa($response,"DBI::Gofer::Response"); - - if (my $dbh_attributes = $response->dbh_attributes) { - - # XXX installed_methods piggybacks on dbh_attributes for now - if (my $installed_methods = delete $dbh_attributes->{dbi_installed_methods}) { - DBD::Gofer::install_methods_proxy($installed_methods) - if $dbh->{go_request_count}==1; - } - - # XXX we don't STORE here, we just stuff the value into the attribute cache - $dbh->{$_} = $dbh_attributes->{$_} - for keys %$dbh_attributes; - } - - my $rv = $response->rv; - if (my $resultset_list = $response->sth_resultsets) { - # dbh method call returned one or more resultsets - # (was probably a metadata method like table_info) - # - # setup an sth but don't execute/forward it - my $sth = $dbh->prepare(undef, { go_skip_prepare_check => 1 }); - # set the sth response to our dbh response - (tied %$sth)->{go_response} = $response; - # setup the sth with the results in our response - $sth->more_results; - # and return that new sth as if it came from original request - $rv = [ $sth ]; - } - elsif (!$rv) { # should only occur for major transport-level error - #carp("no rv in response { @{[ %$response ]} }"); - $rv = [ ]; - } - - DBD::Gofer::set_err_from_response($dbh, $response); - - return (wantarray) ? @$rv : $rv->[0]; - } - - - # Methods that should be forwarded but can be cached - for my $method (qw( - tables table_info column_info primary_key_info foreign_key_info statistics_info - data_sources type_info_all get_info - parse_trace_flags parse_trace_flag - func - )) { - my $policy_name = "cache_$method"; - my $super_name = "SUPER::$method"; - my $sub = sub { - my $dbh = shift; - my $rv; - - # if we know the remote side doesn't override the DBI's default method - # then we might as well just call the DBI's default method on the client - # (which may, in turn, call other methods that are forwarded, like get_info) - if ($dbh->{dbi_default_methods}{$method} && $dbh->{go_policy}->skip_default_methods()) { - $dbh->trace_msg(" !! $method: using local default as remote method is also default\n"); - return $dbh->$super_name(@_); - } - - my $cache; - my $cache_key; - if (my $cache_it = $dbh->{go_policy}->$policy_name(undef, $dbh, @_)) { - $cache = $dbh->{go_meta_cache} ||= {}; # keep separate from go_cache - $cache_key = sprintf "%s_wa%d(%s)", $policy_name, wantarray||0, - join(",\t", map { # XXX basic but sufficient for now - !ref($_) ? DBI::neat($_,1e6) - : ref($_) eq 'ARRAY' ? DBI::neat_list($_,1e6,",\001") - : ref($_) eq 'HASH' ? do { my @k = sort keys %$_; DBI::neat_list([@k,@{$_}{@k}],1e6,",\002") } - : do { warn "unhandled argument type ($_)"; $_ } - } @_); - if ($rv = $cache->{$cache_key}) { - $dbh->trace_msg("$method(@_) returning previously cached value ($cache_key)\n",4); - my @cache_rv = @$rv; - # if it's an sth we have to clone it - $cache_rv[0] = $cache_rv[0]->go_clone_sth if UNIVERSAL::isa($cache_rv[0],'DBI::st'); - return (wantarray) ? @cache_rv : $cache_rv[0]; - } - } - - $rv = [ (wantarray) - ? ($dbh->go_dbh_method(undef, $method, @_)) - : scalar $dbh->go_dbh_method(undef, $method, @_) - ]; - - if ($cache) { - $dbh->trace_msg("$method(@_) caching return value ($cache_key)\n",4); - my @cache_rv = @$rv; - # if it's an sth we have to clone it - #$cache_rv[0] = $cache_rv[0]->go_clone_sth - # if UNIVERSAL::isa($cache_rv[0],'DBI::st'); - $cache->{$cache_key} = \@cache_rv - unless UNIVERSAL::isa($cache_rv[0],'DBI::st'); # XXX cloning sth not yet done - } - - return (wantarray) ? @$rv : $rv->[0]; - }; - no strict 'refs'; - *$method = $sub; - } - - - # Methods that can use the DBI defaults for some situations/drivers - for my $method (qw( - quote quote_identifier - )) { # XXX keep DBD::Gofer::Policy::Base in sync - my $policy_name = "locally_$method"; - my $super_name = "SUPER::$method"; - my $sub = sub { - my $dbh = shift; - - # if we know the remote side doesn't override the DBI's default method - # then we might as well just call the DBI's default method on the client - # (which may, in turn, call other methods that are forwarded, like get_info) - if ($dbh->{dbi_default_methods}{$method} && $dbh->{go_policy}->skip_default_methods()) { - $dbh->trace_msg(" !! $method: using local default as remote method is also default\n"); - return $dbh->$super_name(@_); - } - - # false: use remote gofer - # 1: use local DBI default method - # code ref: use the code ref - my $locally = $dbh->{go_policy}->$policy_name($dbh, @_); - if ($locally) { - return $locally->($dbh, @_) if ref $locally eq 'CODE'; - return $dbh->$super_name(@_); - } - return $dbh->go_dbh_method(undef, $method, @_); # propagate context - }; - no strict 'refs'; - *$method = $sub; - } - - - # Methods that should always fail - for my $method (qw( - begin_work commit rollback - )) { - no strict 'refs'; - *$method = sub { return shift->set_err($DBI::stderr, "$method not available with DBD::Gofer") } - } - - - sub do { - my ($dbh, $sql, $attr, @args) = @_; - delete $dbh->{Statement}; # avoid "Modification of non-creatable hash value attempted" - $dbh->{Statement} = $sql; # for profiling and ShowErrorStatement - my $meta = { go_last_insert_id_args => $attr->{go_last_insert_id_args} }; - return $dbh->go_dbh_method($meta, 'do', $sql, $attr, @args); - } - - sub ping { - my $dbh = shift; - return $dbh->set_err('', "can't ping while not connected") # info - unless $dbh->SUPER::FETCH('Active'); - my $skip_ping = $dbh->{go_policy}->skip_ping(); - return ($skip_ping) ? 1 : $dbh->go_dbh_method(undef, 'ping', @_); - } - - sub last_insert_id { - my $dbh = shift; - my $response = $dbh->{go_response} or return undef; - return $response->last_insert_id; - } - - sub FETCH { - my ($dbh, $attrib) = @_; - - # FETCH is effectively already cached because the DBI checks the - # attribute cache in the handle before calling FETCH - # and this FETCH copies the value into the attribute cache - - # forward driver-private attributes (except ours) - if ($attrib =~ m/^[a-z]/ && $attrib !~ /^go_/) { - my $value = $dbh->go_dbh_method(undef, 'FETCH', $attrib); - $dbh->{$attrib} = $value; # XXX forces caching by DBI - return $dbh->{$attrib} = $value; - } - - # else pass up to DBI to handle - return $dbh->SUPER::FETCH($attrib); - } - - sub STORE { - my ($dbh, $attrib, $value) = @_; - if ($attrib eq 'AutoCommit') { - croak "Can't enable transactions when using DBD::Gofer" if !$value; - return $dbh->SUPER::STORE($attrib => ($value) ? -901 : -900); - } - return $dbh->SUPER::STORE($attrib => $value) - # we handle this attribute locally - if $dbh_local_store_attrib{$attrib} - # or it's a private_ (application) attribute - or $attrib =~ /^private_/ - # or not yet connected (ie being called by DBI->connect) - or not $dbh->FETCH('Active'); - - return $dbh->SUPER::STORE($attrib => $value) - if $DBD::Gofer::xxh_local_store_attrib_if_same_value{$attrib} - && do { # values are the same - my $crnt = $dbh->FETCH($attrib); - local $^W; - (defined($value) ^ defined($crnt)) - ? 0 # definedness differs - : $value eq $crnt; - }; - - # dbh attributes are set at connect-time - see connect() - carp("Can't alter \$dbh->{$attrib} after handle created with DBD::Gofer") if $dbh->FETCH('Warn'); - return $dbh->set_err($DBI::stderr, "Can't alter \$dbh->{$attrib} after handle created with DBD::Gofer"); - } - - sub disconnect { - my $dbh = shift; - $dbh->{go_transport} = undef; - $dbh->STORE(Active => 0); - } - - sub prepare { - my ($dbh, $statement, $attr)= @_; - - return $dbh->set_err($DBI::stderr, "Can't prepare when disconnected") - unless $dbh->FETCH('Active'); - - $attr = { %$attr } if $attr; # copy so we can edit - - my $policy = delete($attr->{go_policy}) || $dbh->{go_policy}; - my $lii_args = delete $attr->{go_last_insert_id_args}; - my $go_prepare = delete($attr->{go_prepare_method}) - || $dbh->{go_prepare_method} - || $policy->prepare_method($dbh, $statement, $attr) - || 'prepare'; # e.g. for code not using placeholders - my $go_cache = delete $attr->{go_cache}; - # set to undef if there are no attributes left for the actual prepare call - $attr = undef if $attr and not %$attr; - - my ($sth, $sth_inner) = DBI::_new_sth($dbh, { - Statement => $statement, - go_prepare_call => [ 0, $go_prepare, $statement, $attr ], - # go_method_calls => [], # autovivs if needed - go_request => $dbh->{go_request}, - go_transport => $dbh->{go_transport}, - go_policy => $policy, - go_last_insert_id_args => $lii_args, - go_cache => $go_cache, - }); - $sth->STORE(Active => 0); # XXX needed? It should be the default - - my $skip_prepare_check = $policy->skip_prepare_check($attr, $dbh, $statement, $attr, $sth); - if (not $skip_prepare_check) { - $sth->go_sth_method() or return undef; - } - - return $sth; - } - - sub prepare_cached { - my ($dbh, $sql, $attr, $if_active)= @_; - $attr ||= {}; - return $dbh->SUPER::prepare_cached($sql, { - %$attr, - go_prepare_method => $attr->{go_prepare_method} || 'prepare_cached', - }, $if_active); - } - - *go_cache = \&DBD::Gofer::go_cache; -} - - -{ package DBD::Gofer::st; # ====== STATEMENT ====== - $imp_data_size = 0; - use strict; - - my %sth_local_store_attrib = (%DBD::Gofer::xxh_local_store_attrib, NUM_OF_FIELDS => 1); - - sub go_sth_method { - my ($sth, $meta) = @_; - - if (my $ParamValues = $sth->{ParamValues}) { - my $ParamAttr = $sth->{ParamAttr}; - # XXX the sort here is a hack to work around a DBD::Sybase bug - # but only works properly for params 1..9 - # (reverse because of the unshift) - my @params = reverse sort keys %$ParamValues; - if (@params > 9 && ($sth->{Database}{go_dsn}||'') =~ /dbi:Sybase/) { - # if more than 9 then we need to do a proper numeric sort - # also warn to alert user of this issue - warn "Sybase param binding order hack in use"; - @params = sort { $b <=> $a } @params; - } - for my $p (@params) { - # unshift to put binds before execute call - unshift @{ $sth->{go_method_calls} }, - [ 'bind_param', $p, $ParamValues->{$p}, $ParamAttr->{$p} ]; - } - } - - my $dbh = $sth->{Database} or die "panic"; - ++$dbh->{go_request_count}; - - my $request = $sth->{go_request}; - $request->init_request($sth->{go_prepare_call}, $sth); - $request->sth_method_calls(delete $sth->{go_method_calls}) - if $sth->{go_method_calls}; - $request->sth_result_attr({}); # (currently) also indicates this is an sth request - - $request->dbh_last_insert_id_args($meta->{go_last_insert_id_args}) - if $meta->{go_last_insert_id_args}; - - my $go_policy = $sth->{go_policy}; - my $dbh_attribute_update = $go_policy->dbh_attribute_update(); - $request->dbh_attributes( $go_policy->dbh_attribute_list() ) - if $dbh_attribute_update eq 'every' - or $dbh->{go_request_count}==1; - - my $transport = $sth->{go_transport} - or return $sth->set_err($DBI::stderr, "Not connected (no transport)"); - - local $transport->{go_cache} = $sth->{go_cache} - if defined $sth->{go_cache}; - - my ($response, $retransmit_sub) = $transport->transmit_request($request); - $response ||= $transport->receive_response($request, $retransmit_sub); - $sth->{go_response} = $response - or die "No response object returned by $transport"; - $dbh->{go_response} = $response; # mainly for last_insert_id - - if (my $dbh_attributes = $response->dbh_attributes) { - # XXX we don't STORE here, we just stuff the value into the attribute cache - $dbh->{$_} = $dbh_attributes->{$_} - for keys %$dbh_attributes; - # record the values returned, so we know that we have fetched - # values are which we have fetched (see dbh->FETCH method) - $dbh->{go_dbh_attributes_fetched} = $dbh_attributes; - } - - my $rv = $response->rv; # may be undef on error - if ($response->sth_resultsets) { - # setup first resultset - including sth attributes - $sth->more_results; - } - else { - $sth->STORE(Active => 0); - $sth->{go_rows} = $rv; - } - # set error/warn/info (after more_results as that'll clear err) - DBD::Gofer::set_err_from_response($sth, $response); - - return $rv; - } - - - sub bind_param { - my ($sth, $param, $value, $attr) = @_; - $sth->{ParamValues}{$param} = $value; - $sth->{ParamAttr}{$param} = $attr - if defined $attr; # attr is sticky if not explicitly set - return 1; - } - - - sub execute { - my $sth = shift; - $sth->bind_param($_, $_[$_-1]) for (1..@_); - push @{ $sth->{go_method_calls} }, [ 'execute' ]; - my $meta = { go_last_insert_id_args => $sth->{go_last_insert_id_args} }; - return $sth->go_sth_method($meta); - } - - - sub more_results { - my $sth = shift; - - $sth->finish; - - my $response = $sth->{go_response} or do { - # e.g., we haven't sent a request yet (ie prepare then more_results) - $sth->trace_msg(" No response object present", 3); - return; - }; - - my $resultset_list = $response->sth_resultsets - or return $sth->set_err($DBI::stderr, "No sth_resultsets"); - - my $meta = shift @$resultset_list - or return undef; # no more result sets - #warn "more_results: ".Data::Dumper::Dumper($meta); - - # pull out the special non-attributes first - my ($rowset, $err, $errstr, $state) - = delete @{$meta}{qw(rowset err errstr state)}; - - # copy meta attributes into attribute cache - my $NUM_OF_FIELDS = delete $meta->{NUM_OF_FIELDS}; - $sth->STORE('NUM_OF_FIELDS', $NUM_OF_FIELDS); - # XXX need to use STORE for some? - $sth->{$_} = $meta->{$_} for keys %$meta; - - if (($NUM_OF_FIELDS||0) > 0) { - $sth->{go_rows} = ($rowset) ? @$rowset : -1; - $sth->{go_current_rowset} = $rowset; - $sth->{go_current_rowset_err} = [ $err, $errstr, $state ] - if defined $err; - $sth->STORE(Active => 1) if $rowset; - } - - return $sth; - } - - - sub go_clone_sth { - my ($sth1) = @_; - # clone an (un-fetched-from) sth - effectively undoes the initial more_results - # not 100% so just for use in caching returned sth e.g. table_info - my $sth2 = $sth1->{Database}->prepare($sth1->{Statement}, { go_skip_prepare_check => 1 }); - $sth2->STORE($_, $sth1->{$_}) for qw(NUM_OF_FIELDS Active); - my $sth2_inner = tied %$sth2; - $sth2_inner->{$_} = $sth1->{$_} for qw(NUM_OF_PARAMS FetchHashKeyName); - die "not fully implemented yet"; - return $sth2; - } - - - sub fetchrow_arrayref { - my ($sth) = @_; - my $resultset = $sth->{go_current_rowset} || do { - # should only happen if fetch called after execute failed - my $rowset_err = $sth->{go_current_rowset_err} - || [ 1, 'no result set (did execute fail)' ]; - return $sth->set_err( @$rowset_err ); - }; - return $sth->_set_fbav(shift @$resultset) if @$resultset; - $sth->finish; # no more data so finish - return undef; - } - *fetch = \&fetchrow_arrayref; # alias - - - sub fetchall_arrayref { - my ($sth, $slice, $max_rows) = @_; - my $resultset = $sth->{go_current_rowset} || do { - # should only happen if fetch called after execute failed - my $rowset_err = $sth->{go_current_rowset_err} - || [ 1, 'no result set (did execute fail)' ]; - return $sth->set_err( @$rowset_err ); - }; - my $mode = ref($slice) || 'ARRAY'; - return $sth->SUPER::fetchall_arrayref($slice, $max_rows) - if ref($slice) or defined $max_rows; - $sth->finish; # no more data after this so finish - return $resultset; - } - - - sub rows { - return shift->{go_rows}; - } - - - sub STORE { - my ($sth, $attrib, $value) = @_; - - return $sth->SUPER::STORE($attrib => $value) - if $sth_local_store_attrib{$attrib} # handle locally - # or it's a private_ (application) attribute - or $attrib =~ /^private_/; - - # otherwise warn but do it anyway - # this will probably need refining later - my $msg = "Altering \$sth->{$attrib} won't affect proxied handle"; - Carp::carp($msg) if $sth->FETCH('Warn'); - - # XXX could perhaps do - # push @{ $sth->{go_method_calls} }, [ 'STORE', $attrib, $value ] - # if not $sth->FETCH('Executed'); - # but how to handle repeat executions? How to we know when an - # attribute is being set to affect the current resultset or the - # next execution? - # Could just always use go_method_calls I guess. - - # do the store locally anyway, just in case - $sth->SUPER::STORE($attrib => $value); - - return $sth->set_err($DBI::stderr, $msg); - } - - # sub bind_param_array - # we use DBI's default, which sets $sth->{ParamArrays}{$param} = $value - # and calls bind_param($param, undef, $attr) if $attr. - - sub execute_array { - my $sth = shift; - my $attr = shift; - $sth->bind_param_array($_, $_[$_-1]) for (1..@_); - push @{ $sth->{go_method_calls} }, [ 'execute_array', $attr ]; - return $sth->go_sth_method($attr); - } - - *go_cache = \&DBD::Gofer::go_cache; -} - -1; - -__END__ - -=head1 NAME - -DBD::Gofer - A stateless-proxy driver for communicating with a remote DBI - -=head1 SYNOPSIS - - use DBI; - - $original_dsn = "dbi:..."; # your original DBI Data Source Name - - $dbh = DBI->connect("dbi:Gofer:transport=$transport;...;dsn=$original_dsn", - $user, $passwd, \%attributes); - - ... use $dbh as if it was connected to $original_dsn ... - - -The C part specifies the name of the module to use to -transport the requests to the remote DBI. If $transport doesn't contain any -double colons then it's prefixed with C. - -The C part I of the DSN because -everything after C is assumed to be the DSN that the remote DBI should -use. - -The C<...> represents attributes that influence the operation of the Gofer -driver or transport. These are described below or in the documentation of the -transport module being used. - -=encoding ISO8859-1 - -=head1 DESCRIPTION - -DBD::Gofer is a DBI database driver that forwards requests to another DBI -driver, usually in a separate process, often on a separate machine. It tries to -be as transparent as possible so it appears that you are using the remote -driver directly. - -DBD::Gofer is very similar to DBD::Proxy. The major difference is that with -DBD::Gofer no state is maintained on the remote end. That means every -request contains all the information needed to create the required state. (So, -for example, every request includes the DSN to connect to.) Each request can be -sent to any available server. The server executes the request and returns a -single response that includes all the data. - -This is very similar to the way http works as a stateless protocol for the web. -Each request from your web browser can be handled by a different web server process. - -=head2 Use Cases - -This may seem like pointless overhead but there are situations where this is a -very good thing. Let's consider a specific case. - -Imagine using DBD::Gofer with an http transport. Your application calls -connect(), prepare("select * from table where foo=?"), bind_param(), and execute(). -At this point DBD::Gofer builds a request containing all the information -about the method calls. It then uses the httpd transport to send that request -to an apache web server. - -This 'dbi execute' web server executes the request (using DBI::Gofer::Execute -and related modules) and builds a response that contains all the rows of data, -if the statement returned any, along with all the attributes that describe the -results, such as $sth->{NAME}. This response is sent back to DBD::Gofer which -unpacks it and presents it to the application as if it had executed the -statement itself. - -=head2 Advantages - -Okay, but you still don't see the point? Well let's consider what we've gained: - -=head3 Connection Pooling and Throttling - -The 'dbi execute' web server leverages all the functionality of web -infrastructure in terms of load balancing, high-availability, firewalls, access -management, proxying, caching. - -At its most basic level you get a configurable pool of persistent database connections. - -=head3 Simple Scaling - -Got thousands of processes all trying to connect to the database? You can use -DBD::Gofer to connect them to your smaller pool of 'dbi execute' web servers instead. - -=head3 Caching - -Client-side caching is as simple as adding "C" to the DSN. -This feature alone can be worth using DBD::Gofer for. - -=head3 Fewer Network Round-trips - -DBD::Gofer sends as few requests as possible (dependent on the policy being used). - -=head3 Thin Clients / Unsupported Platforms - -You no longer need drivers for your database on every system. DBD::Gofer is pure perl. - -=head1 CONSTRAINTS - -There are some natural constraints imposed by the DBD::Gofer 'stateless' approach. -But not many: - -=head2 You can't change database handle attributes after connect() - -You can't change database handle attributes after you've connected. -Use the connect() call to specify all the attribute settings you want. - -This is because it's critical that when a request is complete the database -handle is left in the same state it was when first connected. - -An exception is made for attributes with names starting "C": -They can be set after connect() but the change is only applied locally. - -=head2 You can't change statement handle attributes after prepare() - -You can't change statement handle attributes after prepare. - -An exception is made for attributes with names starting "C": -They can be set after prepare() but the change is only applied locally. - -=head2 You can't use transactions - -AutoCommit only. Transactions aren't supported. - -(In theory transactions could be supported when using a transport that -maintains a connection, like C does. If you're interested in this -please get in touch via dbi-dev@perl.org) - -=head2 You can't call driver-private sth methods - -But that's rarely needed anyway. - -=head1 GENERAL CAVEATS - -A few important things to keep in mind when using DBD::Gofer: - -=head2 Temporary tables, locks, and other per-connection persistent state - -You shouldn't expect any per-session state to persist between requests. -This includes locks and temporary tables. - -Because the server-side may execute your requests via a different -database connections, you can't rely on any per-connection persistent state, -such as temporary tables, being available from one request to the next. - -This is an easy trap to fall into. A good way to check for this is to test your -code with a Gofer policy package that sets the C policy to -'connect' to force a new connection for each request. The C policy does this. - -=head2 Driver-private Database Handle Attributes - -Some driver-private dbh attributes may not be available if the driver has not -implemented the private_attribute_info() method (added in DBI 1.54). - -=head2 Driver-private Statement Handle Attributes - -Driver-private sth attributes can be set in the prepare() call. TODO - -Some driver-private sth attributes may not be available if the driver has not -implemented the private_attribute_info() method (added in DBI 1.54). - -=head2 Multiple Resultsets - -Multiple resultsets are supported only if the driver supports the more_results() method -(an exception is made for DBD::Sybase). - -=head2 Statement activity that also updates dbh attributes - -Some drivers may update one or more dbh attributes after performing activity on -a child sth. For example, DBD::mysql provides $dbh->{mysql_insertid} in addition to -$sth->{mysql_insertid}. Currently mysql_insertid is supported via a hack but a -more general mechanism is needed for other drivers to use. - -=head2 Methods that report an error always return undef - -With DBD::Gofer, a method that sets an error always return an undef or empty list. -That shouldn't be a problem in practice because the DBI doesn't define any -methods that return meaningful values while also reporting an error. - -=head2 Subclassing only applies to client-side - -The RootClass and DbTypeSubclass attributes are not passed to the Gofer server. - -=head1 CAVEATS FOR SPECIFIC METHODS - -=head2 last_insert_id - -To enable use of last_insert_id you need to indicate to DBD::Gofer that you'd -like to use it. You do that my adding a C attribute to -the do() or prepare() method calls. For example: - - $dbh->do($sql, { go_last_insert_id_args => [...] }); - -or - - $sth = $dbh->prepare($sql, { go_last_insert_id_args => [...] }); - -The array reference should contains the args that you want passed to the -last_insert_id() method. - -=head2 execute_for_fetch - -The array methods bind_param_array() and execute_array() are supported. -When execute_array() is called the data is serialized and executed in a single -round-trip to the Gofer server. This makes it very fast, but requires enough -memory to store all the serialized data. - -The execute_for_fetch() method currently isn't optimised, it uses the DBI -fallback behaviour of executing each tuple individually. -(It could be implemented as a wrapper for execute_array() - patches welcome.) - -=head1 TRANSPORTS - -DBD::Gofer doesn't concern itself with transporting requests and responses to and fro. -For that it uses special Gofer transport modules. - -Gofer transport modules usually come in pairs: one for the 'client' DBD::Gofer -driver to use and one for the remote 'server' end. They have very similar names: - - DBD::Gofer::Transport:: - DBI::Gofer::Transport:: - -Sometimes the transports on the DBD and DBI sides may have different names. For -example DBD::Gofer::Transport::http is typically used with DBI::Gofer::Transport::mod_perl -(DBD::Gofer::Transport::http and DBI::Gofer::Transport::mod_perl modules are -part of the GoferTransport-http distribution). - -=head2 Bundled Transports - -Several transport modules are provided with DBD::Gofer: - -=head3 null - -The null transport is the simplest of them all. It doesn't actually transport the request anywhere. -It just serializes (freezes) the request into a string, then thaws it back into -a data structure before passing it to DBI::Gofer::Execute to execute. The same -freeze and thaw is applied to the results. - -The null transport is the best way to test if your application will work with Gofer. -Just set the DBI_AUTOPROXY environment variable to "C" -(see L below) and run your application, or ideally its test suite, as usual. - -It doesn't take any parameters. - -=head3 pipeone - -The pipeone transport launches a subprocess for each request. It passes in the -request and reads the response. - -The fact that a new subprocess is started for each request ensures that the -server side is truly stateless. While this does make the transport I slow, -it is useful as a way to test that your application doesn't depend on -per-connection state, such as temporary tables, persisting between requests. - -It's also useful both as a proof of concept and as a base class for the stream -driver. - -=head3 stream - -The stream driver also launches a subprocess and writes requests and reads -responses, like the pipeone transport. In this case, however, the subprocess -is expected to handle more that one request. (Though it will be automatically -restarted if it exits.) - -This is the first transport that is truly useful because it can launch the -subprocess on a remote machine using C. This means you can now use DBD::Gofer -to easily access any databases that's accessible from any system you can login to. -You also get all the benefits of ssh, including encryption and optional compression. - -See L below for an example. - -=head2 Other Transports - -Implementing a Gofer transport is I simple, and more transports are very welcome. -Just take a look at any existing transports that are similar to your needs. - -=head3 http - -See the GoferTransport-http distribution on CPAN: http://search.cpan.org/dist/GoferTransport-http/ - -=head3 Gearman - -I know Ask Bjørn Hansen has implemented a transport for the C distributed -job system, though it's not on CPAN at the time of writing this. - -=head1 CONNECTING - -Simply prefix your existing DSN with "C" -where $transport is the name of the Gofer transport you want to use (see L). -The C and C attributes must be specified and the C attributes must be last. - -Other attributes can be specified in the DSN to configure DBD::Gofer and/or the -Gofer transport module being used. The main attributes after C, are -C and C. These and other attributes are described below. - -=head2 Using DBI_AUTOPROXY - -The simplest way to try out DBD::Gofer is to set the DBI_AUTOPROXY environment variable. -In this case you don't include the C part. For example: - - export DBI_AUTOPROXY="dbi:Gofer:transport=null" - -or, for a more useful example, try: - - export DBI_AUTOPROXY="dbi:Gofer:transport=stream;url=ssh:user@example.com" - -=head2 Connection Attributes - -These attributes can be specified in the DSN. They can also be passed in the -\%attr parameter of the DBI connect method by adding a "C" prefix to the name. - -=head3 transport - -Specifies the Gofer transport class to use. Required. See L above. - -If the value does not include C<::> then "C" is prefixed. - -The transport object can be accessed via $h->{go_transport}. - -=head3 dsn - -Specifies the DSN for the remote side to connect to. Required, and must be last. - -=head3 url - -Used to tell the transport where to connect to. The exact form of the value depends on the transport used. - -=head3 policy - -Specifies the policy to use. See L. - -If the value does not include C<::> then "C" is prefixed. - -The policy object can be accessed via $h->{go_policy}. - -=head3 timeout - -Specifies a timeout, in seconds, to use when waiting for responses from the server side. - -=head3 retry_limit - -Specifies the number of times a failed request will be retried. Default is 0. - -=head3 retry_hook - -Specifies a code reference to be called to decide if a failed request should be retried. -The code reference is called like this: - - $transport = $h->{go_transport}; - $retry = $transport->go_retry_hook->($request, $response, $transport); - -If it returns true then the request will be retried, up to the C. -If it returns a false but defined value then the request will not be retried. -If it returns undef then the default behaviour will be used, as if C -had not been specified. - -The default behaviour is to retry requests where $request->is_idempotent is true, -or the error message matches C. - -=head3 cache - -Specifies that client-side caching should be performed. The value is the name -of a cache class to use. - -Any class implementing get($key) and set($key, $value) methods can be used. -That includes a great many powerful caching classes on CPAN, including the -Cache and Cache::Cache distributions. - -You can use "C" is a shortcut for "C". -See L for a description of this simple fast default cache. - -The cache object can be accessed via $h->go_cache. For example: - - $dbh->go_cache->clear; # free up memory being used by the cache - -The cache keys are the frozen (serialized) requests, and the values are the -frozen responses. - -The default behaviour is to only use the cache for requests where -$request->is_idempotent is true (i.e., the dbh has the ReadOnly attribute set -or the SQL statement is obviously a SELECT without a FOR UPDATE clause.) - -For even more control you can use the C attribute to pass in an -instantiated cache object. Individual methods, including prepare(), can also -specify alternative caches via the C attribute. For example, to -specify no caching for a particular query, you could use - - $sth = $dbh->prepare( $sql, { go_cache => 0 } ); - -This can be used to implement different caching policies for different statements. - -It's interesting to note that DBD::Gofer can be used to add client-side caching -to any (gofer compatible) application, with no code changes and no need for a -gofer server. Just set the DBI_AUTOPROXY environment variable like this: - - DBI_AUTOPROXY='dbi:Gofer:transport=null;cache=1' - -=head1 CONFIGURING BEHAVIOUR POLICY - -DBD::Gofer supports a 'policy' mechanism that allows you to fine-tune the number of round-trips to the Gofer server. -The policies are grouped into classes (which may be subclassed) and referenced by the name of the class. - -The L class is the base class for all the policy -packages and describes all the available policies. - -Three policy packages are supplied with DBD::Gofer: - -L is most 'transparent' but slowest because it -makes more round-trips to the Gofer server. - -L is a reasonable compromise - it's the default policy. - -L is fastest, but may require code changes in your applications. - -Generally the default C policy is fine. When first testing an existing -application with Gofer it is a good idea to start with the C policy -first and then switch to C or a custom policy, for final testing. - - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 ACKNOWLEDGEMENTS - -The development of DBD::Gofer and related modules was sponsored by -Shopzilla.com (L), where I currently work. - -=head1 SEE ALSO - -L, L, L. - -L, L. - -L - -=head1 Caveats for specific drivers - -This section aims to record issues to be aware of when using Gofer with specific drivers. -It usually only documents issues that are not natural consequences of the limitations -of the Gofer approach - as documented above. - -=head1 TODO - -This is just a random brain dump... (There's more in the source of the Changes file, not the pod) - -Document policy mechanism - -Add mechanism for transports to list config params and for Gofer to apply any that match (and warn if any left over?) - -Driver-private sth attributes - set via prepare() - change DBI spec - -add hooks into transport base class for checking & updating a result set cache - ie via a standard cache interface such as: - http://search.cpan.org/~robm/Cache-FastMmap/FastMmap.pm - http://search.cpan.org/~bradfitz/Cache-Memcached/lib/Cache/Memcached.pm - http://search.cpan.org/~dclinton/Cache-Cache/ - http://search.cpan.org/~cleishman/Cache/ -Also caching instructions could be passed through the httpd transport layer -in such a way that appropriate http cache headers are added to the results -so that web caches (squid etc) could be used to implement the caching. -(MUST require the use of GET rather than POST requests.) - -Rework handling of installed_methods to not piggyback on dbh_attributes? - -Perhaps support transactions for transports where it's possible (ie null and stream)? -Would make stream transport (ie ssh) more useful to more people. - -Make sth_result_attr more like dbh_attributes (using '*' etc) - -Add @val = FETCH_many(@names) to DBI in C and use in Gofer/Execute? - -Implement _new_sth in C. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/Base.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/Base.pm deleted file mode 100644 index 0121c88..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/Base.pm +++ /dev/null @@ -1,162 +0,0 @@ -package DBD::Gofer::Policy::Base; - -# $Id: Base.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; -use Carp; - -our $VERSION = "0.010088"; -our $AUTOLOAD; - -my %policy_defaults = ( - # force connect method (unless overridden by go_connect_method=>'...' attribute) - # if false: call same method on client as on server - connect_method => 'connect', - # force prepare method (unless overridden by go_prepare_method=>'...' attribute) - # if false: call same method on client as on server - prepare_method => 'prepare', - skip_connect_check => 0, - skip_default_methods => 0, - skip_prepare_check => 0, - skip_ping => 0, - dbh_attribute_update => 'every', - dbh_attribute_list => ['*'], - locally_quote => 0, - locally_quote_identifier => 0, - cache_parse_trace_flags => 1, - cache_parse_trace_flag => 1, - cache_data_sources => 1, - cache_type_info_all => 1, - cache_tables => 0, - cache_table_info => 0, - cache_column_info => 0, - cache_primary_key_info => 0, - cache_foreign_key_info => 0, - cache_statistics_info => 0, - cache_get_info => 0, - cache_func => 0, -); - -my $base_policy_file = $INC{"DBD/Gofer/Policy/Base.pm"}; - -__PACKAGE__->create_policy_subs(\%policy_defaults); - -sub create_policy_subs { - my ($class, $policy_defaults) = @_; - - while ( my ($policy_name, $policy_default) = each %$policy_defaults) { - my $policy_attr_name = "go_$policy_name"; - my $sub = sub { - # $policy->foo($attr, ...) - #carp "$policy_name($_[1],...)"; - # return the policy default value unless an attribute overrides it - return (ref $_[1] && exists $_[1]->{$policy_attr_name}) - ? $_[1]->{$policy_attr_name} - : $policy_default; - }; - no strict 'refs'; - *{$class . '::' . $policy_name} = $sub; - } -} - -sub AUTOLOAD { - carp "Unknown policy name $AUTOLOAD used"; - # only warn once - no strict 'refs'; - *$AUTOLOAD = sub { undef }; - return undef; -} - -sub new { - my ($class, $args) = @_; - my $policy = {}; - bless $policy, $class; -} - -sub DESTROY { }; - -1; - -=head1 NAME - -DBD::Gofer::Policy::Base - Base class for DBD::Gofer policies - -=head1 SYNOPSIS - - $dbh = DBI->connect("dbi:Gofer:transport=...;policy=...", ...) - -=head1 DESCRIPTION - -DBD::Gofer can be configured via a 'policy' mechanism that allows you to -fine-tune the number of round-trips to the Gofer server. The policies are -grouped into classes (which may be subclassed) and referenced by the name of -the class. - -The L class is the base class for all the policy -classes and describes all the individual policy items. - -The Base policy is not used directly. You should use a policy class derived from it. - -=head1 POLICY CLASSES - -Three policy classes are supplied with DBD::Gofer: - -L is most 'transparent' but slowest because it -makes more round-trips to the Gofer server. - -L is a reasonable compromise - it's the default policy. - -L is fastest, but may require code changes in your applications. - -Generally the default C policy is fine. When first testing an existing -application with Gofer it is a good idea to start with the C policy -first and then switch to C or a custom policy, for final testing. - -=head1 POLICY ITEMS - -These are temporary docs: See the source code for list of policies and their defaults. - -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. - -See the source code to this module for more details. - -=head1 POLICY CUSTOMIZATION - -XXX This area of DBD::Gofer is subject to change. - -There are three ways to customize policies: - -Policy classes are designed to influence the overall behaviour of DBD::Gofer -with existing, unaltered programs, so they work in a reasonably optimal way -without requiring code changes. You can implement new policy classes as -subclasses of existing policies. - -In many cases individual policy items can be overridden on a case-by-case basis -within your application code. You do this by passing a corresponding -C<>> attribute into DBI methods by your application code. -This let's you fine-tune the behaviour for special cases. - -The policy items are implemented as methods. In many cases the methods are -passed parameters relating to the DBD::Gofer code being executed. This means -the policy can implement dynamic behaviour that varies depending on the -particular circumstances, such as the particular statement being executed. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/classic.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/classic.pm deleted file mode 100644 index 7316f13..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/classic.pm +++ /dev/null @@ -1,79 +0,0 @@ -package DBD::Gofer::Policy::classic; - -# $Id: classic.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -our $VERSION = "0.010088"; - -use base qw(DBD::Gofer::Policy::Base); - -__PACKAGE__->create_policy_subs({ - - # always use connect_cached on server - connect_method => 'connect_cached', - - # use same methods on server as is called on client - prepare_method => '', - - # don't skip the connect check since that also sets dbh attributes - # although this makes connect more expensive, that's partly offset - # by skip_ping=>1 below, which makes connect_cached very fast. - skip_connect_check => 0, - - # most code doesn't rely on sth attributes being set after prepare - skip_prepare_check => 1, - - # we're happy to use local method if that's the same as the remote - skip_default_methods => 1, - - # ping is not important for DBD::Gofer and most transports - skip_ping => 1, - - # only update dbh attributes on first contact with server - dbh_attribute_update => 'first', - - # we'd like to set locally_* but can't because drivers differ - - # get_info results usually don't change - cache_get_info => 1, -}); - - -1; - -=head1 NAME - -DBD::Gofer::Policy::classic - The 'classic' policy for DBD::Gofer - -=head1 SYNOPSIS - - $dbh = DBI->connect("dbi:Gofer:transport=...;policy=classic", ...) - -The C policy is the default DBD::Gofer policy, so need not be included in the DSN. - -=head1 DESCRIPTION - -Temporary docs: See the source code for list of policies and their defaults. - -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/pedantic.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/pedantic.pm deleted file mode 100644 index af3e451..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/pedantic.pm +++ /dev/null @@ -1,53 +0,0 @@ -package DBD::Gofer::Policy::pedantic; - -# $Id: pedantic.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -our $VERSION = "0.010088"; - -use base qw(DBD::Gofer::Policy::Base); - -# the 'pedantic' policy is the same as the Base policy - -1; - -=head1 NAME - -DBD::Gofer::Policy::pedantic - The 'pedantic' policy for DBD::Gofer - -=head1 SYNOPSIS - - $dbh = DBI->connect("dbi:Gofer:transport=...;policy=pedantic", ...) - -=head1 DESCRIPTION - -The C policy tries to be as transparent as possible. To do this it -makes round-trips to the server for almost every DBI method call. - -This is the best policy to use when first testing existing code with Gofer. -Once it's working well you should consider moving to the C policy or defining your own policy class. - -Temporary docs: See the source code for list of policies and their defaults. - -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/rush.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/rush.pm deleted file mode 100644 index f8d5743..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Policy/rush.pm +++ /dev/null @@ -1,90 +0,0 @@ -package DBD::Gofer::Policy::rush; - -# $Id: rush.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -our $VERSION = "0.010088"; - -use base qw(DBD::Gofer::Policy::Base); - -__PACKAGE__->create_policy_subs({ - - # always use connect_cached on server - connect_method => 'connect_cached', - - # use same methods on server as is called on client - # (because code not using placeholders would bloat the sth cache) - prepare_method => '', - - # Skipping the connect check is fast, but it also skips - # fetching the remote dbh attributes! - # Make sure that your application doesn't need access to dbh attributes. - skip_connect_check => 1, - - # most code doesn't rely on sth attributes being set after prepare - skip_prepare_check => 1, - - # we're happy to use local method if that's the same as the remote - skip_default_methods => 1, - - # ping is almost meaningless for DBD::Gofer and most transports anyway - skip_ping => 1, - - # don't update dbh attributes at all - # XXX actually we currently need dbh_attribute_update for skip_default_methods to work - # and skip_default_methods is more valuable to us than the cost of dbh_attribute_update - dbh_attribute_update => 'none', # actually means 'first' currently - #dbh_attribute_list => undef, - - # we'd like to set locally_* but can't because drivers differ - - # in a rush assume metadata doesn't change - cache_tables => 1, - cache_table_info => 1, - cache_column_info => 1, - cache_primary_key_info => 1, - cache_foreign_key_info => 1, - cache_statistics_info => 1, - cache_get_info => 1, -}); - - -1; - -=head1 NAME - -DBD::Gofer::Policy::rush - The 'rush' policy for DBD::Gofer - -=head1 SYNOPSIS - - $dbh = DBI->connect("dbi:Gofer:transport=...;policy=rush", ...) - -=head1 DESCRIPTION - -The C policy tries to make as few round-trips as possible. -It's the opposite end of the policy spectrum to the C policy. - -Temporary docs: See the source code for list of policies and their defaults. - -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/Base.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/Base.pm deleted file mode 100644 index afe96cc..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/Base.pm +++ /dev/null @@ -1,410 +0,0 @@ -package DBD::Gofer::Transport::Base; - -# $Id: Base.pm 14120 2010-06-07 19:52:19Z H.Merijn $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use base qw(DBI::Gofer::Transport::Base); - -our $VERSION = "0.014121"; - -__PACKAGE__->mk_accessors(qw( - trace - go_dsn - go_url - go_policy - go_timeout - go_retry_hook - go_retry_limit - go_cache - cache_hit - cache_miss - cache_store -)); -__PACKAGE__->mk_accessors_using(make_accessor_autoviv_hashref => qw( - meta -)); - - -sub new { - my ($class, $args) = @_; - $args->{$_} = 0 for (qw(cache_hit cache_miss cache_store)); - $args->{keep_meta_frozen} ||= 1 if $args->{go_cache}; - #warn "args @{[ %$args ]}\n"; - return $class->SUPER::new($args); -} - - -sub _init_trace { $ENV{DBD_GOFER_TRACE} || 0 } - - -sub new_response { - my $self = shift; - return DBI::Gofer::Response->new(@_); -} - - -sub transmit_request { - my ($self, $request) = @_; - my $trace = $self->trace; - my $response; - - my ($go_cache, $request_cache_key); - if ($go_cache = $self->{go_cache}) { - $request_cache_key - = $request->{meta}{request_cache_key} - = $self->get_cache_key_for_request($request); - if ($request_cache_key) { - my $frozen_response = eval { $go_cache->get($request_cache_key) }; - if ($frozen_response) { - $self->_dump("cached response found for ".ref($request), $request) - if $trace; - $response = $self->thaw_response($frozen_response); - $self->trace_msg("transmit_request is returning a response from cache $go_cache\n") - if $trace; - ++$self->{cache_hit}; - return $response; - } - warn $@ if $@; - ++$self->{cache_miss}; - $self->trace_msg("transmit_request cache miss\n") - if $trace; - } - } - - my $to = $self->go_timeout; - my $transmit_sub = sub { - $self->trace_msg("transmit_request\n") if $trace; - local $SIG{ALRM} = sub { die "TIMEOUT\n" } if $to; - - my $response = eval { - local $SIG{PIPE} = sub { - my $extra = ($! eq "Broken pipe") ? "" : " ($!)"; - die "Unable to send request: Broken pipe$extra\n"; - }; - alarm($to) if $to; - $self->transmit_request_by_transport($request); - }; - alarm(0) if $to; - - if ($@) { - return $self->transport_timedout("transmit_request", $to) - if $@ eq "TIMEOUT\n"; - return $self->new_response({ err => 1, errstr => $@ }); - } - - return $response; - }; - - $response = $self->_transmit_request_with_retries($request, $transmit_sub); - - if ($response) { - my $frozen_response = delete $response->{meta}{frozen}; - $self->_store_response_in_cache($frozen_response, $request_cache_key) - if $request_cache_key; - } - - $self->trace_msg("transmit_request is returning a response itself\n") - if $trace && $response; - - return $response unless wantarray; - return ($response, $transmit_sub); -} - - -sub _transmit_request_with_retries { - my ($self, $request, $transmit_sub) = @_; - my $response; - do { - $response = $transmit_sub->(); - } while ( $response && $self->response_needs_retransmit($request, $response) ); - return $response; -} - - -sub receive_response { - my ($self, $request, $retransmit_sub) = @_; - my $to = $self->go_timeout; - - my $receive_sub = sub { - $self->trace_msg("receive_response\n"); - local $SIG{ALRM} = sub { die "TIMEOUT\n" } if $to; - - my $response = eval { - alarm($to) if $to; - $self->receive_response_by_transport($request); - }; - alarm(0) if $to; - - if ($@) { - return $self->transport_timedout("receive_response", $to) - if $@ eq "TIMEOUT\n"; - return $self->new_response({ err => 1, errstr => $@ }); - } - return $response; - }; - - my $response; - do { - $response = $receive_sub->(); - if ($self->response_needs_retransmit($request, $response)) { - $response = $self->_transmit_request_with_retries($request, $retransmit_sub); - $response ||= $receive_sub->(); - } - } while ( $self->response_needs_retransmit($request, $response) ); - - if ($response) { - my $frozen_response = delete $response->{meta}{frozen}; - my $request_cache_key = $request->{meta}{request_cache_key}; - $self->_store_response_in_cache($frozen_response, $request_cache_key) - if $request_cache_key && $self->{go_cache}; - } - - return $response; -} - - -sub response_retry_preference { - my ($self, $request, $response) = @_; - - # give the user a chance to express a preference (or undef for default) - if (my $go_retry_hook = $self->go_retry_hook) { - my $retry = $go_retry_hook->($request, $response, $self); - $self->trace_msg(sprintf "go_retry_hook returned %s\n", - (defined $retry) ? $retry : 'undef'); - return $retry if defined $retry; - } - - # This is the main decision point. We don't retry requests that got - # as far as executing because the error is probably from the database - # (not transport) so retrying is unlikely to help. But note that any - # severe transport error occurring after execute is likely to return - # a new response object that doesn't have the execute flag set. Beware! - return 0 if $response->executed_flag_set; - - return 1 if ($response->errstr || '') =~ m/induced by DBI_GOFER_RANDOM/; - - return 1 if $request->is_idempotent; # i.e. is SELECT or ReadOnly was set - - return undef; # we couldn't make up our mind -} - - -sub response_needs_retransmit { - my ($self, $request, $response) = @_; - - my $err = $response->err - or return 0; # nothing went wrong - - my $retry = $self->response_retry_preference($request, $response); - - if (!$retry) { # false or undef - $self->trace_msg("response_needs_retransmit: response not suitable for retry\n"); - return 0; - } - - # we'd like to retry but have we retried too much already? - - my $retry_limit = $self->go_retry_limit; - if (!$retry_limit) { - $self->trace_msg("response_needs_retransmit: retries disabled (retry_limit not set)\n"); - return 0; - } - - my $request_meta = $request->meta; - my $retry_count = $request_meta->{retry_count} || 0; - if ($retry_count >= $retry_limit) { - $self->trace_msg("response_needs_retransmit: $retry_count is too many retries\n"); - # XXX should be possible to disable altering the err - $response->errstr(sprintf "%s (after %d retries by gofer)", $response->errstr, $retry_count); - return 0; - } - - # will retry now, do the admin - ++$retry_count; - $self->trace_msg("response_needs_retransmit: retry $retry_count\n"); - - # hook so response_retry_preference can defer some code execution - # until we've checked retry_count and retry_limit. - if (ref $retry eq 'CODE') { - $retry->($retry_count, $retry_limit) - and warn "should return false"; # protect future use - } - - ++$request_meta->{retry_count}; # update count for this request object - ++$self->meta->{request_retry_count}; # update cumulative transport stats - - return 1; -} - - -sub transport_timedout { - my ($self, $method, $timeout) = @_; - $timeout ||= $self->go_timeout; - return $self->new_response({ err => 1, errstr => "DBD::Gofer $method timed-out after $timeout seconds" }); -} - - -# return undef if we don't want to cache this request -# subclasses may use more specialized rules -sub get_cache_key_for_request { - my ($self, $request) = @_; - - # we only want to cache idempotent requests - # is_idempotent() is true if GOf_REQUEST_IDEMPOTENT or GOf_REQUEST_READONLY set - return undef if not $request->is_idempotent; - - # XXX would be nice to avoid the extra freeze here - my $key = $self->freeze_request($request, undef, 1); - - #use Digest::MD5; warn "get_cache_key_for_request: ".Digest::MD5::md5_base64($key)."\n"; - - return $key; -} - - -sub _store_response_in_cache { - my ($self, $frozen_response, $request_cache_key) = @_; - my $go_cache = $self->{go_cache} - or return; - - # new() ensures that enabling go_cache also enables keep_meta_frozen - warn "No meta frozen in response" if !$frozen_response; - warn "No request_cache_key" if !$request_cache_key; - - if ($frozen_response && $request_cache_key) { - $self->trace_msg("receive_response added response to cache $go_cache\n"); - eval { $go_cache->set($request_cache_key, $frozen_response) }; - warn $@ if $@; - ++$self->{cache_store}; - } -} - -1; - -__END__ - -=head1 NAME - -DBD::Gofer::Transport::Base - base class for DBD::Gofer client transports - -=head1 SYNOPSIS - - my $remote_dsn = "..." - DBI->connect("dbi:Gofer:transport=...;url=...;timeout=...;retry_limit=...;dsn=$remote_dsn",...) - -or, enable by setting the DBI_AUTOPROXY environment variable: - - export DBI_AUTOPROXY='dbi:Gofer:transport=...;url=...' - -which will force I DBI connections to be made via that Gofer server. - -=head1 DESCRIPTION - -This is the base class for all DBD::Gofer client transports. - -=head1 ATTRIBUTES - -Gofer transport attributes can be specified either in the attributes parameter -of the connect() method call, or in the DSN string. When used in the DSN -string, attribute names don't have the C prefix. - -=head2 go_dsn - -The full DBI DSN that the Gofer server should connect to on your behalf. - -When used in the DSN it must be the last element in the DSN string. - -=head2 go_timeout - -A time limit for sending a request and receiving a response. Some drivers may -implement sending and receiving as separate steps, in which case (currently) -the timeout applies to each separately. - -If a request needs to be resent then the timeout is restarted for each sending -of a request and receiving of a response. - -=head2 go_retry_limit - -The maximum number of times an request may be retried. The default is 2. - -=head2 go_retry_hook - -This subroutine reference is called, if defined, for each response received where $response->err is true. - -The subroutine is pass three parameters: the request object, the response object, and the transport object. - -If it returns an undefined value then the default retry behaviour is used. See L below. - -If it returns a defined but false value then the request is not resent. - -If it returns true value then the request is resent, so long as the number of retries does not exceed C. - -=head1 RETRY ON ERROR - -The default retry on error behaviour is: - - - Retry if the error was due to DBI_GOFER_RANDOM. See L. - - - Retry if $request->is_idempotent returns true. See L. - -A retry won't be allowed if the number of previous retries has reached C. - -=head1 TRACING - -Tracing of gofer requests and responses can be enabled by setting the -C environment variable. A value of 1 gives a reasonably -compact summary of each request and response. A value of 2 or more gives a -detailed, and voluminous, dump. - -The trace is written using DBI->trace_msg() and so is written to the default -DBI trace output, which is usually STDERR. - -=head1 METHODS - -I - -=head2 response_retry_preference - - $retry = $transport->response_retry_preference($request, $response); - -The response_retry_preference is called by DBD::Gofer when considering if a -request should be retried after an error. - -Returns true (would like to retry), false (must not retry), undef (no preference). - -If a true value is returned in the form of a CODE ref then, if DBD::Gofer does -decide to retry the request, it calls the code ref passing $retry_count, $retry_limit. -Can be used for logging and/or to implement exponential backoff behaviour. -Currently the called code must return using C to allow for future extensions. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007-2008, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L, L, L, L. - -and some example transports: - -L - -L - -L - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/corostream.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/corostream.pm deleted file mode 100644 index 6e79278..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/corostream.pm +++ /dev/null @@ -1,144 +0,0 @@ -package DBD::Gofer::Transport::corostream; - -use strict; -use warnings; - -use Carp; - -use Coro::Select; # a slow but coro-aware replacement for CORE::select (global effect!) - -use Coro; -use Coro::Handle; - -use base qw(DBD::Gofer::Transport::stream); - -# XXX ensure DBI_PUREPERL for parent doesn't pass to child -sub start_pipe_command { - local $ENV{DBI_PUREPERL} = $ENV{DBI_PUREPERL_COROCHILD}; # typically undef - my $connection = shift->SUPER::start_pipe_command(@_); - return $connection; -} - - - -1; - -__END__ - -=head1 NAME - -DBD::Gofer::Transport::corostream - Async DBD::Gofer stream transport using Coro and AnyEvent - -=head1 SYNOPSIS - - DBI_AUTOPROXY="dbi:Gofer:transport=corostream" perl some-perl-script-using-dbi.pl - -or - - $dsn = ...; # the DSN for the driver and database you want to use - $dbh = DBI->connect("dbi:Gofer:transport=corostream;dsn=$dsn", ...); - -=head1 DESCRIPTION - -The I from using L is that it enables the use of existing -DBI frameworks like L. - -=head1 KNOWN ISSUES AND LIMITATIONS - - - Uses Coro::Select so alters CORE::select globally - Parent class probably needs refactoring to enable a more encapsulated approach. - - - Doesn't prevent multiple concurrent requests - Probably just needs a per-connection semaphore - - - Coro has many caveats. Caveat emptor. - -=head1 STATUS - -THIS IS CURRENTLY JUST A PROOF-OF-CONCEPT IMPLEMENTATION FOR EXPERIMENTATION. - -Please note that I have no plans to develop this code further myself. -I'd very much welcome contributions. Interested? Let me know! - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2010, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L - -L - -=head1 APPENDIX - -Example code: - - #!perl - - use strict; - use warnings; - use Time::HiRes qw(time); - - BEGIN { $ENV{PERL_ANYEVENT_STRICT} = 1; $ENV{PERL_ANYEVENT_VERBOSE} = 1; } - - use AnyEvent; - - BEGIN { $ENV{DBI_TRACE} = 0; $ENV{DBI_GOFER_TRACE} = 0; $ENV{DBD_GOFER_TRACE} = 0; }; - - use DBI; - - $ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=corostream'; - - my $ticker = AnyEvent->timer( after => 0, interval => 0.1, cb => sub { - warn sprintf "-tick- %.2f\n", time - } ); - - warn "connecting...\n"; - my $dbh = DBI->connect("dbi:NullP:"); - warn "...connected\n"; - - for (1..3) { - warn "entering DBI...\n"; - $dbh->do("sleep 0.3"); # pseudo-sql understood by the DBD::NullP driver - warn "...returned\n"; - } - - warn "done."; - -Example output: - - $ perl corogofer.pl - connecting... - -tick- 1293631437.14 - -tick- 1293631437.14 - ...connected - entering DBI... - -tick- 1293631437.25 - -tick- 1293631437.35 - -tick- 1293631437.45 - -tick- 1293631437.55 - ...returned - entering DBI... - -tick- 1293631437.66 - -tick- 1293631437.76 - -tick- 1293631437.86 - ...returned - entering DBI... - -tick- 1293631437.96 - -tick- 1293631438.06 - -tick- 1293631438.16 - ...returned - done. at corogofer.pl line 39. - -You can see that the timer callback is firing while the code 'waits' inside the -do() method for the response from the database. Normally that would block. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/null.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/null.pm deleted file mode 100644 index 22dcc04..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/null.pm +++ /dev/null @@ -1,111 +0,0 @@ -package DBD::Gofer::Transport::null; - -# $Id: null.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use base qw(DBD::Gofer::Transport::Base); - -use DBI::Gofer::Execute; - -our $VERSION = "0.010088"; - -__PACKAGE__->mk_accessors(qw( - pending_response - transmit_count -)); - -my $executor = DBI::Gofer::Execute->new(); - - -sub transmit_request_by_transport { - my ($self, $request) = @_; - $self->transmit_count( ($self->transmit_count()||0) + 1 ); # just for tests - - my $frozen_request = $self->freeze_request($request); - - # ... - # the request is magically transported over to ... ourselves - # ... - - my $response = $executor->execute_request( $self->thaw_request($frozen_request, undef, 1) ); - - # put response 'on the shelf' ready for receive_response() - $self->pending_response( $response ); - - return undef; -} - - -sub receive_response_by_transport { - my $self = shift; - - my $response = $self->pending_response; - - my $frozen_response = $self->freeze_response($response, undef, 1); - - # ... - # the response is magically transported back to ... ourselves - # ... - - return $self->thaw_response($frozen_response); -} - - -1; -__END__ - -=head1 NAME - -DBD::Gofer::Transport::null - DBD::Gofer client transport for testing - -=head1 SYNOPSIS - - my $original_dsn = "..." - DBI->connect("dbi:Gofer:transport=null;dsn=$original_dsn",...) - -or, enable by setting the DBI_AUTOPROXY environment variable: - - export DBI_AUTOPROXY="dbi:Gofer:transport=null" - -=head1 DESCRIPTION - -Connect via DBD::Gofer but execute the requests within the same process. - -This is a quick and simple way to test applications for compatibility with the -(few) restrictions that DBD::Gofer imposes. - -It also provides a simple, portable way for the DBI test suite to be used to -test DBD::Gofer on all platforms with no setup. - -Also, by measuring the difference in performance between normal connections and -connections via C the basic cost of using DBD::Gofer -can be measured. Furthermore, the additional cost of more advanced transports can be -isolated by comparing their performance with the null transport. - -The C script in the DBI distribution includes a comparative benchmark. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L - -L - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/pipeone.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/pipeone.pm deleted file mode 100644 index 3d792b9..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/pipeone.pm +++ /dev/null @@ -1,253 +0,0 @@ -package DBD::Gofer::Transport::pipeone; - -# $Id: pipeone.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use Carp; -use Fcntl; -use IO::Select; -use IPC::Open3 qw(open3); -use Symbol qw(gensym); - -use base qw(DBD::Gofer::Transport::Base); - -our $VERSION = "0.010088"; - -__PACKAGE__->mk_accessors(qw( - connection_info - go_perl -)); - - -sub new { - my ($self, $args) = @_; - $args->{go_perl} ||= do { - ($INC{"blib.pm"}) ? [ $^X, '-Mblib' ] : [ $^X ]; - }; - if (not ref $args->{go_perl}) { - # user can override the perl to be used, either with an array ref - # containing the command name and args to use, or with a string - # (ie via the DSN) in which case, to enable args to be passed, - # we split on two or more consecutive spaces (otherwise the path - # to perl couldn't contain a space itself). - $args->{go_perl} = [ split /\s{2,}/, $args->{go_perl} ]; - } - return $self->SUPER::new($args); -} - - -# nonblock($fh) puts filehandle into nonblocking mode -sub nonblock { - my $fh = shift; - my $flags = fcntl($fh, F_GETFL, 0) - or croak "Can't get flags for filehandle $fh: $!"; - fcntl($fh, F_SETFL, $flags | O_NONBLOCK) - or croak "Can't make filehandle $fh nonblocking: $!"; -} - - -sub start_pipe_command { - my ($self, $cmd) = @_; - $cmd = [ $cmd ] unless ref $cmd eq 'ARRAY'; - - # if it's important that the subprocess uses the same - # (versions of) modules as us then the caller should - # set PERL5LIB itself. - - # limit various forms of insanity, for now - local $ENV{DBI_TRACE}; # use DBI_GOFER_TRACE instead - local $ENV{DBI_AUTOPROXY}; - local $ENV{DBI_PROFILE}; - - my ($wfh, $rfh, $efh) = (gensym, gensym, gensym); - my $pid = open3($wfh, $rfh, $efh, @$cmd) - or die "error starting @$cmd: $!\n"; - if ($self->trace) { - $self->trace_msg(sprintf("Started pid $pid: @$cmd {fd: w%d r%d e%d, ppid=$$}\n", fileno $wfh, fileno $rfh, fileno $efh),0); - } - nonblock($rfh); - nonblock($efh); - my $ios = IO::Select->new($rfh, $efh); - - return { - cmd=>$cmd, - pid=>$pid, - wfh=>$wfh, rfh=>$rfh, efh=>$efh, - ios=>$ios, - }; -} - - -sub cmd_as_string { - my $self = shift; - # XXX meant to return a properly shell-escaped string suitable for system - # but its only for debugging so that can wait - my $connection_info = $self->connection_info; - return join " ", map { (m/^[-:\w]*$/) ? $_ : "'$_'" } @{$connection_info->{cmd}}; -} - - -sub transmit_request_by_transport { - my ($self, $request) = @_; - - my $frozen_request = $self->freeze_request($request); - - my $cmd = [ @{$self->go_perl}, qw(-MDBI::Gofer::Transport::pipeone -e run_one_stdio)]; - my $info = $self->start_pipe_command($cmd); - - my $wfh = delete $info->{wfh}; - # send frozen request - local $\; - print $wfh $frozen_request - or warn "error writing to @$cmd: $!\n"; - # indicate that there's no more - close $wfh - or die "error closing pipe to @$cmd: $!\n"; - - $self->connection_info( $info ); - return; -} - - -sub read_response_from_fh { - my ($self, $fh_actions) = @_; - my $trace = $self->trace; - - my $info = $self->connection_info || die; - my ($ios) = @{$info}{qw(ios)}; - my $errors = 0; - my $complete; - - die "No handles to read response from" unless $ios->count; - - while ($ios->count) { - my @readable = $ios->can_read(); - for my $fh (@readable) { - local $_; - my $actions = $fh_actions->{$fh} || die "panic: no action for $fh"; - my $rv = sysread($fh, $_='', 1024*31); # to fit in 32KB slab - unless ($rv) { # error (undef) or end of file (0) - my $action; - unless (defined $rv) { # was an error - $self->trace_msg("error on handle $fh: $!\n") if $trace >= 4; - $action = $actions->{error} || $actions->{eof}; - ++$errors; - # XXX an error may be a permenent condition of the handle - # if so we'll loop here - not good - } - else { - $action = $actions->{eof}; - $self->trace_msg("eof on handle $fh\n") if $trace >= 4; - } - if ($action->($fh)) { - $self->trace_msg("removing $fh from handle set\n") if $trace >= 4; - $ios->remove($fh); - } - next; - } - # action returns true if the response is now complete - # (we finish all handles - $actions->{read}->($fh) && ++$complete; - } - last if $complete; - } - return $errors; -} - - -sub receive_response_by_transport { - my $self = shift; - - my $info = $self->connection_info || die; - my ($pid, $rfh, $efh, $ios, $cmd) = @{$info}{qw(pid rfh efh ios cmd)}; - - my $frozen_response; - my $stderr_msg; - - $self->read_response_from_fh( { - $efh => { - error => sub { warn "error reading response stderr: $!"; 1 }, - eof => sub { warn "eof on stderr" if 0; 1 }, - read => sub { $stderr_msg .= $_; 0 }, - }, - $rfh => { - error => sub { warn "error reading response: $!"; 1 }, - eof => sub { warn "eof on stdout" if 0; 1 }, - read => sub { $frozen_response .= $_; 0 }, - }, - }); - - waitpid $info->{pid}, 0 - or warn "waitpid: $!"; # XXX do something more useful? - - die ref($self)." command (@$cmd) failed: $stderr_msg" - if not $frozen_response; # no output on stdout at all - - # XXX need to be able to detect and deal with corruption - my $response = $self->thaw_response($frozen_response); - - if ($stderr_msg) { - # add stderr messages as warnings (for PrintWarn) - $response->add_err(0, $stderr_msg, undef, $self->trace) - # but ignore warning from old version of blib - unless $stderr_msg =~ /^Using .*blib/ && "@$cmd" =~ /-Mblib/; - } - - return $response; -} - - -1; - -__END__ - -=head1 NAME - -DBD::Gofer::Transport::pipeone - DBD::Gofer client transport for testing - -=head1 SYNOPSIS - - $original_dsn = "..."; - DBI->connect("dbi:Gofer:transport=pipeone;dsn=$original_dsn",...) - -or, enable by setting the DBI_AUTOPROXY environment variable: - - export DBI_AUTOPROXY="dbi:Gofer:transport=pipeone" - -=head1 DESCRIPTION - -Connect via DBD::Gofer and execute each request by starting executing a subprocess. - -This is, as you might imagine, spectacularly inefficient! - -It's only intended for testing. Specifically it demonstrates that the server -side is completely stateless. - -It also provides a base class for the much more useful L -transport. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L - -L - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/stream.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/stream.pm deleted file mode 100644 index af954f8..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Gofer/Transport/stream.pm +++ /dev/null @@ -1,292 +0,0 @@ -package DBD::Gofer::Transport::stream; - -# $Id: stream.pm 14598 2010-12-21 22:53:25Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use Carp; - -use base qw(DBD::Gofer::Transport::pipeone); - -our $VERSION = "0.014599"; - -__PACKAGE__->mk_accessors(qw( - go_persist -)); - -my $persist_all = 5; -my %persist; - - -sub _connection_key { - my ($self) = @_; - return join "~", $self->go_url||"", @{ $self->go_perl || [] }; -} - - -sub _connection_get { - my ($self) = @_; - - my $persist = $self->go_persist; # = 0 can force non-caching - $persist = $persist_all if not defined $persist; - my $key = ($persist) ? $self->_connection_key : ''; - if ($persist{$key} && $self->_connection_check($persist{$key})) { - $self->trace_msg("reusing persistent connection $key\n",0) if $self->trace >= 1; - return $persist{$key}; - } - - my $connection = $self->_make_connection; - - if ($key) { - %persist = () if keys %persist > $persist_all; # XXX quick hack to limit subprocesses - $persist{$key} = $connection; - } - - return $connection; -} - - -sub _connection_check { - my ($self, $connection) = @_; - $connection ||= $self->connection_info; - my $pid = $connection->{pid}; - my $ok = (kill 0, $pid); - $self->trace_msg("_connection_check: $ok (pid $$)\n",0) if $self->trace; - return $ok; -} - - -sub _connection_kill { - my ($self) = @_; - my $connection = $self->connection_info; - my ($pid, $wfh, $rfh, $efh) = @{$connection}{qw(pid wfh rfh efh)}; - $self->trace_msg("_connection_kill: closing write handle\n",0) if $self->trace; - # closing the write file handle should be enough, generally - close $wfh; - # in future we may want to be more aggressive - #close $rfh; close $efh; kill 15, $pid - # but deleting from the persist cache... - delete $persist{ $self->_connection_key }; - # ... and removing the connection_info should suffice - $self->connection_info( undef ); - return; -} - - -sub _make_connection { - my ($self) = @_; - - my $go_perl = $self->go_perl; - my $cmd = [ @$go_perl, qw(-MDBI::Gofer::Transport::stream -e run_stdio_hex)]; - - #push @$cmd, "DBI_TRACE=2=/tmp/goferstream.log", "sh", "-c"; - if (my $url = $self->go_url) { - die "Only 'ssh:user\@host' style url supported by this transport" - unless $url =~ s/^ssh://; - my $ssh = $url; - my $setup_env = join "||", map { "source $_ 2>/dev/null" } qw(.bash_profile .bash_login .profile); - my $setup = $setup_env.q{; exec "$@"}; - # don't use $^X on remote system by default as it's possibly wrong - $cmd->[0] = 'perl' if "@$go_perl" eq $^X; - # -x not only 'Disables X11 forwarding' but also makes connections *much* faster - unshift @$cmd, qw(ssh -xq), split(' ', $ssh), qw(bash -c), $setup; - } - - $self->trace_msg("new connection: @$cmd\n",0) if $self->trace; - - # XXX add a handshake - some message from DBI::Gofer::Transport::stream that's - # sent as soon as it starts that we can wait for to report success - and soak up - # and report useful warnings etc from ssh before we get it? Increases latency though. - my $connection = $self->start_pipe_command($cmd); - return $connection; -} - - -sub transmit_request_by_transport { - my ($self, $request) = @_; - my $trace = $self->trace; - - my $connection = $self->connection_info || do { - my $con = $self->_connection_get; - $self->connection_info( $con ); - $con; - }; - - my $encoded_request = unpack("H*", $self->freeze_request($request)); - $encoded_request .= "\015\012"; - - my $wfh = $connection->{wfh}; - $self->trace_msg(sprintf("transmit_request_by_transport: to fh %s fd%d\n", $wfh, fileno($wfh)),0) - if $trace >= 4; - - # send frozen request - local $\; - $wfh->print($encoded_request) # autoflush enabled - or do { - my $err = $!; - # XXX could/should make new connection and retry - $self->_connection_kill; - die "Error sending request: $err"; - }; - $self->trace_msg("Request sent: $encoded_request\n",0) if $trace >= 4; - - return undef; # indicate no response yet (so caller calls receive_response_by_transport) -} - - -sub receive_response_by_transport { - my $self = shift; - my $trace = $self->trace; - - $self->trace_msg("receive_response_by_transport: awaiting response\n",0) if $trace >= 4; - my $connection = $self->connection_info || die; - my ($pid, $rfh, $efh, $cmd) = @{$connection}{qw(pid rfh efh cmd)}; - - my $errno = 0; - my $encoded_response; - my $stderr_msg; - - $self->read_response_from_fh( { - $efh => { - error => sub { warn "error reading response stderr: $!"; $errno||=$!; 1 }, - eof => sub { warn "eof reading efh" if $trace >= 4; 1 }, - read => sub { $stderr_msg .= $_; 0 }, - }, - $rfh => { - error => sub { warn "error reading response: $!"; $errno||=$!; 1 }, - eof => sub { warn "eof reading rfh" if $trace >= 4; 1 }, - read => sub { $encoded_response .= $_; ($encoded_response=~s/\015\012$//) ? 1 : 0 }, - }, - }); - - # if we got no output on stdout at all then the command has - # probably exited, possibly with an error to stderr. - # Turn this situation into a reasonably useful DBI error. - if (not $encoded_response) { - my @msg; - push @msg, "error while reading response: $errno" if $errno; - if ($stderr_msg) { - chomp $stderr_msg; - push @msg, sprintf "error reported by \"%s\" (pid %d%s): %s", - $self->cmd_as_string, - $pid, ((kill 0, $pid) ? "" : ", exited"), - $stderr_msg; - } - die join(", ", "No response received", @msg)."\n"; - } - - $self->trace_msg("Response received: $encoded_response\n",0) - if $trace >= 4; - - $self->trace_msg("Gofer stream stderr message: $stderr_msg\n",0) - if $stderr_msg && $trace; - - my $frozen_response = pack("H*", $encoded_response); - - # XXX need to be able to detect and deal with corruption - my $response = $self->thaw_response($frozen_response); - - if ($stderr_msg) { - # add stderr messages as warnings (for PrintWarn) - $response->add_err(0, $stderr_msg, undef, $trace) - # but ignore warning from old version of blib - unless $stderr_msg =~ /^Using .*blib/ && "@$cmd" =~ /-Mblib/; - } - - return $response; -} - -sub transport_timedout { - my $self = shift; - $self->_connection_kill; - return $self->SUPER::transport_timedout(@_); -} - -1; - -__END__ - -=head1 NAME - -DBD::Gofer::Transport::stream - DBD::Gofer transport for stdio streaming - -=head1 SYNOPSIS - - DBI->connect('dbi:Gofer:transport=stream;url=ssh:username@host.example.com;dsn=dbi:...',...) - -or, enable by setting the DBI_AUTOPROXY environment variable: - - export DBI_AUTOPROXY='dbi:Gofer:transport=stream;url=ssh:username@host.example.com' - -=head1 DESCRIPTION - -Without the C parameter it launches a subprocess as - - perl -MDBI::Gofer::Transport::stream -e run_stdio_hex - -and feeds requests into it and reads responses from it. But that's not very useful. - -With a C parameter it uses ssh to launch the subprocess -on a remote system. That's much more useful! - -It gives you secure remote access to DBI databases on any system you can login to. -Using ssh also gives you optional compression and many other features (see the -ssh manual for how to configure that and many other options via ~/.ssh/config file). - -The actual command invoked is something like: - - ssh -xq ssh:username@host.example.com bash -c $setup $run - -where $run is the command shown above, and $command is - - . .bash_profile 2>/dev/null || . .bash_login 2>/dev/null || . .profile 2>/dev/null; exec "$@" - -which is trying (in a limited and fairly unportable way) to setup the environment -(PATH, PERL5LIB etc) as it would be if you had logged in to that system. - -The "C" used in the command will default to the value of $^X when not using ssh. -On most systems that's the full path to the perl that's currently executing. - - -=head1 PERSISTENCE - -Currently gofer stream connections persist (remain connected) after all -database handles have been disconnected. This makes later connections in the -same process very fast. - -Currently up to 5 different gofer stream connections (based on url) can -persist. If more than 5 are in the cache when a new connection is made then -the cache is cleared before adding the new connection. Simple but effective. - -=head1 TO DO - -Document go_perl attribute - -Automatically reconnect (within reason) if there's a transport error. - -Decide on default for persistent connection - on or off? limits? ttl? - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L - -L - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Mem.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Mem.pm deleted file mode 100644 index 86af196..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Mem.pm +++ /dev/null @@ -1,376 +0,0 @@ -# -*- perl -*- -# -# DBD::Mem - A DBI driver for in-memory tables -# -# This module is currently maintained by -# -# Jens Rehsack -# -# Copyright (C) 2016,2017 by Jens Rehsack -# -# All rights reserved. -# -# You may distribute this module under the terms of either the GNU -# General Public License or the Artistic License, as specified in -# the Perl README file. - -require 5.008; -use strict; - -################# -package DBD::Mem; -################# -use base qw( DBI::DBD::SqlEngine ); -use vars qw($VERSION $ATTRIBUTION $drh); -$VERSION = '0.001'; -$ATTRIBUTION = 'DBD::Mem by Jens Rehsack'; - -# no need to have driver() unless you need private methods -# -sub driver ($;$) -{ - my ( $class, $attr ) = @_; - return $drh if ($drh); - - # do the real work in DBI::DBD::SqlEngine - # - $attr->{Attribution} = 'DBD::Mem by Jens Rehsack'; - $drh = $class->SUPER::driver($attr); - - return $drh; -} - -sub CLONE -{ - undef $drh; -} - -##################### -package DBD::Mem::dr; -##################### -$DBD::Mem::dr::imp_data_size = 0; -@DBD::Mem::dr::ISA = qw(DBI::DBD::SqlEngine::dr); - -# you could put some :dr private methods here - -# you may need to over-ride some DBI::DBD::SqlEngine::dr methods here -# but you can probably get away with just letting it do the work -# in most cases - -##################### -package DBD::Mem::db; -##################### -$DBD::Mem::db::imp_data_size = 0; -@DBD::Mem::db::ISA = qw(DBI::DBD::SqlEngine::db); - -use Carp qw/carp/; - -sub set_versions -{ - my $this = $_[0]; - $this->{mem_version} = $DBD::Mem::VERSION; - return $this->SUPER::set_versions(); -} - -sub init_valid_attributes -{ - my $dbh = shift; - - # define valid private attributes - # - # attempts to set non-valid attrs in connect() or - # with $dbh->{attr} will throw errors - # - # the attrs here *must* start with mem_ or foo_ - # - # see the STORE methods below for how to check these attrs - # - $dbh->{mem_valid_attrs} = { - mem_version => 1, # verbose DBD::Mem version - mem_valid_attrs => 1, # DBD::Mem::db valid attrs - mem_readonly_attrs => 1, # DBD::Mem::db r/o attrs - mem_meta => 1, # DBD::Mem public access for f_meta - mem_tables => 1, # DBD::Mem public access for f_meta - }; - $dbh->{mem_readonly_attrs} = { - mem_version => 1, # verbose DBD::Mem version - mem_valid_attrs => 1, # DBD::Mem::db valid attrs - mem_readonly_attrs => 1, # DBD::Mem::db r/o attrs - mem_meta => 1, # DBD::Mem public access for f_meta - }; - - $dbh->{mem_meta} = "mem_tables"; - - return $dbh->SUPER::init_valid_attributes(); -} - -sub get_mem_versions -{ - my ( $dbh, $table ) = @_; - $table ||= ''; - - my $meta; - my $class = $dbh->{ImplementorClass}; - $class =~ s/::db$/::Table/; - $table and ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); - $meta or ( $meta = {} and $class->bootstrap_table_meta( $dbh, $meta, $table ) ); - - return sprintf( "%s using %s", $dbh->{mem_version}, $AnyData2::VERSION ); -} - -package DBD::Mem::st; - -use strict; -use warnings; - -our $imp_data_size = 0; -our @ISA = qw(DBI::DBD::SqlEngine::st); - -############################ -package DBD::Mem::Statement; -############################ - -@DBD::Mem::Statement::ISA = qw(DBI::DBD::SqlEngine::Statement); - - -sub open_table ($$$$$) -{ - my ( $self, $data, $table, $createMode, $lockMode ) = @_; - - my $class = ref $self; - $class =~ s/::Statement/::Table/; - - my $flags = { - createMode => $createMode, - lockMode => $lockMode, - }; - if( defined( $data->{Database}->{mem_table_data}->{$table} ) && $data->{Database}->{mem_table_data}->{$table}) - { - my $t = $data->{Database}->{mem_tables}->{$table}; - $t->seek( $data, 0, 0 ); - return $t; - } - - return $self->SUPER::open_table($data, $table, $createMode, $lockMode); -} - -# ====== DataSource ============================================================ - -package DBD::Mem::DataSource; - -use strict; -use warnings; - -use Carp; - -@DBD::Mem::DataSource::ISA = "DBI::DBD::SqlEngine::DataSource"; - -sub complete_table_name ($$;$) -{ - my ( $self, $meta, $table, $respect_case ) = @_; - $table; -} - -sub open_data ($) -{ - my ( $self, $meta, $attrs, $flags ) = @_; - defined $meta->{data_tbl} or $meta->{data_tbl} = []; -} - -######################## -package DBD::Mem::Table; -######################## - -# shamelessly stolen from SQL::Statement::RAM - -use Carp qw/croak/; - -@DBD::Mem::Table::ISA = qw(DBI::DBD::SqlEngine::Table); - -use Carp qw(croak); - -sub new -{ - #my ( $class, $tname, $col_names, $data_tbl ) = @_; - my ( $class, $data, $attrs, $flags ) = @_; - my $self = $class->SUPER::new($data, $attrs, $flags); - - my $meta = $self->{meta}; - $self->{records} = $meta->{data_tbl}; - $self->{index} = 0; - - $self; -} - -sub bootstrap_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_; - - defined $meta->{sql_data_source} or $meta->{sql_data_source} = "DBD::Mem::DataSource"; - - $meta; -} - -sub fetch_row -{ - my ( $self, $data ) = @_; - - return $self->{row} = - ( $self->{records} and ( $self->{index} < scalar( @{ $self->{records} } ) ) ) - ? [ @{ $self->{records}->[ $self->{index}++ ] } ] - : undef; -} - -sub push_row -{ - my ( $self, $data, $fields ) = @_; - my $currentRow = $self->{index}; - $self->{index} = $currentRow + 1; - $self->{records}->[$currentRow] = $fields; - return 1; -} - -sub truncate -{ - my $self = shift; - return splice @{ $self->{records} }, $self->{index}, 1; -} - -sub push_names -{ - my ( $self, $data, $names ) = @_; - my $meta = $self->{meta}; - $meta->{col_names} = $self->{col_names} = $names; - $self->{org_col_names} = [ @{$names} ]; - $self->{col_nums} = {}; - $self->{col_nums}{ $names->[$_] } = $_ for ( 0 .. scalar @$names - 1 ); -} - -sub drop ($) -{ - my ($self, $data) = @_; - delete $data->{Database}{sql_meta}{$self->{table}}; - return 1; -} # drop - -sub seek -{ - my ( $self, $data, $pos, $whence ) = @_; - return unless defined $self->{records}; - - my ($currentRow) = $self->{index}; - if ( $whence == 0 ) - { - $currentRow = $pos; - } - elsif ( $whence == 1 ) - { - $currentRow += $pos; - } - elsif ( $whence == 2 ) - { - $currentRow = @{ $self->{records} } + $pos; - } - else - { - croak $self . "->seek: Illegal whence argument ($whence)"; - } - - $currentRow < 0 and - croak "Illegal row number: $currentRow"; - $self->{index} = $currentRow; -} - -1; - -=head1 NAME - -DBD::Mem - a DBI driver for Mem & MLMem files - -=head1 SYNOPSIS - - use DBI; - $dbh = DBI->connect('dbi:Mem:', undef, undef, {}); - $dbh = DBI->connect('dbi:Mem:', undef, undef, {RaiseError => 1}); - - # or - $dbh = DBI->connect('dbi:Mem:'); - $dbh = DBI->connect('DBI:Mem(RaiseError=1):'); - -and other variations on connect() as shown in the L docs and -. - -Use standard DBI prepare, execute, fetch, placeholders, etc., -see L for an example. - -=head1 DESCRIPTION - -DBD::Mem is a database management system that works right out of the box. -If you have a standard installation of Perl and DBI you can begin creating, -accessing, and modifying simple database tables without any further modules. -You can add other modules (e.g., SQL::Statement) for improved functionality. - -DBD::Mem doesn't store any data persistently - all data has the lifetime of -the instantiated C<$dbh>. The main reason to use DBD::Mem is to use extended -features of L where temporary tables are required. One can -use DBD::Mem to simulate C or sub-queries. - -Bundling C with L will allow us further compatibility checks -of L beyond the capabilities of L and -L. This will ensure DBI provided basis for drivers like -L or L are better prepared and tested for -not-file based backends. - -=head2 Metadata - -There're no new meta data introduced by C. See -L for full description. - -=head1 GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS - -If you need help installing or using DBD::Mem, please write to the DBI -users mailing list at L or to the -comp.lang.perl.modules newsgroup on usenet. I cannot always answer -every question quickly but there are many on the mailing list or in -the newsgroup who can. - -DBD developers for DBD's which rely on DBI::DBD::SqlEngine or DBD::Mem or -use one of them as an example are suggested to join the DBI developers -mailing list at L and strongly encouraged to join our -IRC channel at L. - -If you have suggestions, ideas for improvements, or bugs to report, please -report a bug as described in DBI. Do not mail any of the authors directly, -you might not get an answer. - -When reporting bugs, please send the output of C<< $dbh->mem_versions($table) >> -for a table that exhibits the bug and as small a sample as you can make of -the code that produces the bug. And of course, patches are welcome, too -:-). - -If you need enhancements quickly, you can get commercial support as -described at L or you can contact Jens Rehsack -at rehsack@cpan.org for commercial support. - -=head1 AUTHOR AND COPYRIGHT - -This module is written by Jens Rehsack < rehsack AT cpan.org >. - - Copyright (c) 2016- by Jens Rehsack, all rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=head1 SEE ALSO - -L for the Database interface of the Perl Programming Language. - -L and L for the available SQL engines. - -L where the implementation is shamelessly stolen from -to allow DBI bundled Pure-Perl drivers increase the test coverage. - -L using C for an incredible fast in-memory database engine. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/NullP.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/NullP.pm deleted file mode 100644 index f70c67c..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/NullP.pm +++ /dev/null @@ -1,206 +0,0 @@ -use strict; -{ - package DBD::NullP; - - require DBI; - require Carp; - - our @EXPORT = qw(); # Do NOT @EXPORT anything. - our $VERSION = "12.014715"; - -# $Id: NullP.pm 14714 2011-02-22 17:27:07Z Tim $ -# -# Copyright (c) 1994-2007 Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - our $drh = undef; # holds driver handle once initialised - - sub driver{ - return $drh if $drh; - my($class, $attr) = @_; - $class .= "::dr"; - ($drh) = DBI::_new_drh($class, { - 'Name' => 'NullP', - 'Version' => $VERSION, - 'Attribution' => 'DBD Example Null Perl stub by Tim Bunce', - }, [ qw'example implementors private data']); - $drh; - } - - sub CLONE { - undef $drh; - } -} - - -{ package DBD::NullP::dr; # ====== DRIVER ====== - our $imp_data_size = 0; - use strict; - - sub connect { # normally overridden, but a handy default - my $dbh = shift->SUPER::connect(@_) - or return; - $dbh->STORE(Active => 1); - $dbh; - } - - - sub DESTROY { undef } -} - - -{ package DBD::NullP::db; # ====== DATABASE ====== - our $imp_data_size = 0; - use strict; - use Carp qw(croak); - - # Added get_info to support tests in 10examp.t - sub get_info { - my ($dbh, $type) = @_; - - if ($type == 29) { # identifier quote - return '"'; - } - return; - } - - # Added table_info to support tests in 10examp.t - sub table_info { - my ($dbh, $catalog, $schema, $table, $type) = @_; - - my ($outer, $sth) = DBI::_new_sth($dbh, { - 'Statement' => 'tables', - }); - if (defined($type) && $type eq '%' && # special case for tables('','','','%') - grep {defined($_) && $_ eq ''} ($catalog, $schema, $table)) { - $outer->{dbd_nullp_data} = [[undef, undef, undef, 'TABLE', undef], - [undef, undef, undef, 'VIEW', undef], - [undef, undef, undef, 'ALIAS', undef]]; - } elsif (defined($catalog) && $catalog eq '%' && # special case for tables('%','','') - grep {defined($_) && $_ eq ''} ($schema, $table)) { - $outer->{dbd_nullp_data} = [['catalog1', undef, undef, undef, undef], - ['catalog2', undef, undef, undef, undef]]; - } else { - $outer->{dbd_nullp_data} = [['catalog', 'schema', 'table1', 'TABLE']]; - $outer->{dbd_nullp_data} = [['catalog', 'schema', 'table2', 'TABLE']]; - $outer->{dbd_nullp_data} = [['catalog', 'schema', 'table3', 'TABLE']]; - } - $outer->STORE(NUM_OF_FIELDS => 5); - $sth->STORE(Active => 1); - return $outer; - } - - sub prepare { - my ($dbh, $statement)= @_; - - my ($outer, $sth) = DBI::_new_sth($dbh, { - 'Statement' => $statement, - }); - - return $outer; - } - - sub FETCH { - my ($dbh, $attrib) = @_; - # In reality this would interrogate the database engine to - # either return dynamic values that cannot be precomputed - # or fetch and cache attribute values too expensive to prefetch. - return $dbh->SUPER::FETCH($attrib); - } - - sub STORE { - my ($dbh, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - if ($attrib eq 'AutoCommit') { - Carp::croak("Can't disable AutoCommit") unless $value; - # convert AutoCommit values to magic ones to let DBI - # know that the driver has 'handled' the AutoCommit attribute - $value = ($value) ? -901 : -900; - } elsif ($attrib eq 'nullp_set_err') { - # a fake attribute to produce a test case where STORE issues a warning - $dbh->set_err($value, $value); - } - return $dbh->SUPER::STORE($attrib, $value); - } - - sub ping { 1 } - - sub disconnect { - shift->STORE(Active => 0); - } - -} - - -{ package DBD::NullP::st; # ====== STATEMENT ====== - our $imp_data_size = 0; - use strict; - - sub bind_param { - my ($sth, $param, $value, $attr) = @_; - $sth->{ParamValues}{$param} = $value; - $sth->{ParamAttr}{$param} = $attr - if defined $attr; # attr is sticky if not explicitly set - return 1; - } - - sub execute { - my $sth = shift; - $sth->bind_param($_, $_[$_-1]) for (1..@_); - if ($sth->{Statement} =~ m/^ \s* SELECT \s+/xmsi) { - $sth->STORE(NUM_OF_FIELDS => 1); - $sth->{NAME} = [ "fieldname" ]; - # just for the sake of returning something, we return the params - my $params = $sth->{ParamValues} || {}; - $sth->{dbd_nullp_data} = [ @{$params}{ sort keys %$params } ]; - $sth->STORE(Active => 1); - } - # force a sleep - handy for testing - elsif ($sth->{Statement} =~ m/^ \s* SLEEP \s+ (\S+) /xmsi) { - my $secs = $1; - if (eval { require Time::HiRes; defined &Time::HiRes::sleep }) { - Time::HiRes::sleep($secs); - } - else { - sleep $secs; - } - } - # force an error - handy for testing - elsif ($sth->{Statement} =~ m/^ \s* ERROR \s+ (\d+) \s* (.*) /xmsi) { - return $sth->set_err($1, $2); - } - # anything else is silently ignored, successfully - 1; - } - - sub fetchrow_arrayref { - my $sth = shift; - my $data = shift @{$sth->{dbd_nullp_data}}; - if (!$data || !@$data) { - $sth->finish; # no more data so finish - return undef; - } - return $sth->_set_fbav($data); - } - *fetch = \&fetchrow_arrayref; # alias - - sub FETCH { - my ($sth, $attrib) = @_; - # would normally validate and only fetch known attributes - # else pass up to DBI to handle - return $sth->SUPER::FETCH($attrib); - } - - sub STORE { - my ($sth, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - return $sth->SUPER::STORE($attrib, $value); - } - -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Proxy.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Proxy.pm deleted file mode 100644 index 4240dab..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Proxy.pm +++ /dev/null @@ -1,1004 +0,0 @@ -# -*- perl -*- -# -# -# DBD::Proxy - DBI Proxy driver -# -# -# Copyright (c) 1997,1998 Jochen Wiedmann -# -# The DBD::Proxy module is free software; you can redistribute it and/or -# modify it under the same terms as Perl itself. In particular permission -# is granted to Tim Bunce for distributing this as a part of the DBI. -# -# -# Author: Jochen Wiedmann -# Am Eisteich 9 -# 72555 Metzingen -# Germany -# -# Email: joe@ispsoft.de -# Phone: +49 7123 14881 -# - -use strict; -use Carp; - -require DBI; -DBI->require_version(1.0201); - -use RPC::PlClient 0.2000; # XXX change to 0.2017 once it's released - -{ package DBD::Proxy::RPC::PlClient; - @DBD::Proxy::RPC::PlClient::ISA = qw(RPC::PlClient); - sub Call { - my $self = shift; - if ($self->{debug}) { - my ($rpcmeth, $obj, $method, @args) = @_; - local $^W; # silence undefs - Carp::carp("Server $rpcmeth $method(@args)"); - } - return $self->SUPER::Call(@_); - } -} - - -package DBD::Proxy; - -use vars qw($VERSION $drh %ATTR); - -$VERSION = "0.2004"; - -$drh = undef; # holds driver handle once initialised - -%ATTR = ( # common to db & st, see also %ATTR in DBD::Proxy::db & ::st - 'Warn' => 'local', - 'Active' => 'local', - 'Kids' => 'local', - 'CachedKids' => 'local', - 'PrintError' => 'local', - 'RaiseError' => 'local', - 'HandleError' => 'local', - 'TraceLevel' => 'cached', - 'CompatMode' => 'local', -); - -sub driver ($$) { - if (!$drh) { - my($class, $attr) = @_; - - $class .= "::dr"; - - $drh = DBI::_new_drh($class, { - 'Name' => 'Proxy', - 'Version' => $VERSION, - 'Attribution' => 'DBD::Proxy by Jochen Wiedmann', - }); - $drh->STORE(CompatMode => 1); # disable DBI dispatcher attribute cache (for FETCH) - } - $drh; -} - -sub CLONE { - undef $drh; -} - -sub proxy_set_err { - my ($h,$errmsg) = @_; - my ($err, $state) = ($errmsg =~ s/ \[err=(.*?),state=(.*?)\]//) - ? ($1, $2) : (1, ' ' x 5); - return $h->set_err($err, $errmsg, $state); -} - -package DBD::Proxy::dr; # ====== DRIVER ====== - -$DBD::Proxy::dr::imp_data_size = 0; - -sub connect ($$;$$) { - my($drh, $dsn, $user, $auth, $attr)= @_; - my($dsnOrig) = $dsn; - - my %attr = %$attr; - my ($var, $val); - while (length($dsn)) { - if ($dsn =~ /^dsn=(.*)/) { - $attr{'dsn'} = $1; - last; - } - if ($dsn =~ /^(.*?);(.*)/) { - $var = $1; - $dsn = $2; - } else { - $var = $dsn; - $dsn = ''; - } - if ($var =~ /^(.*?)=(.*)/) { - $var = $1; - $val = $2; - $attr{$var} = $val; - } - } - - my $err = ''; - if (!defined($attr{'hostname'})) { $err .= " Missing hostname."; } - if (!defined($attr{'port'})) { $err .= " Missing port."; } - if (!defined($attr{'dsn'})) { $err .= " Missing remote dsn."; } - - # Create a cipher object, if requested - my $cipherRef = undef; - if ($attr{'cipher'}) { - $cipherRef = eval { $attr{'cipher'}->new(pack('H*', - $attr{'key'})) }; - if ($@) { $err .= " Cannot create cipher object: $@."; } - } - my $userCipherRef = undef; - if ($attr{'userkey'}) { - my $cipher = $attr{'usercipher'} || $attr{'cipher'}; - $userCipherRef = eval { $cipher->new(pack('H*', $attr{'userkey'})) }; - if ($@) { $err .= " Cannot create usercipher object: $@."; } - } - - return DBD::Proxy::proxy_set_err($drh, $err) if $err; # Returns undef - - my %client_opts = ( - 'peeraddr' => $attr{'hostname'}, - 'peerport' => $attr{'port'}, - 'socket_proto' => 'tcp', - 'application' => $attr{dsn}, - 'user' => $user || '', - 'password' => $auth || '', - 'version' => $DBD::Proxy::VERSION, - 'cipher' => $cipherRef, - 'debug' => $attr{debug} || 0, - 'timeout' => $attr{timeout} || undef, - 'logfile' => $attr{logfile} || undef - ); - # Options starting with 'proxy_rpc_' are forwarded to the RPC layer after - # stripping the prefix. - while (my($var,$val) = each %attr) { - if ($var =~ s/^proxy_rpc_//) { - $client_opts{$var} = $val; - } - } - # Create an RPC::PlClient object. - my($client, $msg) = eval { DBD::Proxy::RPC::PlClient->new(%client_opts) }; - - return DBD::Proxy::proxy_set_err($drh, "Cannot log in to DBI::ProxyServer: $@") - if $@; # Returns undef - return DBD::Proxy::proxy_set_err($drh, "Constructor didn't return a handle: $msg") - unless ($msg =~ /^((?:\w+|\:\:)+)=(\w+)/); # Returns undef - - $msg = RPC::PlClient::Object->new($1, $client, $msg); - - my $max_proto_ver; - my ($server_ver_str) = eval { $client->Call('Version') }; - if ( $@ ) { - # Server denies call, assume legacy protocol. - $max_proto_ver = 1; - } else { - # Parse proxy server version. - my ($server_ver_num) = $server_ver_str =~ /^DBI::ProxyServer\s+([\d\.]+)/; - $max_proto_ver = $server_ver_num >= 0.3 ? 2 : 1; - } - my $req_proto_ver; - if ( exists $attr{proxy_lazy_prepare} ) { - $req_proto_ver = ($attr{proxy_lazy_prepare} == 0) ? 2 : 1; - return DBD::Proxy::proxy_set_err($drh, - "DBI::ProxyServer does not support synchronous statement preparation.") - if $max_proto_ver < $req_proto_ver; - } - - # Switch to user specific encryption mode, if desired - if ($userCipherRef) { - $client->{'cipher'} = $userCipherRef; - } - - # create a 'blank' dbh - my $this = DBI::_new_dbh($drh, { - 'Name' => $dsnOrig, - 'proxy_dbh' => $msg, - 'proxy_client' => $client, - 'RowCacheSize' => $attr{'RowCacheSize'} || 20, - 'proxy_proto_ver' => $req_proto_ver || 1 - }); - - foreach $var (keys %attr) { - if ($var =~ /proxy_/) { - $this->{$var} = $attr{$var}; - } - } - $this->SUPER::STORE('Active' => 1); - - $this; -} - - -sub DESTROY { undef } - - -package DBD::Proxy::db; # ====== DATABASE ====== - -$DBD::Proxy::db::imp_data_size = 0; - -# XXX probably many more methods need to be added here -# in order to trigger our AUTOLOAD to redirect them to the server. -# (Unless the sub is declared it's bypassed by perl method lookup.) -# See notes in ToDo about method metadata -# The question is whether to add all the methods in %DBI::DBI_methods -# to the corresponding classes (::db, ::st etc) -# Also need to consider methods that, if proxied, would change the server state -# in a way that might not be visible on the client, ie begin_work -> AutoCommit. - -sub commit; -sub rollback; -sub ping; - -use vars qw(%ATTR $AUTOLOAD); - -# inherited: STORE / FETCH against this class. -# local: STORE / FETCH against parent class. -# cached: STORE to remote and local objects, FETCH from local. -# remote: STORE / FETCH against remote object only (default). -# -# Note: Attribute names starting with 'proxy_' always treated as 'inherited'. -# -%ATTR = ( # see also %ATTR in DBD::Proxy::st - %DBD::Proxy::ATTR, - RowCacheSize => 'inherited', - #AutoCommit => 'cached', - 'FetchHashKeyName' => 'cached', - Statement => 'local', - Driver => 'local', - dbi_connect_closure => 'local', - Username => 'local', -); - -sub AUTOLOAD { - my $method = $AUTOLOAD; - $method =~ s/(.*::(.*)):://; - my $class = $1; - my $type = $2; - #warn "AUTOLOAD of $method (class=$class, type=$type)"; - my %expand = ( - 'method' => $method, - 'class' => $class, - 'type' => $type, - 'call' => "$method(\@_)", - # XXX was trying to be smart but was tripping up over the DBI's own - # smartness. Disabled, but left here in case there are issues. - # 'call' => (UNIVERSAL::can("DBI::_::$type", $method)) ? "$method(\@_)" : "func(\@_, '$method')", - ); - - my $method_code = q{ - package ~class~; - sub ~method~ { - my $h = shift; - local $@; - my @result = wantarray - ? eval { $h->{'proxy_~type~h'}->~call~ } - : eval { scalar $h->{'proxy_~type~h'}->~call~ }; - return DBD::Proxy::proxy_set_err($h, $@) if $@; - return wantarray ? @result : $result[0]; - } - }; - $method_code =~ s/\~(\w+)\~/$expand{$1}/eg; - local $SIG{__DIE__} = 'DEFAULT'; - my $err = do { local $@; eval $method_code.2; $@ }; - die $err if $err; - goto &$AUTOLOAD; -} - -sub DESTROY { - my $dbh = shift; - local $@ if $@; # protect $@ - $dbh->disconnect if $dbh->SUPER::FETCH('Active'); -} - - -sub connected { } # client-side not server-side, RT#75868 - -sub disconnect ($) { - my ($dbh) = @_; - - # Sadly the Proxy too-often disagrees with the backend database - # on the subject of 'Active'. In the short term, I'd like the - # Proxy to ease up and let me decide when it's proper to go over - # the wire. This ultimately applies to finish() as well. - #return unless $dbh->SUPER::FETCH('Active'); - - # Drop database connection at remote end - my $rdbh = $dbh->{'proxy_dbh'}; - if ( $rdbh ) { - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - eval { $rdbh->disconnect() } ; - DBD::Proxy::proxy_set_err($dbh, $@) if $@; - } - - # Close TCP connect to remote - # XXX possibly best left till DESTROY? Add a config attribute to choose? - #$dbh->{proxy_client}->Disconnect(); # Disconnect method requires newer PlRPC module - $dbh->{proxy_client}->{socket} = undef; # hack - - $dbh->SUPER::STORE('Active' => 0); - 1; -} - - -sub STORE ($$$) { - my($dbh, $attr, $val) = @_; - my $type = $ATTR{$attr} || 'remote'; - - if ($attr eq 'TraceLevel') { - warn("TraceLevel $val"); - my $pc = $dbh->{proxy_client} || die; - $pc->{logfile} ||= 1; # XXX hack - $pc->{debug} = ($val && $val >= 4); - $pc->Debug("$pc debug enabled") if $pc->{debug}; - } - - if ($attr =~ /^proxy_/ || $type eq 'inherited') { - $dbh->{$attr} = $val; - return 1; - } - - if ($type eq 'remote' || $type eq 'cached') { - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $dbh->{'proxy_dbh'}->STORE($attr => $val) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; # returns undef - $dbh->SUPER::STORE($attr => $val) if $type eq 'cached'; - return $result; - } - return $dbh->SUPER::STORE($attr => $val); -} - -sub FETCH ($$) { - my($dbh, $attr) = @_; - # we only get here for cached attribute values if the handle is in CompatMode - # otherwise the DBI dispatcher handles the FETCH itself from the attribute cache. - my $type = $ATTR{$attr} || 'remote'; - - if ($attr =~ /^proxy_/ || $type eq 'inherited' || $type eq 'cached') { - return $dbh->{$attr}; - } - - return $dbh->SUPER::FETCH($attr) unless $type eq 'remote'; - - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $dbh->{'proxy_dbh'}->FETCH($attr) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; - return $result; -} - -sub prepare ($$;$) { - my($dbh, $stmt, $attr) = @_; - my $sth = DBI::_new_sth($dbh, { - 'Statement' => $stmt, - 'proxy_attr' => $attr, - 'proxy_cache_only' => 0, - 'proxy_params' => [], - } - ); - my $proto_ver = $dbh->{'proxy_proto_ver'}; - if ( $proto_ver > 1 ) { - $sth->{'proxy_attr_cache'} = {cache_filled => 0}; - my $rdbh = $dbh->{'proxy_dbh'}; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $rsth = eval { $rdbh->prepare($sth->{'Statement'}, $sth->{'proxy_attr'}, undef, $proto_ver) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - return DBD::Proxy::proxy_set_err($sth, "Constructor didn't return a handle: $rsth") - unless ($rsth =~ /^((?:\w+|\:\:)+)=(\w+)/); - - my $client = $dbh->{'proxy_client'}; - $rsth = RPC::PlClient::Object->new($1, $client, $rsth); - - $sth->{'proxy_sth'} = $rsth; - # If statement is a positioned update we do not want any readahead. - $sth->{'RowCacheSize'} = 1 if $stmt =~ /\bfor\s+update\b/i; - # Since resources are used by prepared remote handle, mark us active. - $sth->SUPER::STORE(Active => 1); - } - $sth; -} - -sub quote { - my $dbh = shift; - my $proxy_quote = $dbh->{proxy_quote} || 'remote'; - - return $dbh->SUPER::quote(@_) - if $proxy_quote eq 'local' && @_ == 1; - - # For the common case of only a single argument - # (no $data_type) we could learn and cache the behaviour. - # Or we could probe the driver with a few test cases. - # Or we could add a way to ask the DBI::ProxyServer - # if $dbh->can('quote') == \&DBI::_::db::quote. - # Tim - # - # Sounds all *very* smart to me. I'd rather suggest to - # implement some of the typical quote possibilities - # and let the user set - # $dbh->{'proxy_quote'} = 'backslash_escaped'; - # for example. - # Jochen - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $dbh->{'proxy_dbh'}->quote(@_) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; - return $result; -} - -sub table_info { - my $dbh = shift; - my $rdbh = $dbh->{'proxy_dbh'}; - #warn "table_info(@_)"; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my($numFields, $names, $types, @rows) = eval { $rdbh->table_info(@_) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; - my ($sth, $inner) = DBI::_new_sth($dbh, { - 'Statement' => "SHOW TABLES", - 'proxy_params' => [], - 'proxy_data' => \@rows, - 'proxy_attr_cache' => { - 'NUM_OF_PARAMS' => 0, - 'NUM_OF_FIELDS' => $numFields, - 'NAME' => $names, - 'TYPE' => $types, - 'cache_filled' => 1 - }, - 'proxy_cache_only' => 1, - }); - $sth->SUPER::STORE('NUM_OF_FIELDS' => $numFields); - $inner->{NAME} = $names; - $inner->{TYPE} = $types; - $sth->SUPER::STORE('Active' => 1); # already execute()'d - $sth->{'proxy_rows'} = @rows; - return $sth; -} - -sub tables { - my $dbh = shift; - #warn "tables(@_)"; - return $dbh->SUPER::tables(@_); -} - - -sub type_info_all { - my $dbh = shift; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $dbh->{'proxy_dbh'}->type_info_all(@_) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; - return $result; -} - - -package DBD::Proxy::st; # ====== STATEMENT ====== - -$DBD::Proxy::st::imp_data_size = 0; - -use vars qw(%ATTR); - -# inherited: STORE to current object. FETCH from current if exists, else call up -# to the (proxy) database object. -# local: STORE / FETCH against parent class. -# cache_only: STORE noop (read-only). FETCH from private_* if exists, else call -# remote and cache the result. -# remote: STORE / FETCH against remote object only (default). -# -# Note: Attribute names starting with 'proxy_' always treated as 'inherited'. -# -%ATTR = ( # see also %ATTR in DBD::Proxy::db - %DBD::Proxy::ATTR, - 'Database' => 'local', - 'RowsInCache' => 'local', - 'RowCacheSize' => 'inherited', - 'NULLABLE' => 'cache_only', - 'NAME' => 'cache_only', - 'TYPE' => 'cache_only', - 'PRECISION' => 'cache_only', - 'SCALE' => 'cache_only', - 'NUM_OF_FIELDS' => 'cache_only', - 'NUM_OF_PARAMS' => 'cache_only' -); - -*AUTOLOAD = \&DBD::Proxy::db::AUTOLOAD; - -sub execute ($@) { - my $sth = shift; - my $params = @_ ? \@_ : $sth->{'proxy_params'}; - - # new execute, so delete any cached rows from previous execute - undef $sth->{'proxy_data'}; - undef $sth->{'proxy_rows'}; - - my $rsth = $sth->{proxy_sth}; - my $dbh = $sth->FETCH('Database'); - my $proto_ver = $dbh->{proxy_proto_ver}; - - my ($numRows, @outData); - - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - if ( $proto_ver > 1 ) { - ($numRows, @outData) = eval { $rsth->execute($params, $proto_ver) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - - # Attributes passed back only on the first execute() of a statement. - unless ($sth->{proxy_attr_cache}->{cache_filled}) { - my ($numFields, $numParams, $names, $types) = splice(@outData, 0, 4); - $sth->{'proxy_attr_cache'} = { - 'NUM_OF_FIELDS' => $numFields, - 'NUM_OF_PARAMS' => $numParams, - 'NAME' => $names, - 'cache_filled' => 1 - }; - $sth->SUPER::STORE('NUM_OF_FIELDS' => $numFields); - $sth->SUPER::STORE('NUM_OF_PARAMS' => $numParams); - } - - } - else { - if ($rsth) { - ($numRows, @outData) = eval { $rsth->execute($params, $proto_ver) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - - } - else { - my $rdbh = $dbh->{'proxy_dbh'}; - - # Legacy prepare is actually prepare + first execute on the server. - ($rsth, @outData) = - eval { $rdbh->prepare($sth->{'Statement'}, - $sth->{'proxy_attr'}, $params, $proto_ver) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - return DBD::Proxy::proxy_set_err($sth, "Constructor didn't return a handle: $rsth") - unless ($rsth =~ /^((?:\w+|\:\:)+)=(\w+)/); - - my $client = $dbh->{'proxy_client'}; - $rsth = RPC::PlClient::Object->new($1, $client, $rsth); - - my ($numFields, $numParams, $names, $types) = splice(@outData, 0, 4); - $sth->{'proxy_sth'} = $rsth; - $sth->{'proxy_attr_cache'} = { - 'NUM_OF_FIELDS' => $numFields, - 'NUM_OF_PARAMS' => $numParams, - 'NAME' => $names - }; - $sth->SUPER::STORE('NUM_OF_FIELDS' => $numFields); - $sth->SUPER::STORE('NUM_OF_PARAMS' => $numParams); - $numRows = shift @outData; - } - } - # Always condition active flag. - $sth->SUPER::STORE('Active' => 1) if $sth->FETCH('NUM_OF_FIELDS'); # is SELECT - $sth->{'proxy_rows'} = $numRows; - # Any remaining items are output params. - if (@outData) { - foreach my $p (@$params) { - if (ref($p->[0])) { - my $ref = shift @outData; - ${$p->[0]} = $$ref; - } - } - } - - $sth->{'proxy_rows'} || '0E0'; -} - -sub fetch ($) { - my $sth = shift; - - my $data = $sth->{'proxy_data'}; - - $sth->{'proxy_rows'} = 0 unless defined $sth->{'proxy_rows'}; - - if(!$data || !@$data) { - return undef unless $sth->SUPER::FETCH('Active'); - - my $rsth = $sth->{'proxy_sth'}; - if (!$rsth) { - die "Attempt to fetch row without execute"; - } - my $num_rows = $sth->FETCH('RowCacheSize') || 20; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my @rows = eval { $rsth->fetch($num_rows) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - unless (@rows == $num_rows) { - undef $sth->{'proxy_data'}; - # server side has already called finish - $sth->SUPER::STORE(Active => 0); - } - return undef unless @rows; - $sth->{'proxy_data'} = $data = [@rows]; - } - my $row = shift @$data; - - $sth->SUPER::STORE(Active => 0) if ( $sth->{proxy_cache_only} and !@$data ); - $sth->{'proxy_rows'}++; - return $sth->_set_fbav($row); -} -*fetchrow_arrayref = \&fetch; - -sub rows ($) { - my $rows = shift->{'proxy_rows'}; - return (defined $rows) ? $rows : -1; -} - -sub finish ($) { - my($sth) = @_; - return 1 unless $sth->SUPER::FETCH('Active'); - my $rsth = $sth->{'proxy_sth'}; - $sth->SUPER::STORE('Active' => 0); - return 0 unless $rsth; # Something's out of sync - my $no_finish = exists($sth->{'proxy_no_finish'}) - ? $sth->{'proxy_no_finish'} - : $sth->FETCH('Database')->{'proxy_no_finish'}; - unless ($no_finish) { - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $rsth->finish() }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - return $result; - } - 1; -} - -sub STORE ($$$) { - my($sth, $attr, $val) = @_; - my $type = $ATTR{$attr} || 'remote'; - - if ($attr =~ /^proxy_/ || $type eq 'inherited') { - $sth->{$attr} = $val; - return 1; - } - - if ($type eq 'cache_only') { - return 0; - } - - if ($type eq 'remote' || $type eq 'cached') { - my $rsth = $sth->{'proxy_sth'} or return undef; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $rsth->STORE($attr => $val) }; - return DBD::Proxy::proxy_set_err($sth, $@) if ($@); - return $result if $type eq 'remote'; # else fall through to cache locally - } - return $sth->SUPER::STORE($attr => $val); -} - -sub FETCH ($$) { - my($sth, $attr) = @_; - - if ($attr =~ /^proxy_/) { - return $sth->{$attr}; - } - - my $type = $ATTR{$attr} || 'remote'; - if ($type eq 'inherited') { - if (exists($sth->{$attr})) { - return $sth->{$attr}; - } - return $sth->FETCH('Database')->{$attr}; - } - - if ($type eq 'cache_only' && - exists($sth->{'proxy_attr_cache'}->{$attr})) { - return $sth->{'proxy_attr_cache'}->{$attr}; - } - - if ($type ne 'local') { - my $rsth = $sth->{'proxy_sth'} or return undef; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $rsth->FETCH($attr) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - return $result; - } - elsif ($attr eq 'RowsInCache') { - my $data = $sth->{'proxy_data'}; - $data ? @$data : 0; - } - else { - $sth->SUPER::FETCH($attr); - } -} - -sub bind_param ($$$@) { - my $sth = shift; my $param = shift; - $sth->{'proxy_params'}->[$param-1] = [@_]; -} -*bind_param_inout = \&bind_param; - -sub DESTROY { - my $sth = shift; - $sth->finish if $sth->SUPER::FETCH('Active'); -} - - -1; - - -__END__ - -=head1 NAME - -DBD::Proxy - A proxy driver for the DBI - -=head1 SYNOPSIS - - use DBI; - - $dbh = DBI->connect("dbi:Proxy:hostname=$host;port=$port;dsn=$db", - $user, $passwd); - - # See the DBI module documentation for full details - -=head1 DESCRIPTION - -DBD::Proxy is a Perl module for connecting to a database via a remote -DBI driver. See L for an alternative with different trade-offs. - -This is of course not needed for DBI drivers which already -support connecting to a remote database, but there are engines which -don't offer network connectivity. - -Another application is offering database access through a firewall, as -the driver offers query based restrictions. For example you can -restrict queries to exactly those that are used in a given CGI -application. - -Speaking of CGI, another application is (or rather, will be) to reduce -the database connect/disconnect overhead from CGI scripts by using -proxying the connect_cached method. The proxy server will hold the -database connections open in a cache. The CGI script then trades the -database connect/disconnect overhead for the DBD::Proxy -connect/disconnect overhead which is typically much less. - - -=head1 CONNECTING TO THE DATABASE - -Before connecting to a remote database, you must ensure, that a Proxy -server is running on the remote machine. There's no default port, so -you have to ask your system administrator for the port number. See -L for details. - -Say, your Proxy server is running on machine "alpha", port 3334, and -you'd like to connect to an ODBC database called "mydb" as user "joe" -with password "hello". When using DBD::ODBC directly, you'd do a - - $dbh = DBI->connect("DBI:ODBC:mydb", "joe", "hello"); - -With DBD::Proxy this becomes - - $dsn = "DBI:Proxy:hostname=alpha;port=3334;dsn=DBI:ODBC:mydb"; - $dbh = DBI->connect($dsn, "joe", "hello"); - -You see, this is mainly the same. The DBD::Proxy module will create a -connection to the Proxy server on "alpha" which in turn will connect -to the ODBC database. - -Refer to the L documentation on the C method for a way -to automatically use DBD::Proxy without having to change your code. - -DBD::Proxy's DSN string has the format - - $dsn = "DBI:Proxy:key1=val1; ... ;keyN=valN;dsn=valDSN"; - -In other words, it is a collection of key/value pairs. The following -keys are recognized: - -=over 4 - -=item hostname - -=item port - -Hostname and port of the Proxy server; these keys must be present, -no defaults. Example: - - hostname=alpha;port=3334 - -=item dsn - -The value of this attribute will be used as a dsn name by the Proxy -server. Thus it must have the format C, in particular -it will contain colons. The I value may contain semicolons, hence -this key *must* be the last and it's value will be the complete -remaining part of the dsn. Example: - - dsn=DBI:ODBC:mydb - -=item cipher - -=item key - -=item usercipher - -=item userkey - -By using these fields you can enable encryption. If you set, -for example, - - cipher=$class;key=$key - -(note the semicolon) then DBD::Proxy will create a new cipher object -by executing - - $cipherRef = $class->new(pack("H*", $key)); - -and pass this object to the RPC::PlClient module when creating a -client. See L. Example: - - cipher=IDEA;key=97cd2375efa329aceef2098babdc9721 - -The usercipher/userkey attributes allow you to use two phase encryption: -The cipher/key encryption will be used in the login and authorisation -phase. Once the client is authorised, he will change to usercipher/userkey -encryption. Thus the cipher/key pair is a B based secret, typically -less secure than the usercipher/userkey secret and readable by anyone. -The usercipher/userkey secret is B private secret. - -Of course encryption requires an appropriately configured server. See -L. - -=item debug - -Turn on debugging mode - -=item stderr - -This attribute will set the corresponding attribute of the RPC::PlClient -object, thus logging will not use syslog(), but redirected to stderr. -This is the default under Windows. - - stderr=1 - -=item logfile - -Similar to the stderr attribute, but output will be redirected to the -given file. - - logfile=/dev/null - -=item RowCacheSize - -The DBD::Proxy driver supports this attribute (which is DBI standard, -as of DBI 1.02). It's used to reduce network round-trips by fetching -multiple rows in one go. The current default value is 20, but this may -change. - - -=item proxy_no_finish - -This attribute can be used to reduce network traffic: If the -application is calling $sth->finish() then the proxy tells the server -to finish the remote statement handle. Of course this slows down things -quite a lot, but is perfectly good for reducing memory usage with -persistent connections. - -However, if you set the I attribute to a TRUE value, -either in the database handle or in the statement handle, then finish() -calls will be suppressed. This is what you want, for example, in small -and fast CGI applications. - -=item proxy_quote - -This attribute can be used to reduce network traffic: By default calls -to $dbh->quote() are passed to the remote driver. Of course this slows -down things quite a lot, but is the safest default behaviour. - -However, if you set the I attribute to the value 'C' -either in the database handle or in the statement handle, and the call -to quote has only one parameter, then the local default DBI quote -method will be used (which will be faster but may be wrong). - -=back - -=head1 KNOWN ISSUES - -=head2 Unproxied method calls - -If a method isn't being proxied, try declaring a stub sub in the appropriate -package (DBD::Proxy::db for a dbh method, and DBD::Proxy::st for an sth method). -For example: - - sub DBD::Proxy::db::selectall_arrayref; - -That will enable selectall_arrayref to be proxied. - -Currently many methods aren't explicitly proxied and so you get the DBI's -default methods executed on the client. - -Some of those methods, like selectall_arrayref, may then call other methods -that are proxied (selectall_arrayref calls fetchall_arrayref which calls fetch -which is proxied). So things may appear to work but operate more slowly than -the could. - -This may all change in a later version. - -=head2 Complex handle attributes - -Sometimes handles are having complex attributes like hash refs or -array refs and not simple strings or integers. For example, with -DBD::CSV, you would like to write something like - - $dbh->{"csv_tables"}->{"passwd"} = - { "sep_char" => ":", "eol" => "\n"; - -The above example would advice the CSV driver to assume the file -"passwd" to be in the format of the /etc/passwd file: Colons as -separators and a line feed without carriage return as line -terminator. - -Surprisingly this example doesn't work with the proxy driver. To understand -the reasons, you should consider the following: The Perl compiler is -executing the above example in two steps: - -=over - -=item 1 - -The first step is fetching the value of the key "csv_tables" in the -handle $dbh. The value returned is complex, a hash ref. - -=item 2 - -The second step is storing some value (the right hand side of the -assignment) as the key "passwd" in the hash ref from step 1. - -=back - -This becomes a little bit clearer, if we rewrite the above code: - - $tables = $dbh->{"csv_tables"}; - $tables->{"passwd"} = { "sep_char" => ":", "eol" => "\n"; - -While the examples work fine without the proxy, the fail due to a -subtle difference in step 1: By DBI magic, the hash ref -$dbh->{'csv_tables'} is returned from the server to the client. -The client creates a local copy. This local copy is the result of -step 1. In other words, step 2 modifies a local copy of the hash ref, -but not the server's hash ref. - -The workaround is storing the modified local copy back to the server: - - $tables = $dbh->{"csv_tables"}; - $tables->{"passwd"} = { "sep_char" => ":", "eol" => "\n"; - $dbh->{"csv_tables"} = $tables; - - -=head1 SECURITY WARNING - -L used underneath is not secure due to serializing and -deserializing data with L module. Use the proxy driver only in -trusted environment. - - -=head1 AUTHOR AND COPYRIGHT - -This module is Copyright (c) 1997, 1998 - - Jochen Wiedmann - Am Eisteich 9 - 72555 Metzingen - Germany - - Email: joe@ispsoft.de - Phone: +49 7123 14887 - -The DBD::Proxy module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. In particular permission -is granted to Tim Bunce for distributing this as a part of the DBI. - - -=head1 SEE ALSO - -L, L, L - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBD/Sponge.pm b/dbLifeLog/DBI-1.641/blib/lib/DBD/Sponge.pm deleted file mode 100644 index 4bd1bbc..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBD/Sponge.pm +++ /dev/null @@ -1,305 +0,0 @@ -use strict; -{ - package DBD::Sponge; - - require DBI; - require Carp; - - our @EXPORT = qw(); # Do NOT @EXPORT anything. - our $VERSION = "12.010003"; - -# $Id: Sponge.pm 10002 2007-09-26 21:03:25Z Tim $ -# -# Copyright (c) 1994-2003 Tim Bunce Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - our $drh = undef; # holds driver handle once initialised - my $methods_already_installed; - - sub driver{ - return $drh if $drh; - - DBD::Sponge::db->install_method("sponge_test_installed_method") - unless $methods_already_installed++; - - my($class, $attr) = @_; - $class .= "::dr"; - ($drh) = DBI::_new_drh($class, { - 'Name' => 'Sponge', - 'Version' => $VERSION, - 'Attribution' => "DBD::Sponge $VERSION (fake cursor driver) by Tim Bunce", - }); - $drh; - } - - sub CLONE { - undef $drh; - } -} - - -{ package DBD::Sponge::dr; # ====== DRIVER ====== - our $imp_data_size = 0; - # we use default (dummy) connect method -} - - -{ package DBD::Sponge::db; # ====== DATABASE ====== - our $imp_data_size = 0; - use strict; - - sub prepare { - my($dbh, $statement, $attribs) = @_; - my $rows = delete $attribs->{'rows'} - or return $dbh->set_err($DBI::stderr,"No rows attribute supplied to prepare"); - my ($outer, $sth) = DBI::_new_sth($dbh, { - 'Statement' => $statement, - 'rows' => $rows, - (map { exists $attribs->{$_} ? ($_=>$attribs->{$_}) : () } - qw(execute_hook) - ), - }); - if (my $behave_like = $attribs->{behave_like}) { - $outer->{$_} = $behave_like->{$_} - foreach (qw(RaiseError PrintError HandleError ShowErrorStatement)); - } - - if ($statement =~ /^\s*insert\b/) { # very basic, just for testing execute_array() - $sth->{is_insert} = 1; - my $NUM_OF_PARAMS = $attribs->{NUM_OF_PARAMS} - or return $dbh->set_err($DBI::stderr,"NUM_OF_PARAMS not specified for INSERT statement"); - $sth->STORE('NUM_OF_PARAMS' => $attribs->{NUM_OF_PARAMS} ); - } - else { #assume select - - # we need to set NUM_OF_FIELDS - my $numFields; - if ($attribs->{'NUM_OF_FIELDS'}) { - $numFields = $attribs->{'NUM_OF_FIELDS'}; - } elsif ($attribs->{'NAME'}) { - $numFields = @{$attribs->{NAME}}; - } elsif ($attribs->{'TYPE'}) { - $numFields = @{$attribs->{TYPE}}; - } elsif (my $firstrow = $rows->[0]) { - $numFields = scalar @$firstrow; - } else { - return $dbh->set_err($DBI::stderr, 'Cannot determine NUM_OF_FIELDS'); - } - $sth->STORE('NUM_OF_FIELDS' => $numFields); - $sth->{NAME} = $attribs->{NAME} - || [ map { "col$_" } 1..$numFields ]; - $sth->{TYPE} = $attribs->{TYPE} - || [ (DBI::SQL_VARCHAR()) x $numFields ]; - $sth->{PRECISION} = $attribs->{PRECISION} - || [ map { length($sth->{NAME}->[$_]) } 0..$numFields -1 ]; - $sth->{SCALE} = $attribs->{SCALE} - || [ (0) x $numFields ]; - $sth->{NULLABLE} = $attribs->{NULLABLE} - || [ (2) x $numFields ]; - } - - $outer; - } - - sub type_info_all { - my ($dbh) = @_; - my $ti = [ - { TYPE_NAME => 0, - DATA_TYPE => 1, - PRECISION => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE=> 9, - MONEY => 10, - AUTO_INCREMENT => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - }, - [ 'VARCHAR', DBI::SQL_VARCHAR(), undef, "'","'", undef, 0, 1, 1, 0, 0,0,undef,0,0 ], - ]; - return $ti; - } - - sub FETCH { - my ($dbh, $attrib) = @_; - # In reality this would interrogate the database engine to - # either return dynamic values that cannot be precomputed - # or fetch and cache attribute values too expensive to prefetch. - return 1 if $attrib eq 'AutoCommit'; - # else pass up to DBI to handle - return $dbh->SUPER::FETCH($attrib); - } - - sub STORE { - my ($dbh, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - if ($attrib eq 'AutoCommit') { - return 1 if $value; # is already set - Carp::croak("Can't disable AutoCommit"); - } - return $dbh->SUPER::STORE($attrib, $value); - } - - sub sponge_test_installed_method { - my ($dbh, @args) = @_; - return $dbh->set_err(42, "not enough parameters") unless @args >= 2; - return \@args; - } -} - - -{ package DBD::Sponge::st; # ====== STATEMENT ====== - our $imp_data_size = 0; - use strict; - - sub execute { - my $sth = shift; - - # hack to support ParamValues (when not using bind_param) - $sth->{ParamValues} = (@_) ? { map { $_ => $_[$_-1] } 1..@_ } : undef; - - if (my $hook = $sth->{execute_hook}) { - &$hook($sth, @_) or return; - } - - if ($sth->{is_insert}) { - my $row; - $row = (@_) ? [ @_ ] : die "bind_param not supported yet" ; - my $NUM_OF_PARAMS = $sth->{NUM_OF_PARAMS}; - return $sth->set_err($DBI::stderr, @$row." values bound (@$row) but $NUM_OF_PARAMS expected") - if @$row != $NUM_OF_PARAMS; - { local $^W; $sth->trace_msg("inserting (@$row)\n"); } - push @{ $sth->{rows} }, $row; - } - else { # mark select sth as Active - $sth->STORE(Active => 1); - } - # else do nothing for select as data is already in $sth->{rows} - return 1; - } - - sub fetch { - my ($sth) = @_; - my $row = shift @{$sth->{'rows'}}; - unless ($row) { - $sth->STORE(Active => 0); - return undef; - } - return $sth->_set_fbav($row); - } - *fetchrow_arrayref = \&fetch; - - sub FETCH { - my ($sth, $attrib) = @_; - # would normally validate and only fetch known attributes - # else pass up to DBI to handle - return $sth->SUPER::FETCH($attrib); - } - - sub STORE { - my ($sth, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - return $sth->SUPER::STORE($attrib, $value); - } -} - -1; - -__END__ - -=pod - -=head1 NAME - -DBD::Sponge - Create a DBI statement handle from Perl data - -=head1 SYNOPSIS - - my $sponge = DBI->connect("dbi:Sponge:","","",{ RaiseError => 1 }); - my $sth = $sponge->prepare($statement, { - rows => $data, - NAME => $names, - %attr - } - ); - -=head1 DESCRIPTION - -DBD::Sponge is useful for making a Perl data structure accessible through a -standard DBI statement handle. This may be useful to DBD module authors who -need to transform data in this way. - -=head1 METHODS - -=head2 connect() - - my $sponge = DBI->connect("dbi:Sponge:","","",{ RaiseError => 1 }); - -Here's a sample syntax for creating a database handle for the Sponge driver. -No username and password are needed. - -=head2 prepare() - - my $sth = $sponge->prepare($statement, { - rows => $data, - NAME => $names, - %attr - } - ); - -=over 4 - -=item * - -The C<$statement> here is an arbitrary statement or name you want -to provide as identity of your data. If you're using DBI::Profile -it will appear in the profile data. - -Generally it's expected that you are preparing a statement handle -as if a C statement is: - - prepare, - execute, fetch, fetch, ... - execute, fetch, fetch, ... - execute, fetch, fetch, ... - -for example: - - $sth = $dbh->prepare("SELECT foo, bar FROM table WHERE baz=?"); - - $sth->execute( $baz ); - - while ( @row = $sth->fetchrow_array ) { - print "@row\n"; - } - -The typical method call sequence for a I-C statement -(or with drivers that don't support placeholders): - - $rows_affected = $dbh->do("UPDATE your_table SET foo = foo + 1"); - -To commit your changes to the database (when L is off): - - $dbh->commit; # or call $dbh->rollback; to undo changes - -Finally, when you have finished working with the data source, you should -L from it: - - $dbh->disconnect; - - -=head2 General Interface Rules & Caveats - -The DBI does not have a concept of a "current session". Every session -has a handle object (i.e., a C<$dbh>) returned from the C method. -That handle object is used to invoke database related methods. - -Most data is returned to the Perl script as strings. (Null values are -returned as C.) This allows arbitrary precision numeric data to be -handled without loss of accuracy. Beware that Perl may not preserve -the same accuracy when the string is used as a number. - -Dates and times are returned as character strings in the current -default format of the corresponding database engine. Time zone effects -are database/driver dependent. - -Perl supports binary data in Perl strings, and the DBI will pass binary -data to and from the driver without change. It is up to the driver -implementors to decide how they wish to handle such binary data. - -Perl supports two kinds of strings: Unicode (utf8 internally) and non-Unicode -(defaults to iso-8859-1 if forced to assume an encoding). Drivers should -accept both kinds of strings and, if required, convert them to the character -set of the database being used. Similarly, when fetching from the database -character data that isn't iso-8859-1 the driver should convert it into utf8. - -Multiple SQL statements may not be combined in a single statement -handle (C<$sth>), although some databases and drivers do support this -(notably Sybase and SQL Server). - -Non-sequential record reads are not supported in this version of the DBI. -In other words, records can only be fetched in the order that the -database returned them, and once fetched they are forgotten. - -Positioned updates and deletes are not directly supported by the DBI. -See the description of the C attribute for an alternative. - -Individual driver implementors are free to provide any private -functions and/or handle attributes that they feel are useful. -Private driver functions can be invoked using the DBI C method. -Private driver attributes are accessed just like standard attributes. - -Many methods have an optional C<\%attr> parameter which can be used to -pass information to the driver implementing the method. Except where -specifically documented, the C<\%attr> parameter can only be used to pass -driver specific hints. In general, you can ignore C<\%attr> parameters -or pass it as C. - - -=head2 Naming Conventions and Name Space - -The DBI package and all packages below it (C) are reserved for -use by the DBI. Extensions and related modules use the C -namespace (see L). -Package names beginning with C are reserved for use -by DBI database drivers. All environment variables used by the DBI -or by individual DBDs begin with "C" or "C". - -The letter case used for attribute names is significant and plays an -important part in the portability of DBI scripts. The case of the -attribute name is used to signify who defined the meaning of that name -and its values. - - Case of name Has a meaning defined by - ------------ ------------------------ - UPPER_CASE Standards, e.g., X/Open, ISO SQL92 etc (portable) - MixedCase DBI API (portable), underscores are not used. - lower_case Driver or database engine specific (non-portable) - -It is of the utmost importance that Driver developers only use -lowercase attribute names when defining private attributes. Private -attribute names must be prefixed with the driver name or suitable -abbreviation (e.g., "C" for Oracle, "C" for Ingres, etc). - - -=head2 SQL - A Query Language - -Most DBI drivers require applications to use a dialect of SQL -(Structured Query Language) to interact with the database engine. -The L section provides links -to useful information about SQL. - -The DBI itself does not mandate or require any particular language to -be used; it is language independent. In ODBC terms, the DBI is in -"pass-thru" mode, although individual drivers might not be. The only requirement -is that queries and other statements must be expressed as a single -string of characters passed as the first argument to the L or -L methods. - -For an interesting diversion on the I history of RDBMS and SQL, -from the people who made it happen, see: - - http://www.mcjones.org/System_R/SQL_Reunion_95/sqlr95.html - -Follow the "Full Contents" then "Intergalactic dataspeak" links for the -SQL history. - -=head2 Placeholders and Bind Values - -Some drivers support placeholders and bind values. -I, also called parameter markers, are used to indicate -values in a database statement that will be supplied later, -before the prepared statement is executed. For example, an application -might use the following to insert a row of data into the SALES table: - - INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?) - -or the following, to select the description for a product: - - SELECT description FROM products WHERE product_code = ? - -The C characters are the placeholders. The association of actual -values with placeholders is known as I, and the values are -referred to as I. -Note that the C is not enclosed in quotation marks, even when the -placeholder represents a string. - -Some drivers also allow placeholders like C<:>I and C<:>I (e.g., -C<:1>, C<:2>, and so on) in addition to C, but their use is not portable. - -If the C<:>I form of placeholder is supported by the driver you're using, -then you should be able to use either L or L to bind -values. Check your driver documentation. - -Some drivers allow you to prevent the recognition of a placeholder by placing a -single backslash character (C<\>) immediately before it. The driver will remove -the backslash character and ignore the placeholder, passing it unchanged to the -backend. If the driver supports this then L(9000) will return true. - -With most drivers, placeholders can't be used for any element of a -statement that would prevent the database server from validating the -statement and creating a query execution plan for it. For example: - - "SELECT name, age FROM ?" # wrong (will probably fail) - "SELECT name, ? FROM people" # wrong (but may not 'fail') - -Also, placeholders can only represent single scalar values. -For example, the following -statement won't work as expected for more than one value: - - "SELECT name, age FROM people WHERE name IN (?)" # wrong - "SELECT name, age FROM people WHERE name IN (?,?)" # two names - -When using placeholders with the SQL C qualifier, you must -remember that the placeholder substitutes for the whole string. -So you should use "C<... LIKE ? ...>" and include any wildcard -characters in the value that you bind to the placeholder. - -B - -Undefined values, or C, are used to indicate NULL values. -You can insert and update columns with a NULL value as you would a -non-NULL value. These examples insert and update the column -C with a NULL value: - - $sth = $dbh->prepare(qq{ - INSERT INTO people (fullname, age) VALUES (?, ?) - }); - $sth->execute("Joe Bloggs", undef); - - $sth = $dbh->prepare(qq{ - UPDATE people SET age = ? WHERE fullname = ? - }); - $sth->execute(undef, "Joe Bloggs"); - -However, care must be taken when trying to use NULL values in a -C clause. Consider: - - SELECT fullname FROM people WHERE age = ? - -Binding an C (NULL) to the placeholder will I select rows -which have a NULL C! At least for database engines that -conform to the SQL standard. Refer to the SQL manual for your database -engine or any SQL book for the reasons for this. To explicitly select -NULLs you have to say "C". - -A common issue is to have a code fragment handle a value that could be -either C or C (non-NULL or NULL) at runtime. -A simple technique is to prepare the appropriate statement as needed, -and substitute the placeholder for non-NULL cases: - - $sql_clause = defined $age? "age = ?" : "age IS NULL"; - $sth = $dbh->prepare(qq{ - SELECT fullname FROM people WHERE $sql_clause - }); - $sth->execute(defined $age ? $age : ()); - -The following technique illustrates qualifying a C clause with -several columns, whose associated values (C or C) are -in a hash %h: - - for my $col ("age", "phone", "email") { - if (defined $h{$col}) { - push @sql_qual, "$col = ?"; - push @sql_bind, $h{$col}; - } - else { - push @sql_qual, "$col IS NULL"; - } - } - $sql_clause = join(" AND ", @sql_qual); - $sth = $dbh->prepare(qq{ - SELECT fullname FROM people WHERE $sql_clause - }); - $sth->execute(@sql_bind); - -The techniques above call prepare for the SQL statement with each call to -execute. Because calls to prepare() can be expensive, performance -can suffer when an application iterates many times over statements -like the above. - -A better solution is a single C clause that supports both -NULL and non-NULL comparisons. Its SQL statement would need to be -prepared only once for all cases, thus improving performance. -Several examples of C clauses that support this are presented -below. But each example lacks portability, robustness, or simplicity. -Whether an example is supported on your database engine depends on -what SQL extensions it provides, and where it supports the C -placeholder in a statement. - - 0) age = ? - 1) NVL(age, xx) = NVL(?, xx) - 2) ISNULL(age, xx) = ISNULL(?, xx) - 3) DECODE(age, ?, 1, 0) = 1 - 4) age = ? OR (age IS NULL AND ? IS NULL) - 5) age = ? OR (age IS NULL AND SP_ISNULL(?) = 1) - 6) age = ? OR (age IS NULL AND ? = 1) - -Statements formed with the above C clauses require execute -statements as follows. The arguments are required, whether their -values are C or C. - - 0,1,2,3) $sth->execute($age); - 4,5) $sth->execute($age, $age); - 6) $sth->execute($age, defined($age) ? 0 : 1); - -Example 0 should not work (as mentioned earlier), but may work on -a few database engines anyway (e.g. Sybase). Example 0 is part -of examples 4, 5, and 6, so if example 0 works, these other -examples may work, even if the engine does not properly support -the right hand side of the C expression. - -Examples 1 and 2 are not robust: they require that you provide a -valid column value xx (e.g. '~') which is not present in any row. -That means you must have some notion of what data won't be stored -in the column, and expect clients to adhere to that. - -Example 5 requires that you provide a stored procedure (SP_ISNULL -in this example) that acts as a function: it checks whether a value -is null, and returns 1 if it is, or 0 if not. - -Example 6, the least simple, is probably the most portable, i.e., it -should work with most, if not all, database engines. - -Here is a table that indicates which examples above are known to -work on various database engines: - - -----Examples------ - 0 1 2 3 4 5 6 - - - - - - - - - Oracle 9 N Y N Y Y ? Y - Informix IDS 9 N N N Y N Y Y - MS SQL N N Y N Y ? Y - Sybase Y N N N N N Y - AnyData,DBM,CSV Y N N N Y Y* Y - SQLite 3.3 N N N N Y N N - MSAccess N N N N Y N Y - -* Works only because Example 0 works. - -DBI provides a sample perl script that will test the examples above -on your database engine and tell you which ones work. It is located -in the F subdirectory of the DBI source distribution, or here: -L -Please use the script to help us fill-in and maintain this table. - -B - -Without using placeholders, the insert statement shown previously would have to -contain the literal values to be inserted and would have to be -re-prepared and re-executed for each row. With placeholders, the insert -statement only needs to be prepared once. The bind values for each row -can be given to the C method each time it's called. By avoiding -the need to re-prepare the statement for each row, the application -typically runs many times faster. Here's an example: - - my $sth = $dbh->prepare(q{ - INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?) - }) or die $dbh->errstr; - while (<>) { - chomp; - my ($product_code, $qty, $price) = split /,/; - $sth->execute($product_code, $qty, $price) or die $dbh->errstr; - } - $dbh->commit or die $dbh->errstr; - -See L and L for more details. - -The C style quoting used in this example avoids clashing with -quotes that may be used in the SQL statement. Use the double-quote like -C operator if you want to interpolate variables into the string. -See L for more details. - -See also the L method, which is used to associate Perl -variables with the output columns of a C -that may have more data to fetch. (Fetching all the data or calling C<$sth-Efinish> -sets C off.) - -=head3 C - -Type: boolean - -The C attribute is true if the handle object has been "executed". -Currently only the $dbh do() method and the $sth execute(), execute_array(), -and execute_for_fetch() methods set the C attribute. - -When it's set on a handle it is also set on the parent handle at the -same time. So calling execute() on a $sth also sets the C -attribute on the parent $dbh. - -The C attribute for a database handle is cleared by the commit() and -rollback() methods (even if they fail). The C attribute of a -statement handle is not cleared by the DBI under any circumstances and so acts -as a permanent record of whether the statement handle was ever used. - -The C attribute was added in DBI 1.41. - -=head3 C - -Type: integer, read-only - -For a driver handle, C is the number of currently existing database -handles that were created from that driver handle. For a database -handle, C is the number of currently existing statement handles that -were created from that database handle. -For a statement handle, the value is zero. - -=head3 C - -Type: integer, read-only - -Like C, but only counting those that are C (as above). - -=head3 C - -Type: hash ref - -For a database handle, C returns a reference to the cache (hash) of -statement handles created by the L method. For a -driver handle, returns a reference to the cache (hash) of -database handles created by the L method. - -=head3 C - -Type: scalar, read-only - -The C attribute identifies the type of a DBI handle. Returns -"dr" for driver handles, "db" for database handles and "st" for -statement handles. - -=head3 C - -Type: array ref - -The ChildHandles attribute contains a reference to an array of all the -handles created by this handle which are still accessible. The -contents of the array are weak-refs and will become undef when the -handle goes out of scope. (They're cleared out occasionally.) - -C returns undef if your perl version does not support weak -references (check the L module). The referenced -array returned should be treated as read-only. - -For example, to enumerate all driver handles, database handles and -statement handles: - - sub show_child_handles { - my ($h, $level) = @_; - printf "%sh %s %s\n", $h->{Type}, "\t" x $level, $h; - show_child_handles($_, $level + 1) - for (grep { defined } @{$h->{ChildHandles}}); - } - - my %drivers = DBI->installed_drivers(); - show_child_handles($_, 0) for (values %drivers); - -=head3 C - -Type: boolean, inherited - -The C attribute is used by emulation layers (such as -Oraperl) to enable compatible behaviour in the underlying driver -(e.g., DBD::Oracle) for this handle. Not normally set by application code. - -It also has the effect of disabling the 'quick FETCH' of attribute -values from the handles attribute cache. So all attribute values -are handled by the drivers own FETCH method. This makes them slightly -slower but is useful for special-purpose drivers like DBD::Multiplex. - -=head3 C - -Type: boolean - -The default value, false, means a handle will be fully destroyed -as normal when the last reference to it is removed, just as you'd expect. - -If set true then the handle will be treated by the DESTROY as if it was no -longer Active, and so the I related effects of DESTROYing a -handle will be skipped. Think of the name as meaning 'treat the handle as -not-Active in the DESTROY method'. - -For a database handle, this attribute does not disable an I -call to the disconnect method, only the implicit call from DESTROY -that happens if the handle is still marked as C. - -This attribute is specifically designed for use in Unix applications -that "fork" child processes. For some drivers, when the child process exits -the destruction of inherited handles cause the corresponding handles in the -parent process to cease working. - -Either the parent or the child process, but not both, should set -C true on all their shared handles. Alternatively, and -preferably, the L can be set in the parent on connect. - -To help tracing applications using fork the process id is shown in -the trace log whenever a DBI or handle trace() method is called. -The process id also shown for I method call if the DBI trace -level (not handle trace level) is set high enough to show the trace -from the DBI's method dispatcher, e.g. >= 9. - -=head3 C - -Type: boolean, inherited - -The L attribute, described above, needs to be explicitly set -in the child process after a fork(), on every active database and statement handle. -This is a problem if the code that performs the fork() is not under your -control, perhaps in a third-party module. Use C to get -around this situation. - -If set true, the DESTROY method will check the process id of the handle and, if -different from the current process id, it will set the I attribute. -It is strongly recommended that C is enabled on all new code -(it's only not enabled by default to avoid backwards compatibility problems). - -This is the example it's designed to deal with: - - my $dbh = DBI->connect(...); - some_code_that_forks(); # Perhaps without your knowledge - # Child process dies, destroying the inherited dbh - $dbh->do(...); # Breaks because parent $dbh is now broken - -The C attribute was added in DBI 1.614. - -=head3 C - -Type: boolean, inherited - -The C attribute controls the printing of warnings recorded -by the driver. When set to a true value (the default) the DBI will check method -calls to see if a warning condition has been set. If so, the DBI -will effectively do a C -where C<$class> is the driver class and C<$method> is the name of -the method which failed. E.g., - - DBD::Oracle::db execute warning: ... warning text here ... - -If desired, the warnings can be caught and processed using a C<$SIG{__WARN__}> -handler or modules like CGI::Carp and CGI::ErrorWrap. - -See also L for how warnings are recorded and L -for how to influence it. - -Fetching the full details of warnings can require an extra round-trip -to the database server for some drivers. In which case the driver -may opt to only fetch the full details of warnings if the C -attribute is true. If C is false then these drivers should -still indicate the fact that there were warnings by setting the -warning string to, for example: "3 warnings". - -=head3 C - -Type: boolean, inherited - -The C attribute can be used to force errors to generate warnings (using -C) in addition to returning error codes in the normal way. When set -"on", any method which results in an error occurring will cause the DBI to -effectively do a C where C<$class> -is the driver class and C<$method> is the name of the method which failed. E.g., - - DBD::Oracle::db prepare failed: ... error text here ... - -By default, Cconnect> sets C "on". - -If desired, the warnings can be caught and processed using a C<$SIG{__WARN__}> -handler or modules like CGI::Carp and CGI::ErrorWrap. - -=head3 C - -Type: boolean, inherited - -The C attribute can be used to force errors to raise exceptions rather -than simply return error codes in the normal way. It is "off" by default. -When set "on", any method which results in an error will cause -the DBI to effectively do a C, -where C<$class> is the driver class and C<$method> is the name of the method -that failed. E.g., - - DBD::Oracle::db prepare failed: ... error text here ... - -If you turn C on then you'd normally turn C off. -If C is also on, then the C is done first (naturally). - -Typically C is used in conjunction with C, -or a module like L or L, -to catch the exception that's been thrown and handle it. -For example: - - use Try::Tiny; - - try { - ... - $sth->execute(); - ... - } catch { - # $sth->err and $DBI::err will be true if error was from DBI - warn $_; # print the error (which Try::Tiny puts into $_) - ... # do whatever you need to deal with the error - }; - -In the catch block the $DBI::lasth variable can be useful for -diagnosis and reporting if you can't be sure which handle triggered -the error. For example, $DBI::lasth->{Type} and $DBI::lasth->{Statement}. - -See also L. - -If you want to temporarily turn C off (inside a library function -that is likely to fail, for example), the recommended way is like this: - - { - local $h->{RaiseError}; # localize and turn off for this block - ... - } - -The original value will automatically and reliably be restored by Perl, -regardless of how the block is exited. -The same logic applies to other attributes, including C. - -=head3 C - -Type: code ref, inherited - -The C attribute can be used to provide your own alternative behaviour -in case of errors. If set to a reference to a subroutine then that -subroutine is called when an error is detected (at the same point that -C and C are handled). - -The subroutine is called with three parameters: the error message -string that C and C would use, -the DBI handle being used, and the first value being returned by -the method that failed (typically undef). - -If the subroutine returns a false value then the C -and/or C attributes are checked and acted upon as normal. - -For example, to C with a full stack trace for any error: - - use Carp; - $h->{HandleError} = sub { confess(shift) }; - -Or to turn errors into exceptions: - - use Exception; # or your own favourite exception module - $h->{HandleError} = sub { Exception->new('DBI')->raise($_[0]) }; - -It is possible to 'stack' multiple HandleError handlers by using -closures: - - sub your_subroutine { - my $previous_handler = $h->{HandleError}; - $h->{HandleError} = sub { - return 1 if $previous_handler and &$previous_handler(@_); - ... your code here ... - }; - } - -Using a C inside a subroutine to store the previous C -value is important. See L and L for more information -about I. - -It is possible for C to alter the error message that -will be used by C and C if it returns false. -It can do that by altering the value of $_[0]. This example appends -a stack trace to all errors and, unlike the previous example using -Carp::confess, this will work C as well as C: - - $h->{HandleError} = sub { $_[0]=Carp::longmess($_[0]); 0; }; - -It is also possible for C to hide an error, to a limited -degree, by using L to reset $DBI::err and $DBI::errstr, -and altering the return value of the failed method. For example: - - $h->{HandleError} = sub { - return 0 unless $_[0] =~ /^\S+ fetchrow_arrayref failed:/; - return 0 unless $_[1]->err == 1234; # the error to 'hide' - $h->set_err(undef,undef); # turn off the error - $_[2] = [ ... ]; # supply alternative return value - return 1; - }; - -This only works for methods which return a single value and is hard -to make reliable (avoiding infinite loops, for example) and so isn't -recommended for general use! If you find a I use for it then -please let me know. - -=head3 C - -Type: code ref, inherited - -The C attribute can be used to intercept -the setting of handle C, C, and C values. -If set to a reference to a subroutine then that subroutine is called -whenever set_err() is called, typically by the driver or a subclass. - -The subroutine is called with five arguments, the first five that -were passed to set_err(): the handle, the C, C, and -C values being set, and the method name. These can be altered -by changing the values in the @_ array. The return value affects -set_err() behaviour, see L for details. - -It is possible to 'stack' multiple HandleSetErr handlers by using -closures. See L for an example. - -The C and C subroutines differ in subtle -but significant ways. HandleError is only invoked at the point where -the DBI is about to return to the application with C set true. -It's not invoked by the failure of a method that's been called by -another DBI method. HandleSetErr, on the other hand, is called -whenever set_err() is called with a defined C value, even if false. -So it's not just for errors, despite the name, but also warn and info states. -The set_err() method, and thus HandleSetErr, may be called multiple -times within a method and is usually invoked from deep within driver code. - -In theory a driver can use the return value from HandleSetErr via -set_err() to decide whether to continue or not. If set_err() returns -an empty list, indicating that the HandleSetErr code has 'handled' -the 'error', the driver could then continue instead of failing (if -that's a reasonable thing to do). This isn't excepted to be -common and any such cases should be clearly marked in the driver -documentation and discussed on the dbi-dev mailing list. - -The C attribute was added in DBI 1.41. - -=head3 C - -Type: unsigned integer - -The C attribute is incremented whenever the set_err() -method records an error. It isn't incremented by warnings or -information states. It is not reset by the DBI at any time. - -The C attribute was added in DBI 1.41. Older drivers may -not have been updated to use set_err() to record errors and so this -attribute may not be incremented when using them. - - -=head3 C - -Type: boolean, inherited - -The C attribute can be used to cause the relevant -Statement text to be appended to the error messages generated by -the C, C, and C attributes. -Only applies to errors on statement handles -plus the prepare(), do(), and the various C database handle methods. -(The exact format of the appended text is subject to change.) - -If C<$h-E{ParamValues}> returns a hash reference of parameter -(placeholder) values then those are formatted and appended to the -end of the Statement text in the error message. - -=head3 C - -Type: integer, inherited - -The C attribute can be used as an alternative to the -L method to set the DBI trace level and trace flags for a -specific handle. See L for more details. - -The C attribute is especially useful combined with -C to alter the trace settings for just a single block of code. - -=head3 C - -Type: string, inherited - -The C attribute is used to specify whether the fetchrow_hashref() -method should perform case conversion on the field names used for -the hash keys. For historical reasons it defaults to 'C' but -it is recommended to set it to 'C' (convert to lower case) -or 'C' (convert to upper case) according to your preference. -It can only be set for driver and database handles. For statement -handles the value is frozen when prepare() is called. - - -=head3 C - -Type: boolean, inherited - -The C attribute can be used to control the trimming of trailing space -characters from fixed width character (CHAR) fields. No other field -types are affected, even where field values have trailing spaces. - -The default is false (although it is possible that the default may change). -Applications that need specific behaviour should set the attribute as -needed. - -Drivers are not required to support this attribute, but any driver which -does not support it must arrange to return C as the attribute value. - - -=head3 C - -Type: unsigned integer, inherited - -The C attribute may be used to control the maximum -length of 'long' type fields (LONG, BLOB, CLOB, MEMO, etc.) which the driver will -read from the database automatically when it fetches each row of data. - -The C attribute only relates to fetching and reading -long values; it is not involved in inserting or updating them. - -A value of 0 means not to automatically fetch any long data. -Drivers may return undef or an empty string for long fields when -C is 0. - -The default is typically 0 (zero) or 80 bytes but may vary between drivers. -Applications fetching long fields should set this value to slightly -larger than the longest long field value to be fetched. - -Some databases return some long types encoded as pairs of hex digits. -For these types, C relates to the underlying data -length and not the doubled-up length of the encoded string. - -Changing the value of C for a statement handle after it -has been C'd will typically have no effect, so it's common to -set C on the C<$dbh> before calling C. - -For most drivers the value used here has a direct effect on the -memory used by the statement handle while it's active, so don't be -too generous. If you can't be sure what value to use you could -execute an extra select statement to determine the longest value. -For example: - - $dbh->{LongReadLen} = $dbh->selectrow_array(qq{ - SELECT MAX(OCTET_LENGTH(long_column_name)) - FROM table WHERE ... - }); - $sth = $dbh->prepare(qq{ - SELECT long_column_name, ... FROM table WHERE ... - }); - -You may need to take extra care if the table can be modified between -the first select and the second being executed. You may also need to -use a different function if OCTET_LENGTH() does not work for long -types in your database. For example, for Sybase use DATALENGTH() and -for Oracle use LENGTHB(). - -See also L for information on truncation of long types. - -=head3 C - -Type: boolean, inherited - -The C attribute may be used to control the effect of -fetching a long field value which has been truncated (typically -because it's longer than the value of the C attribute). - -By default, C is false and so fetching a long value that -needs to be truncated will cause the fetch to fail. -(Applications should always be sure to -check for errors after a fetch loop in case an error, such as a divide -by zero or long field truncation, caused the fetch to terminate -prematurely.) - -If a fetch fails due to a long field truncation when C is -false, many drivers will allow you to continue fetching further rows. - -See also L. - -=head3 C - -Type: boolean, inherited - -If the C attribute is set to a true value I Perl is running in -taint mode (e.g., started with the C<-T> option), then all the arguments -to most DBI method calls are checked for being tainted. I - -The attribute defaults to off, even if Perl is in taint mode. -See L for more about taint mode. If Perl is not -running in taint mode, this attribute has no effect. - -When fetching data that you trust you can turn off the TaintIn attribute, -for that statement handle, for the duration of the fetch loop. - -The C attribute was added in DBI 1.31. - -=head3 C - -Type: boolean, inherited - -If the C attribute is set to a true value I Perl is running in -taint mode (e.g., started with the C<-T> option), then most data fetched -from the database is considered tainted. I - -The attribute defaults to off, even if Perl is in taint mode. -See L for more about taint mode. If Perl is not -running in taint mode, this attribute has no effect. - -When fetching data that you trust you can turn off the TaintOut attribute, -for that statement handle, for the duration of the fetch loop. - -Currently only fetched data is tainted. It is possible that the results -of other DBI method calls, and the value of fetched attributes, may -also be tainted in future versions. That change may well break your -applications unless you take great care now. If you use DBI Taint mode, -please report your experience and any suggestions for changes. - -The C attribute was added in DBI 1.31. - -=head3 C - -Type: boolean, inherited - -The C attribute is a shortcut for L and L (it is also present -for backwards compatibility). - -Setting this attribute sets both L and L, and retrieving -it returns a true value if and only if L and L are -both set to true values. - -=head3 C - -Type: inherited - -The C attribute enables the collection and reporting of -method call timing statistics. See the L module -documentation for I more detail. - -The C attribute was added in DBI 1.24. - -=head3 C - -Type: boolean, inherited - -An application can set the C attribute of a handle to a true value to -indicate that it will not be attempting to make any changes using that handle -or any children of it. - -Note that the exact definition of 'read only' is rather fuzzy. -For more details see the documentation for the driver you're using. - -If the driver can make the handle truly read-only then it should -(unless doing so would have unpleasant side effect, like changing the -consistency level from per-statement to per-session). -Otherwise the attribute is simply advisory. - -A driver can set the C attribute itself to indicate that the data it -is connected to cannot be changed for some reason. - -If the driver cannot ensure the C attribute is adhered to it -will record a warning. In this case reading the C attribute -back after it is set true will return true even if the underlying -driver cannot ensure this (so any application knows the application -declared itself ReadOnly). - -Library modules and proxy drivers can use the attribute to influence -their behavior. For example, the DBD::Gofer driver considers the -C attribute when making a decision about whether to retry an -operation that failed. - -The attribute should be set to 1 or 0 (or undef). Other values are reserved. - -=head3 C - -Type: hash ref - -The DBI callback mechanism lets you intercept, and optionally replace, any -method call on a DBI handle. At the extreme, it lets you become a puppet -master, deceiving the application in any way you want. - -The C attribute is a hash reference where the keys are DBI method -names and the values are code references. For each key naming a method, the -DBI will execute the associated code reference before executing the method. - -The arguments to the code reference will be the same as to the method, -including the invocant (a database handle or statement handle). For example, -say that to callback to some code on a call to C: - - $dbh->{Callbacks} = { - prepare => sub { - my ($dbh, $query, $attrs) = @_; - print "Preparing q{$query}\n" - }, - }; - -The callback would then be executed when you called the C method: - - $dbh->prepare('SELECT 1'); - -And the output of course would be: - - Preparing q{SELECT 1} - -Because callbacks are executed I the methods -they're associated with, you can modify the arguments before they're passed on -to the method call. For example, to make sure that all calls to C -are immediately prepared by L, add a callback that makes sure that -the C attribute is always set: - - my $dbh = DBI->connect($dsn, $username, $auth, { - Callbacks => { - prepare => sub { - $_[2] ||= {}; - $_[2]->{pg_prepare_now} = 1; - return; # must return nothing - }, - } - }); - -Note that we are editing the contents of C<@_> directly. In this case we've -created the attributes hash if it's not passed to the C call. - -You can also prevent the associated method from ever executing. While a -callback executes, C<$_> holds the method name. (This allows multiple callbacks -to share the same code reference and still know what method was called.) -To prevent the method from -executing, simply C. For example, if you wanted to disable calls to -C, you could do this: - - $dbh->{Callbacks} = { - ping => sub { - # tell dispatch to not call the method: - undef $_; - # return this value instead: - return "42 bells"; - } - }; - -As with other attributes, Callbacks can be specified on a handle or via the -attributes to C. Callbacks can also be applied to a statement -methods on a statement handle. For example: - - $sth->{Callbacks} = { - execute => sub { - print "Executing ", shift->{Statement}, "\n"; - } - }; - -The C attribute of a database handle isn't copied to any statement -handles it creates. So setting callbacks for a statement handle requires you to -set the C attribute on the statement handle yourself, as in the -example above, or use the special C key described below. - -B - -In addition to DBI handle method names, the C hash reference -supports four additional keys. - -The first is the C key. When a statement handle is created from -a database handle the C key of the database handle's -C attribute, if any, becomes the new C attribute of the -statement handle. -This allows you to define callbacks for all statement handles created from a -database handle. For example, if you wanted to count how many times C -was called in your application, you could write: - - my $exec_count = 0; - my $dbh = DBI->connect( $dsn, $username, $auth, { - Callbacks => { - ChildCallbacks => { - execute => sub { $exec_count++; return; } - } - } - }); - - END { - print "The execute method was called $exec_count times\n"; - } - -The other three special keys are C, -C, and C. These keys define -callbacks that are called when C is called, but allow -different behaviors depending on whether a new handle is created or a handle -is returned. The callback is invoked with these arguments: -C<$dbh, $dsn, $user, $auth, $attr>. - -For example, some applications uses C to connect with -C enabled and then disable C temporarily for -transactions. If C is called during a transaction, perhaps in -a utility method, then it might select the same cached handle and then force -C on, forcing a commit of the transaction. See the L -documentation for one way to deal with that. Here we'll describe an alternative -approach using a callback. - -Because the C and C callbacks are -invoked before C has applied the connect attributes, you can -use them to edit the attributes that will be applied. To prevent a cached -handle from having its transactions committed before it's returned, you can -eliminate the C attribute in a C callback, -like so: - - my $cb = { - 'connect_cached.reused' => sub { delete $_[4]->{AutoCommit} }, - }; - - sub dbh { - my $self = shift; - DBI->connect_cached( $dsn, $username, $auth, { - PrintError => 0, - RaiseError => 1, - AutoCommit => 1, - Callbacks => $cb, - }); - } - -The upshot is that new database handles are created with C -enabled, while cached database handles are left in whatever transaction state -they happened to be in when retrieved from the cache. - -Note that we've also used a lexical for the callbacks hash reference. This is -because C returns a new database handle if any of the -attributes passed to is have changed. If we used an inline hash reference, -C would return a new database handle every time. Which would -rather defeat the purpose. - -A more common application for callbacks is setting connection state only when -a new connection is made (by connect() or connect_cached()). Adding a callback -to the connected method (when using C) or via -C (when useing connect_cached()>) makes this easy. -The connected() method is a no-op by default (unless you subclass the DBI and -change it). The DBI calls it to indicate that a new connection has been made -and the connection attributes have all been set. You can give it a bit of -added functionality by applying a callback to it. For example, to make sure -that MySQL understands your application's ANSI-compliant SQL, set it up like -so: - - my $dbh = DBI->connect($dsn, $username, $auth, { - Callbacks => { - connected => sub { - shift->do(q{ - SET SESSION sql_mode='ansi,strict_trans_tables,no_auto_value_on_zero'; - }); - return; - }, - } - }); - -If you're using C, use the C -callback, instead. This is because C is called for both new and -reused database handles, but you want to execute a callback only the when a -new database handle is returned. For example, to set the time zone on -connection to a PostgreSQL database, try this: - - my $cb = { - 'connect_cached.connected' => sub { - shift->do('SET timezone = UTC'); - } - }; - - sub dbh { - my $self = shift; - DBI->connect_cached( $dsn, $username, $auth, { Callbacks => $cb }); - } - -One significant limitation with callbacks is that there can only be one per -method per handle. This means it's easy for one use of callbacks to interfere -with, or typically simply overwrite, another use of callbacks. For this reason -modules using callbacks should document the fact clearly so application authors -can tell if use of callbacks by the module will clash with use of callbacks by -the application. - -You might be able to work around this issue by taking a copy of the original -callback and calling it within your own. For example: - - my $prev_cb = $h->{Callbacks}{method_name}; - $h->{Callbacks}{method_name} = sub { - if ($prev_cb) { - my @result = $prev_cb->(@_); - return @result if not $_; # $prev_cb vetoed call - } - ... your callback logic here ... - }; - -=head3 C - -The DBI provides a way to store extra information in a DBI handle as -"private" attributes. The DBI will allow you to store and retrieve any -attribute which has a name starting with "C". - -It is I recommended that you use just I private -attribute (e.g., use a hash ref) I give it a long and unambiguous -name that includes the module or application name that the attribute -relates to (e.g., "C"). - -Because of the way the Perl tie mechanism works you cannot reliably -use the C<||=> operator directly to initialise the attribute, like this: - - my $foo = $dbh->{private_yourmodname_foo} ||= { ... }; # WRONG - -you should use a two step approach like this: - - my $foo = $dbh->{private_yourmodname_foo}; - $foo ||= $dbh->{private_yourmodname_foo} = { ... }; - -This attribute is primarily of interest to people sub-classing DBI, -or for applications to piggy-back extra information onto DBI handles. - -=head1 DBI DATABASE HANDLE OBJECTS - -This section covers the methods and attributes associated with -database handles. - -=head2 Database Handle Methods - -The following methods are specified for DBI database handles: - -=head3 C - - $new_dbh = $dbh->clone(\%attr); - -The C method duplicates the $dbh connection by connecting -with the same parameters ($dsn, $user, $password) as originally used. - -The attributes for the cloned connect are the same as those used -for the I connect, with any other attributes in C<\%attr> -merged over them. Effectively the same as doing: - - %attributes_used = ( %original_attributes, %attr ); - -If \%attr is not given then it defaults to a hash containing all -the attributes in the attribute cache of $dbh excluding any non-code -references, plus the main boolean attributes (RaiseError, PrintError, -AutoCommit, etc.). I - -The clone method can be used even if the database handle is disconnected. - -The C method was added in DBI 1.33. - -=head3 C - - @ary = $dbh->data_sources(); - @ary = $dbh->data_sources(\%attr); - -Returns a list of data sources (databases) available via the $dbh -driver's data_sources() method, plus any extra data sources that -the driver can discover via the connected $dbh. Typically the extra -data sources are other databases managed by the same server process -that the $dbh is connected to. - -Data sources are returned in a form suitable for passing to the -L method (that is, they will include the "C" prefix). - -The data_sources() method, for a $dbh, was added in DBI 1.38. - -=head3 C - - $rows = $dbh->do($statement) or die $dbh->errstr; - $rows = $dbh->do($statement, \%attr) or die $dbh->errstr; - $rows = $dbh->do($statement, \%attr, @bind_values) or die ... - -Prepare and execute a single statement. Returns the number of rows -affected or C on error. A return value of C<-1> means the -number of rows is not known, not applicable, or not available. - -This method is typically most useful for I-C statements because it does not return a statement -handle (so you can't fetch any data). - -The default C method is logically similar to: - - sub do { - my($dbh, $statement, $attr, @bind_values) = @_; - my $sth = $dbh->prepare($statement, $attr) or return undef; - $sth->execute(@bind_values) or return undef; - my $rows = $sth->rows; - ($rows == 0) ? "0E0" : $rows; # always return true if no error - } - -For example: - - my $rows_deleted = $dbh->do(q{ - DELETE FROM table - WHERE status = ? - }, undef, 'DONE') or die $dbh->errstr; - -Using placeholders and C<@bind_values> with the C method can be -useful because it avoids the need to correctly quote any variables -in the C<$statement>. But if you'll be executing the statement many -times then it's more efficient to C it once and call -C many times instead. - -The C style quoting used in this example avoids clashing with -quotes that may be used in the SQL statement. Use the double-quote-like -C operator if you want to interpolate variables into the string. -See L for more details. - -Note drivers are free to avoid the overhead of creating an DBI -statement handle for do(), especially if there are no parameters. In -this case error handlers, if invoked during do(), will be passed the -database handle. - -=head3 C - - $rv = $dbh->last_insert_id($catalog, $schema, $table, $field); - $rv = $dbh->last_insert_id($catalog, $schema, $table, $field, \%attr); - -Returns a value 'identifying' the row just inserted, if possible. -Typically this would be a value assigned by the database server -to a column with an I or I type. -Returns undef if the driver does not support the method or can't -determine the value. - -The $catalog, $schema, $table, and $field parameters may be required -for some drivers (see below). If you don't know the parameter values -and your driver does not need them, then use C for each. - -There are several caveats to be aware of with this method if you want -to use it for portable applications: - -B<*> For some drivers the value may only available immediately after -the insert statement has executed (e.g., mysql, Informix). - -B<*> For some drivers the $catalog, $schema, $table, and $field parameters -are required, for others they are ignored (e.g., mysql). - -B<*> Drivers may return an indeterminate value if no insert has -been performed yet. - -B<*> For some drivers the value may only be available if placeholders -have I been used (e.g., Sybase, MS SQL). In this case the value -returned would be from the last non-placeholder insert statement. - -B<*> Some drivers may need driver-specific hints about how to get -the value. For example, being told the name of the database 'sequence' -object that holds the value. Any such hints are passed as driver-specific -attributes in the \%attr parameter. - -B<*> If the underlying database offers nothing better, then some -drivers may attempt to implement this method by executing -"C statements. -If a row cache is not implemented, then setting C is ignored -and getting the value returns C. - -Some C values have special meaning, as follows: - - 0 - Automatically determine a reasonable cache size for each C. - -Note that large cache sizes may require a very large amount of memory -(I). Also, a large cache will cause -a longer delay not only for the first fetch, but also whenever the -cache needs refilling. - -See also the L statement handle attribute. - -=head3 C - -Type: string - -Returns the username used to connect to the database. - - -=head1 DBI STATEMENT HANDLE OBJECTS - -This section lists the methods and attributes associated with DBI -statement handles. - -=head2 Statement Handle Methods - -The DBI defines the following methods for use on DBI statement handles: - -=head3 C - - $sth->bind_param($p_num, $bind_value) - $sth->bind_param($p_num, $bind_value, \%attr) - $sth->bind_param($p_num, $bind_value, $bind_type) - -The C method takes a copy of $bind_value and associates it -(binds it) with a placeholder, identified by $p_num, embedded in -the prepared statement. Placeholders are indicated with question -mark character (C). For example: - - $dbh->{RaiseError} = 1; # save having to check each method call - $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE ?"); - $sth->bind_param(1, "John%"); # placeholders are numbered from 1 - $sth->execute; - DBI::dump_results($sth); - -See L for more information. - - -B - -The C<\%attr> parameter can be used to hint at the data type the -placeholder should have. This is rarely needed. Typically, the driver is only -interested in knowing if the placeholder should be bound as a number or a string. - - $sth->bind_param(1, $value, { TYPE => SQL_INTEGER }); - -As a short-cut for the common case, the data type can be passed -directly, in place of the C<\%attr> hash reference. This example is -equivalent to the one above: - - $sth->bind_param(1, $value, SQL_INTEGER); - -The C value indicates the standard (non-driver-specific) type for -this parameter. To specify the driver-specific type, the driver may -support a driver-specific attribute, such as C<{ ora_type =E 97 }>. - -The SQL_INTEGER and other related constants can be imported using - - use DBI qw(:sql_types); - -See L for more information. - -The data type is 'sticky' in that bind values passed to execute() are bound -with the data type specified by earlier bind_param() calls, if any. -Portable applications should not rely on being able to change the data type -after the first C call. - -Perl only has string and number scalar data types. All database types -that aren't numbers are bound as strings and must be in a format the -database will understand except where the bind_param() TYPE attribute -specifies a type that implies a particular format. For example, given: - - $sth->bind_param(1, $value, SQL_DATETIME); - -the driver should expect $value to be in the ODBC standard SQL_DATETIME -format, which is 'YYYY-MM-DD HH:MM:SS'. Similarly for SQL_DATE, SQL_TIME etc. - -As an alternative to specifying the data type in the C call, -you can let the driver pass the value as the default type (C). -You can then use an SQL function to convert the type within the statement. -For example: - - INSERT INTO price(code, price) VALUES (?, CONVERT(MONEY,?)) - -The C function used here is just an example. The actual function -and syntax will vary between different databases and is non-portable. - -See also L for more information. - - -=head3 C - - $rc = $sth->bind_param_inout($p_num, \$bind_value, $max_len) or die $sth->errstr; - $rv = $sth->bind_param_inout($p_num, \$bind_value, $max_len, \%attr) or ... - $rv = $sth->bind_param_inout($p_num, \$bind_value, $max_len, $bind_type) or ... - -This method acts like L, but also enables values to be -updated by the statement. The statement is typically -a call to a stored procedure. The C<$bind_value> must be passed as a -reference to the actual value to be used. - -Note that unlike L, the C<$bind_value> variable is not -copied when C is called. Instead, the value in the -variable is read at the time L is called. - -The additional C<$max_len> parameter specifies the minimum amount of -memory to allocate to C<$bind_value> for the new value. If the value -returned from the database is too -big to fit, then the execution should fail. If unsure what value to use, -pick a generous length, i.e., a length larger than the longest value that would ever be -returned. The only cost of using a larger value than needed is wasted memory. - -Undefined values or C are used to indicate null values. -See also L for more information. - - -=head3 C - - $rc = $sth->bind_param_array($p_num, $array_ref_or_value) - $rc = $sth->bind_param_array($p_num, $array_ref_or_value, \%attr) - $rc = $sth->bind_param_array($p_num, $array_ref_or_value, $bind_type) - -The C method is used to bind an array of values -to a placeholder embedded in the prepared statement which is to be executed -with L. For example: - - $dbh->{RaiseError} = 1; # save having to check each method call - $sth = $dbh->prepare("INSERT INTO staff (first_name, last_name, dept) VALUES(?, ?, ?)"); - $sth->bind_param_array(1, [ 'John', 'Mary', 'Tim' ]); - $sth->bind_param_array(2, [ 'Booth', 'Todd', 'Robinson' ]); - $sth->bind_param_array(3, "SALES"); # scalar will be reused for each row - $sth->execute_array( { ArrayTupleStatus => \my @tuple_status } ); - -The C<%attr> ($bind_type) argument is the same as defined for L. -Refer to L for general details on using placeholders. - -(Note that bind_param_array() can I be used to expand a -placeholder into a list of values for a statement like "SELECT foo -WHERE bar IN (?)". A placeholder can only ever represent one value -per execution.) - -Scalar values, including C, may also be bound by -C. In which case the same value will be used for each -L call. Driver-specific implementations may behave -differently, e.g., when binding to a stored procedure call, some -databases may permit mixing scalars and arrays as arguments. - -The default implementation provided by DBI (for drivers that have -not implemented array binding) is to iteratively call L for -each parameter tuple provided in the bound arrays. Drivers may -provide more optimized implementations using whatever bulk operation -support the database API provides. The default driver behaviour should -match the default DBI behaviour, but always consult your driver -documentation as there may be driver specific issues to consider. - -Note that the default implementation currently only supports non-data -returning statements (INSERT, UPDATE, but not SELECT). Also, -C and L cannot be mixed in the same -statement execution, and C must be used with -L; using C will have no effect -for L. - -The C method was added in DBI 1.22. - -=head3 C - - $rv = $sth->execute or die $sth->errstr; - $rv = $sth->execute(@bind_values) or die $sth->errstr; - -Perform whatever processing is necessary to execute the prepared -statement. An C is returned if an error occurs. A successful -C always returns true regardless of the number of rows affected, -even if it's zero (see below). It is always important to check the -return status of C (and most other DBI methods) for errors -if you're not using L. - -For a I-C statements, execute simply "starts" the query within the -database engine. Use one of the fetch methods to retrieve the data after -calling C. The C method does I return the number of -rows that will be returned by the query (because most databases can't -tell in advance), it simply returns a true value. - -You can tell if the statement was a C" -will return only a single key from C. In these cases use -column aliases or C. Note that it is the database server -(and not the DBD implementation) which provides the I for fields -containing functions like "C" or "C" and they may clash -with existing column names (most databases don't care about duplicate column -names in a result-set). If you want these to return as unique names that are -the same across databases, use I, as in "C" depending on the syntax your database -supports. - -Because of the extra work C and Perl have to perform, it -is not as efficient as C or C. - -By default a reference to a new hash is returned for each row. -It is likely that a future version of the DBI will support an -attribute which will enable the same hash to be reused for each -row. This will give a significant performance boost, but it won't -be enabled by default because of the risk of breaking old code. - - -=head3 C - - $tbl_ary_ref = $sth->fetchall_arrayref; - $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); - $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); - -The C method can be used to fetch all the data to be -returned from a prepared and executed statement handle. It returns a -reference to an array that contains one reference per row. - -If called on an I statement handle, C returns undef. - -If there are no rows left to return from an I statement handle, C returns a reference -to an empty array. If an error occurs, C returns the -data fetched thus far, which may be none. You should check C<$sth-Eerr> -afterwards (or use the C attribute) to discover if the data is -complete or was truncated due to an error. - -If $slice is an array reference, C uses L -to fetch each row as an array ref. If the $slice array is not empty -then it is used as a slice to select individual columns by perl array -index number (starting at 0, unlike column and parameter numbers which -start at 1). - -With no parameters, or if $slice is undefined, C -acts as if passed an empty array ref. - -For example, to fetch just the first column of every row: - - $tbl_ary_ref = $sth->fetchall_arrayref([0]); - -To fetch the second to last and last column of every row: - - $tbl_ary_ref = $sth->fetchall_arrayref([-2,-1]); - -Those two examples both return a reference to an array of array refs. - -If $slice is a hash reference, C fetches each row as a hash -reference. If the $slice hash is empty then the keys in the hashes have -whatever name lettercase is returned by default. (See L -attribute.) If the $slice hash is I empty, then it is used as a slice to -select individual columns by name. The values of the hash should be set to 1. -The key names of the returned hashes match the letter case of the names in the -parameter hash, regardless of the L attribute. - -For example, to fetch all fields of every row as a hash ref: - - $tbl_ary_ref = $sth->fetchall_arrayref({}); - -To fetch only the fields called "foo" and "bar" of every row as a hash ref -(with keys named "foo" and "BAR", regardless of the original capitalization): - - $tbl_ary_ref = $sth->fetchall_arrayref({ foo=>1, BAR=>1 }); - -Those two examples both return a reference to an array of hash refs. - -If $slice is a I, that hash is used to select -and rename columns. The keys are 0-based column index numbers and the values -are the corresponding keys for the returned row hashes. - -For example, to fetch only the first and second columns of every row as a hash -ref (with keys named "k" and "v" regardless of their original names): - - $tbl_ary_ref = $sth->fetchall_arrayref( \{ 0 => 'k', 1 => 'v' } ); - -If $max_rows is defined and greater than or equal to zero then it -is used to limit the number of rows fetched before returning. -fetchall_arrayref() can then be called again to fetch more rows. -This is especially useful when you need the better performance of -fetchall_arrayref() but don't have enough memory to fetch and return -all the rows in one go. - -Here's an example (assumes RaiseError is enabled): - - my $rows = []; # cache for batches of rows - while( my $row = ( shift(@$rows) || # get row from cache, or reload cache: - shift(@{$rows=$sth->fetchall_arrayref(undef,10_000)||[]}) ) - ) { - ... - } - -That I be the fastest way to fetch and process lots of rows using the DBI, -but it depends on the relative cost of method calls vs memory allocation. - -A standard C loop with column binding is often faster because -the cost of allocating memory for the batch of rows is greater than -the saving by reducing method calls. It's possible that the DBI may -provide a way to reuse the memory of a previous batch in future, which -would then shift the balance back towards fetchall_arrayref(). - - -=head3 C - - $hash_ref = $sth->fetchall_hashref($key_field); - -The C method can be used to fetch all the data to be -returned from a prepared and executed statement handle. It returns a reference -to a hash containing a key for each distinct value of the $key_field column -that was fetched. For each key the corresponding value is a reference to a hash -containing all the selected columns and their values, as returned by -C. - -If there are no rows to return, C returns a reference -to an empty hash. If an error occurs, C returns the -data fetched thus far, which may be none. You should check -C<$sth-Eerr> afterwards (or use the C attribute) to -discover if the data is complete or was truncated due to an error. - -The $key_field parameter provides the name of the field that holds the -value to be used for the key for the returned hash. For example: - - $dbh->{FetchHashKeyName} = 'NAME_lc'; - $sth = $dbh->prepare("SELECT FOO, BAR, ID, NAME, BAZ FROM TABLE"); - $sth->execute; - $hash_ref = $sth->fetchall_hashref('id'); - print "Name for id 42 is $hash_ref->{42}->{name}\n"; - -The $key_field parameter can also be specified as an integer column -number (counting from 1). If $key_field doesn't match any column in -the statement, as a name first then as a number, then an error is -returned. - -For queries returning more than one 'key' column, you can specify -multiple column names by passing $key_field as a reference to an -array containing one or more key column names (or index numbers). -For example: - - $sth = $dbh->prepare("SELECT foo, bar, baz FROM table"); - $sth->execute; - $hash_ref = $sth->fetchall_hashref( [ qw(foo bar) ] ); - print "For foo 42 and bar 38, baz is $hash_ref->{42}->{38}->{baz}\n"; - -The fetchall_hashref() method is normally used only where the key -fields values for each row are unique. If multiple rows are returned -with the same values for the key fields then later rows overwrite -earlier ones. - -=head3 C - - $rc = $sth->finish; - -Indicate that no more data will be fetched from this statement handle -before it is either executed again or destroyed. You almost certainly -do I need to call this method. - -Adding calls to C after loop that fetches all rows is a common mistake, -don't do it, it can mask genuine problems like uncaught fetch errors. - -When all the data has been fetched from a C -C (for some specific operations like C and C), or -after fetching all the rows of a C statements, it is generally not possible to know how many -rows will be returned except by fetching them all. Some drivers will -return the number of rows the application has fetched so far, but -others may return -1 until all rows have been fetched. So use of the -C method or C<$DBI::rows> with C is to execute a -"SELECT COUNT(*) FROM ..." SQL statement with the same "..." as your -query and then fetch the row count from that. - - -=head3 C - - $rc = $sth->bind_col($column_number, \$var_to_bind); - $rc = $sth->bind_col($column_number, \$var_to_bind, \%attr ); - $rc = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); - -Binds a Perl variable and/or some attributes to an output column -(field) of a C statement. - -The list of references should have the same number of elements as the number of -columns in the C statements, then -this attribute holds the number of un-fetched rows in the cache. If the -driver doesn't, then it returns C. Note that some drivers pre-fetch -rows on execute, whereas others wait till the first fetch. - -See also the L database handle attribute. - -=head1 FURTHER INFORMATION - -=head2 Catalog Methods - -An application can retrieve metadata information from the DBMS by issuing -appropriate queries on the views of the Information Schema. Unfortunately, -C views are seldom supported by the DBMS. -Special methods (catalog methods) are available to return result sets -for a small but important portion of that metadata: - - column_info - foreign_key_info - primary_key_info - table_info - statistics_info - -All catalog methods accept arguments in order to restrict the result sets. -Passing C to an optional argument does not constrain the search for -that argument. -However, an empty string ('') is treated as a regular search criteria -and will only match an empty value. - -B: SQL/CLI and ODBC differ in the handling of empty strings. An -empty string will not restrict the result set in SQL/CLI. - -Most arguments in the catalog methods accept only I, e.g. -the arguments of C. -Such arguments are treated as a literal string, i.e. the case is significant -and quote characters are taken literally. - -Some arguments in the catalog methods accept I (strings -containing '_' and/or '%'), e.g. the C<$table> argument of C. -Passing '%' is equivalent to leaving the argument C. - -B: The underscore ('_') is valid and often used in SQL identifiers. -Passing such a value to a search pattern argument may return more rows than -expected! -To include pattern characters as literals, they must be preceded by an -escape character which can be achieved with - - $esc = $dbh->get_info( 14 ); # SQL_SEARCH_PATTERN_ESCAPE - $search_pattern =~ s/([_%])/$esc$1/g; - -The ODBC and SQL/CLI specifications define a way to change the default -behaviour described above: All arguments (except I) -are treated as I if the C attribute is -set to C. -I are very similar to I, i.e. their -body (the string within the quotes) is interpreted literally. -I are compared in UPPERCASE. - -The DBI (currently) does not support the C attribute, -i.e. it behaves like an ODBC driver where C is set to -C. - - -=head2 Transactions - -Transactions are a fundamental part of any robust database system. They -protect against errors and database corruption by ensuring that sets of -related changes to the database take place in atomic (indivisible, -all-or-nothing) units. - -This section applies to databases that support transactions and where -C is off. See L for details of using C -with various types of databases. - -The recommended way to implement robust transactions in Perl -applications is to enable L and catch the error that's 'thrown' as -an exception. For example, using L: - - use Try::Tiny; - $dbh->{AutoCommit} = 0; # enable transactions, if possible - $dbh->{RaiseError} = 1; - try { - foo(...) # do lots of work here - bar(...) # including inserts - baz(...) # and updates - $dbh->commit; # commit the changes if we get this far - } catch { - warn "Transaction aborted because $_"; # Try::Tiny copies $@ into $_ - # now rollback to undo the incomplete changes - # but do it in an eval{} as it may also fail - eval { $dbh->rollback }; - # add other application on-error-clean-up code here - }; - -If the C attribute is not set, then DBI calls would need to be -manually checked for errors, typically like this: - - $h->method(@args) or die $h->errstr; - -With C set, the DBI will automatically C if any DBI method -call on that handle (or a child handle) fails, so you don't have to -test the return value of each method call. See L for more -details. - -A major advantage of the C approach is that the transaction will be -properly rolled back if I code (not just DBI calls) in the inner -application dies for any reason. The major advantage of using the -C<$h-E{RaiseError}> attribute is that all DBI calls will be checked -automatically. Both techniques are strongly recommended. - -After calling C or C many drivers will not let you -fetch from a previously active C statements. - -See L and L for other important information -about transactions. - - -=head2 Handling BLOB / LONG / Memo Fields - -Many databases support "blob" (binary large objects), "long", or similar -datatypes for holding very long strings or large amounts of binary -data in a single field. Some databases support variable length long -values over 2,000,000,000 bytes in length. - -Since values of that size can't usually be held in memory, and because -databases can't usually know in advance the length of the longest long -that will be returned from a C -statements (or any other statements that can return many -values from the database using a cursor-like mechanism). See -C above for more explanations. - -There plans for a preparse function to be provided by B, but this has -not reached fruition yet. -Meantime, if you want to know how ugly it can get, try looking at the -C in B F and the related -functions in F and F. - -=head3 The dbd_st_fetch method - -This function fetches a row of data. The row is stored in in an array, -of C's that B prepares for you. This has two advantages: it is fast -(you even reuse the C's, so they don't have to be created after the -first C), and it guarantees that B handles C for -you. - -What you do is the following: - - AV* av; - int numFields = DBIc_NUM_FIELDS(imp_sth); /* Correct, if NUM_FIELDS - is constant for this statement. There are drivers where this is - not the case! */ - int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks); - int i; - - if (!fetch_new_row_of_data(...)) { - ... /* check for error or end-of-data */ - DBIc_ACTIVE_off(imp_sth); /* turn off Active flag automatically */ - return Nullav; - } - /* get the fbav (field buffer array value) for this row */ - /* it is very important to only call this after you know */ - /* that you have a row of data to return. */ - av = DBIc_DBISTATE(imp_sth)->get_fbav(imp_sth); - for (i = 0; i < numFields; i++) { - SV* sv = fetch_a_field(..., i); - if (chopBlanks && SvOK(sv) && type_is_blank_padded(field_type[i])) { - /* Remove white space from end (only) of sv */ - } - sv_setsv(AvARRAY(av)[i], sv); /* Note: (re)use! */ - } - return av; - -There's no need to use a C function returning an C. -It's more common to use your database API functions to fetch the -data as character strings and use code like this: - - sv_setpvn(AvARRAY(av)[i], char_ptr, char_count); - -C values must be returned as C. You can use code like this: - - SvOK_off(AvARRAY(av)[i]); - -The function returns the C prepared by B for success or C -otherwise. - - *FIX ME* Discuss what happens when there's no more data to fetch. - Are errors permitted if another fetch occurs after the first fetch - that reports no more data. (Permitted, not required.) - -If an error occurs which leaves the I<$sth> in a state where remaining -rows can't be fetched then I should be turned off before the -method returns. - -=head3 The dbd_st_finish3 method - -The C<$sth-Efinish()> method can be called if the user wishes to -indicate that no more rows will be fetched even if the database has more -rows to offer, and the B code can call the function when handles are -being destroyed. See the B specification for more background details. - -In both circumstances, the B code ends up calling the -C method (if you provide a mapping for -C in F), or C otherwise. -The difference is that C takes a third argument which -is an C with the value 1 if it is being called from a C -method and 0 otherwise. - -Note that B v1.32 and earlier test on C to call -C; if you provide C, either define -C too, or insist on B v1.33 or later. - -All it I to do is turn off the I flag for the I. -It will only be called by F code, if the driver has set I -to on for the I. - -Outline example: - - int dbd_st_finish3(SV* sth, imp_sth_t* imp_sth, int from_destroy) { - if (DBIc_ACTIVE(imp_sth)) - { - /* close cursor or equivalent action */ - DBIc_ACTIVE_off(imp_sth); - } - return 1; - } - -The from_destroy parameter is true if C is being called -from C - and so the statement is about to be destroyed. -For many drivers there is no point in doing anything more than turning off -the I flag in this case. - -The function returns I for success, I otherwise, but there isn't -a lot anyone can do to recover if there is an error. - -=head3 The dbd_st_destroy method - -This function is the private part of the statement handle destructor. - - void dbd_st_destroy(SV* sth, imp_sth_t* imp_sth) { - ... /* any clean-up that's needed */ - DBIc_IMPSET_off(imp_sth); /* let DBI know we've done it */ - } - -The B F code will call C for you, if the -I has the I flag set, before calling C. - -=head3 The dbd_st_STORE_attrib and dbd_st_FETCH_attrib methods - -These functions correspond to C and C attrib -above, except that they are for statement handles. -See above. - - int dbd_st_STORE_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv, - SV* valuesv); - SV* dbd_st_FETCH_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv); - -=head3 The dbd_bind_ph method - -This function is internally used by the C method, the -C method and by the B F code if -C is called with any bind parameters. - - int dbd_bind_ph (SV *sth, imp_sth_t *imp_sth, SV *param, - SV *value, IV sql_type, SV *attribs, - int is_inout, IV maxlen); - -The I argument holds an C with the parameter number (1, 2, ...). -The I argument is the parameter value and I is its type. - -If your driver does not support C then you should -ignore I and croak if I is I. - -If your driver I support C then you should -note that I is the C I dereferencing the reference -passed to C. - -In drivers of simple databases the function will, for example, store -the value in a parameter array and use it later in C. -See the B driver for an example. - -=head3 Implementing bind_param_inout support - -To provide support for parameters bound by reference rather than by -value, the driver must do a number of things. First, and most -importantly, it must note the references and stash them in its own -driver structure. Secondly, when a value is bound to a column, the -driver must discard any previous reference bound to the column. On -each execute, the driver must evaluate the references and internally -bind the values resulting from the references. This is only applicable -if the user writes: - - $sth->execute; - -If the user writes: - - $sth->execute(@values); - -then B automatically calls the binding code for each element of -I<@values>. These calls are indistinguishable from explicit user calls to -C. - -=head2 C/XS version of Makefile.PL - -The F file for a C/XS driver is similar to the code needed -for a pure Perl driver, but there are a number of extra bits of -information needed by the build system. - -For example, the attributes list passed to C needs -to specify the object files that need to be compiled and built into -the shared object (DLL). This is often, but not necessarily, just -F (unless that should be F because you're building -on MS Windows). - -Note that you can reliably determine the extension of the object files -from the I<$Config{obj_ext}> values, and there are many other useful pieces -of configuration information lurking in that hash. -You get access to it with: - - use Config; - -=head2 Methods which do not need to be written - -The B code implements the majority of the methods which are accessed -using the notation Cfunction()>, the only exceptions being -Cconnect()> and Cdata_sources()> which require -support from the driver. - -The B code implements the following documented driver, database and -statement functions which do not need to be written by the B driver -writer. - -=over 4 - -=item $dbh->do() - -The default implementation of this function prepares, executes and -destroys the statement. This can be replaced if there is a better -way to implement this, such as C which can -sometimes be used if there are no parameters. - -=item $h->errstr() - -=item $h->err() - -=item $h->state() - -=item $h->trace() - -The B driver does not need to worry about these routines at all. - -=item $h->{ChopBlanks} - -This attribute needs to be honored during C operations, but does -not need to be handled by the attribute handling code. - -=item $h->{RaiseError} - -The B driver does not need to worry about this attribute at all. - -=item $h->{PrintError} - -The B driver does not need to worry about this attribute at all. - -=item $sth->bind_col() - -Assuming the driver uses the Cget_fbav()> -function (C drivers, see below), or the C<$sth-E_set_fbav($data)> -method (Perl drivers) the driver does not need to do anything about this -routine. - -=item $sth->bind_columns() - -Regardless of whether the driver uses -Cget_fbav()>, the driver does not need -to do anything about this routine as it simply iteratively calls -C<$sth-Ebind_col()>. - -=back - -The B code implements a default implementation of the following -functions which do not need to be written by the B driver writer -unless the default implementation is incorrect for the Driver. - -=over 4 - -=item $dbh->quote() - -This should only be written if the database does not accept the ANSI -SQL standard for quoting strings, with the string enclosed in single -quotes and any embedded single quotes replaced by two consecutive -single quotes. - -For the two argument form of quote, you need to implement the -C method to provide the information that quote needs. - -=item $dbh->ping() - -This should be implemented as a simple efficient way to determine -whether the connection to the database is still alive. Typically -code like this: - - sub ping { - my $dbh = shift; - $sth = $dbh->prepare_cached(q{ - select * from A_TABLE_NAME where 1=0 - }) or return 0; - $sth->execute or return 0; - $sth->finish; - return 1; - } - -where I is the name of a table that always exists (such as a -database system catalogue). - -=item $drh->default_user - -The default implementation of default_user will get the database -username and password fields from C<$ENV{DBI_USER}> and -C<$ENV{DBI_PASS}>. You can override this method. It is called as -follows: - - ($user, $pass) = $drh->default_user($user, $pass, $attr) - -=back - -=head1 METADATA METHODS - -The exposition above ignores the B MetaData methods. -The metadata methods are all associated with a database handle. - -=head2 Using DBI::DBD::Metadata - -The B module is a good semi-automatic way for the -developer of a B module to write the C and C -functions quickly and accurately. - -=head3 Generating the get_info method - -Prior to B v1.33, this existed as the method C -in the B module. From B v1.33, it exists as the method -C in the B module. This -discussion assumes you have B v1.33 or later. - -You examine the documentation for C using: - - perldoc DBI::DBD::Metadata - -To use it, you need a Perl B driver for your database which implements -the C method. In practice, this means you need to install -B, an ODBC driver manager, and an ODBC driver for your -database. - -With the pre-requisites in place, you might type: - - perl -MDBI::DBD::Metadata -we \ - "write_getinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })" - -The procedure writes to standard output the code that should be added to -your F file and the code that should be written to -F. - -You should review the output to ensure that it is sensible. - -=head3 Generating the type_info method - -Given the idea of the C method, it was not hard -to devise a parallel method, C, which does the -analogous job for the B C metadata method. The -C method was added to B v1.33. - -You examine the documentation for C using: - - perldoc DBI::DBD::Metadata - -The setup is exactly analogous to the mechanism described in -L. - -With the pre-requisites in place, you might type: - - perl -MDBI::DBD::Metadata -we \ - "write_typeinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })" - -The procedure writes to standard output the code that should be added to -your F file and the code that should be written to -F. - -You should review the output to ensure that it is sensible. - -=head2 Writing DBD::Driver::db::get_info - -If you use the B module, then the code you need is -generated for you. - -If you decide not to use the B module, you -should probably borrow the code from a driver that has done so (eg -B from version 1.05 onwards) and crib the code from -there, or look at the code that generates that module and follow -that. The method in F will be very simple; the method in -F is not very much more complex unless your -DBMS itself is much more complex. - -Note that some of the B utility methods rely on information from the -C method to perform their operations correctly. See, for -example, the C and quote methods, discussed below. - -=head2 Writing DBD::Driver::db::type_info_all - -If you use the C module, then the code you need is -generated for you. - -If you decide not to use the C module, you -should probably borrow the code from a driver that has done so (eg -C from version 1.05 onwards) and crib the code from -there, or look at the code that generates that module and follow -that. The method in F will be very simple; the method in -F is not very much more complex unless your -DBMS itself is much more complex. - -=head2 Writing DBD::Driver::db::type_info - -The guidelines on writing this method are still not really clear. -No sample implementation is available. - -=head2 Writing DBD::Driver::db::table_info - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::column_info - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::primary_key_info - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::primary_key - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::foreign_key_info - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::tables - -This method generates an array of names in a format suitable for being -embedded in SQL statements in places where a table name is expected. - -If your database hews close enough to the SQL standard or if you have -implemented an appropriate C function and and the appropriate -C function, then the B default version of this method -will work for your driver too. - -Otherwise, you have to write a function yourself, such as: - - sub tables - { - my($dbh, $cat, $sch, $tab, $typ) = @_; - my(@res); - my($sth) = $dbh->table_info($cat, $sch, $tab, $typ); - my(@arr); - while (@arr = $sth->fetchrow_array) - { - push @res, $dbh->quote_identifier($arr[0], $arr[1], $arr[2]); - } - return @res; - } - -See also the default implementation in F. - -=head2 Writing DBD::Driver::db::quote - -This method takes a value and converts it into a string suitable for -embedding in an SQL statement as a string literal. - -If your DBMS accepts the SQL standard notation for strings (single -quotes around the string as a whole with any embedded single quotes -doubled up), then you do not need to write this method as B provides a -default method that does it for you. - -If your DBMS uses an alternative notation or escape mechanism, then you -need to provide an equivalent function. For example, suppose your DBMS -used C notation with double quotes around the string and backslashes -escaping both double quotes and backslashes themselves. Then you might -write the function as: - - sub quote - { - my($dbh, $str) = @_; - $str =~ s/["\\]/\\$&/gmo; - return qq{"$str"}; - } - -Handling newlines and other control characters is left as an exercise -for the reader. - -This sample method ignores the I<$data_type> indicator which is the -optional second argument to the method. - -=head2 Writing DBD::Driver::db::quote_identifier - -This method is called to ensure that the name of the given table (or -other database object) can be embedded into an SQL statement without -danger of misinterpretation. The result string should be usable in the -text of an SQL statement as the identifier for a table. - -If your DBMS accepts the SQL standard notation for quoted identifiers -(which uses double quotes around the identifier as a whole, with any -embedded double quotes doubled up) and accepts I<"schema"."identifier"> -(and I<"catalog"."schema"."identifier"> when a catalog is specified), then -you do not need to write this method as B provides a default method -that does it for you. - -In fact, even if your DBMS does not handle exactly that notation but -you have implemented the C method and it gives the correct -responses, then it will work for you. If your database is fussier, then -you need to implement your own version of the function. - -For example, B has to deal with an environment variable -I. If it is not set, then the DBMS treats names enclosed in -double quotes as strings rather than names, which is usually a syntax -error. Additionally, the catalog portion of the name is separated from -the schema and table by a different delimiter (colon instead of dot), -and the catalog portion is never enclosed in quotes. (Fortunately, -valid strings for the catalog will never contain weird characters that -might need to be escaped, unless you count dots, dashes, slashes and -at-signs as weird.) Finally, an Informix database can contain objects -that cannot be accessed because they were created by a user with the -I environment variable set, but the current user does not -have it set. By design choice, the C method encloses -those identifiers in double quotes anyway, which generally triggers a -syntax error, and the metadata methods which generate lists of tables -etc omit those identifiers from the result sets. - - sub quote_identifier - { - my($dbh, $cat, $sch, $obj) = @_; - my($rv) = ""; - my($qq) = (defined $ENV{DELIMIDENT}) ? '"' : ''; - $rv .= qq{$cat:} if (defined $cat); - if (defined $sch) - { - if ($sch !~ m/^\w+$/o) - { - $qq = '"'; - $sch =~ s/$qq/$qq$qq/gm; - } - $rv .= qq{$qq$sch$qq.}; - } - if (defined $obj) - { - if ($obj !~ m/^\w+$/o) - { - $qq = '"'; - $obj =~ s/$qq/$qq$qq/gm; - } - $rv .= qq{$qq$obj$qq}; - } - return $rv; - } - -Handling newlines and other control characters is left as an exercise -for the reader. - -Note that there is an optional fourth parameter to this function which -is a reference to a hash of attributes; this sample implementation -ignores that. - -This sample implementation also ignores the single-argument variant of -the method. - -=head1 TRACING - -Tracing in DBI is controlled with a combination of a trace level and a -set of flags which together are known as the trace settings. The trace -settings are stored in a single integer and divided into levels and -flags by a set of masks (C and -C). - -Each handle has it's own trace settings and so does the DBI. When you -call a method the DBI merges the handles settings into its own for the -duration of the call: the trace flags of the handle are OR'd into the -trace flags of the DBI, and if the handle has a higher trace level -then the DBI trace level is raised to match it. The previous DBI trace -settings are restored when the called method returns. - -=head2 Trace Level - -The trace level is the first 4 bits of the trace settings (masked by -C) and represents trace levels of 1 to 15. Do -not output anything at trace levels less than 3 as they are reserved -for DBI. - -For advice on what to output at each level see "Trace Levels" in -L. - -To test for a trace level you can use the C macro -like this: - - if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) { - PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar"); - } - -Also B the use of PerlIO_printf which you should always use for -tracing and never the C C I/O functions. - -=head2 Trace Flags - -Trace flags are used to enable tracing of specific activities within -the DBI and drivers. The DBI defines some trace flags and drivers can -define others. DBI trace flag names begin with a capital letter and -driver specific names begin with a lowercase letter. For a list of DBI -defined trace flags see "Trace Flags" in L. - -If you want to use private trace flags you'll probably want to be able -to set them by name. Drivers are expected to override the -parse_trace_flag (note the singular) and check if $trace_flag_name is -a driver specific trace flags and, if not, then call the DBIs default -parse_trace_flag(). To do that you'll need to define a -parse_trace_flag() method like this: - - sub parse_trace_flag { - my ($h, $name) = @_; - return 0x01000000 if $name eq 'foo'; - return 0x02000000 if $name eq 'bar'; - return 0x04000000 if $name eq 'baz'; - return 0x08000000 if $name eq 'boo'; - return 0x10000000 if $name eq 'bop'; - return $h->SUPER::parse_trace_flag($name); - } - -All private flag names must be lowercase, and all private flags must -be in the top 8 of the 32 bits of C i.e., -0xFF000000. - -If you've defined a parse_trace_flag() method in ::db you'll also want -it in ::st, so just alias it in: - - *parse_trace_flag = \&DBD::foo:db::parse_trace_flag; - -You may want to act on the current 'SQL' trace flag that DBI defines -to output SQL prepared/executed as DBI currently does not do SQL -tracing. - -=head2 Trace Macros - -Access to the trace level and trace flags is via a set of macros. - - DBIc_TRACE_SETTINGS(imp) returns the trace settings - DBIc_TRACE_LEVEL(imp) returns the trace level - DBIc_TRACE_FLAGS(imp) returns the trace flags - DBIc_TRACE(imp, flags, flaglevel, level) - - e.g., - - DBIc_TRACE(imp, 0, 0, 4) - if level >= 4 - - DBIc_TRACE(imp, DBDtf_FOO, 2, 4) - if tracing DBDtf_FOO & level>=2 or level>=4 - - DBIc_TRACE(imp, DBDtf_FOO, 2, 0) - as above but never trace just due to level - -=head1 WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE - -Study F (supplied with B) and F (supplied -with B) and the corresponding I files for ideas. - -Note that the emulation code sets C<$dbh-E{CompatMode} = 1;> for each -connection so that the internals of the driver can implement behaviour -compatible with the old interface when dealing with those handles. - -=head2 Setting emulation perl variables - -For example, ingperl has a I<$sql_rowcount> variable. Rather than try -to manually update this in F it can be done faster in C code. -In C: - - sql_rowcount = perl_get_sv("Ingperl::sql_rowcount", GV_ADDMULTI); - -In the relevant places do: - - if (DBIc_COMPAT(imp_sth)) /* only do this for compatibility mode handles */ - sv_setiv(sql_rowcount, the_row_count); - -=head1 OTHER MISCELLANEOUS INFORMATION - -=head2 The imp_xyz_t types - -Any handle has a corresponding C structure filled with private data. -Some of this data is reserved for use by B (except for using the -DBIc macros below), some is for you. See the description of the -F file above for examples. Most functions in F -are passed both the handle C and a pointer to C. In -rare cases, however, you may use the following macros: - -=over 4 - -=item D_imp_dbh(dbh) - -Given a function argument I, declare a variable I and -initialize it with a pointer to the handles private data. Note: This -must be a part of the function header, because it declares a variable. - -=item D_imp_sth(sth) - -Likewise for statement handles. - -=item D_imp_xxx(h) - -Given any handle, declare a variable I and initialize it -with a pointer to the handles private data. It is safe, for example, -to cast I to C, if C. -(You can also call C, but that's much -slower.) - -=item D_imp_dbh_from_sth - -Given a I, declare a variable I and initialize it with a -pointer to the parent database handle's implementors structure. - -=back - -=head2 Using DBIc_IMPSET_on - -The driver code which initializes a handle should use C -as soon as its state is such that the cleanup code must be called. -When this happens is determined by your driver code. - -B - -For example, B maintains a linked list of database -handles in the driver, and within each handle, a linked list of -statements. Once a statement is added to the linked list, it is crucial -that it is cleaned up (removed from the list). When I -was being called too late, it was able to cause all sorts of problems. - -=head2 Using DBIc_is(), DBIc_has(), DBIc_on() and DBIc_off() - -Once upon a long time ago, the only way of handling the internal B -boolean flags/attributes was through macros such as: - - DBIc_WARN DBIc_WARN_on DBIc_WARN_off - DBIc_COMPAT DBIc_COMPAT_on DBIc_COMPAT_off - -Each of these took an I pointer as an argument. - -Since then, new attributes have been added such as I, -I and I, and these do not have the full set of -macros. The approved method for handling these is now the four macros: - - DBIc_is(imp, flag) - DBIc_has(imp, flag) an alias for DBIc_is - DBIc_on(imp, flag) - DBIc_off(imp, flag) - DBIc_set(imp, flag, on) set if on is true, else clear - -Consequently, the C family of macros is now mostly deprecated -and new drivers should avoid using them, even though the older drivers -will probably continue to do so for quite a while yet. However... - -There is an I to that. The I and I -flags should be set via the C and C macros, -and unset via the C and C macros. - -=head2 Using the get_fbav() method - -B. - -The C<$sth-Ebind_col()> and C<$sth-Ebind_columns()> documented -in the B specification do not have to be implemented by the driver -writer because B takes care of the details for you. - -However, the key to ensuring that bound columns work is to call the -function Cget_fbav()> in the code which -fetches a row of data. - -This returns an C, and each element of the C contains the C which -should be set to contain the returned data. - -The pure Perl equivalent is the C<$sth-E_set_fbav($data)> method, as -described in the part on pure Perl drivers. - -=head2 Casting strings to Perl types based on a SQL type - -DBI from 1.611 (and DBIXS_REVISION 13606) defines the -sql_type_cast_svpv method which may be used to cast a string -representation of a value to a more specific Perl type based on a SQL -type. You should consider using this method when processing bound -column data as it provides some support for the TYPE bind_col -attribute which is rarely used in drivers. - - int sql_type_cast_svpv(pTHX_ SV *sv, int sql_type, U32 flags, void *v) - -C is what you would like cast, C is one of the DBI defined -SQL types (e.g., C) and C is a bitmask as follows: - -=over - -=item DBIstcf_STRICT - -If set this indicates you want an error state returned if the cast -cannot be performed. - -=item DBIstcf_DISCARD_STRING - -If set and the pv portion of the C is cast then this will cause -sv's pv to be freed up. - -=back - -sql_type_cast_svpv returns the following states: - - -2 sql_type is not handled - sv not changed - -1 sv is undef, sv not changed - 0 sv could not be cast cleanly and DBIstcf_STRICT was specified - 1 sv could not be case cleanly and DBIstcf_STRICT was not specified - 2 sv was cast ok - -The current implementation of sql_type_cast_svpv supports -C, C and C. C uses -sv_2iv and hence may set IV, UV or NV depending on the -number. C uses sv_2nv so may set NV and C -will set IV or UV or NV. - -DBIstcf_STRICT should be implemented as the StrictlyTyped attribute -and DBIstcf_DISCARD_STRING implemented as the DiscardString attribute -to the bind_col method and both default to off. - -See DBD::Oracle for an example of how this is used. - -=head1 SUBCLASSING DBI DRIVERS - -This is definitely an open subject. It can be done, as demonstrated by -the B driver, but it is not as simple as one might think. - -(Note that this topic is different from subclassing the B. For an -example of that, see the F file supplied with the B.) - -The main problem is that the I's and I's that your C and -C methods return are not instances of your B -or B packages, they are not even derived from it. -Instead they are instances of the B or B classes or -a derived subclass. Thus, if you write a method C and do a - - $dbh->mymethod() - -then the autoloader will search for that method in the package B. -Of course you can instead to a - - $dbh->func('mymethod') - -and that will indeed work, even if C is inherited, but not -without additional work. Setting I<@ISA> is not sufficient. - -=head2 Overwriting methods - -The first problem is, that the C method has no idea of -subclasses. For example, you cannot implement base class and subclass -in the same file: The C method wants to do a - - require DBD::Driver; - -In particular, your subclass B to be a separate driver, from -the view of B, and you cannot share driver handles. - -Of course that's not much of a problem. You should even be able -to inherit the base classes C method. But you cannot -simply overwrite the method, unless you do something like this, -quoted from B: - - sub connect ($$;$$$) { - my ($drh, $dbname, $user, $auth, $attr) = @_; - - my $this = $drh->DBD::File::dr::connect($dbname, $user, $auth, $attr); - if (!exists($this->{csv_tables})) { - $this->{csv_tables} = {}; - } - - $this; - } - -Note that we cannot do a - - $drh->SUPER::connect($dbname, $user, $auth, $attr); - -as we would usually do in a an OO environment, because I<$drh> is an instance -of B. And note, that the C method of B is -able to handle subclass attributes. See the description of Pure Perl -drivers above. - -It is essential that you always call superclass method in the above -manner. However, that should do. - -=head2 Attribute handling - -Fortunately the B specifications allow a simple, but still -performant way of handling attributes. The idea is based on the -convention that any driver uses a prefix I for its private -methods. Thus it's always clear whether to pass attributes to the super -class or not. For example, consider this C method from the -B class: - - sub STORE { - my ($dbh, $attr, $val) = @_; - if ($attr !~ /^driver_/) { - return $dbh->DBD::File::db::STORE($attr, $val); - } - if ($attr eq 'driver_foo') { - ... - } - -=cut - -use Exporter (); -use Config qw(%Config); -use Carp; -use Cwd; -use File::Spec; -use strict; -use vars qw( - @ISA @EXPORT - $is_dbi -); - -BEGIN { - if ($^O eq 'VMS') { - require vmsish; - import vmsish; - require VMS::Filespec; - import VMS::Filespec; - } - else { - *vmsify = sub { return $_[0] }; - *unixify = sub { return $_[0] }; - } -} - -@ISA = qw(Exporter); - -@EXPORT = qw( - dbd_dbi_dir - dbd_dbi_arch_dir - dbd_edit_mm_attribs - dbd_postamble -); - -BEGIN { - $is_dbi = (-r 'DBI.pm' && -r 'DBI.xs' && -r 'DBIXS.h'); - require DBI unless $is_dbi; -} - -my $done_inst_checks; - -sub _inst_checks { - return if $done_inst_checks++; - my $cwd = cwd(); - if ($cwd =~ /\Q$Config{path_sep}/) { - warn "*** Warning: Path separator characters (`$Config{path_sep}') ", - "in the current directory path ($cwd) may cause problems\a\n\n"; - sleep 2; - } - if ($cwd =~ /\s/) { - warn "*** Warning: whitespace characters ", - "in the current directory path ($cwd) may cause problems\a\n\n"; - sleep 2; - } - if ( $^O eq 'MSWin32' - && $Config{cc} eq 'cl' - && !(exists $ENV{'LIB'} && exists $ENV{'INCLUDE'})) - { - die < { name => "DBI::PurePerl", - match => qr/^\d/, - add => [ '$ENV{DBI_PUREPERL} = 2', - 'END { delete $ENV{DBI_PUREPERL}; }' ], - }, - g => { name => "DBD::Gofer", - match => qr/^\d/, - add => [ q{$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'}, - q|END { delete $ENV{DBI_AUTOPROXY}; }| ], - }, - n => { name => "DBI::SQL::Nano", - match => qr/^(?:48dbi_dbd_sqlengine|49dbd_file|5\ddbm_\w+|85gofer)\.t$/, - add => [ q{$ENV{DBI_SQL_NANO} = 1}, - q|END { delete $ENV{DBI_SQL_NANO}; }| ], - }, - # mx => { name => "DBD::Multiplex", - # add => [ q{local $ENV{DBI_AUTOPROXY} = 'dbi:Multiplex:';} ], - # } - # px => { name => "DBD::Proxy", - # need mechanism for starting/stopping the proxy server - # add => [ q{local $ENV{DBI_AUTOPROXY} = 'dbi:Proxy:XXX';} ], - # } - ); - - # decide what needs doing - $dbd_attr->{create_pp_tests} or delete $test_variants{p}; - $dbd_attr->{create_nano_tests} or delete $test_variants{n}; - $dbd_attr->{create_gap_tests} or delete $test_variants{g}; - - # expand for all combinations - my @all_keys = my @tv_keys = sort keys %test_variants; - while( @tv_keys ) { - my $cur_key = shift @tv_keys; - last if( 1 < length $cur_key ); - my @new_keys; - foreach my $remain (@tv_keys) { - push @new_keys, $cur_key . $remain unless $remain =~ /$cur_key/; - } - push @tv_keys, @new_keys; - push @all_keys, @new_keys; - } - - my %uniq_keys; - foreach my $key (@all_keys) { - @tv_keys = sort split //, $key; - my $ordered = join( '', @tv_keys ); - $uniq_keys{$ordered} = 1; - } - @all_keys = sort { length $a <=> length $b or $a cmp $b } keys %uniq_keys; - - # do whatever needs doing - if( keys %test_variants ) { - # XXX need to convert this to work within the generated Makefile - # so 'make' creates them and 'make clean' deletes them - opendir DIR, 't' or die "Can't read 't' directory: $!"; - my @tests = grep { /\.t$/ } readdir DIR; - closedir DIR; - - foreach my $test_combo (@all_keys) { - @tv_keys = split //, $test_combo; - my @test_names = map { $test_variants{$_}->{name} } @tv_keys; - printf "Creating test wrappers for " . join( " + ", @test_names ) . ":\n"; - my @test_matches = map { $test_variants{$_}->{match} } @tv_keys; - my @test_adds; - foreach my $test_add ( map { $test_variants{$_}->{add} } @tv_keys) { - push @test_adds, @$test_add; - } - my $v_type = $test_combo; - $v_type = 'x' . $v_type if length( $v_type ) > 1; - - TEST: - foreach my $test (sort @tests) { - foreach my $match (@test_matches) { - next TEST if $test !~ $match; - } - my $usethr = ($test =~ /(\d+|\b)thr/ && $] >= 5.008 && $Config{useithreads}); - my $v_test = "t/zv${v_type}_$test"; - my $v_perl = ($test =~ /taint/) ? "perl -wT" : "perl -w"; - printf "%s %s\n", $v_test, ($usethr) ? "(use threads)" : ""; - open PPT, ">$v_test" or warn "Can't create $v_test: $!"; - print PPT "#!$v_perl\n"; - print PPT "use threads;\n" if $usethr; - print PPT "$_;\n" foreach @test_adds; - print PPT "require './t/$test'; # or warn \$!;\n"; - close PPT or warn "Error writing $v_test: $!"; - } - } - } - return %$mm_attr; -} - -sub dbd_dbi_dir { - _inst_checks(); - return '.' if $is_dbi; - my $dbidir = $INC{'DBI.pm'} || die "DBI.pm not in %INC!"; - $dbidir =~ s:/DBI\.pm$::; - return $dbidir; -} - -sub dbd_dbi_arch_dir { - _inst_checks(); - return '$(INST_ARCHAUTODIR)' if $is_dbi; - my $dbidir = dbd_dbi_dir(); - my %seen; - my @try = grep { not $seen{$_}++ } map { vmsify( unixify($_) . "/auto/DBI/" ) } @INC; - my @xst = grep { -f vmsify( unixify($_) . "/Driver.xst" ) } @try; - Carp::croak("Unable to locate Driver.xst in @try") unless @xst; - Carp::carp( "Multiple copies of Driver.xst found in: @xst") if @xst > 1; - print "Using DBI $DBI::VERSION (for perl $] on $Config{archname}) installed in $xst[0]\n"; - return File::Spec->canonpath($xst[0]); -} - -sub dbd_postamble { - my $self = shift; - _inst_checks(); - my $dbi_instarch_dir = ($is_dbi) ? "." : dbd_dbi_arch_dir(); - my $dbi_driver_xst= File::Spec->catfile($dbi_instarch_dir, 'Driver.xst'); - my $xstf_h = File::Spec->catfile($dbi_instarch_dir, 'Driver_xst.h'); - - # we must be careful of quotes, especially for Win32 here. - return ' -# --- This section was generated by DBI::DBD::dbd_postamble() -DBI_INSTARCH_DIR='.$dbi_instarch_dir.' -DBI_DRIVER_XST='.$dbi_driver_xst.' - -# The main dependency (technically correct but probably not used) -$(BASEEXT).c: $(BASEEXT).xsi - -# This dependency is needed since MakeMaker uses the .xs.o rule -$(BASEEXT)$(OBJ_EXT): $(BASEEXT).xsi - -$(BASEEXT).xsi: $(DBI_DRIVER_XST) '.$xstf_h.' - $(PERL) -p -e "s/~DRIVER~/$(BASEEXT)/g" $(DBI_DRIVER_XST) > $(BASEEXT).xsi - -# --- -'; -} - -package DBDI; # just to reserve it via PAUSE for the future - -1; - -__END__ - -=head1 AUTHORS - -Jonathan Leffler (previously ), -Jochen Wiedmann , -Steffen Goeldner , -and Tim Bunce . - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/Metadata.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/Metadata.pm deleted file mode 100644 index eec95f0..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/Metadata.pm +++ /dev/null @@ -1,492 +0,0 @@ -package DBI::DBD::Metadata; - -# $Id: Metadata.pm 14213 2010-06-30 19:29:18Z Martin $ -# -# Copyright (c) 1997-2003 Jonathan Leffler, Jochen Wiedmann, -# Steffen Goeldner and Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; - -use Exporter (); -use Carp; - -use DBI; -use DBI::Const::GetInfoType qw(%GetInfoType); - -our @ISA = qw(Exporter); -our @EXPORT = qw(write_getinfo_pm write_typeinfo_pm); - -our $VERSION = "2.014214"; - - -=head1 NAME - -DBI::DBD::Metadata - Generate the code and data for some DBI metadata methods - -=head1 SYNOPSIS - -The idea is to extract metadata information from a good quality -ODBC driver and use it to generate code and data to use in your own -DBI driver for the same database. - -To generate code to support the get_info method: - - perl -MDBI::DBD::Metadata -e "write_getinfo_pm('dbi:ODBC:dsn-name','user','pass','Driver')" - - perl -MDBI::DBD::Metadata -e write_getinfo_pm dbi:ODBC:foo_db username password Driver - -To generate code to support the type_info method: - - perl -MDBI::DBD::Metadata -e "write_typeinfo_pm('dbi:ODBC:dsn-name','user','pass','Driver')" - - perl -MDBI::DBD::Metadata -e write_typeinfo_pm dbi:ODBC:dsn-name user pass Driver - -Where C is the connection to use to extract the -data, and C is the name of the driver you want the code -generated for (the driver name gets embedded into the output in -numerous places). - -=head1 Generating a GetInfo package for a driver - -The C in the DBI::DBD::Metadata module generates a -DBD::Driver::GetInfo package on standard output. - -This method generates a DBD::Driver::GetInfo package from the data -source you specified in the parameter list or in the environment -variable DBI_DSN. -DBD::Driver::GetInfo should help a DBD author implement the DBI -get_info() method. -Because you are just creating this package, it is very unlikely that -DBD::Driver already provides a good implementation for get_info(). -Thus you will probably connect via DBD::ODBC. - -Once you are sure that it is producing reasonably sane data, you should -typically redirect the standard output to lib/DBD/Driver/GetInfo.pm, and -then hand edit the result. -Do not forget to update your Makefile.PL and MANIFEST to include this as -an extra PM file that should be installed. - -If you connect via DBD::ODBC, you should use version 0.38 or greater; - -Please take a critical look at the data returned! -ODBC drivers vary dramatically in their quality. - -The generator assumes that most values are static and places these -values directly in the %info hash. -A few examples show the use of CODE references and the implementation -via subroutines. -It is very likely that you will have to write additional subroutines for -values depending on the session state or server version, e.g. -SQL_DBMS_VER. - -A possible implementation of DBD::Driver::db::get_info() may look like: - - sub get_info { - my($dbh, $info_type) = @_; - require DBD::Driver::GetInfo; - my $v = $DBD::Driver::GetInfo::info{int($info_type)}; - $v = $v->($dbh) if ref $v eq 'CODE'; - return $v; - } - -Please replace Driver (or "") with the name of your driver. -Note that this stub function is generated for you by write_getinfo_pm -function, but you must manually transfer the code to Driver.pm. - -=cut - -sub write_getinfo_pm -{ - my ($dsn, $user, $pass, $driver) = @_ ? @_ : @ARGV; - my $dbh = DBI->connect($dsn, $user, $pass, {RaiseError=>1}); - $driver = "" unless defined $driver; - - print <(\$dbh) if ref \$v eq 'CODE'; - return \$v; - } - -# Transfer this to lib/DBD/${driver}/GetInfo.pm - -# The \%info hash was automatically generated by -# DBI::DBD::Metadata::write_getinfo_pm v$DBI::DBD::Metadata::VERSION. - -package DBD::${driver}::GetInfo; - -use strict; -use DBD::${driver}; - -# Beware: not officially documented interfaces... -# use DBI::Const::GetInfoType qw(\%GetInfoType); -# use DBI::Const::GetInfoReturn qw(\%GetInfoReturnTypes \%GetInfoReturnValues); - -my \$sql_driver = '${driver}'; -my \$sql_ver_fmt = '%02d.%02d.%04d'; # ODBC version string: ##.##.##### -my \$sql_driver_ver = sprintf \$sql_ver_fmt, split (/\\./, \$DBD::${driver}::VERSION); -PERL - -my $kw_map = 0; -{ -# Informix CLI (ODBC) v3.81.0000 does not return a list of keywords. - local $\ = "\n"; - local $, = "\n"; - my ($kw) = $dbh->get_info($GetInfoType{SQL_KEYWORDS}); - if ($kw) - { - print "\nmy \@Keywords = qw(\n"; - print sort split /,/, $kw; - print ");\n\n"; - print "sub sql_keywords {\n"; - print q% return join ',', @Keywords;%; - print "\n}\n\n"; - $kw_map = 1; - } -} - - print <<'PERL'; - -sub sql_data_source_name { - my $dbh = shift; - return "dbi:$sql_driver:" . $dbh->{Name}; -} - -sub sql_user_name { - my $dbh = shift; - # CURRENT_USER is a non-standard attribute, probably undef - # Username is a standard DBI attribute - return $dbh->{CURRENT_USER} || $dbh->{Username}; -} - -PERL - - print "\nour \%info = (\n"; - foreach my $key (sort keys %GetInfoType) - { - my $num = $GetInfoType{$key}; - my $val = eval { $dbh->get_info($num); }; - if ($key eq 'SQL_DATA_SOURCE_NAME') { - $val = '\&sql_data_source_name'; - } - elsif ($key eq 'SQL_KEYWORDS') { - $val = ($kw_map) ? '\&sql_keywords' : 'undef'; - } - elsif ($key eq 'SQL_DRIVER_NAME') { - $val = "\$INC{'DBD/$driver.pm'}"; - } - elsif ($key eq 'SQL_DRIVER_VER') { - $val = '$sql_driver_ver'; - } - elsif ($key eq 'SQL_USER_NAME') { - $val = '\&sql_user_name'; - } - elsif (not defined $val) { - $val = 'undef'; - } - elsif ($val eq '') { - $val = "''"; - } - elsif ($val =~ /\D/) { - $val =~ s/\\/\\\\/g; - $val =~ s/'/\\'/g; - $val = "'$val'"; - } - printf "%s %5d => %-30s # %s\n", (($val eq 'undef') ? '#' : ' '), $num, "$val,", $key; - } - print ");\n\n1;\n\n__END__\n"; -} - - - -=head1 Generating a TypeInfo package for a driver - -The C function in the DBI::DBD::Metadata module generates -on standard output the data needed for a driver's type_info_all method. -It also provides default implementations of the type_info_all -method for inclusion in the driver's main implementation file. - -The driver parameter is the name of the driver for which the methods -will be generated; for the sake of examples, this will be "Driver". -Typically, the dsn parameter will be of the form "dbi:ODBC:odbc_dsn", -where the odbc_dsn is a DSN for one of the driver's databases. -The user and pass parameters are the other optional connection -parameters that will be provided to the DBI connect method. - -Once you are sure that it is producing reasonably sane data, you should -typically redirect the standard output to lib/DBD/Driver/TypeInfo.pm, -and then hand edit the result if necessary. -Do not forget to update your Makefile.PL and MANIFEST to include this as -an extra PM file that should be installed. - -Please take a critical look at the data returned! -ODBC drivers vary dramatically in their quality. - -The generator assumes that all the values are static and places these -values directly in the %info hash. - -A possible implementation of DBD::Driver::type_info_all() may look like: - - sub type_info_all { - my ($dbh) = @_; - require DBD::Driver::TypeInfo; - return [ @$DBD::Driver::TypeInfo::type_info_all ]; - } - -Please replace Driver (or "") with the name of your driver. -Note that this stub function is generated for you by the write_typeinfo_pm -function, but you must manually transfer the code to Driver.pm. - -=cut - - -# These two are used by fmt_value... -my %dbi_inv; -my %sql_type_inv; - -#-DEBUGGING-# -#sub print_hash -#{ -# my ($name, %hash) = @_; -# print "Hash: $name\n"; -# foreach my $key (keys %hash) -# { -# print "$key => $hash{$key}\n"; -# } -#} -#-DEBUGGING-# - -sub inverse_hash -{ - my (%hash) = @_; - my (%inv); - foreach my $key (keys %hash) - { - my $val = $hash{$key}; - die "Double mapping for key value $val ($inv{$val}, $key)!" - if (defined $inv{$val}); - $inv{$val} = $key; - } - return %inv; -} - -sub fmt_value -{ - my ($num, $val) = @_; - if (!defined $val) - { - $val = "undef"; - } - elsif ($val !~ m/^[-+]?\d+$/) - { - # All the numbers in type_info_all are integers! - # Anything that isn't an integer is a string. - # Ensure that no double quotes screw things up. - $val =~ s/"/\\"/g if ($val =~ m/"/o); - $val = qq{"$val"}; - } - elsif ($dbi_inv{$num} =~ m/^(SQL_)?DATA_TYPE$/) - { - # All numeric... - $val = $sql_type_inv{$val} - if (defined $sql_type_inv{$val}); - } - return $val; -} - -sub write_typeinfo_pm -{ - my ($dsn, $user, $pass, $driver) = @_ ? @_ : @ARGV; - my $dbh = DBI->connect($dsn, $user, $pass, {AutoCommit=>1, RaiseError=>1}); - $driver = "" unless defined $driver; - - print < 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - FIXED_PREC_SCALE => 10, - AUTO_UNIQUE_VALUE => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - SQL_DATA_TYPE => 15, - SQL_DATETIME_SUB => 16, - NUM_PREC_RADIX => 17, - INTERVAL_PRECISION => 18, - ); - - #-DEBUG-# print_hash("dbi_map", %dbi_map); - - %dbi_inv = inverse_hash(%dbi_map); - - #-DEBUG-# print_hash("dbi_inv", %dbi_inv); - - my $maxlen = 0; - foreach my $key (keys %dbi_map) - { - $maxlen = length($key) if length($key) > $maxlen; - } - - # Print the name/value mapping entry in the type_info_all array; - my $fmt = " \%-${maxlen}s => \%2d,\n"; - my $numkey = 0; - my $maxkey = 0; - print " \$type_info_all = [\n {\n"; - foreach my $i (sort { $a <=> $b } keys %dbi_inv) - { - printf($fmt, $dbi_inv{$i}, $i); - $numkey++; - $maxkey = $i; - } - print " },\n"; - - print STDERR "### WARNING - Non-dense set of keys ($numkey keys, $maxkey max key)\n" - unless $numkey = $maxkey + 1; - - my $h = $dbh->type_info_all; - my @tia = @$h; - my %odbc_map = map { uc $_ => $tia[0]->{$_} } keys %{$tia[0]}; - shift @tia; # Remove the mapping reference. - my $numtyp = $#tia; - - #-DEBUG-# print_hash("odbc_map", %odbc_map); - - # In theory, the key/number mapping sequence for %dbi_map - # should be the same as the one from the ODBC driver. However, to - # prevent the possibility of mismatches, and to deal with older - # missing attributes or unexpected new ones, we chase back through - # the %dbi_inv and %odbc_map hashes, generating @dbi_to_odbc - # to map our new key number to the old one. - # Report if @dbi_to_odbc is not an identity mapping. - my @dbi_to_odbc; - foreach my $num (sort { $a <=> $b } keys %dbi_inv) - { - # Find the name in %dbi_inv that matches this index number. - my $dbi_key = $dbi_inv{$num}; - #-DEBUG-# print "dbi_key = $dbi_key\n"; - #-DEBUG-# print "odbc_key = $odbc_map{$dbi_key}\n"; - # Find the index in %odbc_map that has this key. - $dbi_to_odbc[$num] = (defined $odbc_map{$dbi_key}) ? $odbc_map{$dbi_key} : undef; - } - - # Determine the length of the longest formatted value in each field - my @len; - for (my $i = 0; $i <= $numtyp; $i++) - { - my @odbc_val = @{$tia[$i]}; - for (my $num = 0; $num <= $maxkey; $num++) - { - # Find the value of the entry in the @odbc_val array. - my $val = (defined $dbi_to_odbc[$num]) ? $odbc_val[$dbi_to_odbc[$num]] : undef; - $val = fmt_value($num, $val); - #-DEBUG-# print "val = $val\n"; - $val = "$val,"; - $len[$num] = length($val) if !defined $len[$num] || length($val) > $len[$num]; - } - } - - # Generate format strings to left justify each string in maximum field width. - my @fmt; - for (my $i = 0; $i <= $maxkey; $i++) - { - $fmt[$i] = "%-$len[$i]s"; - #-DEBUG-# print "fmt[$i] = $fmt[$i]\n"; - } - - # Format the data from type_info_all - for (my $i = 0; $i <= $numtyp; $i++) - { - my @odbc_val = @{$tia[$i]}; - print " [ "; - for (my $num = 0; $num <= $maxkey; $num++) - { - # Find the value of the entry in the @odbc_val array. - my $val = (defined $dbi_to_odbc[$num]) ? $odbc_val[$dbi_to_odbc[$num]] : undef; - $val = fmt_value($num, $val); - printf $fmt[$num], "$val,"; - } - print " ],\n"; - } - - print " ];\n\n 1;\n}\n\n__END__\n"; - -} - -1; - -__END__ - -=head1 AUTHORS - -Jonathan Leffler (previously ), -Jochen Wiedmann , -Steffen Goeldner , -and Tim Bunce . - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine.pm deleted file mode 100644 index fb755ab..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine.pm +++ /dev/null @@ -1,2233 +0,0 @@ -# -*- perl -*- -# -# DBI::DBD::SqlEngine - A base class for implementing DBI drivers that -# have not an own SQL engine -# -# This module is currently maintained by -# -# H.Merijn Brand & Jens Rehsack -# -# The original author is Jochen Wiedmann. -# -# Copyright (C) 2009-2013 by H.Merijn Brand & Jens Rehsack -# Copyright (C) 2004 by Jeff Zucker -# Copyright (C) 1998 by Jochen Wiedmann -# -# All rights reserved. -# -# You may distribute this module under the terms of either the GNU -# General Public License or the Artistic License, as specified in -# the Perl README file. - -require 5.008; - -use strict; - -use DBI (); -require DBI::SQL::Nano; - -package DBI::DBD::SqlEngine; - -use strict; - -use Carp; -use vars qw( @ISA $VERSION $drh %methods_installed); - -$VERSION = "0.06"; - -$drh = undef; # holds driver handle(s) once initialized - -DBI->setup_driver("DBI::DBD::SqlEngine"); # only needed once but harmless to repeat - -my %accessors = ( - versions => "get_driver_versions", - new_meta => "new_sql_engine_meta", - get_meta => "get_sql_engine_meta", - set_meta => "set_sql_engine_meta", - clear_meta => "clear_sql_engine_meta", - ); - -sub driver ($;$) -{ - my ( $class, $attr ) = @_; - - # Drivers typically use a singleton object for the $drh - # We use a hash here to have one singleton per subclass. - # (Otherwise DBD::CSV and DBD::DBM, for example, would - # share the same driver object which would cause problems.) - # An alternative would be to not cache the $drh here at all - # and require that subclasses do that. Subclasses should do - # their own caching, so caching here just provides extra safety. - $drh->{$class} and return $drh->{$class}; - - $attr ||= {}; - { - no strict "refs"; - unless ( $attr->{Attribution} ) - { - $class eq "DBI::DBD::SqlEngine" - and $attr->{Attribution} = "$class by Jens Rehsack"; - $attr->{Attribution} ||= ${ $class . "::ATTRIBUTION" } - || "oops the author of $class forgot to define this"; - } - $attr->{Version} ||= ${ $class . "::VERSION" }; - $attr->{Name} or ( $attr->{Name} = $class ) =~ s/^DBD\:\://; - } - - $drh->{$class} = DBI::_new_drh( $class . "::dr", $attr ); - $drh->{$class}->STORE( ShowErrorStatement => 1 ); - - my $prefix = DBI->driver_prefix($class); - if ($prefix) - { - my $dbclass = $class . "::db"; - while ( my ( $accessor, $funcname ) = each %accessors ) - { - my $method = $prefix . $accessor; - $dbclass->can($method) and next; - my $inject = sprintf <<'EOI', $dbclass, $method, $dbclass, $funcname; -sub %s::%s -{ - my $func = %s->can (q{%s}); - goto &$func; - } -EOI - eval $inject; - $dbclass->install_method($method); - } - } - else - { - warn "Using DBI::DBD::SqlEngine with unregistered driver $class.\n" - . "Reading documentation how to prevent is strongly recommended.\n"; - - } - - # XXX inject DBD::XXX::Statement unless exists - - my $stclass = $class . "::st"; - $stclass->install_method("sql_get_colnames") unless ( $methods_installed{__PACKAGE__}++ ); - - return $drh->{$class}; -} # driver - -sub CLONE -{ - undef $drh; -} # CLONE - -# ====== DRIVER ================================================================ - -package DBI::DBD::SqlEngine::dr; - -use strict; -use warnings; - -use vars qw(@ISA $imp_data_size); - -use Carp qw/carp/; - -$imp_data_size = 0; - -sub connect ($$;$$$) -{ - my ( $drh, $dbname, $user, $auth, $attr ) = @_; - - # create a 'blank' dbh - my $dbh = DBI::_new_dbh( - $drh, - { - Name => $dbname, - USER => $user, - CURRENT_USER => $user, - } - ); - - if ($dbh) - { - # must be done first, because setting flags implicitly calls $dbdname::db->STORE - $dbh->func( 0, "init_default_attributes" ); - my $two_phased_init; - defined $dbh->{sql_init_phase} and $two_phased_init = ++$dbh->{sql_init_phase}; - my %second_phase_attrs; - my @func_inits; - - # this must be done to allow DBI.pm reblessing got handle after successful connecting - exists $attr->{RootClass} and $second_phase_attrs{RootClass} = delete $attr->{RootClass}; - - my ( $var, $val ); - while ( length $dbname ) - { - if ( $dbname =~ s/^((?:[^\\;]|\\.)*?);//s ) - { - $var = $1; - } - else - { - $var = $dbname; - $dbname = ""; - } - - if ( $var =~ m/^(.+?)=(.*)/s ) - { - $var = $1; - ( $val = $2 ) =~ s/\\(.)/$1/g; - exists $attr->{$var} - and carp("$var is given in DSN *and* \$attr during DBI->connect()") - if ($^W); - exists $attr->{$var} or $attr->{$var} = $val; - } - elsif ( $var =~ m/^(.+?)=>(.*)/s ) - { - $var = $1; - ( $val = $2 ) =~ s/\\(.)/$1/g; - my $ref = eval $val; - # $dbh->$var($ref); - push( @func_inits, $var, $ref ); - } - } - - # The attributes need to be sorted in a specific way as the - # assignment is through tied hashes and calls STORE on each - # attribute. Some attributes require to be called prior to - # others - # e.g. f_dir *must* be done before xx_tables in DBD::File - # The dbh attribute sql_init_order is a hash with the order - # as key (low is first, 0 .. 100) and the attributes that - # are set to that oreder as anon-list as value: - # { 0 => [qw( AutoCommit PrintError RaiseError Profile ... )], - # 10 => [ list of attr to be dealt with immediately after first ], - # 50 => [ all fields that are unspecified or default sort order ], - # 90 => [ all fields that are needed after other initialisation ], - # } - - my %order = map { - my $order = $_; - map { ( $_ => $order ) } @{ $dbh->{sql_init_order}{$order} }; - } sort { $a <=> $b } keys %{ $dbh->{sql_init_order} || {} }; - my @ordered_attr = - map { $_->[0] } - sort { $a->[1] <=> $b->[1] } - map { [ $_, defined $order{$_} ? $order{$_} : 50 ] } - keys %$attr; - - # initialize given attributes ... lower weighted before higher weighted - foreach my $a (@ordered_attr) - { - exists $attr->{$a} or next; - $two_phased_init and eval { - $dbh->{$a} = $attr->{$a}; - delete $attr->{$a}; - }; - $@ and $second_phase_attrs{$a} = delete $attr->{$a}; - $two_phased_init or $dbh->STORE( $a, delete $attr->{$a} ); - } - - $two_phased_init and $dbh->func( 1, "init_default_attributes" ); - %$attr = %second_phase_attrs; - - for ( my $i = 0; $i < scalar(@func_inits); $i += 2 ) - { - my $func = $func_inits[$i]; - my $arg = $func_inits[ $i + 1 ]; - $dbh->$func($arg); - } - - $dbh->func("init_done"); - - $dbh->STORE( Active => 1 ); - } - - return $dbh; -} # connect - -sub data_sources ($;$) -{ - my ( $drh, $attr ) = @_; - - my $tbl_src; - $attr - and defined $attr->{sql_table_source} - and $attr->{sql_table_source}->isa('DBI::DBD::SqlEngine::TableSource') - and $tbl_src = $attr->{sql_table_source}; - - !defined($tbl_src) - and $drh->{ImplementorClass}->can('default_table_source') - and $tbl_src = $drh->{ImplementorClass}->default_table_source(); - defined($tbl_src) or return; - - $tbl_src->data_sources( $drh, $attr ); -} # data_sources - -sub disconnect_all -{ -} # disconnect_all - -sub DESTROY -{ - undef; -} # DESTROY - -# ====== DATABASE ============================================================== - -package DBI::DBD::SqlEngine::db; - -use strict; -use warnings; - -use vars qw(@ISA $imp_data_size); - -use Carp; - -if ( eval { require Clone; } ) -{ - Clone->import("clone"); -} -else -{ - require Storable; # in CORE since 5.7.3 - *clone = \&Storable::dclone; -} - -$imp_data_size = 0; - -sub ping -{ - ( $_[0]->FETCH("Active") ) ? 1 : 0; -} # ping - -sub data_sources -{ - my ( $dbh, $attr, @other ) = @_; - my $drh = $dbh->{Driver}; # XXX proxy issues? - ref($attr) eq 'HASH' or $attr = {}; - defined( $attr->{sql_table_source} ) or $attr->{sql_table_source} = $dbh->{sql_table_source}; - return $drh->data_sources( $attr, @other ); -} - -sub prepare ($$;@) -{ - my ( $dbh, $statement, @attribs ) = @_; - - # create a 'blank' sth - my $sth = DBI::_new_sth( $dbh, { Statement => $statement } ); - - if ($sth) - { - my $class = $sth->FETCH("ImplementorClass"); - $class =~ s/::st$/::Statement/; - my $stmt; - - # if using SQL::Statement version > 1 - # cache the parser object if the DBD supports parser caching - # SQL::Nano and older SQL::Statements don't support this - - if ( $class->isa("SQL::Statement") ) - { - my $parser = $dbh->{sql_parser_object}; - $parser ||= eval { $dbh->func("sql_parser_object") }; - if ($@) - { - $stmt = eval { $class->new($statement) }; - } - else - { - $stmt = eval { $class->new( $statement, $parser ) }; - } - } - else - { - $stmt = eval { $class->new($statement) }; - } - if ( $@ || $stmt->{errstr} ) - { - $dbh->set_err( $DBI::stderr, $@ || $stmt->{errstr} ); - undef $sth; - } - else - { - $sth->STORE( "sql_stmt", $stmt ); - $sth->STORE( "sql_params", [] ); - $sth->STORE( "NUM_OF_PARAMS", scalar( $stmt->params() ) ); - my @colnames = $sth->sql_get_colnames(); - $sth->STORE( "NUM_OF_FIELDS", scalar @colnames ); - } - } - return $sth; -} # prepare - -sub set_versions -{ - my $dbh = $_[0]; - $dbh->{sql_engine_version} = $DBI::DBD::SqlEngine::VERSION; - for (qw( nano_version statement_version )) - { - defined $DBI::SQL::Nano::versions->{$_} or next; - $dbh->{"sql_$_"} = $DBI::SQL::Nano::versions->{$_}; - } - $dbh->{sql_handler} = - $dbh->{sql_statement_version} - ? "SQL::Statement" - : "DBI::SQL::Nano"; - - return $dbh; -} # set_versions - -sub init_valid_attributes -{ - my $dbh = $_[0]; - - $dbh->{sql_valid_attrs} = { - sql_engine_version => 1, # DBI::DBD::SqlEngine version - sql_handler => 1, # Nano or S:S - sql_nano_version => 1, # Nano version - sql_statement_version => 1, # S:S version - sql_flags => 1, # flags for SQL::Parser - sql_dialect => 1, # dialect for SQL::Parser - sql_quoted_identifier_case => 1, # case for quoted identifiers - sql_identifier_case => 1, # case for non-quoted identifiers - sql_parser_object => 1, # SQL::Parser instance - sql_sponge_driver => 1, # Sponge driver for table_info () - sql_valid_attrs => 1, # SQL valid attributes - sql_readonly_attrs => 1, # SQL readonly attributes - sql_init_phase => 1, # Only during initialization - sql_meta => 1, # meta data for tables - sql_meta_map => 1, # mapping table for identifier case - sql_data_source => 1, # reasonable datasource class - }; - $dbh->{sql_readonly_attrs} = { - sql_engine_version => 1, # DBI::DBD::SqlEngine version - sql_handler => 1, # Nano or S:S - sql_nano_version => 1, # Nano version - sql_statement_version => 1, # S:S version - sql_quoted_identifier_case => 1, # case for quoted identifiers - sql_parser_object => 1, # SQL::Parser instance - sql_sponge_driver => 1, # Sponge driver for table_info () - sql_valid_attrs => 1, # SQL valid attributes - sql_readonly_attrs => 1, # SQL readonly attributes - }; - - return $dbh; -} # init_valid_attributes - -sub init_default_attributes -{ - my ( $dbh, $phase ) = @_; - my $given_phase = $phase; - - unless ( defined($phase) ) - { - # we have an "old" driver here - $phase = defined $dbh->{sql_init_phase}; - $phase and $phase = $dbh->{sql_init_phase}; - } - - if ( 0 == $phase ) - { - # must be done first, because setting flags implicitly calls $dbdname::db->STORE - $dbh->func("init_valid_attributes"); - - $dbh->func("set_versions"); - - $dbh->{sql_identifier_case} = 2; # SQL_IC_LOWER - $dbh->{sql_quoted_identifier_case} = 3; # SQL_IC_SENSITIVE - - $dbh->{sql_dialect} = "CSV"; - - $dbh->{sql_init_phase} = $given_phase; - - # complete derived attributes, if required - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix($drv_class); - my $valid_attrs = $drv_prefix . "valid_attrs"; - my $ro_attrs = $drv_prefix . "readonly_attrs"; - - # check whether we're running in a Gofer server or not (see - # validate_FETCH_attr for details) - $dbh->{sql_engine_in_gofer} = - ( defined $INC{"DBD/Gofer.pm"} && ( caller(5) )[0] eq "DBI::Gofer::Execute" ); - $dbh->{sql_meta} = {}; - $dbh->{sql_meta_map} = {}; # choose new name because it contains other keys - - # init_default_attributes calls inherited routine before derived DBD's - # init their default attributes, so we don't override something here - # - # defining an order of attribute initialization from connect time - # specified ones with a magic baarier (see next statement) - my $drv_pfx_meta = $drv_prefix . "meta"; - $dbh->{sql_init_order} = { - 0 => [qw( Profile RaiseError PrintError AutoCommit )], - 90 => [ "sql_meta", $dbh->{$drv_pfx_meta} ? $dbh->{$drv_pfx_meta} : () ], - }; - # ensuring Profile, RaiseError, PrintError, AutoCommit are initialized - # first when initializing attributes from connect time specified - # attributes - # further, initializations to predefined tables are happens after any - # unspecified attribute initialization (that default to order 50) - - my @comp_attrs = qw(valid_attrs version readonly_attrs); - - if ( exists $dbh->{$drv_pfx_meta} and !$dbh->{sql_engine_in_gofer} ) - { - my $attr = $dbh->{$drv_pfx_meta}; - defined $attr - and defined $dbh->{$valid_attrs} - and !defined $dbh->{$valid_attrs}{$attr} - and $dbh->{$valid_attrs}{$attr} = 1; - - my %h; - tie %h, "DBI::DBD::SqlEngine::TieTables", $dbh; - $dbh->{$attr} = \%h; - - push @comp_attrs, "meta"; - } - - foreach my $comp_attr (@comp_attrs) - { - my $attr = $drv_prefix . $comp_attr; - defined $dbh->{$valid_attrs} - and !defined $dbh->{$valid_attrs}{$attr} - and $dbh->{$valid_attrs}{$attr} = 1; - defined $dbh->{$ro_attrs} - and !defined $dbh->{$ro_attrs}{$attr} - and $dbh->{$ro_attrs}{$attr} = 1; - } - } - - return $dbh; -} # init_default_attributes - -sub init_done -{ - defined $_[0]->{sql_init_phase} and delete $_[0]->{sql_init_phase}; - delete $_[0]->{sql_valid_attrs}->{sql_init_phase}; - return; -} - -sub sql_parser_object -{ - my $dbh = $_[0]; - my $dialect = $dbh->{sql_dialect} || "CSV"; - my $parser = { - RaiseError => $dbh->FETCH("RaiseError"), - PrintError => $dbh->FETCH("PrintError"), - }; - my $sql_flags = $dbh->FETCH("sql_flags") || {}; - %$parser = ( %$parser, %$sql_flags ); - $parser = SQL::Parser->new( $dialect, $parser ); - $dbh->{sql_parser_object} = $parser; - return $parser; -} # sql_parser_object - -sub sql_sponge_driver -{ - my $dbh = $_[0]; - my $dbh2 = $dbh->{sql_sponge_driver}; - unless ($dbh2) - { - $dbh2 = $dbh->{sql_sponge_driver} = DBI->connect("DBI:Sponge:"); - unless ($dbh2) - { - $dbh->set_err( $DBI::stderr, $DBI::errstr ); - return; - } - } -} - -sub disconnect ($) -{ - %{ $_[0]->{sql_meta} } = (); - %{ $_[0]->{sql_meta_map} } = (); - $_[0]->STORE( Active => 0 ); - return 1; -} # disconnect - -sub validate_FETCH_attr -{ - my ( $dbh, $attrib ) = @_; - - # If running in a Gofer server, access to our tied compatibility hash - # would force Gofer to serialize the tieing object including it's - # private $dbh reference used to do the driver function calls. - # This will result in nasty exceptions. So return a copy of the - # sql_meta structure instead, which is the source of for the compatibility - # tie-hash. It's not as good as liked, but the best we can do in this - # situation. - if ( $dbh->{sql_engine_in_gofer} ) - { - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix($drv_class); - exists $dbh->{ $drv_prefix . "meta" } && $attrib eq $dbh->{ $drv_prefix . "meta" } - and $attrib = "sql_meta"; - } - - return $attrib; -} - -sub FETCH ($$) -{ - my ( $dbh, $attrib ) = @_; - $attrib eq "AutoCommit" - and return 1; - - # Driver private attributes are lower cased - if ( $attrib eq ( lc $attrib ) ) - { - # first let the implementation deliver an alias for the attribute to fetch - # after it validates the legitimation of the fetch request - $attrib = $dbh->func( $attrib, "validate_FETCH_attr" ) or return; - - my $attr_prefix; - $attrib =~ m/^([a-z]+_)/ and $attr_prefix = $1; - unless ($attr_prefix) - { - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - $attr_prefix = DBI->driver_prefix($drv_class); - $attrib = $attr_prefix . $attrib; - } - my $valid_attrs = $attr_prefix . "valid_attrs"; - my $ro_attrs = $attr_prefix . "readonly_attrs"; - - exists $dbh->{$valid_attrs} - and ( $dbh->{$valid_attrs}{$attrib} - or return $dbh->set_err( $DBI::stderr, "Invalid attribute '$attrib'" ) ); - exists $dbh->{$ro_attrs} - and $dbh->{$ro_attrs}{$attrib} - and defined $dbh->{$attrib} - and refaddr( $dbh->{$attrib} ) - and return clone( $dbh->{$attrib} ); - - return $dbh->{$attrib}; - } - # else pass up to DBI to handle - return $dbh->SUPER::FETCH($attrib); -} # FETCH - -sub validate_STORE_attr -{ - my ( $dbh, $attrib, $value ) = @_; - - if ( $attrib eq "sql_identifier_case" || $attrib eq "sql_quoted_identifier_case" - and $value < 1 || $value > 4 ) - { - croak "attribute '$attrib' must have a value from 1 .. 4 (SQL_IC_UPPER .. SQL_IC_MIXED)"; - # XXX correctly a remap of all entries in sql_meta/sql_meta_map is required here - } - - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix($drv_class); - - exists $dbh->{ $drv_prefix . "meta" } - and $attrib eq $dbh->{ $drv_prefix . "meta" } - and $attrib = "sql_meta"; - - return ( $attrib, $value ); -} - -# the ::db::STORE method is what gets called when you set -# a lower-cased database handle attribute such as $dbh->{somekey}=$someval; -# -# STORE should check to make sure that "somekey" is a valid attribute name -# but only if it is really one of our attributes (starts with dbm_ or foo_) -# You can also check for valid values for the attributes if needed -# and/or perform other operations -# -sub STORE ($$$) -{ - my ( $dbh, $attrib, $value ) = @_; - - if ( $attrib eq "AutoCommit" ) - { - $value and return 1; # is already set - croak "Can't disable AutoCommit"; - } - - if ( $attrib eq lc $attrib ) - { - # Driver private attributes are lower cased - - ( $attrib, $value ) = $dbh->func( $attrib, $value, "validate_STORE_attr" ); - $attrib or return; - - my $attr_prefix; - $attrib =~ m/^([a-z]+_)/ and $attr_prefix = $1; - unless ($attr_prefix) - { - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - $attr_prefix = DBI->driver_prefix($drv_class); - $attrib = $attr_prefix . $attrib; - } - my $valid_attrs = $attr_prefix . "valid_attrs"; - my $ro_attrs = $attr_prefix . "readonly_attrs"; - - exists $dbh->{$valid_attrs} - and ( $dbh->{$valid_attrs}{$attrib} - or return $dbh->set_err( $DBI::stderr, "Invalid attribute '$attrib'" ) ); - exists $dbh->{$ro_attrs} - and $dbh->{$ro_attrs}{$attrib} - and defined $dbh->{$attrib} - and return $dbh->set_err( $DBI::stderr, - "attribute '$attrib' is readonly and must not be modified" ); - - if ( $attrib eq "sql_meta" ) - { - while ( my ( $k, $v ) = each %$value ) - { - $dbh->{$attrib}{$k} = $v; - } - } - else - { - $dbh->{$attrib} = $value; - } - - return 1; - } - - return $dbh->SUPER::STORE( $attrib, $value ); -} # STORE - -sub get_driver_versions -{ - my ( $dbh, $table ) = @_; - my %vsn = ( - OS => "$^O ($Config::Config{osvers})", - Perl => "$] ($Config::Config{archname})", - DBI => $DBI::VERSION, - ); - my %vmp; - - my $sql_engine_verinfo = - join " ", - $dbh->{sql_engine_version}, "using", $dbh->{sql_handler}, - $dbh->{sql_handler} eq "SQL::Statement" - ? $dbh->{sql_statement_version} - : $dbh->{sql_nano_version}; - - my $indent = 0; - my @deriveds = ( $dbh->{ImplementorClass} ); - while (@deriveds) - { - my $derived = shift @deriveds; - $derived eq "DBI::DBD::SqlEngine::db" and last; - $derived->isa("DBI::DBD::SqlEngine::db") or next; - #no strict 'refs'; - eval "push \@deriveds, \@${derived}::ISA"; - #use strict; - ( my $drv_class = $derived ) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix($drv_class); - my $ddgv = $dbh->{ImplementorClass}->can("get_${drv_prefix}versions"); - my $drv_version = $ddgv ? &$ddgv( $dbh, $table ) : $dbh->{ $drv_prefix . "version" }; - $drv_version ||= - eval { $derived->VERSION() }; # XXX access $drv_class::VERSION via symbol table - $vsn{$drv_class} = $drv_version; - $indent and $vmp{$drv_class} = " " x $indent . $drv_class; - $indent += 2; - } - - $vsn{"DBI::DBD::SqlEngine"} = $sql_engine_verinfo; - $indent and $vmp{"DBI::DBD::SqlEngine"} = " " x $indent . "DBI::DBD::SqlEngine"; - - $DBI::PurePerl and $vsn{"DBI::PurePerl"} = $DBI::PurePerl::VERSION; - - $indent += 20; - my @versions = map { sprintf "%-${indent}s %s", $vmp{$_} || $_, $vsn{$_} } - sort { - $a->isa($b) and return -1; - $b->isa($a) and return 1; - $a->isa("DBI::DBD::SqlEngine") and return -1; - $b->isa("DBI::DBD::SqlEngine") and return 1; - return $a cmp $b; - } keys %vsn; - - return wantarray ? @versions : join "\n", @versions; -} # get_versions - -sub get_single_table_meta -{ - my ( $dbh, $table, $attr ) = @_; - my $meta; - - $table eq "." - and return $dbh->FETCH($attr); - - ( my $class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); - $meta or croak "No such table '$table'"; - - # prevent creation of undef attributes - return $class->get_table_meta_attr( $meta, $attr ); -} # get_single_table_meta - -sub get_sql_engine_meta -{ - my ( $dbh, $table, $attr ) = @_; - - my $gstm = $dbh->{ImplementorClass}->can("get_single_table_meta"); - - $table eq "*" - and $table = [ ".", keys %{ $dbh->{sql_meta} } ]; - $table eq "+" - and $table = [ grep { m/^[_A-Za-z0-9]+$/ } keys %{ $dbh->{sql_meta} } ]; - ref $table eq "Regexp" - and $table = [ grep { $_ =~ $table } keys %{ $dbh->{sql_meta} } ]; - - ref $table || ref $attr - or return $gstm->( $dbh, $table, $attr ); - - ref $table or $table = [$table]; - ref $attr or $attr = [$attr]; - "ARRAY" eq ref $table - or return - $dbh->set_err( $DBI::stderr, - "Invalid argument for \$table - SCALAR, Regexp or ARRAY expected but got " . ref $table ); - "ARRAY" eq ref $attr - or return $dbh->set_err( - "Invalid argument for \$attr - SCALAR or ARRAY expected but got " . ref $attr ); - - my %results; - foreach my $tname ( @{$table} ) - { - my %tattrs; - foreach my $aname ( @{$attr} ) - { - $tattrs{$aname} = $gstm->( $dbh, $tname, $aname ); - } - $results{$tname} = \%tattrs; - } - - return \%results; -} # get_sql_engine_meta - -sub new_sql_engine_meta -{ - my ( $dbh, $table, $values ) = @_; - my $respect_case = 0; - - "HASH" eq ref $values - or croak "Invalid argument for \$values - SCALAR or HASH expected but got " . ref $values; - - $table =~ s/^\"// and $respect_case = 1; # handle quoted identifiers - $table =~ s/\"$//; - - unless ($respect_case) - { - defined $dbh->{sql_meta_map}{$table} and $table = $dbh->{sql_meta_map}{$table}; - } - - $dbh->{sql_meta}{$table} = { %{$values} }; - my $class; - defined $values->{sql_table_class} and $class = $values->{sql_table_class}; - defined $class or ( $class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - # XXX we should never hit DBD::File::Table::get_table_meta here ... - my ( undef, $meta ) = $class->get_table_meta( $dbh, $table, $respect_case ); - 1; -} # new_sql_engine_meta - -sub set_single_table_meta -{ - my ( $dbh, $table, $attr, $value ) = @_; - my $meta; - - $table eq "." - and return $dbh->STORE( $attr, $value ); - - ( my $class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); # 1 means: respect case - $meta or croak "No such table '$table'"; - $class->set_table_meta_attr( $meta, $attr, $value ); - - return $dbh; -} # set_single_table_meta - -sub set_sql_engine_meta -{ - my ( $dbh, $table, $attr, $value ) = @_; - - my $sstm = $dbh->{ImplementorClass}->can("set_single_table_meta"); - - $table eq "*" - and $table = [ ".", keys %{ $dbh->{sql_meta} } ]; - $table eq "+" - and $table = [ grep { m/^[_A-Za-z0-9]+$/ } keys %{ $dbh->{sql_meta} } ]; - ref($table) eq "Regexp" - and $table = [ grep { $_ =~ $table } keys %{ $dbh->{sql_meta} } ]; - - ref $table || ref $attr - or return $sstm->( $dbh, $table, $attr, $value ); - - ref $table or $table = [$table]; - ref $attr or $attr = { $attr => $value }; - "ARRAY" eq ref $table - or croak "Invalid argument for \$table - SCALAR, Regexp or ARRAY expected but got " - . ref $table; - "HASH" eq ref $attr - or croak "Invalid argument for \$attr - SCALAR or HASH expected but got " . ref $attr; - - foreach my $tname ( @{$table} ) - { - while ( my ( $aname, $aval ) = each %$attr ) - { - $sstm->( $dbh, $tname, $aname, $aval ); - } - } - - return $dbh; -} # set_file_meta - -sub clear_sql_engine_meta -{ - my ( $dbh, $table ) = @_; - - ( my $class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - my ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); - $meta and %{$meta} = (); - - return; -} # clear_file_meta - -sub DESTROY ($) -{ - my $dbh = shift; - $dbh->SUPER::FETCH("Active") and $dbh->disconnect; - undef $dbh->{sql_parser_object}; -} # DESTROY - -sub type_info_all ($) -{ - [ - { - TYPE_NAME => 0, - DATA_TYPE => 1, - PRECISION => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - MONEY => 10, - AUTO_INCREMENT => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - }, - [ - "VARCHAR", DBI::SQL_VARCHAR(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, 999999, - ], - [ "CHAR", DBI::SQL_CHAR(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, 999999, ], - [ "INTEGER", DBI::SQL_INTEGER(), undef, "", "", undef, 0, 0, 1, 0, 0, 0, undef, 0, 0, ], - [ "REAL", DBI::SQL_REAL(), undef, "", "", undef, 0, 0, 1, 0, 0, 0, undef, 0, 0, ], - [ - "BLOB", DBI::SQL_LONGVARBINARY(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, - 999999, - ], - [ - "BLOB", DBI::SQL_LONGVARBINARY(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, - 999999, - ], - [ - "TEXT", DBI::SQL_LONGVARCHAR(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, - 999999, - ], - ]; -} # type_info_all - -sub get_avail_tables -{ - my $dbh = $_[0]; - my @tables = (); - - if ( $dbh->{sql_handler} eq "SQL::Statement" and $dbh->{sql_ram_tables} ) - { - # XXX map +[ undef, undef, $_, "TABLE", "TEMP" ], keys %{...} - foreach my $table ( keys %{ $dbh->{sql_ram_tables} } ) - { - push @tables, [ undef, undef, $table, "TABLE", "TEMP" ]; - } - } - - my $tbl_src; - defined $dbh->{sql_table_source} - and $dbh->{sql_table_source}->isa('DBI::DBD::SqlEngine::TableSource') - and $tbl_src = $dbh->{sql_table_source}; - - !defined($tbl_src) - and $dbh->{Driver}->{ImplementorClass}->can('default_table_source') - and $tbl_src = $dbh->{Driver}->{ImplementorClass}->default_table_source(); - defined($tbl_src) and push( @tables, $tbl_src->avail_tables($dbh) ); - - return @tables; -} # get_avail_tables - -{ - my $names = [qw( TABLE_QUALIFIER TABLE_OWNER TABLE_NAME TABLE_TYPE REMARKS )]; - - sub table_info ($) - { - my $dbh = shift; - - my @tables = $dbh->func("get_avail_tables"); - - # Temporary kludge: DBD::Sponge dies if @tables is empty. :-( - # this no longer seems to be true @tables or return; - - my $dbh2 = $dbh->func("sql_sponge_driver"); - my $sth = $dbh2->prepare( - "TABLE_INFO", - { - rows => \@tables, - NAME => $names, - } - ); - $sth or return $dbh->set_err( $DBI::stderr, $dbh2->errstr ); - $sth->execute or return; - return $sth; - } # table_info -} - -sub list_tables ($) -{ - my $dbh = shift; - my @table_list; - - my @tables = $dbh->func("get_avail_tables") or return; - foreach my $ref (@tables) - { - # rt69260 and rt67223 - the same issue in 2 different queues - push @table_list, $ref->[2]; - } - - return @table_list; -} # list_tables - -sub quote ($$;$) -{ - my ( $self, $str, $type ) = @_; - defined $str or return "NULL"; - defined $type && ( $type == DBI::SQL_NUMERIC() - || $type == DBI::SQL_DECIMAL() - || $type == DBI::SQL_INTEGER() - || $type == DBI::SQL_SMALLINT() - || $type == DBI::SQL_FLOAT() - || $type == DBI::SQL_REAL() - || $type == DBI::SQL_DOUBLE() - || $type == DBI::SQL_TINYINT() ) - and return $str; - - $str =~ s/\\/\\\\/sg; - $str =~ s/\0/\\0/sg; - $str =~ s/\'/\\\'/sg; - $str =~ s/\n/\\n/sg; - $str =~ s/\r/\\r/sg; - return "'$str'"; -} # quote - -sub commit ($) -{ - my $dbh = shift; - $dbh->FETCH("Warn") - and carp "Commit ineffective while AutoCommit is on", -1; - return 1; -} # commit - -sub rollback ($) -{ - my $dbh = shift; - $dbh->FETCH("Warn") - and carp "Rollback ineffective while AutoCommit is on", -1; - return 0; -} # rollback - -# ====== Tie-Meta ============================================================== - -package DBI::DBD::SqlEngine::TieMeta; - -use Carp qw(croak); -require Tie::Hash; -@DBI::DBD::SqlEngine::TieMeta::ISA = qw(Tie::Hash); - -sub TIEHASH -{ - my ( $class, $tblClass, $tblMeta ) = @_; - - my $self = bless( - { - tblClass => $tblClass, - tblMeta => $tblMeta, - }, - $class - ); - return $self; -} # new - -sub STORE -{ - my ( $self, $meta_attr, $meta_val ) = @_; - - $self->{tblClass}->set_table_meta_attr( $self->{tblMeta}, $meta_attr, $meta_val ); - - return; -} # STORE - -sub FETCH -{ - my ( $self, $meta_attr ) = @_; - - return $self->{tblClass}->get_table_meta_attr( $self->{tblMeta}, $meta_attr ); -} # FETCH - -sub FIRSTKEY -{ - my $a = scalar keys %{ $_[0]->{tblMeta} }; - each %{ $_[0]->{tblMeta} }; -} # FIRSTKEY - -sub NEXTKEY -{ - each %{ $_[0]->{tblMeta} }; -} # NEXTKEY - -sub EXISTS -{ - exists $_[0]->{tblMeta}{ $_[1] }; -} # EXISTS - -sub DELETE -{ - croak "Can't delete single attributes from table meta structure"; -} # DELETE - -sub CLEAR -{ - %{ $_[0]->{tblMeta} } = (); -} # CLEAR - -sub SCALAR -{ - scalar %{ $_[0]->{tblMeta} }; -} # SCALAR - -# ====== Tie-Tables ============================================================ - -package DBI::DBD::SqlEngine::TieTables; - -use Carp qw(croak); -require Tie::Hash; -@DBI::DBD::SqlEngine::TieTables::ISA = qw(Tie::Hash); - -sub TIEHASH -{ - my ( $class, $dbh ) = @_; - - ( my $tbl_class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - my $self = bless( - { - dbh => $dbh, - tblClass => $tbl_class, - }, - $class - ); - return $self; -} # new - -sub STORE -{ - my ( $self, $table, $tbl_meta ) = @_; - - "HASH" eq ref $tbl_meta - or croak "Invalid data for storing as table meta data (must be hash)"; - - ( undef, my $meta ) = $self->{tblClass}->get_table_meta( $self->{dbh}, $table, 1 ); - $meta or croak "Invalid table name '$table'"; - - while ( my ( $meta_attr, $meta_val ) = each %$tbl_meta ) - { - $self->{tblClass}->set_table_meta_attr( $meta, $meta_attr, $meta_val ); - } - - return; -} # STORE - -sub FETCH -{ - my ( $self, $table ) = @_; - - ( undef, my $meta ) = $self->{tblClass}->get_table_meta( $self->{dbh}, $table, 1 ); - $meta or croak "Invalid table name '$table'"; - - my %h; - tie %h, "DBI::DBD::SqlEngine::TieMeta", $self->{tblClass}, $meta; - - return \%h; -} # FETCH - -sub FIRSTKEY -{ - my $a = scalar keys %{ $_[0]->{dbh}->{sql_meta} }; - each %{ $_[0]->{dbh}->{sql_meta} }; -} # FIRSTKEY - -sub NEXTKEY -{ - each %{ $_[0]->{dbh}->{sql_meta} }; -} # NEXTKEY - -sub EXISTS -{ - exists $_[0]->{dbh}->{sql_meta}->{ $_[1] } - or exists $_[0]->{dbh}->{sql_meta_map}->{ $_[1] }; -} # EXISTS - -sub DELETE -{ - my ( $self, $table ) = @_; - - ( undef, my $meta ) = $self->{tblClass}->get_table_meta( $self->{dbh}, $table, 1 ); - $meta or croak "Invalid table name '$table'"; - - delete $_[0]->{dbh}->{sql_meta}->{ $meta->{table_name} }; -} # DELETE - -sub CLEAR -{ - %{ $_[0]->{dbh}->{sql_meta} } = (); - %{ $_[0]->{dbh}->{sql_meta_map} } = (); -} # CLEAR - -sub SCALAR -{ - scalar %{ $_[0]->{dbh}->{sql_meta} }; -} # SCALAR - -# ====== STATEMENT ============================================================= - -package DBI::DBD::SqlEngine::st; - -use strict; -use warnings; - -use vars qw(@ISA $imp_data_size); - -$imp_data_size = 0; - -sub bind_param ($$$;$) -{ - my ( $sth, $pNum, $val, $attr ) = @_; - if ( $attr && defined $val ) - { - my $type = ref $attr eq "HASH" ? $attr->{TYPE} : $attr; - if ( $type == DBI::SQL_BIGINT() - || $type == DBI::SQL_INTEGER() - || $type == DBI::SQL_SMALLINT() - || $type == DBI::SQL_TINYINT() ) - { - $val += 0; - } - elsif ( $type == DBI::SQL_DECIMAL() - || $type == DBI::SQL_DOUBLE() - || $type == DBI::SQL_FLOAT() - || $type == DBI::SQL_NUMERIC() - || $type == DBI::SQL_REAL() ) - { - $val += 0.; - } - else - { - $val = "$val"; - } - } - $sth->{sql_params}[ $pNum - 1 ] = $val; - return 1; -} # bind_param - -sub execute -{ - my $sth = shift; - my $params = @_ ? ( $sth->{sql_params} = [@_] ) : $sth->{sql_params}; - - $sth->finish; - my $stmt = $sth->{sql_stmt}; - - # must not proved when already executed - SQL::Statement modifies - # received params - unless ( $sth->{sql_params_checked}++ ) - { - # SQL::Statement and DBI::SQL::Nano will return the list of required params - # when called in list context. Do not look into the several items, they're - # implementation specific and may change without warning - unless ( ( my $req_prm = $stmt->params() ) == ( my $nparm = @$params ) ) - { - my $msg = "You passed $nparm parameters where $req_prm required"; - return $sth->set_err( $DBI::stderr, $msg ); - } - } - - my @err; - my $result; - eval { - local $SIG{__WARN__} = sub { push @err, @_ }; - $result = $stmt->execute( $sth, $params ); - }; - unless ( defined $result ) - { - $sth->set_err( $DBI::stderr, $@ || $stmt->{errstr} || $err[0] ); - return; - } - - if ( $stmt->{NUM_OF_FIELDS} ) - { # is a SELECT statement - $sth->STORE( Active => 1 ); - $sth->FETCH("NUM_OF_FIELDS") - or $sth->STORE( "NUM_OF_FIELDS", $stmt->{NUM_OF_FIELDS} ); - } - return $result; -} # execute - -sub finish -{ - my $sth = $_[0]; - $sth->SUPER::STORE( Active => 0 ); - delete $sth->{sql_stmt}{data}; - return 1; -} # finish - -sub fetch ($) -{ - my $sth = $_[0]; - my $data = $sth->{sql_stmt}{data}; - if ( !$data || ref $data ne "ARRAY" ) - { - $sth->set_err( - $DBI::stderr, - "Attempt to fetch row without a preceding execute () call or from a non-SELECT statement" - ); - return; - } - my $dav = shift @$data; - unless ($dav) - { - $sth->finish; - return; - } - if ( $sth->FETCH("ChopBlanks") ) # XXX: (TODO) Only chop on CHAR fields, - { # not on VARCHAR or NUMERIC (see DBI docs) - $_ && $_ =~ s/ +$// for @$dav; - } - return $sth->_set_fbav($dav); -} # fetch - -no warnings 'once'; -*fetchrow_arrayref = \&fetch; - -use warnings; - -sub sql_get_colnames -{ - my $sth = $_[0]; - # Being a bit dirty here, as neither SQL::Statement::Structure nor - # DBI::SQL::Nano::Statement_ does not offer an interface to the - # required data - my @colnames; - if ( $sth->{sql_stmt}->{NAME} and "ARRAY" eq ref( $sth->{sql_stmt}->{NAME} ) ) - { - @colnames = @{ $sth->{sql_stmt}->{NAME} }; - } - elsif ( $sth->{sql_stmt}->isa('SQL::Statement') ) - { - my $stmt = $sth->{sql_stmt} || {}; - my @coldefs = @{ $stmt->{column_defs} || [] }; - @colnames = map { $_->{name} || $_->{value} } @coldefs; - } - @colnames = $sth->{sql_stmt}->column_names() unless (@colnames); - - @colnames = () if ( grep { m/\*/ } @colnames ); - - return @colnames; -} - -sub FETCH ($$) -{ - my ( $sth, $attrib ) = @_; - - $attrib eq "NAME" and return [ $sth->sql_get_colnames() ]; - - $attrib eq "TYPE" and return [ ( DBI::SQL_VARCHAR() ) x scalar $sth->sql_get_colnames() ]; - $attrib eq "TYPE_NAME" and return [ ("VARCHAR") x scalar $sth->sql_get_colnames() ]; - $attrib eq "PRECISION" and return [ (0) x scalar $sth->sql_get_colnames() ]; - $attrib eq "NULLABLE" and return [ (1) x scalar $sth->sql_get_colnames() ]; - - if ( $attrib eq lc $attrib ) - { - # Private driver attributes are lower cased - return $sth->{$attrib}; - } - - # else pass up to DBI to handle - return $sth->SUPER::FETCH($attrib); -} # FETCH - -sub STORE ($$$) -{ - my ( $sth, $attrib, $value ) = @_; - if ( $attrib eq lc $attrib ) # Private driver attributes are lower cased - { - $sth->{$attrib} = $value; - return 1; - } - return $sth->SUPER::STORE( $attrib, $value ); -} # STORE - -sub DESTROY ($) -{ - my $sth = shift; - $sth->SUPER::FETCH("Active") and $sth->finish; - undef $sth->{sql_stmt}; - undef $sth->{sql_params}; -} # DESTROY - -sub rows ($) -{ - return $_[0]->{sql_stmt}{NUM_OF_ROWS}; -} # rows - -# ====== TableSource =========================================================== - -package DBI::DBD::SqlEngine::TableSource; - -use strict; -use warnings; - -use Carp; - -sub data_sources ($;$) -{ - my ( $class, $drh, $attrs ) = @_; - croak( ( ref( $_[0] ) ? ref( $_[0] ) : $_[0] ) . " must implement data_sources" ); -} - -sub avail_tables -{ - my ( $self, $dbh ) = @_; - croak( ( ref( $_[0] ) ? ref( $_[0] ) : $_[0] ) . " must implement avail_tables" ); -} - -# ====== DataSource ============================================================ - -package DBI::DBD::SqlEngine::DataSource; - -use strict; -use warnings; - -use Carp; - -sub complete_table_name ($$;$) -{ - my ( $self, $meta, $table, $respect_case ) = @_; - croak( ( ref( $_[0] ) ? ref( $_[0] ) : $_[0] ) . " must implement complete_table_name" ); -} - -sub open_data ($) -{ - my ( $self, $meta, $attrs, $flags ) = @_; - croak( ( ref( $_[0] ) ? ref( $_[0] ) : $_[0] ) . " must implement open_data" ); -} - -# ====== SQL::STATEMENT ======================================================== - -package DBI::DBD::SqlEngine::Statement; - -use strict; -use warnings; - -use Carp; - -@DBI::DBD::SqlEngine::Statement::ISA = qw(DBI::SQL::Nano::Statement); - -sub open_table ($$$$$) -{ - my ( $self, $data, $table, $createMode, $lockMode ) = @_; - - my $class = ref $self; - $class =~ s/::Statement/::Table/; - - my $flags = { - createMode => $createMode, - lockMode => $lockMode, - }; - $self->{command} eq "DROP" and $flags->{dropMode} = 1; - - my ( $tblnm, $table_meta ) = $class->get_table_meta( $data->{Database}, $table, 1 ) - or croak "Cannot find appropriate meta for table '$table'"; - - defined $table_meta->{sql_table_class} and $class = $table_meta->{sql_table_class}; - - # because column name mapping is initialized in constructor ... - # and therefore specific opening operations might be done before - # reaching DBI::DBD::SqlEngine::Table->new(), we need to intercept - # ReadOnly here - my $write_op = $createMode || $lockMode || $flags->{dropMode}; - if ($write_op) - { - $table_meta->{readonly} - and croak "Table '$table' is marked readonly - " - . $self->{command} - . ( $lockMode ? " with locking" : "" ) - . " command forbidden"; - } - - return $class->new( $data, { table => $table }, $flags ); -} # open_table - -# ====== SQL::TABLE ============================================================ - -package DBI::DBD::SqlEngine::Table; - -use strict; -use warnings; - -use Carp; - -@DBI::DBD::SqlEngine::Table::ISA = qw(DBI::SQL::Nano::Table); - -sub bootstrap_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_; - - defined $dbh->{ReadOnly} - and !defined( $meta->{readonly} ) - and $meta->{readonly} = $dbh->{ReadOnly}; - defined $meta->{sql_identifier_case} - or $meta->{sql_identifier_case} = $dbh->{sql_identifier_case}; - - exists $meta->{sql_data_source} or $meta->{sql_data_source} = $dbh->{sql_data_source}; - - $meta; -} - -sub init_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_ if (0); - - return; -} # init_table_meta - -sub get_table_meta ($$$;$) -{ - my ( $self, $dbh, $table, $respect_case, @other ) = @_; - unless ( defined $respect_case ) - { - $respect_case = 0; - $table =~ s/^\"// and $respect_case = 1; # handle quoted identifiers - $table =~ s/\"$//; - } - - unless ($respect_case) - { - defined $dbh->{sql_meta_map}{$table} and $table = $dbh->{sql_meta_map}{$table}; - } - - my $meta = {}; - defined $dbh->{sql_meta}{$table} and $meta = $dbh->{sql_meta}{$table}; - - do_initialize: - unless ( $meta->{initialized} ) - { - $self->bootstrap_table_meta( $dbh, $meta, $table, @other ); - $meta->{sql_data_source}->complete_table_name( $meta, $table, $respect_case, @other ) - or return; - - if ( defined $meta->{table_name} and $table ne $meta->{table_name} ) - { - $dbh->{sql_meta_map}{$table} = $meta->{table_name}; - $table = $meta->{table_name}; - } - - # now we know a bit more - let's check if user can't use consequent spelling - # XXX add know issue about reset sql_identifier_case here ... - if ( defined $dbh->{sql_meta}{$table} ) - { - $meta = delete $dbh->{sql_meta}{$table}; # avoid endless loop - $meta->{initialized} - or goto do_initialize; - #or $meta->{sql_data_source}->complete_table_name( $meta, $table, $respect_case, @other ) - #or return; - } - - unless ( $dbh->{sql_meta}{$table}{initialized} ) - { - $self->init_table_meta( $dbh, $meta, $table ); - $meta->{initialized} = 1; - $dbh->{sql_meta}{$table} = $meta; - } - } - - return ( $table, $meta ); -} # get_table_meta - -my %reset_on_modify = (); -my %compat_map = (); - -sub register_reset_on_modify -{ - my ( $proto, $extra_resets ) = @_; - foreach my $cv ( keys %$extra_resets ) - { - #%reset_on_modify = ( %reset_on_modify, %$extra_resets ); - push @{ $reset_on_modify{$cv} }, - ref $extra_resets->{$cv} ? @{ $extra_resets->{$cv} } : ( $extra_resets->{$cv} ); - } - return; -} # register_reset_on_modify - -sub register_compat_map -{ - my ( $proto, $extra_compat_map ) = @_; - %compat_map = ( %compat_map, %$extra_compat_map ); - return; -} # register_compat_map - -sub get_table_meta_attr -{ - my ( $class, $meta, $attrib ) = @_; - exists $compat_map{$attrib} - and $attrib = $compat_map{$attrib}; - exists $meta->{$attrib} - and return $meta->{$attrib}; - return; -} # get_table_meta_attr - -sub set_table_meta_attr -{ - my ( $class, $meta, $attrib, $value ) = @_; - exists $compat_map{$attrib} - and $attrib = $compat_map{$attrib}; - $class->table_meta_attr_changed( $meta, $attrib, $value ); - $meta->{$attrib} = $value; -} # set_table_meta_attr - -sub table_meta_attr_changed -{ - my ( $class, $meta, $attrib, $value ) = @_; - defined $reset_on_modify{$attrib} - and delete @$meta{ @{ $reset_on_modify{$attrib} } } - and $meta->{initialized} = 0; -} # table_meta_attr_changed - -sub open_data -{ - my ( $self, $meta, $attrs, $flags ) = @_; - - $meta->{sql_data_source} - or croak "Table " . $meta->{table_name} . " not completely initialized"; - $meta->{sql_data_source}->open_data( $meta, $attrs, $flags ); - - return; -} # open_data - -# ====== SQL::Eval API ========================================================= - -sub new -{ - my ( $className, $data, $attrs, $flags ) = @_; - my $dbh = $data->{Database}; - - my ( $tblnm, $meta ) = $className->get_table_meta( $dbh, $attrs->{table}, 1 ) - or croak "Cannot find appropriate table '$attrs->{table}'"; - $attrs->{table} = $tblnm; - - # Being a bit dirty here, as SQL::Statement::Structure does not offer - # me an interface to the data I want - $flags->{createMode} && $data->{sql_stmt}{table_defs} - and $meta->{table_defs} = $data->{sql_stmt}{table_defs}; - - # open_file must be called before inherited new is invoked - # because column name mapping is initialized in constructor ... - $className->open_data( $meta, $attrs, $flags ); - - my $tbl = { - %{$attrs}, - meta => $meta, - col_names => $meta->{col_names} || [], - }; - return $className->SUPER::new($tbl); -} # new - -sub DESTROY -{ - my $self = shift; - my $meta = $self->{meta}; - $self->{row} and undef $self->{row}; - () -} - -1; - -=pod - -=head1 NAME - -DBI::DBD::SqlEngine - Base class for DBI drivers without their own SQL engine - -=head1 SYNOPSIS - - package DBD::myDriver; - - use base qw(DBI::DBD::SqlEngine); - - sub driver - { - ... - my $drh = $proto->SUPER::driver($attr); - ... - return $drh->{class}; - } - - package DBD::myDriver::dr; - - @ISA = qw(DBI::DBD::SqlEngine::dr); - - sub data_sources { ... } - ... - - package DBD::myDriver::db; - - @ISA = qw(DBI::DBD::SqlEngine::db); - - sub init_valid_attributes { ... } - sub init_default_attributes { ... } - sub set_versions { ... } - sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } - sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } - sub get_myd_versions { ... } - sub get_avail_tables { ... } - - package DBD::myDriver::st; - - @ISA = qw(DBI::DBD::SqlEngine::st); - - sub FETCH { ... } - sub STORE { ... } - - package DBD::myDriver::Statement; - - @ISA = qw(DBI::DBD::SqlEngine::Statement); - - sub open_table { ... } - - package DBD::myDriver::Table; - - @ISA = qw(DBI::DBD::SqlEngine::Table); - - sub new { ... } - -=head1 DESCRIPTION - -DBI::DBD::SqlEngine abstracts the usage of SQL engines from the -DBD. DBD authors can concentrate on the data retrieval they want to -provide. - -It is strongly recommended that you read L and -L, because many of the DBD::File API is provided -by DBI::DBD::SqlEngine. - -Currently the API of DBI::DBD::SqlEngine is experimental and will -likely change in the near future to provide the table meta data basics -like DBD::File. - -DBI::DBD::SqlEngine expects that any driver in inheritance chain has -a L. - -=head2 Metadata - -The following attributes are handled by DBI itself and not by -DBI::DBD::SqlEngine, thus they all work as expected: - - Active - ActiveKids - CachedKids - CompatMode (Not used) - InactiveDestroy - AutoInactiveDestroy - Kids - PrintError - RaiseError - Warn (Not used) - -=head3 The following DBI attributes are handled by DBI::DBD::SqlEngine: - -=head4 AutoCommit - -Always on. - -=head4 ChopBlanks - -Works. - -=head4 NUM_OF_FIELDS - -Valid after C<< $sth->execute >>. - -=head4 NUM_OF_PARAMS - -Valid after C<< $sth->prepare >>. - -=head4 NAME - -Valid after C<< $sth->execute >>; probably undef for Non-Select statements. - -=head4 NULLABLE - -Not really working, always returns an array ref of ones, as DBD::CSV -does not verify input data. Valid after C<< $sth->execute >>; undef for -non-select statements. - -=head3 The following DBI attributes and methods are not supported: - -=over 4 - -=item bind_param_inout - -=item CursorName - -=item LongReadLen - -=item LongTruncOk - -=back - -=head3 DBI::DBD::SqlEngine specific attributes - -In addition to the DBI attributes, you can use the following dbh -attributes: - -=head4 sql_engine_version - -Contains the module version of this driver (B) - -=head4 sql_nano_version - -Contains the module version of DBI::SQL::Nano (B) - -=head4 sql_statement_version - -Contains the module version of SQL::Statement, if available (B) - -=head4 sql_handler - -Contains the SQL Statement engine, either DBI::SQL::Nano or SQL::Statement -(B). - -=head4 sql_parser_object - -Contains an instantiated instance of SQL::Parser (B). -This is filled when used first time (only when used with SQL::Statement). - -=head4 sql_sponge_driver - -Contains an internally used DBD::Sponge handle (B). - -=head4 sql_valid_attrs - -Contains the list of valid attributes for each DBI::DBD::SqlEngine based -driver (B). - -=head4 sql_readonly_attrs - -Contains the list of those attributes which are readonly (B). - -=head4 sql_identifier_case - -Contains how DBI::DBD::SqlEngine deals with non-quoted SQL identifiers: - - * SQL_IC_UPPER (1) means all identifiers are internally converted - into upper-cased pendants - * SQL_IC_LOWER (2) means all identifiers are internally converted - into lower-cased pendants - * SQL_IC_MIXED (4) means all identifiers are taken as they are - -These conversions happen if (and only if) no existing identifier matches. -Once existing identifier is used as known. - -The SQL statement execution classes doesn't have to care, so don't expect -C affects column names in statements like - - SELECT * FROM foo - -=head4 sql_quoted_identifier_case - -Contains how DBI::DBD::SqlEngine deals with quoted SQL identifiers -(B). It's fixated to SQL_IC_SENSITIVE (3), which is interpreted -as SQL_IC_MIXED. - -=head4 sql_flags - -Contains additional flags to instantiate an SQL::Parser. Because an -SQL::Parser is instantiated only once, it's recommended to set this flag -before any statement is executed. - -=head4 sql_dialect - -Controls the dialect understood by SQL::Parser. Possible values (delivery -state of SQL::Statement): - - * ANSI - * CSV - * AnyData - -Defaults to "CSV". Because an SQL::Parser is instantiated only once and -SQL::Parser doesn't allow one to modify the dialect once instantiated, -it's strongly recommended to set this flag before any statement is -executed (best place is connect attribute hash). - -=head4 sql_engine_in_gofer - -This value has a true value in case of this driver is operated via -L. The impact of being operated via Gofer is a read-only -driver (not read-only databases!), so you cannot modify any attributes -later - neither any table settings. B you won't get an error in -cases you modify table attributes, so please carefully watch -C. - -=head4 sql_meta - -Private data area which contains information about the tables this -module handles. Table meta data might not be available until the -table has been accessed for the first time e.g., by issuing a select -on it however it is possible to pre-initialize attributes for each table -you use. - -DBI::DBD::SqlEngine recognizes the (public) attributes C, -C, C, C and C. -Be very careful when modifying attributes you do not know, the consequence -might be a destroyed or corrupted table. - -While C is a private and readonly attribute (which means, you -cannot modify it's values), derived drivers might provide restricted -write access through another attribute. Well known accessors are -C for L, C for L and -C for L. - -=head4 sql_table_source - -Controls the class which will be used for fetching available tables. - -See L for details. - -=head4 sql_data_source - -Contains the class name to be used for opening tables. - -See L for details. - -=head2 Driver private methods - -=head3 Default DBI methods - -=head4 data_sources - -The C method returns a list of subdirectories of the current -directory in the form "dbi:CSV:f_dir=$dirname". - -If you want to read the subdirectories of another directory, use - - my ($drh) = DBI->install_driver ("CSV"); - my (@list) = $drh->data_sources (f_dir => "/usr/local/csv_data"); - -=head4 list_tables - -This method returns a list of file names inside $dbh->{f_dir}. -Example: - - my ($dbh) = DBI->connect ("dbi:CSV:f_dir=/usr/local/csv_data"); - my (@list) = $dbh->func ("list_tables"); - -Note that the list includes all files contained in the directory, even -those that have non-valid table names, from the view of SQL. - -=head3 Additional methods - -The following methods are only available via their documented name when -DBI::DBD::SQlEngine is used directly. Because this is only reasonable for -testing purposes, the real names must be used instead. Those names can be -computed by replacing the C in the method name with the driver prefix. - -=head4 sql_versions - -Signature: - - sub sql_versions (;$) { - my ($table_name) = @_; - $table_name ||= "."; - ... - } - -Returns the versions of the driver, including the DBI version, the Perl -version, DBI::PurePerl version (if DBI::PurePerl is active) and the version -of the SQL engine in use. - - my $dbh = DBI->connect ("dbi:File:"); - my $sql_versions = $dbh->func( "sql_versions" ); - print "$sql_versions\n"; - __END__ - # DBI::DBD::SqlEngine 0.05 using SQL::Statement 1.402 - # DBI 1.623 - # OS netbsd (6.99.12) - # Perl 5.016002 (x86_64-netbsd-thread-multi) - -Called in list context, sql_versions will return an array containing each -line as single entry. - -Some drivers might use the optional (table name) argument and modify -version information related to the table (e.g. DBD::DBM provides storage -backend information for the requested table, when it has a table name). - -=head4 sql_get_meta - -Signature: - - sub sql_get_meta ($$) - { - my ($table_name, $attrib) = @_; - ... - } - -Returns the value of a meta attribute set for a specific table, if any. -See L for the possible attributes. - -A table name of C<"."> (single dot) is interpreted as the default table. -This will retrieve the appropriate attribute globally from the dbh. -This has the same restrictions as C<< $dbh->{$attrib} >>. - -=head4 sql_set_meta - -Signature: - - sub sql_set_meta ($$$) - { - my ($table_name, $attrib, $value) = @_; - ... - } - -Sets the value of a meta attribute set for a specific table. -See L for the possible attributes. - -A table name of C<"."> (single dot) is interpreted as the default table -which will set the specified attribute globally for the dbh. -This has the same restrictions as C<< $dbh->{$attrib} = $value >>. - -=head4 sql_clear_meta - -Signature: - - sub sql_clear_meta ($) - { - my ($table_name) = @_; - ... - } - -Clears the table specific meta information in the private storage of the -dbh. - -=head2 Extensibility - -=head3 DBI::DBD::SqlEngine::TableSource - -Provides data sources and table information on database driver and database -handle level. - - package DBI::DBD::SqlEngine::TableSource; - - sub data_sources ($;$) - { - my ( $class, $drh, $attrs ) = @_; - ... - } - - sub avail_tables - { - my ( $class, $drh ) = @_; - ... - } - -The C method is called when the user invokes any of the -following: - - @ary = DBI->data_sources($driver); - @ary = DBI->data_sources($driver, \%attr); - - @ary = $dbh->data_sources(); - @ary = $dbh->data_sources(\%attr); - -The C method is called when the user invokes any of the -following: - - @names = $dbh->tables( $catalog, $schema, $table, $type ); - - $sth = $dbh->table_info( $catalog, $schema, $table, $type ); - $sth = $dbh->table_info( $catalog, $schema, $table, $type, \%attr ); - - $dbh->func( "list_tables" ); - -Every time where an C<\%attr> argument can be specified, this C<\%attr> -object's C attribute is preferred over the C<$dbh> -attribute or the driver default, eg. - - @ary = DBI->data_sources("dbi:CSV:", { - f_dir => "/your/csv/tables", - # note: this class doesn't comes with DBI - sql_table_source => "DBD::File::Archive::Tar::TableSource", - # scan tarballs instead of directories - }); - -When you're going to implement such a DBD::File::Archive::Tar::TableSource -class, remember to add correct attributes (including C -and C) to the returned DSN's. - -=head3 DBI::DBD::SqlEngine::DataSource - -Provides base functionality for dealing with tables. It is primarily -designed for allowing transparent access to files on disk or already -opened (file-)streams (eg. for DBD::CSV). - -Derived classes shall be restricted to similar functionality, too (eg. -opening streams from an archive, transparently compress/uncompress -log files before parsing them, - - package DBI::DBD::SqlEngine::DataSource; - - sub complete_table_name ($$;$) - { - my ( $self, $meta, $table, $respect_case ) = @_; - ... - } - -The method C is called when first setting up the -I for a table: - - "SELECT user.id, user.name, user.shell FROM user WHERE ..." - -results in opening the table C. First step of the table open -process is completing the name. Let's imagine you're having a L -handle with following settings: - - $dbh->{sql_identifier_case} = SQL_IC_LOWER; - $dbh->{f_ext} = '.lst'; - $dbh->{f_dir} = '/data/web/adrmgr'; - -Those settings will result in looking for files matching -C<[Uu][Ss][Ee][Rr](\.lst)?$> in C. The scanning of the -directory C and the pattern match check will be done -in C by the C method. - -If you intend to provide other sources of data streams than files, in -addition to provide an appropriate C method, a method -to open the resource is required: - - package DBI::DBD::SqlEngine::DataSource; - - sub open_data ($) - { - my ( $self, $meta, $attrs, $flags ) = @_; - ... - } - -After the method C has been run successfully, the table's meta -information are in a state which allowes the table's data accessor methods -will be able to fetch/store row information. Implementation details heavily -depends on the table implementation, whereby the most famous is surely -L. - -=head1 SQL ENGINES - -DBI::DBD::SqlEngine currently supports two SQL engines: -L and -L. DBI::SQL::Nano supports a -I limited subset of SQL statements, but it might be faster for some -very simple tasks. SQL::Statement in contrast supports a much larger subset -of ANSI SQL. - -To use SQL::Statement, you need at least version 1.401 of -SQL::Statement and the environment variable C must not -be set to a true value. - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command. - - perldoc DBI::DBD::SqlEngine - -You can also look for information at: - -=over 4 - -=item * RT: CPAN's request tracker - -L -L - -=item * AnnoCPAN: Annotated CPAN documentation - -L -L - -=item * CPAN Ratings - -L - -=item * Search CPAN - -L - -=back - -=head2 Where can I go for more help? - -For questions about installation or usage, please ask on the -dbi-dev@perl.org mailing list. - -If you have a bug report, patch or suggestion, please open -a new report ticket on CPAN, if there is not already one for -the issue you want to report. Of course, you can mail any of the -module maintainers, but it is less likely to be missed if -it is reported on RT. - -Report tickets should contain a detailed description of the bug or -enhancement request you want to report and at least an easy way to -verify/reproduce the issue and any supplied fix. Patches are always -welcome, too. - -=head1 ACKNOWLEDGEMENTS - -Thanks to Tim Bunce, Martin Evans and H.Merijn Brand for their continued -support while developing DBD::File, DBD::DBM and DBD::AnyData. -Their support, hints and feedback helped to design and implement this -module. - -=head1 AUTHOR - -This module is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -The original authors are Jochen Wiedmann and Jeff Zucker. - -=head1 COPYRIGHT AND LICENSE - - Copyright (C) 2009-2013 by H.Merijn Brand & Jens Rehsack - Copyright (C) 2004-2009 by Jeff Zucker - Copyright (C) 1998-2004 by Jochen Wiedmann - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=head1 SEE ALSO - -L, L, L and L. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine/Developers.pod b/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine/Developers.pod deleted file mode 100644 index ff272ab..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine/Developers.pod +++ /dev/null @@ -1,851 +0,0 @@ -=head1 NAME - -DBI::DBD::SqlEngine::Developers - Developers documentation for DBI::DBD::SqlEngine - -=head1 SYNOPSIS - - package DBD::myDriver; - - use base qw(DBI::DBD::SqlEngine); - - sub driver - { - ... - my $drh = $proto->SUPER::driver($attr); - ... - return $drh->{class}; - } - - sub CLONE { ... } - - package DBD::myDriver::dr; - - @ISA = qw(DBI::DBD::SqlEngine::dr); - - sub data_sources { ... } - ... - - package DBD::myDriver::db; - - @ISA = qw(DBI::DBD::SqlEngine::db); - - sub init_valid_attributes { ... } - sub init_default_attributes { ... } - sub set_versions { ... } - sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } - sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } - sub get_myd_versions { ... } - sub get_avail_tables { ... } - - package DBD::myDriver::st; - - @ISA = qw(DBI::DBD::SqlEngine::st); - - sub FETCH { ... } - sub STORE { ... } - - package DBD::myDriver::Statement; - - @ISA = qw(DBI::DBD::SqlEngine::Statement); - - sub open_table { ... } - - package DBD::myDriver::Table; - - @ISA = qw(DBI::DBD::SqlEngine::Table); - - my %reset_on_modify = ( - myd_abc => "myd_foo", - myd_mno => "myd_bar", - ); - __PACKAGE__->register_reset_on_modify( \%reset_on_modify ); - my %compat_map = ( - abc => 'foo_abc', - xyz => 'foo_xyz', - ); - __PACKAGE__->register_compat_map( \%compat_map ); - - sub bootstrap_table_meta { ... } - sub init_table_meta { ... } - sub table_meta_attr_changed { ... } - sub open_data { ... } - - sub new { ... } - - sub fetch_row { ... } - sub push_row { ... } - sub push_names { ... } - sub seek { ... } - sub truncate { ... } - sub drop { ... } - - # optimize the SQL engine by add one or more of - sub update_current_row { ... } - # or - sub update_specific_row { ... } - # or - sub update_one_row { ... } - # or - sub insert_new_row { ... } - # or - sub delete_current_row { ... } - # or - sub delete_one_row { ... } - -=head1 DESCRIPTION - -This document describes the interface of DBI::DBD::SqlEngine for DBD -developers who write DBI::DBD::SqlEngine based DBI drivers. It supplements -L and L, which you should read first. - -=head1 CLASSES - -Each DBI driver must provide a package global C<< driver >> method and -three DBI related classes: - -=over 4 - -=item DBI::DBD::SqlEngine::dr - -Driver package, contains the methods DBI calls indirectly via DBI -interface: - - DBI->connect ('DBI:DBM:', undef, undef, {}) - - # invokes - package DBD::DBM::dr; - @DBD::DBM::dr::ISA = qw(DBI::DBD::SqlEngine::dr); - - sub connect ($$;$$$) - { - ... - } - -Similar for C and C. - -Pure Perl DBI drivers derived from DBI::DBD::SqlEngine usually don't need to -override any of the methods provided through the DBD::XXX::dr package. -However if you need additional initialization not fitting in -C and C of you're ::db -class, the connect method might be the final place to be modified. - -=item DBI::DBD::SqlEngine::db - -Contains the methods which are called through DBI database handles -(C<< $dbh >>). e.g., - - $sth = $dbh->prepare ("select * from foo"); - # returns the f_encoding setting for table foo - $dbh->csv_get_meta ("foo", "f_encoding"); - -DBI::DBD::SqlEngine provides the typical methods required here. Developers who -write DBI drivers based on DBI::DBD::SqlEngine need to override the methods -C<< set_versions >> and C<< init_valid_attributes >>. - -=item DBI::DBD::SqlEngine::TieMeta; - -Provides the tie-magic for C<< $dbh->{$drv_pfx . "_meta"} >>. Routes -C through C<< $drv->set_sql_engine_meta() >> and C through -C<< $drv->get_sql_engine_meta() >>. C is not supported, you have -to execute a C statement, where applicable. - -=item DBI::DBD::SqlEngine::TieTables; - -Provides the tie-magic for tables in C<< $dbh->{$drv_pfx . "_meta"} >>. -Routes C though C<< $tblClass->set_table_meta_attr() >> and C -though C<< $tblClass->get_table_meta_attr() >>. C removes an -attribute from the I retrieved by -C<< $tblClass->get_table_meta() >>. - -=item DBI::DBD::SqlEngine::st - -Contains the methods to deal with prepared statement handles. e.g., - - $sth->execute () or die $sth->errstr; - -=item DBI::DBD::SqlEngine::TableSource; - -Base class for 3rd party table sources: - - $dbh->{sql_table_source} = "DBD::Foo::TableSource"; - -=item DBI::DBD::SqlEngine::DataSource; - -Base class for 3rd party data sources: - - $dbh->{sql_data_source} = "DBD::Foo::DataSource"; - -=item DBI::DBD::SqlEngine::Statement; - -Base class for derived drivers statement engine. Implements C. - -=item DBI::DBD::SqlEngine::Table; - -Contains tailoring between SQL engine's requirements and -C magic for finding the right tables and storage. -Builds bridges between C handling of C, -table initialization for SQL engines and I's attribute -management for derived drivers. - -=back - -=head2 DBI::DBD::SqlEngine - -This is the main package containing the routines to initialize -DBI::DBD::SqlEngine based DBI drivers. Primarily the -C<< DBI::DBD::SqlEngine::driver >> method is invoked, either directly -from DBI when the driver is initialized or from the derived class. - - package DBD::DBM; - - use base qw( DBI::DBD::SqlEngine ); - - sub driver - { - my ( $class, $attr ) = @_; - ... - my $drh = $class->SUPER::driver( $attr ); - ... - return $drh; - } - -It is not necessary to implement your own driver method as long as -additional initialization (e.g. installing more private driver -methods) is not required. You do not need to call C<< setup_driver >> -as DBI::DBD::SqlEngine takes care of it. - -=head2 DBI::DBD::SqlEngine::dr - -The driver package contains the methods DBI calls indirectly via the DBI -interface (see L). - -DBI::DBD::SqlEngine based DBI drivers usually do not need to implement anything here, -it is enough to do the basic initialization: - - package DBD:XXX::dr; - - @DBD::XXX::dr::ISA = qw (DBI::DBD::SqlEngine::dr); - $DBD::XXX::dr::imp_data_size = 0; - $DBD::XXX::dr::data_sources_attr = undef; - $DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann"; - -=head3 Methods provided by C<< DBI::DBD::SqlEngine::dr >>: - -=over 4 - -=item connect - -Supervises the driver bootstrap when calling - - DBI->connect( "dbi:Foo", , , { ... } ); - -First it instantiates a new driver using C. After that, -initial bootstrap of the newly instantiated driver is done by - - $dbh->func( 0, "init_default_attributes" ); - -The first argument (C<0>) signals that this is the very first call to -C. Modern drivers understand that and do early -stage setup here after calling - - package DBD::Foo::db; - our @DBD::Foo::db::ISA = qw(DBI::DBD::SqlEngine::db); - - sub init_default_attributes - { - my ($dbh, $phase) = @_; - $dbh->SUPER::init_default_attributes($phase); - ...; # own setup code, maybe separated by phases - } - -When the C<$phase> argument is passed down until -C, C recognizes -a I driver and initializes the attributes from I and I<$attr> -arguments passed via C<< DBI->connect( $dsn, $user, $pass, \%attr ) >>. - -At the end of the attribute initialization after I, C -invoked C again for I: - - $dbh->func( 1, "init_default_attributes" ); - -=item data_sources - -Returns a list of I's using the C method of the -class specified in C<< $dbh->{sql_table_source} >> or via C<\%attr>: - - @ary = DBI->data_sources($driver); - @ary = DBI->data_sources($driver, \%attr); - -=item disconnect_all - -C doesn't have an overall driver cache, so nothing -happens here at all. - -=back - -=head2 DBI::DBD::SqlEngine::db - -This package defines the database methods, which are called via the DBI -database handle C<< $dbh >>. - -=head3 Methods provided by C<< DBI::DBD::SqlEngine::db >>: - -=over 4 - -=item ping - -Simply returns the content of the C<< Active >> attribute. Override -when your driver needs more complicated actions here. - -=item prepare - -Prepares a new SQL statement to execute. Returns a statement handle, -C<< $sth >> - instance of the DBD:XXX::st. It is neither required nor -recommended to override this method. - -=item validate_FETCH_attr - -Called by C to allow inherited drivers do their own attribute -name validation. Calling convention is similar to C and the -return value is the approved attribute name. - - return $validated_attribute_name; - -In case of validation fails (e.g. accessing private attribute or similar), -C is permitted to throw an exception. - -=item FETCH - -Fetches an attribute of a DBI database object. Private handle attributes -must have a prefix (this is mandatory). If a requested attribute is -detected as a private attribute without a valid prefix, the driver prefix -(written as C<$drv_prefix>) is added. - -The driver prefix is extracted from the attribute name and verified against -C<< $dbh->{ $drv_prefix . "valid_attrs" } >> (when it exists). If the -requested attribute value is not listed as a valid attribute, this method -croaks. If the attribute is valid and readonly (listed in C<< $dbh->{ -$drv_prefix . "readonly_attrs" } >> when it exists), a real copy of the -attribute value is returned. So it's not possible to modify -C from outside of DBI::DBD::SqlEngine::db or a derived class. - -=item validate_STORE_attr - -Called by C to allow inherited drivers do their own attribute -name validation. Calling convention is similar to C and the -return value is the approved attribute name followed by the approved -new value. - - return ($validated_attribute_name, $validated_attribute_value); - -In case of validation fails (e.g. accessing private attribute or similar), -C is permitted to throw an exception -(C throws an exception when -someone tries to assign value other than C -to C<< $dbh->{sql_identifier_case} >> or -C<< $dbh->{sql_quoted_identifier_case} >>). - -=item STORE - -Stores a database private attribute. Private handle attributes must have a -prefix (this is mandatory). If a requested attribute is detected as a private -attribute without a valid prefix, the driver prefix (written as -C<$drv_prefix>) is added. If the database handle has an attribute -C<${drv_prefix}_valid_attrs> - for attribute names which are not listed in -that hash, this method croaks. If the database handle has an attribute -C<${drv_prefix}_readonly_attrs>, only attributes which are not listed there -can be stored (once they are initialized). Trying to overwrite such an -immutable attribute forces this method to croak. - -An example of a valid attributes list can be found in -C<< DBI::DBD::SqlEngine::db::init_valid_attributes >>. - -=item set_versions - -This method sets the attributes C<< f_version >>, C<< sql_nano_version >>, -C<< sql_statement_version >> and (if not prohibited by a restrictive -C<< ${prefix}_valid_attrs >>) C<< ${prefix}_version >>. - -This method is called at the end of the C<< connect () >> phase. - -When overriding this method, do not forget to invoke the superior one. - -=item init_valid_attributes - -This method is called after the database handle is instantiated as the -first attribute initialization. - -C<< DBI::DBD::SqlEngine::db::init_valid_attributes >> initializes the -attributes C and C. - -When overriding this method, do not forget to invoke the superior one, -preferably before doing anything else. - -=item init_default_attributes - -This method is called after the database handle is instantiated to -initialize the default attributes. It expects one argument: C<$phase>. -If C<$phase> is not given, C of C -expects this is an old-fashioned driver which isn't capable of multi-phased -initialization. - -C<< DBI::DBD::SqlEngine::db::init_default_attributes >> initializes the -attributes C, C, -C, C, C, C, -C and C when L -is available. - -It sets C to the given C<$phase>. - -When the derived implementor class provides the attribute to validate -attributes (e.g. C<< $dbh->{dbm_valid_attrs} = {...}; >>) or the attribute -containing the immutable attributes (e.g. C<< $dbh->{dbm_readonly_attrs} -= {...}; >>), the attributes C, C and -C are added (when available) to the list of valid and -immutable attributes (where C is interpreted as the driver prefix). - -=item get_versions - -This method is called by the code injected into the instantiated driver to -provide the user callable driver method C<< ${prefix}versions >> (e.g. -C<< dbm_versions >>, C<< csv_versions >>, ...). - -The DBI::DBD::SqlEngine implementation returns all version information known by -DBI::DBD::SqlEngine (e.g. DBI version, Perl version, DBI::DBD::SqlEngine version and -the SQL handler version). - -C takes the C<$dbh> as the first argument and optionally a -second argument containing a table name. The second argument is not -evaluated in C<< DBI::DBD::SqlEngine::db::get_versions >> itself - but -might be in the future. - -If the derived implementor class provides a method named -C, this is invoked and the return value of -it is associated to the derived driver name: - - if (my $dgv = $dbh->{ImplementorClass}->can ("get_" . $drv_prefix . "versions") { - (my $derived_driver = $dbh->{ImplementorClass}) =~ s/::db$//; - $versions{$derived_driver} = &$dgv ($dbh, $table); - } - -Override it to add more version information about your module, (e.g. -some kind of parser version in case of DBD::CSV, ...), if one line is not -enough room to provide all relevant information. - -=item sql_parser_object - -Returns a L instance, when C<< sql_handler >> is set to -"SQL::Statement". The parser instance is stored in C<< sql_parser_object >>. - -It is not recommended to override this method. - -=item disconnect - -Disconnects from a database. All local table information is discarded and -the C<< Active >> attribute is set to 0. - -=item type_info_all - -Returns information about all the types supported by DBI::DBD::SqlEngine. - -=item table_info - -Returns a statement handle which is prepared to deliver information about -all known tables. - -=item list_tables - -Returns a list of all known table names. - -=item quote - -Quotes a string for use in SQL statements. - -=item commit - -Warns about a useless call (if warnings enabled) and returns. -DBI::DBD::SqlEngine is typically a driver which commits every action -instantly when executed. - -=item rollback - -Warns about a useless call (if warnings enabled) and returns. -DBI::DBD::SqlEngine is typically a driver which commits every action -instantly when executed. - -=back - -=head3 Attributes used by C<< DBI::DBD::SqlEngine::db >>: - -This section describes attributes which are important to developers of DBI -Database Drivers derived from C. - -=over 4 - -=item sql_init_order - -This attribute contains a hash with priorities as key and an array -containing the C<$dbh> attributes to be initialized during before/after -other attributes. - -C initializes following attributes: - - $dbh->{sql_init_order} = { - 0 => [qw( Profile RaiseError PrintError AutoCommit )], - 90 => [ "sql_meta", $dbh->{$drv_pfx_meta} ? $dbh->{$drv_pfx_meta} : () ] - } - -The default priority of not listed attribute keys is C<50>. It is well -known that a lot of attributes needed to be set before some table settings -are initialized. For example, for L, when using - - my $dbh = DBI->connect( "dbi:DBM:", undef, undef, { - f_dir => "/path/to/dbm/databases", - dbm_type => "BerkeleyDB", - dbm_mldbm => "JSON", # use MLDBM::Serializer::JSON - dbm_tables => { - quick => { - dbm_type => "GDBM_File", - dbm_MLDBM => "FreezeThaw" - } - } - }); - -This defines a known table C which uses the L backend and -L as serializer instead of the overall default L and -L. B all files containing the table data have to be searched in -C<< $dbh->{f_dir} >>, which requires C<< $dbh->{f_dir} >> must be initialized -before C<< $dbh->{sql_meta}->{quick} >> is initialized by -C method of L to get -C<< $dbh->{sql_meta}->{quick}->{f_dir} >> being initialized properly. - -=item sql_init_phase - -This attribute is only set during the initialization steps of the DBI -Database Driver. It contains the value of the currently run initialization -phase. Currently supported phases are I and I. This -attribute is set in C and removed in C. - -=item sql_engine_in_gofer - -This value has a true value in case of this driver is operated via -L. The impact of being operated via Gofer is a read-only -driver (not read-only databases!), so you cannot modify any attributes -later - neither any table settings. B you won't get an error in -cases you modify table attributes, so please carefully watch -C. - -=item sql_table_source - -Names a class which is responsible for delivering I and -I (Database Driver related). I here -refers to L, not C. - -See L for details. - -=item sql_data_source - -Name a class which is responsible for handling table resources open -and completing table names requested via SQL statements. - -See L for details. - -=item sql_dialect - -Controls the dialect understood by SQL::Parser. Possible values (delivery -state of SQL::Statement): - - * ANSI - * CSV - * AnyData - -Defaults to "CSV". Because an SQL::Parser is instantiated only once and -SQL::Parser doesn't allow one to modify the dialect once instantiated, -it's strongly recommended to set this flag before any statement is -executed (best place is connect attribute hash). - -=back - -=head2 DBI::DBD::SqlEngine::st - -Contains the methods to deal with prepared statement handles: - -=over 4 - -=item bind_param - -Common routine to bind placeholders to a statement for execution. It -is dangerous to override this method without detailed knowledge about -the DBI::DBD::SqlEngine internal storage structure. - -=item execute - -Executes a previously prepared statement (with placeholders, if any). - -=item finish - -Finishes a statement handle, discards all buffered results. The prepared -statement is not discarded so the statement can be executed again. - -=item fetch - -Fetches the next row from the result-set. This method may be rewritten -in a later version and if it's overridden in a derived class, the -derived implementation should not rely on the storage details. - -=item fetchrow_arrayref - -Alias for C<< fetch >>. - -=item FETCH - -Fetches statement handle attributes. Supported attributes (for full overview -see L) are C, C, C -and C. Each column is returned as C which might be wrong -depending on the derived backend storage. If the statement handle has -private attributes, they can be fetched using this method, too. B that -statement attributes are not associated with any table used in this statement. - -This method usually requires extending in a derived implementation. -See L or L for some example. - -=item STORE - -Allows storing of statement private attributes. No special handling is -currently implemented here. - -=item rows - -Returns the number of rows affected by the last execute. This method might -return C. - -=back - -=head2 DBI::DBD::SqlEngine::TableSource - -Provides data sources and table information on database driver and database -handle level. - - package DBI::DBD::SqlEngine::TableSource; - - sub data_sources ($;$) - { - my ( $class, $drh, $attrs ) = @_; - ... - } - - sub avail_tables - { - my ( $class, $drh ) = @_; - ... - } - -The C method is called when the user invokes any of the -following: - - @ary = DBI->data_sources($driver); - @ary = DBI->data_sources($driver, \%attr); - - @ary = $dbh->data_sources(); - @ary = $dbh->data_sources(\%attr); - -The C method is called when the user invokes any of the -following: - - @names = $dbh->tables( $catalog, $schema, $table, $type ); - - $sth = $dbh->table_info( $catalog, $schema, $table, $type ); - $sth = $dbh->table_info( $catalog, $schema, $table, $type, \%attr ); - - $dbh->func( "list_tables" ); - -Every time where an C<\%attr> argument can be specified, this C<\%attr> -object's C attribute is preferred over the C<$dbh> -attribute or the driver default. - -=head2 DBI::DBD::SqlEngine::DataSource - -Provides base functionality for dealing with tables. It is primarily -designed for allowing transparent access to files on disk or already -opened (file-)streams (e.g. for DBD::CSV). - -Derived classes shall be restricted to similar functionality, too (e.g. -opening streams from an archive, transparently compress/uncompress -log files before parsing them, - - package DBI::DBD::SqlEngine::DataSource; - - sub complete_table_name ($$;$) - { - my ( $self, $meta, $table, $respect_case ) = @_; - ... - } - -The method C is called when first setting up the -I for a table: - - "SELECT user.id, user.name, user.shell FROM user WHERE ..." - -results in opening the table C. First step of the table open -process is completing the name. Let's imagine you're having a L -handle with following settings: - - $dbh->{sql_identifier_case} = SQL_IC_LOWER; - $dbh->{f_ext} = '.lst'; - $dbh->{f_dir} = '/data/web/adrmgr'; - -Those settings will result in looking for files matching -C<[Uu][Ss][Ee][Rr](\.lst)?$> in C. The scanning of the -directory C and the pattern match check will be done -in C by the C method. - -If you intend to provide other sources of data streams than files, in -addition to provide an appropriate C method, a method -to open the resource is required: - - package DBI::DBD::SqlEngine::DataSource; - - sub open_data ($) - { - my ( $self, $meta, $attrs, $flags ) = @_; - ... - } - -After the method C has been run successfully, the table's meta -information are in a state which allows the table's data accessor methods -will be able to fetch/store row information. Implementation details heavily -depends on the table implementation, whereby the most famous is surely -L. - -=head2 DBI::DBD::SqlEngine::Statement - -Derives from DBI::SQL::Nano::Statement for unified naming when deriving -new drivers. No additional feature is provided from here. - -=head2 DBI::DBD::SqlEngine::Table - -Derives from DBI::SQL::Nano::Table for unified naming when deriving -new drivers. - -You should consult the documentation of C<< SQL::Eval::Table >> (see -L) to get more information about the abstract methods of the -table's base class you have to override and a description of the table -meta information expected by the SQL engines. - -=over 4 - -=item bootstrap_table_meta - -Initializes a table meta structure. Can be safely overridden in a -derived class, as long as the C<< SUPER >> method is called at the end -of the overridden method. - -It copies the following attributes from the database into the table meta data -C<< $dbh->{ReadOnly} >> into C<< $meta->{readonly} >>, C -and C and makes them sticky to the table. - -This method should be called before you attempt to map between file -name and table name to ensure the correct directory, extension etc. are -used. - -=item init_table_meta - -Initializes more attributes of the table meta data - usually more -expensive ones (e.g. those which require class instantiations) - when -the file name and the table name could mapped. - -=item get_table_meta - -Returns the table meta data. If there are none for the required table, -a new one is initialized. When after bootstrapping a new I -and L a -mapping can be established between an existing I and the -new bootstrapped one, the already existing is used and a mapping -shortcut between the recent used table name and the already known -table name is hold in C<< $dbh->{sql_meta_map} >>. When it fails, -nothing is returned. On success, the name of the table and the meta data -structure is returned. - -=item get_table_meta_attr - -Returns a single attribute from the table meta data. If the attribute -name appears in C<%compat_map>, the attribute name is updated from -there. - -=item set_table_meta_attr - -Sets a single attribute in the table meta data. If the attribute -name appears in C<%compat_map>, the attribute name is updated from -there. - -=item table_meta_attr_changed - -Called when an attribute of the meta data is modified. - -If the modified attribute requires to reset a calculated attribute, the -calculated attribute is reset (deleted from meta data structure) and -the I flag is removed, too. The decision is made based on -C<%register_reset_on_modify>. - -=item register_reset_on_modify - -Allows C to reset meta attributes when special -attributes are modified. For DBD::File, modifying one of C, C, -C or C will reset C. DBD::DBM extends the -list for C and C to reset the value of C. - -If your DBD has calculated values in the meta data area, then call -C: - - my %reset_on_modify = ( "xxx_foo" => "xxx_bar" ); - __PACKAGE__->register_reset_on_modify( \%reset_on_modify ); - -=item register_compat_map - -Allows C and C to update the -attribute name to the current favored one: - - # from DBD::DBM - my %compat_map = ( "dbm_ext" => "f_ext" ); - __PACKAGE__->register_compat_map( \%compat_map ); - -=item open_data - -Called to open the table's data storage. This is silently forwarded -to C<< $meta->{sql_data_source}->open_data() >>. - -After this is done, a derived class might add more steps in an overridden -C<< open_file >> method. - -=item new - -Instantiates the table. This is done in 3 steps: - - 1. get the table meta data - 2. open the data file - 3. bless the table data structure using inherited constructor new - -It is not recommended to override the constructor of the table class. -Find a reasonable place to add you extensions in one of the above four -methods. - -=back - -=head1 AUTHOR - -The module DBI::DBD::SqlEngine is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine/HowTo.pod b/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine/HowTo.pod deleted file mode 100644 index b6c8caa..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/DBD/SqlEngine/HowTo.pod +++ /dev/null @@ -1,333 +0,0 @@ -=head1 NAME - -DBI::DBD::SqlEngine::HowTo - Guide to create DBI::DBD::SqlEngine based driver - -=head1 SYNOPSIS - - perldoc DBI::DBD::SqlEngine::HowTo - perldoc DBI - perldoc DBI::DBD - perldoc DBI::DBD::SqlEngine::Developers - perldoc SQL::Eval - perldoc DBI::DBD::SqlEngine - perldoc DBI::DBD::SqlEngine::HowTo - perldoc SQL::Statement::Embed - -=head1 DESCRIPTION - -This document provides a step-by-step guide, how to create a new -C based DBD. It expects that you carefully read the -L documentation and that you're familiar with L and had -read and understood L. - -This document addresses experienced developers who are really sure that -they need to invest time when writing a new DBI Driver. Writing a DBI -Driver is neither a weekend project nor an easy job for hobby coders -after work. Expect one or two man-month of time for the first start. - -Those who are still reading, should be able to sing the rules of -L. - -=head1 CREATING DRIVER CLASSES - -Do you have an entry in DBI's DBD registry? DBI::DBD::SqlEngine expect -having a unique prefix for every driver class in inheritance chain. - -It's easy to get a prefix - just drop the DBI team a note -(L). If you want for some reason hide your work, take -a look at L how to wrap a private prefix method -around existing C. - -For this guide, a prefix of C is assumed. - -=head2 Sample Skeleton - - package DBD::Foo; - - use strict; - use warnings; - use vars qw($VERSION); - use base qw(DBI::DBD::SqlEngine); - - use DBI (); - - $VERSION = "0.001"; - - package DBD::Foo::dr; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBI::DBD::SqlEngine::dr); - $imp_data_size = 0; - - package DBD::Foo::db; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBI::DBD::SqlEngine::db); - $imp_data_size = 0; - - package DBD::Foo::st; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBI::DBD::SqlEngine::st); - $imp_data_size = 0; - - package DBD::Foo::Statement; - - use vars qw(@ISA); - - @ISA = qw(DBI::DBD::SqlEngine::Statement); - - package DBD::Foo::Table; - - use vars qw(@ISA); - - @ISA = qw(DBI::DBD::SqlEngine::Table); - - 1; - -Tiny, eh? And all you have now is a DBD named foo which will is able to -deal with temporary tables, as long as you use L. In -L environments, this DBD can do nothing. - -=head2 Deal with own attributes - -Before we start doing usable stuff with our DBI driver, we need to think -about what we want to do and how we want to do it. - -Do we need tunable knobs accessible by users? Do we need status -information? All this is handled in attributes of the database handles (be -careful when your DBD is running "behind" a L proxy). - -How come the attributes into the DBD and how are they fetchable by the -user? Good question, but you should know because you've read the L -documentation. - -C and C -taking care for you - all they need to know is which attribute names -are valid and mutable or immutable. Tell them by adding -C to your db class: - - sub init_valid_attributes - { - my $dbh = $_[0]; - - $dbh->SUPER::init_valid_attributes (); - - $dbh->{foo_valid_attrs} = { - foo_version => 1, # contains version of this driver - foo_valid_attrs => 1, # contains the valid attributes of foo drivers - foo_readonly_attrs => 1, # contains immutable attributes of foo drivers - foo_bar => 1, # contains the bar attribute - foo_baz => 1, # contains the baz attribute - foo_manager => 1, # contains the manager of the driver instance - foo_manager_type => 1, # contains the manager class of the driver instance - }; - $dbh->{foo_readonly_attrs} = { - foo_version => 1, # ensure no-one modifies the driver version - foo_valid_attrs => 1, # do not permit one to add more valid attributes ... - foo_readonly_attrs => 1, # ... or make the immutable mutable - foo_manager => 1, # manager is set internally only - }; - - return $dbh; - } - -Woooho - but now the user cannot assign new managers? This is intended, -overwrite C to handle it! - - sub STORE ($$$) - { - my ( $dbh, $attrib, $value ) = @_; - - $dbh->SUPER::STORE( $attrib, $value ); - - # we're still alive, so no exception is thrown ... - # by DBI::DBD::SqlEngine::db::STORE - if ( $attrib eq "foo_manager_type" ) - { - $dbh->{foo_manager} = $dbh->{foo_manager_type}->new(); - # ... probably correct some states based on the new - # foo_manager_type - see DBD::Sys for an example - } - } - -But ... my driver runs without a manager until someone first assignes -a C. Well, no - there're two places where you can -initialize defaults: - - sub init_default_attributes - { - my ($dbh, $phase) = @_; - - $dbh->SUPER::init_default_attributes($phase); - - if( 0 == $phase ) - { - # init all attributes which have no knowledge about - # user settings from DSN or the attribute hash - $dbh->{foo_manager_type} = "DBD::Foo::Manager"; - } - elsif( 1 == $phase ) - { - # init phase with more knowledge from DSN or attribute - # hash - $dbh->{foo_manager} = $dbh->{foo_manager_type}->new(); - } - - return $dbh; - } - -So far we can prevent the users to use our database driver as data -storage for anything and everything. We care only about the real important -stuff for peace on earth and alike attributes. But in fact, the driver -still can't do anything. It can do less than nothing - meanwhile it's -not a stupid storage area anymore. - -=head2 User comfort - -C since C<0.05> consolidates all persistent meta data -of a table into a single structure stored in C<< $dbh->{sql_meta} >>. While -DBI::DBD::SqlEngine provides only readonly access to this structure, -modifications are still allowed. - -Primarily DBI::DBD::SqlEngine provides access via the setters -C, C, C, -C, C and C. -Those methods are easily accessible by the users via the C<< $dbh->func () >> -interface provided by DBI. Well, many users don't feel comfortize when calling - - # don't require extension for tables cars - $dbh->func ("cars", "f_ext", ".csv", "set_sql_engine_meta"); - -DBI::DBD::SqlEngine will inject a method into your driver to increase the -user comfort to allow: - - # don't require extension for tables cars - $dbh->foo_set_meta ("cars", "f_ext", ".csv"); - -Better, but here and there users likes to do: - - # don't require extension for tables cars - $dbh->{foo_tables}->{cars}->{f_ext} = ".csv"; - -This interface is provided when derived DBD's define following in -C (re-capture L): - - sub init_valid_attributes - { - my $dbh = $_[0]; - - $dbh->SUPER::init_valid_attributes (); - - $dbh->{foo_valid_attrs} = { - foo_version => 1, # contains version of this driver - foo_valid_attrs => 1, # contains the valid attributes of foo drivers - foo_readonly_attrs => 1, # contains immutable attributes of foo drivers - foo_bar => 1, # contains the bar attribute - foo_baz => 1, # contains the baz attribute - foo_manager => 1, # contains the manager of the driver instance - foo_manager_type => 1, # contains the manager class of the driver instance - foo_meta => 1, # contains the public interface to modify table meta attributes - }; - $dbh->{foo_readonly_attrs} = { - foo_version => 1, # ensure no-one modifies the driver version - foo_valid_attrs => 1, # do not permit one to add more valid attributes ... - foo_readonly_attrs => 1, # ... or make the immutable mutable - foo_manager => 1, # manager is set internally only - foo_meta => 1, # ensure public interface to modify table meta attributes are immutable - }; - - $dbh->{foo_meta} = "foo_tables"; - - return $dbh; - } - -This provides a tied hash in C<< $dbh->{foo_tables} >> and a tied hash for -each table's meta data in C<< $dbh->{foo_tables}->{$table_name} >>. -Modifications on the table meta attributes are done using the table -methods: - - sub get_table_meta_attr { ... } - sub set_table_meta_attr { ... } - -Both methods can adjust the attribute name for compatibility reasons, e.g. -when former versions of the DBD allowed different names to be used for the -same flag: - - my %compat_map = ( - abc => 'foo_abc', - xyz => 'foo_xyz', - ); - __PACKAGE__->register_compat_map( \%compat_map ); - -If any user modification on a meta attribute needs reinitialization of -the meta structure (in case of C these are the attributes -C, C, C and C), inform DBI::DBD::SqlEngine by -doing - - my %reset_on_modify = ( - foo_xyz => "foo_bar", - foo_abc => "foo_bar", - ); - __PACKAGE__->register_reset_on_modify( \%reset_on_modify ); - -The next access to the table meta data will force DBI::DBD::SqlEngine to re-do the -entire meta initialization process. - -Any further action which needs to be taken can handled in -C: - - sub table_meta_attr_changed - { - my ($class, $meta, $attrib, $value) = @_; - ... - $class->SUPER::table_meta_attr_changed ($meta, $attrib, $value); - } - -This is done before the new value is set in C<$meta>, so the attribute -changed handler can act depending on the old value. - -=head2 Dealing with Tables - -Let's put some life into it - it's going to be time for it. - -This is a good point where a quick side step to L -will help to shorten the next paragraph. The documentation in -SQL::Statement::Embed regarding embedding in own DBD's works pretty -fine with SQL::Statement and DBI::SQL::Nano. - -Second look should go to L to get a -picture over the driver part of the table API. Usually there isn't much -to do for an easy driver. - -=head2 Testing - -Now you should have your first own DBD. Was easy, wasn't it? But does -it work well? Prove it by writing tests and remember to use -dbd_edit_mm_attribs from L to ensure testing even rare cases. - -=head1 AUTHOR - -This guide is written by Jens Rehsack. DBI::DBD::SqlEngine is written by -Jens Rehsack using code from DBD::File originally written by Jochen -Wiedmann and Jeff Zucker. - -The module DBI::DBD::SqlEngine is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Execute.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Execute.pm deleted file mode 100644 index 5fdf9b3..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Execute.pm +++ /dev/null @@ -1,900 +0,0 @@ -package DBI::Gofer::Execute; - -# $Id: Execute.pm 14282 2010-07-26 00:12:54Z David $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use Carp; - -use DBI qw(dbi_time); -use DBI::Gofer::Request; -use DBI::Gofer::Response; - -use base qw(DBI::Util::_accessor); - -our $VERSION = "0.014283"; - -our @all_dbh_methods = sort map { keys %$_ } $DBI::DBI_methods{db}, $DBI::DBI_methods{common}; -our %all_dbh_methods = map { $_ => (DBD::_::db->can($_)||undef) } @all_dbh_methods; - -our $local_log = $ENV{DBI_GOFER_LOCAL_LOG}; # do extra logging to stderr - -our $current_dbh; # the dbh we're using for this request - - -# set trace for server-side gofer -# Could use DBI_TRACE env var when it's an unrelated separate process -# but using DBI_GOFER_TRACE makes testing easier for subprocesses (eg stream) -DBI->trace(split /=/, $ENV{DBI_GOFER_TRACE}, 2) if $ENV{DBI_GOFER_TRACE}; - - -# define valid configuration attributes (args to new()) -# the values here indicate the basic type of values allowed -my %configuration_attributes = ( - gofer_execute_class => 1, - default_connect_dsn => 1, - forced_connect_dsn => 1, - default_connect_attributes => {}, - forced_connect_attributes => {}, - track_recent => 1, - check_request_sub => sub {}, - check_response_sub => sub {}, - forced_single_resultset => 1, - max_cached_dbh_per_drh => 1, - max_cached_sth_per_dbh => 1, - forced_response_attributes => {}, - forced_gofer_random => 1, - stats => {}, -); - -__PACKAGE__->mk_accessors( - keys %configuration_attributes -); - - - -sub new { - my ($self, $args) = @_; - $args->{default_connect_attributes} ||= {}; - $args->{forced_connect_attributes} ||= {}; - $args->{max_cached_sth_per_dbh} ||= 1000; - $args->{stats} ||= {}; - return $self->SUPER::new($args); -} - - -sub valid_configuration_attributes { - my $self = shift; - return { %configuration_attributes }; -} - - -my %extra_attr = ( - # Only referenced if the driver doesn't support private_attribute_info method. - # What driver-specific attributes should be returned for the driver being used? - # keyed by $dbh->{Driver}{Name} - # XXX for sth should split into attr specific to resultsets (where NUM_OF_FIELDS > 0) and others - # which would reduce processing/traffic for non-select statements - mysql => { - dbh => [qw( - mysql_errno mysql_error mysql_hostinfo mysql_info mysql_insertid - mysql_protoinfo mysql_serverinfo mysql_stat mysql_thread_id - )], - sth => [qw( - mysql_is_blob mysql_is_key mysql_is_num mysql_is_pri_key mysql_is_auto_increment - mysql_length mysql_max_length mysql_table mysql_type mysql_type_name mysql_insertid - )], - # XXX this dbh_after_sth stuff is a temporary, but important, hack. - # should be done via hash instead of arrays where the hash value contains - # flags that can indicate which attributes need to be handled in this way - dbh_after_sth => [qw( - mysql_insertid - )], - }, - Pg => { - dbh => [qw( - pg_protocol pg_lib_version pg_server_version - pg_db pg_host pg_port pg_default_port - pg_options pg_pid - )], - sth => [qw( - pg_size pg_type pg_oid_status pg_cmd_status - )], - }, - Sybase => { - dbh => [qw( - syb_dynamic_supported syb_oc_version syb_server_version syb_server_version_string - )], - sth => [qw( - syb_types syb_proc_status syb_result_type - )], - }, - SQLite => { - dbh => [qw( - sqlite_version - )], - sth => [qw( - )], - }, - ExampleP => { - dbh => [qw( - examplep_private_dbh_attrib - )], - sth => [qw( - examplep_private_sth_attrib - )], - dbh_after_sth => [qw( - examplep_insertid - )], - }, -); - - -sub _connect { - my ($self, $request) = @_; - - my $stats = $self->{stats}; - - # discard CachedKids from time to time - if (++$stats->{_requests_served} % 1000 == 0 # XXX config? - and my $max_cached_dbh_per_drh = $self->{max_cached_dbh_per_drh} - ) { - my %drivers = DBI->installed_drivers(); - while ( my ($driver, $drh) = each %drivers ) { - next unless my $CK = $drh->{CachedKids}; - next unless keys %$CK > $max_cached_dbh_per_drh; - next if $driver eq 'Gofer'; # ie transport=null when testing - DBI->trace_msg(sprintf "Clearing %d cached dbh from $driver", - scalar keys %$CK, $self->{max_cached_dbh_per_drh}); - $_->{Active} && $_->disconnect for values %$CK; - %$CK = (); - } - } - - # local $ENV{...} can leak, so only do it if required - local $ENV{DBI_AUTOPROXY} if $ENV{DBI_AUTOPROXY}; - - my ($connect_method, $dsn, $username, $password, $attr) = @{ $request->dbh_connect_call }; - $connect_method ||= 'connect_cached'; - $stats->{method_calls_dbh}->{$connect_method}++; - - # delete attributes we don't want to affect the server-side - # (Could just do this on client-side and trust the client. DoS?) - delete @{$attr}{qw(Profile InactiveDestroy AutoInactiveDestroy HandleError HandleSetErr TraceLevel Taint TaintIn TaintOut)}; - - $dsn = $self->forced_connect_dsn || $dsn || $self->default_connect_dsn - or die "No forced_connect_dsn, requested dsn, or default_connect_dsn for request"; - - my $random = $self->{forced_gofer_random} || $ENV{DBI_GOFER_RANDOM} || ''; - - my $connect_attr = { - - # the configured default attributes, if any - %{ $self->default_connect_attributes }, - - # pass username and password as attributes - # then they can be overridden by forced_connect_attributes - Username => $username, - Password => $password, - - # the requested attributes - %$attr, - - # force some attributes the way we'd like them - PrintWarn => $local_log, - PrintError => $local_log, - - # the configured default attributes, if any - %{ $self->forced_connect_attributes }, - - # RaiseError must be enabled - RaiseError => 1, - - # reset Executed flag (of the cached handle) so we can use it to tell - # if errors happened before the main part of the request was executed - Executed => 0, - - # ensure this connect_cached doesn't have the same args as the client - # because that causes subtle issues if in the same process (ie transport=null) - # include pid to avoid problems with forking (ie null transport in mod_perl) - # include gofer-random to avoid random behaviour leaking to other handles - dbi_go_execute_unique => join("|", __PACKAGE__, $$, $random), - }; - - # XXX implement our own private connect_cached method? (with rate-limited ping) - my $dbh = DBI->$connect_method($dsn, undef, undef, $connect_attr); - - $dbh->{ShowErrorStatement} = 1 if $local_log; - - # XXX should probably just be a Callbacks => arg to connect_cached - # with a cache of pre-built callback hooks (memoized, without $self) - if (my $random = $self->{forced_gofer_random} || $ENV{DBI_GOFER_RANDOM}) { - $self->_install_rand_callbacks($dbh, $random); - } - - my $CK = $dbh->{CachedKids}; - if ($CK && keys %$CK > $self->{max_cached_sth_per_dbh}) { - %$CK = (); # clear all statement handles - } - - #$dbh->trace(0); - $current_dbh = $dbh; - return $dbh; -} - - -sub reset_dbh { - my ($self, $dbh) = @_; - $dbh->set_err(undef, undef); # clear any error state -} - - -sub new_response_with_err { - my ($self, $rv, $eval_error, $dbh) = @_; - # this is the usual way to create a response for both success and failure - # capture err+errstr etc and merge in $eval_error ($@) - - my ($err, $errstr, $state) = ($DBI::err, $DBI::errstr, $DBI::state); - - if ($eval_error) { - $err ||= $DBI::stderr || 1; # ensure err is true - if ($errstr) { - $eval_error =~ s/(?: : \s)? \Q$errstr//x if $errstr; - chomp $errstr; - $errstr .= "; $eval_error"; - } - else { - $errstr = $eval_error; - } - } - chomp $errstr if $errstr; - - my $flags; - # (XXX if we ever add transaction support then we'll need to take extra - # steps because the commit/rollback would reset Executed before we get here) - $flags |= GOf_RESPONSE_EXECUTED if $dbh && $dbh->{Executed}; - - my $response = DBI::Gofer::Response->new({ - rv => $rv, - err => $err, - errstr => $errstr, - state => $state, - flags => $flags, - }); - - return $response; -} - - -sub execute_request { - my ($self, $request) = @_; - # should never throw an exception - - DBI->trace_msg("-----> execute_request\n"); - - my @warnings; - local $SIG{__WARN__} = sub { - push @warnings, @_; - warn @_ if $local_log; - }; - - my $response = eval { - - if (my $check_request_sub = $self->check_request_sub) { - $request = $check_request_sub->($request, $self) - or die "check_request_sub failed"; - } - - my $version = $request->version || 0; - die ref($request)." version $version is not supported" - if $version < 0.009116 or $version >= 1; - - ($request->is_sth_request) - ? $self->execute_sth_request($request) - : $self->execute_dbh_request($request); - }; - $response ||= $self->new_response_with_err(undef, $@, $current_dbh); - - if (my $check_response_sub = $self->check_response_sub) { - # not protected with an eval so it can choose to throw an exception - my $new = $check_response_sub->($response, $self, $request); - $response = $new if ref $new; - } - - undef $current_dbh; - - $response->warnings(\@warnings) if @warnings; - DBI->trace_msg("<----- execute_request\n"); - return $response; -} - - -sub execute_dbh_request { - my ($self, $request) = @_; - my $stats = $self->{stats}; - - my $dbh; - my $rv_ref = eval { - $dbh = $self->_connect($request); - my $args = $request->dbh_method_call; # [ wantarray, 'method_name', @args ] - my $wantarray = shift @$args; - my $meth = shift @$args; - $stats->{method_calls_dbh}->{$meth}++; - my @rv = ($wantarray) - ? $dbh->$meth(@$args) - : scalar $dbh->$meth(@$args); - \@rv; - } || []; - my $response = $self->new_response_with_err($rv_ref, $@, $dbh); - - return $response if not $dbh; - - # does this request also want any dbh attributes returned? - if (my $dbh_attributes = $request->dbh_attributes) { - $response->dbh_attributes( $self->gather_dbh_attributes($dbh, $dbh_attributes) ); - } - - if ($rv_ref and my $lid_args = $request->dbh_last_insert_id_args) { - $stats->{method_calls_dbh}->{last_insert_id}++; - my $id = $dbh->last_insert_id( @$lid_args ); - $response->last_insert_id( $id ); - } - - if ($rv_ref and UNIVERSAL::isa($rv_ref->[0],'DBI::st')) { - # dbh_method_call was probably a metadata method like table_info - # that returns a statement handle, so turn the $sth into resultset - my $sth = $rv_ref->[0]; - $response->sth_resultsets( $self->gather_sth_resultsets($sth, $request, $response) ); - $response->rv("(sth)"); # don't try to return actual sth - } - - # we're finished with this dbh for this request - $self->reset_dbh($dbh); - - return $response; -} - - -sub gather_dbh_attributes { - my ($self, $dbh, $dbh_attributes) = @_; - my @req_attr_names = @$dbh_attributes; - if ($req_attr_names[0] eq '*') { # auto include std + private - shift @req_attr_names; - push @req_attr_names, @{ $self->_std_response_attribute_names($dbh) }; - } - my %dbh_attr_values; - @dbh_attr_values{@req_attr_names} = $dbh->FETCH_many(@req_attr_names); - - # XXX piggyback installed_methods onto dbh_attributes for now - $dbh_attr_values{dbi_installed_methods} = { DBI->installed_methods }; - - # XXX piggyback default_methods onto dbh_attributes for now - $dbh_attr_values{dbi_default_methods} = _get_default_methods($dbh); - - return \%dbh_attr_values; -} - - -sub _std_response_attribute_names { - my ($self, $h) = @_; - $h = tied(%$h) || $h; # switch to inner handle - - # cache the private_attribute_info data for each handle - # XXX might be better to cache it in the executor - # as it's unlikely to change - # or perhaps at least cache it in the dbh even for sth - # as the sth are typically very short lived - - my ($dbh, $h_type, $driver_name, @attr_names); - - if ($dbh = $h->{Database}) { # is an sth - - # does the dbh already have the answer cached? - return $dbh->{private_gofer_std_attr_names_sth} if $dbh->{private_gofer_std_attr_names_sth}; - - ($h_type, $driver_name) = ('sth', $dbh->{Driver}{Name}); - push @attr_names, qw(NUM_OF_PARAMS NUM_OF_FIELDS NAME TYPE NULLABLE PRECISION SCALE); - } - else { # is a dbh - return $h->{private_gofer_std_attr_names_dbh} if $h->{private_gofer_std_attr_names_dbh}; - - ($h_type, $driver_name, $dbh) = ('dbh', $h->{Driver}{Name}, $h); - # explicitly add these because drivers may have different defaults - # add Name so the client gets the real Name of the connection - push @attr_names, qw(ChopBlanks LongReadLen LongTruncOk ReadOnly Name); - } - - if (my $pai = $h->private_attribute_info) { - push @attr_names, keys %$pai; - } - else { - push @attr_names, @{ $extra_attr{ $driver_name }{$h_type} || []}; - } - if (my $fra = $self->{forced_response_attributes}) { - push @attr_names, @{ $fra->{ $driver_name }{$h_type} || []} - } - $dbh->trace_msg("_std_response_attribute_names for $driver_name $h_type: @attr_names\n"); - - # cache into the dbh even for sth, as the dbh is usually longer lived - return $dbh->{"private_gofer_std_attr_names_$h_type"} = \@attr_names; -} - - -sub execute_sth_request { - my ($self, $request) = @_; - my $dbh; - my $sth; - my $last_insert_id; - my $stats = $self->{stats}; - - my $rv = eval { - $dbh = $self->_connect($request); - - my $args = $request->dbh_method_call; # [ wantarray, 'method_name', @args ] - shift @$args; # discard wantarray - my $meth = shift @$args; - $stats->{method_calls_sth}->{$meth}++; - $sth = $dbh->$meth(@$args); - my $last = '(sth)'; # a true value (don't try to return actual sth) - - # execute methods on the sth, e.g., bind_param & execute - if (my $calls = $request->sth_method_calls) { - for my $meth_call (@$calls) { - my $method = shift @$meth_call; - $stats->{method_calls_sth}->{$method}++; - $last = $sth->$method(@$meth_call); - } - } - - if (my $lid_args = $request->dbh_last_insert_id_args) { - $stats->{method_calls_sth}->{last_insert_id}++; - $last_insert_id = $dbh->last_insert_id( @$lid_args ); - } - - $last; - }; - my $response = $self->new_response_with_err($rv, $@, $dbh); - - return $response if not $dbh; - - $response->last_insert_id( $last_insert_id ) - if defined $last_insert_id; - - # even if the eval failed we still want to try to gather attribute values - # (XXX would be nice to be able to support streaming of results. - # which would reduce memory usage and latency for large results) - if ($sth) { - $response->sth_resultsets( $self->gather_sth_resultsets($sth, $request, $response) ); - $sth->finish; - } - - # does this request also want any dbh attributes returned? - my $dbh_attr_set; - if (my $dbh_attributes = $request->dbh_attributes) { - $dbh_attr_set = $self->gather_dbh_attributes($dbh, $dbh_attributes); - } - # XXX needs to be integrated with private_attribute_info() etc - if (my $dbh_attr = $extra_attr{$dbh->{Driver}{Name}}{dbh_after_sth}) { - @{$dbh_attr_set}{@$dbh_attr} = $dbh->FETCH_many(@$dbh_attr); - } - $response->dbh_attributes($dbh_attr_set) if $dbh_attr_set && %$dbh_attr_set; - - $self->reset_dbh($dbh); - - return $response; -} - - -sub gather_sth_resultsets { - my ($self, $sth, $request, $response) = @_; - my $resultsets = eval { - - my $attr_names = $self->_std_response_attribute_names($sth); - my $sth_attr = {}; - $sth_attr->{$_} = 1 for @$attr_names; - - # let the client add/remove sth attributes - if (my $sth_result_attr = $request->sth_result_attr) { - $sth_attr->{$_} = $sth_result_attr->{$_} - for keys %$sth_result_attr; - } - my @sth_attr = grep { $sth_attr->{$_} } keys %$sth_attr; - - my $row_count = 0; - my $rs_list = []; - while (1) { - my $rs = $self->fetch_result_set($sth, \@sth_attr); - push @$rs_list, $rs; - if (my $rows = $rs->{rowset}) { - $row_count += @$rows; - } - last if $self->{forced_single_resultset}; - last if !($sth->more_results || $sth->{syb_more_results}); - } - - my $stats = $self->{stats}; - $stats->{rows_returned_total} += $row_count; - $stats->{rows_returned_max} = $row_count - if $row_count > ($stats->{rows_returned_max}||0); - - $rs_list; - }; - $response->add_err(1, $@) if $@; - return $resultsets; -} - - -sub fetch_result_set { - my ($self, $sth, $sth_attr) = @_; - my %meta; - eval { - @meta{ @$sth_attr } = $sth->FETCH_many(@$sth_attr); - # we assume @$sth_attr contains NUM_OF_FIELDS - $meta{rowset} = $sth->fetchall_arrayref() - if (($meta{NUM_OF_FIELDS}||0) > 0); # is SELECT - # the fetchall_arrayref may fail with a 'not executed' kind of error - # because gather_sth_resultsets/fetch_result_set are called even if - # execute() failed, or even if there was no execute() call at all. - # The corresponding error goes into the resultset err, not the top-level - # response err, so in most cases this resultset err is never noticed. - }; - if ($@) { - chomp $@; - $meta{err} = $DBI::err || 1; - $meta{errstr} = $DBI::errstr || $@; - $meta{state} = $DBI::state; - } - return \%meta; -} - - -sub _get_default_methods { - my ($dbh) = @_; - # returns a ref to a hash of dbh method names for methods which the driver - # hasn't overridden i.e., quote(). These don't need to be forwarded via gofer. - my $ImplementorClass = $dbh->{ImplementorClass} or die; - my %default_methods; - for my $method (@all_dbh_methods) { - my $dbi_sub = $all_dbh_methods{$method} || 42; - my $imp_sub = $ImplementorClass->can($method) || 42; - next if $imp_sub != $dbi_sub; - #warn("default $method\n"); - $default_methods{$method} = 1; - } - return \%default_methods; -} - - -# XXX would be nice to make this a generic DBI module -sub _install_rand_callbacks { - my ($self, $dbh, $dbi_gofer_random) = @_; - - my $callbacks = $dbh->{Callbacks} || {}; - my $prev = $dbh->{private_gofer_rand_fail_callbacks} || {}; - - # return if we've already setup this handle with callbacks for these specs - return if (($callbacks->{_dbi_gofer_random_spec}||'') eq $dbi_gofer_random); - #warn "$dbh # $callbacks->{_dbi_gofer_random_spec}"; - $callbacks->{_dbi_gofer_random_spec} = $dbi_gofer_random; - - my ($fail_percent, $fail_err, $delay_percent, $delay_duration, %spec_part, @spec_note); - my @specs = split /,/, $dbi_gofer_random; - for my $spec (@specs) { - if ($spec =~ m/^fail=(-?[.\d]+)%?$/) { - $fail_percent = $1; - $spec_part{fail} = $spec; - next; - } - if ($spec =~ m/^err=(-?\d+)$/) { - $fail_err = $1; - $spec_part{err} = $spec; - next; - } - if ($spec =~ m/^delay([.\d]+)=(-?[.\d]+)%?$/) { - $delay_duration = $1; - $delay_percent = $2; - $spec_part{delay} = $spec; - next; - } - elsif ($spec !~ m/^(\w+|\*)$/) { - warn "Ignored DBI_GOFER_RANDOM item '$spec' which isn't a config or a dbh method name"; - next; - } - - my $method = $spec; - if ($callbacks->{$method} && $prev->{$method} && $callbacks->{$method} != $prev->{$method}) { - warn "Callback for $method method already installed so DBI_GOFER_RANDOM callback not installed\n"; - next; - } - unless (defined $fail_percent or defined $delay_percent) { - warn "Ignored DBI_GOFER_RANDOM item '$spec' because not preceded by 'fail=N' and/or 'delayN=N'"; - next; - } - - push @spec_note, join(",", values(%spec_part), $method); - $callbacks->{$method} = $self->_mk_rand_callback($method, $fail_percent, $delay_percent, $delay_duration, $fail_err); - } - warn "DBI_GOFER_RANDOM failures/delays enabled: @spec_note\n" - if @spec_note; - $dbh->{Callbacks} = $callbacks; - $dbh->{private_gofer_rand_fail_callbacks} = $callbacks; -} - -my %_mk_rand_callback_seqn; - -sub _mk_rand_callback { - my ($self, $method, $fail_percent, $delay_percent, $delay_duration, $fail_err) = @_; - my ($fail_modrate, $delay_modrate); - $fail_percent ||= 0; $fail_modrate = int(1/(-$fail_percent )*100) if $fail_percent; - $delay_percent ||= 0; $delay_modrate = int(1/(-$delay_percent)*100) if $delay_percent; - # note that $method may be "*" but that's not recommended or documented or wise - return sub { - my ($h) = @_; - my $seqn = ++$_mk_rand_callback_seqn{$method}; - my $delay = ($delay_percent > 0) ? rand(100) < $delay_percent : - ($delay_percent < 0) ? !($seqn % $delay_modrate): 0; - my $fail = ($fail_percent > 0) ? rand(100) < $fail_percent : - ($fail_percent < 0) ? !($seqn % $fail_modrate) : 0; - #no warnings 'uninitialized'; - #warn "_mk_rand_callback($fail_percent:$fail_modrate, $delay_percent:$delay_modrate): seqn=$seqn fail=$fail delay=$delay"; - if ($delay) { - my $msg = "DBI_GOFER_RANDOM delaying execution of $method() by $delay_duration seconds\n"; - # Note what's happening in a trace message. If the delay percent is an even - # number then use warn() instead so it's sent back to the client. - ($delay_percent % 2 == 1) ? warn($msg) : $h->trace_msg($msg); - select undef, undef, undef, $delay_duration; # allows floating point value - } - if ($fail) { - undef $_; # tell DBI to not call the method - # the "induced by DBI_GOFER_RANDOM" is special and must be included in errstr - # as it's checked for in a few places, such as the gofer retry logic - return $h->set_err($fail_err || $DBI::stderr, - "fake error from $method method induced by DBI_GOFER_RANDOM env var ($fail_percent%)"); - } - return; - } -} - - -sub update_stats { - my ($self, - $request, $response, - $frozen_request, $frozen_response, - $time_received, - $store_meta, $other_meta, - ) = @_; - - # should always have a response object here - carp("No response object provided") unless $request; - - my $stats = $self->{stats}; - $stats->{frozen_request_max_bytes} = length($frozen_request) - if $frozen_request - && length($frozen_request) > ($stats->{frozen_request_max_bytes}||0); - $stats->{frozen_response_max_bytes} = length($frozen_response) - if $frozen_response - && length($frozen_response) > ($stats->{frozen_response_max_bytes}||0); - - my $recent; - if (my $track_recent = $self->{track_recent}) { - $recent = { - request => $frozen_request, - response => $frozen_response, - time_received => $time_received, - duration => dbi_time()-$time_received, - # for any other info - ($store_meta) ? (meta => $store_meta) : (), - }; - $recent->{request_object} = $request - if !$frozen_request && $request; - $recent->{response_object} = $response - if !$frozen_response; - my @queues = ($stats->{recent_requests} ||= []); - push @queues, ($stats->{recent_errors} ||= []) - if !$response or $response->err; - for my $queue (@queues) { - push @$queue, $recent; - shift @$queue if @$queue > $track_recent; - } - } - return $recent; -} - - -1; -__END__ - -=head1 NAME - -DBI::Gofer::Execute - Executes Gofer requests and returns Gofer responses - -=head1 SYNOPSIS - - $executor = DBI::Gofer::Execute->new( { ...config... }); - - $response = $executor->execute_request( $request ); - -=head1 DESCRIPTION - -Accepts a DBI::Gofer::Request object, executes the requested DBI method calls, -and returns a DBI::Gofer::Response object. - -Any error, including any internal 'fatal' errors are caught and converted into -a DBI::Gofer::Response object. - -This module is usually invoked by a 'server-side' Gofer transport module. -They usually have names in the "C" namespace. -Examples include: L and L. - -=head1 CONFIGURATION - -=head2 check_request_sub - -If defined, it must be a reference to a subroutine that will 'check' the request. -It is passed the request object and the executor as its only arguments. - -The subroutine can either return the original request object or die with a -suitable error message (which will be turned into a Gofer response). - -It can also construct and return a new request that should be executed instead -of the original request. - -=head2 check_response_sub - -If defined, it must be a reference to a subroutine that will 'check' the response. -It is passed the response object, the executor, and the request object. -The sub may alter the response object and return undef, or return a new response object. - -This mechanism can be used to, for example, terminate the service if specific -database errors are seen. - -=head2 forced_connect_dsn - -If set, this DSN is always used instead of the one in the request. - -=head2 default_connect_dsn - -If set, this DSN is used if C is not set and the request does not contain a DSN itself. - -=head2 forced_connect_attributes - -A reference to a hash of connect() attributes. Individual attributes in -C will take precedence over corresponding attributes -in the request. - -=head2 default_connect_attributes - -A reference to a hash of connect() attributes. Individual attributes in the -request take precedence over corresponding attributes in C. - -=head2 max_cached_dbh_per_drh - -If set, the loaded drivers will be checked to ensure they don't have more than -this number of cached connections. There is no default value. This limit is not -enforced for every request. - -=head2 max_cached_sth_per_dbh - -If set, all the cached statement handles will be cleared once the number of -cached statement handles rises above this limit. The default is 1000. - -=head2 forced_single_resultset - -If true, then only the first result set will be fetched and returned in the response. - -=head2 forced_response_attributes - -A reference to a data structure that can specify extra attributes to be returned in responses. - - forced_response_attributes => { - DriverName => { - dbh => [ qw(dbh_attrib_name) ], - sth => [ qw(sth_attrib_name) ], - }, - }, - -This can be useful in cases where the driver has not implemented the -private_attribute_info() method and DBI::Gofer::Execute's own fallback list of -private attributes doesn't include the driver or attributes you need. - -=head2 track_recent - -If set, specifies the number of recent requests and responses that should be -kept by the update_stats() method for diagnostics. See L. - -Note that this setting can significantly increase memory use. Use with caution. - -=head2 forced_gofer_random - -Enable forced random failures and/or delays for testing. See L below. - -=head1 DRIVER-SPECIFIC ISSUES - -Gofer needs to know about any driver-private attributes that should have their -values sent back to the client. - -If the driver doesn't support private_attribute_info() method, and very few do, -then the module fallsback to using some hard-coded details, if available, for -the driver being used. Currently hard-coded details are available for the -mysql, Pg, Sybase, and SQLite drivers. - -=head1 TESTING - -DBD::Gofer, DBD::Execute and related packages are well tested by executing the -DBI test suite with DBI_AUTOPROXY configured to route all DBI calls via DBD::Gofer. - -Because Gofer includes timeout and 'retry on error' mechanisms there is a need -for some way to trigger delays and/or errors. This can be done via the -C configuration item, or else the DBI_GOFER_RANDOM environment -variable. - -=head2 DBI_GOFER_RANDOM - -The value of the C configuration item (or else the -DBI_GOFER_RANDOM environment variable) is treated as a series of tokens -separated by commas. - -The tokens can be one of three types: - -=over 4 - -=item fail=R% - -Set the current failure rate to R where R is a percentage. -The value R can be floating point, e.g., C. -Negative values for R have special meaning, see below. - -=item err=N - -Sets the current failure err value to N (instead of the DBI's default 'standard -err value' of 2000000000). This is useful when you want to simulate a -specific error. - -=item delayN=R% - -Set the current random delay rate to R where R is a percentage, and set the -current delay duration to N seconds. The values of R and N can be floating point, -e.g., C. Negative values for R have special meaning, see below. - -If R is an odd number (R % 2 == 1) then a message is logged via warn() which -will be returned to, and echoed at, the client. - -=item methodname - -Applies the current fail, err, and delay values to the named method. -If neither a fail nor delay have been set yet then a warning is generated. - -=back - -For example: - - $executor = DBI::Gofer::Execute->new( { - forced_gofer_random => "fail=0.01%,do,delay60=1%,execute", - }); - -will cause the do() method to fail for 0.01% of calls, and the execute() method to -fail 0.01% of calls and be delayed by 60 seconds on 1% of calls. - -If the percentage value (C) is negative then instead of the failures being -triggered randomly (via the rand() function) they are triggered via a sequence -number. In other words "C" will mean every fifth call will fail. -Each method has a distinct sequence number. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Request.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Request.pm deleted file mode 100644 index 1b64748..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Request.pm +++ /dev/null @@ -1,200 +0,0 @@ -package DBI::Gofer::Request; - -# $Id: Request.pm 12536 2009-02-24 22:37:09Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; - -use DBI qw(neat neat_list); - -use base qw(DBI::Util::_accessor); - -our $VERSION = "0.012537"; - -use constant GOf_REQUEST_IDEMPOTENT => 0x0001; -use constant GOf_REQUEST_READONLY => 0x0002; - -our @EXPORT = qw(GOf_REQUEST_IDEMPOTENT GOf_REQUEST_READONLY); - - -__PACKAGE__->mk_accessors(qw( - version - flags - dbh_connect_call - dbh_method_call - dbh_attributes - dbh_last_insert_id_args - sth_method_calls - sth_result_attr -)); -__PACKAGE__->mk_accessors_using(make_accessor_autoviv_hashref => qw( - meta -)); - - -sub new { - my ($self, $args) = @_; - $args->{version} ||= $VERSION; - return $self->SUPER::new($args); -} - - -sub reset { - my ($self, $flags) = @_; - # remove everything except connect and version - %$self = ( - version => $self->{version}, - dbh_connect_call => $self->{dbh_connect_call}, - ); - $self->{flags} = $flags if $flags; -} - - -sub init_request { - my ($self, $method_and_args, $dbh) = @_; - $self->reset( $dbh->{ReadOnly} ? GOf_REQUEST_READONLY : 0 ); - $self->dbh_method_call($method_and_args); -} - - -sub is_sth_request { - return shift->{sth_result_attr}; -} - - -sub statements { - my $self = shift; - my @statements; - if (my $dbh_method_call = $self->dbh_method_call) { - my $statement_method_regex = qr/^(?:do|prepare)$/; - my (undef, $method, $arg1) = @$dbh_method_call; - push @statements, $arg1 if $method && $method =~ $statement_method_regex; - } - return @statements; -} - - -sub is_idempotent { - my $self = shift; - - if (my $flags = $self->flags) { - return 1 if $flags & (GOf_REQUEST_IDEMPOTENT|GOf_REQUEST_READONLY); - } - - # else check if all statements are SELECT statement that don't include FOR UPDATE - my @statements = $self->statements; - # XXX this is very minimal for now, doesn't even allow comments before the select - # (and can't ever work for "exec stored_procedure_name" kinds of statements) - # XXX it also doesn't deal with multiple statements: prepare("select foo; update bar") - return 1 if @statements == grep { - m/^ \s* SELECT \b /xmsi && !m/ \b FOR \s+ UPDATE \b /xmsi - } @statements; - - return 0; -} - - -sub summary_as_text { - my $self = shift; - my ($context) = @_; - my @s = ''; - - if ($context && %$context) { - my @keys = sort keys %$context; - push @s, join(", ", map { "$_=>".$context->{$_} } @keys); - } - - my ($method, $dsn, $user, $pass, $attr) = @{ $self->dbh_connect_call }; - $method ||= 'connect_cached'; - $pass = '***' if defined $pass; - my $tmp = ''; - if ($attr) { - $tmp = { %{$attr||{}} }; # copy so we can edit - $tmp->{Password} = '***' if exists $tmp->{Password}; - $tmp = "{ ".neat_list([ %$tmp ])." }"; - } - push @s, sprintf "dbh= $method(%s, %s)", neat_list([$dsn, $user, $pass]), $tmp; - - if (my $flags = $self->flags) { - push @s, sprintf "flags: 0x%x", $flags; - } - - if (my $dbh_attr = $self->dbh_attributes) { - push @s, sprintf "dbh->FETCH: %s", @$dbh_attr - if @$dbh_attr; - } - - my ($wantarray, $meth, @args) = @{ $self->dbh_method_call }; - my $args = neat_list(\@args); - $args =~ s/\n+/ /g; - push @s, sprintf "dbh->%s(%s)", $meth, $args; - - if (my $lii_args = $self->dbh_last_insert_id_args) { - push @s, sprintf "dbh->last_insert_id(%s)", neat_list($lii_args); - } - - for my $call (@{ $self->sth_method_calls || [] }) { - my ($meth, @args) = @$call; - ($args = neat_list(\@args)) =~ s/\n+/ /g; - push @s, sprintf "sth->%s(%s)", $meth, $args; - } - - if (my $sth_attr = $self->sth_result_attr) { - push @s, sprintf "sth->FETCH: %s", %$sth_attr - if %$sth_attr; - } - - return join("\n\t", @s) . "\n"; -} - - -sub outline_as_text { # one-line version of summary_as_text - my $self = shift; - my @s = ''; - my $neatlen = 80; - - if (my $flags = $self->flags) { - push @s, sprintf "flags=0x%x", $flags; - } - - my (undef, $meth, @args) = @{ $self->dbh_method_call }; - push @s, sprintf "%s(%s)", $meth, neat_list(\@args, $neatlen); - - for my $call (@{ $self->sth_method_calls || [] }) { - my ($meth, @args) = @$call; - push @s, sprintf "%s(%s)", $meth, neat_list(\@args, $neatlen); - } - - my ($method, $dsn) = @{ $self->dbh_connect_call }; - push @s, "$method($dsn,...)"; # dsn last as it's usually less interesting - - (my $outline = join("; ", @s)) =~ s/\s+/ /g; # squish whitespace, incl newlines - return $outline; -} - -1; - -=head1 NAME - -DBI::Gofer::Request - Encapsulate a request from DBD::Gofer to DBI::Gofer::Execute - -=head1 DESCRIPTION - -This is an internal class. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Response.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Response.pm deleted file mode 100644 index 24915b6..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Response.pm +++ /dev/null @@ -1,218 +0,0 @@ -package DBI::Gofer::Response; - -# $Id: Response.pm 11565 2008-07-22 20:17:33Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; - -use Carp; -use DBI qw(neat neat_list); - -use base qw(DBI::Util::_accessor Exporter); - -our $VERSION = "0.011566"; - -use constant GOf_RESPONSE_EXECUTED => 0x0001; - -our @EXPORT = qw(GOf_RESPONSE_EXECUTED); - - -__PACKAGE__->mk_accessors(qw( - version - rv - err - errstr - state - flags - last_insert_id - dbh_attributes - sth_resultsets - warnings -)); -__PACKAGE__->mk_accessors_using(make_accessor_autoviv_hashref => qw( - meta -)); - - -sub new { - my ($self, $args) = @_; - $args->{version} ||= $VERSION; - chomp $args->{errstr} if $args->{errstr}; - return $self->SUPER::new($args); -} - - -sub err_errstr_state { - my $self = shift; - return @{$self}{qw(err errstr state)}; -} - -sub executed_flag_set { - my $flags = shift->flags - or return 0; - return $flags & GOf_RESPONSE_EXECUTED; -} - - -sub add_err { - my ($self, $err, $errstr, $state, $trace) = @_; - - # acts like the DBI's set_err method. - # this code copied from DBI::PurePerl's set_err method. - - chomp $errstr if $errstr; - $state ||= ''; - carp ref($self)."->add_err($err, $errstr, $state)" - if $trace and defined($err) || $errstr; - - my ($r_err, $r_errstr, $r_state) = ($self->{err}, $self->{errstr}, $self->{state}); - - if ($r_errstr) { - $r_errstr .= sprintf " [err was %s now %s]", $r_err, $err - if $r_err && $err && $r_err ne $err; - $r_errstr .= sprintf " [state was %s now %s]", $r_state, $state - if $r_state and $r_state ne "S1000" && $state && $r_state ne $state; - $r_errstr .= "\n$errstr" if $r_errstr ne $errstr; - } - else { - $r_errstr = $errstr; - } - - # assign if higher priority: err > "0" > "" > undef - my $err_changed; - if ($err # new error: so assign - or !defined $r_err # no existing warn/info: so assign - # new warn ("0" len 1) > info ("" len 0): so assign - or defined $err && length($err) > length($r_err) - ) { - $r_err = $err; - ++$err_changed; - } - - $r_state = ($state eq "00000") ? "" : $state - if $state && $err_changed; - - ($self->{err}, $self->{errstr}, $self->{state}) = ($r_err, $r_errstr, $r_state); - - return undef; -} - - -sub summary_as_text { - my $self = shift; - my ($context) = @_; - - my ($rv, $err, $errstr, $state) = ($self->{rv}, $self->{err}, $self->{errstr}, $self->{state}); - - my @s = sprintf("\trv=%s", (ref $rv) ? "[".neat_list($rv)."]" : neat($rv)); - $s[-1] .= sprintf(", err=%s, errstr=%s", $err, neat($errstr)) - if defined $err; - $s[-1] .= sprintf(", flags=0x%x", $self->{flags}) - if defined $self->{flags}; - - push @s, "last_insert_id=%s", $self->last_insert_id - if defined $self->last_insert_id; - - if (my $dbh_attr = $self->dbh_attributes) { - my @keys = sort keys %$dbh_attr; - push @s, sprintf "dbh= { %s }", join(", ", map { "$_=>".neat($dbh_attr->{$_},100) } @keys) - if @keys; - } - - for my $rs (@{$self->sth_resultsets || []}) { - my ($rowset, $err, $errstr, $state) - = @{$rs}{qw(rowset err errstr state)}; - my $summary = "rowset: "; - my $NUM_OF_FIELDS = $rs->{NUM_OF_FIELDS} || 0; - my $rows = $rowset ? @$rowset : 0; - if ($rowset || $NUM_OF_FIELDS > 0) { - $summary .= sprintf "%d rows, %d columns", $rows, $NUM_OF_FIELDS; - } - $summary .= sprintf ", err=%s, errstr=%s", $err, neat($errstr) if defined $err; - if ($rows) { - my $NAME = $rs->{NAME}; - # generate - my @colinfo = map { "$NAME->[$_]=".neat($rowset->[0][$_], 30) } 0..@{$NAME}-1; - $summary .= sprintf " [%s]", join ", ", @colinfo; - $summary .= ",..." if $rows > 1; - # we can be a little more helpful for Sybase/MSSQL user - $summary .= " syb_result_type=$rs->{syb_result_type}" - if $rs->{syb_result_type} and $rs->{syb_result_type} != 4040; - } - push @s, $summary; - } - for my $w (@{$self->warnings || []}) { - chomp $w; - push @s, "warning: $w"; - } - if ($context && %$context) { - my @keys = sort keys %$context; - push @s, join(", ", map { "$_=>".$context->{$_} } @keys); - } - return join("\n\t", @s). "\n"; -} - - -sub outline_as_text { # one-line version of summary_as_text - my $self = shift; - my ($context) = @_; - - my ($rv, $err, $errstr, $state) = ($self->{rv}, $self->{err}, $self->{errstr}, $self->{state}); - - my $s = sprintf("rv=%s", (ref $rv) ? "[".neat_list($rv)."]" : neat($rv)); - $s .= sprintf(", err=%s %s", $err, neat($errstr)) - if defined $err; - $s .= sprintf(", flags=0x%x", $self->{flags}) - if $self->{flags}; - - if (my $sth_resultsets = $self->sth_resultsets) { - $s .= sprintf(", %d resultsets ", scalar @$sth_resultsets); - - my @rs; - for my $rs (@{$self->sth_resultsets || []}) { - my $summary = ""; - my ($rowset, $err, $errstr) - = @{$rs}{qw(rowset err errstr)}; - my $NUM_OF_FIELDS = $rs->{NUM_OF_FIELDS} || 0; - my $rows = $rowset ? @$rowset : 0; - if ($rowset || $NUM_OF_FIELDS > 0) { - $summary .= sprintf "%dr x %dc", $rows, $NUM_OF_FIELDS; - } - $summary .= sprintf "%serr %s %s", ($summary?", ":""), $err, neat($errstr) - if defined $err; - push @rs, $summary; - } - $s .= join "; ", map { "[$_]" } @rs; - } - - return $s; -} - - -1; - -=head1 NAME - -DBI::Gofer::Response - Encapsulate a response from DBI::Gofer::Execute to DBD::Gofer - -=head1 DESCRIPTION - -This is an internal class. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/Base.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/Base.pm deleted file mode 100644 index 84f4fdc..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/Base.pm +++ /dev/null @@ -1,64 +0,0 @@ -package DBI::Gofer::Serializer::Base; - -# $Id: Base.pm 9949 2007-09-18 09:38:15Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -=head1 NAME - -DBI::Gofer::Serializer::Base - base class for Gofer serialization - -=head1 SYNOPSIS - - $serializer = $serializer_class->new(); - - $string = $serializer->serialize( $data ); - ($string, $deserializer_class) = $serializer->serialize( $data ); - - $data = $serializer->deserialize( $string ); - -=head1 DESCRIPTION - -DBI::Gofer::Serializer::* classes implement a very minimal subset of the L API. - -Gofer serializers are expected to be very fast and are not required to deal -with anything other than non-blessed references to arrays and hashes, and plain scalars. - -=cut - - -use strict; -use warnings; - -use Carp qw(croak); - -our $VERSION = "0.009950"; - - -sub new { - my $class = shift; - my $deserializer_class = $class->deserializer_class; - return bless { deserializer_class => $deserializer_class } => $class; -} - -sub deserializer_class { - my $self = shift; - my $class = ref($self) || $self; - $class =~ s/^DBI::Gofer::Serializer:://; - return $class; -} - -sub serialize { - my $self = shift; - croak ref($self)." has not implemented the serialize method"; -} - -sub deserialize { - my $self = shift; - croak ref($self)." has not implemented the deserialize method"; -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/DataDumper.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/DataDumper.pm deleted file mode 100644 index f374196..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/DataDumper.pm +++ /dev/null @@ -1,53 +0,0 @@ -package DBI::Gofer::Serializer::DataDumper; - -use strict; -use warnings; - -our $VERSION = "0.009950"; - -# $Id: DataDumper.pm 9949 2007-09-18 09:38:15Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -=head1 NAME - -DBI::Gofer::Serializer::DataDumper - Gofer serialization using DataDumper - -=head1 SYNOPSIS - - $serializer = DBI::Gofer::Serializer::DataDumper->new(); - - $string = $serializer->serialize( $data ); - -=head1 DESCRIPTION - -Uses DataDumper to serialize. Deserialization is not supported. -The output of this class is only meant for human consumption. - -See also L. - -=cut - -use Data::Dumper; - -use base qw(DBI::Gofer::Serializer::Base); - - -sub serialize { - my $self = shift; - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Terse = 1; - local $Data::Dumper::Useqq = 0; # enabling this disables xs - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - local $Data::Dumper::Deparse = 0; - local $Data::Dumper::Purity = 0; - my $frozen = Data::Dumper::Dumper(shift); - return $frozen unless wantarray; - return ($frozen, $self->{deserializer_class}); -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/Storable.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/Storable.pm deleted file mode 100644 index 9d03de0..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Serializer/Storable.pm +++ /dev/null @@ -1,60 +0,0 @@ -package DBI::Gofer::Serializer::Storable; - -use strict; -use warnings; - -use base qw(DBI::Gofer::Serializer::Base); - -# $Id: Storable.pm 15585 2013-03-22 20:31:22Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -=head1 NAME - -DBI::Gofer::Serializer::Storable - Gofer serialization using Storable - -=head1 SYNOPSIS - - $serializer = DBI::Gofer::Serializer::Storable->new(); - - $string = $serializer->serialize( $data ); - ($string, $deserializer_class) = $serializer->serialize( $data ); - - $data = $serializer->deserialize( $string ); - -=head1 DESCRIPTION - -Uses Storable::nfreeze() to serialize and Storable::thaw() to deserialize. - -The serialize() method sets local $Storable::forgive_me = 1; so it doesn't -croak if it encounters any data types that can't be serialized, such as code refs. - -See also L. - -=cut - -use Storable qw(nfreeze thaw); - -our $VERSION = "0.015586"; - -use base qw(DBI::Gofer::Serializer::Base); - - -sub serialize { - my $self = shift; - local $Storable::forgive_me = 1; # for CODE refs etc - local $Storable::canonical = 1; # for go_cache - my $frozen = nfreeze(shift); - return $frozen unless wantarray; - return ($frozen, $self->{deserializer_class}); -} - -sub deserialize { - my $self = shift; - return thaw(shift); -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/Base.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/Base.pm deleted file mode 100644 index 08a5f3b..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/Base.pm +++ /dev/null @@ -1,174 +0,0 @@ -package DBI::Gofer::Transport::Base; - -# $Id: Base.pm 12536 2009-02-24 22:37:09Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use DBI; - -use base qw(DBI::Util::_accessor); - -use DBI::Gofer::Serializer::Storable; -use DBI::Gofer::Serializer::DataDumper; - -our $VERSION = "0.012537"; - -__PACKAGE__->mk_accessors(qw( - trace - keep_meta_frozen - serializer_obj -)); - - -# see also $ENV{DBI_GOFER_TRACE} in DBI::Gofer::Execute -sub _init_trace { (split(/=/,$ENV{DBI_GOFER_TRACE}||0))[0] } - - -sub new { - my ($class, $args) = @_; - $args->{trace} ||= $class->_init_trace; - $args->{serializer_obj} ||= DBI::Gofer::Serializer::Storable->new(); - my $self = bless {}, $class; - $self->$_( $args->{$_} ) for keys %$args; - $self->trace_msg("$class->new({ @{[ %$args ]} })\n") if $self->trace; - return $self; -} - -my $packet_header_text = "GoFER1:"; -my $packet_header_regex = qr/^GoFER(\d+):/; - - -sub _freeze_data { - my ($self, $data, $serializer, $skip_trace) = @_; - my $frozen = eval { - $self->_dump("freezing $self->{trace} ".ref($data), $data) - if !$skip_trace and $self->trace; - - local $data->{meta}; # don't include meta in serialization - $serializer ||= $self->{serializer_obj}; - my ($data, $deserializer_class) = $serializer->serialize($data); - - $packet_header_text . $data; - }; - if ($@) { - chomp $@; - die "Error freezing ".ref($data)." object: $@"; - } - - # stash the frozen data into the data structure itself - # to make life easy for the client caching code in DBD::Gofer::Transport::Base - $data->{meta}{frozen} = $frozen if $self->keep_meta_frozen; - - return $frozen; -} -# public aliases used by subclasses -*freeze_request = \&_freeze_data; -*freeze_response = \&_freeze_data; - - -sub _thaw_data { - my ($self, $frozen_data, $serializer, $skip_trace) = @_; - my $data; - eval { - # check for and extract our gofer header and the info it contains - (my $frozen = $frozen_data) =~ s/$packet_header_regex//o - or die "does not have gofer header\n"; - my ($t_version) = $1; - $serializer ||= $self->{serializer_obj}; - $data = $serializer->deserialize($frozen); - die ref($serializer)."->deserialize didn't return a reference" - unless ref $data; - $data->{_transport}{version} = $t_version; - - $data->{meta}{frozen} = $frozen_data if $self->keep_meta_frozen; - }; - if ($@) { - chomp(my $err = $@); - # remove extra noise from Storable - $err =~ s{ at \S+?/Storable.pm \(autosplit into \S+?/Storable/thaw.al\) line \d+(, \S+ line \d+)?}{}; - my $msg = sprintf "Error thawing: %s (data=%s)", $err, DBI::neat($frozen_data,50); - Carp::cluck("$msg, pid $$ stack trace follows:"); # XXX if $self->trace; - die $msg; - } - $self->_dump("thawing $self->{trace} ".ref($data), $data) - if !$skip_trace and $self->trace; - - return $data; -} -# public aliases used by subclasses -*thaw_request = \&_thaw_data; -*thaw_response = \&_thaw_data; - - -# this should probably live in the request and response classes -# and the tace level passed in -sub _dump { - my ($self, $label, $data) = @_; - - # don't dump the binary - local $data->{meta}{frozen} if $data->{meta} && $data->{meta}{frozen}; - - my $trace_level = $self->trace; - my $summary; - if ($trace_level >= 4) { - require Data::Dumper; - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Terse = 1; - local $Data::Dumper::Useqq = 0; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - local $Data::Dumper::Deparse = 0; - local $Data::Dumper::Purity = 0; - $summary = Data::Dumper::Dumper($data); - } - elsif ($trace_level >= 2) { - $summary = eval { $data->summary_as_text } || $@ || "no summary available\n"; - } - else { - $summary = eval { $data->outline_as_text."\n" } || $@ || "no summary available\n"; - } - $self->trace_msg("$label: $summary"); -} - - -sub trace_msg { - my ($self, $msg, $min_level) = @_; - $min_level = 1 unless defined $min_level; - # transport trace level can override DBI's trace level - $min_level = 0 if $self->trace >= $min_level; - return DBI->trace_msg("gofer ".$msg, $min_level); -} - -1; - -=head1 NAME - -DBI::Gofer::Transport::Base - Base class for Gofer transports - -=head1 DESCRIPTION - -This is the base class for server-side Gofer transports. - -It's also the base class for the client-side base class L. - -This is an internal class. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/pipeone.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/pipeone.pm deleted file mode 100644 index 0d6985e..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/pipeone.pm +++ /dev/null @@ -1,64 +0,0 @@ -package DBI::Gofer::Transport::pipeone; - -# $Id: pipeone.pm 12536 2009-02-24 22:37:09Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use DBI::Gofer::Execute; - -use base qw(DBI::Gofer::Transport::Base Exporter); - -our $VERSION = "0.012537"; - -our @EXPORT = qw(run_one_stdio); - -my $executor = DBI::Gofer::Execute->new(); - -sub run_one_stdio { - - binmode STDIN; - binmode STDOUT; - - my $transport = DBI::Gofer::Transport::pipeone->new(); - - my $frozen_request = do { local $/; }; - - my $response = $executor->execute_request( $transport->thaw_request($frozen_request) ); - - my $frozen_response = $transport->freeze_response($response); - - print $frozen_response; - - # no point calling $executor->update_stats(...) for pipeONE -} - -1; -__END__ - -=head1 NAME - -DBI::Gofer::Transport::pipeone - DBD::Gofer server-side transport for pipeone - -=head1 SYNOPSIS - -See L. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/stream.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/stream.pm deleted file mode 100644 index 24b0ba6..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Gofer/Transport/stream.pm +++ /dev/null @@ -1,76 +0,0 @@ -package DBI::Gofer::Transport::stream; - -# $Id: stream.pm 12536 2009-02-24 22:37:09Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use DBI qw(dbi_time); -use DBI::Gofer::Execute; - -use base qw(DBI::Gofer::Transport::pipeone Exporter); - -our $VERSION = "0.012537"; - -our @EXPORT = qw(run_stdio_hex); - -my $executor = DBI::Gofer::Execute->new(); - -sub run_stdio_hex { - - my $transport = DBI::Gofer::Transport::stream->new(); - local $| = 1; - - DBI->trace_msg("$0 started (pid $$)\n"); - - local $\; # OUTPUT_RECORD_SEPARATOR - local $/ = "\012"; # INPUT_RECORD_SEPARATOR - while ( defined( my $encoded_request = ) ) { - my $time_received = dbi_time(); - $encoded_request =~ s/\015?\012$//; - - my $frozen_request = pack "H*", $encoded_request; - my $request = $transport->thaw_request( $frozen_request ); - - my $response = $executor->execute_request( $request ); - - my $frozen_response = $transport->freeze_response($response); - my $encoded_response = unpack "H*", $frozen_response; - - print $encoded_response, "\015\012"; # autoflushed due to $|=1 - - # there's no way to access the stats currently - # so this just serves as a basic test and illustration of update_stats() - $executor->update_stats($request, $response, $frozen_request, $frozen_response, $time_received, 1); - } - DBI->trace_msg("$0 ending (pid $$)\n"); -} - -1; -__END__ - -=head1 NAME - -DBI::Gofer::Transport::stream - DBD::Gofer server-side transport for stream - -=head1 SYNOPSIS - -See L. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Profile.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Profile.pm deleted file mode 100644 index f2cc886..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Profile.pm +++ /dev/null @@ -1,954 +0,0 @@ -package DBI::Profile; - -=head1 NAME - -DBI::Profile - Performance profiling and benchmarking for the DBI - -=head1 SYNOPSIS - -The easiest way to enable DBI profiling is to set the DBI_PROFILE -environment variable to 2 and then run your code as usual: - - DBI_PROFILE=2 prog.pl - -This will profile your program and then output a textual summary -grouped by query when the program exits. You can also enable profiling by -setting the Profile attribute of any DBI handle: - - $dbh->{Profile} = 2; - -Then the summary will be printed when the handle is destroyed. - -Many other values apart from are possible - see L<"ENABLING A PROFILE"> below. - -=head1 DESCRIPTION - -The DBI::Profile module provides a simple interface to collect and -report performance and benchmarking data from the DBI. - -For a more elaborate interface, suitable for larger programs, see -L and L. -For Apache/mod_perl applications see -L. - -=head1 OVERVIEW - -Performance data collection for the DBI is built around several -concepts which are important to understand clearly. - -=over 4 - -=item Method Dispatch - -Every method call on a DBI handle passes through a single 'dispatch' -function which manages all the common aspects of DBI method calls, -such as handling the RaiseError attribute. - -=item Data Collection - -If profiling is enabled for a handle then the dispatch code takes -a high-resolution timestamp soon after it is entered. Then, after -calling the appropriate method and just before returning, it takes -another high-resolution timestamp and calls a function to record -the information. That function is passed the two timestamps -plus the DBI handle and the name of the method that was called. -That data about a single DBI method call is called a I. - -=item Data Filtering - -If the method call was invoked by the DBI or by a driver then the call is -ignored for profiling because the time spent will be accounted for by the -original 'outermost' call for your code. - -For example, the calls that the selectrow_arrayref() method makes -to prepare() and execute() etc. are not counted individually -because the time spent in those methods is going to be allocated -to the selectrow_arrayref() method when it returns. If this was not -done then it would be very easy to double count time spent inside -the DBI. - -=item Data Storage Tree - -The profile data is accumulated as 'leaves on a tree'. The 'path' through the -branches of the tree to a particular leaf is determined dynamically for each sample. -This is a key feature of DBI profiling. - -For each profiled method call the DBI walks along the Path and uses each value -in the Path to step into and grow the Data tree. - -For example, if the Path is - - [ 'foo', 'bar', 'baz' ] - -then the new profile sample data will be I into the tree at - - $h->{Profile}->{Data}->{foo}->{bar}->{baz} - -But it's not very useful to merge all the call data into one leaf node (except -to get an overall 'time spent inside the DBI' total). It's more common to want -the Path to include dynamic values such as the current statement text and/or -the name of the method called to show what the time spent inside the DBI was for. - -The Path can contain some 'magic cookie' values that are automatically replaced -by corresponding dynamic values when they're used. These magic cookies always -start with a punctuation character. - -For example a value of 'C' in the Path causes the corresponding -entry in the Data to be the name of the method that was called. -For example, if the Path was: - - [ 'foo', '!MethodName', 'bar' ] - -and the selectall_arrayref() method was called, then the profile sample data -for that call will be merged into the tree at: - - $h->{Profile}->{Data}->{foo}->{selectall_arrayref}->{bar} - -=item Profile Data - -Profile data is stored at the 'leaves' of the tree as references -to an array of numeric values. For example: - - [ - 106, # 0: count of samples at this node - 0.0312958955764771, # 1: total duration - 0.000490069389343262, # 2: first duration - 0.000176072120666504, # 3: shortest duration - 0.00140702724456787, # 4: longest duration - 1023115819.83019, # 5: time of first sample - 1023115819.86576, # 6: time of last sample - ] - -After the first sample, later samples always update elements 0, 1, and 6, and -may update 3 or 4 depending on the duration of the sampled call. - -=back - -=head1 ENABLING A PROFILE - -Profiling is enabled for a handle by assigning to the Profile -attribute. For example: - - $h->{Profile} = DBI::Profile->new(); - -The Profile attribute holds a blessed reference to a hash object -that contains the profile data and attributes relating to it. - -The class the Profile object is blessed into is expected to -provide at least a DESTROY method which will dump the profile data -to the DBI trace file handle (STDERR by default). - -All these examples have the same effect as each other: - - $h->{Profile} = 0; - $h->{Profile} = "/DBI::Profile"; - $h->{Profile} = DBI::Profile->new(); - $h->{Profile} = {}; - $h->{Profile} = { Path => [] }; - -Similarly, these examples have the same effect as each other: - - $h->{Profile} = 6; - $h->{Profile} = "6/DBI::Profile"; - $h->{Profile} = "!Statement:!MethodName/DBI::Profile"; - $h->{Profile} = { Path => [ '!Statement', '!MethodName' ] }; - -If a non-blessed hash reference is given then the DBI::Profile -module is automatically C'd and the reference is blessed -into that class. - -If a string is given then it is processed like this: - - ($path, $module, $args) = split /\//, $string, 3 - - @path = split /:/, $path - @args = split /:/, $args - - eval "require $module" if $module - $module ||= "DBI::Profile" - - $module->new( Path => \@Path, @args ) - -So the first value is used to select the Path to be used (see below). -The second value, if present, is used as the name of a module which -will be loaded and it's C method called. If not present it -defaults to DBI::Profile. Any other values are passed as arguments -to the C method. For example: "C<2/DBIx::OtherProfile/Foo:42>". - -Numbers can be used as a shorthand way to enable common Path values. -The simplest way to explain how the values are interpreted is to show the code: - - push @Path, "DBI" if $path_elem & 0x01; - push @Path, "!Statement" if $path_elem & 0x02; - push @Path, "!MethodName" if $path_elem & 0x04; - push @Path, "!MethodClass" if $path_elem & 0x08; - push @Path, "!Caller2" if $path_elem & 0x10; - -So "2" is the same as "!Statement" and "6" (2+4) is the same as -"!Statement:!Method". Those are the two most commonly used values. Using a -negative number will reverse the path. Thus "-6" will group by method name then -statement. - -The splitting and parsing of string values assigned to the Profile -attribute may seem a little odd, but there's a good reason for it. -Remember that attributes can be embedded in the Data Source Name -string which can be passed in to a script as a parameter. For -example: - - dbi:DriverName(Profile=>2):dbname - dbi:DriverName(Profile=>{Username}:!Statement/MyProfiler/Foo:42):dbname - -And also, if the C environment variable is set then -The DBI arranges for every driver handle to share the same profile -object. When perl exits a single profile summary will be generated -that reflects (as nearly as practical) the total use of the DBI by -the application. - - -=head1 THE PROFILE OBJECT - -The DBI core expects the Profile attribute value to be a hash -reference and if the following values don't exist it will create -them as needed: - -=head2 Data - -A reference to a hash containing the collected profile data. - -=head2 Path - -The Path value is a reference to an array. Each element controls the -value to use at the corresponding level of the profile Data tree. - -If the value of Path is anything other than an array reference, -it is treated as if it was: - - [ '!Statement' ] - -The elements of Path array can be one of the following types: - -=head3 Special Constant - -B - -Use the current Statement text. Typically that's the value of the Statement -attribute for the handle the method was called with. Some methods, like -commit() and rollback(), are unrelated to a particular statement. For those -methods !Statement records an empty string. - -For statement handles this is always simply the string that was -given to prepare() when the handle was created. For database handles -this is the statement that was last prepared or executed on that -database handle. That can lead to a little 'fuzzyness' because, for -example, calls to the quote() method to build a new statement will -typically be associated with the previous statement. In practice -this isn't a significant issue and the dynamic Path mechanism can -be used to setup your own rules. - -B - -Use the name of the DBI method that the profile sample relates to. - -B - -Use the fully qualified name of the DBI method, including -the package, that the profile sample relates to. This shows you -where the method was implemented. For example: - - 'DBD::_::db::selectrow_arrayref' => - 0.022902s - 'DBD::mysql::db::selectrow_arrayref' => - 2.244521s / 99 = 0.022445s avg (first 0.022813s, min 0.022051s, max 0.028932s) - -The "DBD::_::db::selectrow_arrayref" shows that the driver has -inherited the selectrow_arrayref method provided by the DBI. - -But you'll note that there is only one call to -DBD::_::db::selectrow_arrayref but another 99 to -DBD::mysql::db::selectrow_arrayref. Currently the first -call doesn't record the true location. That may change. - -B - -Use a string showing the filename and line number of the code calling the method. - -B - -Use a string showing the filename and line number of the code calling the -method, as for !Caller, but also include filename and line number of the code -that called that. Calls from DBI:: and DBD:: packages are skipped. - -B - -Same as !Caller above except that only the filename is included, not the line number. - -B - -Same as !Caller2 above except that only the filenames are included, not the line number. - -B - -Use the current value of time(). Rarely used. See the more useful C below. - -B - -Where C is an integer. Use the current value of time() but with reduced precision. -The value used is determined in this way: - - int( time() / N ) * N - -This is a useful way to segregate a profile into time slots. For example: - - [ '!Time~60', '!Statement' ] - -=head3 Code Reference - -The subroutine is passed the handle it was called on and the DBI method name. -The current Statement is in $_. The statement string should not be modified, -so most subs start with C. - -The list of values it returns is used at that point in the Profile Path. -Any undefined values are treated as the string "C". - -The sub can 'veto' (reject) a profile sample by including a reference to undef -(C<\undef>) in the returned list. That can be useful when you want to only profile -statements that match a certain pattern, or only profile certain methods. - -=head3 Subroutine Specifier - -A Path element that begins with 'C<&>' is treated as the name of a subroutine -in the DBI::ProfileSubs namespace and replaced with the corresponding code reference. - -Currently this only works when the Path is specified by the C -environment variable. - -Also, currently, the only subroutine in the DBI::ProfileSubs namespace is -C<'&norm_std_n3'>. That's a very handy subroutine when profiling code that -doesn't use placeholders. See L for more information. - -=head3 Attribute Specifier - -A string enclosed in braces, such as 'C<{Username}>', specifies that the current -value of the corresponding database handle attribute should be used at that -point in the Path. - -=head3 Reference to a Scalar - -Specifies that the current value of the referenced scalar be used at that point -in the Path. This provides an efficient way to get 'contextual' values into -your profile. - -=head3 Other Values - -Any other values are stringified and used literally. - -(References, and values that begin with punctuation characters are reserved.) - - -=head1 REPORTING - -=head2 Report Format - -The current accumulated profile data can be formatted and output using - - print $h->{Profile}->format; - -To discard the profile data and start collecting fresh data -you can do: - - $h->{Profile}->{Data} = undef; - - -The default results format looks like this: - - DBI::Profile: 0.001015s 42.7% (5 calls) programname @ YYYY-MM-DD HH:MM:SS - '' => - 0.000024s / 2 = 0.000012s avg (first 0.000015s, min 0.000009s, max 0.000015s) - 'SELECT mode,size,name FROM table' => - 0.000991s / 3 = 0.000330s avg (first 0.000678s, min 0.000009s, max 0.000678s) - -Which shows the total time spent inside the DBI, with a count of -the total number of method calls and the name of the script being -run, then a formatted version of the profile data tree. - -If the results are being formatted when the perl process is exiting -(which is usually the case when the DBI_PROFILE environment variable -is used) then the percentage of time the process spent inside the -DBI is also shown. If the process is not exiting then the percentage is -calculated using the time between the first and last call to the DBI. - -In the example above the paths in the tree are only one level deep and -use the Statement text as the value (that's the default behaviour). - -The merged profile data at the 'leaves' of the tree are presented -as total time spent, count, average time spent (which is simply total -time divided by the count), then the time spent on the first call, -the time spent on the fastest call, and finally the time spent on -the slowest call. - -The 'avg', 'first', 'min' and 'max' times are not particularly -useful when the profile data path only contains the statement text. -Here's an extract of a more detailed example using both statement -text and method name in the path: - - 'SELECT mode,size,name FROM table' => - 'FETCH' => - 0.000076s - 'fetchrow_hashref' => - 0.036203s / 108 = 0.000335s avg (first 0.000490s, min 0.000152s, max 0.002786s) - -Here you can see the 'avg', 'first', 'min' and 'max' for the -108 calls to fetchrow_hashref() become rather more interesting. -Also the data for FETCH just shows a time value because it was only -called once. - -Currently the profile data is output sorted by branch names. That -may change in a later version so the leaf nodes are sorted by total -time per leaf node. - - -=head2 Report Destination - -The default method of reporting is for the DESTROY method of the -Profile object to format the results and write them using: - - DBI->trace_msg($results, 0); # see $ON_DESTROY_DUMP below - -to write them to the DBI trace() filehandle (which defaults to -STDERR). To direct the DBI trace filehandle to write to a file -without enabling tracing the trace() method can be called with a -trace level of 0. For example: - - DBI->trace(0, $filename); - -The same effect can be achieved without changing the code by -setting the C environment variable to C<0=filename>. - -The $DBI::Profile::ON_DESTROY_DUMP variable holds a code ref -that's called to perform the output of the formatted results. -The default value is: - - $ON_DESTROY_DUMP = sub { DBI->trace_msg($results, 0) }; - -Apart from making it easy to send the dump elsewhere, it can also -be useful as a simple way to disable dumping results. - -=head1 CHILD HANDLES - -Child handles inherit a reference to the Profile attribute value -of their parent. So if profiling is enabled for a database handle -then by default the statement handles created from it all contribute -to the same merged profile data tree. - - -=head1 PROFILE OBJECT METHODS - -=head2 format - -See L. - -=head2 as_node_path_list - - @ary = $dbh->{Profile}->as_node_path_list(); - @ary = $dbh->{Profile}->as_node_path_list($node, $path); - -Returns the collected data ($dbh->{Profile}{Data}) restructured into a list of -array refs, one for each leaf node in the Data tree. This 'flat' structure is -often much simpler for applications to work with. - -The first element of each array ref is a reference to the leaf node. -The remaining elements are the 'path' through the data tree to that node. - -For example, given a data tree like this: - - {key1a}{key2a}[node1] - {key1a}{key2b}[node2] - {key1b}{key2a}{key3a}[node3] - -The as_node_path_list() method will return this list: - - [ [node1], 'key1a', 'key2a' ] - [ [node2], 'key1a', 'key2b' ] - [ [node3], 'key1b', 'key2a', 'key3a' ] - -The nodes are ordered by key, depth-first. - -The $node argument can be used to focus on a sub-tree. -If not specified it defaults to $dbh->{Profile}{Data}. - -The $path argument can be used to specify a list of path elements that will be -added to each element of the returned list. If not specified it defaults to a -ref to an empty array. - -=head2 as_text - - @txt = $dbh->{Profile}->as_text(); - $txt = $dbh->{Profile}->as_text({ - node => undef, - path => [], - separator => " > ", - format => '%1$s: %11$fs / %10$d = %2$fs avg (first %12$fs, min %13$fs, max %14$fs)'."\n"; - sortsub => sub { ... }, - ); - -Returns the collected data ($dbh->{Profile}{Data}) reformatted into a list of formatted strings. -In scalar context the list is returned as a single concatenated string. - -A hashref can be used to pass in arguments, the default values are shown in the example above. - -The C and arguments are passed to as_node_path_list(). - -The C argument is used to join the elements of the path for each leaf node. - -The C argument is used to pass in a ref to a sub that will order the list. -The subroutine will be passed a reference to the array returned by -as_node_path_list() and should sort the contents of the array in place. -The return value from the sub is ignored. For example, to sort the nodes by the -second level key you could use: - - sortsub => sub { my $ary=shift; @$ary = sort { $a->[2] cmp $b->[2] } @$ary } - -The C argument is a C format string that specifies the format -to use for each leaf node. It uses the explicit format parameter index -mechanism to specify which of the arguments should appear where in the string. -The arguments to sprintf are: - - 1: path to node, joined with the separator - 2: average duration (total duration/count) - (3 thru 9 are currently unused) - 10: count - 11: total duration - 12: first duration - 13: smallest duration - 14: largest duration - 15: time of first call - 16: time of first call - -=head1 CUSTOM DATA MANIPULATION - -Recall that C<< $h->{Profile}->{Data} >> is a reference to the collected data. -Either to a 'leaf' array (when the Path is empty, i.e., DBI_PROFILE env var is 1), -or a reference to hash containing values that are either further hash -references or leaf array references. - -Sometimes it's useful to be able to summarise some or all of the collected data. -The dbi_profile_merge_nodes() function can be used to merge leaf node values. - -=head2 dbi_profile_merge_nodes - - use DBI qw(dbi_profile_merge_nodes); - - $time_in_dbi = dbi_profile_merge_nodes(my $totals=[], @$leaves); - -Merges profile data node. Given a reference to a destination array, and zero or -more references to profile data, merges the profile data into the destination array. -For example: - - $time_in_dbi = dbi_profile_merge_nodes( - my $totals=[], - [ 10, 0.51, 0.11, 0.01, 0.22, 1023110000, 1023110010 ], - [ 15, 0.42, 0.12, 0.02, 0.23, 1023110005, 1023110009 ], - ); - -$totals will then contain - - [ 25, 0.93, 0.11, 0.01, 0.23, 1023110000, 1023110010 ] - -and $time_in_dbi will be 0.93; - -The second argument need not be just leaf nodes. If given a reference to a hash -then the hash is recursively searched for leaf nodes and all those found -are merged. - -For example, to get the time spent 'inside' the DBI during an http request, -your logging code run at the end of the request (i.e. mod_perl LogHandler) -could use: - - my $time_in_dbi = 0; - if (my $Profile = $dbh->{Profile}) { # if DBI profiling is enabled - $time_in_dbi = dbi_profile_merge_nodes(my $total=[], $Profile->{Data}); - $Profile->{Data} = {}; # reset the profile data - } - -If profiling has been enabled then $time_in_dbi will hold the time spent inside -the DBI for that handle (and any other handles that share the same profile data) -since the last request. - -Prior to DBI 1.56 the dbi_profile_merge_nodes() function was called dbi_profile_merge(). -That name still exists as an alias. - -=head1 CUSTOM DATA COLLECTION - -=head2 Using The Path Attribute - - XXX example to be added later using a selectall_arrayref call - XXX nested inside a fetch loop where the first column of the - XXX outer loop is bound to the profile Path using - XXX bind_column(1, \${ $dbh->{Profile}->{Path}->[0] }) - XXX so you end up with separate profiles for each loop - XXX (patches welcome to add this to the docs :) - -=head2 Adding Your Own Samples - -The dbi_profile() function can be used to add extra sample data -into the profile data tree. For example: - - use DBI; - use DBI::Profile (dbi_profile dbi_time); - - my $t1 = dbi_time(); # floating point high-resolution time - - ... execute code you want to profile here ... - - my $t2 = dbi_time(); - dbi_profile($h, $statement, $method, $t1, $t2); - -The $h parameter is the handle the extra profile sample should be -associated with. The $statement parameter is the string to use where -the Path specifies !Statement. If $statement is undef -then $h->{Statement} will be used. Similarly $method is the string -to use if the Path specifies !MethodName. There is no -default value for $method. - -The $h->{Profile}{Path} attribute is processed by dbi_profile() in -the usual way. - -The $h parameter is usually a DBI handle but it can also be a reference to a -hash, in which case the dbi_profile() acts on each defined value in the hash. -This is an efficient way to update multiple profiles with a single sample, -and is used by the L module. - -=head1 SUBCLASSING - -Alternate profile modules must subclass DBI::Profile to help ensure -they work with future versions of the DBI. - - -=head1 CAVEATS - -Applications which generate many different statement strings -(typically because they don't use placeholders) and profile with -!Statement in the Path (the default) will consume memory -in the Profile Data structure for each statement. Use a code ref -in the Path to return an edited (simplified) form of the statement. - -If a method throws an exception itself (not via RaiseError) then -it won't be counted in the profile. - -If a HandleError subroutine throws an exception (rather than returning -0 and letting RaiseError do it) then the method call won't be counted -in the profile. - -Time spent in DESTROY is added to the profile of the parent handle. - -Time spent in DBI->*() methods is not counted. The time spent in -the driver connect method, $drh->connect(), when it's called by -DBI->connect is counted if the DBI_PROFILE environment variable is set. - -Time spent fetching tied variables, $DBI::errstr, is counted. - -Time spent in FETCH for $h->{Profile} is not counted, so getting the profile -data doesn't alter it. - -DBI::PurePerl does not support profiling (though it could in theory). - -For asynchronous queries, time spent while the query is running on the -backend is not counted. - -A few platforms don't support the gettimeofday() high resolution -time function used by the DBI (and available via the dbi_time() function). -In which case you'll get integer resolution time which is mostly useless. - -On Windows platforms the dbi_time() function is limited to millisecond -resolution. Which isn't sufficiently fine for our needs, but still -much better than integer resolution. This limited resolution means -that fast method calls will often register as taking 0 time. And -timings in general will have much more 'jitter' depending on where -within the 'current millisecond' the start and end timing was taken. - -This documentation could be more clear. Probably needs to be reordered -to start with several examples and build from there. Trying to -explain the concepts first seems painful and to lead to just as -many forward references. (Patches welcome!) - -=cut - - -use strict; -use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); -use Exporter (); -use UNIVERSAL (); -use Carp; - -use DBI qw(dbi_time dbi_profile dbi_profile_merge_nodes dbi_profile_merge); - -$VERSION = "2.015065"; - -@ISA = qw(Exporter); -@EXPORT = qw( - DBIprofile_Statement - DBIprofile_MethodName - DBIprofile_MethodClass - dbi_profile - dbi_profile_merge_nodes - dbi_profile_merge - dbi_time -); -@EXPORT_OK = qw( - format_profile_thingy -); - -use constant DBIprofile_Statement => '!Statement'; -use constant DBIprofile_MethodName => '!MethodName'; -use constant DBIprofile_MethodClass => '!MethodClass'; - -our $ON_DESTROY_DUMP = sub { DBI->trace_msg(shift, 0) }; -our $ON_FLUSH_DUMP = sub { DBI->trace_msg(shift, 0) }; - -sub new { - my $class = shift; - my $profile = { @_ }; - return bless $profile => $class; -} - - -sub _auto_new { - my $class = shift; - my ($arg) = @_; - - # This sub is called by DBI internals when a non-hash-ref is - # assigned to the Profile attribute. For example - # dbi:mysql(RaiseError=>1,Profile=>!Statement:!MethodName/DBIx::MyProfile/arg1:arg2):dbname - # This sub works out what to do and returns a suitable hash ref. - - $arg =~ s/^DBI::/2\/DBI::/ - and carp "Automatically changed old-style DBI::Profile specification to $arg"; - - # it's a path/module/k1:v1:k2:v2:... list - my ($path, $package, $args) = split /\//, $arg, 3; - my @args = (defined $args) ? split(/:/, $args, -1) : (); - my @Path; - - for my $element (split /:/, $path) { - if (DBI::looks_like_number($element)) { - my $reverse = ($element < 0) ? ($element=-$element, 1) : 0; - my @p; - # a single "DBI" is special-cased in format() - push @p, "DBI" if $element & 0x01; - push @p, DBIprofile_Statement if $element & 0x02; - push @p, DBIprofile_MethodName if $element & 0x04; - push @p, DBIprofile_MethodClass if $element & 0x08; - push @p, '!Caller2' if $element & 0x10; - push @Path, ($reverse ? reverse @p : @p); - } - elsif ($element =~ m/^&(\w.*)/) { - my $name = "DBI::ProfileSubs::$1"; # capture $1 early - require DBI::ProfileSubs; - my $code = do { no strict; *{$name}{CODE} }; - if (defined $code) { - push @Path, $code; - } - else { - warn "$name: subroutine not found\n"; - push @Path, $element; - } - } - else { - push @Path, $element; - } - } - - eval "require $package" if $package; # silently ignores errors - $package ||= $class; - - return $package->new(Path => \@Path, @args); -} - - -sub empty { # empty out profile data - my $self = shift; - DBI->trace_msg("profile data discarded\n",0) if $self->{Trace}; - $self->{Data} = undef; -} - -sub filename { # baseclass method, see DBI::ProfileDumper - return undef; -} - -sub flush_to_disk { # baseclass method, see DBI::ProfileDumper & DashProfiler::Core - my $self = shift; - return unless $ON_FLUSH_DUMP; - return unless $self->{Data}; - my $detail = $self->format(); - $ON_FLUSH_DUMP->($detail) if $detail; -} - - -sub as_node_path_list { - my ($self, $node, $path) = @_; - # convert the tree into an array of arrays - # from - # {key1a}{key2a}[node1] - # {key1a}{key2b}[node2] - # {key1b}{key2a}{key3a}[node3] - # to - # [ [node1], 'key1a', 'key2a' ] - # [ [node2], 'key1a', 'key2b' ] - # [ [node3], 'key1b', 'key2a', 'key3a' ] - - $node ||= $self->{Data} or return; - $path ||= []; - if (ref $node eq 'HASH') { # recurse - $path = [ @$path, undef ]; - return map { - $path->[-1] = $_; - ($node->{$_}) ? $self->as_node_path_list($node->{$_}, $path) : () - } sort keys %$node; - } - return [ $node, @$path ]; -} - - -sub as_text { - my ($self, $args_ref) = @_; - my $separator = $args_ref->{separator} || " > "; - my $format_path_element = $args_ref->{format_path_element} - || "%s"; # or e.g., " key%2$d='%s'" - my $format = $args_ref->{format} - || '%1$s: %11$fs / %10$d = %2$fs avg (first %12$fs, min %13$fs, max %14$fs)'."\n"; - - my @node_path_list = $self->as_node_path_list(undef, $args_ref->{path}); - - $args_ref->{sortsub}->(\@node_path_list) if $args_ref->{sortsub}; - - my $eval = "qr/".quotemeta($separator)."/"; - my $separator_re = eval($eval) || quotemeta($separator); - #warn "[$eval] = [$separator_re]"; - my @text; - my @spare_slots = (undef) x 7; - for my $node_path (@node_path_list) { - my ($node, @path) = @$node_path; - my $idx = 0; - for (@path) { - s/[\r\n]+/ /g; - s/$separator_re/ /g; - ++$idx; - if ($format_path_element eq "%s") { - $_ = sprintf $format_path_element, $_; - } else { - $_ = sprintf $format_path_element, $_, $idx; - } - } - push @text, sprintf $format, - join($separator, @path), # 1=path - ($node->[0] ? $node->[1]/$node->[0] : 0), # 2=avg - @spare_slots, - @$node; # 10=count, 11=dur, 12=first_dur, 13=min, 14=max, 15=first_called, 16=last_called - } - return @text if wantarray; - return join "", @text; -} - - -sub format { - my $self = shift; - my $class = ref($self) || $self; - - my $prologue = "$class: "; - my $detail = $self->format_profile_thingy( - $self->{Data}, 0, " ", - my $path = [], - my $leaves = [], - )."\n"; - - if (@$leaves) { - dbi_profile_merge_nodes(my $totals=[], @$leaves); - my ($count, $time_in_dbi, undef, undef, undef, $t1, $t2) = @$totals; - (my $progname = $0) =~ s:.*/::; - if ($count) { - $prologue .= sprintf "%fs ", $time_in_dbi; - my $perl_time = ($DBI::PERL_ENDING) ? time() - $^T : $t2-$t1; - $prologue .= sprintf "%.2f%% ", $time_in_dbi/$perl_time*100 if $perl_time; - my @lt = localtime(time); - my $ts = sprintf "%d-%02d-%02d %02d:%02d:%02d", - 1900+$lt[5], $lt[4]+1, @lt[3,2,1,0]; - $prologue .= sprintf "(%d calls) $progname \@ $ts\n", $count; - } - if (@$leaves == 1 && ref($self->{Data}) eq 'HASH' && $self->{Data}->{DBI}) { - $detail = ""; # hide the "DBI" from DBI_PROFILE=1 - } - } - return ($prologue, $detail) if wantarray; - return $prologue.$detail; -} - - -sub format_profile_leaf { - my ($self, $thingy, $depth, $pad, $path, $leaves) = @_; - croak "format_profile_leaf called on non-leaf ($thingy)" - unless UNIVERSAL::isa($thingy,'ARRAY'); - - push @$leaves, $thingy if $leaves; - my ($count, $total_time, $first_time, $min, $max, $first_called, $last_called) = @$thingy; - return sprintf "%s%fs\n", ($pad x $depth), $total_time - if $count <= 1; - return sprintf "%s%fs / %d = %fs avg (first %fs, min %fs, max %fs)\n", - ($pad x $depth), $total_time, $count, $count ? $total_time/$count : 0, - $first_time, $min, $max; -} - - -sub format_profile_branch { - my ($self, $thingy, $depth, $pad, $path, $leaves) = @_; - croak "format_profile_branch called on non-branch ($thingy)" - unless UNIVERSAL::isa($thingy,'HASH'); - my @chunk; - my @keys = sort keys %$thingy; - while ( @keys ) { - my $k = shift @keys; - my $v = $thingy->{$k}; - push @$path, $k; - push @chunk, sprintf "%s'%s' =>\n%s", - ($pad x $depth), $k, - $self->format_profile_thingy($v, $depth+1, $pad, $path, $leaves); - pop @$path; - } - return join "", @chunk; -} - - -sub format_profile_thingy { - my ($self, $thingy, $depth, $pad, $path, $leaves) = @_; - return "undef" if not defined $thingy; - return $self->format_profile_leaf( $thingy, $depth, $pad, $path, $leaves) - if UNIVERSAL::isa($thingy,'ARRAY'); - return $self->format_profile_branch($thingy, $depth, $pad, $path, $leaves) - if UNIVERSAL::isa($thingy,'HASH'); - return "$thingy\n"; -} - - -sub on_destroy { - my $self = shift; - return unless $ON_DESTROY_DUMP; - return unless $self->{Data}; - my $detail = $self->format(); - $ON_DESTROY_DUMP->($detail) if $detail; - $self->{Data} = undef; -} - -sub DESTROY { - my $self = shift; - local $@; - DBI->trace_msg("profile data DESTROY\n",0) - if (($self->{Trace}||0) >= 2); - eval { $self->on_destroy }; - if ($@) { - chomp $@; - my $class = ref($self) || $self; - DBI->trace_msg("$class on_destroy failed: $@", 0); - } -} - -1; - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileData.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileData.pm deleted file mode 100644 index e6bb994..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileData.pm +++ /dev/null @@ -1,736 +0,0 @@ -package DBI::ProfileData; -use strict; - -=head1 NAME - -DBI::ProfileData - manipulate DBI::ProfileDumper data dumps - -=head1 SYNOPSIS - -The easiest way to use this module is through the dbiprof frontend -(see L for details): - - dbiprof --number 15 --sort count - -This module can also be used to roll your own profile analysis: - - # load data from dbi.prof - $prof = DBI::ProfileData->new(File => "dbi.prof"); - - # get a count of the records (unique paths) in the data set - $count = $prof->count(); - - # sort by longest overall time - $prof->sort(field => "longest"); - - # sort by longest overall time, least to greatest - $prof->sort(field => "longest", reverse => 1); - - # exclude records with key2 eq 'disconnect' - $prof->exclude(key2 => 'disconnect'); - - # exclude records with key1 matching /^UPDATE/i - $prof->exclude(key1 => qr/^UPDATE/i); - - # remove all records except those where key1 matches /^SELECT/i - $prof->match(key1 => qr/^SELECT/i); - - # produce a formatted report with the given number of items - $report = $prof->report(number => 10); - - # clone the profile data set - $clone = $prof->clone(); - - # get access to hash of header values - $header = $prof->header(); - - # get access to sorted array of nodes - $nodes = $prof->nodes(); - - # format a single node in the same style as report() - $text = $prof->format($nodes->[0]); - - # get access to Data hash in DBI::Profile format - $Data = $prof->Data(); - -=head1 DESCRIPTION - -This module offers the ability to read, manipulate and format -L profile data. - -Conceptually, a profile consists of a series of records, or nodes, -each of each has a set of statistics and set of keys. Each record -must have a unique set of keys, but there is no requirement that every -record have the same number of keys. - -=head1 METHODS - -The following methods are supported by DBI::ProfileData objects. - -=cut - -our $VERSION = "2.010008"; - -use Carp qw(croak); -use Symbol; -use Fcntl qw(:flock); - -use DBI::Profile qw(dbi_profile_merge); - -# some constants for use with node data arrays -sub COUNT () { 0 }; -sub TOTAL () { 1 }; -sub FIRST () { 2 }; -sub SHORTEST () { 3 }; -sub LONGEST () { 4 }; -sub FIRST_AT () { 5 }; -sub LAST_AT () { 6 }; -sub PATH () { 7 }; - - -my $HAS_FLOCK = (defined $ENV{DBI_PROFILE_FLOCK}) - ? $ENV{DBI_PROFILE_FLOCK} - : do { local $@; eval { flock STDOUT, 0; 1 } }; - - -=head2 $prof = DBI::ProfileData->new(File => "dbi.prof") - -=head2 $prof = DBI::ProfileData->new(File => "dbi.prof", Filter => sub { ... }) - -=head2 $prof = DBI::ProfileData->new(Files => [ "dbi.prof.1", "dbi.prof.2" ]) - -Creates a new DBI::ProfileData object. Takes either a single file -through the File option or a list of Files in an array ref. If -multiple files are specified then the header data from the first file -is used. - -=head3 Files - -Reference to an array of file names to read. - -=head3 File - -Name of file to read. Takes precedence over C. - -=head3 DeleteFiles - -If true, the files are deleted after being read. - -Actually the files are renamed with a C suffix before being read, -and then, after reading all the files, they're all deleted together. - -The files are locked while being read which, combined with the rename, makes it -safe to 'consume' files that are still being generated by L. - -=head3 Filter - -The C parameter can be used to supply a code reference that can -manipulate the profile data as it is being read. This is most useful for -editing SQL statements so that slightly different statements in the raw data -will be merged and aggregated in the loaded data. For example: - - Filter => sub { - my ($path_ref, $data_ref) = @_; - s/foo = '.*?'/foo = '...'/ for @$path_ref; - } - -Here's an example that performs some normalization on the SQL. It converts all -numbers to C and all quoted strings to C. It can also convert digits to -N within names. Finally, it summarizes long "IN (...)" clauses. - -It's aggressive and simplistic, but it's often sufficient, and serves as an -example that you can tailor to suit your own needs: - - Filter => sub { - my ($path_ref, $data_ref) = @_; - local $_ = $path_ref->[0]; # whichever element contains the SQL Statement - s/\b\d+\b/N/g; # 42 -> N - s/\b0x[0-9A-Fa-f]+\b/N/g; # 0xFE -> N - s/'.*?'/'S'/g; # single quoted strings (doesn't handle escapes) - s/".*?"/"S"/g; # double quoted strings (doesn't handle escapes) - # convert names like log_20001231 into log_NNNNNNNN, controlled by $opt{n} - s/([a-z_]+)(\d{$opt{n},})/$1.('N' x length($2))/ieg if $opt{n}; - # abbreviate massive "in (...)" statements and similar - s!(([NS],){100,})!sprintf("$2,{repeated %d times}",length($1)/2)!eg; - } - -It's often better to perform this kinds of normalization in the DBI while the -data is being collected, to avoid too much memory being used by storing profile -data for many different SQL statement. See L. - -=cut - -sub new { - my $pkg = shift; - my $self = { - Files => [ "dbi.prof" ], - Filter => undef, - DeleteFiles => 0, - LockFile => $HAS_FLOCK, - _header => {}, - _nodes => [], - _node_lookup => {}, - _sort => 'none', - @_ - }; - bless $self, $pkg; - - # File (singular) overrides Files (plural) - $self->{Files} = [ $self->{File} ] if exists $self->{File}; - - $self->_read_files(); - return $self; -} - -# read files into _header and _nodes -sub _read_files { - my $self = shift; - my $files = $self->{Files}; - my $read_header = 0; - my @files_to_delete; - - my $fh = gensym; - foreach (@$files) { - my $filename = $_; - - if ($self->{DeleteFiles}) { - my $newfilename = $filename . ".deleteme"; - if ($^O eq 'VMS') { - # VMS default filesystem can only have one period - $newfilename = $filename . 'deleteme'; - } - # will clobber an existing $newfilename - rename($filename, $newfilename) - or croak "Can't rename($filename, $newfilename): $!"; - # On a versioned filesystem we want old versions to be removed - 1 while (unlink $filename); - $filename = $newfilename; - } - - open($fh, "<", $filename) - or croak("Unable to read profile file '$filename': $!"); - - # lock the file in case it's still being written to - # (we'll be forced to wait till the write is complete) - flock($fh, LOCK_SH) if $self->{LockFile}; - - if (-s $fh) { # not empty - $self->_read_header($fh, $filename, $read_header ? 0 : 1); - $read_header = 1; - $self->_read_body($fh, $filename); - } - close($fh); # and release lock - - push @files_to_delete, $filename - if $self->{DeleteFiles}; - } - for (@files_to_delete){ - # for versioned file systems - 1 while (unlink $_); - if(-e $_){ - warn "Can't delete '$_': $!"; - } - } - - # discard node_lookup now that all files are read - delete $self->{_node_lookup}; -} - -# read the header from the given $fh named $filename. Discards the -# data unless $keep. -sub _read_header { - my ($self, $fh, $filename, $keep) = @_; - - # get profiler module id - my $first = <$fh>; - chomp $first; - $self->{_profiler} = $first if $keep; - - # collect variables from the header - local $_; - while (<$fh>) { - chomp; - last unless length $_; - /^(\S+)\s*=\s*(.*)/ - or croak("Syntax error in header in $filename line $.: $_"); - # XXX should compare new with existing (from previous file) - # and warn if they differ (different program or path) - $self->{_header}{$1} = unescape_key($2) if $keep; - } -} - - -sub unescape_key { # inverse of escape_key() in DBI::ProfileDumper - local $_ = shift; - s/(?{_nodes}; - my $lookup = $self->{_node_lookup}; - my $filter = $self->{Filter}; - - # build up node array - my @path = (""); - my (@data, $path_key); - local $_; - while (<$fh>) { - chomp; - if (/^\+\s+(\d+)\s?(.*)/) { - # it's a key - my ($key, $index) = ($2, $1 - 1); - - $#path = $index; # truncate path to new length - $path[$index] = unescape_key($key); # place new key at end - - } - elsif (s/^=\s+//) { - # it's data - file in the node array with the path in index 0 - # (the optional minus is to make it more robust against systems - # with unstable high-res clocks - typically due to poor NTP config - # of kernel SMP behaviour, i.e. min time may be -0.000008)) - - @data = split / /, $_; - - # corrupt data? - croak("Invalid number of fields in $filename line $.: $_") - unless @data == 7; - croak("Invalid leaf node characters $filename line $.: $_") - unless m/^[-+ 0-9eE\.]+$/; - - # hook to enable pre-processing of the data - such as mangling SQL - # so that slightly different statements get treated as the same - # and so merged in the results - $filter->(\@path, \@data) if $filter; - - # elements of @path can't have NULLs in them, so this - # forms a unique string per @path. If there's some way I - # can get this without arbitrarily stripping out a - # character I'd be happy to hear it! - $path_key = join("\0",@path); - - # look for previous entry - if (exists $lookup->{$path_key}) { - # merge in the new data - dbi_profile_merge($nodes->[$lookup->{$path_key}], \@data); - } else { - # insert a new node - nodes are arrays with data in 0-6 - # and path data after that - push(@$nodes, [ @data, @path ]); - - # record node in %seen - $lookup->{$path_key} = $#$nodes; - } - } - else { - croak("Invalid line type syntax error in $filename line $.: $_"); - } - } -} - - - -=head2 $copy = $prof->clone(); - -Clone a profile data set creating a new object. - -=cut - -sub clone { - my $self = shift; - - # start with a simple copy - my $clone = bless { %$self }, ref($self); - - # deep copy nodes - $clone->{_nodes} = [ map { [ @$_ ] } @{$self->{_nodes}} ]; - - # deep copy header - $clone->{_header} = { %{$self->{_header}} }; - - return $clone; -} - -=head2 $header = $prof->header(); - -Returns a reference to a hash of header values. These are the key -value pairs included in the header section of the L -data format. For example: - - $header = { - Path => [ '!Statement', '!MethodName' ], - Program => 't/42profile_data.t', - }; - -Note that modifying this hash will modify the header data stored -inside the profile object. - -=cut - -sub header { shift->{_header} } - - -=head2 $nodes = $prof->nodes() - -Returns a reference the sorted nodes array. Each element in the array -is a single record in the data set. The first seven elements are the -same as the elements provided by L. After that each key is -in a separate element. For example: - - $nodes = [ - [ - 2, # 0, count - 0.0312958955764771, # 1, total duration - 0.000490069389343262, # 2, first duration - 0.000176072120666504, # 3, shortest duration - 0.00140702724456787, # 4, longest duration - 1023115819.83019, # 5, time of first event - 1023115819.86576, # 6, time of last event - 'SELECT foo FROM bar' # 7, key1 - 'execute' # 8, key2 - # 6+N, keyN - ], - # ... - ]; - -Note that modifying this array will modify the node data stored inside -the profile object. - -=cut - -sub nodes { shift->{_nodes} } - - -=head2 $count = $prof->count() - -Returns the number of items in the profile data set. - -=cut - -sub count { scalar @{shift->{_nodes}} } - - -=head2 $prof->sort(field => "field") - -=head2 $prof->sort(field => "field", reverse => 1) - -Sorts data by the given field. Available fields are: - - longest - total - count - shortest - -The default sort is greatest to smallest, which is the opposite of the -normal Perl meaning. This, however, matches the expected behavior of -the dbiprof frontend. - -=cut - - -# sorts data by one of the available fields -{ - my %FIELDS = ( - longest => LONGEST, - total => TOTAL, - count => COUNT, - shortest => SHORTEST, - key1 => PATH+0, - key2 => PATH+1, - key3 => PATH+2, - ); - sub sort { - my $self = shift; - my $nodes = $self->{_nodes}; - my %opt = @_; - - croak("Missing required field option.") unless $opt{field}; - - my $index = $FIELDS{$opt{field}}; - - croak("Unrecognized sort field '$opt{field}'.") - unless defined $index; - - # sort over index - if ($opt{reverse}) { - @$nodes = sort { - $a->[$index] <=> $b->[$index] - } @$nodes; - } else { - @$nodes = sort { - $b->[$index] <=> $a->[$index] - } @$nodes; - } - - # remember how we're sorted - $self->{_sort} = $opt{field}; - - return $self; - } -} - - -=head2 $count = $prof->exclude(key2 => "disconnect") - -=head2 $count = $prof->exclude(key2 => "disconnect", case_sensitive => 1) - -=head2 $count = $prof->exclude(key1 => qr/^SELECT/i) - -Removes records from the data set that match the given string or -regular expression. This method modifies the data in a permanent -fashion - use clone() first to maintain the original data after -exclude(). Returns the number of nodes left in the profile data set. - -=cut - -sub exclude { - my $self = shift; - my $nodes = $self->{_nodes}; - my %opt = @_; - - # find key index number - my ($index, $val); - foreach (keys %opt) { - if (/^key(\d+)$/) { - $index = PATH + $1 - 1; - $val = $opt{$_}; - last; - } - } - croak("Missing required keyN option.") unless $index; - - if (UNIVERSAL::isa($val,"Regexp")) { - # regex match - @$nodes = grep { - $#$_ < $index or $_->[$index] !~ /$val/ - } @$nodes; - } else { - if ($opt{case_sensitive}) { - @$nodes = grep { - $#$_ < $index or $_->[$index] ne $val; - } @$nodes; - } else { - $val = lc $val; - @$nodes = grep { - $#$_ < $index or lc($_->[$index]) ne $val; - } @$nodes; - } - } - - return scalar @$nodes; -} - - -=head2 $count = $prof->match(key2 => "disconnect") - -=head2 $count = $prof->match(key2 => "disconnect", case_sensitive => 1) - -=head2 $count = $prof->match(key1 => qr/^SELECT/i) - -Removes records from the data set that do not match the given string -or regular expression. This method modifies the data in a permanent -fashion - use clone() first to maintain the original data after -match(). Returns the number of nodes left in the profile data set. - -=cut - -sub match { - my $self = shift; - my $nodes = $self->{_nodes}; - my %opt = @_; - - # find key index number - my ($index, $val); - foreach (keys %opt) { - if (/^key(\d+)$/) { - $index = PATH + $1 - 1; - $val = $opt{$_}; - last; - } - } - croak("Missing required keyN option.") unless $index; - - if (UNIVERSAL::isa($val,"Regexp")) { - # regex match - @$nodes = grep { - $#$_ >= $index and $_->[$index] =~ /$val/ - } @$nodes; - } else { - if ($opt{case_sensitive}) { - @$nodes = grep { - $#$_ >= $index and $_->[$index] eq $val; - } @$nodes; - } else { - $val = lc $val; - @$nodes = grep { - $#$_ >= $index and lc($_->[$index]) eq $val; - } @$nodes; - } - } - - return scalar @$nodes; -} - - -=head2 $Data = $prof->Data() - -Returns the same Data hash structure as seen in L. This -structure is not sorted. The nodes() structure probably makes more -sense for most analysis. - -=cut - -sub Data { - my $self = shift; - my (%Data, @data, $ptr); - - foreach my $node (@{$self->{_nodes}}) { - # traverse to key location - $ptr = \%Data; - foreach my $key (@{$node}[PATH .. $#$node - 1]) { - $ptr->{$key} = {} unless exists $ptr->{$key}; - $ptr = $ptr->{$key}; - } - - # slice out node data - $ptr->{$node->[-1]} = [ @{$node}[0 .. 6] ]; - } - - return \%Data; -} - - -=head2 $text = $prof->format($nodes->[0]) - -Formats a single node into a human-readable block of text. - -=cut - -sub format { - my ($self, $node) = @_; - my $format; - - # setup keys - my $keys = ""; - for (my $i = PATH; $i <= $#$node; $i++) { - my $key = $node->[$i]; - - # remove leading and trailing space - $key =~ s/^\s+//; - $key =~ s/\s+$//; - - # if key has newlines or is long take special precautions - if (length($key) > 72 or $key =~ /\n/) { - $keys .= " Key " . ($i - PATH + 1) . " :\n\n$key\n\n"; - } else { - $keys .= " Key " . ($i - PATH + 1) . " : $key\n"; - } - } - - # nodes with multiple runs get the long entry format, nodes with - # just one run get a single count. - if ($node->[COUNT] > 1) { - $format = <[TOTAL] / $node->[COUNT]) . $keys; - } else { - $format = <report(number => 10) - -Produces a report with the given number of items. - -=cut - -sub report { - my $self = shift; - my $nodes = $self->{_nodes}; - my %opt = @_; - - croak("Missing required number option") unless exists $opt{number}; - - $opt{number} = @$nodes if @$nodes < $opt{number}; - - my $report = $self->_report_header($opt{number}); - for (0 .. $opt{number} - 1) { - $report .= sprintf("#" x 5 . "[ %d ]". "#" x 59 . "\n", - $_ + 1); - $report .= $self->format($nodes->[$_]); - $report .= "\n"; - } - return $report; -} - -# format the header for report() -sub _report_header { - my ($self, $number) = @_; - my $nodes = $self->{_nodes}; - my $node_count = @$nodes; - - # find total runtime and method count - my ($time, $count) = (0,0); - foreach my $node (@$nodes) { - $time += $node->[TOTAL]; - $count += $node->[COUNT]; - } - - my $header = <{_profiler}) - -END - - # output header fields - while (my ($key, $value) = each %{$self->{_header}}) { - $header .= sprintf(" %-13s : %s\n", $key, $value); - } - - # output summary data fields - $header .= sprintf(<{_sort}, $count, $time); - Total Records : %d (showing %d, sorted by %s) - Total Count : %d - Total Runtime : %3.6f seconds - -END - - return $header; -} - - -1; - -__END__ - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileDumper.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileDumper.pm deleted file mode 100644 index 440b5c9..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileDumper.pm +++ /dev/null @@ -1,351 +0,0 @@ -package DBI::ProfileDumper; -use strict; - -=head1 NAME - -DBI::ProfileDumper - profile DBI usage and output data to a file - -=head1 SYNOPSIS - -To profile an existing program using DBI::ProfileDumper, set the -DBI_PROFILE environment variable and run your program as usual. For -example, using bash: - - DBI_PROFILE=2/DBI::ProfileDumper program.pl - -Then analyze the generated file (F) with L: - - dbiprof - -You can also activate DBI::ProfileDumper from within your code: - - use DBI; - - # profile with default path (2) and output file (dbi.prof) - $dbh->{Profile} = "!Statement/DBI::ProfileDumper"; - - # same thing, spelled out - $dbh->{Profile} = "!Statement/DBI::ProfileDumper/File:dbi.prof"; - - # another way to say it - use DBI::ProfileDumper; - $dbh->{Profile} = DBI::ProfileDumper->new( - Path => [ '!Statement' ], - File => 'dbi.prof' ); - - # using a custom path - $dbh->{Profile} = DBI::ProfileDumper->new( - Path => [ "foo", "bar" ], - File => 'dbi.prof', - ); - - -=head1 DESCRIPTION - -DBI::ProfileDumper is a subclass of L which -dumps profile data to disk instead of printing a summary to your -screen. You can then use L to analyze the data in -a number of interesting ways, or you can roll your own analysis using -L. - -B For Apache/mod_perl applications, use -L. - -=head1 USAGE - -One way to use this module is just to enable it in your C<$dbh>: - - $dbh->{Profile} = "1/DBI::ProfileDumper"; - -This will write out profile data by statement into a file called -F. If you want to modify either of these properties, you -can construct the DBI::ProfileDumper object yourself: - - use DBI::ProfileDumper; - $dbh->{Profile} = DBI::ProfileDumper->new( - Path => [ '!Statement' ], - File => 'dbi.prof' - ); - -The C option takes the same values as in -L. The C option gives the name of the -file where results will be collected. If it already exists it will be -overwritten. - -You can also activate this module by setting the DBI_PROFILE -environment variable: - - $ENV{DBI_PROFILE} = "!Statement/DBI::ProfileDumper"; - -This will cause all DBI handles to share the same profiling object. - -=head1 METHODS - -The following methods are available to be called using the profile -object. You can get access to the profile object from the Profile key -in any DBI handle: - - my $profile = $dbh->{Profile}; - -=head2 flush_to_disk - - $profile->flush_to_disk() - -Flushes all collected profile data to disk and empties the Data hash. Returns -the filename written to. If no profile data has been collected then the file is -not written and flush_to_disk() returns undef. - -The file is locked while it's being written. A process 'consuming' the files -while they're being written to, should rename the file first, then lock it, -then read it, then close and delete it. The C option to -L does the right thing. - -This method may be called multiple times during a program run. - -=head2 empty - - $profile->empty() - -Clears the Data hash without writing to disk. - -=head2 filename - - $filename = $profile->filename(); - -Get or set the filename. - -The filename can be specified as a CODE reference, in which case the referenced -code should return the filename to be used. The code will be called with the -profile object as its first argument. - -=head1 DATA FORMAT - -The data format written by DBI::ProfileDumper starts with a header -containing the version number of the module used to generate it. Then -a block of variable declarations describes the profile. After two -newlines, the profile data forms the body of the file. For example: - - DBI::ProfileDumper 2.003762 - Path = [ '!Statement', '!MethodName' ] - Program = t/42profile_data.t - - + 1 SELECT name FROM users WHERE id = ? - + 2 prepare - = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - + 2 execute - 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - + 2 fetchrow_hashref - = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - + 1 UPDATE users SET name = ? WHERE id = ? - + 2 prepare - = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - + 2 execute - = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - -The lines beginning with C<+> signs signify keys. The number after -the C<+> sign shows the nesting level of the key. Lines beginning -with C<=> are the actual profile data, in the same order as -in DBI::Profile. - -Note that the same path may be present multiple times in the data file -since C may be called more than once. When read by -DBI::ProfileData the data points will be merged to produce a single -data set for each distinct path. - -The key strings are transformed in three ways. First, all backslashes -are doubled. Then all newlines and carriage-returns are transformed -into C<\n> and C<\r> respectively. Finally, any NULL bytes (C<\0>) -are entirely removed. When DBI::ProfileData reads the file the first -two transformations will be reversed, but NULL bytes will not be -restored. - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=cut - -# inherit from DBI::Profile -use DBI::Profile; - -our @ISA = ("DBI::Profile"); - -our $VERSION = "2.015325"; - -use Carp qw(croak); -use Fcntl qw(:flock); -use Symbol; - -my $HAS_FLOCK = (defined $ENV{DBI_PROFILE_FLOCK}) - ? $ENV{DBI_PROFILE_FLOCK} - : do { local $@; eval { flock STDOUT, 0; 1 } }; - -my $program_header; - - -# validate params and setup default -sub new { - my $pkg = shift; - my $self = $pkg->SUPER::new( - LockFile => $HAS_FLOCK, - @_, - ); - - # provide a default filename - $self->filename("dbi.prof") unless $self->filename; - - DBI->trace_msg("$self: @{[ %$self ]}\n",0) - if $self->{Trace} && $self->{Trace} >= 2; - - return $self; -} - - -# get/set filename to use -sub filename { - my $self = shift; - $self->{File} = shift if @_; - my $filename = $self->{File}; - $filename = $filename->($self) if ref($filename) eq 'CODE'; - return $filename; -} - - -# flush available data to disk -sub flush_to_disk { - my $self = shift; - my $class = ref $self; - my $filename = $self->filename; - my $data = $self->{Data}; - - if (1) { # make an option - if (not $data or ref $data eq 'HASH' && !%$data) { - DBI->trace_msg("flush_to_disk skipped for empty profile\n",0) if $self->{Trace}; - return undef; - } - } - - my $fh = gensym; - if (($self->{_wrote_header}||'') eq $filename) { - # append more data to the file - # XXX assumes that Path hasn't changed - open($fh, ">>", $filename) - or croak("Unable to open '$filename' for $class output: $!"); - } else { - # create new file (or overwrite existing) - if (-f $filename) { - my $bak = $filename.'.prev'; - unlink($bak); - rename($filename, $bak) - or warn "Error renaming $filename to $bak: $!\n"; - } - open($fh, ">", $filename) - or croak("Unable to open '$filename' for $class output: $!"); - } - # lock the file (before checking size and writing the header) - flock($fh, LOCK_EX) if $self->{LockFile}; - # write header if file is empty - typically because we just opened it - # in '>' mode, or perhaps we used '>>' but the file had been truncated externally. - if (-s $fh == 0) { - DBI->trace_msg("flush_to_disk wrote header to $filename\n",0) if $self->{Trace}; - $self->write_header($fh); - $self->{_wrote_header} = $filename; - } - - my $lines = $self->write_data($fh, $self->{Data}, 1); - DBI->trace_msg("flush_to_disk wrote $lines lines to $filename\n",0) if $self->{Trace}; - - close($fh) # unlocks the file - or croak("Error closing '$filename': $!"); - - $self->empty(); - - - return $filename; -} - - -# write header to a filehandle -sub write_header { - my ($self, $fh) = @_; - - # isolate us against globals which effect print - local($\, $,); - - # $self->VERSION can return undef during global destruction - my $version = $self->VERSION || $VERSION; - - # module name and version number - print $fh ref($self)." $version\n"; - - # print out Path (may contain CODE refs etc) - my @path_words = map { escape_key($_) } @{ $self->{Path} || [] }; - print $fh "Path = [ ", join(', ', @path_words), " ]\n"; - - # print out $0 and @ARGV - if (!$program_header) { - # XXX should really quote as well as escape - $program_header = "Program = " - . join(" ", map { escape_key($_) } $0, @ARGV) - . "\n"; - } - print $fh $program_header; - - # all done - print $fh "\n"; -} - - -# write data in the proscribed format -sub write_data { - my ($self, $fh, $data, $level) = @_; - - # XXX it's valid for $data to be an ARRAY ref, i.e., Path is empty. - # produce an empty profile for invalid $data - return 0 unless $data and UNIVERSAL::isa($data,'HASH'); - - # isolate us against globals which affect print - local ($\, $,); - - my $lines = 0; - while (my ($key, $value) = each(%$data)) { - # output a key - print $fh "+ $level ". escape_key($key). "\n"; - if (UNIVERSAL::isa($value,'ARRAY')) { - # output a data set for a leaf node - print $fh "= ".join(' ', @$value)."\n"; - $lines += 1; - } else { - # recurse through keys - this could be rewritten to use a - # stack for some small performance gain - $lines += $self->write_data($fh, $value, $level + 1); - } - } - return $lines; -} - - -# escape a key for output -sub escape_key { - my $key = shift; - $key =~ s!\\!\\\\!g; - $key =~ s!\n!\\n!g; - $key =~ s!\r!\\r!g; - $key =~ s!\0!!g; - return $key; -} - - -# flush data to disk when profile object goes out of scope -sub on_destroy { - shift->flush_to_disk(); -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileDumper/Apache.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileDumper/Apache.pm deleted file mode 100644 index df0d35c..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileDumper/Apache.pm +++ /dev/null @@ -1,219 +0,0 @@ -package DBI::ProfileDumper::Apache; - -use strict; - -=head1 NAME - -DBI::ProfileDumper::Apache - capture DBI profiling data from Apache/mod_perl - -=head1 SYNOPSIS - -Add this line to your F: - - PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache - -(If you're using mod_perl2, see L for some additional notes.) - -Then restart your server. Access the code you wish to test using a -web browser, then shutdown your server. This will create a set of -F files in your Apache log directory. - -Get a profiling report with L: - - dbiprof /path/to/your/apache/logs/dbi.prof.* - -When you're ready to perform another profiling run, delete the old files and start again. - -=head1 DESCRIPTION - -This module interfaces DBI::ProfileDumper to Apache/mod_perl. Using -this module you can collect profiling data from mod_perl applications. -It works by creating a DBI::ProfileDumper data file for each Apache -process. These files are created in your Apache log directory. You -can then use the dbiprof utility to analyze the profile files. - -=head1 USAGE - -=head2 LOADING THE MODULE - -The easiest way to use this module is just to set the DBI_PROFILE -environment variable in your F: - - PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache - -The DBI will look after loading and using the module when the first DBI handle -is created. - -It's also possible to use this module by setting the Profile attribute -of any DBI handle: - - $dbh->{Profile} = "2/DBI::ProfileDumper::Apache"; - -See L for more possibilities, and L for full -details of the DBI's profiling mechanism. - -=head2 WRITING PROFILE DATA - -The profile data files will be written to your Apache log directory by default. - -The user that the httpd processes run as will need write access to the -directory. So, for example, if you're running the child httpds as user 'nobody' -and using chronolog to write to the logs directory, then you'll need to change -the default. - -You can change the destination directory either by specifying a C value -when creating the profile (like C in the L docs), -or you can use the C env var to change that. For example: - - PerlSetEnv DBI_PROFILE_APACHE_LOG_DIR /server_root/logs - -=head3 When using mod_perl2 - -Under mod_perl2 you'll need to either set the C env var, -or enable the mod_perl2 C option, like this: - - PerlOptions +GlobalRequest - -to the global config section you're about test with DBI::ProfileDumper::Apache. -If you don't do one of those then you'll see messages in your error_log similar to: - - DBI::ProfileDumper::Apache on_destroy failed: Global $r object is not available. Set: - PerlOptions +GlobalRequest in httpd.conf at ..../DBI/ProfileDumper/Apache.pm line 144 - -=head3 Naming the files - -The default file name is inherited from L via the -filename() method, but DBI::ProfileDumper::Apache appends the parent pid and -the current pid, separated by dots, to that name. - -=head3 Silencing the log - -By default a message is written to STDERR (i.e., the apache error_log file) -when flush_to_disk() is called (either explicitly, or implicitly via DESTROY). - -That's usually very useful. If you don't want the log message you can silence -it by setting the C attribute true. - - PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache/Quiet:1 - - $dbh->{Profile} = "!Statement/DBI::ProfileDumper/Quiet:1"; - - $dbh->{Profile} = DBI::ProfileDumper->new( - Path => [ '!Statement' ] - Quiet => 1 - ); - - -=head2 GATHERING PROFILE DATA - -Once you have the module loaded, use your application as you normally -would. Stop the webserver when your tests are complete. Profile data -files will be produced when Apache exits and you'll see something like -this in your error_log: - - DBI::ProfileDumper::Apache writing to /usr/local/apache/logs/dbi.prof.2604.2619 - -Now you can use dbiprof to examine the data: - - dbiprof /usr/local/apache/logs/dbi.prof.2604.* - -By passing dbiprof a list of all generated files, dbiprof will -automatically merge them into one result set. You can also pass -dbiprof sorting and querying options, see L for details. - -=head2 CLEANING UP - -Once you've made some code changes, you're ready to start again. -First, delete the old profile data files: - - rm /usr/local/apache/logs/dbi.prof.* - -Then restart your server and get back to work. - -=head1 OTHER ISSUES - -=head2 Memory usage - -DBI::Profile can use a lot of memory for very active applications because it -collects profiling data in memory for each distinct query run. -Calling C will write the current data to disk and free the -memory it's using. For example: - - $dbh->{Profile}->flush_to_disk() if $dbh->{Profile}; - -or, rather than flush every time, you could flush less often: - - $dbh->{Profile}->flush_to_disk() - if $dbh->{Profile} and ++$i % 100; - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=cut - -our $VERSION = "2.014121"; - -our @ISA = qw(DBI::ProfileDumper); - -use DBI::ProfileDumper; -use File::Spec; - -my $initial_pid = $$; - -use constant MP2 => ($ENV{MOD_PERL_API_VERSION} and $ENV{MOD_PERL_API_VERSION} == 2) ? 1 : 0; - -my $server_root_dir; - -if (MP2) { - require Apache2::ServerUtil; - $server_root_dir = Apache2::ServerUtil::server_root(); -} -else { - require Apache; - $server_root_dir = eval { Apache->server_root_relative('') } || "/tmp"; -} - - -sub _dirname { - my $self = shift; - return $self->{Dir} ||= $ENV{DBI_PROFILE_APACHE_LOG_DIR} - || File::Spec->catdir($server_root_dir, "logs"); -} - - -sub filename { - my $self = shift; - my $filename = $self->SUPER::filename(@_); - return $filename if not $filename; # not set yet - - # to be able to identify groups of profile files from the same set of - # apache processes, we include the parent pid in the file name - # as well as the pid. - my $group_pid = ($$ eq $initial_pid) ? $$ : getppid(); - $filename .= ".$group_pid.$$"; - - return $filename if File::Spec->file_name_is_absolute($filename); - return File::Spec->catfile($self->_dirname, $filename); -} - - -sub flush_to_disk { - my $self = shift; - - my $filename = $self->SUPER::flush_to_disk(@_); - - print STDERR ref($self)." pid$$ written to $filename\n" - if $filename && not $self->{Quiet}; - - return $filename; -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileSubs.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileSubs.pm deleted file mode 100644 index 015462b..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProfileSubs.pm +++ /dev/null @@ -1,50 +0,0 @@ -package DBI::ProfileSubs; - -our $VERSION = "0.009396"; - -=head1 NAME - -DBI::ProfileSubs - Subroutines for dynamic profile Path - -=head1 SYNOPSIS - - DBI_PROFILE='&norm_std_n3' prog.pl - -This is new and still experimental. - -=head1 TO DO - -Define come kind of naming convention for the subs. - -=cut - -use strict; -use warnings; - - -# would be good to refactor these regex into separate subs and find some -# way to compose them in various combinations into multiple subs. -# Perhaps via AUTOLOAD where \&auto_X_Y_Z creates a sub that does X, Y, and Z. -# The final subs always need to be very fast. -# - -sub norm_std_n3 { - # my ($h, $method_name) = @_; - local $_ = $_; - - s/\b\d+\b//g; # 42 -> - s/\b0x[0-9A-Fa-f]+\b//g; # 0xFE -> - - s/'.*?'/''/g; # single quoted strings (doesn't handle escapes) - s/".*?"/""/g; # double quoted strings (doesn't handle escapes) - - # convert names like log20001231 into log - s/([a-z_]+)(\d{3,})\b/${1}/ig; - - # abbreviate massive "in (...)" statements and similar - s!((\s*<[NS]>\s*,\s*){100,})!sprintf("$2,",length($1)/2)!eg; - - return $_; -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProxyServer.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/ProxyServer.pm deleted file mode 100644 index ef21849..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/ProxyServer.pm +++ /dev/null @@ -1,897 +0,0 @@ -# $Header: /home/timbo/dbi/lib/DBI/RCS/ProxyServer.pm,v 11.9 2003/05/14 11:08:17 timbo Exp $ -# -*- perl -*- -# -# DBI::ProxyServer - a proxy server for DBI drivers -# -# Copyright (c) 1997 Jochen Wiedmann -# -# The DBD::Proxy module is free software; you can redistribute it and/or -# modify it under the same terms as Perl itself. In particular permission -# is granted to Tim Bunce for distributing this as a part of the DBI. -# -# -# Author: Jochen Wiedmann -# Am Eisteich 9 -# 72555 Metzingen -# Germany -# -# Email: joe@ispsoft.de -# Phone: +49 7123 14881 -# -# -############################################################################## - - -require 5.004; -use strict; - -use RPC::PlServer 0.2001; -require DBI; -require Config; - - -package DBI::ProxyServer; - - - -############################################################################ -# -# Constants -# -############################################################################ - -use vars qw($VERSION @ISA); - -$VERSION = "0.3005"; -@ISA = qw(RPC::PlServer DBI); - - -# Most of the options below are set to default values, we note them here -# just for the sake of documentation. -my %DEFAULT_SERVER_OPTIONS; -{ - my $o = \%DEFAULT_SERVER_OPTIONS; - $o->{'chroot'} = undef, # To be used in the initfile, - # after loading the required - # DBI drivers. - $o->{'clients'} = - [ { 'mask' => '.*', - 'accept' => 1, - 'cipher' => undef - } - ]; - $o->{'configfile'} = '/etc/dbiproxy.conf' if -f '/etc/dbiproxy.conf'; - $o->{'debug'} = 0; - $o->{'facility'} = 'daemon'; - $o->{'group'} = undef; - $o->{'localaddr'} = undef; # Bind to any local IP number - $o->{'localport'} = undef; # Must set port number on the - # command line. - $o->{'logfile'} = undef; # Use syslog or EventLog. - - # XXX don't restrict methods that can be called (trust users once connected) - $o->{'XXX_methods'} = { - 'DBI::ProxyServer' => { - 'Version' => 1, - 'NewHandle' => 1, - 'CallMethod' => 1, - 'DestroyHandle' => 1 - }, - 'DBI::ProxyServer::db' => { - 'prepare' => 1, - 'commit' => 1, - 'rollback' => 1, - 'STORE' => 1, - 'FETCH' => 1, - 'func' => 1, - 'quote' => 1, - 'type_info_all' => 1, - 'table_info' => 1, - 'disconnect' => 1, - }, - 'DBI::ProxyServer::st' => { - 'execute' => 1, - 'STORE' => 1, - 'FETCH' => 1, - 'func' => 1, - 'fetch' => 1, - 'finish' => 1 - } - }; - if ($Config::Config{'usethreads'} eq 'define') { - $o->{'mode'} = 'threads'; - } elsif ($Config::Config{'d_fork'} eq 'define') { - $o->{'mode'} = 'fork'; - } else { - $o->{'mode'} = 'single'; - } - # No pidfile by default, configuration must provide one if needed - $o->{'pidfile'} = 'none'; - $o->{'user'} = undef; -}; - - -############################################################################ -# -# Name: Version -# -# Purpose: Return version string -# -# Inputs: $class - This class -# -# Result: Version string; suitable for printing by "--version" -# -############################################################################ - -sub Version { - my $version = $DBI::ProxyServer::VERSION; - "DBI::ProxyServer $version, Copyright (C) 1998, Jochen Wiedmann"; -} - - -############################################################################ -# -# Name: AcceptApplication -# -# Purpose: Verify DBI DSN -# -# Inputs: $self - This instance -# $dsn - DBI dsn -# -# Returns: TRUE for a valid DSN, FALSE otherwise -# -############################################################################ - -sub AcceptApplication { - my $self = shift; my $dsn = shift; - $dsn =~ /^dbi:\w+:/i; -} - - -############################################################################ -# -# Name: AcceptVersion -# -# Purpose: Verify requested DBI version -# -# Inputs: $self - Instance -# $version - DBI version being requested -# -# Returns: TRUE for ok, FALSE otherwise -# -############################################################################ - -sub AcceptVersion { - my $self = shift; my $version = shift; - require DBI; - DBI::ProxyServer->init_rootclass(); - $DBI::VERSION >= $version; -} - - -############################################################################ -# -# Name: AcceptUser -# -# Purpose: Verify user and password by connecting to the client and -# creating a database connection -# -# Inputs: $self - Instance -# $user - User name -# $password - Password -# -############################################################################ - -sub AcceptUser { - my $self = shift; my $user = shift; my $password = shift; - return 0 if (!$self->SUPER::AcceptUser($user, $password)); - my $dsn = $self->{'application'}; - $self->Debug("Connecting to $dsn as $user"); - local $ENV{DBI_AUTOPROXY} = ''; # :-) - $self->{'dbh'} = eval { - DBI::ProxyServer->connect($dsn, $user, $password, - { 'PrintError' => 0, - 'Warn' => 0, - 'RaiseError' => 1, - 'HandleError' => sub { - my $err = $_[1]->err; - my $state = $_[1]->state || ''; - $_[0] .= " [err=$err,state=$state]"; - return 0; - } }) - }; - if ($@) { - $self->Error("Error while connecting to $dsn as $user: $@"); - return 0; - } - [1, $self->StoreHandle($self->{'dbh'}) ]; -} - - -sub CallMethod { - my $server = shift; - my $dbh = $server->{'dbh'}; - # We could store the private_server attribute permanently in - # $dbh. However, we'd have a reference loop in that case and - # I would be concerned about garbage collection. :-( - $dbh->{'private_server'} = $server; - $server->Debug("CallMethod: => " . do { local $^W; join(",", @_)}); - my @result = eval { $server->SUPER::CallMethod(@_) }; - my $msg = $@; - undef $dbh->{'private_server'}; - if ($msg) { - $server->Debug("CallMethod died with: $@"); - die $msg; - } else { - $server->Debug("CallMethod: <= " . do { local $^W; join(",", @result) }); - } - @result; -} - - -sub main { - my $server = DBI::ProxyServer->new(\%DEFAULT_SERVER_OPTIONS, \@_); - $server->Bind(); -} - - -############################################################################ -# -# The DBI part of the proxyserver is implemented as a DBI subclass. -# Thus we can reuse some of the DBI methods and overwrite only -# those that need additional handling. -# -############################################################################ - -package DBI::ProxyServer::dr; - -@DBI::ProxyServer::dr::ISA = qw(DBI::dr); - - -package DBI::ProxyServer::db; - -@DBI::ProxyServer::db::ISA = qw(DBI::db); - -sub prepare { - my($dbh, $statement, $attr, $params, $proto_ver) = @_; - my $server = $dbh->{'private_server'}; - if (my $client = $server->{'client'}) { - if ($client->{'sql'}) { - if ($statement =~ /^\s*(\S+)/) { - my $st = $1; - if (!($statement = $client->{'sql'}->{$st})) { - die "Unknown SQL query: $st"; - } - } else { - die "Cannot parse restricted SQL statement: $statement"; - } - } - } - my $sth = $dbh->SUPER::prepare($statement, $attr); - my $handle = $server->StoreHandle($sth); - - if ( $proto_ver and $proto_ver > 1 ) { - $sth->{private_proxyserver_described} = 0; - return $handle; - - } else { - # The difference between the usual prepare and ours is that we implement - # a combined prepare/execute. The DBD::Proxy driver doesn't call us for - # prepare. Only if an execute happens, then we are called with method - # "prepare". Further execute's are called as "execute". - my @result = $sth->execute($params); - my ($NAME, $TYPE); - my $NUM_OF_FIELDS = $sth->{NUM_OF_FIELDS}; - if ($NUM_OF_FIELDS) { # is a SELECT - $NAME = $sth->{NAME}; - $TYPE = $sth->{TYPE}; - } - ($handle, $NUM_OF_FIELDS, $sth->{'NUM_OF_PARAMS'}, - $NAME, $TYPE, @result); - } -} - -sub table_info { - my $dbh = shift; - my $sth = $dbh->SUPER::table_info(); - my $numFields = $sth->{'NUM_OF_FIELDS'}; - my $names = $sth->{'NAME'}; - my $types = $sth->{'TYPE'}; - - # We wouldn't need to send all the rows at this point, instead we could - # make use of $rsth->fetch() on the client as usual. - # The problem is that some drivers (namely DBD::ExampleP, DBD::mysql and - # DBD::mSQL) are returning foreign sth's here, thus an instance of - # DBI::st and not DBI::ProxyServer::st. We could fix this by permitting - # the client to execute method DBI::st, but I don't like this. - my @rows; - while (my ($row) = $sth->fetch()) { - last unless defined $row; - push(@rows, [@$row]); - } - ($numFields, $names, $types, @rows); -} - - -package DBI::ProxyServer::st; - -@DBI::ProxyServer::st::ISA = qw(DBI::st); - -sub execute { - my $sth = shift; my $params = shift; my $proto_ver = shift; - my @outParams; - if ($params) { - for (my $i = 0; $i < @$params;) { - my $param = $params->[$i++]; - if (!ref($param)) { - $sth->bind_param($i, $param); - } - else { - if (!ref(@$param[0])) {#It's not a reference - $sth->bind_param($i, @$param); - } - else { - $sth->bind_param_inout($i, @$param); - my $ref = shift @$param; - push(@outParams, $ref); - } - } - } - } - my $rows = $sth->SUPER::execute(); - if ( $proto_ver and $proto_ver > 1 and not $sth->{private_proxyserver_described} ) { - my ($NAME, $TYPE); - my $NUM_OF_FIELDS = $sth->{NUM_OF_FIELDS}; - if ($NUM_OF_FIELDS) { # is a SELECT - $NAME = $sth->{NAME}; - $TYPE = $sth->{TYPE}; - } - $sth->{private_proxyserver_described} = 1; - # First execution, we ship back description. - return ($rows, $NUM_OF_FIELDS, $sth->{'NUM_OF_PARAMS'}, $NAME, $TYPE, @outParams); - } - ($rows, @outParams); -} - -sub fetch { - my $sth = shift; my $numRows = shift || 1; - my($ref, @rows); - while ($numRows-- && ($ref = $sth->SUPER::fetch())) { - push(@rows, [@$ref]); - } - @rows; -} - - -1; - - -__END__ - -=head1 NAME - -DBI::ProxyServer - a server for the DBD::Proxy driver - -=head1 SYNOPSIS - - use DBI::ProxyServer; - DBI::ProxyServer::main(@ARGV); - -=head1 DESCRIPTION - -DBI::Proxy Server is a module for implementing a proxy for the DBI proxy -driver, DBD::Proxy. It allows access to databases over the network if the -DBMS does not offer networked operations. But the proxy server might be -useful for you, even if you have a DBMS with integrated network -functionality: It can be used as a DBI proxy in a firewalled environment. - -DBI::ProxyServer runs as a daemon on the machine with the DBMS or on the -firewall. The client connects to the agent using the DBI driver DBD::Proxy, -thus in the exactly same way than using DBD::mysql, DBD::mSQL or any other -DBI driver. - -The agent is implemented as a RPC::PlServer application. Thus you have -access to all the possibilities of this module, in particular encryption -and a similar configuration file. DBI::ProxyServer adds the possibility of -query restrictions: You can define a set of queries that a client may -execute and restrict access to those. (Requires a DBI driver that supports -parameter binding.) See L. - -The provided driver script, L, may either be used as it is or -used as the basis for a local version modified to meet your needs. - -=head1 OPTIONS - -When calling the DBI::ProxyServer::main() function, you supply an -array of options. These options are parsed by the Getopt::Long module. -The ProxyServer inherits all of RPC::PlServer's and hence Net::Daemon's -options and option handling, in particular the ability to read -options from either the command line or a config file. See -L. See L. Available options include - -=over 4 - -=item I (B<--chroot=dir>) - -(UNIX only) After doing a bind(), change root directory to the given -directory by doing a chroot(). This is useful for security, but it -restricts the environment a lot. For example, you need to load DBI -drivers in the config file or you have to create hard links to Unix -sockets, if your drivers are using them. For example, with MySQL, a -config file might contain the following lines: - - my $rootdir = '/var/dbiproxy'; - my $unixsockdir = '/tmp'; - my $unixsockfile = 'mysql.sock'; - foreach $dir ($rootdir, "$rootdir$unixsockdir") { - mkdir 0755, $dir; - } - link("$unixsockdir/$unixsockfile", - "$rootdir$unixsockdir/$unixsockfile"); - require DBD::mysql; - - { - 'chroot' => $rootdir, - ... - } - -If you don't know chroot(), think of an FTP server where you can see a -certain directory tree only after logging in. See also the --group and ---user options. - -=item I - -An array ref with a list of clients. Clients are hash refs, the attributes -I (0 for denying access and 1 for permitting) and I, a Perl -regular expression for the clients IP number or its host name. - -=item I (B<--configfile=file>) - -Config files are assumed to return a single hash ref that overrides the -arguments of the new method. However, command line arguments in turn take -precedence over the config file. See the L<"CONFIGURATION FILE"> section -below for details on the config file. - -=item I (B<--debug>) - -Turn debugging mode on. Mainly this asserts that logging messages of -level "debug" are created. - -=item I (B<--facility=mode>) - -(UNIX only) Facility to use for L. The default is -B. - -=item I (B<--group=gid>) - -After doing a bind(), change the real and effective GID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --user option. - -GID's can be passed as group names or numeric values. - -=item I (B<--localaddr=ip>) - -By default a daemon is listening to any IP number that a machine -has. This attribute allows one to restrict the server to the given -IP number. - -=item I (B<--localport=port>) - -This attribute sets the port on which the daemon is listening. It -must be given somehow, as there's no default. - -=item I (B<--logfile=file>) - -Be default logging messages will be written to the syslog (Unix) or -to the event log (Windows NT). On other operating systems you need to -specify a log file. The special value "STDERR" forces logging to -stderr. See L for details. - -=item I (B<--mode=modename>) - -The server can run in three different modes, depending on the environment. - -If you are running Perl 5.005 and did compile it for threads, then the -server will create a new thread for each connection. The thread will -execute the server's Run() method and then terminate. This mode is the -default, you can force it with "--mode=threads". - -If threads are not available, but you have a working fork(), then the -server will behave similar by creating a new process for each connection. -This mode will be used automatically in the absence of threads or if -you use the "--mode=fork" option. - -Finally there's a single-connection mode: If the server has accepted a -connection, he will enter the Run() method. No other connections are -accepted until the Run() method returns (if the client disconnects). -This operation mode is useful if you have neither threads nor fork(), -for example on the Macintosh. For debugging purposes you can force this -mode with "--mode=single". - -=item I (B<--pidfile=file>) - -(UNIX only) If this option is present, a PID file will be created at the -given location. Default is to not create a pidfile. - -=item I (B<--user=uid>) - -After doing a bind(), change the real and effective UID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --group and the --chroot options. - -UID's can be passed as group names or numeric values. - -=item I (B<--version>) - -Suppresses startup of the server; instead the version string will -be printed and the program exits immediately. - -=back - -=head1 SHUTDOWN - -DBI::ProxyServer is built on L which is, in turn, built on L. - -You should refer to L for how to shutdown the server, except that -you can't because it's not currently documented there (as of v0.43). -The bottom-line is that it seems that there's no support for graceful shutdown. - -=head1 CONFIGURATION FILE - -The configuration file is just that of I or I -with some additional attributes in the client list. - -The config file is a Perl script. At the top of the file you may include -arbitrary Perl source, for example load drivers at the start (useful -to enhance performance), prepare a chroot environment and so on. - -The important thing is that you finally return a hash ref of option -name/value pairs. The possible options are listed above. - -All possibilities of Net::Daemon and RPC::PlServer apply, in particular - -=over 4 - -=item Host and/or User dependent access control - -=item Host and/or User dependent encryption - -=item Changing UID and/or GID after binding to the port - -=item Running in a chroot() environment - -=back - -Additionally the server offers you query restrictions. Suggest the -following client list: - - 'clients' => [ - { 'mask' => '^admin\.company\.com$', - 'accept' => 1, - 'users' => [ 'root', 'wwwrun' ], - }, - { - 'mask' => '^admin\.company\.com$', - 'accept' => 1, - 'users' => [ 'root', 'wwwrun' ], - 'sql' => { - 'select' => 'SELECT * FROM foo', - 'insert' => 'INSERT INTO foo VALUES (?, ?, ?)' - } - } - -then only the users root and wwwrun may connect from admin.company.com, -executing arbitrary queries, but only wwwrun may connect from other -hosts and is restricted to - - $sth->prepare("select"); - -or - - $sth->prepare("insert"); - -which in fact are "SELECT * FROM foo" or "INSERT INTO foo VALUES (?, ?, ?)". - - -=head1 Proxyserver Configuration file (bigger example) - -This section tells you how to restrict a DBI-Proxy: Not every user from -every workstation shall be able to execute every query. - -There is a perl program "dbiproxy" which runs on a machine which is able -to connect to all the databases we wish to reach. All Perl-DBD-drivers must -be installed on this machine. You can also reach databases for which drivers -are not available on the machine where you run the program querying the -database, e.g. ask MS-Access-database from Linux. - -Create a configuration file "proxy_oracle.cfg" at the dbproxy-server: - - { - # This shall run in a shell or a DOS-window - # facility => 'daemon', - pidfile => 'your_dbiproxy.pid', - logfile => 1, - debug => 0, - mode => 'single', - localport => '12400', - - # Access control, the first match in this list wins! - # So the order is important - clients => [ - # hint to organize: - # the most specialized rules for single machines/users are 1st - # then the denying rules - # then the rules about whole networks - - # rule: internal_webserver - # desc: to get statistical information - { - # this IP-address only is meant - mask => '^10\.95\.81\.243$', - # accept (not defer) connections like this - accept => 1, - # only users from this list - # are allowed to log on - users => [ 'informationdesk' ], - # only this statistical query is allowed - # to get results for a web-query - sql => { - alive => 'select count(*) from dual', - statistic_area => 'select count(*) from e01admin.e01e203 where geb_bezei like ?', - } - }, - - # rule: internal_bad_guy_1 - { - mask => '^10\.95\.81\.1$', - accept => 0, - }, - - # rule: employee_workplace - # desc: get detailed information - { - # any IP-address is meant here - mask => '^10\.95\.81\.(\d+)$', - # accept (not defer) connections like this - accept => 1, - # only users from this list - # are allowed to log on - users => [ 'informationdesk', 'lippmann' ], - # all these queries are allowed: - sql => { - search_city => 'select ort_nr, plz, ort from e01admin.e01e200 where plz like ?', - search_area => 'select gebiettyp, geb_bezei from e01admin.e01e203 where geb_bezei like ? or geb_bezei like ?', - } - }, - - # rule: internal_bad_guy_2 - # This does NOT work, because rule "employee_workplace" hits - # with its ip-address-mask of the whole network - { - # don't accept connection from this ip-address - mask => '^10\.95\.81\.5$', - accept => 0, - } - ] - } - -Start the proxyserver like this: - - rem well-set Oracle_home needed for Oracle - set ORACLE_HOME=d:\oracle\ora81 - dbiproxy --configfile proxy_oracle.cfg - - -=head2 Testing the connection from a remote machine - -Call a program "dbish" from your commandline. I take the machine from rule "internal_webserver" - - dbish "dbi:Proxy:hostname=oracle.zdf;port=12400;dsn=dbi:Oracle:e01" informationdesk xxx - -There will be a shell-prompt: - - informationdesk@dbi...> alive - - Current statement buffer (enter '/'...): - alive - - informationdesk@dbi...> / - COUNT(*) - '1' - [1 rows of 1 fields returned] - - -=head2 Testing the connection with a perl-script - -Create a perl-script like this: - - # file: oratest.pl - # call me like this: perl oratest.pl user password - - use strict; - use DBI; - - my $user = shift || die "Usage: $0 user password"; - my $pass = shift || die "Usage: $0 user password"; - my $config = { - dsn_at_proxy => "dbi:Oracle:e01", - proxy => "hostname=oechsle.zdf;port=12400", - }; - my $dsn = sprintf "dbi:Proxy:%s;dsn=%s", - $config->{proxy}, - $config->{dsn_at_proxy}; - - my $dbh = DBI->connect( $dsn, $user, $pass ) - || die "connect did not work: $DBI::errstr"; - - my $sql = "search_city"; - printf "%s\n%s\n%s\n", "="x40, $sql, "="x40; - my $cur = $dbh->prepare($sql); - $cur->bind_param(1,'905%'); - &show_result ($cur); - - my $sql = "search_area"; - printf "%s\n%s\n%s\n", "="x40, $sql, "="x40; - my $cur = $dbh->prepare($sql); - $cur->bind_param(1,'Pfarr%'); - $cur->bind_param(2,'Bronnamberg%'); - &show_result ($cur); - - my $sql = "statistic_area"; - printf "%s\n%s\n%s\n", "="x40, $sql, "="x40; - my $cur = $dbh->prepare($sql); - $cur->bind_param(1,'Pfarr%'); - &show_result ($cur); - - $dbh->disconnect; - exit; - - - sub show_result { - my $cur = shift; - unless ($cur->execute()) { - print "Could not execute\n"; - return; - } - - my $rownum = 0; - while (my @row = $cur->fetchrow_array()) { - printf "Row is: %s\n", join(", ",@row); - if ($rownum++ > 5) { - print "... and so on\n"; - last; - } - } - $cur->finish; - } - -The result - - C:\>perl oratest.pl informationdesk xxx - ======================================== - search_city - ======================================== - Row is: 3322, 9050, Chemnitz - Row is: 3678, 9051, Chemnitz - Row is: 10447, 9051, Chemnitz - Row is: 12128, 9051, Chemnitz - Row is: 10954, 90513, Zirndorf - Row is: 5808, 90513, Zirndorf - Row is: 5715, 90513, Zirndorf - ... and so on - ======================================== - search_area - ======================================== - Row is: 101, Bronnamberg - Row is: 400, Pfarramt Zirndorf - Row is: 400, Pfarramt Rosstal - Row is: 400, Pfarramt Oberasbach - Row is: 401, Pfarramt Zirndorf - Row is: 401, Pfarramt Rosstal - ======================================== - statistic_area - ======================================== - DBD::Proxy::st execute failed: Server returned error: Failed to execute method CallMethod: Unknown SQL query: statistic_area at E:/Perl/site/lib/DBI/ProxyServer.pm line 258. - Could not execute - - -=head2 How the configuration works - -The most important section to control access to your dbi-proxy is "client=>" -in the file "proxy_oracle.cfg": - -Controlling which person at which machine is allowed to access - -=over 4 - -=item * "mask" is a perl regular expression against the plain ip-address of the machine which wishes to connect _or_ the reverse-lookup from a nameserver. - -=item * "accept" tells the dbiproxy-server whether ip-adresse like in "mask" are allowed to connect or not (0/1) - -=item * "users" is a reference to a list of usernames which must be matched, this is NOT a regular expression. - -=back - -Controlling which SQL-statements are allowed - -You can put every SQL-statement you like in simply omitting "sql => ...", but the more important thing is to restrict the connection so that only allowed queries are possible. - -If you include an sql-section in your config-file like this: - - sql => { - alive => 'select count(*) from dual', - statistic_area => 'select count(*) from e01admin.e01e203 where geb_bezei like ?', - } - -The user is allowed to put two queries against the dbi-proxy. The queries are _not_ "select count(*)...", the queries are "alive" and "statistic_area"! These keywords are replaced by the real query. So you can run a query for "alive": - - my $sql = "alive"; - my $cur = $dbh->prepare($sql); - ... - -The flexibility is that you can put parameters in the where-part of the query so the query are not static. Simply replace a value in the where-part of the query through a question mark and bind it as a parameter to the query. - - my $sql = "statistic_area"; - my $cur = $dbh->prepare($sql); - $cur->bind_param(1,'905%'); - # A second parameter would be called like this: - # $cur->bind_param(2,'98%'); - -The result is this query: - - select count(*) from e01admin.e01e203 - where geb_bezei like '905%' - -Don't try to put parameters into the sql-query like this: - - # Does not work like you think. - # Only the first word of the query is parsed, - # so it's changed to "statistic_area", the rest is omitted. - # You _have_ to work with $cur->bind_param. - my $sql = "statistic_area 905%"; - my $cur = $dbh->prepare($sql); - ... - - -=head2 Problems - -=over 4 - -=item * I don't know how to restrict users to special databases. - -=item * I don't know how to pass query-parameters via dbish - -=back - - -=head1 SECURITY WARNING - -L used underneath is not secure due to serializing and -deserializing data with L module. Use the proxy driver only in -trusted environment. - - -=head1 AUTHOR - - Copyright (c) 1997 Jochen Wiedmann - Am Eisteich 9 - 72555 Metzingen - Germany - - Email: joe@ispsoft.de - Phone: +49 7123 14881 - -The DBI::ProxyServer module is free software; you can redistribute it -and/or modify it under the same terms as Perl itself. In particular -permission is granted to Tim Bunce for distributing this as a part of -the DBI. - - -=head1 SEE ALSO - -L, L, L, L, -L, L, L, -L, L, L diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/PurePerl.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/PurePerl.pm deleted file mode 100644 index 32a8f1f..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/PurePerl.pm +++ /dev/null @@ -1,1279 +0,0 @@ -######################################################################## -package # hide from PAUSE - DBI; -# vim: ts=8:sw=4 -######################################################################## -# -# Copyright (c) 2002,2003 Tim Bunce Ireland. -# -# See COPYRIGHT section in DBI.pm for usage and distribution rights. -# -######################################################################## -# -# Please send patches and bug reports to -# -# Jeff Zucker with cc to -# -######################################################################## - -use strict; -use Carp; -require Symbol; - -require utf8; -*utf8::is_utf8 = sub { # hack for perl 5.6 - require bytes; - return unless defined $_[0]; - return !(length($_[0]) == bytes::length($_[0])) -} unless defined &utf8::is_utf8; - -$DBI::PurePerl = $ENV{DBI_PUREPERL} || 1; -$DBI::PurePerl::VERSION = "2.014286"; - -$DBI::neat_maxlen ||= 400; - -$DBI::tfh = Symbol::gensym(); -open $DBI::tfh, ">&STDERR" or warn "Can't dup STDERR: $!"; -select( (select($DBI::tfh), $| = 1)[0] ); # autoflush - -# check for weaken support, used by ChildHandles -my $HAS_WEAKEN = eval { - require Scalar::Util; - # this will croak() if this Scalar::Util doesn't have a working weaken(). - Scalar::Util::weaken( my $test = [] ); - 1; -}; - -%DBI::last_method_except = map { $_=>1 } qw(DESTROY _set_fbav set_err); - -use constant SQL_ALL_TYPES => 0; -use constant SQL_ARRAY => 50; -use constant SQL_ARRAY_LOCATOR => 51; -use constant SQL_BIGINT => (-5); -use constant SQL_BINARY => (-2); -use constant SQL_BIT => (-7); -use constant SQL_BLOB => 30; -use constant SQL_BLOB_LOCATOR => 31; -use constant SQL_BOOLEAN => 16; -use constant SQL_CHAR => 1; -use constant SQL_CLOB => 40; -use constant SQL_CLOB_LOCATOR => 41; -use constant SQL_DATE => 9; -use constant SQL_DATETIME => 9; -use constant SQL_DECIMAL => 3; -use constant SQL_DOUBLE => 8; -use constant SQL_FLOAT => 6; -use constant SQL_GUID => (-11); -use constant SQL_INTEGER => 4; -use constant SQL_INTERVAL => 10; -use constant SQL_INTERVAL_DAY => 103; -use constant SQL_INTERVAL_DAY_TO_HOUR => 108; -use constant SQL_INTERVAL_DAY_TO_MINUTE => 109; -use constant SQL_INTERVAL_DAY_TO_SECOND => 110; -use constant SQL_INTERVAL_HOUR => 104; -use constant SQL_INTERVAL_HOUR_TO_MINUTE => 111; -use constant SQL_INTERVAL_HOUR_TO_SECOND => 112; -use constant SQL_INTERVAL_MINUTE => 105; -use constant SQL_INTERVAL_MINUTE_TO_SECOND => 113; -use constant SQL_INTERVAL_MONTH => 102; -use constant SQL_INTERVAL_SECOND => 106; -use constant SQL_INTERVAL_YEAR => 101; -use constant SQL_INTERVAL_YEAR_TO_MONTH => 107; -use constant SQL_LONGVARBINARY => (-4); -use constant SQL_LONGVARCHAR => (-1); -use constant SQL_MULTISET => 55; -use constant SQL_MULTISET_LOCATOR => 56; -use constant SQL_NUMERIC => 2; -use constant SQL_REAL => 7; -use constant SQL_REF => 20; -use constant SQL_ROW => 19; -use constant SQL_SMALLINT => 5; -use constant SQL_TIME => 10; -use constant SQL_TIMESTAMP => 11; -use constant SQL_TINYINT => (-6); -use constant SQL_TYPE_DATE => 91; -use constant SQL_TYPE_TIME => 92; -use constant SQL_TYPE_TIMESTAMP => 93; -use constant SQL_TYPE_TIMESTAMP_WITH_TIMEZONE => 95; -use constant SQL_TYPE_TIME_WITH_TIMEZONE => 94; -use constant SQL_UDT => 17; -use constant SQL_UDT_LOCATOR => 18; -use constant SQL_UNKNOWN_TYPE => 0; -use constant SQL_VARBINARY => (-3); -use constant SQL_VARCHAR => 12; -use constant SQL_WCHAR => (-8); -use constant SQL_WLONGVARCHAR => (-10); -use constant SQL_WVARCHAR => (-9); - -# for Cursor types -use constant SQL_CURSOR_FORWARD_ONLY => 0; -use constant SQL_CURSOR_KEYSET_DRIVEN => 1; -use constant SQL_CURSOR_DYNAMIC => 2; -use constant SQL_CURSOR_STATIC => 3; -use constant SQL_CURSOR_TYPE_DEFAULT => SQL_CURSOR_FORWARD_ONLY; - -use constant IMA_HAS_USAGE => 0x0001; #/* check parameter usage */ -use constant IMA_FUNC_REDIRECT => 0x0002; #/* is $h->func(..., "method")*/ -use constant IMA_KEEP_ERR => 0x0004; #/* don't reset err & errstr */ -use constant IMA_KEEP_ERR_SUB => 0x0008; #/* '' if in nested call */ -use constant IMA_NO_TAINT_IN => 0x0010; #/* don't check for tainted args*/ -use constant IMA_NO_TAINT_OUT => 0x0020; #/* don't taint results */ -use constant IMA_COPY_UP_STMT => 0x0040; #/* copy sth Statement to dbh */ -use constant IMA_END_WORK => 0x0080; #/* set on commit & rollback */ -use constant IMA_STUB => 0x0100; #/* do nothing eg $dbh->connected */ -use constant IMA_CLEAR_STMT => 0x0200; #/* clear Statement before call */ -use constant IMA_UNRELATED_TO_STMT=> 0x0400; #/* profile as empty Statement */ -use constant IMA_NOT_FOUND_OKAY => 0x0800; #/* not error if not found */ -use constant IMA_EXECUTE => 0x1000; #/* do/execute: DBIcf_Executed */ -use constant IMA_SHOW_ERR_STMT => 0x2000; #/* dbh meth relates to Statement*/ -use constant IMA_HIDE_ERR_PARAMVALUES => 0x4000; #/* ParamValues are not relevant */ -use constant IMA_IS_FACTORY => 0x8000; #/* new h ie connect & prepare */ -use constant IMA_CLEAR_CACHED_KIDS => 0x10000; #/* clear CachedKids before call */ - -use constant DBIstcf_STRICT => 0x0001; -use constant DBIstcf_DISCARD_STRING => 0x0002; - -my %is_flag_attribute = map {$_ =>1 } qw( - Active - AutoCommit - ChopBlanks - CompatMode - Executed - Taint - TaintIn - TaintOut - InactiveDestroy - AutoInactiveDestroy - LongTruncOk - MultiThread - PrintError - PrintWarn - RaiseError - ShowErrorStatement - Warn -); -my %is_valid_attribute = map {$_ =>1 } (keys %is_flag_attribute, qw( - ActiveKids - Attribution - BegunWork - CachedKids - Callbacks - ChildHandles - CursorName - Database - DebugDispatch - Driver - Err - Errstr - ErrCount - FetchHashKeyName - HandleError - HandleSetErr - ImplementorClass - Kids - LongReadLen - NAME NAME_uc NAME_lc NAME_uc_hash NAME_lc_hash - NULLABLE - NUM_OF_FIELDS - NUM_OF_PARAMS - Name - PRECISION - ParamValues - Profile - Provider - ReadOnly - RootClass - RowCacheSize - RowsInCache - SCALE - State - Statement - TYPE - Type - TraceLevel - Username - Version -)); - -sub valid_attribute { - my $attr = shift; - return 1 if $is_valid_attribute{$attr}; - return 1 if $attr =~ m/^[a-z]/; # starts with lowercase letter - return 0 -} - -my $initial_setup; -sub initial_setup { - $initial_setup = 1; - print $DBI::tfh __FILE__ . " version " . $DBI::PurePerl::VERSION . "\n" - if $DBI::dbi_debug & 0xF; - untie $DBI::err; - untie $DBI::errstr; - untie $DBI::state; - untie $DBI::rows; - #tie $DBI::lasth, 'DBI::var', '!lasth'; # special case: return boolean -} - -sub _install_method { - my ( $caller, $method, $from, $param_hash ) = @_; - initial_setup() unless $initial_setup; - - my ($class, $method_name) = $method =~ /^[^:]+::(.+)::(.+)$/; - my $bitmask = $param_hash->{'O'} || 0; - my @pre_call_frag; - - return if $method_name eq 'can'; - - push @pre_call_frag, q{ - delete $h->{CachedKids}; - # ignore DESTROY for outer handle (DESTROY for inner likely to follow soon) - return if $h_inner; - # handle AutoInactiveDestroy and InactiveDestroy - $h->{InactiveDestroy} = 1 - if $h->{AutoInactiveDestroy} and $$ != $h->{dbi_pp_pid}; - $h->{Active} = 0 - if $h->{InactiveDestroy}; - # copy err/errstr/state up to driver so $DBI::err etc still work - if ($h->{err} and my $drh = $h->{Driver}) { - $drh->{$_} = $h->{$_} for ('err','errstr','state'); - } - } if $method_name eq 'DESTROY'; - - push @pre_call_frag, q{ - return $h->{$_[0]} if exists $h->{$_[0]}; - } if $method_name eq 'FETCH' && !exists $ENV{DBI_TRACE}; # XXX ? - - push @pre_call_frag, "return;" - if IMA_STUB & $bitmask; - - push @pre_call_frag, q{ - $method_name = pop @_; - } if IMA_FUNC_REDIRECT & $bitmask; - - push @pre_call_frag, q{ - my $parent_dbh = $h->{Database}; - } if (IMA_COPY_UP_STMT|IMA_EXECUTE) & $bitmask; - - push @pre_call_frag, q{ - warn "No Database set for $h on $method_name!" unless $parent_dbh; # eg proxy problems - $parent_dbh->{Statement} = $h->{Statement} if $parent_dbh; - } if IMA_COPY_UP_STMT & $bitmask; - - push @pre_call_frag, q{ - $h->{Executed} = 1; - $parent_dbh->{Executed} = 1 if $parent_dbh; - } if IMA_EXECUTE & $bitmask; - - push @pre_call_frag, q{ - %{ $h->{CachedKids} } = () if $h->{CachedKids}; - } if IMA_CLEAR_CACHED_KIDS & $bitmask; - - if (IMA_KEEP_ERR & $bitmask) { - push @pre_call_frag, q{ - my $keep_error = DBI::_err_hash($h); - }; - } - else { - my $ke_init = (IMA_KEEP_ERR_SUB & $bitmask) - ? q{= ($h->{dbi_pp_parent}->{dbi_pp_call_depth} && DBI::_err_hash($h)) } - : ""; - push @pre_call_frag, qq{ - my \$keep_error $ke_init; - }; - my $clear_error_code = q{ - #warn "$method_name cleared err"; - $h->{err} = $DBI::err = undef; - $h->{errstr} = $DBI::errstr = undef; - $h->{state} = $DBI::state = ''; - }; - $clear_error_code = q{ - printf $DBI::tfh " !! %s: %s CLEARED by call to }.$method_name.q{ method\n". - $h->{err}, $h->{err} - if defined $h->{err} && $DBI::dbi_debug & 0xF; - }. $clear_error_code - if exists $ENV{DBI_TRACE}; - push @pre_call_frag, ($ke_init) - ? qq{ unless (\$keep_error) { $clear_error_code }} - : $clear_error_code - unless $method_name eq 'set_err'; - } - - push @pre_call_frag, q{ - my $ErrCount = $h->{ErrCount}; - }; - - push @pre_call_frag, q{ - if (($DBI::dbi_debug & 0xF) >= 2) { - local $^W; - my $args = join " ", map { DBI::neat($_) } ($h, @_); - printf $DBI::tfh " > $method_name in $imp ($args) [$@]\n"; - } - } if exists $ENV{DBI_TRACE}; # note use of 'exists' - - push @pre_call_frag, q{ - $h->{'dbi_pp_last_method'} = $method_name; - } unless exists $DBI::last_method_except{$method_name}; - - # --- post method call code fragments --- - my @post_call_frag; - - push @post_call_frag, q{ - if (my $trace_level = ($DBI::dbi_debug & 0xF)) { - if ($h->{err}) { - printf $DBI::tfh " !! ERROR: %s %s\n", $h->{err}, $h->{errstr}; - } - my $ret = join " ", map { DBI::neat($_) } @ret; - my $msg = " < $method_name= $ret"; - $msg = ($trace_level >= 2) ? Carp::shortmess($msg) : "$msg\n"; - print $DBI::tfh $msg; - } - } if exists $ENV{DBI_TRACE}; # note use of exists - - push @post_call_frag, q{ - $h->{Executed} = 0; - if ($h->{BegunWork}) { - $h->{BegunWork} = 0; - $h->{AutoCommit} = 1; - } - } if IMA_END_WORK & $bitmask; - - push @post_call_frag, q{ - if ( ref $ret[0] and - UNIVERSAL::isa($ret[0], 'DBI::_::common') and - defined( (my $h_new = tied(%{$ret[0]})||$ret[0])->{err} ) - ) { - # copy up info/warn to drh so PrintWarn on connect is triggered - $h->set_err($h_new->{err}, $h_new->{errstr}, $h_new->{state}) - } - } if IMA_IS_FACTORY & $bitmask; - - push @post_call_frag, q{ - if ($keep_error) { - $keep_error = 0 - if $h->{ErrCount} > $ErrCount - or DBI::_err_hash($h) ne $keep_error; - } - - $DBI::err = $h->{err}; - $DBI::errstr = $h->{errstr}; - $DBI::state = $h->{state}; - - if ( !$keep_error - && defined(my $err = $h->{err}) - && ($call_depth <= 1 && !$h->{dbi_pp_parent}{dbi_pp_call_depth}) - ) { - - my($pe,$pw,$re,$he) = @{$h}{qw(PrintError PrintWarn RaiseError HandleError)}; - my $msg; - - if ($err && ($pe || $re || $he) # error - or (!$err && length($err) && $pw) # warning - ) { - my $last = ($DBI::last_method_except{$method_name}) - ? ($h->{'dbi_pp_last_method'}||$method_name) : $method_name; - my $errstr = $h->{errstr} || $DBI::errstr || $err || ''; - my $msg = sprintf "%s %s %s: %s", $imp, $last, - ($err eq "0") ? "warning" : "failed", $errstr; - - if ($h->{'ShowErrorStatement'} and my $Statement = $h->{Statement}) { - $msg .= ' [for Statement "' . $Statement; - if (my $ParamValues = $h->FETCH('ParamValues')) { - $msg .= '" with ParamValues: '; - $msg .= DBI::_concat_hash_sorted($ParamValues, "=", ", ", 1, undef); - $msg .= "]"; - } - else { - $msg .= '"]'; - } - } - if ($err eq "0") { # is 'warning' (not info) - carp $msg if $pw; - } - else { - my $do_croak = 1; - if (my $subsub = $h->{'HandleError'}) { - $do_croak = 0 if &$subsub($msg,$h,$ret[0]); - } - if ($do_croak) { - printf $DBI::tfh " $method_name has failed ($h->{PrintError},$h->{RaiseError})\n" - if ($DBI::dbi_debug & 0xF) >= 4; - carp $msg if $pe; - die $msg if $h->{RaiseError}; - } - } - } - } - }; - - - my $method_code = q[ - sub { - my $h = shift; - my $h_inner = tied(%$h); - $h = $h_inner if $h_inner; - - my $imp; - if ($method_name eq 'DESTROY') { - # during global destruction, $h->{...} can trigger "Can't call FETCH on an undef value" - # implying that tied() above lied to us, so we need to use eval - local $@; # protect $@ - $imp = eval { $h->{"ImplementorClass"} } or return; # probably global destruction - } - else { - $imp = $h->{"ImplementorClass"} or do { - warn "Can't call $method_name method on handle $h after take_imp_data()\n" - if not exists $h->{Active}; - return; # or, more likely, global destruction - }; - } - - ] . join("\n", '', @pre_call_frag, '') . q[ - - my $call_depth = $h->{'dbi_pp_call_depth'} + 1; - local ($h->{'dbi_pp_call_depth'}) = $call_depth; - - my @ret; - my $sub = $imp->can($method_name); - if (!$sub and IMA_FUNC_REDIRECT & $bitmask and $sub = $imp->can('func')) { - push @_, $method_name; - } - if ($sub) { - (wantarray) ? (@ret = &$sub($h,@_)) : (@ret = scalar &$sub($h,@_)); - } - else { - # XXX could try explicit fallback to $imp->can('AUTOLOAD') etc - # which would then let Multiplex pass PurePerl tests, but some - # hook into install_method may be better. - croak "Can't locate DBI object method \"$method_name\" via package \"$imp\"" - if ] . ((IMA_NOT_FOUND_OKAY & $bitmask) ? 0 : 1) . q[; - } - - ] . join("\n", '', @post_call_frag, '') . q[ - - return (wantarray) ? @ret : $ret[0]; - } - ]; - no strict qw(refs); - my $code_ref = eval qq{#line 1 "DBI::PurePerl $method"\n$method_code}; - warn "$@\n$method_code\n" if $@; - die "$@\n$method_code\n" if $@; - *$method = $code_ref; - if (0 && $method =~ /\b(connect|FETCH)\b/) { # debuging tool - my $l=0; # show line-numbered code for method - warn "*$method code:\n".join("\n", map { ++$l.": $_" } split/\n/,$method_code); - } -} - - -sub _new_handle { - my ($class, $parent, $attr, $imp_data, $imp_class) = @_; - - DBI->trace_msg(" New $class (for $imp_class, parent=$parent, id=".($imp_data||'').")\n") - if $DBI::dbi_debug >= 3; - - $attr->{ImplementorClass} = $imp_class - or Carp::croak("_new_handle($class): 'ImplementorClass' attribute not given"); - - # This is how we create a DBI style Object: - # %outer gets tied to %$attr (which becomes the 'inner' handle) - my (%outer, $i, $h); - $i = tie %outer, $class, $attr; # ref to inner hash (for driver) - $h = bless \%outer, $class; # ref to outer hash (for application) - # The above tie and bless may migrate down into _setup_handle()... - # Now add magic so DBI method dispatch works - DBI::_setup_handle($h, $imp_class, $parent, $imp_data); - return $h unless wantarray; - return ($h, $i); -} - -sub _setup_handle { - my($h, $imp_class, $parent, $imp_data) = @_; - my $h_inner = tied(%$h) || $h; - if (($DBI::dbi_debug & 0xF) >= 4) { - local $^W; - print $DBI::tfh " _setup_handle(@_)\n"; - } - $h_inner->{"imp_data"} = $imp_data; - $h_inner->{"ImplementorClass"} = $imp_class; - $h_inner->{"Kids"} = $h_inner->{"ActiveKids"} = 0; # XXX not maintained - if ($parent) { - foreach (qw( - RaiseError PrintError PrintWarn HandleError HandleSetErr - Warn LongTruncOk ChopBlanks AutoCommit ReadOnly - ShowErrorStatement FetchHashKeyName LongReadLen CompatMode - )) { - $h_inner->{$_} = $parent->{$_} - if exists $parent->{$_} && !exists $h_inner->{$_}; - } - if (ref($parent) =~ /::db$/) { # is sth - $h_inner->{Database} = $parent; - $parent->{Statement} = $h_inner->{Statement}; - $h_inner->{NUM_OF_PARAMS} = 0; - $h_inner->{Active} = 0; # driver sets true when there's data to fetch - } - elsif (ref($parent) =~ /::dr$/){ # is dbh - $h_inner->{Driver} = $parent; - $h_inner->{Active} = 0; - } - else { - warn "panic: ".ref($parent); # should never happen - } - $h_inner->{dbi_pp_parent} = $parent; - - # add to the parent's ChildHandles - if ($HAS_WEAKEN) { - my $handles = $parent->{ChildHandles} ||= []; - push @$handles, $h; - Scalar::Util::weaken($handles->[-1]); - # purge destroyed handles occasionally - if (@$handles % 120 == 0) { - @$handles = grep { defined } @$handles; - Scalar::Util::weaken($_) for @$handles; # re-weaken after grep - } - } - } - else { # setting up a driver handle - $h_inner->{Warn} = 1; - $h_inner->{PrintWarn} = 1; - $h_inner->{AutoCommit} = 1; - $h_inner->{TraceLevel} = 0; - $h_inner->{CompatMode} = (1==0); - $h_inner->{FetchHashKeyName} ||= 'NAME'; - $h_inner->{LongReadLen} ||= 80; - $h_inner->{ChildHandles} ||= [] if $HAS_WEAKEN; - $h_inner->{Type} ||= 'dr'; - $h_inner->{Active} = 1; - } - $h_inner->{"dbi_pp_call_depth"} = 0; - $h_inner->{"dbi_pp_pid"} = $$; - $h_inner->{ErrCount} = 0; -} - -sub constant { - warn "constant(@_) called unexpectedly"; return undef; -} - -sub trace { - my ($h, $level, $file) = @_; - $level = $h->parse_trace_flags($level) - if defined $level and !DBI::looks_like_number($level); - my $old_level = $DBI::dbi_debug; - _set_trace_file($file) if $level; - if (defined $level) { - $DBI::dbi_debug = $level; - print $DBI::tfh " DBI $DBI::VERSION (PurePerl) " - . "dispatch trace level set to $DBI::dbi_debug\n" - if $DBI::dbi_debug & 0xF; - } - _set_trace_file($file) if !$level; - return $old_level; -} - -sub _set_trace_file { - my ($file) = @_; - # - # DAA add support for filehandle inputs - # - # DAA required to avoid closing a prior fh trace() - $DBI::tfh = undef unless $DBI::tfh_needs_close; - - if (ref $file eq 'GLOB') { - $DBI::tfh = $file; - select((select($DBI::tfh), $| = 1)[0]); - $DBI::tfh_needs_close = 0; - return 1; - } - if ($file && ref \$file eq 'GLOB') { - $DBI::tfh = *{$file}{IO}; - select((select($DBI::tfh), $| = 1)[0]); - $DBI::tfh_needs_close = 0; - return 1; - } - $DBI::tfh_needs_close = 1; - if (!$file || $file eq 'STDERR') { - open $DBI::tfh, ">&STDERR" or carp "Can't dup STDERR: $!"; - } - elsif ($file eq 'STDOUT') { - open $DBI::tfh, ">&STDOUT" or carp "Can't dup STDOUT: $!"; - } - else { - open $DBI::tfh, ">>$file" or carp "Can't open $file: $!"; - } - select((select($DBI::tfh), $| = 1)[0]); - return 1; -} -sub _get_imp_data { shift->{"imp_data"}; } -sub _svdump { } -sub dump_handle { - my ($h,$msg,$level) = @_; - $msg||="dump_handle $h"; - print $DBI::tfh "$msg:\n"; - for my $attrib (sort keys %$h) { - print $DBI::tfh "\t$attrib => ".DBI::neat($h->{$attrib})."\n"; - } -} - -sub _handles { - my $h = shift; - my $h_inner = tied %$h; - if ($h_inner) { # this is okay - return $h unless wantarray; - return ($h, $h_inner); - } - # XXX this isn't okay... we have an inner handle but - # currently have no way to get at its outer handle, - # so we just warn and return the inner one for both... - Carp::carp("Can't return outer handle from inner handle using DBI::PurePerl"); - return $h unless wantarray; - return ($h,$h); -} - -sub hash { - my ($key, $type) = @_; - my ($hash); - if (!$type) { - $hash = 0; - # XXX The C version uses the "char" type, which could be either - # signed or unsigned. I use signed because so do the two - # compilers on my system. - for my $char (unpack ("c*", $key)) { - $hash = $hash * 33 + $char; - } - $hash &= 0x7FFFFFFF; # limit to 31 bits - $hash |= 0x40000000; # set bit 31 - return -$hash; # return negative int - } - elsif ($type == 1) { # Fowler/Noll/Vo hash - # see http://www.isthe.com/chongo/tech/comp/fnv/ - require Math::BigInt; # feel free to reimplement w/o BigInt! - (my $version = $Math::BigInt::VERSION || 0) =~ s/_.*//; # eg "1.70_01" - if ($version >= 1.56) { - $hash = Math::BigInt->new(0x811c9dc5); - for my $uchar (unpack ("C*", $key)) { - # multiply by the 32 bit FNV magic prime mod 2^64 - $hash = ($hash * 0x01000193) & 0xffffffff; - # xor the bottom with the current octet - $hash ^= $uchar; - } - # cast to int - return unpack "i", pack "i", $hash; - } - croak("DBI::PurePerl doesn't support hash type 1 without Math::BigInt >= 1.56 (available on CPAN)"); - } - else { - croak("bad hash type $type"); - } -} - -sub looks_like_number { - my @new = (); - for my $thing(@_) { - if (!defined $thing or $thing eq '') { - push @new, undef; - } - else { - push @new, ($thing =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) ? 1 : 0; - } - } - return (@_ >1) ? @new : $new[0]; -} - -sub neat { - my $v = shift; - return "undef" unless defined $v; - my $quote = q{"}; - if (not utf8::is_utf8($v)) { - return $v if (($v & ~ $v) eq "0"); # is SvNIOK - $quote = q{'}; - } - my $maxlen = shift || $DBI::neat_maxlen; - if ($maxlen && $maxlen < length($v) + 2) { - $v = substr($v,0,$maxlen-5); - $v .= '...'; - } - $v =~ s/[^[:print:]]/./g; - return "$quote$v$quote"; -} - -sub sql_type_cast { - my (undef, $sql_type, $flags) = @_; - - return -1 unless defined $_[0]; - - my $cast_ok = 1; - - my $evalret = eval { - use warnings FATAL => qw(numeric); - if ($sql_type == SQL_INTEGER) { - my $dummy = $_[0] + 0; - return 1; - } - elsif ($sql_type == SQL_DOUBLE) { - my $dummy = $_[0] + 0.0; - return 1; - } - elsif ($sql_type == SQL_NUMERIC) { - my $dummy = $_[0] + 0.0; - return 1; - } - else { - return -2; - } - } or $^W && warn $@; # XXX warnings::warnif("numeric", $@) ? - - return $evalret if defined($evalret) && ($evalret == -2); - $cast_ok = 0 unless $evalret; - - # DBIstcf_DISCARD_STRING not supported for PurePerl currently - - return 2 if $cast_ok; - return 0 if $flags & DBIstcf_STRICT; - return 1; -} - -sub dbi_time { - return time(); -} - -sub DBI::st::TIEHASH { bless $_[1] => $_[0] }; - -sub _concat_hash_sorted { - my ( $hash_ref, $kv_separator, $pair_separator, $use_neat, $num_sort ) = @_; - # $num_sort: 0=lexical, 1=numeric, undef=try to guess - - return undef unless defined $hash_ref; - die "hash is not a hash reference" unless ref $hash_ref eq 'HASH'; - my $keys = _get_sorted_hash_keys($hash_ref, $num_sort); - my $string = ''; - for my $key (@$keys) { - $string .= $pair_separator if length $string > 0; - my $value = $hash_ref->{$key}; - if ($use_neat) { - $value = DBI::neat($value, 0); - } - else { - $value = (defined $value) ? "'$value'" : 'undef'; - } - $string .= $key . $kv_separator . $value; - } - return $string; -} - -sub _get_sorted_hash_keys { - my ($hash_ref, $num_sort) = @_; - if (not defined $num_sort) { - my $sort_guess = 1; - $sort_guess = (not looks_like_number($_)) ? 0 : $sort_guess - for keys %$hash_ref; - $num_sort = $sort_guess; - } - - my @keys = keys %$hash_ref; - no warnings 'numeric'; - my @sorted = ($num_sort) - ? sort { $a <=> $b or $a cmp $b } @keys - : sort @keys; - return \@sorted; -} - -sub _err_hash { - return 1 unless defined $_[0]->{err}; - return "$_[0]->{err} $_[0]->{errstr}" -} - - -package - DBI::var; - -sub FETCH { - my($key)=shift; - return $DBI::err if $$key eq '*err'; - return $DBI::errstr if $$key eq '&errstr'; - Carp::confess("FETCH $key not supported when using DBI::PurePerl"); -} - -package - DBD::_::common; - -sub swap_inner_handle { - my ($h1, $h2) = @_; - # can't make this work till we can get the outer handle from the inner one - # probably via a WeakRef - return $h1->set_err($DBI::stderr, "swap_inner_handle not currently supported by DBI::PurePerl"); -} - -sub trace { # XXX should set per-handle level, not global - my ($h, $level, $file) = @_; - $level = $h->parse_trace_flags($level) - if defined $level and !DBI::looks_like_number($level); - my $old_level = $DBI::dbi_debug; - DBI::_set_trace_file($file) if defined $file; - if (defined $level) { - $DBI::dbi_debug = $level; - if ($DBI::dbi_debug) { - printf $DBI::tfh - " %s trace level set to %d in DBI $DBI::VERSION (PurePerl)\n", - $h, $DBI::dbi_debug; - print $DBI::tfh " Full trace not available because DBI_TRACE is not in environment\n" - unless exists $ENV{DBI_TRACE}; - } - } - return $old_level; -} -*debug = \&trace; *debug = \&trace; # twice to avoid typo warning - -sub FETCH { - my($h,$key)= @_; - my $v = $h->{$key}; - #warn ((exists $h->{$key}) ? "$key=$v\n" : "$key NONEXISTANT\n"); - return $v if defined $v; - if ($key =~ /^NAME_.c$/) { - my $cols = $h->FETCH('NAME'); - return undef unless $cols; - my @lcols = map { lc $_ } @$cols; - $h->{NAME_lc} = \@lcols; - my @ucols = map { uc $_ } @$cols; - $h->{NAME_uc} = \@ucols; - return $h->FETCH($key); - } - if ($key =~ /^NAME.*_hash$/) { - my $i=0; - for my $c(@{$h->FETCH('NAME')||[]}) { - $h->{'NAME_hash'}->{$c} = $i; - $h->{'NAME_lc_hash'}->{"\L$c"} = $i; - $h->{'NAME_uc_hash'}->{"\U$c"} = $i; - $i++; - } - return $h->{$key}; - } - if (!defined $v && !exists $h->{$key}) { - return ($h->FETCH('TaintIn') && $h->FETCH('TaintOut')) if $key eq'Taint'; - return (1==0) if $is_flag_attribute{$key}; # return perl-style sv_no, not undef - return $DBI::dbi_debug if $key eq 'TraceLevel'; - return [] if $key eq 'ChildHandles' && $HAS_WEAKEN; - if ($key eq 'Type') { - return "dr" if $h->isa('DBI::dr'); - return "db" if $h->isa('DBI::db'); - return "st" if $h->isa('DBI::st'); - Carp::carp( sprintf "Can't determine Type for %s",$h ); - } - if (!$is_valid_attribute{$key} and $key =~ m/^[A-Z]/) { - local $^W; # hide undef warnings - Carp::carp( sprintf "Can't get %s->{%s}: unrecognised attribute (@{[ %$h ]})",$h,$key ) - } - } - return $v; -} -sub STORE { - my ($h,$key,$value) = @_; - if ($key eq 'AutoCommit') { - Carp::croak("DBD driver has not implemented the AutoCommit attribute") - unless $value == -900 || $value == -901; - $value = ($value == -901); - } - elsif ($key =~ /^Taint/ ) { - Carp::croak(sprintf "Can't set %s->{%s}: Taint mode not supported by DBI::PurePerl",$h,$key) - if $value; - } - elsif ($key eq 'TraceLevel') { - $h->trace($value); - return 1; - } - elsif ($key eq 'NUM_OF_FIELDS') { - $h->{$key} = $value; - if ($value) { - my $fbav = DBD::_::st::dbih_setup_fbav($h); - @$fbav = (undef) x $value if @$fbav != $value; - } - return 1; - } - elsif (!$is_valid_attribute{$key} && $key =~ /^[A-Z]/ && !exists $h->{$key}) { - Carp::carp(sprintf "Can't set %s->{%s}: unrecognised attribute or invalid value %s", - $h,$key,$value); - } - $h->{$key} = $is_flag_attribute{$key} ? !!$value : $value; - Scalar::Util::weaken($h->{$key}) if $key eq 'CachedKids'; - return 1; -} -sub DELETE { - my ($h, $key) = @_; - return $h->FETCH($key) unless $key =~ /^private_/; - return delete $h->{$key}; -} -sub err { return shift->{err} } -sub errstr { return shift->{errstr} } -sub state { return shift->{state} } -sub set_err { - my ($h, $errnum,$msg,$state, $method, $rv) = @_; - $h = tied(%$h) || $h; - - if (my $hss = $h->{HandleSetErr}) { - return if $hss->($h, $errnum, $msg, $state, $method); - } - - if (!defined $errnum) { - $h->{err} = $DBI::err = undef; - $h->{errstr} = $DBI::errstr = undef; - $h->{state} = $DBI::state = ''; - return; - } - - if ($h->{errstr}) { - $h->{errstr} .= sprintf " [err was %s now %s]", $h->{err}, $errnum - if $h->{err} && $errnum && $h->{err} ne $errnum; - $h->{errstr} .= sprintf " [state was %s now %s]", $h->{state}, $state - if $h->{state} and $h->{state} ne "S1000" && $state && $h->{state} ne $state; - $h->{errstr} .= "\n$msg" if $h->{errstr} ne $msg; - $DBI::errstr = $h->{errstr}; - } - else { - $h->{errstr} = $DBI::errstr = $msg; - } - - # assign if higher priority: err > "0" > "" > undef - my $err_changed; - if ($errnum # new error: so assign - or !defined $h->{err} # no existing warn/info: so assign - # new warn ("0" len 1) > info ("" len 0): so assign - or defined $errnum && length($errnum) > length($h->{err}) - ) { - $h->{err} = $DBI::err = $errnum; - ++$h->{ErrCount} if $errnum; - ++$err_changed; - } - - if ($err_changed) { - $state ||= "S1000" if $DBI::err; - $h->{state} = $DBI::state = ($state eq "00000") ? "" : $state - if $state; - } - - if (my $p = $h->{Database}) { # just sth->dbh, not dbh->drh (see ::db::DESTROY) - $p->{err} = $DBI::err; - $p->{errstr} = $DBI::errstr; - $p->{state} = $DBI::state; - } - - $h->{'dbi_pp_last_method'} = $method; - return $rv; # usually undef -} -sub trace_msg { - my ($h, $msg, $minlevel)=@_; - $minlevel = 1 unless defined $minlevel; - return unless $minlevel <= ($DBI::dbi_debug & 0xF); - print $DBI::tfh $msg; - return 1; -} -sub private_data { - warn "private_data @_"; -} -sub take_imp_data { - my $dbh = shift; - # A reasonable default implementation based on the one in DBI.xs. - # Typically a pure-perl driver would have their own take_imp_data method - # that would delete all but the essential items in the hash before ending with: - # return $dbh->SUPER::take_imp_data(); - # Of course it's useless if the driver doesn't also implement support for - # the dbi_imp_data attribute to the connect() method. - require Storable; - croak("Can't take_imp_data from handle that's not Active") - unless $dbh->{Active}; - for my $sth (@{ $dbh->{ChildHandles} || [] }) { - next unless $sth; - $sth->finish if $sth->{Active}; - bless $sth, 'DBI::zombie'; - } - delete $dbh->{$_} for (keys %is_valid_attribute); - delete $dbh->{$_} for grep { m/^dbi_/ } keys %$dbh; - # warn "@{[ %$dbh ]}"; - local $Storable::forgive_me = 1; # in case there are some CODE refs - my $imp_data = Storable::freeze($dbh); - # XXX um, should probably untie here - need to check dispatch behaviour - return $imp_data; -} -sub rows { - return -1; # always returns -1 here, see DBD::_::st::rows below -} -sub DESTROY { -} - -package - DBD::_::dr; - -sub dbixs_revision { - return 0; -} - -package - DBD::_::db; - -sub connected { -} - - -package - DBD::_::st; - -sub fetchrow_arrayref { - my $h = shift; - # if we're here then driver hasn't implemented fetch/fetchrow_arrayref - # so we assume they've implemented fetchrow_array and call that instead - my @row = $h->fetchrow_array or return; - return $h->_set_fbav(\@row); -} -# twice to avoid typo warning -*fetch = \&fetchrow_arrayref; *fetch = \&fetchrow_arrayref; - -sub fetchrow_array { - my $h = shift; - # if we're here then driver hasn't implemented fetchrow_array - # so we assume they've implemented fetch/fetchrow_arrayref - my $row = $h->fetch or return; - return @$row; -} -*fetchrow = \&fetchrow_array; *fetchrow = \&fetchrow_array; - -sub fetchrow_hashref { - my $h = shift; - my $row = $h->fetch or return; - my $FetchCase = shift; - my $FetchHashKeyName = $FetchCase || $h->{'FetchHashKeyName'} || 'NAME'; - my $FetchHashKeys = $h->FETCH($FetchHashKeyName); - my %rowhash; - @rowhash{ @$FetchHashKeys } = @$row; - return \%rowhash; -} -sub dbih_setup_fbav { - my $h = shift; - return $h->{'_fbav'} || do { - $DBI::rows = $h->{'_rows'} = 0; - my $fields = $h->{'NUM_OF_FIELDS'} - or DBI::croak("NUM_OF_FIELDS not set"); - my @row = (undef) x $fields; - \@row; - }; -} -sub _get_fbav { - my $h = shift; - my $av = $h->{'_fbav'} ||= dbih_setup_fbav($h); - $DBI::rows = ++$h->{'_rows'}; - return $av; -} -sub _set_fbav { - my $h = shift; - my $fbav = $h->{'_fbav'}; - if ($fbav) { - $DBI::rows = ++$h->{'_rows'}; - } - else { - $fbav = $h->_get_fbav; - } - my $row = shift; - if (my $bc = $h->{'_bound_cols'}) { - for my $i (0..@$row-1) { - my $bound = $bc->[$i]; - $fbav->[$i] = ($bound) ? ($$bound = $row->[$i]) : $row->[$i]; - } - } - else { - @$fbav = @$row; - } - return $fbav; -} -sub bind_col { - my ($h, $col, $value_ref,$from_bind_columns) = @_; - my $fbav = $h->{'_fbav'} ||= dbih_setup_fbav($h); # from _get_fbav() - my $num_of_fields = @$fbav; - DBI::croak("bind_col: column $col is not a valid column (1..$num_of_fields)") - if $col < 1 or $col > $num_of_fields; - return 1 if not defined $value_ref; # ie caller is just trying to set TYPE - DBI::croak("bind_col($col,$value_ref) needs a reference to a scalar") - unless ref $value_ref eq 'SCALAR'; - $h->{'_bound_cols'}->[$col-1] = $value_ref; - return 1; -} -sub finish { - my $h = shift; - $h->{'_fbav'} = undef; - $h->{'Active'} = 0; - return 1; -} -sub rows { - my $h = shift; - my $rows = $h->{'_rows'}; - return -1 unless defined $rows; - return $rows; -} - -1; -__END__ - -=pod - -=head1 NAME - -DBI::PurePerl -- a DBI emulation using pure perl (no C/XS compilation required) - -=head1 SYNOPSIS - - BEGIN { $ENV{DBI_PUREPERL} = 2 } - use DBI; - -=head1 DESCRIPTION - -This is a pure perl emulation of the DBI internals. In almost all -cases you will be better off using standard DBI since the portions -of the standard version written in C make it *much* faster. - -However, if you are in a situation where it isn't possible to install -a compiled version of standard DBI, and you're using pure-perl DBD -drivers, then this module allows you to use most common features -of DBI without needing any changes in your scripts. - -=head1 EXPERIMENTAL STATUS - -DBI::PurePerl is new so please treat it as experimental pending -more extensive testing. So far it has passed all tests with DBD::CSV, -DBD::AnyData, DBD::XBase, DBD::Sprite, DBD::mysqlPP. Please send -bug reports to Jeff Zucker at with a cc to -. - -=head1 USAGE - -The usage is the same as for standard DBI with the exception -that you need to set the environment variable DBI_PUREPERL if -you want to use the PurePerl version. - - DBI_PUREPERL == 0 (the default) Always use compiled DBI, die - if it isn't properly compiled & installed - - DBI_PUREPERL == 1 Use compiled DBI if it is properly compiled - & installed, otherwise use PurePerl - - DBI_PUREPERL == 2 Always use PurePerl - -You may set the environment variable in your shell (e.g. with -set or setenv or export, etc) or else set it in your script like -this: - - BEGIN { $ENV{DBI_PUREPERL}=2 } - -before you C. - -=head1 INSTALLATION - -In most situations simply install DBI (see the DBI pod for details). - -In the situation in which you can not install DBI itself, you -may manually copy DBI.pm and PurePerl.pm into the appropriate -directories. - -For example: - - cp DBI.pm /usr/jdoe/mylibs/. - cp PurePerl.pm /usr/jdoe/mylibs/DBI/. - -Then add this to the top of scripts: - - BEGIN { - $ENV{DBI_PUREPERL} = 1; # or =2 - unshift @INC, '/usr/jdoe/mylibs'; - } - -(Or should we perhaps patch Makefile.PL so that if DBI_PUREPERL -is set to 2 prior to make, the normal compile process is skipped -and the files are installed automatically?) - -=head1 DIFFERENCES BETWEEN DBI AND DBI::PurePerl - -=head2 Attributes - -Boolean attributes still return boolean values but the actual values -used may be different, i.e., 0 or undef instead of an empty string. - -Some handle attributes are either not supported or have very limited -functionality: - - ActiveKids - InactiveDestroy - AutoInactiveDestroy - Kids - Taint - TaintIn - TaintOut - -(and probably others) - -=head2 Tracing - -Trace functionality is more limited and the code to handle tracing is -only embedded into DBI:PurePerl if the DBI_TRACE environment variable -is defined. To enable total tracing you can set the DBI_TRACE -environment variable as usual. But to enable individual handle -tracing using the trace() method you also need to set the DBI_TRACE -environment variable, but set it to 0. - -=head2 Parameter Usage Checking - -The DBI does some basic parameter count checking on method calls. -DBI::PurePerl doesn't. - -=head2 Speed - -DBI::PurePerl is slower. Although, with some drivers in some -contexts this may not be very significant for you. - -By way of example... the test.pl script in the DBI source -distribution has a simple benchmark that just does: - - my $null_dbh = DBI->connect('dbi:NullP:','',''); - my $i = 10_000; - $null_dbh->prepare('') while $i--; - -In other words just prepares a statement, creating and destroying -a statement handle, over and over again. Using the real DBI this -runs at ~4550 handles per second whereas DBI::PurePerl manages -~2800 per second on the same machine (not too bad really). - -=head2 May not fully support hash() - -If you want to use type 1 hash, i.e., C with -DBI::PurePerl, you'll need version 1.56 or higher of Math::BigInt -(available on CPAN). - -=head2 Doesn't support preparse() - -The DBI->preparse() method isn't supported in DBI::PurePerl. - -=head2 Doesn't support DBD::Proxy - -There's a subtle problem somewhere I've not been able to identify. -DBI::ProxyServer seem to work fine with DBI::PurePerl but DBD::Proxy -does not work 100% (which is sad because that would be far more useful :) -Try re-enabling t/80proxy.t for DBI::PurePerl to see if the problem -that remains will affect you're usage. - -=head2 Others - - can() - doesn't have any special behaviour - -Please let us know if you find any other differences between DBI -and DBI::PurePerl. - -=head1 AUTHORS - -Tim Bunce and Jeff Zucker. - -Tim provided the direction and basis for the code. The original -idea for the module and most of the brute force porting from C to -Perl was by Jeff. Tim then reworked some core parts to boost the -performance and accuracy of the emulation. Thanks also to Randal -Schwartz and John Tobey for patches. - -=head1 COPYRIGHT - -Copyright (c) 2002 Tim Bunce Ireland. - -See COPYRIGHT section in DBI.pm for usage and distribution rights. - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/SQL/Nano.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/SQL/Nano.pm deleted file mode 100644 index 2988c10..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/SQL/Nano.pm +++ /dev/null @@ -1,1014 +0,0 @@ -####################################################################### -# -# DBI::SQL::Nano - a very tiny SQL engine -# -# Copyright (c) 2010 by Jens Rehsack < rehsack AT cpan.org > -# Copyright (c) 2004 by Jeff Zucker < jzucker AT cpan.org > -# -# All rights reserved. -# -# You may freely distribute and/or modify this module under the terms -# of either the GNU General Public License (GPL) or the Artistic License, -# as specified in the Perl README file. -# -# See the pod at the bottom of this file for help information -# -####################################################################### - -####################### -package DBI::SQL::Nano; -####################### -use strict; -use warnings; -use vars qw( $VERSION $versions ); - -use Carp qw(croak); - -require DBI; # for looks_like_number() - -BEGIN -{ - $VERSION = "1.015544"; - - $versions->{nano_version} = $VERSION; - if ( $ENV{DBI_SQL_NANO} || !eval { require SQL::Statement; $SQL::Statement::VERSION ge '1.400' } ) - { - @DBI::SQL::Nano::Statement::ISA = qw(DBI::SQL::Nano::Statement_); - @DBI::SQL::Nano::Table::ISA = qw(DBI::SQL::Nano::Table_); - } - else - { - @DBI::SQL::Nano::Statement::ISA = qw( SQL::Statement ); - @DBI::SQL::Nano::Table::ISA = qw( SQL::Eval::Table); - $versions->{statement_version} = $SQL::Statement::VERSION; - } -} - -################################### -package DBI::SQL::Nano::Statement_; -################################### - -use Carp qw(croak); -use Errno; - -if ( eval { require Clone; } ) -{ - Clone->import("clone"); -} -else -{ - require Storable; # in CORE since 5.7.3 - *clone = \&Storable::dclone; -} - -sub new -{ - my ( $class, $sql ) = @_; - my $self = {}; - bless $self, $class; - return $self->prepare($sql); -} - -##################################################################### -# PREPARE -##################################################################### -sub prepare -{ - my ( $self, $sql ) = @_; - $sql =~ s/\s+$//; - $sql =~ s/\s*;$//; - for ($sql) - { - /^\s*CREATE\s+TABLE\s+(.*?)\s*\((.+)\)\s*$/is - && do - { - $self->{command} = 'CREATE'; - $self->{table_name} = $1; - defined $2 and $2 ne "" and - $self->{column_names} = parse_coldef_list($2); - $self->{column_names} or croak "Can't find columns"; - }; - /^\s*DROP\s+TABLE\s+(IF\s+EXISTS\s+)?(.*?)\s*$/is - && do - { - $self->{command} = 'DROP'; - $self->{table_name} = $2; - defined $1 and $1 ne "" and - $self->{ignore_missing_table} = 1; - }; - /^\s*SELECT\s+(.*?)\s+FROM\s+(\S+)((.*))?/is - && do - { - $self->{command} = 'SELECT'; - defined $1 and $1 ne "" and - $self->{column_names} = parse_comma_list($1); - $self->{column_names} or croak "Can't find columns"; - $self->{table_name} = $2; - if ( my $clauses = $4 ) - { - if ( $clauses =~ /^(.*)\s+ORDER\s+BY\s+(.*)$/is ) - { - $clauses = $1; - $self->{order_clause} = $self->parse_order_clause($2); - } - $self->{where_clause} = $self->parse_where_clause($clauses) if ($clauses); - } - }; - /^\s*INSERT\s+(?:INTO\s+)?(\S+)\s*(\((.*?)\))?\s*VALUES\s*\((.+)\)/is - && do - { - $self->{command} = 'INSERT'; - $self->{table_name} = $1; - defined $2 and $2 ne "" and - $self->{column_names} = parse_comma_list($2); - defined $4 and $4 ne "" and - $self->{values} = $self->parse_values_list($4); - $self->{values} or croak "Can't parse values"; - }; - /^\s*DELETE\s+FROM\s+(\S+)((.*))?/is - && do - { - $self->{command} = 'DELETE'; - $self->{table_name} = $1; - defined $3 and $3 ne "" and - $self->{where_clause} = $self->parse_where_clause($3); - }; - /^\s*UPDATE\s+(\S+)\s+SET\s+(.+)(\s+WHERE\s+.+)/is - && do - { - $self->{command} = 'UPDATE'; - $self->{table_name} = $1; - defined $2 and $2 ne "" and - $self->parse_set_clause($2); - defined $3 and $3 ne "" and - $self->{where_clause} = $self->parse_where_clause($3); - }; - } - croak "Couldn't parse" unless ( $self->{command} and $self->{table_name} ); - return $self; -} - -sub parse_order_clause -{ - my ( $self, $str ) = @_; - my @clause = split /\s+/, $str; - return { $clause[0] => 'ASC' } if ( @clause == 1 ); - croak "Bad ORDER BY clause '$str'" if ( @clause > 2 ); - $clause[1] ||= ''; - return { $clause[0] => uc $clause[1] } - if $clause[1] =~ /^ASC$/i - or $clause[1] =~ /^DESC$/i; - croak "Bad ORDER BY clause '$clause[1]'"; -} - -sub parse_coldef_list -{ # check column definitions - my @col_defs; - for ( split ',', shift ) - { - my $col = clean_parse_str($_); - if ( $col =~ /^(\S+?)\s+.+/ ) - { # doesn't check what it is - $col = $1; # just checks if it exists - } - else - { - croak "No column definition for '$_'"; - } - push @col_defs, $col; - } - return \@col_defs; -} - -sub parse_comma_list -{ - [ map { clean_parse_str($_) } split( ',', shift ) ]; -} -sub clean_parse_str { local $_ = shift; s/\(//; s/\)//; s/^\s+//; s/\s+$//; $_; } - -sub parse_values_list -{ - my ( $self, $str ) = @_; - [ map { $self->parse_value( clean_parse_str($_) ) } split( ',', $str ) ]; -} - -sub parse_set_clause -{ - my $self = shift; - my @cols = split /,/, shift; - my $set_clause; - for my $col (@cols) - { - my ( $col_name, $value ) = $col =~ /^\s*(.+?)\s*=\s*(.+?)\s*$/s; - push @{ $self->{column_names} }, $col_name; - push @{ $self->{values} }, $self->parse_value($value); - } - croak "Can't parse set clause" unless ( $self->{column_names} and $self->{values} ); -} - -sub parse_value -{ - my ( $self, $str ) = @_; - return unless ( defined $str ); - $str =~ s/\s+$//; - $str =~ s/^\s+//; - if ( $str =~ /^\?$/ ) - { - push @{ $self->{params} }, '?'; - return { - value => '?', - type => 'placeholder' - }; - } - return { - value => undef, - type => 'NULL' - } if ( $str =~ /^NULL$/i ); - return { - value => $1, - type => 'string' - } if ( $str =~ /^'(.+)'$/s ); - return { - value => $str, - type => 'number' - } if ( DBI::looks_like_number($str) ); - return { - value => $str, - type => 'column' - }; -} - -sub parse_where_clause -{ - my ( $self, $str ) = @_; - $str =~ s/\s+$//; - if ( $str =~ /^\s*WHERE\s+(.*)/i ) - { - $str = $1; - } - else - { - croak "Couldn't find WHERE clause in '$str'"; - } - my ($neg) = $str =~ s/^\s*(NOT)\s+//is; - my $opexp = '=|<>|<=|>=|<|>|LIKE|CLIKE|IS'; - my ( $val1, $op, $val2 ) = $str =~ /^(.+?)\s*($opexp)\s*(.+)\s*$/iso; - croak "Couldn't parse WHERE expression '$str'" unless ( defined $val1 and defined $op and defined $val2 ); - return { - arg1 => $self->parse_value($val1), - arg2 => $self->parse_value($val2), - op => $op, - neg => $neg, - }; -} - -##################################################################### -# EXECUTE -##################################################################### -sub execute -{ - my ( $self, $data, $params ) = @_; - my $num_placeholders = $self->params; - my $num_params = scalar @$params || 0; - croak "Number of params '$num_params' does not match number of placeholders '$num_placeholders'" - unless ( $num_placeholders == $num_params ); - if ( scalar @$params ) - { - for my $i ( 0 .. $#{ $self->{values} } ) - { - if ( $self->{values}->[$i]->{type} eq 'placeholder' ) - { - $self->{values}->[$i]->{value} = shift @$params; - } - } - if ( $self->{where_clause} ) - { - if ( $self->{where_clause}->{arg1}->{type} eq 'placeholder' ) - { - $self->{where_clause}->{arg1}->{value} = shift @$params; - } - if ( $self->{where_clause}->{arg2}->{type} eq 'placeholder' ) - { - $self->{where_clause}->{arg2}->{value} = shift @$params; - } - } - } - my $command = $self->{command}; - ( $self->{'NUM_OF_ROWS'}, $self->{'NUM_OF_FIELDS'}, $self->{'data'}, ) = $self->$command( $data, $params ); - $self->{NAME} ||= $self->{column_names}; - return $self->{'NUM_OF_ROWS'} || '0E0'; -} - -my $enoentstr = "Cannot open .*\(" . Errno::ENOENT . "\)"; -my $enoentrx = qr/$enoentstr/; - -sub DROP ($$$) -{ - my ( $self, $data, $params ) = @_; - - my $table; - my @err; - eval { - local $SIG{__WARN__} = sub { push @err, @_ }; - ($table) = $self->open_tables( $data, 0, 1 ); - }; - if ( $self->{ignore_missing_table} and ( $@ or @err ) and grep { $_ =~ $enoentrx } ( @err, $@ ) ) - { - $@ = ''; - return ( -1, 0 ); - } - - croak( $@ || $err[0] ) if ( $@ || @err ); - return ( -1, 0 ) unless $table; - - $table->drop($data); - ( -1, 0 ); -} - -sub CREATE ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 1, 1 ); - $table->push_names( $data, $self->{column_names} ); - ( 0, 0 ); -} - -sub INSERT ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 0, 1 ); - $self->verify_columns($table); - my $all_columns = $table->{col_names}; - $table->seek( $data, 0, 2 ) unless ( $table->can('insert_one_row') ); - my ($array) = []; - my ( $val, $col, $i ); - $self->{column_names} = $table->col_names() unless ( $self->{column_names} ); - my $cNum = scalar( @{ $self->{column_names} } ) if ( $self->{column_names} ); - my $param_num = 0; - - $cNum or - croak "Bad col names in INSERT"; - - my $maxCol = $#$all_columns; - - for ( $i = 0; $i < $cNum; $i++ ) - { - $col = $self->{column_names}->[$i]; - $array->[ $self->column_nums( $table, $col ) ] = $self->row_values($i); - } - - # Extend row to put values in ALL fields - $#$array < $maxCol and $array->[$maxCol] = undef; - - $table->can('insert_new_row') ? $table->insert_new_row( $data, $array ) : $table->push_row( $data, $array ); - - return ( 1, 0 ); -} - -sub DELETE ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 0, 1 ); - $self->verify_columns($table); - my ($affected) = 0; - my ( @rows, $array ); - my $can_dor = $table->can('delete_one_row'); - while ( $array = $table->fetch_row($data) ) - { - if ( $self->eval_where( $table, $array ) ) - { - ++$affected; - if ( $self->{fetched_from_key} ) - { - $array = $self->{fetched_value}; - $table->delete_one_row( $data, $array ); - return ( $affected, 0 ); - } - push( @rows, $array ) if ($can_dor); - } - else - { - push( @rows, $array ) unless ($can_dor); - } - } - if ($can_dor) - { - foreach $array (@rows) - { - $table->delete_one_row( $data, $array ); - } - } - else - { - $table->seek( $data, 0, 0 ); - foreach $array (@rows) - { - $table->push_row( $data, $array ); - } - $table->truncate($data); - } - return ( $affected, 0 ); -} - -sub _anycmp($$;$) -{ - my ( $a, $b, $case_fold ) = @_; - - if ( !defined($a) || !defined($b) ) - { - return defined($a) - defined($b); - } - elsif ( DBI::looks_like_number($a) && DBI::looks_like_number($b) ) - { - return $a <=> $b; - } - else - { - return $case_fold ? lc($a) cmp lc($b) || $a cmp $b : $a cmp $b; - } -} - -sub SELECT ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 0, 0 ); - $self->verify_columns($table); - my $tname = $self->{table_name}; - my ($affected) = 0; - my ( @rows, %cols, $array, $val, $col, $i ); - while ( $array = $table->fetch_row($data) ) - { - if ( $self->eval_where( $table, $array ) ) - { - $array = $self->{fetched_value} if ( $self->{fetched_from_key} ); - unless ( keys %cols ) - { - my $col_nums = $self->column_nums($table); - %cols = reverse %{$col_nums}; - } - - my $rowhash; - for ( sort keys %cols ) - { - $rowhash->{ $cols{$_} } = $array->[$_]; - } - my @newarray; - for ( $i = 0; $i < @{ $self->{column_names} }; $i++ ) - { - $col = $self->{column_names}->[$i]; - push @newarray, $rowhash->{$col}; - } - push( @rows, \@newarray ); - return ( scalar(@rows), scalar @{ $self->{column_names} }, \@rows ) - if ( $self->{fetched_from_key} ); - } - } - if ( $self->{order_clause} ) - { - my ( $sort_col, $desc ) = each %{ $self->{order_clause} }; - my @sortCols = ( $self->column_nums( $table, $sort_col, 1 ) ); - $sortCols[1] = uc $desc eq 'DESC' ? 1 : 0; - - @rows = sort { - my ( $result, $colNum, $desc ); - my $i = 0; - do - { - $colNum = $sortCols[ $i++ ]; - $desc = $sortCols[ $i++ ]; - $result = _anycmp( $a->[$colNum], $b->[$colNum] ); - $result = -$result if ($desc); - } while ( !$result && $i < @sortCols ); - $result; - } @rows; - } - ( scalar(@rows), scalar @{ $self->{column_names} }, \@rows ); -} - -sub UPDATE ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 0, 1 ); - $self->verify_columns($table); - return undef unless $table; - my $affected = 0; - my $can_usr = $table->can('update_specific_row'); - my $can_uor = $table->can('update_one_row'); - my $can_rwu = $can_usr || $can_uor; - my ( @rows, $array, $f_array, $val, $col, $i ); - - while ( $array = $table->fetch_row($data) ) - { - if ( $self->eval_where( $table, $array ) ) - { - $array = $self->{fetched_value} if ( $self->{fetched_from_key} and $can_rwu ); - my $orig_ary = clone($array) if ($can_usr); - for ( $i = 0; $i < @{ $self->{column_names} }; $i++ ) - { - $col = $self->{column_names}->[$i]; - $array->[ $self->column_nums( $table, $col ) ] = $self->row_values($i); - } - $affected++; - if ( $self->{fetched_value} ) - { - if ($can_usr) - { - $table->update_specific_row( $data, $array, $orig_ary ); - } - elsif ($can_uor) - { - $table->update_one_row( $data, $array ); - } - return ( $affected, 0 ); - } - push( @rows, $can_usr ? [ $array, $orig_ary ] : $array ); - } - else - { - push( @rows, $array ) unless ($can_rwu); - } - } - if ($can_rwu) - { - foreach my $array (@rows) - { - if ($can_usr) - { - $table->update_specific_row( $data, @$array ); - } - elsif ($can_uor) - { - $table->update_one_row( $data, $array ); - } - } - } - else - { - $table->seek( $data, 0, 0 ); - foreach my $array (@rows) - { - $table->push_row( $data, $array ); - } - $table->truncate($data); - } - - return ( $affected, 0 ); -} - -sub verify_columns -{ - my ( $self, $table ) = @_; - my @cols = @{ $self->{column_names} }; - if ( $self->{where_clause} ) - { - if ( my $col = $self->{where_clause}->{arg1} ) - { - push @cols, $col->{value} if $col->{type} eq 'column'; - } - if ( my $col = $self->{where_clause}->{arg2} ) - { - push @cols, $col->{value} if $col->{type} eq 'column'; - } - } - for (@cols) - { - $self->column_nums( $table, $_ ); - } -} - -sub column_nums -{ - my ( $self, $table, $stmt_col_name, $find_in_stmt ) = @_; - my %dbd_nums = %{ $table->col_nums() }; - my @dbd_cols = @{ $table->col_names() }; - my %stmt_nums; - if ( $stmt_col_name and !$find_in_stmt ) - { - while ( my ( $k, $v ) = each %dbd_nums ) - { - return $v if uc $k eq uc $stmt_col_name; - } - croak "No such column '$stmt_col_name'"; - } - if ( $stmt_col_name and $find_in_stmt ) - { - for my $i ( 0 .. @{ $self->{column_names} } ) - { - return $i if uc $stmt_col_name eq uc $self->{column_names}->[$i]; - } - croak "No such column '$stmt_col_name'"; - } - for my $i ( 0 .. $#dbd_cols ) - { - for my $stmt_col ( @{ $self->{column_names} } ) - { - $stmt_nums{$stmt_col} = $i if uc $dbd_cols[$i] eq uc $stmt_col; - } - } - return \%stmt_nums; -} - -sub eval_where -{ - my ( $self, $table, $rowary ) = @_; - my $where = $self->{"where_clause"} || return 1; - my $col_nums = $table->col_nums(); - my %cols = reverse %{$col_nums}; - my $rowhash; - for ( sort keys %cols ) - { - $rowhash->{ uc $cols{$_} } = $rowary->[$_]; - } - return $self->process_predicate( $where, $table, $rowhash ); -} - -sub process_predicate -{ - my ( $self, $pred, $table, $rowhash ) = @_; - my $val1 = $pred->{arg1}; - if ( $val1->{type} eq 'column' ) - { - $val1 = $rowhash->{ uc $val1->{value} }; - } - else - { - $val1 = $val1->{value}; - } - my $val2 = $pred->{arg2}; - if ( $val2->{type} eq 'column' ) - { - $val2 = $rowhash->{ uc $val2->{value} }; - } - else - { - $val2 = $val2->{value}; - } - my $op = $pred->{op}; - my $neg = $pred->{neg}; - if ( $op eq '=' and !$neg and $table->can('fetch_one_row') ) - { - my $key_col = $table->fetch_one_row( 1, 1 ); - if ( $pred->{arg1}->{value} =~ /^$key_col$/i ) - { - $self->{fetched_from_key} = 1; - $self->{fetched_value} = $table->fetch_one_row( 0, $pred->{arg2}->{value} ); - return 1; - } - } - my $match = $self->is_matched( $val1, $op, $val2 ) || 0; - if ($neg) { $match = $match ? 0 : 1; } - return $match; -} - -sub is_matched -{ - my ( $self, $val1, $op, $val2 ) = @_; - if ( $op eq 'IS' ) - { - return 1 if ( !defined $val1 or $val1 eq '' ); - return 0; - } - $val1 = '' unless ( defined $val1 ); - $val2 = '' unless ( defined $val2 ); - if ( $op =~ /LIKE|CLIKE/i ) - { - $val2 = quotemeta($val2); - $val2 =~ s/\\%/.*/g; - $val2 =~ s/_/./g; - } - if ( $op eq 'LIKE' ) { return $val1 =~ /^$val2$/s; } - if ( $op eq 'CLIKE' ) { return $val1 =~ /^$val2$/si; } - if ( DBI::looks_like_number($val1) && DBI::looks_like_number($val2) ) - { - if ( $op eq '<' ) { return $val1 < $val2; } - if ( $op eq '>' ) { return $val1 > $val2; } - if ( $op eq '=' ) { return $val1 == $val2; } - if ( $op eq '<>' ) { return $val1 != $val2; } - if ( $op eq '<=' ) { return $val1 <= $val2; } - if ( $op eq '>=' ) { return $val1 >= $val2; } - } - else - { - if ( $op eq '<' ) { return $val1 lt $val2; } - if ( $op eq '>' ) { return $val1 gt $val2; } - if ( $op eq '=' ) { return $val1 eq $val2; } - if ( $op eq '<>' ) { return $val1 ne $val2; } - if ( $op eq '<=' ) { return $val1 ge $val2; } - if ( $op eq '>=' ) { return $val1 le $val2; } - } -} - -sub params -{ - my ( $self, $val_num ) = @_; - if ( !$self->{"params"} ) { return 0; } - if ( defined $val_num ) - { - return $self->{"params"}->[$val_num]; - } - - return wantarray ? @{ $self->{"params"} } : scalar @{ $self->{"params"} }; -} - -sub open_tables -{ - my ( $self, $data, $createMode, $lockMode ) = @_; - my $table_name = $self->{table_name}; - my $table; - eval { $table = $self->open_table( $data, $table_name, $createMode, $lockMode ) }; - if ($@) - { - chomp $@; - croak $@; - } - croak "Couldn't open table '$table_name'" unless $table; - if ( !$self->{column_names} or $self->{column_names}->[0] eq '*' ) - { - $self->{column_names} = $table->col_names(); - } - return $table; -} - -sub row_values -{ - my ( $self, $val_num ) = @_; - if ( !$self->{"values"} ) { return 0; } - if ( defined $val_num ) - { - return $self->{"values"}->[$val_num]->{value}; - } - if (wantarray) - { - return map { $_->{"value"} } @{ $self->{"values"} }; - } - else - { - return scalar @{ $self->{"values"} }; - } -} - -sub column_names -{ - my ($self) = @_; - my @col_names; - if ( $self->{column_names} and $self->{column_names}->[0] ne '*' ) - { - @col_names = @{ $self->{column_names} }; - } - return @col_names; -} - -############################### -package DBI::SQL::Nano::Table_; -############################### - -use Carp qw(croak); - -sub new ($$) -{ - my ( $proto, $attr ) = @_; - my ($self) = {%$attr}; - - defined( $self->{col_names} ) and "ARRAY" eq ref( $self->{col_names} ) - or croak("attribute 'col_names' must be defined as an array"); - exists( $self->{col_nums} ) or $self->{col_nums} = _map_colnums( $self->{col_names} ); - defined( $self->{col_nums} ) and "HASH" eq ref( $self->{col_nums} ) - or croak("attribute 'col_nums' must be defined as a hash"); - - bless( $self, ( ref($proto) || $proto ) ); - return $self; -} - -sub _map_colnums -{ - my $col_names = $_[0]; - my %col_nums; - for my $i ( 0 .. $#$col_names ) - { - next unless $col_names->[$i]; - $col_nums{ $col_names->[$i] } = $i; - } - return \%col_nums; -} - -sub row() { return $_[0]->{row}; } -sub column($) { return $_[0]->{row}->[ $_[0]->column_num( $_[1] ) ]; } -sub column_num($) { $_[0]->{col_nums}->{ $_[1] }; } -sub col_nums() { $_[0]->{col_nums} } -sub col_names() { $_[0]->{col_names}; } - -sub drop ($$) { croak "Abstract method " . ref( $_[0] ) . "::drop called" } -sub fetch_row ($$$) { croak "Abstract method " . ref( $_[0] ) . "::fetch_row called" } -sub push_row ($$$) { croak "Abstract method " . ref( $_[0] ) . "::push_row called" } -sub push_names ($$$) { croak "Abstract method " . ref( $_[0] ) . "::push_names called" } -sub truncate ($$) { croak "Abstract method " . ref( $_[0] ) . "::truncate called" } -sub seek ($$$$) { croak "Abstract method " . ref( $_[0] ) . "::seek called" } - -1; -__END__ - -=pod - -=head1 NAME - -DBI::SQL::Nano - a very tiny SQL engine - -=head1 SYNOPSIS - - BEGIN { $ENV{DBI_SQL_NANO}=1 } # forces use of Nano rather than SQL::Statement - use DBI::SQL::Nano; - use Data::Dumper; - my $stmt = DBI::SQL::Nano::Statement->new( - "SELECT bar,baz FROM foo WHERE qux = 1" - ) or die "Couldn't parse"; - print Dumper $stmt; - -=head1 DESCRIPTION - -C<< DBI::SQL::Nano >> is meant as a I minimal SQL engine for use in -situations where SQL::Statement is not available. In most situations you are -better off installing L although DBI::SQL::Nano may be faster -for some B simple tasks. - -DBI::SQL::Nano, like SQL::Statement is primarily intended to provide a SQL -engine for use with some pure perl DBDs including L, L, -L, and L. It is not of much use in and of itself. -You can dump out the structure of a parsed SQL statement, but that is about -it. - -=head1 USAGE - -=head2 Setting the DBI_SQL_NANO flag - -By default, when a C<< DBD >> uses C<< DBI::SQL::Nano >>, the module will -look to see if C<< SQL::Statement >> is installed. If it is, SQL::Statement -objects are used. If SQL::Statement is not available, DBI::SQL::Nano -objects are used. - -In some cases, you may wish to use DBI::SQL::Nano objects even if -SQL::Statement is available. To force usage of DBI::SQL::Nano objects -regardless of the availability of SQL::Statement, set the environment -variable DBI_SQL_NANO to 1. - -You can set the environment variable in your shell prior to running your -script (with SET or EXPORT or whatever), or else you can set it in your -script by putting this at the top of the script: - - BEGIN { $ENV{DBI_SQL_NANO} = 1 } - -=head2 Supported SQL syntax - - Here's a pseudo-BNF. Square brackets [] indicate optional items; - Angle brackets <> indicate items defined elsewhere in the BNF. - - statement ::= - DROP TABLE [IF EXISTS] - | CREATE TABLE - | INSERT INTO [] VALUES - | DELETE FROM [] - | UPDATE SET - | SELECT FROM [] - [] - - the optional IF EXISTS clause ::= - * similar to MySQL - prevents errors when trying to drop - a table that doesn't exist - - identifiers ::= - * table and column names should be valid SQL identifiers - * especially avoid using spaces and commas in identifiers - * note: there is no error checking for invalid names, some - will be accepted, others will cause parse failures - - table_name ::= - * only one table (no multiple table operations) - * see identifier for valid table names - - col_def_list ::= - * a parens delimited, comma-separated list of column names - * see identifier for valid column names - * column types and column constraints may be included but are ignored - e.g. these are all the same: - (id,phrase) - (id INT, phrase VARCHAR(40)) - (id INT PRIMARY KEY, phrase VARCHAR(40) NOT NULL) - * you are *strongly* advised to put in column types even though - they are ignored ... it increases portability - - insert_col_list ::= - * a parens delimited, comma-separated list of column names - * as in standard SQL, this is optional - - select_col_list ::= - * a comma-separated list of column names - * or an asterisk denoting all columns - - val_list ::= - * a parens delimited, comma-separated list of values which can be: - * placeholders (an unquoted question mark) - * numbers (unquoted numbers) - * column names (unquoted strings) - * nulls (unquoted word NULL) - * strings (delimited with single quote marks); - * note: leading and trailing percent mark (%) and underscore (_) - can be used as wildcards in quoted strings for use with - the LIKE and CLIKE operators - * note: escaped single quotation marks within strings are not - supported, neither are embedded commas, use placeholders instead - - set_clause ::= - * a comma-separated list of column = value pairs - * see val_list for acceptable value formats - - where_clause ::= - * a single "column/value column/value" predicate, optionally - preceded by "NOT" - * note: multiple predicates combined with ORs or ANDs are not supported - * see val_list for acceptable value formats - * op may be one of: - < > >= <= = <> LIKE CLIKE IS - * CLIKE is a case insensitive LIKE - - order_clause ::= column_name [ASC|DESC] - * a single column optional ORDER BY clause is supported - * as in standard SQL, if neither ASC (ascending) nor - DESC (descending) is specified, ASC becomes the default - -=head1 TABLES - -DBI::SQL::Nano::Statement operates on exactly one table. This table will be -opened by inherit from DBI::SQL::Nano::Statement and implements the -C<< open_table >> method. - - sub open_table ($$$$$) - { - ... - return Your::Table->new( \%attributes ); - } - -DBI::SQL::Nano::Statement_ expects a rudimentary interface is implemented by -the table object, as well as SQL::Statement expects. - - package Your::Table; - - use vars qw(@ISA); - @ISA = qw(DBI::SQL::Nano::Table); - - sub drop ($$) { ... } - sub fetch_row ($$$) { ... } - sub push_row ($$$) { ... } - sub push_names ($$$) { ... } - sub truncate ($$) { ... } - sub seek ($$$$) { ... } - -The base class interfaces are provided by DBI::SQL::Nano::Table_ in case of -relying on DBI::SQL::Nano or SQL::Eval::Table (see L for details) -otherwise. - -=head1 BUGS AND LIMITATIONS - -There are no known bugs in DBI::SQL::Nano::Statement. If you find a one -and want to report, please see L for how to report bugs. - -DBI::SQL::Nano::Statement is designed to provide a minimal subset for -executing SQL statements. - -The most important limitation might be the restriction on one table per -statement. This implies, that no JOINs are supported and there cannot be -any foreign key relation between tables. - -The where clause evaluation of DBI::SQL::Nano::Statement is very slow -(SQL::Statement uses a precompiled evaluation). - -INSERT can handle only one row per statement. To insert multiple rows, -use placeholders as explained in DBI. - -The DBI::SQL::Nano parser is very limited and does not support any -additional syntax such as brackets, comments, functions, aggregations -etc. - -In contrast to SQL::Statement, temporary tables are not supported. - -=head1 ACKNOWLEDGEMENTS - -Tim Bunce provided the original idea for this module, helped me out of the -tangled trap of namespaces, and provided help and advice all along the way. -Although I wrote it from the ground up, it is based on Jochen Wiedmann's -original design of SQL::Statement, so much of the credit for the API goes -to him. - -=head1 AUTHOR AND COPYRIGHT - -This module is originally written by Jeff Zucker < jzucker AT cpan.org > - -This module is currently maintained by Jens Rehsack < jrehsack AT cpan.org > - -Copyright (C) 2010 by Jens Rehsack, all rights reserved. -Copyright (C) 2004 by Jeff Zucker, all rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, -as specified in the Perl README file. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Util/CacheMemory.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Util/CacheMemory.pm deleted file mode 100644 index ee61690..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Util/CacheMemory.pm +++ /dev/null @@ -1,117 +0,0 @@ -package DBI::Util::CacheMemory; - -# $Id: CacheMemory.pm 10314 2007-11-26 22:25:33Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -=head1 NAME - -DBI::Util::CacheMemory - a very fast but very minimal subset of Cache::Memory - -=head1 DESCRIPTION - -Like Cache::Memory (part of the Cache distribution) but doesn't support any fancy features. - -This module aims to be a very fast compatible strict sub-set for simple cases, -such as basic client-side caching for DBD::Gofer. - -Like Cache::Memory, and other caches in the Cache and Cache::Cache -distributions, the data will remain in the cache until cleared, it expires, -or the process dies. The cache object simply going out of scope will I -destroy the data. - -=head1 METHODS WITH CHANGES - -=head2 new - -All options except C are ignored. - -=head2 set - -Doesn't support expiry. - -=head2 purge - -Same as clear() - deletes everything in the namespace. - -=head1 METHODS WITHOUT CHANGES - -=over - -=item clear - -=item count - -=item exists - -=item remove - -=back - -=head1 UNSUPPORTED METHODS - -If it's not listed above, it's not supported. - -=cut - -our $VERSION = "0.010315"; - -my %cache; - -sub new { - my ($class, %options ) = @_; - my $namespace = $options{namespace} ||= 'Default'; - #$options{_cache} = \%cache; # can be handy for debugging/dumping - my $self = bless \%options => $class; - $cache{ $namespace } ||= {}; # init - ensure it exists - return $self; -} - -sub set { - my ($self, $key, $value) = @_; - $cache{ $self->{namespace} }->{$key} = $value; -} - -sub get { - my ($self, $key) = @_; - return $cache{ $self->{namespace} }->{$key}; -} - -sub exists { - my ($self, $key) = @_; - return exists $cache{ $self->{namespace} }->{$key}; -} - -sub remove { - my ($self, $key) = @_; - return delete $cache{ $self->{namespace} }->{$key}; -} - -sub purge { - return shift->clear; -} - -sub clear { - $cache{ shift->{namespace} } = {}; -} - -sub count { - return scalar keys %{ $cache{ shift->{namespace} } }; -} - -sub size { - my $c = $cache{ shift->{namespace} }; - my $size = 0; - while ( my ($k,$v) = each %$c ) { - $size += length($k) + length($v); - } - return $size; -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/Util/_accessor.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/Util/_accessor.pm deleted file mode 100644 index 6bb0936..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/Util/_accessor.pm +++ /dev/null @@ -1,65 +0,0 @@ -package DBI::Util::_accessor; -use strict; -use Carp; -our $VERSION = "0.009479"; - -# inspired by Class::Accessor::Fast - -sub new { - my($proto, $fields) = @_; - my($class) = ref $proto || $proto; - $fields ||= {}; - - my @dubious = grep { !m/^_/ && !$proto->can($_) } keys %$fields; - carp "$class doesn't have accessors for fields: @dubious" if @dubious; - - # make a (shallow) copy of $fields. - bless {%$fields}, $class; -} - -sub mk_accessors { - my($self, @fields) = @_; - $self->mk_accessors_using('make_accessor', @fields); -} - -sub mk_accessors_using { - my($self, $maker, @fields) = @_; - my $class = ref $self || $self; - - # So we don't have to do lots of lookups inside the loop. - $maker = $self->can($maker) unless ref $maker; - - no strict 'refs'; - foreach my $field (@fields) { - my $accessor = $self->$maker($field); - *{$class."\:\:$field"} = $accessor - unless defined &{$class."\:\:$field"}; - } - #my $hash_ref = \%{$class."\:\:_accessors_hash}; - #$hash_ref->{$_}++ for @fields; - # XXX also copy down _accessors_hash of base class(es) - # so one in this class is complete - return; -} - -sub make_accessor { - my($class, $field) = @_; - return sub { - my $self = shift; - return $self->{$field} unless @_; - croak "Too many arguments to $field" if @_ > 1; - return $self->{$field} = shift; - }; -} - -sub make_accessor_autoviv_hashref { - my($class, $field) = @_; - return sub { - my $self = shift; - return $self->{$field} ||= {} unless @_; - croak "Too many arguments to $field" if @_ > 1; - return $self->{$field} = shift; - }; -} - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/DBI/W32ODBC.pm b/dbLifeLog/DBI-1.641/blib/lib/DBI/W32ODBC.pm deleted file mode 100644 index 2689968..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/DBI/W32ODBC.pm +++ /dev/null @@ -1,181 +0,0 @@ -package - DBI; # hide this non-DBI package from simple indexers - -# $Id: W32ODBC.pm 8696 2007-01-24 23:12:38Z Tim $ -# -# Copyright (c) 1997,1999 Tim Bunce -# With many thanks to Patrick Hollins for polishing. -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -=head1 NAME - -DBI::W32ODBC - An experimental DBI emulation layer for Win32::ODBC - -=head1 SYNOPSIS - - use DBI::W32ODBC; - - # apart from the line above everything is just the same as with - # the real DBI when using a basic driver with few features. - -=head1 DESCRIPTION - -This is an experimental pure perl DBI emulation layer for Win32::ODBC - -If you can improve this code I'd be interested in hearing about it. If -you are having trouble using it please respect the fact that it's very -experimental. Ideally fix it yourself and send me the details. - -=head2 Some Things Not Yet Implemented - - Most attributes including PrintError & RaiseError. - type_info and table_info - -Volunteers welcome! - -=cut - -${'DBI::VERSION'} # hide version from PAUSE indexer - = "0.01"; - -my $Revision = sprintf("12.%06d", q$Revision: 8696 $ =~ /(\d+)/o); - - -sub DBI::W32ODBC::import { } # must trick here since we're called DBI/W32ODBC.pm - - -use Carp; - -use Win32::ODBC; - -@ISA = qw(Win32::ODBC); - -use strict; - -$DBI::dbi_debug = $ENV{PERL_DBI_DEBUG} || 0; -carp "Loaded (W32ODBC) DBI.pm ${'DBI::VERSION'} (debug $DBI::dbi_debug)" - if $DBI::dbi_debug; - - - -sub connect { - my ($class, $dbname, $dbuser, $dbpasswd, $module, $attr) = @_; - $dbname .= ";UID=$dbuser" if $dbuser; - $dbname .= ";PWD=$dbpasswd" if $dbpasswd; - my $h = new Win32::ODBC $dbname; - warn "Error connecting to $dbname: ".Win32::ODBC::Error()."\n" unless $h; - bless $h, $class if $h; # rebless into our class - $h; -} - - -sub quote { - my ($h, $string) = @_; - return "NULL" if !defined $string; - $string =~ s/'/''/g; # standard - # This hack seems to be required for Access but probably breaks for - # other databases when using \r and \n. It would be better if we could - # use ODBC options to detect that we're actually using Access. - $string =~ s/\r/' & chr\$(13) & '/g; - $string =~ s/\n/' & chr\$(10) & '/g; - "'$string'"; -} - -sub do { - my($h, $statement, $attribs, @params) = @_; - Carp::carp "\$h->do() attribs unused" if $attribs; - my $new_h = $h->prepare($statement) or return undef; ## - pop @{ $h->{'___sths'} }; ## certain death assured - $new_h->execute(@params) or return undef; ## - my $rows = $new_h->rows; ## - $new_h->finish; ## bang bang - ($rows == 0) ? "0E0" : $rows; -} - -# --- - -sub prepare { - my ($h, $sql) = @_; - ## opens a new connection with every prepare to allow - ## multiple, concurrent queries - my $new_h = new Win32::ODBC $h->{DSN}; ## - return undef if not $new_h; ## bail if no connection - bless $new_h; ## shouldn't be sub-classed... - $new_h->{'__prepare'} = $sql; ## - $new_h->{NAME} = []; ## - $new_h->{NUM_OF_FIELDS} = -1; ## - push @{ $h->{'___sths'} } ,$new_h; ## save sth in parent for mass destruction - return $new_h; ## -} - -sub execute { - my ($h) = @_; - my $rc = $h->Sql($h->{'__prepare'}); - return undef if $rc; - my @fields = $h->FieldNames; - $h->{NAME} = \@fields; - $h->{NUM_OF_FIELDS} = scalar @fields; - $h; # return dbh as pseudo sth -} - - -sub fetchrow_hashref { ## provide DBI compatibility - my $h = shift; - my $NAME = shift || "NAME"; - my $row = $h->fetchrow_arrayref or return undef; - my %hash; - @hash{ @{ $h->{$NAME} } } = @$row; - return \%hash; -} - -sub fetchrow { - my $h = shift; - return unless $h->FetchRow(); - my $fields_r = $h->{NAME}; - return $h->Data(@$fields_r); -} -sub fetch { - my @row = shift->fetchrow; - return undef unless @row; - return \@row; -} -*fetchrow_arrayref = \&fetch; ## provide DBI compatibility -*fetchrow_array = \&fetchrow; ## provide DBI compatibility - -sub rows { - shift->RowCount; -} - -sub finish { - shift->Close; ## uncommented this line -} - -# --- - -sub commit { - shift->Transact(ODBC::SQL_COMMIT); -} -sub rollback { - shift->Transact(ODBC::SQL_ROLLBACK); -} - -sub disconnect { - my ($h) = shift; ## this will kill all the statement handles - foreach (@{$h->{'___sths'}}) { ## created for a specific connection - $_->Close if $_->{DSN}; ## - } ## - $h->Close; ## -} - -sub err { - (shift->Error)[0]; -} -sub errstr { - scalar( shift->Error ); -} - -# --- - -1; diff --git a/dbLifeLog/DBI-1.641/blib/lib/Win32/DBIODBC.pm b/dbLifeLog/DBI-1.641/blib/lib/Win32/DBIODBC.pm deleted file mode 100644 index f033444..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/Win32/DBIODBC.pm +++ /dev/null @@ -1,248 +0,0 @@ -package # hide this package from CPAN indexer - Win32::ODBC; - -use strict; - -use DBI; - -# once we've been loaded we don't want perl to load the real Win32::ODBC -$INC{'Win32/ODBC.pm'} = $INC{'Win32/DBIODBC.pm'} || 1; - -#my $db = new Win32::ODBC("DSN=$self->{'DSN'};UID=$self->{'UID'};PWD=$self->{'PWD'};"); - -#EMU --- my $db = new Win32::ODBC("DSN=$DSN;UID=$login;PWD=$password;"); -sub new -{ - shift; - my $connect_line= shift; - -# [R] self-hack to allow empty UID and PWD - my $temp_connect_line; - $connect_line=~/DSN=\w+/; - $temp_connect_line="$&;"; - if ($connect_line=~/UID=\w?/) - {$temp_connect_line.="$&;";} - else {$temp_connect_line.="UID=;";}; - if ($connect_line=~/PWD=\w?/) - {$temp_connect_line.="$&;";} - else {$temp_connect_line.="PWD=;";}; - $connect_line=$temp_connect_line; -# -[R]- - - my $self= {}; - - - $_=$connect_line; - /^(DSN=)(.*)(;UID=)(.*)(;PWD=)(.*)(;)$/; - - #---- DBI CONNECTION VARIABLES - - $self->{ODBC_DSN}=$2; - $self->{ODBC_UID}=$4; - $self->{ODBC_PWD}=$6; - - - #---- DBI CONNECTION VARIABLES - $self->{DBI_DBNAME}=$self->{ODBC_DSN}; - $self->{DBI_USER}=$self->{ODBC_UID}; - $self->{DBI_PASSWORD}=$self->{ODBC_PWD}; - $self->{DBI_DBD}='ODBC'; - - #---- DBI CONNECTION - $self->{'DBI_DBH'}=DBI->connect($self->{'DBI_DBNAME'}, - $self->{'DBI_USER'},$self->{'DBI_PASSWORD'},$self->{'DBI_DBD'}); - - warn "Error($DBI::err) : $DBI::errstr\n" if ! $self->{'DBI_DBH'}; - - - #---- RETURN - - bless $self; -} - - -#EMU --- $db->Sql('SELECT * FROM DUAL'); -sub Sql -{ - my $self= shift; - my $SQL_statment=shift; - - # print " SQL : $SQL_statment \n"; - - $self->{'DBI_SQL_STATMENT'}=$SQL_statment; - - my $dbh=$self->{'DBI_DBH'}; - - # print " DBH : $dbh \n"; - - my $sth=$dbh->prepare("$SQL_statment"); - - # print " STH : $sth \n"; - - $self->{'DBI_STH'}=$sth; - - if ($sth) - { - $sth->execute(); - } - - #--- GET ERROR MESSAGES - $self->{DBI_ERR}=$DBI::err; - $self->{DBI_ERRSTR}=$DBI::errstr; - - if ($sth) - { - #--- GET COLUMNS NAMES - $self->{'DBI_NAME'} = $sth->{NAME}; - } - -# [R] provide compatibility with Win32::ODBC's way of identifying erroneous SQL statements - return ($self->{'DBI_ERR'})?1:undef; -# -[R]- -} - - -#EMU --- $db->FetchRow()) -sub FetchRow -{ - my $self= shift; - - my $sth=$self->{'DBI_STH'}; - if ($sth) - { - my @row=$sth->fetchrow_array; - $self->{'DBI_ROW'}=\@row; - - if (scalar(@row)>0) - { - #-- the row of result is not nul - #-- return something nothing will be return else - return 1; - } - } - return undef; -} - -# [R] provide compatibility with Win32::ODBC's Data() method. -sub Data -{ - my $self=shift; - my @array=@{$self->{'DBI_ROW'}}; - foreach my $element (@array) - { - # remove padding of spaces by DBI - $element=~s/(\s*$)//; - }; - return (wantarray())?@array:join('', @array); -}; -# -[R]- - -#EMU --- %record = $db->DataHash; -sub DataHash -{ - my $self= shift; - - my $p_name=$self->{'DBI_NAME'}; - my $p_row=$self->{'DBI_ROW'}; - - my @name=@$p_name; - my @row=@$p_row; - - my %DataHash; -#print @name; print "\n"; print @row; -# [R] new code that seems to work consistent with Win32::ODBC - while (@name) - { - my $name=shift(@name); - my $value=shift(@row); - - # remove padding of spaces by DBI - $name=~s/(\s*$)//; - $value=~s/(\s*$)//; - - $DataHash{$name}=$value; - }; -# -[R]- - -# [R] old code that didn't appear to work -# foreach my $name (@name) -# { -# $name=~s/(^\s*)|(\s*$)//; -# my @arr=@$name; -# foreach (@arr) -# { -# print "lot $name name col $_ or ROW= 0 $row[0] 1 $row[1] 2 $row[2] \n "; -# $DataHash{$name}=shift(@row); -# } -# } -# -[R]- - - #--- Return Hash - return %DataHash; -} - - -#EMU --- $db->Error() -sub Error -{ - my $self= shift; - - if ($self->{'DBI_ERR'} ne '') - { - #--- Return error message - $self->{'DBI_ERRSTR'}; - } - - #-- else good no error message - -} - -# [R] provide compatibility with Win32::ODBC's Close() method. -sub Close -{ - my $self=shift; - - my $dbh=$self->{'DBI_DBH'}; - $dbh->disconnect; -} -# -[R]- - -1; - -__END__ - -# [R] to -[R]- indicate sections edited by me, Roy Lee - -=head1 NAME - -Win32::DBIODBC - Win32::ODBC emulation layer for the DBI - -=head1 SYNOPSIS - - use Win32::DBIODBC; # instead of use Win32::ODBC - -=head1 DESCRIPTION - -This is a I basic I alpha quality Win32::ODBC emulation -for the DBI. To use it just replace - - use Win32::ODBC; - -in your scripts with - - use Win32::DBIODBC; - -or, while experimenting, you can pre-load this module without changing your -scripts by doing - - perl -MWin32::DBIODBC your_script_name - -=head1 TO DO - -Error handling is virtually non-existent. - -=head1 AUTHOR - -Tom Horen - -=cut diff --git a/dbLifeLog/DBI-1.641/blib/lib/auto/DBI/.exists b/dbLifeLog/DBI-1.641/blib/lib/auto/DBI/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBI-1.641/blib/lib/dbixs_rev.pl b/dbLifeLog/DBI-1.641/blib/lib/dbixs_rev.pl deleted file mode 100644 index 9e83eb1..0000000 --- a/dbLifeLog/DBI-1.641/blib/lib/dbixs_rev.pl +++ /dev/null @@ -1,51 +0,0 @@ -#!perl -w -use strict; - -my $dbixs_rev_file = "dbixs_rev.h"; - -my $is_make_dist; -my $svnversion; - -if (is_dbi_svn_dir(".")) { - $svnversion = `svnversion -n`; -} -elsif (is_dbi_svn_dir("..")) { - # presumably we're in a subdirectory because the user is doing a 'make dist' - $svnversion = `svnversion -n ..`; - $is_make_dist = 1; -} -else { - # presumably we're being run by an end-user because their file timestamps - # got messed up - print "Skipping regeneration of $dbixs_rev_file\n"; - utime(time(), time(), $dbixs_rev_file); # update modification time - exit 0; -} - -my @warn; -die "Neither current directory nor parent directory are an svn working copy\n" - unless $svnversion and $svnversion =~ m/^\d+/; -push @warn, "Mixed revision working copy ($svnversion:$1)" - if $svnversion =~ s/:(\d+)//; -push @warn, "Code modified since last checkin" - if $svnversion =~ s/[MS]+$//; -warn "$dbixs_rev_file warning: $_\n" for @warn; -die "$0 failed\n" if $is_make_dist && @warn; - -write_header($dbixs_rev_file, DBIXS_REVISION => $svnversion, \@warn); - -sub write_header { - my ($file, $macro, $version, $comments_ref) = @_; - open my $fh, ">$file" or die "Can't open $file: $!\n"; - unshift @$comments_ref, scalar localtime(time); - print $fh "/* $_ */\n" for @$comments_ref; - print $fh "#define $macro $version\n"; - close $fh or die "Error closing $file: $!\n"; - print "Wrote $macro $version to $file\n"; -} - -sub is_dbi_svn_dir { - my ($dir) = @_; - return (-d "$dir/.svn" && -f "$dir/MANIFEST.SKIP"); -} - diff --git a/dbLifeLog/DBI-1.641/blib/man1/.exists b/dbLifeLog/DBI-1.641/blib/man1/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBI-1.641/blib/man1/dbilogstrip.1p b/dbLifeLog/DBI-1.641/blib/man1/dbilogstrip.1p deleted file mode 100644 index 21fa102..0000000 --- a/dbLifeLog/DBI-1.641/blib/man1/dbilogstrip.1p +++ /dev/null @@ -1,115 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBILOGSTRIP 1p" -.TH DBILOGSTRIP 1p "2018-08-03" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -dbilogstrip \- filter to normalize DBI trace logs for diff'ing -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -Read \s-1DBI\s0 trace file \f(CW\*(C`dbitrace.log\*(C'\fR and write out a stripped version to \f(CW\*(C`dbitrace_stripped.log\*(C'\fR -.PP -.Vb 1 -\& dbilogstrip dbitrace.log > dbitrace_stripped.log -.Ve -.PP -Run \f(CW\*(C`yourscript.pl\*(C'\fR twice, each with different sets of arguments, with -\&\s-1DBI_TRACE\s0 enabled. Filter the output and trace through \f(CW\*(C`dbilogstrip\*(C'\fR into a -separate file for each run. Then compare using diff. (This example assumes -you're using a standard shell.) -.PP -.Vb 3 -\& DBI_TRACE=2 perl yourscript.pl ...args1... 2>&1 | dbilogstrip > dbitrace1.log -\& DBI_TRACE=2 perl yourscript.pl ...args2... 2>&1 | dbilogstrip > dbitrace2.log -\& diff \-u dbitrace1.log dbitrace2.log -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Replaces any hex addresses, e.g, \f(CW0x128f72ce\fR with \f(CW\*(C`0xN\*(C'\fR. -.PP -Replaces any references to process id or thread id, like \f(CW\*(C`pid#6254\*(C'\fR with \f(CW\*(C`pidN\*(C'\fR. -.PP -So a \s-1DBI\s0 trace line like this: -.PP -.Vb 1 -\& \-> STORE for DBD::DBM::st (DBI::st=HASH(0x19162a0)~0x191f9c8 \*(Aqf_params\*(Aq ARRAY(0x1922018)) thr#1800400 -.Ve -.PP -will look like this: -.PP -.Vb 1 -\& \-> STORE for DBD::DBM::st (DBI::st=HASH(0xN)~0xN \*(Aqf_params\*(Aq ARRAY(0xN)) thrN -.Ve diff --git a/dbLifeLog/DBI-1.641/blib/man1/dbiprof.1p b/dbLifeLog/DBI-1.641/blib/man1/dbiprof.1p deleted file mode 100644 index 54c7b76..0000000 --- a/dbLifeLog/DBI-1.641/blib/man1/dbiprof.1p +++ /dev/null @@ -1,225 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBIPROF 1p" -.TH DBIPROF 1p "2018-08-03" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -dbiprof \- command\-line client for DBI::ProfileData -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -See a report of the ten queries with the longest total runtime in the -profile dump file \fIprof1.out\fR: -.PP -.Vb 1 -\& dbiprof prof1.out -.Ve -.PP -See the top 10 most frequently run queries in the profile file -\&\fIdbi.prof\fR (the default): -.PP -.Vb 1 -\& dbiprof \-\-sort count -.Ve -.PP -See the same report with 15 entries: -.PP -.Vb 1 -\& dbiprof \-\-sort count \-\-number 15 -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This tool is a command-line client for the DBI::ProfileData. It -allows you to analyze the profile data file produced by -DBI::ProfileDumper and produce various useful reports. -.SH "OPTIONS" -.IX Header "OPTIONS" -This program accepts the following options: -.IP "\-\-number N" 4 -.IX Item "--number N" -Produce this many items in the report. Defaults to 10. If set to -\&\*(L"all\*(R" then all results are shown. -.IP "\-\-sort field" 4 -.IX Item "--sort field" -Sort results by the given field. Sorting by multiple fields isn't currently -supported (patches welcome). The available sort fields are: -.RS 4 -.IP "total" 4 -.IX Item "total" -Sorts by total time run time across all runs. This is the default -sort. -.IP "longest" 4 -.IX Item "longest" -Sorts by the longest single run. -.IP "count" 4 -.IX Item "count" -Sorts by total number of runs. -.IP "first" 4 -.IX Item "first" -Sorts by the time taken in the first run. -.IP "shortest" 4 -.IX Item "shortest" -Sorts by the shortest single run. -.IP "key1" 4 -.IX Item "key1" -Sorts by the value of the first element in the Path, which should be numeric. -You can also sort by \f(CW\*(C`key2\*(C'\fR and \f(CW\*(C`key3\*(C'\fR. -.RE -.RS 4 -.RE -.IP "\-\-reverse" 4 -.IX Item "--reverse" -Reverses the selected sort. For example, to see a report of the -shortest overall time: -.Sp -.Vb 1 -\& dbiprof \-\-sort total \-\-reverse -.Ve -.IP "\-\-match keyN=value" 4 -.IX Item "--match keyN=value" -Consider only items where the specified key matches the given value. -Keys are numbered from 1. For example, let's say you used a -DBI::Profile Path of: -.Sp -.Vb 1 -\& [ DBIprofile_Statement, DBIprofile_Methodname ] -.Ve -.Sp -And called dbiprof as in: -.Sp -.Vb 1 -\& dbiprof \-\-match key2=execute -.Ve -.Sp -Your report would only show execute queries, leaving out prepares, -fetches, etc. -.Sp -If the value given starts and ends with slashes (\f(CW\*(C`/\*(C'\fR) then it will be -treated as a regular expression. For example, to only include \s-1SELECT\s0 -queries where key1 is the statement: -.Sp -.Vb 1 -\& dbiprof \-\-match key1=/^SELECT/ -.Ve -.Sp -By default the match expression is matched case-insensitively, but -this can be changed with the \-\-case\-sensitive option. -.IP "\-\-exclude keyN=value" 4 -.IX Item "--exclude keyN=value" -Remove items for where the specified key matches the given value. For -example, to exclude all prepare entries where key2 is the method name: -.Sp -.Vb 1 -\& dbiprof \-\-exclude key2=prepare -.Ve -.Sp -Like \f(CW\*(C`\-\-match\*(C'\fR, If the value given starts and ends with slashes -(\f(CW\*(C`/\*(C'\fR) then it will be treated as a regular expression. For example, -to exclude \s-1UPDATE\s0 queries where key1 is the statement: -.Sp -.Vb 1 -\& dbiprof \-\-match key1=/^UPDATE/ -.Ve -.Sp -By default the exclude expression is matched case-insensitively, but -this can be changed with the \-\-case\-sensitive option. -.IP "\-\-case\-sensitive" 4 -.IX Item "--case-sensitive" -Using this option causes \-\-match and \-\-exclude to work -case-sensitively. Defaults to off. -.IP "\-\-delete" 4 -.IX Item "--delete" -Sets the \f(CW\*(C`DeleteFiles\*(C'\fR option to DBI::ProfileData which causes the -files to be deleted after reading. See DBI::ProfileData for more details. -.IP "\-\-dumpnodes" 4 -.IX Item "--dumpnodes" -Print the list of nodes in the form of a perl data structure. -Use the \f(CW\*(C`\-sort\*(C'\fR option if you want the list sorted. -.IP "\-\-version" 4 -.IX Item "--version" -Print the dbiprof version number and exit. -.SH "AUTHOR" -.IX Header "AUTHOR" -Sam Tregar -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -Copyright (C) 2002 Sam Tregar -.PP -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -DBI::ProfileDumper, -DBI::Profile, \s-1DBI\s0. diff --git a/dbLifeLog/DBI-1.641/blib/man1/dbiproxy.1p b/dbLifeLog/DBI-1.641/blib/man1/dbiproxy.1p deleted file mode 100644 index 9c23fe1..0000000 --- a/dbLifeLog/DBI-1.641/blib/man1/dbiproxy.1p +++ /dev/null @@ -1,213 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBIPROXY 1p" -.TH DBIPROXY 1p "2018-08-03" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -dbiproxy \- A proxy server for the DBD::Proxy driver -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& dbiproxy \-\-localport= -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This tool is just a front end for the DBI::ProxyServer package. All it -does is picking options from the command line and calling -\&\fIDBI::ProxyServer::main()\fR. See DBI::ProxyServer for details. -.PP -Available options include: -.IP "\fB\-\-chroot=dir\fR" 4 -.IX Item "--chroot=dir" -(\s-1UNIX\s0 only) After doing a \fIbind()\fR, change root directory to the given -directory by doing a \fIchroot()\fR. This is useful for security, but it -restricts the environment a lot. For example, you need to load \s-1DBI\s0 -drivers in the config file or you have to create hard links to Unix -sockets, if your drivers are using them. For example, with MySQL, a -config file might contain the following lines: -.Sp -.Vb 9 -\& my $rootdir = \*(Aq/var/dbiproxy\*(Aq; -\& my $unixsockdir = \*(Aq/tmp\*(Aq; -\& my $unixsockfile = \*(Aqmysql.sock\*(Aq; -\& foreach $dir ($rootdir, "$rootdir$unixsockdir") { -\& mkdir 0755, $dir; -\& } -\& link("$unixsockdir/$unixsockfile", -\& "$rootdir$unixsockdir/$unixsockfile"); -\& require DBD::mysql; -\& -\& { -\& \*(Aqchroot\*(Aq => $rootdir, -\& ... -\& } -.Ve -.Sp -If you don't know \fIchroot()\fR, think of an \s-1FTP\s0 server where you can see a -certain directory tree only after logging in. See also the \-\-group and -\&\-\-user options. -.IP "\fB\-\-configfile=file\fR" 4 -.IX Item "--configfile=file" -Config files are assumed to return a single hash ref that overrides the -arguments of the new method. However, command line arguments in turn take -precedence over the config file. See the \*(L"\s-1CONFIGURATION FILE\*(R"\s0 section -in the DBI::ProxyServer documentation for details on the config file. -.IP "\fB\-\-debug\fR" 4 -.IX Item "--debug" -Turn debugging mode on. Mainly this asserts that logging messages of -level \*(L"debug\*(R" are created. -.IP "\fB\-\-facility=mode\fR" 4 -.IX Item "--facility=mode" -(\s-1UNIX\s0 only) Facility to use for Sys::Syslog. The default is -\&\fBdaemon\fR. -.IP "\fB\-\-group=gid\fR" 4 -.IX Item "--group=gid" -After doing a \fIbind()\fR, change the real and effective \s-1GID\s0 to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the \-\-user option. -.Sp -\&\s-1GID\s0's can be passed as group names or numeric values. -.IP "\fB\-\-localaddr=ip\fR" 4 -.IX Item "--localaddr=ip" -By default a daemon is listening to any \s-1IP\s0 number that a machine -has. This attribute allows one to restrict the server to the given -\&\s-1IP\s0 number. -.IP "\fB\-\-localport=port\fR" 4 -.IX Item "--localport=port" -This attribute sets the port on which the daemon is listening. It -must be given somehow, as there's no default. -.IP "\fB\-\-logfile=file\fR" 4 -.IX Item "--logfile=file" -Be default logging messages will be written to the syslog (Unix) or -to the event log (Windows \s-1NT\s0). On other operating systems you need to -specify a log file. The special value \*(L"\s-1STDERR\*(R"\s0 forces logging to -stderr. See Net::Daemon::Log for details. -.IP "\fB\-\-mode=modename\fR" 4 -.IX Item "--mode=modename" -The server can run in three different modes, depending on the environment. -.Sp -If you are running Perl 5.005 and did compile it for threads, then the -server will create a new thread for each connection. The thread will -execute the server's \fIRun()\fR method and then terminate. This mode is the -default, you can force it with \*(L"\-\-mode=threads\*(R". -.Sp -If threads are not available, but you have a working \fIfork()\fR, then the -server will behave similar by creating a new process for each connection. -This mode will be used automatically in the absence of threads or if -you use the \*(L"\-\-mode=fork\*(R" option. -.Sp -Finally there's a single-connection mode: If the server has accepted a -connection, he will enter the \fIRun()\fR method. No other connections are -accepted until the \fIRun()\fR method returns (if the client disconnects). -This operation mode is useful if you have neither threads nor \fIfork()\fR, -for example on the Macintosh. For debugging purposes you can force this -mode with \*(L"\-\-mode=single\*(R". -.IP "\fB\-\-pidfile=file\fR" 4 -.IX Item "--pidfile=file" -(\s-1UNIX\s0 only) If this option is present, a \s-1PID\s0 file will be created at the -given location. Default is to not create a pidfile. -.IP "\fB\-\-user=uid\fR" 4 -.IX Item "--user=uid" -After doing a \fIbind()\fR, change the real and effective \s-1UID\s0 to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the \-\-group and the \-\-chroot options. -.Sp -\&\s-1UID\s0's can be passed as group names or numeric values. -.IP "\fB\-\-version\fR" 4 -.IX Item "--version" -Suppresses startup of the server; instead the version string will -be printed and the program exits immediately. -.SH "AUTHOR" -.IX Header "AUTHOR" -.Vb 4 -\& Copyright (c) 1997 Jochen Wiedmann -\& Am Eisteich 9 -\& 72555 Metzingen -\& Germany -\& -\& Email: joe@ispsoft.de -\& Phone: +49 7123 14881 -.Ve -.PP -The DBI::ProxyServer module is free software; you can redistribute it -and/or modify it under the same terms as Perl itself. In particular -permission is granted to Tim Bunce for distributing this as a part of -the \s-1DBI.\s0 -.SH "SEE ALSO" -.IX Header "SEE ALSO" -DBI::ProxyServer, DBD::Proxy, \s-1DBI\s0 diff --git a/dbLifeLog/DBI-1.641/blib/man3/.exists b/dbLifeLog/DBI-1.641/blib/man3/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBI-1.641/blib/man3/Bundle::DBI.3pm b/dbLifeLog/DBI-1.641/blib/man3/Bundle::DBI.3pm deleted file mode 100644 index d957a10..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/Bundle::DBI.3pm +++ /dev/null @@ -1,114 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "Bundle::DBI 3pm" -.TH Bundle::DBI 3pm "2015-05-26" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -Bundle::DBI \- A bundle to install DBI and required modules. -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& perl \-MCPAN \-e \*(Aqinstall Bundle::DBI\*(Aq -.Ve -.SH "CONTENTS" -.IX Header "CONTENTS" -\&\s-1DBI \-\s0 for to get to know thyself -.PP -DBI::Shell 11.91 \- the \s-1DBI\s0 command line shell -.PP -Storable 2.06 \- for DBD::Proxy, DBI::ProxyServer, DBD::Forward -.PP -Net::Daemon 0.37 \- for DBD::Proxy and DBI::ProxyServer -.PP -RPC::PlServer 0.2016 \- for DBD::Proxy and DBI::ProxyServer -.PP -DBD::Multiplex 1.19 \- treat multiple db handles as one -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This bundle includes all the modules used by the Perl Database -Interface (\s-1DBI\s0) module, created by Tim Bunce. -.PP -A \fIBundle\fR is a module that simply defines a collection of other -modules. It is used by the \s-1CPAN\s0 module to automate the fetching, -building and installing of modules from the \s-1CPAN\s0 ftp archive sites. -.PP -This bundle does not deal with the various database drivers (e.g. -DBD::Informix, DBD::Oracle etc), most of which require software from -sources other than \s-1CPAN.\s0 You'll need to fetch and build those drivers -yourself. -.SH "AUTHORS" -.IX Header "AUTHORS" -Jonathan Leffler, Jochen Wiedmann and Tim Bunce. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::DBM.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::DBM.3pm deleted file mode 100644 index 6dffd34..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::DBM.3pm +++ /dev/null @@ -1,924 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::DBM 3pm" -.TH DBD::DBM 3pm "2013-09-08" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::DBM \- a DBI driver for DBM & MLDBM files -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 5 -\& use DBI; -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); # defaults to SDBM_File -\& $dbh = DBI\->connect(\*(AqDBI:DBM(RaiseError=1):\*(Aq); # defaults to SDBM_File -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:dbm_type=DB_File\*(Aq); # defaults to DB_File -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:dbm_mldbm=Storable\*(Aq); # MLDBM with SDBM_File -\& -\& # or -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef); -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { -\& f_ext => \*(Aq.db/r\*(Aq, -\& f_dir => \*(Aq/path/to/dbfiles/\*(Aq, -\& f_lockfile => \*(Aq.lck\*(Aq, -\& dbm_type => \*(AqBerkeleyDB\*(Aq, -\& dbm_mldbm => \*(AqFreezeThaw\*(Aq, -\& dbm_store_metadata => 1, -\& dbm_berkeley_flags => { -\& \*(Aq\-Cachesize\*(Aq => 1000, # set a ::Hash flag -\& }, -\& }); -.Ve -.PP -and other variations on \fIconnect()\fR as shown in the \s-1DBI\s0 docs, -DBD::File metadata and \*(L"Metadata\*(R" -shown below. -.PP -Use standard \s-1DBI\s0 prepare, execute, fetch, placeholders, etc., -see \*(L"\s-1QUICK START\*(R"\s0 for an example. -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\s-1DBD::DBM\s0 is a database management system that works right out of the -box. If you have a standard installation of Perl and \s-1DBI\s0 you can -begin creating, accessing, and modifying simple database tables -without any further modules. You can add other modules (e.g., -SQL::Statement, DB_File etc) for improved functionality. -.PP -The module uses a \s-1DBM\s0 file storage layer. \s-1DBM\s0 file storage is common on -many platforms and files can be created with it in many programming -languages using different APIs. That means, in addition to creating -files with \s-1DBI/SQL,\s0 you can also use \s-1DBI/SQL\s0 to access and modify files -created by other \s-1DBM\s0 modules and programs and vice versa. \fBNote\fR that -in those cases it might be necessary to use a common subset of the -provided features. -.PP -\&\s-1DBM\s0 files are stored in binary format optimized for quick retrieval -when using a key field. That optimization can be used advantageously -to make \s-1DBD::DBM SQL\s0 operations that use key fields very fast. There -are several different \*(L"flavors\*(R" of \s-1DBM\s0 which use different storage -formats supported by perl modules such as SDBM_File and \s-1MLDBM. \s0 This -module supports all of the flavors that perl supports and, when used -with \s-1MLDBM,\s0 supports tables with any number of columns and insertion -of Perl objects into tables. -.PP -\&\s-1DBD::DBM\s0 has been tested with the following \s-1DBM\s0 types: SDBM_File, -NDBM_File, ODBM_File, GDBM_File, DB_File, BerkeleyDB. Each type was -tested both with and without \s-1MLDBM\s0 and with the Data::Dumper, -Storable, FreezeThaw, \s-1YAML\s0 and \s-1JSON\s0 serializers using the DBI::SQL::Nano -or the SQL::Statement engines. -.SH "QUICK START" -.IX Header "QUICK START" -\&\s-1DBD::DBM\s0 operates like all other \s-1DBD\s0 drivers \- it's basic syntax and -operation is specified by \s-1DBI. \s0 If you're not familiar with \s-1DBI,\s0 you should -start by reading \s-1DBI\s0 and the documents it points to and then come back -and read this file. If you are familiar with \s-1DBI,\s0 you already know most of -what you need to know to operate this module. Just jump in and create a -test script something like the one shown below. -.PP -You should be aware that there are several options for the \s-1SQL\s0 engine -underlying \s-1DBD::DBM,\s0 see \*(L"Supported \s-1SQL\s0 syntax\*(R". There are also many -options for \s-1DBM\s0 support, see especially the section on \*(L"Adding -multi-column support with \s-1MLDBM\*(R"\s0. -.PP -But here's a sample to get you started. -.PP -.Vb 10 -\& use DBI; -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); -\& $dbh\->{RaiseError} = 1; -\& for my $sql( split /;\en+/," -\& CREATE TABLE user ( user_name TEXT, phone TEXT ); -\& INSERT INTO user VALUES (\*(AqFred Bloggs\*(Aq,\*(Aq233\-7777\*(Aq); -\& INSERT INTO user VALUES (\*(AqSanjay Patel\*(Aq,\*(Aq777\-3333\*(Aq); -\& INSERT INTO user VALUES (\*(AqJunk\*(Aq,\*(Aqxxx\-xxxx\*(Aq); -\& DELETE FROM user WHERE user_name = \*(AqJunk\*(Aq; -\& UPDATE user SET phone = \*(Aq999\-4444\*(Aq WHERE user_name = \*(AqSanjay Patel\*(Aq; -\& SELECT * FROM user -\& "){ -\& my $sth = $dbh\->prepare($sql); -\& $sth\->execute; -\& $sth\->dump_results if $sth\->{NUM_OF_FIELDS}; -\& } -\& $dbh\->disconnect; -.Ve -.SH "USAGE" -.IX Header "USAGE" -This section will explain some usage cases in more detail. To get an -overview about the available attributes, see \*(L"Metadata\*(R". -.SS "Specifying Files and Directories" -.IX Subsection "Specifying Files and Directories" -\&\s-1DBD::DBM\s0 will automatically supply an appropriate file extension for the -type of \s-1DBM\s0 you are using. For example, if you use SDBM_File, a table -called \*(L"fruit\*(R" will be stored in two files called \*(L"fruit.pag\*(R" and -\&\*(L"fruit.dir\*(R". You should \fBnever\fR specify the file extensions in your \s-1SQL\s0 -statements. -.PP -\&\s-1DBD::DBM\s0 recognizes following default extensions for following types: -.IP ".pag/r" 4 -.IX Item ".pag/r" -Chosen for dbm_type \f(CW\*(C`SDBM_File\*(C'\fR, \f(CW\*(C`ODBM_File\*(C'\fR and \f(CW\*(C`NDBM_File\*(C'\fR -when an implementation is detected which wraps \f(CW\*(C`\-ldbm\*(C'\fR for -\&\f(CW\*(C`NDBM_File\*(C'\fR (e.g. Solaris, \s-1AIX, ...\s0). -.Sp -For those types, the \f(CW\*(C`.dir\*(C'\fR extension is recognized, too (for being -deleted when dropping a table). -.IP ".db/r" 4 -.IX Item ".db/r" -Chosen for dbm_type \f(CW\*(C`NDBM_File\*(C'\fR when an implementation is detected -which wraps BerkeleyDB 1.x for \f(CW\*(C`NDBM_File\*(C'\fR (typically \s-1BSD\s0's, Darwin). -.PP -\&\f(CW\*(C`GDBM_File\*(C'\fR, \f(CW\*(C`DB_File\*(C'\fR and \f(CW\*(C`BerkeleyDB\*(C'\fR don't usually -use a file extension. -.PP -If your \s-1DBM\s0 type uses an extension other than one of the recognized -types of extensions, you should set the \fIf_ext\fR attribute to the -extension \fBand\fR file a bug report as described in \s-1DBI\s0 with the name -of the implementation and extension so we can add it to \s-1DBD::DBM.\s0 -Thanks in advance for that :\-). -.PP -.Vb 2 -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:f_ext=.db\*(Aq); # .db extension is used -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:f_ext=\*(Aq); # no extension is used -\& -\& # or -\& $dbh\->{f_ext}=\*(Aq.db\*(Aq; # global setting -\& $dbh\->{f_meta}\->{\*(Aqqux\*(Aq}\->{f_ext}=\*(Aq.db\*(Aq; # setting for table \*(Aqqux\*(Aq -.Ve -.PP -By default files are assumed to be in the current working directory. -To use other directories specify the \fIf_dir\fR attribute in either the -connect string or by setting the database handle attribute. -.PP -For example, this will look for the file /foo/bar/fruit (or -/foo/bar/fruit.pag for \s-1DBM\s0 types that use that extension) -.PP -.Vb 6 -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:f_dir=/foo/bar\*(Aq); -\& # and this will too: -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); -\& $dbh\->{f_dir} = \*(Aq/foo/bar\*(Aq; -\& # but this is recommended -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { f_dir => \*(Aq/foo/bar\*(Aq } ); -\& -\& # now you can do -\& my $ary = $dbh\->selectall_arrayref(q{ SELECT x FROM fruit }); -.Ve -.PP -You can also use delimited identifiers to specify paths directly in \s-1SQL\s0 -statements. This looks in the same place as the two examples above but -without setting \fIf_dir\fR: -.PP -.Vb 4 -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); -\& my $ary = $dbh\->selectall_arrayref(q{ -\& SELECT x FROM "/foo/bar/fruit" -\& }); -.Ve -.PP -You can also tell \s-1DBD::DBM\s0 to use a specified path for a specific table: -.PP -.Vb 1 -\& $dbh\->{dbm_tables}\->{f}\->{file} = q(/foo/bar/fruit); -.Ve -.PP -Please be aware that you cannot specify this during connection. -.PP -If you have SQL::Statement installed, you can use table aliases: -.PP -.Vb 4 -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); -\& my $ary = $dbh\->selectall_arrayref(q{ -\& SELECT f.x FROM "/foo/bar/fruit" AS f -\& }); -.Ve -.PP -See the \*(L"\s-1GOTCHAS AND WARNINGS\*(R"\s0 for using \s-1DROP\s0 on tables. -.SS "Table locking and \fIflock()\fP" -.IX Subsection "Table locking and flock()" -Table locking is accomplished using a lockfile which has the same -basename as the table's file but with the file extension '.lck' (or a -lockfile extension that you supply, see below). This lock file is -created with the table during a \s-1CREATE\s0 and removed during a \s-1DROP.\s0 -Every time the table itself is opened, the lockfile is \fIflocked()\fR. For -\&\s-1SELECT,\s0 this is a shared lock. For all other operations, it is an -exclusive lock (except when you specify something different using the -\&\fIf_lock\fR attribute). -.PP -Since the locking depends on \fIflock()\fR, it only works on operating -systems that support \fIflock()\fR. In cases where \fIflock()\fR is not -implemented, \s-1DBD::DBM\s0 will simply behave as if the \fIflock()\fR had -occurred although no actual locking will happen. Read the -documentation for \fIflock()\fR for more information. -.PP -Even on those systems that do support \fIflock()\fR, locking is only -advisory \- as is always the case with \fIflock()\fR. This means that if -another program tries to access the table file while \s-1DBD::DBM\s0 has the -table locked, that other program will *succeed* at opening unless -it is also using flock on the '.lck' file. As a result \s-1DBD::DBM\s0's -locking only really applies to other programs using \s-1DBD::DBM\s0 or other -program written to cooperate with \s-1DBD::DBM\s0 locking. -.SS "Specifying the \s-1DBM\s0 type" -.IX Subsection "Specifying the DBM type" -Each \*(L"flavor\*(R" of \s-1DBM\s0 stores its files in a different format and has -different capabilities and limitations. See AnyDBM_File for a -comparison of \s-1DBM\s0 types. -.PP -By default, \s-1DBD::DBM\s0 uses the \f(CW\*(C`SDBM_File\*(C'\fR type of storage since -\&\f(CW\*(C`SDBM_File\*(C'\fR comes with Perl itself. If you have other types of -\&\s-1DBM\s0 storage available, you can use any of them with \s-1DBD::DBM.\s0 It is -strongly recommended to use at least \f(CW\*(C`DB_File\*(C'\fR, because \f(CW\*(C`SDBM_File\*(C'\fR has quirks and limitations and \f(CW\*(C`ODBM_file\*(C'\fR, \f(CW\*(C`NDBM_File\*(C'\fR and \f(CW\*(C`GDBM_File\*(C'\fR are not always available. -.PP -You can specify the \s-1DBM\s0 type using the \fIdbm_type\fR attribute which can -be set in the connection string or with \f(CW\*(C`$dbh\->{dbm_type}\*(C'\fR and -\&\f(CW\*(C`$dbh\->{f_meta}\->{$table_name}\->{type}\*(C'\fR for per-table settings in -cases where a single script is accessing more than one kind of \s-1DBM\s0 -file. -.PP -In the connection string, just set \f(CW\*(C`dbm_type=TYPENAME\*(C'\fR where -\&\f(CW\*(C`TYPENAME\*(C'\fR is any \s-1DBM\s0 type such as GDBM_File, DB_File, etc. Do \fInot\fR -use \s-1MLDBM\s0 as your \fIdbm_type\fR as that is set differently, see below. -.PP -.Vb 2 -\& my $dbh=DBI\->connect(\*(Aqdbi:DBM:\*(Aq); # uses the default SDBM_File -\& my $dbh=DBI\->connect(\*(Aqdbi:DBM:dbm_type=GDBM_File\*(Aq); # uses the GDBM_File -\& -\& # You can also use $dbh\->{dbm_type} to set the DBM type for the connection: -\& $dbh\->{dbm_type} = \*(AqDB_File\*(Aq; # set the global DBM type -\& print $dbh\->{dbm_type}; # display the global DBM type -.Ve -.PP -If you have several tables in your script that use different \s-1DBM\s0 -types, you can use the \f(CW$dbh\fR\->{dbm_tables} hash to store different -settings for the various tables. You can even use this to perform -joins on files that have completely different storage mechanisms. -.PP -.Vb 2 -\& # sets global default of GDBM_File -\& my $dbh\->(\*(Aqdbi:DBM:type=GDBM_File\*(Aq); -\& -\& # overrides the global setting, but only for the tables called -\& # I and I -\& my $dbh\->{f_meta}\->{foo}\->{dbm_type} = \*(AqDB_File\*(Aq; -\& my $dbh\->{f_meta}\->{bar}\->{dbm_type} = \*(AqBerkeleyDB\*(Aq; -\& -\& # prints the dbm_type for the table "foo" -\& print $dbh\->{f_meta}\->{foo}\->{dbm_type}; -.Ve -.PP -\&\fBNote\fR that you must change the \fIdbm_type\fR of a table before you access -it for first time. -.SS "Adding multi-column support with \s-1MLDBM\s0" -.IX Subsection "Adding multi-column support with MLDBM" -Most of the \s-1DBM\s0 types only support two columns and even if it would -support more, \s-1DBD::DBM\s0 would only use two. However a \s-1CPAN\s0 module -called \s-1MLDBM\s0 overcomes this limitation by allowing more than two -columns. \s-1MLDBM\s0 does this by serializing the data \- basically it puts -a reference to an array into the second column. It can also put almost -any kind of Perl object or even \fBPerl coderefs\fR into columns. -.PP -If you want more than two columns, you \fBmust\fR install \s-1MLDBM.\s0 It's available -for many platforms and is easy to install. -.PP -\&\s-1MLDBM\s0 is by default distributed with three serializers \- Data::Dumper, -Storable, and FreezeThaw. Data::Dumper is the default and Storable is the -fastest. \s-1MLDBM\s0 can also make use of user-defined serialization methods or -other serialization modules (e.g. \s-1YAML::MLDBM\s0 or -MLDBM::Serializer::JSON. You select the serializer using the -\&\fIdbm_mldbm\fR attribute. -.PP -Some examples: -.PP -.Vb 10 -\& $dbh=DBI\->connect(\*(Aqdbi:DBM:dbm_mldbm=Storable\*(Aq); # use MLDBM with Storable -\& $dbh=DBI\->connect( -\& \*(Aqdbi:DBM:dbm_mldbm=MySerializer\*(Aq # use MLDBM with a user defined module -\& ); -\& $dbh=DBI\->connect(\*(Aqdbi::dbm:\*(Aq, undef, -\& undef, { dbm_mldbm => \*(AqYAML\*(Aq }); # use 3rd party serializer -\& $dbh\->{dbm_mldbm} = \*(AqYAML\*(Aq; # same as above -\& print $dbh\->{dbm_mldbm} # show the MLDBM serializer -\& $dbh\->{f_meta}\->{foo}\->{dbm_mldbm}=\*(AqData::Dumper\*(Aq; # set Data::Dumper for table "foo" -\& print $dbh\->{f_meta}\->{foo}\->{mldbm}; # show serializer for table "foo" -.Ve -.PP -\&\s-1MLDBM\s0 works on top of other \s-1DBM\s0 modules so you can also set a \s-1DBM\s0 type -along with setting dbm_mldbm. The examples above would default to using -SDBM_File with \s-1MLDBM. \s0 If you wanted GDBM_File instead, here's how: -.PP -.Vb 5 -\& # uses DB_File with MLDBM and Storable -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { -\& dbm_type => \*(AqDB_File\*(Aq, -\& dbm_mldbm => \*(AqStorable\*(Aq, -\& }); -.Ve -.PP -SDBM_File, the default \fIdbm_type\fR is quite limited, so if you are going to -use \s-1MLDBM,\s0 you should probably use a different type, see AnyDBM_File. -.PP -See below for some \*(L"\s-1GOTCHAS AND WARNINGS\*(R"\s0 about \s-1MLDBM.\s0 -.SS "Support for Berkeley \s-1DB\s0" -.IX Subsection "Support for Berkeley DB" -The Berkeley \s-1DB\s0 storage type is supported through two different Perl -modules \- DB_File (which supports only features in old versions of Berkeley -\&\s-1DB\s0) and BerkeleyDB (which supports all versions). \s-1DBD::DBM\s0 supports -specifying either \*(L"DB_File\*(R" or \*(L"BerkeleyDB\*(R" as a \fIdbm_type\fR, with or -without \s-1MLDBM\s0 support. -.PP -The \*(L"BerkeleyDB\*(R" dbm_type is experimental and it's interface is likely to -change. It currently defaults to BerkeleyDB::Hash and does not currently -support ::Btree or ::Recno. -.PP -With BerkeleyDB, you can specify initialization flags by setting them in -your script like this: -.PP -.Vb 12 -\& use BerkeleyDB; -\& my $env = new BerkeleyDB::Env \-Home => $dir; # and/or other Env flags -\& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { -\& dbm_type => \*(AqBerkeleyDB\*(Aq, -\& dbm_mldbm => \*(AqStorable\*(Aq, -\& dbm_berkeley_flags => { -\& \*(AqDB_CREATE\*(Aq => DB_CREATE, # pass in constants -\& \*(AqDB_RDONLY\*(Aq => DB_RDONLY, # pass in constants -\& \*(Aq\-Cachesize\*(Aq => 1000, # set a ::Hash flag -\& \*(Aq\-Env\*(Aq => $env, # pass in an environment -\& }, -\& }); -.Ve -.PP -Do \fInot\fR set the \-Flags or \-Filename flags as those are determined and -overwritten by the \s-1SQL \s0(e.g. \-Flags => \s-1DB_RDONLY\s0 is set automatically -when you issue a \s-1SELECT\s0 statement). -.PP -Time has not permitted us to provide support in this release of \s-1DBD::DBM\s0 -for further Berkeley \s-1DB\s0 features such as transactions, concurrency, -locking, etc. We will be working on these in the future and would value -suggestions, patches, etc. -.PP -See DB_File and BerkeleyDB for further details. -.SS "Optimizing the use of key fields" -.IX Subsection "Optimizing the use of key fields" -Most \*(L"flavors\*(R" of \s-1DBM\s0 have only two physical columns (but can contain -multiple logical columns as explained above in -\&\*(L"Adding multi-column support with \s-1MLDBM\*(R"\s0). They work similarly to a -Perl hash with the first column serving as the key. Like a Perl hash, \s-1DBM\s0 -files permit you to do quick lookups by specifying the key and thus avoid -looping through all records (supported by DBI::SQL::Nano only). Also like -a Perl hash, the keys must be unique. It is impossible to create two -records with the same key. To put this more simply and in \s-1SQL\s0 terms, -the key column functions as the \fI\s-1PRIMARY KEY\s0\fR or \s-1UNIQUE INDEX.\s0 -.PP -In \s-1DBD::DBM,\s0 you can take advantage of the speed of keyed lookups by using -DBI::SQL::Nano and a \s-1WHERE\s0 clause with a single equal comparison on the key -field. For example, the following \s-1SQL\s0 statements are optimized for keyed -lookup: -.PP -.Vb 4 -\& CREATE TABLE user ( user_name TEXT, phone TEXT); -\& INSERT INTO user VALUES (\*(AqFred Bloggs\*(Aq,\*(Aq233\-7777\*(Aq); -\& # ... many more inserts -\& SELECT phone FROM user WHERE user_name=\*(AqFred Bloggs\*(Aq; -.Ve -.PP -The \*(L"user_name\*(R" column is the key column since it is the first -column. The \s-1SELECT\s0 statement uses the key column in a single equal -comparison \- \*(L"user_name='Fred Bloggs'\*(R" \- so the search will find it -very quickly without having to loop through all the names which were -inserted into the table. -.PP -In contrast, these searches on the same table are not optimized: -.PP -.Vb 2 -\& 1. SELECT phone FROM user WHERE user_name < \*(AqFred\*(Aq; -\& 2. SELECT user_name FROM user WHERE phone = \*(Aq233\-7777\*(Aq; -.Ve -.PP -In #1, the operation uses a less-than (<) comparison rather than an equals -comparison, so it will not be optimized for key searching. In #2, the key -field \*(L"user_name\*(R" is not specified in the \s-1WHERE\s0 clause, and therefore the -search will need to loop through all rows to find the requested row(s). -.PP -\&\fBNote\fR that the underlying \s-1DBM\s0 storage needs to loop over all \fIkey/value\fR -pairs when the optimized fetch is used. SQL::Statement has a massively -improved where clause evaluation which costs around 15% of the evaluation -in DBI::SQL::Nano \- combined with the loop in the \s-1DBM\s0 storage the speed -improvement isn't so impressive. -.PP -Even if lookups are faster by around 50%, DBI::SQL::Nano and -SQL::Statement can benefit from the key field optimizations on -updating and deleting rows \- and here the improved where clause -evaluation of SQL::Statement might beat DBI::SQL::Nano every time the -where clause contains not only the key field (or more than one). -.SS "Supported \s-1SQL\s0 syntax" -.IX Subsection "Supported SQL syntax" -\&\s-1DBD::DBM\s0 uses a subset of \s-1SQL. \s0 The robustness of that subset depends on -what other modules you have installed. Both options support basic \s-1SQL\s0 -operations including \s-1CREATE TABLE, DROP TABLE, INSERT, DELETE, UPDATE,\s0 and -\&\s-1SELECT.\s0 -.PP -\&\fBOption #1:\fR By default, this module inherits its \s-1SQL\s0 support from -DBI::SQL::Nano that comes with \s-1DBI. \s0 Nano is, as its name implies, a *very* -small \s-1SQL\s0 engine. Although limited in scope, it is faster than option #2 -for some operations (especially single \fIprimary key\fR lookups). See -DBI::SQL::Nano for a description of the \s-1SQL\s0 it supports and comparisons -of it with option #2. -.PP -\&\fBOption #2:\fR If you install the pure Perl \s-1CPAN\s0 module SQL::Statement, -\&\s-1DBD::DBM\s0 will use it instead of Nano. This adds support for table aliases, -functions, joins, and much more. If you're going to use \s-1DBD::DBM\s0 -for anything other than very simple tables and queries, you should install -SQL::Statement. You don't have to change \s-1DBD::DBM\s0 or your scripts in any -way, simply installing SQL::Statement will give you the more robust \s-1SQL\s0 -capabilities without breaking scripts written for DBI::SQL::Nano. See -SQL::Statement for a description of the \s-1SQL\s0 it supports. -.PP -To find out which \s-1SQL\s0 module is working in a given script, you can use the -\&\fIdbm_versions()\fR method or, if you don't need the full output and version -numbers, just do this: -.PP -.Vb 1 -\& print $dbh\->{sql_handler}, "\en"; -.Ve -.PP -That will print out either \*(L"SQL::Statement\*(R" or \*(L"DBI::SQL::Nano\*(R". -.PP -Baring the section about optimized access to the \s-1DBM\s0 storage in mind, -comparing the benefits of both engines: -.PP -.Vb 6 -\& # DBI::SQL::Nano is faster -\& $sth = $dbh\->prepare( "update foo set value=\*(Aqnew\*(Aq where key=15" ); -\& $sth\->execute(); -\& $sth = $dbh\->prepare( "delete from foo where key=27" ); -\& $sth\->execute(); -\& $sth = $dbh\->prepare( "select * from foo where key=\*(Aqabc\*(Aq" ); -\& -\& # SQL::Statement might faster (depending on DB size) -\& $sth = $dbh\->prepare( "update foo set value=\*(Aqnew\*(Aq where key=?" ); -\& $sth\->execute(15); -\& $sth = $dbh\->prepare( "update foo set value=? where key=15" ); -\& $sth\->execute(\*(Aqnew\*(Aq); -\& $sth = $dbh\->prepare( "delete from foo where key=?" ); -\& $sth\->execute(27); -\& -\& # SQL::Statement is faster -\& $sth = $dbh\->prepare( "update foo set value=\*(Aqnew\*(Aq where value=\*(Aqold\*(Aq" ); -\& $sth\->execute(); -\& # must be expressed using "where key = 15 or key = 27 or key = 42 or key = \*(Aqabc\*(Aq" -\& # in DBI::SQL::Nano -\& $sth = $dbh\->prepare( "delete from foo where key in (15,27,42,\*(Aqabc\*(Aq)" ); -\& $sth\->execute(); -\& # must be expressed using "where key > 10 and key < 90" in DBI::SQL::Nano -\& $sth = $dbh\->prepare( "select * from foo where key between (10,90)" ); -\& $sth\->execute(); -\& -\& # only SQL::Statement can handle -\& $sth\->prepare( "select * from foo,bar where foo.name = bar.name" ); -\& $sth\->execute(); -\& $sth\->prepare( "insert into foo values ( 1, \*(Aqfoo\*(Aq ), ( 2, \*(Aqbar\*(Aq )" ); -\& $sth\->execute(); -.Ve -.SS "Specifying Column Names" -.IX Subsection "Specifying Column Names" -\&\s-1DBM\s0 files don't have a standard way to store column names. \s-1DBD::DBM\s0 gets -around this issue with a \s-1DBD::DBM\s0 specific way of storing the column names. -\&\fBIf you are working only with \s-1DBD::DBM\s0 and not using files created by or -accessed with other \s-1DBM\s0 programs, you can ignore this section.\fR -.PP -\&\s-1DBD::DBM\s0 stores column names as a row in the file with the key \fI_metadata -\&\e0\fR. So this code -.PP -.Vb 3 -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); -\& $dbh\->do("CREATE TABLE baz (foo CHAR(10), bar INTEGER)"); -\& $dbh\->do("INSERT INTO baz (foo,bar) VALUES (\*(Aqzippy\*(Aq,1)"); -.Ve -.PP -Will create a file that has a structure something like this: -.PP -.Vb 2 -\& _metadata \e0 | foo,bar -\& zippy | 1 -.Ve -.PP -The next time you access this table with \s-1DBD::DBM,\s0 it will treat the -\&\fI_metadata \e0\fR row as a header rather than as data and will pull the column -names from there. However, if you access the file with something other -than \s-1DBD::DBM,\s0 the row will be treated as a regular data row. -.PP -If you do not want the column names stored as a data row in the table you -can set the \fIdbm_store_metadata\fR attribute to 0. -.PP -.Vb 1 -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { dbm_store_metadata => 0 }); -\& -\& # or -\& $dbh\->{dbm_store_metadata} = 0; -\& -\& # or for per\-table setting -\& $dbh\->{f_meta}\->{qux}\->{dbm_store_metadata} = 0; -.Ve -.PP -By default, \s-1DBD::DBM\s0 assumes that you have two columns named \*(L"k\*(R" and \*(L"v\*(R" -(short for \*(L"key\*(R" and \*(L"value\*(R"). So if you have \fIdbm_store_metadata\fR set to -1 and you want to use alternate column names, you need to specify the -column names like this: -.PP -.Vb 4 -\& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { -\& dbm_store_metadata => 0, -\& dbm_cols => [ qw(foo bar) ], -\& }); -\& -\& # or -\& $dbh\->{dbm_store_metadata} = 0; -\& $dbh\->{dbm_cols} = \*(Aqfoo,bar\*(Aq; -\& -\& # or to set the column names on per\-table basis, do this: -\& # sets the column names only for table "qux" -\& $dbh\->{f_meta}\->{qux}\->{dbm_store_metadata} = 0; -\& $dbh\->{f_meta}\->{qux}\->{col_names} = [qw(foo bar)]; -.Ve -.PP -If you have a file that was created by another \s-1DBM\s0 program or created with -\&\fIdbm_store_metadata\fR set to zero and you want to convert it to using -\&\s-1DBD::DBM\s0's column name storage, just use one of the methods above to name -the columns but *without* specifying \fIdbm_store_metadata\fR as zero. You -only have to do that once \- thereafter you can get by without setting -either \fIdbm_store_metadata\fR or setting \fIdbm_cols\fR because the names will -be stored in the file. -.SH "DBI database handle attributes" -.IX Header "DBI database handle attributes" -.SS "Metadata" -.IX Subsection "Metadata" -\fIStatement handle ($sth) attributes and methods\fR -.IX Subsection "Statement handle ($sth) attributes and methods" -.PP -Most statement handle attributes such as \s-1NAME, NUM_OF_FIELDS,\s0 etc. are -available only after an execute. The same is true of \f(CW$sth\fR\->rows which is -available after the execute but does \fInot\fR require a fetch. -.PP -\fIDriver handle ($dbh) attributes\fR -.IX Subsection "Driver handle ($dbh) attributes" -.PP -It is not supported anymore to use dbm-attributes without the dbm_\-prefix. -Currently, if an \s-1DBD::DBM\s0 private attribute is accessed without an -underscore in it's name, dbm_ is prepended to that attribute and it's -processed further. If the resulting attribute name is invalid, an error is -thrown. -.PP -dbm_cols -.IX Subsection "dbm_cols" -.PP -Contains a comma separated list of column names or an array reference to -the column names. -.PP -dbm_type -.IX Subsection "dbm_type" -.PP -Contains the \s-1DBM\s0 storage type. Currently known supported type are -\&\f(CW\*(C`ODBM_File\*(C'\fR, \f(CW\*(C`NDBM_File\*(C'\fR, \f(CW\*(C`SDBM_File\*(C'\fR, \f(CW\*(C`GDBM_File\*(C'\fR, -\&\f(CW\*(C`DB_File\*(C'\fR and \f(CW\*(C`BerkeleyDB\*(C'\fR. It is not recommended to use one -of the first three types \- even if \f(CW\*(C`SDBM_File\*(C'\fR is the most commonly -available \fIdbm_type\fR. -.PP -dbm_mldbm -.IX Subsection "dbm_mldbm" -.PP -Contains the serializer for \s-1DBM\s0 storage (value column). Requires the -\&\s-1CPAN\s0 module \s-1MLDBM\s0 installed. Currently known supported serializers -are: -.IP "Data::Dumper" 8 -.IX Item "Data::Dumper" -Default serializer. Deployed with Perl core. -.IP "Storable" 8 -.IX Item "Storable" -Faster serializer. Deployed with Perl core. -.IP "FreezeThaw" 8 -.IX Item "FreezeThaw" -Pure Perl serializer, requires FreezeThaw to be installed. -.IP "\s-1YAML\s0" 8 -.IX Item "YAML" -Portable serializer (between languages but not architectures). -Requires \s-1YAML::MLDBM\s0 installation. -.IP "\s-1JSON\s0" 8 -.IX Item "JSON" -Portable, fast serializer (between languages but not architectures). -Requires MLDBM::Serializer::JSON installation. -.PP -dbm_store_metadata -.IX Subsection "dbm_store_metadata" -.PP -Boolean value which determines if the metadata in \s-1DBM\s0 is stored or not. -.PP -dbm_berkeley_flags -.IX Subsection "dbm_berkeley_flags" -.PP -Hash reference with additional flags for BerkeleyDB::Hash instantiation. -.PP -dbm_version -.IX Subsection "dbm_version" -.PP -Readonly attribute containing the version of \s-1DBD::DBM.\s0 -.PP -f_meta -.IX Subsection "f_meta" -.PP -In addition to the attributes DBD::File recognizes, \s-1DBD::DBM\s0 knows -about the (public) attributes \f(CW\*(C`col_names\*(C'\fR (\fBNote\fR not \fIdbm_cols\fR -here!), \f(CW\*(C`dbm_type\*(C'\fR, \f(CW\*(C`dbm_mldbm\*(C'\fR, \f(CW\*(C`dbm_store_metadata\*(C'\fR and -\&\f(CW\*(C`dbm_berkeley_flags\*(C'\fR. As in DBD::File, there are undocumented, -internal attributes in \s-1DBD::DBM. \s0 Be very careful when modifying -attributes you do not know; the consequence might a destroyed or -corrupted table. -.PP -dbm_tables -.IX Subsection "dbm_tables" -.PP -This attribute provides restricted access to the table meta data. See -f_meta and \*(L"f_meta\*(R" in DBD::File for attribute details. -.PP -dbm_tables is a tied hash providing the internal table names as keys -(accessing unknown tables might create an entry) and their meta -data as another tied hash. The table meta storage is obtained via -the \f(CW\*(C`get_table_meta\*(C'\fR method from the table implementation (see -DBD::File::Developers). Attribute setting and getting within the -table meta data is handled via the methods \f(CW\*(C`set_table_meta_attr\*(C'\fR and -\&\f(CW\*(C`get_table_meta_attr\*(C'\fR. -.PP -\fIFollowing attributes are no longer handled by \s-1DBD::DBM:\s0\fR -.IX Subsection "Following attributes are no longer handled by DBD::DBM:" -.PP -dbm_ext -.IX Subsection "dbm_ext" -.PP -This attribute is silently mapped to DBD::File's attribute \fIf_ext\fR. -Later versions of \s-1DBI\s0 might show a depreciated warning when this attribute -is used and eventually it will be removed. -.PP -dbm_lockfile -.IX Subsection "dbm_lockfile" -.PP -This attribute is silently mapped to DBD::File's attribute \fIf_lockfile\fR. -Later versions of \s-1DBI\s0 might show a depreciated warning when this attribute -is used and eventually it will be removed. -.SH "DBI database handle methods" -.IX Header "DBI database handle methods" -.ie n .SS "The $dbh\->\fIdbm_versions()\fP method" -.el .SS "The \f(CW$dbh\fP\->\fIdbm_versions()\fP method" -.IX Subsection "The $dbh->dbm_versions() method" -The private method \fIdbm_versions()\fR returns a summary of what other modules -are being used at any given time. \s-1DBD::DBM\s0 can work with or without many -other modules \- it can use either SQL::Statement or DBI::SQL::Nano as its -\&\s-1SQL\s0 engine, it can be run with \s-1DBI\s0 or DBI::PurePerl, it can use many kinds -of \s-1DBM\s0 modules, and many kinds of serializers when run with \s-1MLDBM. \s0 The -\&\fIdbm_versions()\fR method reports all of that and more. -.PP -.Vb 2 -\& print $dbh\->dbm_versions; # displays global settings -\& print $dbh\->dbm_versions($table_name); # displays per table settings -.Ve -.PP -An important thing to note about this method is that when it called -with no arguments, it displays the *global* settings. If you override -these by setting per-table attributes, these will \fInot\fR be shown -unless you specify a table name as an argument to the method call. -.SS "Storing Objects" -.IX Subsection "Storing Objects" -If you are using \s-1MLDBM,\s0 you can use \s-1DBD::DBM\s0 to take advantage of its -serializing abilities to serialize any Perl object that \s-1MLDBM\s0 can handle. -To store objects in columns, you should (but don't absolutely need to) -declare it as a column of type \s-1BLOB \s0(the type is *currently* ignored by -the \s-1SQL\s0 engine, but it's good form). -.SH "EXTENSIBILITY" -.IX Header "EXTENSIBILITY" -.ie n .IP """SQL::Statement""" 8 -.el .IP "\f(CWSQL::Statement\fR" 8 -.IX Item "SQL::Statement" -Improved \s-1SQL\s0 engine compared to the built-in DBI::SQL::Nano \- see -\&\*(L"Supported \s-1SQL\s0 syntax\*(R". -.ie n .IP """DB_File""" 8 -.el .IP "\f(CWDB_File\fR" 8 -.IX Item "DB_File" -Berkeley \s-1DB\s0 version 1. This database library is available on many -systems without additional installation and most systems are -supported. -.ie n .IP """GDBM_File""" 8 -.el .IP "\f(CWGDBM_File\fR" 8 -.IX Item "GDBM_File" -Simple dbm type (comparable to \f(CW\*(C`DB_File\*(C'\fR) under the \s-1GNU\s0 license. -Typically not available (or requires extra installation) on non-GNU -operating systems. -.ie n .IP """BerkeleyDB""" 8 -.el .IP "\f(CWBerkeleyDB\fR" 8 -.IX Item "BerkeleyDB" -Berkeley \s-1DB\s0 version up to v4 (and maybe higher) \- requires additional -installation but is easier than GDBM_File on non-GNU systems. -.Sp -db4 comes with a many tools which allow repairing and migrating -databases. This is the \fBrecommended\fR dbm type for production use. -.ie n .IP """MLDBM""" 8 -.el .IP "\f(CWMLDBM\fR" 8 -.IX Item "MLDBM" -Serializer wrapper to support more than one column for the files. -Comes with serializers using \f(CW\*(C`Data::Dumper\*(C'\fR, \f(CW\*(C`FreezeThaw\*(C'\fR and -\&\f(CW\*(C`Storable\*(C'\fR. -.ie n .IP """YAML::MLDBM""" 8 -.el .IP "\f(CWYAML::MLDBM\fR" 8 -.IX Item "YAML::MLDBM" -Additional serializer for \s-1MLDBM. YAML\s0 is very portable between languages. -.ie n .IP """MLDBM::Serializer::JSON""" 8 -.el .IP "\f(CWMLDBM::Serializer::JSON\fR" 8 -.IX Item "MLDBM::Serializer::JSON" -Additional serializer for \s-1MLDBM. JSON\s0 is very portable between languages, -probably more than \s-1YAML.\s0 -.SH "GOTCHAS AND WARNINGS" -.IX Header "GOTCHAS AND WARNINGS" -Using the \s-1SQL DROP\s0 command will remove any file that has the name specified -in the command with either '.pag' and '.dir', '.db' or your {f_ext} appended -to it. So this be dangerous if you aren't sure what file it refers to: -.PP -.Vb 1 -\& $dbh\->do(qq{DROP TABLE "/path/to/any/file"}); -.Ve -.PP -Each \s-1DBM\s0 type has limitations. SDBM_File, for example, can only store -values of less than 1,000 characters. *You* as the script author must -ensure that you don't exceed those bounds. If you try to insert a value -that is larger than \s-1DBM\s0 can store, the results will be unpredictable. -See the documentation for whatever \s-1DBM\s0 you are using for details. -.PP -Different \s-1DBM\s0 implementations return records in different orders. -That means that you \fIshould not\fR rely on the order of records unless -you use an \s-1ORDER BY\s0 statement. -.PP -\&\s-1DBM\s0 data files are platform-specific. To move them from one platform to -another, you'll need to do something along the lines of dumping your data -to \s-1CSV\s0 on platform #1 and then dumping from \s-1CSV\s0 to \s-1DBM\s0 on platform #2. -DBD::AnyData and \s-1DBD::CSV\s0 can help with that. There may also be \s-1DBM\s0 -conversion tools for your platforms which would probably be quicker. -.PP -When using \s-1MLDBM,\s0 there is a very powerful serializer \- it will allow -you to store Perl code or objects in database columns. When these get -de-serialized, they may be eval'ed \- in other words \s-1MLDBM \s0(or actually -Data::Dumper when used by \s-1MLDBM\s0) may take the values and try to -execute them in Perl. Obviously, this can present dangers, so if you -do not know what is in a file, be careful before you access it with -\&\s-1MLDBM\s0 turned on! -.PP -See the entire section on \*(L"Table locking and \fIflock()\fR\*(R" for gotchas and -warnings about the use of \fIflock()\fR. -.SH "BUGS AND LIMITATIONS" -.IX Header "BUGS AND LIMITATIONS" -This module uses hash interfaces of two column file databases. While -none of supported \s-1SQL\s0 engines have support for indices, the following -statements really do the same (even if they mean something completely -different) for each dbm type which lacks \f(CW\*(C`EXISTS\*(C'\fR support: -.PP -.Vb 1 -\& $sth\->do( "insert into foo values (1, \*(Aqhello\*(Aq)" ); -\& -\& # this statement does ... -\& $sth\->do( "update foo set v=\*(Aqworld\*(Aq where k=1" ); -\& # ... the same as this statement -\& $sth\->do( "insert into foo values (1, \*(Aqworld\*(Aq)" ); -.Ve -.PP -This is considered to be a bug and might change in a future release. -.PP -Known affected dbm types are \f(CW\*(C`ODBM_File\*(C'\fR and \f(CW\*(C`NDBM_File\*(C'\fR. We highly -recommended you use a more modern dbm type such as \f(CW\*(C`DB_File\*(C'\fR. -.SH "GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS" -.IX Header "GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS" -If you need help installing or using \s-1DBD::DBM,\s0 please write to the \s-1DBI\s0 -users mailing list at dbi\-users@perl.org or to the -comp.lang.perl.modules newsgroup on usenet. I cannot always answer -every question quickly but there are many on the mailing list or in -the newsgroup who can. -.PP -\&\s-1DBD\s0 developers for \s-1DBD\s0's which rely on DBD::File or \s-1DBD::DBM\s0 or use -one of them as an example are suggested to join the \s-1DBI\s0 developers -mailing list at dbi\-dev@perl.org and strongly encouraged to join our -\&\s-1IRC\s0 channel at . -.PP -If you have suggestions, ideas for improvements, or bugs to report, please -report a bug as described in \s-1DBI.\s0 Do not mail any of the authors directly, -you might not get an answer. -.PP -When reporting bugs, please send the output of \f(CW$dbh\fR\->dbm_versions($table) -for a table that exhibits the bug and as small a sample as you can make of -the code that produces the bug. And of course, patches are welcome, too -:\-). -.PP -If you need enhancements quickly, you can get commercial support as -described at or you can contact Jens Rehsack -at rehsack@cpan.org for commercial support in Germany. -.PP -Please don't bother Jochen Wiedmann or Jeff Zucker for support \- they -handed over further maintenance to H.Merijn Brand and Jens Rehsack. -.SH "ACKNOWLEDGEMENTS" -.IX Header "ACKNOWLEDGEMENTS" -Many, many thanks to Tim Bunce for prodding me to write this, and for -copious, wise, and patient suggestions all along the way. (Jeff Zucker) -.PP -I send my thanks and acknowledgements to H.Merijn Brand for his -initial refactoring of DBD::File and his strong and ongoing support of -SQL::Statement. Without him, the current progress would never have -been made. And I have to name Martin J. Evans for each laugh (and -correction) of all those funny word creations I (as non-native -speaker) made to the documentation. And \- of course \- I have to thank -all those unnamed contributors and testers from the Perl -community. (Jens Rehsack) -.SH "AUTHOR AND COPYRIGHT" -.IX Header "AUTHOR AND COPYRIGHT" -This module is written by Jeff Zucker < jzucker \s-1AT\s0 cpan.org >, who also -maintained it till 2007. After that, in 2010, Jens Rehsack & H.Merijn Brand -took over maintenance. -.PP -.Vb 2 -\& Copyright (c) 2004 by Jeff Zucker, all rights reserved. -\& Copyright (c) 2010\-2013 by Jens Rehsack & H.Merijn Brand, all rights reserved. -.Ve -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as -specified in the Perl \s-1README\s0 file. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -\&\s-1DBI\s0, -SQL::Statement, DBI::SQL::Nano, -AnyDBM_File, DB_File, BerkeleyDB, -\&\s-1MLDBM\s0, \s-1YAML::MLDBM\s0, MLDBM::Serializer::JSON diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::File.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::File.3pm deleted file mode 100644 index 924932a..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::File.3pm +++ /dev/null @@ -1,605 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::File 3pm" -.TH DBD::File 3pm "2016-11-09" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::File \- Base class for writing file based DBI drivers -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -This module is a base class for writing other \s-1DBD\s0s. -It is not intended to function as a \s-1DBD\s0 itself (though it is possible). -If you want to access flat files, use DBD::AnyData, or -\&\s-1DBD::CSV\s0 (both of which are subclasses of DBD::File). -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -The DBD::File module is not a true \s-1DBI\s0 driver, but an abstract -base class for deriving concrete \s-1DBI\s0 drivers from it. The implication -is, that these drivers work with plain files, for example \s-1CSV\s0 files or -\&\s-1INI\s0 files. The module is based on the SQL::Statement -module, a simple \s-1SQL\s0 engine. -.PP -See \s-1DBI\s0 for details on \s-1DBI, \s0SQL::Statement for -details on SQL::Statement and \s-1DBD::CSV\s0, \s-1DBD::DBM\s0 -or DBD::AnyData for example drivers. -.SS "Metadata" -.IX Subsection "Metadata" -The following attributes are handled by \s-1DBI\s0 itself and not by DBD::File, -thus they all work as expected: -.PP -.Vb 10 -\& Active -\& ActiveKids -\& CachedKids -\& CompatMode (Not used) -\& InactiveDestroy -\& AutoInactiveDestroy -\& Kids -\& PrintError -\& RaiseError -\& Warn (Not used) -.Ve -.PP -\fIThe following \s-1DBI\s0 attributes are handled by DBD::File:\fR -.IX Subsection "The following DBI attributes are handled by DBD::File:" -.PP -AutoCommit -.IX Subsection "AutoCommit" -.PP -Always on. -.PP -ChopBlanks -.IX Subsection "ChopBlanks" -.PP -Works. -.PP -\s-1NUM_OF_FIELDS\s0 -.IX Subsection "NUM_OF_FIELDS" -.PP -Valid after \f(CW\*(C`$sth\->execute\*(C'\fR. -.PP -\s-1NUM_OF_PARAMS\s0 -.IX Subsection "NUM_OF_PARAMS" -.PP -Valid after \f(CW\*(C`$sth\->prepare\*(C'\fR. -.PP -\s-1NAME\s0 -.IX Subsection "NAME" -.PP -Valid after \f(CW\*(C`$sth\->execute\*(C'\fR; undef for Non-Select statements. -.PP -\s-1NULLABLE\s0 -.IX Subsection "NULLABLE" -.PP -Not really working, always returns an array ref of ones, except the -affected table has been created in this session. Valid after -\&\f(CW\*(C`$sth\->execute\*(C'\fR; undef for non-select statements. -.PP -\fIUnsupported \s-1DBI\s0 attributes and methods\fR -.IX Subsection "Unsupported DBI attributes and methods" -.PP -bind_param_inout -.IX Subsection "bind_param_inout" -.PP -CursorName -.IX Subsection "CursorName" -.PP -LongReadLen -.IX Subsection "LongReadLen" -.PP -LongTruncOk -.IX Subsection "LongTruncOk" -.PP -\fIDBD::File specific attributes\fR -.IX Subsection "DBD::File specific attributes" -.PP -In addition to the \s-1DBI\s0 attributes, you can use the following dbh -attributes: -.PP -f_dir -.IX Subsection "f_dir" -.PP -This attribute is used for setting the directory where the files are -opened and it defaults to the current directory (\fI.\fR). Usually you set -it on the dbh but it may be overridden per table (see f_meta). -.PP -When the value for \f(CW\*(C`f_dir\*(C'\fR is a relative path, it is converted into -the appropriate absolute path name (based on the current working -directory) when the dbh attribute is set. -.PP -.Vb 1 -\& f_dir => "/data/foo/csv", -.Ve -.PP -See \*(L"\s-1KNOWN BUGS AND LIMITATIONS\*(R"\s0. -.PP -f_dir_search -.IX Subsection "f_dir_search" -.PP -This optional attribute can be set to pass a list of folders to also -find existing tables. It will \fBnot\fR be used to create new files. -.PP -.Vb 1 -\& f_dir_search => [ "/data/bar/csv", "/dump/blargh/data" ], -.Ve -.PP -f_ext -.IX Subsection "f_ext" -.PP -This attribute is used for setting the file extension. The format is: -.PP -.Vb 1 -\& extension{/flag} -.Ve -.PP -where the /flag is optional and the extension is case-insensitive. -\&\f(CW\*(C`f_ext\*(C'\fR allows you to specify an extension which: -.PP -.Vb 1 -\& f_ext => ".csv/r", -.Ve -.IP "\(bu" 4 -makes DBD::File prefer \fItable.extension\fR over \fItable\fR. -.IP "\(bu" 4 -makes the table name the filename minus the extension. -.PP -.Vb 1 -\& DBI:CSV:f_dir=data;f_ext=.csv -.Ve -.PP -In the above example and when \f(CW\*(C`f_dir\*(C'\fR contains both \fItable.csv\fR and -\&\fItable\fR, DBD::File will open \fItable.csv\fR and the table will be -named \*(L"table\*(R". If \fItable.csv\fR does not exist but \fItable\fR does -that file is opened and the table is also called \*(L"table\*(R". -.PP -If \f(CW\*(C`f_ext\*(C'\fR is not specified and \fItable.csv\fR exists it will be opened -and the table will be called \*(L"table.csv\*(R" which is probably not what -you want. -.PP -\&\s-1NOTE:\s0 even though extensions are case-insensitive, table names are -not. -.PP -.Vb 1 -\& DBI:CSV:f_dir=data;f_ext=.csv/r -.Ve -.PP -The \f(CW\*(C`r\*(C'\fR flag means the file extension is required and any filename -that does not match the extension is ignored. -.PP -Usually you set it on the dbh but it may be overridden per table -(see f_meta). -.PP -f_schema -.IX Subsection "f_schema" -.PP -This will set the schema name and defaults to the owner of the -directory in which the table file resides. You can set \f(CW\*(C`f_schema\*(C'\fR to -\&\f(CW\*(C`undef\*(C'\fR. -.PP -.Vb 5 -\& my $dbh = DBI\->connect ("dbi:CSV:", "", "", { -\& f_schema => undef, -\& f_dir => "data", -\& f_ext => ".csv/r", -\& }) or die $DBI::errstr; -.Ve -.PP -By setting the schema you affect the results from the tables call: -.PP -.Vb 1 -\& my @tables = $dbh\->tables (); -\& -\& # no f_schema -\& "merijn".foo -\& "merijn".bar -\& -\& # f_schema => "dbi" -\& "dbi".foo -\& "dbi".bar -\& -\& # f_schema => undef -\& foo -\& bar -.Ve -.PP -Defining \f(CW\*(C`f_schema\*(C'\fR to the empty string is equal to setting it to \f(CW\*(C`undef\*(C'\fR -so the \s-1DSN\s0 can be \f(CW"dbi:CSV:f_schema=;f_dir=."\fR. -.PP -f_lock -.IX Subsection "f_lock" -.PP -The \f(CW\*(C`f_lock\*(C'\fR attribute is used to set the locking mode on the opened -table files. Note that not all platforms support locking. By default, -tables are opened with a shared lock for reading, and with an -exclusive lock for writing. The supported modes are: -.PP -.Vb 1 -\& 0: No locking at all. -\& -\& 1: Shared locks will be used. -\& -\& 2: Exclusive locks will be used. -.Ve -.PP -But see \s-1KNOWN BUGS\s0 below. -.PP -f_lockfile -.IX Subsection "f_lockfile" -.PP -If you wish to use a lockfile extension other than \f(CW\*(C`.lck\*(C'\fR, simply specify -the \f(CW\*(C`f_lockfile\*(C'\fR attribute: -.PP -.Vb 3 -\& $dbh = DBI\->connect ("dbi:DBM:f_lockfile=.foo"); -\& $dbh\->{f_lockfile} = ".foo"; -\& $dbh\->{dbm_tables}{qux}{f_lockfile} = ".foo"; -.Ve -.PP -If you wish to disable locking, set the \f(CW\*(C`f_lockfile\*(C'\fR to \f(CW0\fR. -.PP -.Vb 3 -\& $dbh = DBI\->connect ("dbi:DBM:f_lockfile=0"); -\& $dbh\->{f_lockfile} = 0; -\& $dbh\->{dbm_tables}{qux}{f_lockfile} = 0; -.Ve -.PP -f_encoding -.IX Subsection "f_encoding" -.PP -With this attribute, you can set the encoding in which the file is opened. -This is implemented using \f(CW\*(C`binmode $fh, ":encoding()"\*(C'\fR. -.PP -f_meta -.IX Subsection "f_meta" -.PP -Private data area aliasing \*(L"sql_meta\*(R" in DBI::DBD::SqlEngine which -contains information about the tables this module handles. Table meta -data might not be available until the table has been accessed for the -first time e.g., by issuing a select on it however it is possible to -pre-initialize attributes for each table you use. -.PP -DBD::File recognizes the (public) attributes \f(CW\*(C`f_ext\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, -\&\f(CW\*(C`f_file\*(C'\fR, \f(CW\*(C`f_encoding\*(C'\fR, \f(CW\*(C`f_lock\*(C'\fR, \f(CW\*(C`f_lockfile\*(C'\fR, \f(CW\*(C`f_schema\*(C'\fR, -in addition to the attributes \*(L"sql_meta\*(R" in DBI::DBD::SqlEngine already -supports. Be very careful when modifying attributes you do not know, -the consequence might be a destroyed or corrupted table. -.PP -\&\f(CW\*(C`f_file\*(C'\fR is an attribute applicable to table meta data only and you -will not find a corresponding attribute in the dbh. Whilst it may be -reasonable to have several tables with the same column names, it is -not for the same file name. If you need access to the same file using -different table names, use \f(CW\*(C`SQL::Statement\*(C'\fR as the \s-1SQL\s0 engine and the -\&\f(CW\*(C`AS\*(C'\fR keyword: -.PP -.Vb 1 -\& SELECT * FROM tbl AS t1, tbl AS t2 WHERE t1.id = t2.id -.Ve -.PP -\&\f(CW\*(C`f_file\*(C'\fR can be an absolute path name or a relative path name but if -it is relative, it is interpreted as being relative to the \f(CW\*(C`f_dir\*(C'\fR -attribute of the table meta data. When \f(CW\*(C`f_file\*(C'\fR is set DBD::File will -use \f(CW\*(C`f_file\*(C'\fR as specified and will not attempt to work out an -alternative for \f(CW\*(C`f_file\*(C'\fR using the \f(CW\*(C`table name\*(C'\fR and \f(CW\*(C`f_ext\*(C'\fR -attribute. -.PP -While \f(CW\*(C`f_meta\*(C'\fR is a private and readonly attribute (which means, you -cannot modify it's values), derived drivers might provide restricted -write access through another attribute. Well known accessors are -\&\f(CW\*(C`csv_tables\*(C'\fR for \s-1DBD::CSV\s0, \f(CW\*(C`ad_tables\*(C'\fR for DBD::AnyData and -\&\f(CW\*(C`dbm_tables\*(C'\fR for \s-1DBD::DBM\s0. -.PP -\fINew opportunities for attributes from DBI::DBD::SqlEngine\fR -.IX Subsection "New opportunities for attributes from DBI::DBD::SqlEngine" -.PP -sql_table_source -.IX Subsection "sql_table_source" -.PP -\&\f(CW\*(C`$dbh\->{sql_table_source}\*(C'\fR can be set to -\&\fIDBD::File::TableSource::FileSystem\fR (and is the default setting -of DBD::File). This provides usual behaviour of previous DBD::File -releases on -.PP -.Vb 2 -\& @ary = DBI\->data_sources ($driver); -\& @ary = DBI\->data_sources ($driver, \e%attr); -\& -\& @ary = $dbh\->data_sources (); -\& @ary = $dbh\->data_sources (\e%attr); -\& -\& @names = $dbh\->tables ($catalog, $schema, $table, $type); -\& -\& $sth = $dbh\->table_info ($catalog, $schema, $table, $type); -\& $sth = $dbh\->table_info ($catalog, $schema, $table, $type, \e%attr); -\& -\& $dbh\->func ("list_tables"); -.Ve -.PP -sql_data_source -.IX Subsection "sql_data_source" -.PP -\&\f(CW\*(C`$dbh\->{sql_data_source}\*(C'\fR can be set to either -\&\fIDBD::File::DataSource::File\fR, which is default and provides the -well known behavior of DBD::File releases prior to 0.41, or -\&\fIDBD::File::DataSource::Stream\fR, which reuses already opened -file-handle for operations. -.PP -\fIInternally private attributes to deal with \s-1SQL\s0 backends\fR -.IX Subsection "Internally private attributes to deal with SQL backends" -.PP -Do not modify any of these private attributes unless you understand -the implications of doing so. The behavior of DBD::File and derived -DBDs might be unpredictable when one or more of those attributes are -modified. -.PP -sql_nano_version -.IX Subsection "sql_nano_version" -.PP -Contains the version of loaded DBI::SQL::Nano. -.PP -sql_statement_version -.IX Subsection "sql_statement_version" -.PP -Contains the version of loaded SQL::Statement. -.PP -sql_handler -.IX Subsection "sql_handler" -.PP -Contains either the text 'SQL::Statement' or 'DBI::SQL::Nano'. -.PP -sql_ram_tables -.IX Subsection "sql_ram_tables" -.PP -Contains optionally temporary tables. -.PP -sql_flags -.IX Subsection "sql_flags" -.PP -Contains optional flags to instantiate the SQL::Parser parsing engine -when SQL::Statement is used as \s-1SQL\s0 engine. See SQL::Parser for valid -flags. -.SS "Driver private methods" -.IX Subsection "Driver private methods" -\fIDefault \s-1DBI\s0 methods\fR -.IX Subsection "Default DBI methods" -.PP -data_sources -.IX Subsection "data_sources" -.PP -The \f(CW\*(C`data_sources\*(C'\fR method returns a list of subdirectories of the current -directory in the form \*(L"dbi:CSV:f_dir=$dirname\*(R". -.PP -If you want to read the subdirectories of another directory, use -.PP -.Vb 2 -\& my ($drh) = DBI\->install_driver ("CSV"); -\& my (@list) = $drh\->data_sources (f_dir => "/usr/local/csv_data"); -.Ve -.PP -\fIAdditional methods\fR -.IX Subsection "Additional methods" -.PP -The following methods are only available via their documented name when -DBD::File is used directly. Because this is only reasonable for testing -purposes, the real names must be used instead. Those names can be computed -by replacing the \f(CW\*(C`f_\*(C'\fR in the method name with the driver prefix. -.PP -f_versions -.IX Subsection "f_versions" -.PP -Signature: -.PP -.Vb 6 -\& sub f_versions (;$) -\& { -\& my ($table_name) = @_; -\& $table_name ||= "."; -\& ... -\& } -.Ve -.PP -Returns the versions of the driver, including the \s-1DBI\s0 version, the Perl -version, DBI::PurePerl version (if DBI::PurePerl is active) and the version -of the \s-1SQL\s0 engine in use. -.PP -.Vb 9 -\& my $dbh = DBI\->connect ("dbi:File:"); -\& my $f_versions = $dbh\->func ("f_versions"); -\& print "$f_versions\en"; -\& _\|_END_\|_ -\& # DBD::File 0.41 using IO::File (1.16) -\& # DBI::DBD::SqlEngine 0.05 using SQL::Statement 1.406 -\& # DBI 1.623 -\& # OS darwin (12.2.1) -\& # Perl 5.017006 (darwin\-thread\-multi\-ld\-2level) -.Ve -.PP -Called in list context, f_versions will return an array containing each -line as single entry. -.PP -Some drivers might use the optional (table name) argument and modify -version information related to the table (e.g. \s-1DBD::DBM\s0 provides storage -backend information for the requested table, when it has a table name). -.SH "KNOWN BUGS AND LIMITATIONS" -.IX Header "KNOWN BUGS AND LIMITATIONS" -.IP "\(bu" 4 -This module uses flock () internally but flock is not available on all -platforms. On MacOS and Windows 95 there is no locking at all (perhaps -not so important on MacOS and Windows 95, as there is only a single -user). -.IP "\(bu" 4 -The module stores details about the handled tables in a private area -of the driver handle (\f(CW$drh\fR). This data area is not shared between -different driver instances, so several \f(CW\*(C`DBI\->connect ()\*(C'\fR calls will -cause different table instances and private data areas. -.Sp -This data area is filled for the first time when a table is accessed, -either via an \s-1SQL\s0 statement or via \f(CW\*(C`table_info\*(C'\fR and is not -destroyed until the table is dropped or the driver handle is released. -Manual destruction is possible via f_clear_meta. -.Sp -The following attributes are preserved in the data area and will -evaluated instead of driver globals: -.RS 4 -.IP "f_ext" 8 -.IX Item "f_ext" -.PD 0 -.IP "f_dir" 8 -.IX Item "f_dir" -.IP "f_dir_search" 8 -.IX Item "f_dir_search" -.IP "f_lock" 8 -.IX Item "f_lock" -.IP "f_lockfile" 8 -.IX Item "f_lockfile" -.IP "f_encoding" 8 -.IX Item "f_encoding" -.IP "f_schema" 8 -.IX Item "f_schema" -.IP "col_names" 8 -.IX Item "col_names" -.IP "sql_identifier_case" 8 -.IX Item "sql_identifier_case" -.RE -.RS 4 -.PD -.Sp -The following attributes are preserved in the data area only and -cannot be set globally. -.IP "f_file" 8 -.IX Item "f_file" -.RE -.RS 4 -.Sp -The following attributes are preserved in the data area only and are -computed when initializing the data area: -.IP "f_fqfn" 8 -.IX Item "f_fqfn" -.PD 0 -.IP "f_fqbn" 8 -.IX Item "f_fqbn" -.IP "f_fqln" 8 -.IX Item "f_fqln" -.IP "table_name" 8 -.IX Item "table_name" -.RE -.RS 4 -.PD -.Sp -For \s-1DBD::CSV\s0 tables this means, once opened \*(L"foo.csv\*(R" as table named \*(L"foo\*(R", -another table named \*(L"foo\*(R" accessing the file \*(L"foo.txt\*(R" cannot be opened. -Accessing \*(L"foo\*(R" will always access the file \*(L"foo.csv\*(R" in memorized -\&\f(CW\*(C`f_dir\*(C'\fR, locking \f(CW\*(C`f_lockfile\*(C'\fR via memorized \f(CW\*(C`f_lock\*(C'\fR. -.Sp -You can use f_clear_meta or the \f(CW\*(C`f_file\*(C'\fR attribute for a specific table -to work around this. -.RE -.IP "\(bu" 4 -When used with SQL::Statement and temporary tables e.g., -.Sp -.Vb 1 -\& CREATE TEMP TABLE ... -.Ve -.Sp -the table data processing bypasses DBD::File::Table. No file system -calls will be made and there are no clashes with existing (file based) -tables with the same name. Temporary tables are chosen over file -tables, but they will not covered by \f(CW\*(C`table_info\*(C'\fR. -.SH "AUTHOR" -.IX Header "AUTHOR" -This module is currently maintained by -.PP -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > -.PP -The original author is Jochen Wiedmann. -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -.Vb 3 -\& Copyright (C) 2009\-2013 by H.Merijn Brand & Jens Rehsack -\& Copyright (C) 2004\-2009 by Jeff Zucker -\& Copyright (C) 1998\-2004 by Jochen Wiedmann -.Ve -.PP -All rights reserved. -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as -specified in the Perl \s-1README\s0 file. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -\&\s-1DBI\s0, \s-1DBD::DBM\s0, \s-1DBD::CSV\s0, Text::CSV, -Text::CSV_XS, SQL::Statement, and -DBI::SQL::Nano diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::File::Developers.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::File::Developers.3pm deleted file mode 100644 index 9144c00..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::File::Developers.3pm +++ /dev/null @@ -1,720 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::File::Developers 3pm" -.TH DBD::File::Developers 3pm "2013-04-04" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::File::Developers \- Developers documentation for DBD::File -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& package DBD::myDriver; -\& -\& use base qw( DBD::File ); -\& -\& sub driver -\& { -\& ... -\& my $drh = $proto\->SUPER::driver ($attr); -\& ... -\& return $drh\->{class}; -\& } -\& -\& sub CLONE { ... } -\& -\& package DBD::myDriver::dr; -\& -\& @ISA = qw( DBD::File::dr ); -\& -\& sub data_sources { ... } -\& ... -\& -\& package DBD::myDriver::db; -\& -\& @ISA = qw( DBD::File::db ); -\& -\& sub init_valid_attributes { ... } -\& sub init_default_attributes { ... } -\& sub set_versions { ... } -\& sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } -\& sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } -\& sub get_myd_versions { ... } -\& -\& package DBD::myDriver::st; -\& -\& @ISA = qw( DBD::File::st ); -\& -\& sub FETCH { ... } -\& sub STORE { ... } -\& -\& package DBD::myDriver::Statement; -\& -\& @ISA = qw( DBD::File::Statement ); -\& -\& package DBD::myDriver::Table; -\& -\& @ISA = qw( DBD::File::Table ); -\& -\& my %reset_on_modify = ( -\& myd_abc => "myd_foo", -\& myd_mno => "myd_bar", -\& ); -\& _\|_PACKAGE_\|_\->register_reset_on_modify (\e%reset_on_modify); -\& my %compat_map = ( -\& abc => \*(Aqfoo_abc\*(Aq, -\& xyz => \*(Aqfoo_xyz\*(Aq, -\& ); -\& _\|_PACKAGE_\|_\->register_compat_map (\e%compat_map); -\& -\& sub bootstrap_table_meta { ... } -\& sub init_table_meta { ... } -\& sub table_meta_attr_changed { ... } -\& sub open_data { ... } -\& -\& sub fetch_row { ... } -\& sub push_row { ... } -\& sub push_names { ... } -\& -\& # optimize the SQL engine by add one or more of -\& sub update_current_row { ... } -\& # or -\& sub update_specific_row { ... } -\& # or -\& sub update_one_row { ... } -\& # or -\& sub insert_new_row { ... } -\& # or -\& sub delete_current_row { ... } -\& # or -\& sub delete_one_row { ... } -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This document describes how \s-1DBD\s0 developers can write DBD::File based \s-1DBI\s0 -drivers. It supplements \s-1DBI::DBD\s0 and DBI::DBD::SqlEngine::Developers, -which you should read first. -.SH "CLASSES" -.IX Header "CLASSES" -Each \s-1DBI\s0 driver must provide a package global \f(CW\*(C`driver\*(C'\fR method and three -\&\s-1DBI\s0 related classes: -.IP "DBD::File::dr" 4 -.IX Item "DBD::File::dr" -Driver package, contains the methods \s-1DBI\s0 calls indirectly via \s-1DBI\s0 -interface: -.Sp -.Vb 1 -\& DBI\->connect (\*(AqDBI:DBM:\*(Aq, undef, undef, {}) -\& -\& # invokes -\& package DBD::DBM::dr; -\& @DBD::DBM::dr::ISA = qw( DBD::File::dr ); -\& -\& sub connect ($$;$$$) -\& { -\& ... -\& } -.Ve -.Sp -Similar for \f(CW\*(C`data_sources\*(C'\fR and \f(CW\*(C`disconnect_all\*(C'\fR. -.Sp -Pure Perl \s-1DBI\s0 drivers derived from DBD::File do not usually need to -override any of the methods provided through the DBD::XXX::dr package -however if you need additional initialization in the connect method -you may need to. -.IP "DBD::File::db" 4 -.IX Item "DBD::File::db" -Contains the methods which are called through \s-1DBI\s0 database handles -(\f(CW$dbh\fR). e.g., -.Sp -.Vb 3 -\& $sth = $dbh\->prepare ("select * from foo"); -\& # returns the f_encoding setting for table foo -\& $dbh\->csv_get_meta ("foo", "f_encoding"); -.Ve -.Sp -DBD::File provides the typical methods required here. Developers who -write \s-1DBI\s0 drivers based on DBD::File need to override the methods \f(CW\*(C`set_versions\*(C'\fR and \f(CW\*(C`init_valid_attributes\*(C'\fR. -.IP "DBD::File::st" 4 -.IX Item "DBD::File::st" -Contains the methods to deal with prepared statement handles. e.g., -.Sp -.Vb 1 -\& $sth\->execute () or die $sth\->errstr; -.Ve -.SS "DBD::File" -.IX Subsection "DBD::File" -This is the main package containing the routines to initialize -DBD::File based \s-1DBI\s0 drivers. Primarily the \f(CW\*(C`DBD::File::driver\*(C'\fR -method is invoked, either directly from \s-1DBI\s0 when the driver is -initialized or from the derived class. -.PP -.Vb 1 -\& package DBD::DBM; -\& -\& use base qw( DBD::File ); -\& -\& sub driver -\& { -\& my ($class, $attr) = @_; -\& ... -\& my $drh = $class\->SUPER::driver ($attr); -\& ... -\& return $drh; -\& } -.Ve -.PP -It is not necessary to implement your own driver method as long as -additional initialization (e.g. installing more private driver -methods) is not required. You do not need to call \f(CW\*(C`setup_driver\*(C'\fR -as DBD::File takes care of it. -.SS "DBD::File::dr" -.IX Subsection "DBD::File::dr" -The driver package contains the methods \s-1DBI\s0 calls indirectly via the \s-1DBI\s0 -interface (see \*(L"\s-1DBI\s0 Class Methods\*(R" in \s-1DBI\s0). -.PP -DBD::File based \s-1DBI\s0 drivers usually do not need to implement anything here, -it is enough to do the basic initialization: -.PP -.Vb 1 -\& package DBD:XXX::dr; -\& -\& @DBD::XXX::dr::ISA = qw (DBD::File::dr); -\& $DBD::XXX::dr::imp_data_size = 0; -\& $DBD::XXX::dr::data_sources_attr = undef; -\& $DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann"; -.Ve -.SS "DBD::File::db" -.IX Subsection "DBD::File::db" -This package defines the database methods, which are called via the \s-1DBI\s0 -database handle \f(CW$dbh\fR. -.PP -Methods provided by DBD::File: -.IP "ping" 4 -.IX Item "ping" -Simply returns the content of the \f(CW\*(C`Active\*(C'\fR attribute. Override -when your driver needs more complicated actions here. -.IP "prepare" 4 -.IX Item "prepare" -Prepares a new \s-1SQL\s0 statement to execute. Returns a statement handle, -\&\f(CW$sth\fR \- instance of the DBD:XXX::st. It is neither required nor -recommended to override this method. -.IP "\s-1FETCH\s0" 4 -.IX Item "FETCH" -Fetches an attribute of a \s-1DBI\s0 database object. Private handle attributes -must have a prefix (this is mandatory). If a requested attribute is -detected as a private attribute without a valid prefix, the driver prefix -(written as \f(CW$drv_prefix\fR) is added. -.Sp -The driver prefix is extracted from the attribute name and verified against -\&\f(CW\*(C`$dbh\->{$drv_prefix . "valid_attrs"}\*(C'\fR (when it exists). If the -requested attribute value is not listed as a valid attribute, this method -croaks. If the attribute is valid and readonly (listed in \f(CW\*(C`$dbh\->{ -$drv_prefix . "readonly_attrs" }\*(C'\fR when it exists), a real copy of the -attribute value is returned. So it's not possible to modify -\&\f(CW\*(C`f_valid_attrs\*(C'\fR from outside of DBD::File::db or a derived class. -.IP "\s-1STORE\s0" 4 -.IX Item "STORE" -Stores a database private attribute. Private handle attributes must have a -prefix (this is mandatory). If a requested attribute is detected as a private -attribute without a valid prefix, the driver prefix (written as -\&\f(CW$drv_prefix\fR) is added. If the database handle has an attribute -\&\f(CW\*(C`${drv_prefix}_valid_attrs\*(C'\fR \- for attribute names which are not listed in -that hash, this method croaks. If the database handle has an attribute -\&\f(CW\*(C`${drv_prefix}_readonly_attrs\*(C'\fR, only attributes which are not listed there -can be stored (once they are initialized). Trying to overwrite such an -immutable attribute forces this method to croak. -.Sp -An example of a valid attributes list can be found in -\&\f(CW\*(C`DBD::File::db::init_valid_attributes\*(C'\fR. -.IP "set_versions" 4 -.IX Item "set_versions" -This method sets the attribute \f(CW\*(C`f_version\*(C'\fR with the version of DBD::File. -.Sp -This method is called at the begin of the \f(CW\*(C`connect ()\*(C'\fR phase. -.Sp -When overriding this method, do not forget to invoke the superior one. -.IP "init_valid_attributes" 4 -.IX Item "init_valid_attributes" -This method is called after the database handle is instantiated as the -first attribute initialization. -.Sp -\&\f(CW\*(C`DBD::File::db::init_valid_attributes\*(C'\fR initializes the attributes -\&\f(CW\*(C`f_valid_attrs\*(C'\fR and \f(CW\*(C`f_readonly_attrs\*(C'\fR. -.Sp -When overriding this method, do not forget to invoke the superior one, -preferably before doing anything else. Compatibility table attribute -access must be initialized here to allow DBD::File to instantiate the -map tie: -.Sp -.Vb 6 -\& # for DBD::CSV -\& $dbh\->{csv_meta} = "csv_tables"; -\& # for DBD::DBM -\& $dbh\->{dbm_meta} = "dbm_tables"; -\& # for DBD::AnyData -\& $dbh\->{ad_meta} = "ad_tables"; -.Ve -.IP "init_default_attributes" 4 -.IX Item "init_default_attributes" -This method is called after the database handle is instantiated to -initialize the default attributes. -.Sp -\&\f(CW\*(C`DBD::File::db::init_default_attributes\*(C'\fR initializes the attributes -\&\f(CW\*(C`f_dir\*(C'\fR, \f(CW\*(C`f_meta\*(C'\fR, \f(CW\*(C`f_meta_map\*(C'\fR, \f(CW\*(C`f_version\*(C'\fR. -.Sp -When the derived implementor class provides the attribute to validate -attributes (e.g. \f(CW\*(C`$dbh\->{dbm_valid_attrs} = {...};\*(C'\fR) or the attribute -containing the immutable attributes (e.g. -\&\f(CW\*(C`$dbh\->{dbm_readonly_attrs} = {...};\*(C'\fR), the attributes -\&\f(CW\*(C`drv_valid_attrs\*(C'\fR, \f(CW\*(C`drv_readonly_attrs\*(C'\fR, \f(CW\*(C`drv_version\*(C'\fR and \f(CW\*(C`drv_meta\*(C'\fR -are added (when available) to the list of valid and immutable attributes -(where \f(CW\*(C`drv_\*(C'\fR is interpreted as the driver prefix). -.Sp -If \f(CW\*(C`drv_meta\*(C'\fR is set, an attribute with the name in \f(CW\*(C`drv_meta\*(C'\fR is -initialized providing restricted read/write access to the meta data of the -tables using \f(CW\*(C`DBD::File::TieTables\*(C'\fR in the first (table) level and -\&\f(CW\*(C`DBD::File::TieMeta\*(C'\fR for the meta attribute level. \f(CW\*(C`DBD::File::TieTables\*(C'\fR -uses \f(CW\*(C`DBD::DRV::Table::get_table_meta\*(C'\fR to initialize the second level -tied hash on \s-1FETCH/STORE.\s0 The \f(CW\*(C`DBD::File::TieMeta\*(C'\fR class uses -\&\f(CW\*(C`DBD::DRV::Table::get_table_meta_attr\*(C'\fR to \s-1FETCH\s0 attribute values and -\&\f(CW\*(C`DBD::DRV::Table::set_table_meta_attr\*(C'\fR to \s-1STORE\s0 attribute values. This -allows it to map meta attributes for compatibility reasons. -.IP "get_single_table_meta" 4 -.IX Item "get_single_table_meta" -.PD 0 -.IP "get_file_meta" 4 -.IX Item "get_file_meta" -.PD -Retrieve an attribute from a table's meta information. The method -signature is \f(CW\*(C`get_file_meta ($dbh, $table, $attr)\*(C'\fR. This method -is called by the injected db handle method \f(CW\*(C`${drv_prefix}get_meta\*(C'\fR. -.Sp -While get_file_meta allows \f(CW$table\fR or \f(CW$attr\fR to be a list of tables or -attributes to retrieve, get_single_table_meta allows only one table name -and only one attribute name. A table name of \f(CW\*(Aq.\*(Aq\fR (single dot) is -interpreted as the default table and this will retrieve the appropriate -attribute globally from the dbh. This has the same restrictions as -\&\f(CW\*(C`$dbh\->{$attrib}\*(C'\fR. -.Sp -get_file_meta allows \f(CW\*(Aq+\*(Aq\fR and \f(CW\*(Aq*\*(Aq\fR as wildcards for table names and -\&\f(CW$table\fR being a regular expression matching against the table names -(evaluated without the default table). The table name \f(CW\*(Aq*\*(Aq\fR is -\&\fIall currently known tables, including the default one\fR. The table -name \f(CW\*(Aq+\*(Aq\fR is \fIall table names which conform to -\&\s-1ANSI\s0 file name restrictions\fR (/^[_A\-Za\-z0\-9]+$/). -.Sp -The table meta information is retrieved using the get_table_meta and -get_table_meta_attr methods of the table class of the implementation. -.IP "set_single_table_meta" 4 -.IX Item "set_single_table_meta" -.PD 0 -.IP "set_file_meta" 4 -.IX Item "set_file_meta" -.PD -Sets an attribute in a table's meta information. The method signature is -\&\f(CW\*(C`set_file_meta ($dbh, $table, $attr, $value)\*(C'\fR. This method is called -by the injected db handle method \f(CW\*(C`${drv_prefix}set_meta\*(C'\fR. -.Sp -While set_file_meta allows \f(CW$table\fR to be a list of tables and \f(CW$attr\fR -to be a hash of several attributes to set, set_single_table_meta allows -only one table name and only one attribute name/value pair. -.Sp -The wildcard characters for the table name are the same as for -get_file_meta. -.Sp -The table meta information is updated using the get_table_meta and -set_table_meta_attr methods of the table class of the implementation. -.IP "clear_file_meta" 4 -.IX Item "clear_file_meta" -Clears all meta information cached about a table. The method signature is -\&\f(CW\*(C`clear_file_meta ($dbh, $table)\*(C'\fR. This method is called -by the injected db handle method \f(CW\*(C`${drv_prefix}clear_meta\*(C'\fR. -.SS "DBD::File::st" -.IX Subsection "DBD::File::st" -Contains the methods to deal with prepared statement handles: -.IP "\s-1FETCH\s0" 4 -.IX Item "FETCH" -Fetches statement handle attributes. Supported attributes (for full overview -see \*(L"Statement Handle Attributes\*(R" in \s-1DBI\s0) are \f(CW\*(C`NAME\*(C'\fR, \f(CW\*(C`TYPE\*(C'\fR, \f(CW\*(C`PRECISION\*(C'\fR -and \f(CW\*(C`NULLABLE\*(C'\fR in case that SQL::Statement is used as \s-1SQL\s0 execution engine -and a statement is successful prepared. When SQL::Statement has additional -information about a table, those information are returned. Otherwise, the -same defaults as in DBI::DBD::SqlEngine are used. -.Sp -This method usually requires extending in a derived implementation. -See \s-1DBD::CSV\s0 or \s-1DBD::DBM\s0 for some example. -.SS "DBD::File::TableSource::FileSystem" -.IX Subsection "DBD::File::TableSource::FileSystem" -Provides data sources and table information on database driver and database -handle level. -.PP -.Vb 1 -\& package DBD::File::TableSource::FileSystem; -\& -\& sub data_sources ($;$) -\& { -\& my ($class, $drh, $attrs) = @_; -\& ... -\& } -\& -\& sub avail_tables -\& { -\& my ($class, $drh) = @_; -\& ... -\& } -.Ve -.PP -The \f(CW\*(C`data_sources\*(C'\fR method is called when the user invokes any of the -following: -.PP -.Vb 2 -\& @ary = DBI\->data_sources ($driver); -\& @ary = DBI\->data_sources ($driver, \e%attr); -\& -\& @ary = $dbh\->data_sources (); -\& @ary = $dbh\->data_sources (\e%attr); -.Ve -.PP -The \f(CW\*(C`avail_tables\*(C'\fR method is called when the user invokes any of the -following: -.PP -.Vb 1 -\& @names = $dbh\->tables ($catalog, $schema, $table, $type); -\& -\& $sth = $dbh\->table_info ($catalog, $schema, $table, $type); -\& $sth = $dbh\->table_info ($catalog, $schema, $table, $type, \e%attr); -\& -\& $dbh\->func ("list_tables"); -.Ve -.PP -Every time where an \f(CW\*(C`\e%attr\*(C'\fR argument can be specified, this \f(CW\*(C`\e%attr\*(C'\fR -object's \f(CW\*(C`sql_table_source\*(C'\fR attribute is preferred over the \f(CW$dbh\fR -attribute or the driver default. -.SS "DBD::File::DataSource::Stream" -.IX Subsection "DBD::File::DataSource::Stream" -.Vb 1 -\& package DBD::File::DataSource::Stream; -\& -\& @DBD::File::DataSource::Stream::ISA = \*(AqDBI::DBD::SqlEngine::DataSource\*(Aq; -\& -\& sub complete_table_name -\& { -\& my ($self, $meta, $file, $respect_case) = @_; -\& ... -\& } -.Ve -.PP -Clears all meta attributes identifying a file: \f(CW\*(C`f_fqfn\*(C'\fR, \f(CW\*(C`f_fqbn\*(C'\fR and -\&\f(CW\*(C`f_fqln\*(C'\fR. The table name is set according to \f(CW$respect_case\fR and -\&\f(CW\*(C`$meta\->{sql_identifier_case}\*(C'\fR (\s-1SQL_IC_LOWER, SQL_IC_UPPER\s0). -.PP -.Vb 1 -\& package DBD::File::DataSource::Stream; -\& -\& sub apply_encoding -\& { -\& my ($self, $meta, $fn) = @_; -\& ... -\& } -.Ve -.PP -Applies the encoding from \fImeta information\fR (\f(CW\*(C`$meta\->{f_encoding}\*(C'\fR) -to the file handled opened in \f(CW\*(C`open_data\*(C'\fR. -.PP -.Vb 1 -\& package DBD::File::DataSource::Stream; -\& -\& sub open_data -\& { -\& my ($self, $meta, $attrs, $flags) = @_; -\& ... -\& } -.Ve -.PP -Opens (\f(CW\*(C`dup (2)\*(C'\fR) the file handle provided in \f(CW\*(C`$meta\->{f_file}\*(C'\fR. -.PP -.Vb 1 -\& package DBD::File::DataSource::Stream; -\& -\& sub can_flock { ... } -.Ve -.PP -Returns whether \f(CW\*(C`flock (2)\*(C'\fR is available or not (avoids retesting in -subclasses). -.SS "DBD::File::DataSource::File" -.IX Subsection "DBD::File::DataSource::File" -.Vb 1 -\& package DBD::File::DataSource::File; -\& -\& sub complete_table_name ($$;$) -\& { -\& my ($self, $meta, $table, $respect_case) = @_; -\& ... -\& } -.Ve -.PP -The method \f(CW\*(C`complete_table_name\*(C'\fR tries to map a filename to the associated -table name. It is called with a partially filled meta structure for the -resulting table containing at least the following attributes: -\&\f(CW\*(C`f_ext\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, \f(CW\*(C`f_lockfile\*(C'\fR and \f(CW\*(C`sql_identifier_case\*(C'\fR. -.PP -If a file/table map can be found then this method sets the \f(CW\*(C`f_fqfn\*(C'\fR, \f(CW\*(C`f_fqbn\*(C'\fR, \f(CW\*(C`f_fqln\*(C'\fR and \f(CW\*(C`table_name\*(C'\fR attributes in -the meta structure. If a map cannot be found the table name will be -undef. -.PP -.Vb 1 -\& package DBD::File::DataSource::File; -\& -\& sub open_data ($) -\& { -\& my ($self, $meta, $attrs, $flags) = @_; -\& ... -\& } -.Ve -.PP -Depending on the attributes set in the table's meta data, the -following steps are performed. Unless \f(CW\*(C`f_dontopen\*(C'\fR is set to a -true value, \f(CW\*(C`f_fqfn\*(C'\fR must contain the full qualified file name -for the table to work on (file2table ensures this). The encoding in -\&\f(CW\*(C`f_encoding\*(C'\fR is applied if set and the file is opened. If -\&\f(CW\*(C` (full qualified lock name) is set, this file is opened, -too. Depending on the value in \f(CW\*(C`f_lock\*(C'\fR, the appropriate lock is -set on the opened data file or lock file. -.SS "DBD::File::Statement" -.IX Subsection "DBD::File::Statement" -Derives from DBI::SQL::Nano::Statement to provide following method: -.IP "open_table" 4 -.IX Item "open_table" -Implements the open_table method required by SQL::Statement and -DBI::SQL::Nano. All the work for opening the file(s) belonging to the -table is handled and parametrized in DBD::File::Table. Unless you intend -to add anything to the following implementation, an empty DBD::XXX::Statement -package satisfies DBD::File. -.Sp -.Vb 3 -\& sub open_table ($$$$$) -\& { -\& my ($self, $data, $table, $createMode, $lockMode) = @_; -\& -\& my $class = ref $self; -\& $class =~ s/::Statement/::Table/; -\& -\& my $flags = { -\& createMode => $createMode, -\& lockMode => $lockMode, -\& }; -\& $self\->{command} eq "DROP" and $flags\->{dropMode} = 1; -\& -\& return $class\->new ($data, { table => $table }, $flags); -\& } # open_table -.Ve -.SS "DBD::File::Table" -.IX Subsection "DBD::File::Table" -Derives from DBI::SQL::Nano::Table and provides physical file access for -the table data which are stored in the files. -.IP "bootstrap_table_meta" 4 -.IX Item "bootstrap_table_meta" -Initializes a table meta structure. Can be safely overridden in a -derived class, as long as the \f(CW\*(C`SUPER\*(C'\fR method is called at the end -of the overridden method. -.Sp -It copies the following attributes from the database into the table meta data -\&\f(CW\*(C`f_dir\*(C'\fR, \f(CW\*(C`f_ext\*(C'\fR, \f(CW\*(C`f_encoding\*(C'\fR, \f(CW\*(C`f_lock\*(C'\fR, \f(CW\*(C`f_schema\*(C'\fR -and \f(CW\*(C`f_lockfile\*(C'\fR and makes them sticky to the table. -.Sp -This method should be called before you attempt to map between file -name and table name to ensure the correct directory, extension etc. are -used. -.IP "init_table_meta" 4 -.IX Item "init_table_meta" -Initializes more attributes of the table meta data \- usually more -expensive ones (e.g. those which require class instantiations) \- when -the file name and the table name could mapped. -.IP "get_table_meta" 4 -.IX Item "get_table_meta" -Returns the table meta data. If there are none for the required -table, a new one is initialized. When it fails, nothing is -returned. On success, the name of the table and the meta data -structure is returned. -.IP "get_table_meta_attr" 4 -.IX Item "get_table_meta_attr" -Returns a single attribute from the table meta data. If the attribute -name appears in \f(CW%compat_map\fR, the attribute name is updated from -there. -.IP "set_table_meta_attr" 4 -.IX Item "set_table_meta_attr" -Sets a single attribute in the table meta data. If the attribute -name appears in \f(CW%compat_map\fR, the attribute name is updated from -there. -.IP "table_meta_attr_changed" 4 -.IX Item "table_meta_attr_changed" -Called when an attribute of the meta data is modified. -.Sp -If the modified attribute requires to reset a calculated attribute, the -calculated attribute is reset (deleted from meta data structure) and -the \fIinitialized\fR flag is removed, too. The decision is made based on -\&\f(CW%register_reset_on_modify\fR. -.IP "register_reset_on_modify" 4 -.IX Item "register_reset_on_modify" -Allows \f(CW\*(C`set_table_meta_attr\*(C'\fR to reset meta attributes when special -attributes are modified. For DBD::File, modifying one of \f(CW\*(C`f_file\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, -\&\f(CW\*(C`f_ext\*(C'\fR or \f(CW\*(C`f_lockfile\*(C'\fR will reset \f(CW\*(C`f_fqfn\*(C'\fR. \s-1DBD::DBM\s0 extends the -list for \f(CW\*(C`dbm_type\*(C'\fR and \f(CW\*(C`dbm_mldbm\*(C'\fR to reset the value of \f(CW\*(C`dbm_tietype\*(C'\fR. -.Sp -If your \s-1DBD\s0 has calculated values in the meta data area, then call -\&\f(CW\*(C`register_reset_on_modify\*(C'\fR: -.Sp -.Vb 2 -\& my %reset_on_modify = (xxx_foo => "xxx_bar"); -\& _\|_PACKAGE_\|_\->register_reset_on_modify (\e%reset_on_modify); -.Ve -.IP "register_compat_map" 4 -.IX Item "register_compat_map" -Allows \f(CW\*(C`get_table_meta_attr\*(C'\fR and \f(CW\*(C`set_table_meta_attr\*(C'\fR to update the -attribute name to the current favored one: -.Sp -.Vb 3 -\& # from DBD::DBM -\& my %compat_map = (dbm_ext => "f_ext"); -\& _\|_PACKAGE_\|_\->register_compat_map (\e%compat_map); -.Ve -.IP "open_file" 4 -.IX Item "open_file" -Called to open the table's data file. -.Sp -Depending on the attributes set in the table's meta data, the -following steps are performed. Unless \f(CW\*(C`f_dontopen\*(C'\fR is set to a -true value, \f(CW\*(C`f_fqfn\*(C'\fR must contain the full qualified file name -for the table to work on (file2table ensures this). The encoding in -\&\f(CW\*(C`f_encoding\*(C'\fR is applied if set and the file is opened. If -\&\f(CW\*(C` (full qualified lock name) is set, this file is opened, -too. Depending on the value in \f(CW\*(C`f_lock\*(C'\fR, the appropriate lock is -set on the opened data file or lock file. -.Sp -After this is done, a derived class might add more steps in an overridden -\&\f(CW\*(C`open_file\*(C'\fR method. -.IP "new" 4 -.IX Item "new" -Instantiates the table. This is done in 3 steps: -.Sp -.Vb 3 -\& 1. get the table meta data -\& 2. open the data file -\& 3. bless the table data structure using inherited constructor new -.Ve -.Sp -It is not recommended to override the constructor of the table class. -Find a reasonable place to add you extensions in one of the above four -methods. -.IP "drop" 4 -.IX Item "drop" -Implements the abstract table method for the \f(CW\*(C`DROP\*(C'\fR -command. Discards table meta data after all files belonging to the -table are closed and unlinked. -.Sp -Overriding this method might be reasonable in very rare cases. -.IP "seek" 4 -.IX Item "seek" -Implements the abstract table method used when accessing the table from the -engine. \f(CW\*(C`seek\*(C'\fR is called every time the engine uses dumb algorithms -for iterating over the table content. -.IP "truncate" 4 -.IX Item "truncate" -Implements the abstract table method used when dumb table algorithms -for \f(CW\*(C`UPDATE\*(C'\fR or \f(CW\*(C`DELETE\*(C'\fR need to truncate the table storage -after the last written row. -.PP -You should consult the documentation of \f(CW\*(C`SQL::Eval::Table\*(C'\fR (see -SQL::Eval) to get more information about the abstract methods of the -table's base class you have to override and a description of the table -meta information expected by the \s-1SQL\s0 engines. -.SH "AUTHOR" -.IX Header "AUTHOR" -The module DBD::File is currently maintained by -.PP -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > -.PP -The original author is Jochen Wiedmann. -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -Copyright (C) 2010\-2013 by H.Merijn Brand & Jens Rehsack -.PP -All rights reserved. -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as -specified in the Perl \s-1README\s0 file. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::File::HowTo.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::File::HowTo.3pm deleted file mode 100644 index 5def364..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::File::HowTo.3pm +++ /dev/null @@ -1,267 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::File::HowTo 3pm" -.TH DBD::File::HowTo 3pm "2013-04-04" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::File::HowTo \- Guide to create DBD::File based driver -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 12 -\& perldoc DBD::File::HowTo -\& perldoc DBI -\& perldoc DBI::DBD -\& perldoc DBD::File::Developers -\& perldoc DBI::DBD::SqlEngine::Developers -\& perldoc DBI::DBD::SqlEngine -\& perldoc SQL::Eval -\& perldoc DBI::DBD::SqlEngine::HowTo -\& perldoc SQL::Statement::Embed -\& perldoc DBD::File -\& perldoc DBD::File::HowTo -\& perldoc DBD::File::Developers -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This document provides a step-by-step guide, how to create a new -\&\f(CW\*(C`DBD::File\*(C'\fR based \s-1DBD.\s0 It expects that you carefully read the \s-1DBI\s0 -documentation and that you're familiar with \s-1DBI::DBD\s0 and had read and -understood DBD::ExampleP. -.PP -This document addresses experienced developers who are really sure that -they need to invest time when writing a new \s-1DBI\s0 Driver. Writing a \s-1DBI\s0 -Driver is neither a weekend project nor an easy job for hobby coders -after work. Expect one or two man-month of time for the first start. -.PP -Those who are still reading, should be able to sing the rules of -\&\*(L"\s-1CREATING A NEW DRIVER\*(R"\s0 in \s-1DBI::DBD\s0. -.PP -Of course, DBD::File is a DBI::DBD::SqlEngine and you surely read -DBI::DBD::SqlEngine::HowTo before continuing here. -.SH "CREATING DRIVER CLASSES" -.IX Header "CREATING DRIVER CLASSES" -Do you have an entry in \s-1DBI\s0's \s-1DBD\s0 registry? For this guide, a prefix of -\&\f(CW\*(C`foo_\*(C'\fR is assumed. -.SS "Sample Skeleton" -.IX Subsection "Sample Skeleton" -.Vb 1 -\& package DBD::Foo; -\& -\& use strict; -\& use warnings; -\& use vars qw(@ISA $VERSION); -\& use base qw(DBD::File); -\& -\& use DBI (); -\& -\& $VERSION = "0.001"; -\& -\& package DBD::Foo::dr; -\& -\& use vars qw(@ISA $imp_data_size); -\& -\& @ISA = qw(DBD::File::dr); -\& $imp_data_size = 0; -\& -\& package DBD::Foo::db; -\& -\& use vars qw(@ISA $imp_data_size); -\& -\& @ISA = qw(DBD::File::db); -\& $imp_data_size = 0; -\& -\& package DBD::Foo::st; -\& -\& use vars qw(@ISA $imp_data_size); -\& -\& @ISA = qw(DBD::File::st); -\& $imp_data_size = 0; -\& -\& package DBD::Foo::Statement; -\& -\& use vars qw(@ISA); -\& -\& @ISA = qw(DBD::File::Statement); -\& -\& package DBD::Foo::Table; -\& -\& use vars qw(@ISA); -\& -\& @ISA = qw(DBD::File::Table); -\& -\& 1; -.Ve -.PP -Tiny, eh? And all you have now is a \s-1DBD\s0 named foo which will is able to -deal with temporary tables, as long as you use SQL::Statement. In -DBI::SQL::Nano environments, this \s-1DBD\s0 can do nothing. -.SS "Start over" -.IX Subsection "Start over" -Based on DBI::DBD::SqlEngine::HowTo, we're now having a driver which -could do basic things. Of course, it should now derive from DBD::File -instead of DBI::DBD::SqlEngine, shouldn't it? -.PP -DBD::File extends DBI::DBD::SqlEngine to deal with any kind of files. -In principle, the only extensions required are to the table class: -.PP -.Vb 1 -\& package DBD::Foo::Table; -\& -\& sub bootstrap_table_meta -\& { -\& my ( $self, $dbh, $meta, $table ) = @_; -\& -\& # initialize all $meta attributes which might be relevant for -\& # file2table -\& -\& return $self\->SUPER::bootstrap_table_meta($dbh, $meta, $table); -\& } -\& -\& sub init_table_meta -\& { -\& my ( $self, $dbh, $meta, $table ) = @_; -\& -\& # called after $meta contains the results from file2table -\& # initialize all missing $meta attributes -\& -\& $self\->SUPER::init_table_meta( $dbh, $meta, $table ); -\& } -.Ve -.PP -In case \f(CW\*(C`DBD::File::Table::open_file\*(C'\fR doesn't open the files as the driver -needs that, override it! -.PP -.Vb 7 -\& sub open_file -\& { -\& my ( $self, $meta, $attrs, $flags ) = @_; -\& # ensure that $meta\->{f_dontopen} is set -\& $self\->SUPER::open_file( $meta, $attrs, $flags ); -\& # now do what ever needs to be done -\& } -.Ve -.PP -Combined with the methods implemented using the SQL::Statement::Embed -guide, the table is full working and you could try a start over. -.SS "User comfort" -.IX Subsection "User comfort" -\&\f(CW\*(C`DBD::File\*(C'\fR since \f(CW0.39\fR consolidates all persistent meta data of a table -into a single structure stored in \f(CW\*(C`$dbh\->{f_meta}\*(C'\fR. With \f(CW\*(C`DBD::File\*(C'\fR -version \f(CW0.41\fR and \f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR version \f(CW0.05\fR, this -consolidation moves to DBI::DBD::SqlEngine. It's still the -\&\f(CW\*(C`$dbh\->{$drv_prefix . "_meta"}\*(C'\fR attribute which cares, so what you -learned at this place before, is still valid. -.PP -.Vb 3 -\& sub init_valid_attributes -\& { -\& my $dbh = $_[0]; -\& -\& $dbh\->SUPER::init_valid_attributes (); -\& -\& $dbh\->{foo_valid_attrs} = { ... }; -\& $dbh\->{foo_readonly_attrs} = { ... }; -\& -\& $dbh\->{foo_meta} = "foo_tables"; -\& -\& return $dbh; -\& } -.Ve -.PP -See updates at \*(L"User comfort\*(R" in DBI::DBD::SqlEngine::HowTo. -.SS "Testing" -.IX Subsection "Testing" -Now you should have your own DBD::File based driver. Was easy, wasn't it? -But does it work well? Prove it by writing tests and remember to use -dbd_edit_mm_attribs from \s-1DBI::DBD\s0 to ensure testing even rare cases. -.SH "AUTHOR" -.IX Header "AUTHOR" -This guide is written by Jens Rehsack. DBD::File is written by Jochen -Wiedmann and Jeff Zucker. -.PP -The module DBD::File is currently maintained by -.PP -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack -.PP -All rights reserved. -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as -specified in the Perl \s-1README\s0 file. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::File::Roadmap.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::File::Roadmap.3pm deleted file mode 100644 index 9e73006..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::File::Roadmap.3pm +++ /dev/null @@ -1,224 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::File::Roadmap 3pm" -.TH DBD::File::Roadmap 3pm "2013-04-04" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::File::Roadmap \- Planned Enhancements for DBD::File and pure Perl DBD's -.PP -Jens Rehsack \- May 2010 -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -This document gives a high level overview of the future of the DBD::File \s-1DBI\s0 -driver and groundwork for pure Perl \s-1DBI\s0 drivers. -.PP -The planned enhancements cover features, testing, performance, reliability, -extensibility and more. -.SH "CHANGES AND ENHANCEMENTS" -.IX Header "CHANGES AND ENHANCEMENTS" -.SS "Features" -.IX Subsection "Features" -There are some features missing we would like to add, but there is -no time plan: -.IP "\s-1LOCK TABLE\s0" 4 -.IX Item "LOCK TABLE" -The newly implemented internal common table meta storage area would allow -us to implement \s-1LOCK TABLE\s0 support based on file system \f(CW\*(C`flock ()\*(C'\fR -support. -.IP "Transaction support" 4 -.IX Item "Transaction support" -While DBD::AnyData recommends explicitly committing by importing and -exporting tables, DBD::File might be enhanced in a future version to allow -transparent transactions using the temporary tables of SQL::Statement as -shadow (dirty) tables. -.Sp -Transaction support will heavily rely on lock table support. -.IP "Data Dictionary Persistence" 4 -.IX Item "Data Dictionary Persistence" -SQL::Statement provides dictionary information when a \*(L"\s-1CREATE TABLE ...\*(R"\s0 -statement is executed. This dictionary is preserved for some statement -handle attribute fetches (as \f(CW\*(C`NULLABLE\*(C'\fR or \f(CW\*(C`PRECISION\*(C'\fR). -.Sp -It is planned to extend DBD::File to support data dictionaries to work -on the tables in it. It is not planned to support one table in different -dictionaries, but you can have several dictionaries in one directory. -.IP "\s-1SQL\s0 Engine selecting on connect" 4 -.IX Item "SQL Engine selecting on connect" -Currently the \s-1SQL\s0 engine selected is chosen during the loading of the module -DBI::SQL::Nano. Ideally end users should be able to select the engine -used in \f(CW\*(C`DBI\->connect ()\*(C'\fR with a special DBD::File attribute. -.PP -Other points of view to the planned features (and more features for the -SQL::Statement engine) are shown in SQL::Statement::Roadmap. -.SS "Testing" -.IX Subsection "Testing" -DBD::File and the dependent \s-1DBD::DBM\s0 requires a lot more automated tests -covering \s-1API\s0 stability and compatibility with optional modules -like SQL::Statement. -.SS "Performance" -.IX Subsection "Performance" -Several arguments for support of features like indexes on columns -and cursors are made for \s-1DBD::CSV \s0(which is a DBD::File based driver, -too). Similar arguments could be made for \s-1DBD::DBM,\s0 DBD::AnyData, -\&\s-1DBD::RAM\s0 or \s-1DBD::PO\s0 etc. -.PP -To improve the performance of the underlying \s-1SQL\s0 engines, a clean -re-implementation seems to be required. Currently both engines are -prematurely optimized and therefore it is not trivial to provide -further optimization without the risk of breaking existing features. -.PP -Join the \s-1DBI\s0 developers \s-1IRC\s0 channel at to -participate or post to the \s-1DBI\s0 Developers Mailing List. -.SS "Reliability" -.IX Subsection "Reliability" -DBD::File currently lacks the following points: -.IP "duplicate table names" 4 -.IX Item "duplicate table names" -It is currently possible to access a table quoted with a relative path -(a) and additionally using an absolute path (b). If (a) and (b) are -the same file that is not recognized (except for -flock protection handled by the Operating System) and two independent -tables are handled. -.IP "invalid table names" 4 -.IX Item "invalid table names" -The current implementation does not prevent someone choosing a -directory name as a physical file name for the table to open. -.SS "Extensibility" -.IX Subsection "Extensibility" -I (Jens Rehsack) have some (partially for example only) \s-1DBD\s0's in mind: -.IP "DBD::Sys" 4 -.IX Item "DBD::Sys" -Derive DBD::Sys from a common code base shared with DBD::File which handles -all the emulation \s-1DBI\s0 needs (as getinfo, \s-1SQL\s0 engine handling, ...) -.IP "DBD::Dir" 4 -.IX Item "DBD::Dir" -Provide a DBD::File derived to work with fixed table definitions through the -file system to demonstrate how \s-1DBI /\s0 Pure Perl DBDs could handle databases -with hierarchical structures. -.IP "DBD::Join" 4 -.IX Item "DBD::Join" -Provide a \s-1DBI\s0 driver which is able to manage multiple connections to other -Databases (as DBD::Multiplex), but allow them to point to different data -sources and allow joins between the tables of them: -.Sp -.Vb 6 -\& # Example -\& # Let table \*(Aqlsof\*(Aq being a table in DBD::Sys giving a list of open files using lsof utility -\& # Let table \*(Aqdir\*(Aq being a atable from DBD::Dir -\& $sth = $dbh\->prepare( "select * from dir,lsof where path=\*(Aq/documents\*(Aq and dir.entry = lsof.filename" ) -\& $sth\->execute(); # gives all open files in \*(Aq/documents\*(Aq -\& ... -\& -\& # Let table \*(Aqfilesys\*(Aq a DBD::Sys table of known file systems on current host -\& # Let table \*(Aqapplications\*(Aq a table of your Configuration Management Database -\& # where current applications (relocatable, with mountpoints for filesystems) -\& # are stored -\& $sth = dbh\->prepare( "select * from applications,filesys where " . -\& "application.mountpoint = filesys.mountpoint and ". -\& "filesys.mounted is true" ); -\& $sth\->execute(); # gives all currently mounted applications on this host -.Ve -.SH "PRIORITIES" -.IX Header "PRIORITIES" -Our priorities are focused on current issues. Initially many new test -cases for DBD::File and \s-1DBD::DBM\s0 should be added to the \s-1DBI\s0 test -suite. After that some additional documentation on how to use the -DBD::File \s-1API\s0 will be provided. -.PP -Any additional priorities will come later and can be modified by (paying) -users. -.SH "RESOURCES AND CONTRIBUTIONS" -.IX Header "RESOURCES AND CONTRIBUTIONS" -See for \fIhow you can help\fR. -.PP -If your company has benefited from \s-1DBI,\s0 please consider if -it could make a donation to The Perl Foundation \*(L"\s-1DBI\s0 Development\*(R" -fund at to secure future development. -.PP -Alternatively, if your company would benefit from a specific new -\&\s-1DBI\s0 feature, please consider sponsoring it's development through -the options listed in the section \*(L"Commercial Support from the Author\*(R" -on . -.PP -Using such targeted financing allows you to contribute to \s-1DBI\s0 -development and rapidly get something specific and directly valuable -to you in return. -.PP -My company also offers annual support contracts for the \s-1DBI,\s0 which -provide another way to support the \s-1DBI\s0 and get something specific -in return. Contact me for details. -.PP -Thank you. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer.3pm deleted file mode 100644 index 791843e..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer.3pm +++ /dev/null @@ -1,557 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer 3pm" -.TH DBD::Gofer 3pm "2014-02-05" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer \- A stateless\-proxy driver for communicating with a remote DBI -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& use DBI; -\& -\& $original_dsn = "dbi:..."; # your original DBI Data Source Name -\& -\& $dbh = DBI\->connect("dbi:Gofer:transport=$transport;...;dsn=$original_dsn", -\& $user, $passwd, \e%attributes); -\& -\& ... use $dbh as if it was connected to $original_dsn ... -.Ve -.PP -The \f(CW\*(C`transport=$transport\*(C'\fR part specifies the name of the module to use to -transport the requests to the remote \s-1DBI.\s0 If \f(CW$transport\fR doesn't contain any -double colons then it's prefixed with \f(CW\*(C`DBD::Gofer::Transport::\*(C'\fR. -.PP -The \f(CW\*(C`dsn=$original_dsn\*(C'\fR part \fImust be the last element\fR of the \s-1DSN\s0 because -everything after \f(CW\*(C`dsn=\*(C'\fR is assumed to be the \s-1DSN\s0 that the remote \s-1DBI\s0 should -use. -.PP -The \f(CW\*(C`...\*(C'\fR represents attributes that influence the operation of the Gofer -driver or transport. These are described below or in the documentation of the -transport module being used. -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBD::Gofer is a \s-1DBI\s0 database driver that forwards requests to another \s-1DBI\s0 -driver, usually in a separate process, often on a separate machine. It tries to -be as transparent as possible so it appears that you are using the remote -driver directly. -.PP -DBD::Gofer is very similar to DBD::Proxy. The major difference is that with -DBD::Gofer no state is maintained on the remote end. That means every -request contains all the information needed to create the required state. (So, -for example, every request includes the \s-1DSN\s0 to connect to.) Each request can be -sent to any available server. The server executes the request and returns a -single response that includes all the data. -.PP -This is very similar to the way http works as a stateless protocol for the web. -Each request from your web browser can be handled by a different web server process. -.SS "Use Cases" -.IX Subsection "Use Cases" -This may seem like pointless overhead but there are situations where this is a -very good thing. Let's consider a specific case. -.PP -Imagine using DBD::Gofer with an http transport. Your application calls -\&\fIconnect()\fR, prepare(\*(L"select * from table where foo=?\*(R"), \fIbind_param()\fR, and \fIexecute()\fR. -At this point DBD::Gofer builds a request containing all the information -about the method calls. It then uses the httpd transport to send that request -to an apache web server. -.PP -This 'dbi execute' web server executes the request (using DBI::Gofer::Execute -and related modules) and builds a response that contains all the rows of data, -if the statement returned any, along with all the attributes that describe the -results, such as \f(CW$sth\fR\->{\s-1NAME\s0}. This response is sent back to DBD::Gofer which -unpacks it and presents it to the application as if it had executed the -statement itself. -.SS "Advantages" -.IX Subsection "Advantages" -Okay, but you still don't see the point? Well let's consider what we've gained: -.PP -\fIConnection Pooling and Throttling\fR -.IX Subsection "Connection Pooling and Throttling" -.PP -The 'dbi execute' web server leverages all the functionality of web -infrastructure in terms of load balancing, high-availability, firewalls, access -management, proxying, caching. -.PP -At its most basic level you get a configurable pool of persistent database connections. -.PP -\fISimple Scaling\fR -.IX Subsection "Simple Scaling" -.PP -Got thousands of processes all trying to connect to the database? You can use -DBD::Gofer to connect them to your smaller pool of 'dbi execute' web servers instead. -.PP -\fICaching\fR -.IX Subsection "Caching" -.PP -Client-side caching is as simple as adding "\f(CW\*(C`cache=1\*(C'\fR" to the \s-1DSN.\s0 -This feature alone can be worth using DBD::Gofer for. -.PP -\fIFewer Network Round-trips\fR -.IX Subsection "Fewer Network Round-trips" -.PP -DBD::Gofer sends as few requests as possible (dependent on the policy being used). -.PP -\fIThin Clients / Unsupported Platforms\fR -.IX Subsection "Thin Clients / Unsupported Platforms" -.PP -You no longer need drivers for your database on every system. DBD::Gofer is pure perl. -.SH "CONSTRAINTS" -.IX Header "CONSTRAINTS" -There are some natural constraints imposed by the DBD::Gofer 'stateless' approach. -But not many: -.SS "You can't change database handle attributes after \fIconnect()\fP" -.IX Subsection "You can't change database handle attributes after connect()" -You can't change database handle attributes after you've connected. -Use the \fIconnect()\fR call to specify all the attribute settings you want. -.PP -This is because it's critical that when a request is complete the database -handle is left in the same state it was when first connected. -.PP -An exception is made for attributes with names starting "\f(CW\*(C`private_\*(C'\fR": -They can be set after \fIconnect()\fR but the change is only applied locally. -.SS "You can't change statement handle attributes after \fIprepare()\fP" -.IX Subsection "You can't change statement handle attributes after prepare()" -You can't change statement handle attributes after prepare. -.PP -An exception is made for attributes with names starting "\f(CW\*(C`private_\*(C'\fR": -They can be set after \fIprepare()\fR but the change is only applied locally. -.SS "You can't use transactions" -.IX Subsection "You can't use transactions" -AutoCommit only. Transactions aren't supported. -.PP -(In theory transactions could be supported when using a transport that -maintains a connection, like \f(CW\*(C`stream\*(C'\fR does. If you're interested in this -please get in touch via dbi\-dev@perl.org) -.SS "You can't call driver-private sth methods" -.IX Subsection "You can't call driver-private sth methods" -But that's rarely needed anyway. -.SH "GENERAL CAVEATS" -.IX Header "GENERAL CAVEATS" -A few important things to keep in mind when using DBD::Gofer: -.SS "Temporary tables, locks, and other per-connection persistent state" -.IX Subsection "Temporary tables, locks, and other per-connection persistent state" -You shouldn't expect any per-session state to persist between requests. -This includes locks and temporary tables. -.PP -Because the server-side may execute your requests via a different -database connections, you can't rely on any per-connection persistent state, -such as temporary tables, being available from one request to the next. -.PP -This is an easy trap to fall into. A good way to check for this is to test your -code with a Gofer policy package that sets the \f(CW\*(C`connect_method\*(C'\fR policy to -\&'connect' to force a new connection for each request. The \f(CW\*(C`pedantic\*(C'\fR policy does this. -.SS "Driver-private Database Handle Attributes" -.IX Subsection "Driver-private Database Handle Attributes" -Some driver-private dbh attributes may not be available if the driver has not -implemented the \fIprivate_attribute_info()\fR method (added in \s-1DBI 1.54\s0). -.SS "Driver-private Statement Handle Attributes" -.IX Subsection "Driver-private Statement Handle Attributes" -Driver-private sth attributes can be set in the \fIprepare()\fR call. \s-1TODO\s0 -.PP -Some driver-private sth attributes may not be available if the driver has not -implemented the \fIprivate_attribute_info()\fR method (added in \s-1DBI 1.54\s0). -.SS "Multiple Resultsets" -.IX Subsection "Multiple Resultsets" -Multiple resultsets are supported only if the driver supports the \fImore_results()\fR method -(an exception is made for DBD::Sybase). -.SS "Statement activity that also updates dbh attributes" -.IX Subsection "Statement activity that also updates dbh attributes" -Some drivers may update one or more dbh attributes after performing activity on -a child sth. For example, DBD::mysql provides \f(CW$dbh\fR\->{mysql_insertid} in addition to -\&\f(CW$sth\fR\->{mysql_insertid}. Currently mysql_insertid is supported via a hack but a -more general mechanism is needed for other drivers to use. -.SS "Methods that report an error always return undef" -.IX Subsection "Methods that report an error always return undef" -With DBD::Gofer, a method that sets an error always return an undef or empty list. -That shouldn't be a problem in practice because the \s-1DBI\s0 doesn't define any -methods that return meaningful values while also reporting an error. -.SS "Subclassing only applies to client-side" -.IX Subsection "Subclassing only applies to client-side" -The RootClass and DbTypeSubclass attributes are not passed to the Gofer server. -.SH "CAVEATS FOR SPECIFIC METHODS" -.IX Header "CAVEATS FOR SPECIFIC METHODS" -.SS "last_insert_id" -.IX Subsection "last_insert_id" -To enable use of last_insert_id you need to indicate to DBD::Gofer that you'd -like to use it. You do that my adding a \f(CW\*(C`go_last_insert_id_args\*(C'\fR attribute to -the \fIdo()\fR or \fIprepare()\fR method calls. For example: -.PP -.Vb 1 -\& $dbh\->do($sql, { go_last_insert_id_args => [...] }); -.Ve -.PP -or -.PP -.Vb 1 -\& $sth = $dbh\->prepare($sql, { go_last_insert_id_args => [...] }); -.Ve -.PP -The array reference should contains the args that you want passed to the -\&\fIlast_insert_id()\fR method. -.SS "execute_for_fetch" -.IX Subsection "execute_for_fetch" -The array methods \fIbind_param_array()\fR and \fIexecute_array()\fR are supported. -When \fIexecute_array()\fR is called the data is serialized and executed in a single -round-trip to the Gofer server. This makes it very fast, but requires enough -memory to store all the serialized data. -.PP -The \fIexecute_for_fetch()\fR method currently isn't optimised, it uses the \s-1DBI\s0 -fallback behaviour of executing each tuple individually. -(It could be implemented as a wrapper for \fIexecute_array()\fR \- patches welcome.) -.SH "TRANSPORTS" -.IX Header "TRANSPORTS" -DBD::Gofer doesn't concern itself with transporting requests and responses to and fro. -For that it uses special Gofer transport modules. -.PP -Gofer transport modules usually come in pairs: one for the 'client' DBD::Gofer -driver to use and one for the remote 'server' end. They have very similar names: -.PP -.Vb 2 -\& DBD::Gofer::Transport:: -\& DBI::Gofer::Transport:: -.Ve -.PP -Sometimes the transports on the \s-1DBD\s0 and \s-1DBI\s0 sides may have different names. For -example DBD::Gofer::Transport::http is typically used with DBI::Gofer::Transport::mod_perl -(DBD::Gofer::Transport::http and DBI::Gofer::Transport::mod_perl modules are -part of the GoferTransport-http distribution). -.SS "Bundled Transports" -.IX Subsection "Bundled Transports" -Several transport modules are provided with DBD::Gofer: -.PP -\fInull\fR -.IX Subsection "null" -.PP -The null transport is the simplest of them all. It doesn't actually transport the request anywhere. -It just serializes (freezes) the request into a string, then thaws it back into -a data structure before passing it to DBI::Gofer::Execute to execute. The same -freeze and thaw is applied to the results. -.PP -The null transport is the best way to test if your application will work with Gofer. -Just set the \s-1DBI_AUTOPROXY\s0 environment variable to "\f(CW\*(C`dbi:Gofer:transport=null;policy=pedantic\*(C'\fR" -(see \*(L"Using \s-1DBI_AUTOPROXY\*(R"\s0 below) and run your application, or ideally its test suite, as usual. -.PP -It doesn't take any parameters. -.PP -\fIpipeone\fR -.IX Subsection "pipeone" -.PP -The pipeone transport launches a subprocess for each request. It passes in the -request and reads the response. -.PP -The fact that a new subprocess is started for each request ensures that the -server side is truly stateless. While this does make the transport \fIvery\fR slow, -it is useful as a way to test that your application doesn't depend on -per-connection state, such as temporary tables, persisting between requests. -.PP -It's also useful both as a proof of concept and as a base class for the stream -driver. -.PP -\fIstream\fR -.IX Subsection "stream" -.PP -The stream driver also launches a subprocess and writes requests and reads -responses, like the pipeone transport. In this case, however, the subprocess -is expected to handle more that one request. (Though it will be automatically -restarted if it exits.) -.PP -This is the first transport that is truly useful because it can launch the -subprocess on a remote machine using \f(CW\*(C`ssh\*(C'\fR. This means you can now use DBD::Gofer -to easily access any databases that's accessible from any system you can login to. -You also get all the benefits of ssh, including encryption and optional compression. -.PP -See \*(L"Using \s-1DBI_AUTOPROXY\*(R"\s0 below for an example. -.SS "Other Transports" -.IX Subsection "Other Transports" -Implementing a Gofer transport is \fIvery\fR simple, and more transports are very welcome. -Just take a look at any existing transports that are similar to your needs. -.PP -\fIhttp\fR -.IX Subsection "http" -.PP -See the GoferTransport-http distribution on \s-1CPAN:\s0 http://search.cpan.org/dist/GoferTransport\-http/ -.PP -\fIGearman\fR -.IX Subsection "Gearman" -.PP -I know Ask Bjørn Hansen has implemented a transport for the \f(CW\*(C`gearman\*(C'\fR distributed -job system, though it's not on \s-1CPAN\s0 at the time of writing this. -.SH "CONNECTING" -.IX Header "CONNECTING" -Simply prefix your existing \s-1DSN\s0 with "\f(CW\*(C`dbi:Gofer:transport=$transport;dsn=\*(C'\fR" -where \f(CW$transport\fR is the name of the Gofer transport you want to use (see \*(L"\s-1TRANSPORTS\*(R"\s0). -The \f(CW\*(C`transport\*(C'\fR and \f(CW\*(C`dsn\*(C'\fR attributes must be specified and the \f(CW\*(C`dsn\*(C'\fR attributes must be last. -.PP -Other attributes can be specified in the \s-1DSN\s0 to configure DBD::Gofer and/or the -Gofer transport module being used. The main attributes after \f(CW\*(C`transport\*(C'\fR, are -\&\f(CW\*(C`url\*(C'\fR and \f(CW\*(C`policy\*(C'\fR. These and other attributes are described below. -.SS "Using \s-1DBI_AUTOPROXY\s0" -.IX Subsection "Using DBI_AUTOPROXY" -The simplest way to try out DBD::Gofer is to set the \s-1DBI_AUTOPROXY\s0 environment variable. -In this case you don't include the \f(CW\*(C`dsn=\*(C'\fR part. For example: -.PP -.Vb 1 -\& export DBI_AUTOPROXY="dbi:Gofer:transport=null" -.Ve -.PP -or, for a more useful example, try: -.PP -.Vb 1 -\& export DBI_AUTOPROXY="dbi:Gofer:transport=stream;url=ssh:user@example.com" -.Ve -.SS "Connection Attributes" -.IX Subsection "Connection Attributes" -These attributes can be specified in the \s-1DSN.\s0 They can also be passed in the -\&\e%attr parameter of the \s-1DBI\s0 connect method by adding a "\f(CW\*(C`go_\*(C'\fR" prefix to the name. -.PP -\fItransport\fR -.IX Subsection "transport" -.PP -Specifies the Gofer transport class to use. Required. See \*(L"\s-1TRANSPORTS\*(R"\s0 above. -.PP -If the value does not include \f(CW\*(C`::\*(C'\fR then "\f(CW\*(C`DBD::Gofer::Transport::\*(C'\fR" is prefixed. -.PP -The transport object can be accessed via \f(CW$h\fR\->{go_transport}. -.PP -\fIdsn\fR -.IX Subsection "dsn" -.PP -Specifies the \s-1DSN\s0 for the remote side to connect to. Required, and must be last. -.PP -\fIurl\fR -.IX Subsection "url" -.PP -Used to tell the transport where to connect to. The exact form of the value depends on the transport used. -.PP -\fIpolicy\fR -.IX Subsection "policy" -.PP -Specifies the policy to use. See \*(L"\s-1CONFIGURING BEHAVIOUR POLICY\*(R"\s0. -.PP -If the value does not include \f(CW\*(C`::\*(C'\fR then "\f(CW\*(C`DBD::Gofer::Policy\*(C'\fR" is prefixed. -.PP -The policy object can be accessed via \f(CW$h\fR\->{go_policy}. -.PP -\fItimeout\fR -.IX Subsection "timeout" -.PP -Specifies a timeout, in seconds, to use when waiting for responses from the server side. -.PP -\fIretry_limit\fR -.IX Subsection "retry_limit" -.PP -Specifies the number of times a failed request will be retried. Default is 0. -.PP -\fIretry_hook\fR -.IX Subsection "retry_hook" -.PP -Specifies a code reference to be called to decide if a failed request should be retried. -The code reference is called like this: -.PP -.Vb 2 -\& $transport = $h\->{go_transport}; -\& $retry = $transport\->go_retry_hook\->($request, $response, $transport); -.Ve -.PP -If it returns true then the request will be retried, up to the \f(CW\*(C`retry_limit\*(C'\fR. -If it returns a false but defined value then the request will not be retried. -If it returns undef then the default behaviour will be used, as if \f(CW\*(C`retry_hook\*(C'\fR -had not been specified. -.PP -The default behaviour is to retry requests where \f(CW$request\fR\->is_idempotent is true, -or the error message matches \f(CW\*(C`/induced by DBI_GOFER_RANDOM/\*(C'\fR. -.PP -\fIcache\fR -.IX Subsection "cache" -.PP -Specifies that client-side caching should be performed. The value is the name -of a cache class to use. -.PP -Any class implementing get($key) and set($key, \f(CW$value\fR) methods can be used. -That includes a great many powerful caching classes on \s-1CPAN,\s0 including the -Cache and Cache::Cache distributions. -.PP -You can use "\f(CW\*(C`cache=1\*(C'\fR\*(L" is a shortcut for \*(R"\f(CW\*(C`cache=DBI::Util::CacheMemory\*(C'\fR". -See DBI::Util::CacheMemory for a description of this simple fast default cache. -.PP -The cache object can be accessed via \f(CW$h\fR\->go_cache. For example: -.PP -.Vb 1 -\& $dbh\->go_cache\->clear; # free up memory being used by the cache -.Ve -.PP -The cache keys are the frozen (serialized) requests, and the values are the -frozen responses. -.PP -The default behaviour is to only use the cache for requests where -\&\f(CW$request\fR\->is_idempotent is true (i.e., the dbh has the ReadOnly attribute set -or the \s-1SQL\s0 statement is obviously a \s-1SELECT\s0 without a \s-1FOR UPDATE\s0 clause.) -.PP -For even more control you can use the \f(CW\*(C`go_cache\*(C'\fR attribute to pass in an -instantiated cache object. Individual methods, including \fIprepare()\fR, can also -specify alternative caches via the \f(CW\*(C`go_cache\*(C'\fR attribute. For example, to -specify no caching for a particular query, you could use -.PP -.Vb 1 -\& $sth = $dbh\->prepare( $sql, { go_cache => 0 } ); -.Ve -.PP -This can be used to implement different caching policies for different statements. -.PP -It's interesting to note that DBD::Gofer can be used to add client-side caching -to any (gofer compatible) application, with no code changes and no need for a -gofer server. Just set the \s-1DBI_AUTOPROXY\s0 environment variable like this: -.PP -.Vb 1 -\& DBI_AUTOPROXY=\*(Aqdbi:Gofer:transport=null;cache=1\*(Aq -.Ve -.SH "CONFIGURING BEHAVIOUR POLICY" -.IX Header "CONFIGURING BEHAVIOUR POLICY" -DBD::Gofer supports a 'policy' mechanism that allows you to fine-tune the number of round-trips to the Gofer server. -The policies are grouped into classes (which may be subclassed) and referenced by the name of the class. -.PP -The DBD::Gofer::Policy::Base class is the base class for all the policy -packages and describes all the available policies. -.PP -Three policy packages are supplied with DBD::Gofer: -.PP -DBD::Gofer::Policy::pedantic is most 'transparent' but slowest because it -makes more round-trips to the Gofer server. -.PP -DBD::Gofer::Policy::classic is a reasonable compromise \- it's the default policy. -.PP -DBD::Gofer::Policy::rush is fastest, but may require code changes in your applications. -.PP -Generally the default \f(CW\*(C`classic\*(C'\fR policy is fine. When first testing an existing -application with Gofer it is a good idea to start with the \f(CW\*(C`pedantic\*(C'\fR policy -first and then switch to \f(CW\*(C`classic\*(C'\fR or a custom policy, for final testing. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. -.SH "ACKNOWLEDGEMENTS" -.IX Header "ACKNOWLEDGEMENTS" -The development of DBD::Gofer and related modules was sponsored by -Shopzilla.com (), where I currently work. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -DBI::Gofer::Request, DBI::Gofer::Response, DBI::Gofer::Execute. -.PP -DBI::Gofer::Transport::Base, DBD::Gofer::Policy::Base. -.PP -\&\s-1DBI\s0 -.SH "Caveats for specific drivers" -.IX Header "Caveats for specific drivers" -This section aims to record issues to be aware of when using Gofer with specific drivers. -It usually only documents issues that are not natural consequences of the limitations -of the Gofer approach \- as documented above. -.SH "TODO" -.IX Header "TODO" -This is just a random brain dump... (There's more in the source of the Changes file, not the pod) -.PP -Document policy mechanism -.PP -Add mechanism for transports to list config params and for Gofer to apply any that match (and warn if any left over?) -.PP -Driver-private sth attributes \- set via \fIprepare()\fR \- change \s-1DBI\s0 spec -.PP -add hooks into transport base class for checking & updating a result set cache - ie via a standard cache interface such as: - http://search.cpan.org/~robm/Cache\-FastMmap/FastMmap.pm - http://search.cpan.org/~bradfitz/Cache\-Memcached/lib/Cache/Memcached.pm - http://search.cpan.org/~dclinton/Cache\-Cache/ - http://search.cpan.org/~cleishman/Cache/ -Also caching instructions could be passed through the httpd transport layer -in such a way that appropriate http cache headers are added to the results -so that web caches (squid etc) could be used to implement the caching. -(\s-1MUST\s0 require the use of \s-1GET\s0 rather than \s-1POST\s0 requests.) -.PP -Rework handling of installed_methods to not piggyback on dbh_attributes? -.PP -Perhaps support transactions for transports where it's possible (ie null and stream)? -Would make stream transport (ie ssh) more useful to more people. -.PP -Make sth_result_attr more like dbh_attributes (using '*' etc) -.PP -Add \f(CW@val\fR = FETCH_many(@names) to \s-1DBI\s0 in C and use in Gofer/Execute? -.PP -Implement _new_sth in C. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::Base.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::Base.3pm deleted file mode 100644 index d64d85c..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::Base.3pm +++ /dev/null @@ -1,146 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Policy::Base 3pm" -.TH DBD::Gofer::Policy::Base 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Policy::Base \- Base class for DBD::Gofer policies -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& $dbh = DBI\->connect("dbi:Gofer:transport=...;policy=...", ...) -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBD::Gofer can be configured via a 'policy' mechanism that allows you to -fine-tune the number of round-trips to the Gofer server. The policies are -grouped into classes (which may be subclassed) and referenced by the name of -the class. -.PP -The DBD::Gofer::Policy::Base class is the base class for all the policy -classes and describes all the individual policy items. -.PP -The Base policy is not used directly. You should use a policy class derived from it. -.SH "POLICY CLASSES" -.IX Header "POLICY CLASSES" -Three policy classes are supplied with DBD::Gofer: -.PP -DBD::Gofer::Policy::pedantic is most 'transparent' but slowest because it -makes more round-trips to the Gofer server. -.PP -DBD::Gofer::Policy::classic is a reasonable compromise \- it's the default policy. -.PP -DBD::Gofer::Policy::rush is fastest, but may require code changes in your applications. -.PP -Generally the default \f(CW\*(C`classic\*(C'\fR policy is fine. When first testing an existing -application with Gofer it is a good idea to start with the \f(CW\*(C`pedantic\*(C'\fR policy -first and then switch to \f(CW\*(C`classic\*(C'\fR or a custom policy, for final testing. -.SH "POLICY ITEMS" -.IX Header "POLICY ITEMS" -These are temporary docs: See the source code for list of policies and their defaults. -.PP -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. -.PP -See the source code to this module for more details. -.SH "POLICY CUSTOMIZATION" -.IX Header "POLICY CUSTOMIZATION" -\&\s-1XXX\s0 This area of DBD::Gofer is subject to change. -.PP -There are three ways to customize policies: -.PP -Policy classes are designed to influence the overall behaviour of DBD::Gofer -with existing, unaltered programs, so they work in a reasonably optimal way -without requiring code changes. You can implement new policy classes as -subclasses of existing policies. -.PP -In many cases individual policy items can be overridden on a case-by-case basis -within your application code. You do this by passing a corresponding -\&\f(CW\*(C`> attribute into \s-1DBI\s0 methods by your application code. -This let's you fine-tune the behaviour for special cases. -.PP -The policy items are implemented as methods. In many cases the methods are -passed parameters relating to the DBD::Gofer code being executed. This means -the policy can implement dynamic behaviour that varies depending on the -particular circumstances, such as the particular statement being executed. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::classic.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::classic.3pm deleted file mode 100644 index a94eb73..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::classic.3pm +++ /dev/null @@ -1,101 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Policy::classic 3pm" -.TH DBD::Gofer::Policy::classic 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Policy::classic \- The 'classic' policy for DBD::Gofer -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& $dbh = DBI\->connect("dbi:Gofer:transport=...;policy=classic", ...) -.Ve -.PP -The \f(CW\*(C`classic\*(C'\fR policy is the default DBD::Gofer policy, so need not be included in the \s-1DSN.\s0 -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Temporary docs: See the source code for list of policies and their defaults. -.PP -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::pedantic.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::pedantic.3pm deleted file mode 100644 index 1653593..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::pedantic.3pm +++ /dev/null @@ -1,105 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Policy::pedantic 3pm" -.TH DBD::Gofer::Policy::pedantic 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Policy::pedantic \- The 'pedantic' policy for DBD::Gofer -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& $dbh = DBI\->connect("dbi:Gofer:transport=...;policy=pedantic", ...) -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -The \f(CW\*(C`pedantic\*(C'\fR policy tries to be as transparent as possible. To do this it -makes round-trips to the server for almost every \s-1DBI\s0 method call. -.PP -This is the best policy to use when first testing existing code with Gofer. -Once it's working well you should consider moving to the \f(CW\*(C`classic\*(C'\fR policy or defining your own policy class. -.PP -Temporary docs: See the source code for list of policies and their defaults. -.PP -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::rush.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::rush.3pm deleted file mode 100644 index 0d32ac5..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Policy::rush.3pm +++ /dev/null @@ -1,102 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Policy::rush 3pm" -.TH DBD::Gofer::Policy::rush 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Policy::rush \- The 'rush' policy for DBD::Gofer -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& $dbh = DBI\->connect("dbi:Gofer:transport=...;policy=rush", ...) -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -The \f(CW\*(C`rush\*(C'\fR policy tries to make as few round-trips as possible. -It's the opposite end of the policy spectrum to the \f(CW\*(C`pedantic\*(C'\fR policy. -.PP -Temporary docs: See the source code for list of policies and their defaults. -.PP -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::Base.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::Base.3pm deleted file mode 100644 index b5e1c91..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::Base.3pm +++ /dev/null @@ -1,187 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Transport::Base 3pm" -.TH DBD::Gofer::Transport::Base 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Transport::Base \- base class for DBD::Gofer client transports -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 2 -\& my $remote_dsn = "..." -\& DBI\->connect("dbi:Gofer:transport=...;url=...;timeout=...;retry_limit=...;dsn=$remote_dsn",...) -.Ve -.PP -or, enable by setting the \s-1DBI_AUTOPROXY\s0 environment variable: -.PP -.Vb 1 -\& export DBI_AUTOPROXY=\*(Aqdbi:Gofer:transport=...;url=...\*(Aq -.Ve -.PP -which will force \fIall\fR \s-1DBI\s0 connections to be made via that Gofer server. -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This is the base class for all DBD::Gofer client transports. -.SH "ATTRIBUTES" -.IX Header "ATTRIBUTES" -Gofer transport attributes can be specified either in the attributes parameter -of the \fIconnect()\fR method call, or in the \s-1DSN\s0 string. When used in the \s-1DSN\s0 -string, attribute names don't have the \f(CW\*(C`go_\*(C'\fR prefix. -.SS "go_dsn" -.IX Subsection "go_dsn" -The full \s-1DBI DSN\s0 that the Gofer server should connect to on your behalf. -.PP -When used in the \s-1DSN\s0 it must be the last element in the \s-1DSN\s0 string. -.SS "go_timeout" -.IX Subsection "go_timeout" -A time limit for sending a request and receiving a response. Some drivers may -implement sending and receiving as separate steps, in which case (currently) -the timeout applies to each separately. -.PP -If a request needs to be resent then the timeout is restarted for each sending -of a request and receiving of a response. -.SS "go_retry_limit" -.IX Subsection "go_retry_limit" -The maximum number of times an request may be retried. The default is 2. -.SS "go_retry_hook" -.IX Subsection "go_retry_hook" -This subroutine reference is called, if defined, for each response received where \f(CW$response\fR\->err is true. -.PP -The subroutine is pass three parameters: the request object, the response object, and the transport object. -.PP -If it returns an undefined value then the default retry behaviour is used. See \*(L"\s-1RETRY ON ERROR\*(R"\s0 below. -.PP -If it returns a defined but false value then the request is not resent. -.PP -If it returns true value then the request is resent, so long as the number of retries does not exceed \f(CW\*(C`go_retry_limit\*(C'\fR. -.SH "RETRY ON ERROR" -.IX Header "RETRY ON ERROR" -The default retry on error behaviour is: -.PP -.Vb 1 -\& \- Retry if the error was due to DBI_GOFER_RANDOM. See L. -\& -\& \- Retry if $request\->is_idempotent returns true. See L. -.Ve -.PP -A retry won't be allowed if the number of previous retries has reached \f(CW\*(C`go_retry_limit\*(C'\fR. -.SH "TRACING" -.IX Header "TRACING" -Tracing of gofer requests and responses can be enabled by setting the -\&\f(CW\*(C`DBD_GOFER_TRACE\*(C'\fR environment variable. A value of 1 gives a reasonably -compact summary of each request and response. A value of 2 or more gives a -detailed, and voluminous, dump. -.PP -The trace is written using \s-1DBI\-\s0>\fItrace_msg()\fR and so is written to the default -\&\s-1DBI\s0 trace output, which is usually \s-1STDERR.\s0 -.SH "METHODS" -.IX Header "METHODS" -\&\fIThis section is currently far from complete.\fR -.SS "response_retry_preference" -.IX Subsection "response_retry_preference" -.Vb 1 -\& $retry = $transport\->response_retry_preference($request, $response); -.Ve -.PP -The response_retry_preference is called by DBD::Gofer when considering if a -request should be retried after an error. -.PP -Returns true (would like to retry), false (must not retry), undef (no preference). -.PP -If a true value is returned in the form of a \s-1CODE\s0 ref then, if DBD::Gofer does -decide to retry the request, it calls the code ref passing \f(CW$retry_count\fR, \f(CW$retry_limit\fR. -Can be used for logging and/or to implement exponential backoff behaviour. -Currently the called code must return using \f(CW\*(C`return;\*(C'\fR to allow for future extensions. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007\-2008, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -DBD::Gofer, DBI::Gofer::Request, DBI::Gofer::Response, DBI::Gofer::Execute. -.PP -and some example transports: -.PP -DBD::Gofer::Transport::stream -.PP -DBD::Gofer::Transport::http -.PP -DBI::Gofer::Transport::mod_perl diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::corostream.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::corostream.3pm deleted file mode 100644 index 32d64ab..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::corostream.3pm +++ /dev/null @@ -1,194 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Transport::corostream 3pm" -.TH DBD::Gofer::Transport::corostream 3pm "2013-04-04" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Transport::corostream \- Async DBD::Gofer stream transport using Coro and AnyEvent -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& DBI_AUTOPROXY="dbi:Gofer:transport=corostream" perl some\-perl\-script\-using\-dbi.pl -.Ve -.PP -or -.PP -.Vb 2 -\& $dsn = ...; # the DSN for the driver and database you want to use -\& $dbh = DBI\->connect("dbi:Gofer:transport=corostream;dsn=$dsn", ...); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -The \fI\s-1BIG WIN\s0\fR from using Coro is that it enables the use of existing -\&\s-1DBI\s0 frameworks like DBIx::Class. -.SH "KNOWN ISSUES AND LIMITATIONS" -.IX Header "KNOWN ISSUES AND LIMITATIONS" -.Vb 2 -\& \- Uses Coro::Select so alters CORE::select globally -\& Parent class probably needs refactoring to enable a more encapsulated approach. -\& -\& \- Doesn\*(Aqt prevent multiple concurrent requests -\& Probably just needs a per\-connection semaphore -\& -\& \- Coro has many caveats. Caveat emptor. -.Ve -.SH "STATUS" -.IX Header "STATUS" -\&\s-1THIS IS CURRENTLY JUST A\s0 PROOF-OF-CONCEPT \s-1IMPLEMENTATION FOR EXPERIMENTATION.\s0 -.PP -Please note that I have no plans to develop this code further myself. -I'd very much welcome contributions. Interested? Let me know! -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2010, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -DBD::Gofer::Transport::stream -.PP -DBD::Gofer -.SH "APPENDIX" -.IX Header "APPENDIX" -Example code: -.PP -.Vb 1 -\& #!perl -\& -\& use strict; -\& use warnings; -\& use Time::HiRes qw(time); -\& -\& BEGIN { $ENV{PERL_ANYEVENT_STRICT} = 1; $ENV{PERL_ANYEVENT_VERBOSE} = 1; } -\& -\& use AnyEvent; -\& -\& BEGIN { $ENV{DBI_TRACE} = 0; $ENV{DBI_GOFER_TRACE} = 0; $ENV{DBD_GOFER_TRACE} = 0; }; -\& -\& use DBI; -\& -\& $ENV{DBI_AUTOPROXY} = \*(Aqdbi:Gofer:transport=corostream\*(Aq; -\& -\& my $ticker = AnyEvent\->timer( after => 0, interval => 0.1, cb => sub { -\& warn sprintf "\-tick\- %.2f\en", time -\& } ); -\& -\& warn "connecting...\en"; -\& my $dbh = DBI\->connect("dbi:NullP:"); -\& warn "...connected\en"; -\& -\& for (1..3) { -\& warn "entering DBI...\en"; -\& $dbh\->do("sleep 0.3"); # pseudo\-sql understood by the DBD::NullP driver -\& warn "...returned\en"; -\& } -\& -\& warn "done."; -.Ve -.PP -Example output: -.PP -.Vb 10 -\& $ perl corogofer.pl -\& connecting... -\& \-tick\- 1293631437.14 -\& \-tick\- 1293631437.14 -\& ...connected -\& entering DBI... -\& \-tick\- 1293631437.25 -\& \-tick\- 1293631437.35 -\& \-tick\- 1293631437.45 -\& \-tick\- 1293631437.55 -\& ...returned -\& entering DBI... -\& \-tick\- 1293631437.66 -\& \-tick\- 1293631437.76 -\& \-tick\- 1293631437.86 -\& ...returned -\& entering DBI... -\& \-tick\- 1293631437.96 -\& \-tick\- 1293631438.06 -\& \-tick\- 1293631438.16 -\& ...returned -\& done. at corogofer.pl line 39. -.Ve -.PP -You can see that the timer callback is firing while the code 'waits' inside the -\&\fIdo()\fR method for the response from the database. Normally that would block. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::null.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::null.3pm deleted file mode 100644 index 14ee9d4..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::null.3pm +++ /dev/null @@ -1,122 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Transport::null 3pm" -.TH DBD::Gofer::Transport::null 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Transport::null \- DBD::Gofer client transport for testing -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 2 -\& my $original_dsn = "..." -\& DBI\->connect("dbi:Gofer:transport=null;dsn=$original_dsn",...) -.Ve -.PP -or, enable by setting the \s-1DBI_AUTOPROXY\s0 environment variable: -.PP -.Vb 1 -\& export DBI_AUTOPROXY="dbi:Gofer:transport=null" -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Connect via DBD::Gofer but execute the requests within the same process. -.PP -This is a quick and simple way to test applications for compatibility with the -(few) restrictions that DBD::Gofer imposes. -.PP -It also provides a simple, portable way for the \s-1DBI\s0 test suite to be used to -test DBD::Gofer on all platforms with no setup. -.PP -Also, by measuring the difference in performance between normal connections and -connections via \f(CW\*(C`dbi:Gofer:transport=null\*(C'\fR the basic cost of using DBD::Gofer -can be measured. Furthermore, the additional cost of more advanced transports can be -isolated by comparing their performance with the null transport. -.PP -The \f(CW\*(C`t/85gofer.t\*(C'\fR script in the \s-1DBI\s0 distribution includes a comparative benchmark. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -DBD::Gofer::Transport::Base -.PP -DBD::Gofer diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::pipeone.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::pipeone.3pm deleted file mode 100644 index a304bb3..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::pipeone.3pm +++ /dev/null @@ -1,117 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Transport::pipeone 3pm" -.TH DBD::Gofer::Transport::pipeone 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Transport::pipeone \- DBD::Gofer client transport for testing -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 2 -\& $original_dsn = "..."; -\& DBI\->connect("dbi:Gofer:transport=pipeone;dsn=$original_dsn",...) -.Ve -.PP -or, enable by setting the \s-1DBI_AUTOPROXY\s0 environment variable: -.PP -.Vb 1 -\& export DBI_AUTOPROXY="dbi:Gofer:transport=pipeone" -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Connect via DBD::Gofer and execute each request by starting executing a subprocess. -.PP -This is, as you might imagine, spectacularly inefficient! -.PP -It's only intended for testing. Specifically it demonstrates that the server -side is completely stateless. -.PP -It also provides a base class for the much more useful DBD::Gofer::Transport::stream -transport. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -DBD::Gofer::Transport::Base -.PP -DBD::Gofer diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::stream.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::stream.3pm deleted file mode 100644 index a63862b..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Gofer::Transport::stream.3pm +++ /dev/null @@ -1,155 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Gofer::Transport::stream 3pm" -.TH DBD::Gofer::Transport::stream 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Gofer::Transport::stream \- DBD::Gofer transport for stdio streaming -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& DBI\->connect(\*(Aqdbi:Gofer:transport=stream;url=ssh:username@host.example.com;dsn=dbi:...\*(Aq,...) -.Ve -.PP -or, enable by setting the \s-1DBI_AUTOPROXY\s0 environment variable: -.PP -.Vb 1 -\& export DBI_AUTOPROXY=\*(Aqdbi:Gofer:transport=stream;url=ssh:username@host.example.com\*(Aq -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Without the \f(CW\*(C`url=\*(C'\fR parameter it launches a subprocess as -.PP -.Vb 1 -\& perl \-MDBI::Gofer::Transport::stream \-e run_stdio_hex -.Ve -.PP -and feeds requests into it and reads responses from it. But that's not very useful. -.PP -With a \f(CW\*(C`url=ssh:username@host.example.com\*(C'\fR parameter it uses ssh to launch the subprocess -on a remote system. That's much more useful! -.PP -It gives you secure remote access to \s-1DBI\s0 databases on any system you can login to. -Using ssh also gives you optional compression and many other features (see the -ssh manual for how to configure that and many other options via ~/.ssh/config file). -.PP -The actual command invoked is something like: -.PP -.Vb 1 -\& ssh \-xq ssh:username@host.example.com bash \-c $setup $run -.Ve -.PP -where \f(CW$run\fR is the command shown above, and \f(CW$command\fR is -.PP -.Vb 1 -\& . .bash_profile 2>/dev/null || . .bash_login 2>/dev/null || . .profile 2>/dev/null; exec "$@" -.Ve -.PP -which is trying (in a limited and fairly unportable way) to setup the environment -(\s-1PATH, PERL5LIB\s0 etc) as it would be if you had logged in to that system. -.PP -The "\f(CW\*(C`perl\*(C'\fR" used in the command will default to the value of $^X when not using ssh. -On most systems that's the full path to the perl that's currently executing. -.SH "PERSISTENCE" -.IX Header "PERSISTENCE" -Currently gofer stream connections persist (remain connected) after all -database handles have been disconnected. This makes later connections in the -same process very fast. -.PP -Currently up to 5 different gofer stream connections (based on url) can -persist. If more than 5 are in the cache when a new connection is made then -the cache is cleared before adding the new connection. Simple but effective. -.SH "TO DO" -.IX Header "TO DO" -Document go_perl attribute -.PP -Automatically reconnect (within reason) if there's a transport error. -.PP -Decide on default for persistent connection \- on or off? limits? ttl? -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -DBD::Gofer::Transport::Base -.PP -DBD::Gofer diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Mem.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Mem.3pm deleted file mode 100644 index 2f6f72c..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Mem.3pm +++ /dev/null @@ -1,164 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Mem 3pm" -.TH DBD::Mem 3pm "2017-12-28" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Mem \- a DBI driver for Mem & MLMem files -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 3 -\& use DBI; -\& $dbh = DBI\->connect(\*(Aqdbi:Mem:\*(Aq, undef, undef, {}); -\& $dbh = DBI\->connect(\*(Aqdbi:Mem:\*(Aq, undef, undef, {RaiseError => 1}); -\& -\& # or -\& $dbh = DBI\->connect(\*(Aqdbi:Mem:\*(Aq); -\& $dbh = DBI\->connect(\*(AqDBI:Mem(RaiseError=1):\*(Aq); -.Ve -.PP -and other variations on \fIconnect()\fR as shown in the \s-1DBI\s0 docs and -. -.PP -Use standard \s-1DBI\s0 prepare, execute, fetch, placeholders, etc., -see \*(L"\s-1QUICK START\*(R"\s0 for an example. -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBD::Mem is a database management system that works right out of the box. -If you have a standard installation of Perl and \s-1DBI\s0 you can begin creating, -accessing, and modifying simple database tables without any further modules. -You can add other modules (e.g., SQL::Statement) for improved functionality. -.PP -DBD::Mem doesn't store any data persistently \- all data has the lifetime of -the instantiated \f(CW$dbh\fR. The main reason to use DBD::Mem is to use extended -features of SQL::Statement where temporary tables are required. One can -use DBD::Mem to simulate \f(CW\*(C`VIEWS\*(C'\fR or sub-queries. -.PP -Bundling \f(CW\*(C`DBD::Mem\*(C'\fR with \s-1DBI\s0 will allow us further compatibility checks -of DBI::DBD::SqlEngine beyond the capabilities of DBD::File and -\&\s-1DBD::DBM\s0. This will ensure \s-1DBI\s0 provided basis for drivers like -DBD::AnyData2 or DBD::Amazon are better prepared and tested for -not-file based backends. -.SS "Metadata" -.IX Subsection "Metadata" -There're no new meta data introduced by \f(CW\*(C`DBD::Mem\*(C'\fR. See -\&\*(L"Metadata\*(R" in DBI::DBD::SqlEngine for full description. -.SH "GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS" -.IX Header "GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS" -If you need help installing or using DBD::Mem, please write to the \s-1DBI\s0 -users mailing list at or to the -comp.lang.perl.modules newsgroup on usenet. I cannot always answer -every question quickly but there are many on the mailing list or in -the newsgroup who can. -.PP -\&\s-1DBD\s0 developers for \s-1DBD\s0's which rely on DBI::DBD::SqlEngine or DBD::Mem or -use one of them as an example are suggested to join the \s-1DBI\s0 developers -mailing list at and strongly encouraged to join our -\&\s-1IRC\s0 channel at . -.PP -If you have suggestions, ideas for improvements, or bugs to report, please -report a bug as described in \s-1DBI.\s0 Do not mail any of the authors directly, -you might not get an answer. -.PP -When reporting bugs, please send the output of \f(CW\*(C`$dbh\->mem_versions($table)\*(C'\fR -for a table that exhibits the bug and as small a sample as you can make of -the code that produces the bug. And of course, patches are welcome, too -:\-). -.PP -If you need enhancements quickly, you can get commercial support as -described at or you can contact Jens Rehsack -at rehsack@cpan.org for commercial support. -.SH "AUTHOR AND COPYRIGHT" -.IX Header "AUTHOR AND COPYRIGHT" -This module is written by Jens Rehsack < rehsack \s-1AT\s0 cpan.org >. -.PP -.Vb 1 -\& Copyright (c) 2016\- by Jens Rehsack, all rights reserved. -.Ve -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as -specified in the Perl \s-1README\s0 file. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -\&\s-1DBI\s0 for the Database interface of the Perl Programming Language. -.PP -SQL::Statement and DBI::SQL::Nano for the available \s-1SQL\s0 engines. -.PP -SQL::Statement::RAM where the implementation is shamelessly stolen from -to allow \s-1DBI\s0 bundled Pure-Perl drivers increase the test coverage. -.PP -DBD::SQLite using \f(CW\*(C`dbname=:memory:\*(C'\fR for an incredible fast in-memory database engine. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Proxy.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Proxy.3pm deleted file mode 100644 index 17386a3..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Proxy.3pm +++ /dev/null @@ -1,353 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Proxy 3pm" -.TH DBD::Proxy 3pm "2014-09-21" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Proxy \- A proxy driver for the DBI -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& use DBI; -\& -\& $dbh = DBI\->connect("dbi:Proxy:hostname=$host;port=$port;dsn=$db", -\& $user, $passwd); -\& -\& # See the DBI module documentation for full details -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBD::Proxy is a Perl module for connecting to a database via a remote -\&\s-1DBI\s0 driver. See DBD::Gofer for an alternative with different trade-offs. -.PP -This is of course not needed for \s-1DBI\s0 drivers which already -support connecting to a remote database, but there are engines which -don't offer network connectivity. -.PP -Another application is offering database access through a firewall, as -the driver offers query based restrictions. For example you can -restrict queries to exactly those that are used in a given \s-1CGI\s0 -application. -.PP -Speaking of \s-1CGI,\s0 another application is (or rather, will be) to reduce -the database connect/disconnect overhead from \s-1CGI\s0 scripts by using -proxying the connect_cached method. The proxy server will hold the -database connections open in a cache. The \s-1CGI\s0 script then trades the -database connect/disconnect overhead for the DBD::Proxy -connect/disconnect overhead which is typically much less. -.SH "CONNECTING TO THE DATABASE" -.IX Header "CONNECTING TO THE DATABASE" -Before connecting to a remote database, you must ensure, that a Proxy -server is running on the remote machine. There's no default port, so -you have to ask your system administrator for the port number. See -DBI::ProxyServer for details. -.PP -Say, your Proxy server is running on machine \*(L"alpha\*(R", port 3334, and -you'd like to connect to an \s-1ODBC\s0 database called \*(L"mydb\*(R" as user \*(L"joe\*(R" -with password \*(L"hello\*(R". When using \s-1DBD::ODBC\s0 directly, you'd do a -.PP -.Vb 1 -\& $dbh = DBI\->connect("DBI:ODBC:mydb", "joe", "hello"); -.Ve -.PP -With DBD::Proxy this becomes -.PP -.Vb 2 -\& $dsn = "DBI:Proxy:hostname=alpha;port=3334;dsn=DBI:ODBC:mydb"; -\& $dbh = DBI\->connect($dsn, "joe", "hello"); -.Ve -.PP -You see, this is mainly the same. The DBD::Proxy module will create a -connection to the Proxy server on \*(L"alpha\*(R" which in turn will connect -to the \s-1ODBC\s0 database. -.PP -Refer to the \s-1DBI\s0 documentation on the \f(CW\*(C`connect\*(C'\fR method for a way -to automatically use DBD::Proxy without having to change your code. -.PP -DBD::Proxy's \s-1DSN\s0 string has the format -.PP -.Vb 1 -\& $dsn = "DBI:Proxy:key1=val1; ... ;keyN=valN;dsn=valDSN"; -.Ve -.PP -In other words, it is a collection of key/value pairs. The following -keys are recognized: -.IP "hostname" 4 -.IX Item "hostname" -.PD 0 -.IP "port" 4 -.IX Item "port" -.PD -Hostname and port of the Proxy server; these keys must be present, -no defaults. Example: -.Sp -.Vb 1 -\& hostname=alpha;port=3334 -.Ve -.IP "dsn" 4 -.IX Item "dsn" -The value of this attribute will be used as a dsn name by the Proxy -server. Thus it must have the format \f(CW\*(C`DBI:driver:...\*(C'\fR, in particular -it will contain colons. The \fIdsn\fR value may contain semicolons, hence -this key *must* be the last and it's value will be the complete -remaining part of the dsn. Example: -.Sp -.Vb 1 -\& dsn=DBI:ODBC:mydb -.Ve -.IP "cipher" 4 -.IX Item "cipher" -.PD 0 -.IP "key" 4 -.IX Item "key" -.IP "usercipher" 4 -.IX Item "usercipher" -.IP "userkey" 4 -.IX Item "userkey" -.PD -By using these fields you can enable encryption. If you set, -for example, -.Sp -.Vb 1 -\& cipher=$class;key=$key -.Ve -.Sp -(note the semicolon) then DBD::Proxy will create a new cipher object -by executing -.Sp -.Vb 1 -\& $cipherRef = $class\->new(pack("H*", $key)); -.Ve -.Sp -and pass this object to the RPC::PlClient module when creating a -client. See RPC::PlClient. Example: -.Sp -.Vb 1 -\& cipher=IDEA;key=97cd2375efa329aceef2098babdc9721 -.Ve -.Sp -The usercipher/userkey attributes allow you to use two phase encryption: -The cipher/key encryption will be used in the login and authorisation -phase. Once the client is authorised, he will change to usercipher/userkey -encryption. Thus the cipher/key pair is a \fBhost\fR based secret, typically -less secure than the usercipher/userkey secret and readable by anyone. -The usercipher/userkey secret is \fByour\fR private secret. -.Sp -Of course encryption requires an appropriately configured server. See -\&\*(L"\s-1CONFIGURATION FILE\*(R"\s0 in DBD::ProxyServer. -.IP "debug" 4 -.IX Item "debug" -Turn on debugging mode -.IP "stderr" 4 -.IX Item "stderr" -This attribute will set the corresponding attribute of the RPC::PlClient -object, thus logging will not use \fIsyslog()\fR, but redirected to stderr. -This is the default under Windows. -.Sp -.Vb 1 -\& stderr=1 -.Ve -.IP "logfile" 4 -.IX Item "logfile" -Similar to the stderr attribute, but output will be redirected to the -given file. -.Sp -.Vb 1 -\& logfile=/dev/null -.Ve -.IP "RowCacheSize" 4 -.IX Item "RowCacheSize" -The DBD::Proxy driver supports this attribute (which is \s-1DBI\s0 standard, -as of \s-1DBI 1.02\s0). It's used to reduce network round-trips by fetching -multiple rows in one go. The current default value is 20, but this may -change. -.IP "proxy_no_finish" 4 -.IX Item "proxy_no_finish" -This attribute can be used to reduce network traffic: If the -application is calling \f(CW$sth\fR\->\fIfinish()\fR then the proxy tells the server -to finish the remote statement handle. Of course this slows down things -quite a lot, but is perfectly good for reducing memory usage with -persistent connections. -.Sp -However, if you set the \fIproxy_no_finish\fR attribute to a \s-1TRUE\s0 value, -either in the database handle or in the statement handle, then \fIfinish()\fR -calls will be suppressed. This is what you want, for example, in small -and fast \s-1CGI\s0 applications. -.IP "proxy_quote" 4 -.IX Item "proxy_quote" -This attribute can be used to reduce network traffic: By default calls -to \f(CW$dbh\fR\->\fIquote()\fR are passed to the remote driver. Of course this slows -down things quite a lot, but is the safest default behaviour. -.Sp -However, if you set the \fIproxy_quote\fR attribute to the value '\f(CW\*(C`local\*(C'\fR' -either in the database handle or in the statement handle, and the call -to quote has only one parameter, then the local default \s-1DBI\s0 quote -method will be used (which will be faster but may be wrong). -.SH "KNOWN ISSUES" -.IX Header "KNOWN ISSUES" -.SS "Unproxied method calls" -.IX Subsection "Unproxied method calls" -If a method isn't being proxied, try declaring a stub sub in the appropriate -package (DBD::Proxy::db for a dbh method, and DBD::Proxy::st for an sth method). -For example: -.PP -.Vb 1 -\& sub DBD::Proxy::db::selectall_arrayref; -.Ve -.PP -That will enable selectall_arrayref to be proxied. -.PP -Currently many methods aren't explicitly proxied and so you get the \s-1DBI\s0's -default methods executed on the client. -.PP -Some of those methods, like selectall_arrayref, may then call other methods -that are proxied (selectall_arrayref calls fetchall_arrayref which calls fetch -which is proxied). So things may appear to work but operate more slowly than -the could. -.PP -This may all change in a later version. -.SS "Complex handle attributes" -.IX Subsection "Complex handle attributes" -Sometimes handles are having complex attributes like hash refs or -array refs and not simple strings or integers. For example, with -\&\s-1DBD::CSV,\s0 you would like to write something like -.PP -.Vb 2 -\& $dbh\->{"csv_tables"}\->{"passwd"} = -\& { "sep_char" => ":", "eol" => "\en"; -.Ve -.PP -The above example would advice the \s-1CSV\s0 driver to assume the file -\&\*(L"passwd\*(R" to be in the format of the /etc/passwd file: Colons as -separators and a line feed without carriage return as line -terminator. -.PP -Surprisingly this example doesn't work with the proxy driver. To understand -the reasons, you should consider the following: The Perl compiler is -executing the above example in two steps: -.IP "1." 4 -The first step is fetching the value of the key \*(L"csv_tables\*(R" in the -handle \f(CW$dbh\fR. The value returned is complex, a hash ref. -.IP "2." 4 -The second step is storing some value (the right hand side of the -assignment) as the key \*(L"passwd\*(R" in the hash ref from step 1. -.PP -This becomes a little bit clearer, if we rewrite the above code: -.PP -.Vb 2 -\& $tables = $dbh\->{"csv_tables"}; -\& $tables\->{"passwd"} = { "sep_char" => ":", "eol" => "\en"; -.Ve -.PP -While the examples work fine without the proxy, the fail due to a -subtle difference in step 1: By \s-1DBI\s0 magic, the hash ref -\&\f(CW$dbh\fR\->{'csv_tables'} is returned from the server to the client. -The client creates a local copy. This local copy is the result of -step 1. In other words, step 2 modifies a local copy of the hash ref, -but not the server's hash ref. -.PP -The workaround is storing the modified local copy back to the server: -.PP -.Vb 3 -\& $tables = $dbh\->{"csv_tables"}; -\& $tables\->{"passwd"} = { "sep_char" => ":", "eol" => "\en"; -\& $dbh\->{"csv_tables"} = $tables; -.Ve -.SH "SECURITY WARNING" -.IX Header "SECURITY WARNING" -RPC::PlClient used underneath is not secure due to serializing and -deserializing data with Storable module. Use the proxy driver only in -trusted environment. -.SH "AUTHOR AND COPYRIGHT" -.IX Header "AUTHOR AND COPYRIGHT" -This module is Copyright (c) 1997, 1998 -.PP -.Vb 4 -\& Jochen Wiedmann -\& Am Eisteich 9 -\& 72555 Metzingen -\& Germany -\& -\& Email: joe@ispsoft.de -\& Phone: +49 7123 14887 -.Ve -.PP -The DBD::Proxy module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. In particular permission -is granted to Tim Bunce for distributing this as a part of the \s-1DBI.\s0 -.SH "SEE ALSO" -.IX Header "SEE ALSO" -\&\s-1DBI\s0, RPC::PlClient, Storable diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBD::Sponge.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBD::Sponge.3pm deleted file mode 100644 index 9764c41..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBD::Sponge.3pm +++ /dev/null @@ -1,147 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBD::Sponge 3pm" -.TH DBD::Sponge 3pm "2015-05-26" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBD::Sponge \- Create a DBI statement handle from Perl data -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 7 -\& my $sponge = DBI\->connect("dbi:Sponge:","","",{ RaiseError => 1 }); -\& my $sth = $sponge\->prepare($statement, { -\& rows => $data, -\& NAME => $names, -\& %attr -\& } -\& ); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBD::Sponge is useful for making a Perl data structure accessible through a -standard \s-1DBI\s0 statement handle. This may be useful to \s-1DBD\s0 module authors who -need to transform data in this way. -.SH "METHODS" -.IX Header "METHODS" -.SS "\fIconnect()\fP" -.IX Subsection "connect()" -.Vb 1 -\& my $sponge = DBI\->connect("dbi:Sponge:","","",{ RaiseError => 1 }); -.Ve -.PP -Here's a sample syntax for creating a database handle for the Sponge driver. -No username and password are needed. -.SS "\fIprepare()\fP" -.IX Subsection "prepare()" -.Vb 6 -\& my $sth = $sponge\->prepare($statement, { -\& rows => $data, -\& NAME => $names, -\& %attr -\& } -\& ); -.Ve -.IP "\(bu" 4 -The \f(CW$statement\fR here is an arbitrary statement or name you want -to provide as identity of your data. If you're using DBI::Profile -it will appear in the profile data. -.Sp -Generally it's expected that you are preparing a statement handle -as if a \f(CW\*(C`select\*(C'\fR statement happened. -.IP "\(bu" 4 -\&\f(CW$data\fR is a reference to the data you are providing, given as an array of arrays. -.IP "\(bu" 4 -\&\f(CW$names\fR is a reference an array of column names for the \f(CW$data\fR you are providing. -The number and order should match the number and ordering of the \f(CW$data\fR columns. -.IP "\(bu" 4 -\&\f(CW%attr\fR is a hash of other standard \s-1DBI\s0 attributes that you might pass to a prepare statement. -.Sp -Currently only \s-1NAME, TYPE,\s0 and \s-1PRECISION\s0 are supported. -.SH "BUGS" -.IX Header "BUGS" -Using this module to prepare INSERT-like statements is not currently documented. -.SH "AUTHOR AND COPYRIGHT" -.IX Header "AUTHOR AND COPYRIGHT" -This module is Copyright (c) 2003 Tim Bunce -.PP -Documentation initially written by Mark Stosberg -.PP -The DBD::Sponge module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. In particular permission -is granted to Tim Bunce for distributing this as a part of the \s-1DBI.\s0 -.SH "SEE ALSO" -.IX Header "SEE ALSO" -\&\s-1DBI\s0 diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI.3pm deleted file mode 100644 index d68772d..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI.3pm +++ /dev/null @@ -1,6991 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI 3pm" -.TH DBI 3pm "2018-03-19" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI \- Database independent interface for Perl -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& use DBI; -\& -\& @driver_names = DBI\->available_drivers; -\& %drivers = DBI\->installed_drivers; -\& @data_sources = DBI\->data_sources($driver_name, \e%attr); -\& -\& $dbh = DBI\->connect($data_source, $username, $auth, \e%attr); -\& -\& $rv = $dbh\->do($statement); -\& $rv = $dbh\->do($statement, \e%attr); -\& $rv = $dbh\->do($statement, \e%attr, @bind_values); -\& -\& $ary_ref = $dbh\->selectall_arrayref($statement); -\& $hash_ref = $dbh\->selectall_hashref($statement, $key_field); -\& -\& $ary_ref = $dbh\->selectcol_arrayref($statement); -\& $ary_ref = $dbh\->selectcol_arrayref($statement, \e%attr); -\& -\& @row_ary = $dbh\->selectrow_array($statement); -\& $ary_ref = $dbh\->selectrow_arrayref($statement); -\& $hash_ref = $dbh\->selectrow_hashref($statement); -\& -\& $sth = $dbh\->prepare($statement); -\& $sth = $dbh\->prepare_cached($statement); -\& -\& $rc = $sth\->bind_param($p_num, $bind_value); -\& $rc = $sth\->bind_param($p_num, $bind_value, $bind_type); -\& $rc = $sth\->bind_param($p_num, $bind_value, \e%attr); -\& -\& $rv = $sth\->execute; -\& $rv = $sth\->execute(@bind_values); -\& $rv = $sth\->execute_array(\e%attr, ...); -\& -\& $rc = $sth\->bind_col($col_num, \e$col_variable); -\& $rc = $sth\->bind_columns(@list_of_refs_to_vars_to_bind); -\& -\& @row_ary = $sth\->fetchrow_array; -\& $ary_ref = $sth\->fetchrow_arrayref; -\& $hash_ref = $sth\->fetchrow_hashref; -\& -\& $ary_ref = $sth\->fetchall_arrayref; -\& $ary_ref = $sth\->fetchall_arrayref( $slice, $max_rows ); -\& -\& $hash_ref = $sth\->fetchall_hashref( $key_field ); -\& -\& $rv = $sth\->rows; -\& -\& $rc = $dbh\->begin_work; -\& $rc = $dbh\->commit; -\& $rc = $dbh\->rollback; -\& -\& $quoted_string = $dbh\->quote($string); -\& -\& $rc = $h\->err; -\& $str = $h\->errstr; -\& $rv = $h\->state; -\& -\& $rc = $dbh\->disconnect; -.Ve -.PP -\&\fIThe synopsis above only lists the major methods and parameters.\fR -.SS "\s-1GETTING HELP\s0" -.IX Subsection "GETTING HELP" -\fIGeneral\fR -.IX Subsection "General" -.PP -Before asking any questions, reread this document, consult the -archives and read the \s-1DBI FAQ.\s0 The archives are listed -at the end of this document and on the \s-1DBI\s0 home page -.PP -You might also like to read the Advanced \s-1DBI\s0 Tutorial at - -.PP -To help you make the best use of the dbi-users mailing list, -and any other lists or forums you may use, I recommend that you read -\&\*(L"Getting Answers\*(R" by Mike Ash: . -.PP -\fIMailing Lists\fR -.IX Subsection "Mailing Lists" -.PP -If you have questions about \s-1DBI,\s0 or \s-1DBD\s0 driver modules, you can get -help from the \fIdbi\-users@perl.org\fR mailing list. This is the best way to get -help. You don't have to subscribe to the list in order to post, though I'd -recommend it. You can get help on subscribing and using the list by emailing -\&\fIdbi\-users\-help@perl.org\fR. -.PP -Please note that Tim Bunce does not maintain the mailing lists or the -web pages (generous volunteers do that). So please don't send mail -directly to him; he just doesn't have the time to answer questions -personally. The \fIdbi-users\fR mailing list has lots of experienced -people who should be able to help you if you need it. If you do email -Tim he is very likely to just forward it to the mailing list. -.PP -\fI\s-1IRC\s0\fR -.IX Subsection "IRC" -.PP -\&\s-1DBI IRC\s0 Channel: #dbi on irc.perl.org () -.PP -\fIOnline\fR -.IX Subsection "Online" -.PP -StackOverflow has a \s-1DBI\s0 tag -with over 800 questions. -.PP -The \s-1DBI\s0 home page at and the \s-1DBI FAQ\s0 -at may be worth a visit. -They include links to other resources, but \fIare rather out-dated\fR. -.PP -\fIReporting a Bug\fR -.IX Subsection "Reporting a Bug" -.PP -If you think you've found a bug then please read -\&\*(L"How to Report Bugs Effectively\*(R" by Simon Tatham: -. -.PP -If you think you've found a memory leak then read \*(L"Memory Leaks\*(R". -.PP -Your problem is most likely related to the specific \s-1DBD\s0 driver module you're -using. If that's the case then click on the 'Bugs' link on the -page for your driver. Only submit a bug report against the \s-1DBI\s0 itself if you're -sure that your issue isn't related to the driver you're using. -.SS "\s-1NOTES\s0" -.IX Subsection "NOTES" -This is the \s-1DBI\s0 specification that corresponds to \s-1DBI\s0 version 1.641 -(see DBI::Changes for details). -.PP -The \s-1DBI\s0 is evolving at a steady pace, so it's good to check that -you have the latest copy. -.PP -The significant user-visible changes in each release are documented -in the DBI::Changes module so you can read them by executing -\&\f(CW\*(C`perldoc DBI::Changes\*(C'\fR. -.PP -Some \s-1DBI\s0 changes require changes in the drivers, but the drivers -can take some time to catch up. Newer versions of the \s-1DBI\s0 have -added features that may not yet be supported by the drivers you -use. Talk to the authors of your drivers if you need a new feature -that is not yet supported. -.PP -Features added after \s-1DBI 1.21 \s0(February 2002) are marked in the -text with the version number of the \s-1DBI\s0 release they first appeared in. -.PP -Extensions to the \s-1DBI API\s0 often use the \f(CW\*(C`DBIx::*\*(C'\fR namespace. -See \*(L"Naming Conventions and Name Space\*(R". \s-1DBI\s0 extension modules -can be found at . And all modules -related to the \s-1DBI\s0 can be found at . -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -The \s-1DBI\s0 is a database access module for the Perl programming language. It defines -a set of methods, variables, and conventions that provide a consistent -database interface, independent of the actual database being used. -.PP -It is important to remember that the \s-1DBI\s0 is just an interface. -The \s-1DBI\s0 is a layer -of \*(L"glue\*(R" between an application and one or more database \fIdriver\fR -modules. It is the driver modules which do most of the real work. The \s-1DBI\s0 -provides a standard interface and framework for the drivers to operate -within. -.PP -This document often uses terms like \fIreferences\fR, \fIobjects\fR, -\&\fImethods\fR. If you're not familiar with those terms then it would -be a good idea to read at least the following perl manuals first: -perlreftut, perldsc, perllol, and perlboot. -.SS "Architecture of a \s-1DBI\s0 Application" -.IX Subsection "Architecture of a DBI Application" -.Vb 11 -\& |<\- Scope of DBI \->| -\& .\-. .\-\-\-\-\-\-\-\-\-\-\-\-\-\-. .\-\-\-\-\-\-\-\-\-\-\-\-\-. -\& .\-\-\-\-\-\-\-. | |\-\-\-| XYZ Driver |\-\-\-| XYZ Engine | -\& | Perl | | | \`\-\-\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq \`\-\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq -\& | script| |A| |D| .\-\-\-\-\-\-\-\-\-\-\-\-\-\-. .\-\-\-\-\-\-\-\-\-\-\-\-\-. -\& | using |\-\-|P|\-\-|B|\-\-\-|Oracle Driver |\-\-\-|Oracle Engine| -\& | DBI | |I| |I| \`\-\-\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq \`\-\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq -\& | API | | |... -\& |methods| | |... Other drivers -\& \`\-\-\-\-\-\-\-\*(Aq | |... -\& \`\-\*(Aq -.Ve -.PP -The \s-1API,\s0 or Application Programming Interface, defines the -call interface and variables for Perl scripts to use. The \s-1API\s0 -is implemented by the Perl \s-1DBI\s0 extension. -.PP -The \s-1DBI \s0\*(L"dispatches\*(R" the method calls to the appropriate driver for -actual execution. The \s-1DBI\s0 is also responsible for the dynamic loading -of drivers, error checking and handling, providing default -implementations for methods, and many other non-database specific duties. -.PP -Each driver -contains implementations of the \s-1DBI\s0 methods using the -private interface functions of the corresponding database engine. Only authors -of sophisticated/multi\-database applications or generic library -functions need be concerned with drivers. -.SS "Notation and Conventions" -.IX Subsection "Notation and Conventions" -The following conventions are used in this document: -.PP -.Vb 11 -\& $dbh Database handle object -\& $sth Statement handle object -\& $drh Driver handle object (rarely seen or used in applications) -\& $h Any of the handle types above ($dbh, $sth, or $drh) -\& $rc General Return Code (boolean: true=ok, false=error) -\& $rv General Return Value (typically an integer) -\& @ary List of values returned from the database, typically a row of data -\& $rows Number of rows processed (if available, else \-1) -\& $fh A filehandle -\& undef NULL values are represented by undefined values in Perl -\& \e%attr Reference to a hash of attribute values passed to methods -.Ve -.PP -Note that Perl will automatically destroy database and statement handle objects -if all references to them are deleted. -.SS "Outline Usage" -.IX Subsection "Outline Usage" -To use \s-1DBI,\s0 -first you need to load the \s-1DBI\s0 module: -.PP -.Vb 2 -\& use DBI; -\& use strict; -.Ve -.PP -(The \f(CW\*(C`use strict;\*(C'\fR isn't required but is strongly recommended.) -.PP -Then you need to \*(L"connect\*(R" to your data source and get a \fIhandle\fR for that -connection: -.PP -.Vb 2 -\& $dbh = DBI\->connect($dsn, $user, $password, -\& { RaiseError => 1, AutoCommit => 0 }); -.Ve -.PP -Since connecting can be expensive, you generally just connect at the -start of your program and disconnect at the end. -.PP -Explicitly defining the required \f(CW\*(C`AutoCommit\*(C'\fR behaviour is strongly -recommended and may become mandatory in a later version. This -determines whether changes are automatically committed to the -database when executed, or need to be explicitly committed later. -.PP -The \s-1DBI\s0 allows an application to \*(L"prepare\*(R" statements for later -execution. A prepared statement is identified by a statement handle -held in a Perl variable. -We'll call the Perl variable \f(CW$sth\fR in our examples. -.PP -The typical method call sequence for a \f(CW\*(C`SELECT\*(C'\fR statement is: -.PP -.Vb 4 -\& prepare, -\& execute, fetch, fetch, ... -\& execute, fetch, fetch, ... -\& execute, fetch, fetch, ... -.Ve -.PP -for example: -.PP -.Vb 1 -\& $sth = $dbh\->prepare("SELECT foo, bar FROM table WHERE baz=?"); -\& -\& $sth\->execute( $baz ); -\& -\& while ( @row = $sth\->fetchrow_array ) { -\& print "@row\en"; -\& } -.Ve -.PP -The typical method call sequence for a \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR statement is: -.PP -.Vb 4 -\& prepare, -\& execute, -\& execute, -\& execute. -.Ve -.PP -for example: -.PP -.Vb 1 -\& $sth = $dbh\->prepare("INSERT INTO table(foo,bar,baz) VALUES (?,?,?)"); -\& -\& while() { -\& chomp; -\& my ($foo,$bar,$baz) = split /,/; -\& $sth\->execute( $foo, $bar, $baz ); -\& } -.Ve -.PP -The \f(CW\*(C`do()\*(C'\fR method can be used for non repeated \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR statement -(or with drivers that don't support placeholders): -.PP -.Vb 1 -\& $rows_affected = $dbh\->do("UPDATE your_table SET foo = foo + 1"); -.Ve -.PP -To commit your changes to the database (when \*(L"AutoCommit\*(R" is off): -.PP -.Vb 1 -\& $dbh\->commit; # or call $dbh\->rollback; to undo changes -.Ve -.PP -Finally, when you have finished working with the data source, you should -\&\*(L"disconnect\*(R" from it: -.PP -.Vb 1 -\& $dbh\->disconnect; -.Ve -.SS "General Interface Rules & Caveats" -.IX Subsection "General Interface Rules & Caveats" -The \s-1DBI\s0 does not have a concept of a \*(L"current session\*(R". Every session -has a handle object (i.e., a \f(CW$dbh\fR) returned from the \f(CW\*(C`connect\*(C'\fR method. -That handle object is used to invoke database related methods. -.PP -Most data is returned to the Perl script as strings. (Null values are -returned as \f(CW\*(C`undef\*(C'\fR.) This allows arbitrary precision numeric data to be -handled without loss of accuracy. Beware that Perl may not preserve -the same accuracy when the string is used as a number. -.PP -Dates and times are returned as character strings in the current -default format of the corresponding database engine. Time zone effects -are database/driver dependent. -.PP -Perl supports binary data in Perl strings, and the \s-1DBI\s0 will pass binary -data to and from the driver without change. It is up to the driver -implementors to decide how they wish to handle such binary data. -.PP -Perl supports two kinds of strings: Unicode (utf8 internally) and non-Unicode -(defaults to iso\-8859\-1 if forced to assume an encoding). Drivers should -accept both kinds of strings and, if required, convert them to the character -set of the database being used. Similarly, when fetching from the database -character data that isn't iso\-8859\-1 the driver should convert it into utf8. -.PP -Multiple \s-1SQL\s0 statements may not be combined in a single statement -handle (\f(CW$sth\fR), although some databases and drivers do support this -(notably Sybase and \s-1SQL\s0 Server). -.PP -Non-sequential record reads are not supported in this version of the \s-1DBI.\s0 -In other words, records can only be fetched in the order that the -database returned them, and once fetched they are forgotten. -.PP -Positioned updates and deletes are not directly supported by the \s-1DBI.\s0 -See the description of the \f(CW\*(C`CursorName\*(C'\fR attribute for an alternative. -.PP -Individual driver implementors are free to provide any private -functions and/or handle attributes that they feel are useful. -Private driver functions can be invoked using the \s-1DBI \s0\f(CW\*(C`func()\*(C'\fR method. -Private driver attributes are accessed just like standard attributes. -.PP -Many methods have an optional \f(CW\*(C`\e%attr\*(C'\fR parameter which can be used to -pass information to the driver implementing the method. Except where -specifically documented, the \f(CW\*(C`\e%attr\*(C'\fR parameter can only be used to pass -driver specific hints. In general, you can ignore \f(CW\*(C`\e%attr\*(C'\fR parameters -or pass it as \f(CW\*(C`undef\*(C'\fR. -.SS "Naming Conventions and Name Space" -.IX Subsection "Naming Conventions and Name Space" -The \s-1DBI\s0 package and all packages below it (\f(CW\*(C`DBI::*\*(C'\fR) are reserved for -use by the \s-1DBI.\s0 Extensions and related modules use the \f(CW\*(C`DBIx::\*(C'\fR -namespace (see ). -Package names beginning with \f(CW\*(C`DBD::\*(C'\fR are reserved for use -by \s-1DBI\s0 database drivers. All environment variables used by the \s-1DBI\s0 -or by individual DBDs begin with "\f(CW\*(C`DBI_\*(C'\fR\*(L" or \*(R"\f(CW\*(C`DBD_\*(C'\fR". -.PP -The letter case used for attribute names is significant and plays an -important part in the portability of \s-1DBI\s0 scripts. The case of the -attribute name is used to signify who defined the meaning of that name -and its values. -.PP -.Vb 5 -\& Case of name Has a meaning defined by -\& \-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- -\& UPPER_CASE Standards, e.g., X/Open, ISO SQL92 etc (portable) -\& MixedCase DBI API (portable), underscores are not used. -\& lower_case Driver or database engine specific (non\-portable) -.Ve -.PP -It is of the utmost importance that Driver developers only use -lowercase attribute names when defining private attributes. Private -attribute names must be prefixed with the driver name or suitable -abbreviation (e.g., "\f(CW\*(C`ora_\*(C'\fR\*(L" for Oracle, \*(R"\f(CW\*(C`ing_\*(C'\fR" for Ingres, etc). -.SS "\s-1SQL \- A\s0 Query Language" -.IX Subsection "SQL - A Query Language" -Most \s-1DBI\s0 drivers require applications to use a dialect of \s-1SQL -\&\s0(Structured Query Language) to interact with the database engine. -The \*(L"Standards Reference Information\*(R" section provides links -to useful information about \s-1SQL.\s0 -.PP -The \s-1DBI\s0 itself does not mandate or require any particular language to -be used; it is language independent. In \s-1ODBC\s0 terms, the \s-1DBI\s0 is in -\&\*(L"pass-thru\*(R" mode, although individual drivers might not be. The only requirement -is that queries and other statements must be expressed as a single -string of characters passed as the first argument to the \*(L"prepare\*(R" or -\&\*(L"do\*(R" methods. -.PP -For an interesting diversion on the \fIreal\fR history of \s-1RDBMS\s0 and \s-1SQL,\s0 -from the people who made it happen, see: -.PP -.Vb 1 -\& http://www.mcjones.org/System_R/SQL_Reunion_95/sqlr95.html -.Ve -.PP -Follow the \*(L"Full Contents\*(R" then \*(L"Intergalactic dataspeak\*(R" links for the -\&\s-1SQL\s0 history. -.SS "Placeholders and Bind Values" -.IX Subsection "Placeholders and Bind Values" -Some drivers support placeholders and bind values. -\&\fIPlaceholders\fR, also called parameter markers, are used to indicate -values in a database statement that will be supplied later, -before the prepared statement is executed. For example, an application -might use the following to insert a row of data into the \s-1SALES\s0 table: -.PP -.Vb 1 -\& INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?) -.Ve -.PP -or the following, to select the description for a product: -.PP -.Vb 1 -\& SELECT description FROM products WHERE product_code = ? -.Ve -.PP -The \f(CW\*(C`?\*(C'\fR characters are the placeholders. The association of actual -values with placeholders is known as \fIbinding\fR, and the values are -referred to as \fIbind values\fR. -Note that the \f(CW\*(C`?\*(C'\fR is not enclosed in quotation marks, even when the -placeholder represents a string. -.PP -Some drivers also allow placeholders like \f(CW\*(C`:\*(C'\fR\fIname\fR and \f(CW\*(C`:\*(C'\fR\fIN\fR (e.g., -\&\f(CW\*(C`:1\*(C'\fR, \f(CW\*(C`:2\*(C'\fR, and so on) in addition to \f(CW\*(C`?\*(C'\fR, but their use is not portable. -.PP -If the \f(CW\*(C`:\*(C'\fR\fIN\fR form of placeholder is supported by the driver you're using, -then you should be able to use either \*(L"bind_param\*(R" or \*(L"execute\*(R" to bind -values. Check your driver documentation. -.PP -Some drivers allow you to prevent the recognition of a placeholder by placing a -single backslash character (\f(CW\*(C`\e\*(C'\fR) immediately before it. The driver will remove -the backslash character and ignore the placeholder, passing it unchanged to the -backend. If the driver supports this then \*(L"get_info\*(R"(9000) will return true. -.PP -With most drivers, placeholders can't be used for any element of a -statement that would prevent the database server from validating the -statement and creating a query execution plan for it. For example: -.PP -.Vb 2 -\& "SELECT name, age FROM ?" # wrong (will probably fail) -\& "SELECT name, ? FROM people" # wrong (but may not \*(Aqfail\*(Aq) -.Ve -.PP -Also, placeholders can only represent single scalar values. -For example, the following -statement won't work as expected for more than one value: -.PP -.Vb 2 -\& "SELECT name, age FROM people WHERE name IN (?)" # wrong -\& "SELECT name, age FROM people WHERE name IN (?,?)" # two names -.Ve -.PP -When using placeholders with the \s-1SQL \s0\f(CW\*(C`LIKE\*(C'\fR qualifier, you must -remember that the placeholder substitutes for the whole string. -So you should use "\f(CW\*(C`... LIKE ? ...\*(C'\fR" and include any wildcard -characters in the value that you bind to the placeholder. -.PP -\&\fB\s-1NULL\s0 Values\fR -.PP -Undefined values, or \f(CW\*(C`undef\*(C'\fR, are used to indicate \s-1NULL\s0 values. -You can insert and update columns with a \s-1NULL\s0 value as you would a -non-NULL value. These examples insert and update the column -\&\f(CW\*(C`age\*(C'\fR with a \s-1NULL\s0 value: -.PP -.Vb 4 -\& $sth = $dbh\->prepare(qq{ -\& INSERT INTO people (fullname, age) VALUES (?, ?) -\& }); -\& $sth\->execute("Joe Bloggs", undef); -\& -\& $sth = $dbh\->prepare(qq{ -\& UPDATE people SET age = ? WHERE fullname = ? -\& }); -\& $sth\->execute(undef, "Joe Bloggs"); -.Ve -.PP -However, care must be taken when trying to use \s-1NULL\s0 values in a -\&\f(CW\*(C`WHERE\*(C'\fR clause. Consider: -.PP -.Vb 1 -\& SELECT fullname FROM people WHERE age = ? -.Ve -.PP -Binding an \f(CW\*(C`undef\*(C'\fR (\s-1NULL\s0) to the placeholder will \fInot\fR select rows -which have a \s-1NULL \s0\f(CW\*(C`age\*(C'\fR! At least for database engines that -conform to the \s-1SQL\s0 standard. Refer to the \s-1SQL\s0 manual for your database -engine or any \s-1SQL\s0 book for the reasons for this. To explicitly select -NULLs you have to say "\f(CW\*(C`WHERE age IS NULL\*(C'\fR". -.PP -A common issue is to have a code fragment handle a value that could be -either \f(CW\*(C`defined\*(C'\fR or \f(CW\*(C`undef\*(C'\fR (non-NULL or \s-1NULL\s0) at runtime. -A simple technique is to prepare the appropriate statement as needed, -and substitute the placeholder for non-NULL cases: -.PP -.Vb 5 -\& $sql_clause = defined $age? "age = ?" : "age IS NULL"; -\& $sth = $dbh\->prepare(qq{ -\& SELECT fullname FROM people WHERE $sql_clause -\& }); -\& $sth\->execute(defined $age ? $age : ()); -.Ve -.PP -The following technique illustrates qualifying a \f(CW\*(C`WHERE\*(C'\fR clause with -several columns, whose associated values (\f(CW\*(C`defined\*(C'\fR or \f(CW\*(C`undef\*(C'\fR) are -in a hash \f(CW%h:\fR -.PP -.Vb 10 -\& for my $col ("age", "phone", "email") { -\& if (defined $h{$col}) { -\& push @sql_qual, "$col = ?"; -\& push @sql_bind, $h{$col}; -\& } -\& else { -\& push @sql_qual, "$col IS NULL"; -\& } -\& } -\& $sql_clause = join(" AND ", @sql_qual); -\& $sth = $dbh\->prepare(qq{ -\& SELECT fullname FROM people WHERE $sql_clause -\& }); -\& $sth\->execute(@sql_bind); -.Ve -.PP -The techniques above call prepare for the \s-1SQL\s0 statement with each call to -execute. Because calls to \fIprepare()\fR can be expensive, performance -can suffer when an application iterates many times over statements -like the above. -.PP -A better solution is a single \f(CW\*(C`WHERE\*(C'\fR clause that supports both -\&\s-1NULL\s0 and non-NULL comparisons. Its \s-1SQL\s0 statement would need to be -prepared only once for all cases, thus improving performance. -Several examples of \f(CW\*(C`WHERE\*(C'\fR clauses that support this are presented -below. But each example lacks portability, robustness, or simplicity. -Whether an example is supported on your database engine depends on -what \s-1SQL\s0 extensions it provides, and where it supports the \f(CW\*(C`?\*(C'\fR -placeholder in a statement. -.PP -.Vb 7 -\& 0) age = ? -\& 1) NVL(age, xx) = NVL(?, xx) -\& 2) ISNULL(age, xx) = ISNULL(?, xx) -\& 3) DECODE(age, ?, 1, 0) = 1 -\& 4) age = ? OR (age IS NULL AND ? IS NULL) -\& 5) age = ? OR (age IS NULL AND SP_ISNULL(?) = 1) -\& 6) age = ? OR (age IS NULL AND ? = 1) -.Ve -.PP -Statements formed with the above \f(CW\*(C`WHERE\*(C'\fR clauses require execute -statements as follows. The arguments are required, whether their -values are \f(CW\*(C`defined\*(C'\fR or \f(CW\*(C`undef\*(C'\fR. -.PP -.Vb 3 -\& 0,1,2,3) $sth\->execute($age); -\& 4,5) $sth\->execute($age, $age); -\& 6) $sth\->execute($age, defined($age) ? 0 : 1); -.Ve -.PP -Example 0 should not work (as mentioned earlier), but may work on -a few database engines anyway (e.g. Sybase). Example 0 is part -of examples 4, 5, and 6, so if example 0 works, these other -examples may work, even if the engine does not properly support -the right hand side of the \f(CW\*(C`OR\*(C'\fR expression. -.PP -Examples 1 and 2 are not robust: they require that you provide a -valid column value xx (e.g. '~') which is not present in any row. -That means you must have some notion of what data won't be stored -in the column, and expect clients to adhere to that. -.PP -Example 5 requires that you provide a stored procedure (\s-1SP_ISNULL\s0 -in this example) that acts as a function: it checks whether a value -is null, and returns 1 if it is, or 0 if not. -.PP -Example 6, the least simple, is probably the most portable, i.e., it -should work with most, if not all, database engines. -.PP -Here is a table that indicates which examples above are known to -work on various database engines: -.PP -.Vb 10 -\& \-\-\-\-\-Examples\-\-\-\-\-\- -\& 0 1 2 3 4 5 6 -\& \- \- \- \- \- \- \- -\& Oracle 9 N Y N Y Y ? Y -\& Informix IDS 9 N N N Y N Y Y -\& MS SQL N N Y N Y ? Y -\& Sybase Y N N N N N Y -\& AnyData,DBM,CSV Y N N N Y Y* Y -\& SQLite 3.3 N N N N Y N N -\& MSAccess N N N N Y N Y -.Ve -.PP -* Works only because Example 0 works. -.PP -\&\s-1DBI\s0 provides a sample perl script that will test the examples above -on your database engine and tell you which ones work. It is located -in the \fIex/\fR subdirectory of the \s-1DBI\s0 source distribution, or here: - -Please use the script to help us fill-in and maintain this table. -.PP -\&\fBPerformance\fR -.PP -Without using placeholders, the insert statement shown previously would have to -contain the literal values to be inserted and would have to be -re-prepared and re-executed for each row. With placeholders, the insert -statement only needs to be prepared once. The bind values for each row -can be given to the \f(CW\*(C`execute\*(C'\fR method each time it's called. By avoiding -the need to re-prepare the statement for each row, the application -typically runs many times faster. Here's an example: -.PP -.Vb 9 -\& my $sth = $dbh\->prepare(q{ -\& INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?) -\& }) or die $dbh\->errstr; -\& while (<>) { -\& chomp; -\& my ($product_code, $qty, $price) = split /,/; -\& $sth\->execute($product_code, $qty, $price) or die $dbh\->errstr; -\& } -\& $dbh\->commit or die $dbh\->errstr; -.Ve -.PP -See \*(L"execute\*(R" and \*(L"bind_param\*(R" for more details. -.PP -The \f(CW\*(C`q{...}\*(C'\fR style quoting used in this example avoids clashing with -quotes that may be used in the \s-1SQL\s0 statement. Use the double-quote like -\&\f(CW\*(C`qq{...}\*(C'\fR operator if you want to interpolate variables into the string. -See \*(L"Quote and Quote-like Operators\*(R" in perlop for more details. -.PP -See also the \*(L"bind_columns\*(R" method, which is used to associate Perl -variables with the output columns of a \f(CW\*(C`SELECT\*(C'\fR statement. -.SH "THE DBI PACKAGE AND CLASS" -.IX Header "THE DBI PACKAGE AND CLASS" -In this section, we cover the \s-1DBI\s0 class methods, utility functions, -and the dynamic attributes associated with generic \s-1DBI\s0 handles. -.SS "\s-1DBI\s0 Constants" -.IX Subsection "DBI Constants" -Constants representing the values of the \s-1SQL\s0 standard types can be -imported individually by name, or all together by importing the -special \f(CW\*(C`:sql_types\*(C'\fR tag. -.PP -The names and values of all the defined \s-1SQL\s0 standard types can be -produced like this: -.PP -.Vb 3 -\& foreach (@{ $DBI::EXPORT_TAGS{sql_types} }) { -\& printf "%s=%d\en", $_, &{"DBI::$_"}; -\& } -.Ve -.PP -These constants are defined by \s-1SQL/CLI, ODBC\s0 or both. -\&\f(CW\*(C`SQL_BIGINT\*(C'\fR has conflicting codes in \s-1SQL/CLI\s0 and \s-1ODBC, -DBI\s0 uses the \s-1ODBC\s0 one. -.PP -See the \*(L"type_info\*(R", \*(L"type_info_all\*(R", and \*(L"bind_param\*(R" methods -for possible uses. -.PP -Note that just because the \s-1DBI\s0 defines a named constant for a given -data type doesn't mean that drivers will support that data type. -.SS "\s-1DBI\s0 Class Methods" -.IX Subsection "DBI Class Methods" -The following methods are provided by the \s-1DBI\s0 class: -.PP -\fI\f(CI\*(C`parse_dsn\*(C'\fI\fR -.IX Subsection "parse_dsn" -.PP -.Vb 2 -\& ($scheme, $driver, $attr_string, $attr_hash, $driver_dsn) = DBI\->parse_dsn($dsn) -\& or die "Can\*(Aqt parse DBI DSN \*(Aq$dsn\*(Aq"; -.Ve -.PP -Breaks apart a \s-1DBI\s0 Data Source Name (\s-1DSN\s0) and returns the individual -parts. If \f(CW$dsn\fR doesn't contain a valid \s-1DSN\s0 then \fIparse_dsn()\fR returns -an empty list. -.PP -\&\f(CW$scheme\fR is the first part of the \s-1DSN\s0 and is currently always 'dbi'. -\&\f(CW$driver\fR is the driver name, possibly defaulted to \f(CW$ENV\fR{\s-1DBI_DRIVER\s0}, -and may be undefined. \f(CW$attr_string\fR is the contents of the optional attribute -string, which may be undefined. If \f(CW$attr_string\fR is not empty then \f(CW$attr_hash\fR -is a reference to a hash containing the parsed attribute names and values. -\&\f(CW$driver_dsn\fR is the last part of the \s-1DBI DSN\s0 string. For example: -.PP -.Vb 7 -\& ($scheme, $driver, $attr_string, $attr_hash, $driver_dsn) -\& = DBI\->parse_dsn("dbi:MyDriver(RaiseError=>1):db=test;port=42"); -\& $scheme = \*(Aqdbi\*(Aq; -\& $driver = \*(AqMyDriver\*(Aq; -\& $attr_string = \*(AqRaiseError=>1\*(Aq; -\& $attr_hash = { \*(AqRaiseError\*(Aq => \*(Aq1\*(Aq }; -\& $driver_dsn = \*(Aqdb=test;port=42\*(Aq; -.Ve -.PP -The \fIparse_dsn()\fR method was added in \s-1DBI 1.43.\s0 -.PP -\fI\f(CI\*(C`connect\*(C'\fI\fR -.IX Subsection "connect" -.PP -.Vb 4 -\& $dbh = DBI\->connect($data_source, $username, $password) -\& or die $DBI::errstr; -\& $dbh = DBI\->connect($data_source, $username, $password, \e%attr) -\& or die $DBI::errstr; -.Ve -.PP -Establishes a database connection, or session, to the requested \f(CW$data_source\fR. -Returns a database handle object if the connection succeeds. Use -\&\f(CW\*(C`$dbh\->disconnect\*(C'\fR to terminate the connection. -.PP -If the connect fails (see below), it returns \f(CW\*(C`undef\*(C'\fR and sets both \f(CW$DBI::err\fR -and \f(CW$DBI::errstr\fR. (It does \fInot\fR explicitly set \f(CW$!\fR.) You should generally -test the return status of \f(CW\*(C`connect\*(C'\fR and \f(CW\*(C`print $DBI::errstr\*(C'\fR if it has failed. -.PP -Multiple simultaneous connections to multiple databases through multiple -drivers can be made via the \s-1DBI.\s0 Simply make one \f(CW\*(C`connect\*(C'\fR call for each -database and keep a copy of each returned database handle. -.PP -The \f(CW$data_source\fR value must begin with "\f(CW\*(C`dbi:\*(C'\fR\fIdriver_name\fR\f(CW\*(C`:\*(C'\fR". -The \fIdriver_name\fR specifies the driver that will be used to make the -connection. (Letter case is significant.) -.PP -As a convenience, if the \f(CW$data_source\fR parameter is undefined or empty, -the \s-1DBI\s0 will substitute the value of the environment variable \f(CW\*(C`DBI_DSN\*(C'\fR. -If just the \fIdriver_name\fR part is empty (i.e., the \f(CW$data_source\fR -prefix is "\f(CW\*(C`dbi::\*(C'\fR"), the environment variable \f(CW\*(C`DBI_DRIVER\*(C'\fR is -used. If neither variable is set, then \f(CW\*(C`connect\*(C'\fR dies. -.PP -Examples of \f(CW$data_source\fR values are: -.PP -.Vb 3 -\& dbi:DriverName:database_name -\& dbi:DriverName:database_name@hostname:port -\& dbi:DriverName:database=database_name;host=hostname;port=port -.Ve -.PP -There is \fIno standard\fR for the text following the driver name. Each -driver is free to use whatever syntax it wants. The only requirement the -\&\s-1DBI\s0 makes is that all the information is supplied in a single string. -You must consult the documentation for the drivers you are using for a -description of the syntax they require. -.PP -It is recommended that drivers support the \s-1ODBC\s0 style, shown in the -last example above. It is also recommended that they support the -three common names '\f(CW\*(C`host\*(C'\fR', '\f(CW\*(C`port\*(C'\fR', and '\f(CW\*(C`database\*(C'\fR' (plus '\f(CW\*(C`db\*(C'\fR' -as an alias for \f(CW\*(C`database\*(C'\fR). This simplifies automatic construction -of basic DSNs: \f(CW"dbi:$driver:database=$db;host=$host;port=$port"\fR. -Drivers should aim to 'do something reasonable' when given a \s-1DSN\s0 -in this form, but if any part is meaningless for that driver (such -as 'port' for Informix) it should generate an error if that part -is not empty. -.PP -If the environment variable \f(CW\*(C`DBI_AUTOPROXY\*(C'\fR is defined (and the -driver in \f(CW$data_source\fR is not "\f(CW\*(C`Proxy\*(C'\fR") then the connect request -will automatically be changed to: -.PP -.Vb 1 -\& $ENV{DBI_AUTOPROXY};dsn=$data_source -.Ve -.PP -\&\f(CW\*(C`DBI_AUTOPROXY\*(C'\fR is typically set as "\f(CW\*(C`dbi:Proxy:hostname=...;port=...\*(C'\fR". -If \f(CW$ENV\fR{\s-1DBI_AUTOPROXY\s0} doesn't begin with '\f(CW\*(C`dbi:\*(C'\fR' then \*(L"dbi:Proxy:\*(R" -will be prepended to it first. See the DBD::Proxy documentation -for more details. -.PP -If \f(CW$username\fR or \f(CW$password\fR are undefined (rather than just empty), -then the \s-1DBI\s0 will substitute the values of the \f(CW\*(C`DBI_USER\*(C'\fR and \f(CW\*(C`DBI_PASS\*(C'\fR -environment variables, respectively. The \s-1DBI\s0 will warn if the -environment variables are not defined. However, the everyday use -of these environment variables is not recommended for security -reasons. The mechanism is primarily intended to simplify testing. -See below for alternative way to specify the username and password. -.PP -\&\f(CW\*(C`DBI\->connect\*(C'\fR automatically installs the driver if it has not been -installed yet. Driver installation either returns a valid driver -handle, or it \fIdies\fR with an error message that includes the string -"\f(CW\*(C`install_driver\*(C'\fR" and the underlying problem. So \f(CW\*(C`DBI\->connect\*(C'\fR -will die -on a driver installation failure and will only return \f(CW\*(C`undef\*(C'\fR on a -connect failure, in which case \f(CW$DBI::errstr\fR will hold the error message. -Use \f(CW\*(C`eval\*(C'\fR if you need to catch the "\f(CW\*(C`install_driver\*(C'\fR" error. -.PP -The \f(CW$data_source\fR argument (with the "\f(CW\*(C`dbi:...:\*(C'\fR" prefix removed) and the -\&\f(CW$username\fR and \f(CW$password\fR arguments are then passed to the driver for -processing. The \s-1DBI\s0 does not define any interpretation for the -contents of these fields. The driver is free to interpret the -\&\f(CW$data_source\fR, \f(CW$username\fR, and \f(CW$password\fR fields in any way, and supply -whatever defaults are appropriate for the engine being accessed. -(Oracle, for example, uses the \s-1ORACLE_SID\s0 and \s-1TWO_TASK\s0 environment -variables if no \f(CW$data_source\fR is specified.) -.PP -The \f(CW\*(C`AutoCommit\*(C'\fR and \f(CW\*(C`PrintError\*(C'\fR attributes for each connection -default to \*(L"on\*(R". (See \*(L"AutoCommit\*(R" and \*(L"PrintError\*(R" for more information.) -However, it is strongly recommended that you explicitly define \f(CW\*(C`AutoCommit\*(C'\fR -rather than rely on the default. The \f(CW\*(C`PrintWarn\*(C'\fR attribute defaults to true. -.PP -The \f(CW\*(C`\e%attr\*(C'\fR parameter can be used to alter the default settings of -\&\f(CW\*(C`PrintError\*(C'\fR, \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`AutoCommit\*(C'\fR, and other attributes. For example: -.PP -.Vb 4 -\& $dbh = DBI\->connect($data_source, $user, $pass, { -\& PrintError => 0, -\& AutoCommit => 0 -\& }); -.Ve -.PP -The username and password can also be specified using the attributes -\&\f(CW\*(C`Username\*(C'\fR and \f(CW\*(C`Password\*(C'\fR, in which case they take precedence -over the \f(CW$username\fR and \f(CW$password\fR parameters. -.PP -You can also define connection attribute values within the \f(CW$data_source\fR -parameter. For example: -.PP -.Vb 1 -\& dbi:DriverName(PrintWarn=>0,PrintError=>0,Taint=>1):... -.Ve -.PP -Individual attributes values specified in this way take precedence over -any conflicting values specified via the \f(CW\*(C`\e%attr\*(C'\fR parameter to \f(CW\*(C`connect\*(C'\fR. -.PP -The \f(CW\*(C`dbi_connect_method\*(C'\fR attribute can be used to specify which driver -method should be called to establish the connection. The only useful -values are 'connect', 'connect_cached', or some specialized case like -\&'Apache::DBI::connect' (which is automatically the default when running -within Apache). -.PP -Where possible, each session (\f(CW$dbh\fR) is independent from the transactions -in other sessions. This is useful when you need to hold cursors open -across transactions\*(--for example, if you use one session for your long lifespan -cursors (typically read-only) and another for your short update -transactions. -.PP -For compatibility with old \s-1DBI\s0 scripts, the driver can be specified by -passing its name as the fourth argument to \f(CW\*(C`connect\*(C'\fR (instead of \f(CW\*(C`\e%attr\*(C'\fR): -.PP -.Vb 1 -\& $dbh = DBI\->connect($data_source, $user, $pass, $driver); -.Ve -.PP -In this \*(L"old-style\*(R" form of \f(CW\*(C`connect\*(C'\fR, the \f(CW$data_source\fR should not start -with "\f(CW\*(C`dbi:driver_name:\*(C'\fR". (If it does, the embedded driver_name -will be ignored). Also note that in this older form of \f(CW\*(C`connect\*(C'\fR, -the \f(CW\*(C`$dbh\->{AutoCommit}\*(C'\fR attribute is \fIundefined\fR, the -\&\f(CW\*(C`$dbh\->{PrintError}\*(C'\fR attribute is off, and the old \f(CW\*(C`DBI_DBNAME\*(C'\fR -environment variable is -checked if \f(CW\*(C`DBI_DSN\*(C'\fR is not defined. Beware that this \*(L"old-style\*(R" -\&\f(CW\*(C`connect\*(C'\fR will soon be withdrawn in a future version of \s-1DBI.\s0 -.PP -\fI\f(CI\*(C`connect_cached\*(C'\fI\fR -.IX Subsection "connect_cached" -.PP -.Vb 4 -\& $dbh = DBI\->connect_cached($data_source, $username, $password) -\& or die $DBI::errstr; -\& $dbh = DBI\->connect_cached($data_source, $username, $password, \e%attr) -\& or die $DBI::errstr; -.Ve -.PP -\&\f(CW\*(C`connect_cached\*(C'\fR is like \*(L"connect\*(R", except that the database handle -returned is also -stored in a hash associated with the given parameters. If another call -is made to \f(CW\*(C`connect_cached\*(C'\fR with the same parameter values, then the -corresponding cached \f(CW$dbh\fR will be returned if it is still valid. -The cached database handle is replaced with a new connection if it -has been disconnected or if the \f(CW\*(C`ping\*(C'\fR method fails. -.PP -Note that the behaviour of this method differs in several respects from the -behaviour of persistent connections implemented by Apache::DBI. -However, if Apache::DBI is loaded then \f(CW\*(C`connect_cached\*(C'\fR will use it. -.PP -Caching connections can be useful in some applications, but it can -also cause problems, such as too many connections, and so should -be used with care. In particular, avoid changing the attributes of -a database handle created via \fIconnect_cached()\fR because it will affect -other code that may be using the same handle. When \fIconnect_cached()\fR -returns a handle the attributes will be reset to their initial values. -This can cause problems, especially with the \f(CW\*(C`AutoCommit\*(C'\fR attribute. -.PP -Also, to ensure that the attributes passed are always the same, avoid passing -references inline. For example, the \f(CW\*(C`Callbacks\*(C'\fR attribute is specified as a -hash reference. Be sure to declare it external to the call to -\&\fIconnect_cached()\fR, such that the hash reference is not re-created on every -call. A package-level lexical works well: -.PP -.Vb 4 -\& package MyDBH; -\& my $cb = { -\& \*(Aqconnect_cached.reused\*(Aq => sub { delete $_[4]\->{AutoCommit} }, -\& }; -\& -\& sub dbh { -\& DBI\->connect_cached( $dsn, $username, $auth, { Callbacks => $cb }); -\& } -.Ve -.PP -Where multiple separate parts of a program are using \fIconnect_cached()\fR -to connect to the same database with the same (initial) attributes -it is a good idea to add a private attribute to the \fIconnect_cached()\fR -call to effectively limit the scope of the caching. For example: -.PP -.Vb 1 -\& DBI\->connect_cached(..., { private_foo_cachekey => "Bar", ... }); -.Ve -.PP -Handles returned from that \fIconnect_cached()\fR call will only be returned -by other \fIconnect_cached()\fR call elsewhere in the code if those other -calls also pass in the same attribute values, including the private one. -(I've used \f(CW\*(C`private_foo_cachekey\*(C'\fR here as an example, you can use -any attribute name with a \f(CW\*(C`private_\*(C'\fR prefix.) -.PP -Taking that one step further, you can limit a particular \fIconnect_cached()\fR -call to return handles unique to that one place in the code by setting the -private attribute to a unique value for that place: -.PP -.Vb 1 -\& DBI\->connect_cached(..., { private_foo_cachekey => _\|_FILE_\|_._\|_LINE_\|_, ... }); -.Ve -.PP -By using a private attribute you still get connection caching for -the individual calls to \fIconnect_cached()\fR but, by making separate -database connections for separate parts of the code, the database -handles are isolated from any attribute changes made to other handles. -.PP -The cache can be accessed (and cleared) via the \*(L"CachedKids\*(R" attribute: -.PP -.Vb 2 -\& my $CachedKids_hashref = $dbh\->{Driver}\->{CachedKids}; -\& %$CachedKids_hashref = () if $CachedKids_hashref; -.Ve -.PP -\fI\f(CI\*(C`available_drivers\*(C'\fI\fR -.IX Subsection "available_drivers" -.PP -.Vb 2 -\& @ary = DBI\->available_drivers; -\& @ary = DBI\->available_drivers($quiet); -.Ve -.PP -Returns a list of all available drivers by searching for \f(CW\*(C`DBD::*\*(C'\fR modules -through the directories in \f(CW@INC\fR. By default, a warning is given if -some drivers are hidden by others of the same name in earlier -directories. Passing a true value for \f(CW$quiet\fR will inhibit the warning. -.PP -\fI\f(CI\*(C`installed_drivers\*(C'\fI\fR -.IX Subsection "installed_drivers" -.PP -.Vb 1 -\& %drivers = DBI\->installed_drivers(); -.Ve -.PP -Returns a list of driver name and driver handle pairs for all drivers -\&'installed' (loaded) into the current process. The driver name does not -include the '\s-1DBD::\s0' prefix. -.PP -To get a list of all drivers available in your perl installation you can use -\&\*(L"available_drivers\*(R". -.PP -Added in \s-1DBI 1.49.\s0 -.PP -\fI\f(CI\*(C`installed_versions\*(C'\fI\fR -.IX Subsection "installed_versions" -.PP -.Vb 3 -\& DBI\->installed_versions; -\& @ary = DBI\->installed_versions; -\& $hash = DBI\->installed_versions; -.Ve -.PP -Calls \fIavailable_drivers()\fR and attempts to load each of them in turn -using \fIinstall_driver()\fR. For each load that succeeds the driver -name and version number are added to a hash. When running under -DBI::PurePerl drivers which appear not be pure-perl are ignored. -.PP -When called in array context the list of successfully loaded drivers -is returned (without the '\s-1DBD::\s0' prefix). -.PP -When called in scalar context an extra entry for the \f(CW\*(C`DBI\*(C'\fR is added (and -\&\f(CW\*(C`DBI::PurePerl\*(C'\fR if appropriate) and a reference to the hash is returned. -.PP -When called in a void context the \fIinstalled_versions()\fR method will -print out a formatted list of the hash contents, one per line, along with some -other information about the \s-1DBI\s0 version and \s-1OS.\s0 -.PP -Due to the potentially high memory cost and unknown risks of loading -in an unknown number of drivers that just happen to be installed -on the system, this method is not recommended for general use. -Use \fIavailable_drivers()\fR instead. -.PP -The \fIinstalled_versions()\fR method is primarily intended as a quick -way to see from the command line what's installed. For example: -.PP -.Vb 1 -\& perl \-MDBI \-e \*(AqDBI\->installed_versions\*(Aq -.Ve -.PP -The \fIinstalled_versions()\fR method was added in \s-1DBI 1.38.\s0 -.PP -\fI\f(CI\*(C`data_sources\*(C'\fI\fR -.IX Subsection "data_sources" -.PP -.Vb 2 -\& @ary = DBI\->data_sources($driver); -\& @ary = DBI\->data_sources($driver, \e%attr); -.Ve -.PP -Returns a list of data sources (databases) available via the named -driver. If \f(CW$driver\fR is empty or \f(CW\*(C`undef\*(C'\fR, then the value of the -\&\f(CW\*(C`DBI_DRIVER\*(C'\fR environment variable is used. -.PP -The driver will be loaded if it hasn't been already. Note that if the -driver loading fails then \fIdata_sources()\fR \fIdies\fR with an error message -that includes the string "\f(CW\*(C`install_driver\*(C'\fR" and the underlying problem. -.PP -Data sources are returned in a form suitable for passing to the -\&\*(L"connect\*(R" method (that is, they will include the "\f(CW\*(C`dbi:$driver:\*(C'\fR" prefix). -.PP -Note that many drivers have no way of knowing what data sources might -be available for it. These drivers return an empty or incomplete list -or may require driver-specific attributes. -.PP -There is also a \fIdata_sources()\fR method defined for database handles. -.PP -\fI\f(CI\*(C`trace\*(C'\fI\fR -.IX Subsection "trace" -.PP -.Vb 4 -\& DBI\->trace($trace_setting) -\& DBI\->trace($trace_setting, $trace_filename) -\& DBI\->trace($trace_setting, $trace_filehandle) -\& $trace_setting = DBI\->trace; -.Ve -.PP -The \f(CW\*(C`DBI\->trace\*(C'\fR method sets the \fIglobal default\fR trace -settings and returns the \fIprevious\fR trace settings. It can also -be used to change where the trace output is sent. -.PP -There's a similar method, \f(CW\*(C`$h\->trace\*(C'\fR, which sets the trace -settings for the specific handle it's called on. -.PP -See the \*(L"\s-1TRACING\*(R"\s0 section for full details about the \s-1DBI\s0's powerful -tracing facilities. -.PP -\fI\f(CI\*(C`visit_handles\*(C'\fI\fR -.IX Subsection "visit_handles" -.PP -.Vb 2 -\& DBI\->visit_handles( $coderef ); -\& DBI\->visit_handles( $coderef, $info ); -.Ve -.PP -Where \f(CW$coderef\fR is a reference to a subroutine and \f(CW$info\fR is an arbitrary value -which, if undefined, defaults to a reference to an empty hash. Returns \f(CW$info\fR. -.PP -For each installed driver handle, if any, \f(CW$coderef\fR is invoked as: -.PP -.Vb 1 -\& $coderef\->($driver_handle, $info); -.Ve -.PP -If the execution of \f(CW$coderef\fR returns a true value then \*(L"visit_child_handles\*(R" -is called on that child handle and passed the returned value as \f(CW$info\fR. -.PP -For example: -.PP -.Vb 5 -\& my $info = $dbh\->{Driver}\->visit_child_handles(sub { -\& my ($h, $info) = @_; -\& ++$info\->{ $h\->{Type} }; # count types of handles (dr/db/st) -\& return $info; # visit kids -\& }); -.Ve -.PP -See also \*(L"visit_child_handles\*(R". -.SS "\s-1DBI\s0 Utility Functions" -.IX Subsection "DBI Utility Functions" -In addition to the \s-1DBI\s0 methods listed in the previous section, -the \s-1DBI\s0 package also provides several utility functions. -.PP -These can be imported into your code by listing them in -the \f(CW\*(C`use\*(C'\fR statement. For example: -.PP -.Vb 1 -\& use DBI qw(neat data_diff); -.Ve -.PP -Alternatively, all these utility functions (except hash) can be -imported using the \f(CW\*(C`:utils\*(C'\fR import tag. For example: -.PP -.Vb 1 -\& use DBI qw(:utils); -.Ve -.PP -\fI\f(CI\*(C`data_string_desc\*(C'\fI\fR -.IX Subsection "data_string_desc" -.PP -.Vb 1 -\& $description = data_string_desc($string); -.Ve -.PP -Returns an informal description of the string. For example: -.PP -.Vb 5 -\& UTF8 off, ASCII, 42 characters 42 bytes -\& UTF8 off, non\-ASCII, 42 characters 42 bytes -\& UTF8 on, non\-ASCII, 4 characters 6 bytes -\& UTF8 on but INVALID encoding, non\-ASCII, 4 characters 6 bytes -\& UTF8 off, undef -.Ve -.PP -The initial \f(CW\*(C`UTF8\*(C'\fR on/off refers to Perl's internal SvUTF8 flag. -If \f(CW$string\fR has the SvUTF8 flag set but the sequence of bytes it -contains are not a valid \s-1UTF\-8\s0 encoding then \fIdata_string_desc()\fR -will report \f(CW\*(C`UTF8 on but INVALID encoding\*(C'\fR. -.PP -The \f(CW\*(C`ASCII\*(C'\fR vs \f(CW\*(C`non\-ASCII\*(C'\fR portion shows \f(CW\*(C`ASCII\*(C'\fR if \fIall\fR the -characters in the string are \s-1ASCII \s0(have code points <= 127). -.PP -The \fIdata_string_desc()\fR function was added in \s-1DBI 1.46.\s0 -.PP -\fI\f(CI\*(C`data_string_diff\*(C'\fI\fR -.IX Subsection "data_string_diff" -.PP -.Vb 1 -\& $diff = data_string_diff($a, $b); -.Ve -.PP -Returns an informal description of the first character difference -between the strings. If both \f(CW$a\fR and \f(CW$b\fR contain the same sequence -of characters then \fIdata_string_diff()\fR returns an empty string. -For example: -.PP -.Vb 6 -\& Params a & b Result -\& \-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\- -\& \*(Aqaaa\*(Aq, \*(Aqaaa\*(Aq \*(Aq\*(Aq -\& \*(Aqaaa\*(Aq, \*(Aqabc\*(Aq \*(AqStrings differ at index 2: a[2]=a, b[2]=b\*(Aq -\& \*(Aqaaa\*(Aq, undef \*(AqString b is undef, string a has 3 characters\*(Aq -\& \*(Aqaaa\*(Aq, \*(Aqaa\*(Aq \*(AqString b truncated after 2 characters\*(Aq -.Ve -.PP -Unicode characters are reported in \f(CW\*(C`\ex{XXXX}\*(C'\fR format. Unicode -code points in the range U+0800 to U+08FF are unassigned and most -likely to occur due to double-encoding. Characters in this range -are reported as \f(CW\*(C`\ex{08XX}=\*(AqC\*(Aq\*(C'\fR where \f(CW\*(C`C\*(C'\fR is the corresponding -latin\-1 character. -.PP -The \fIdata_string_diff()\fR function only considers logical \fIcharacters\fR -and not the underlying encoding. See \*(L"data_diff\*(R" for an alternative. -.PP -The \fIdata_string_diff()\fR function was added in \s-1DBI 1.46.\s0 -.PP -\fI\f(CI\*(C`data_diff\*(C'\fI\fR -.IX Subsection "data_diff" -.PP -.Vb 2 -\& $diff = data_diff($a, $b); -\& $diff = data_diff($a, $b, $logical); -.Ve -.PP -Returns an informal description of the difference between two strings. -It calls \*(L"data_string_desc\*(R" and \*(L"data_string_diff\*(R" -and returns the combined results as a multi-line string. -.PP -For example, \f(CW\*(C`data_diff("abc", "ab\ex{263a}")\*(C'\fR will return: -.PP -.Vb 3 -\& a: UTF8 off, ASCII, 3 characters 3 bytes -\& b: UTF8 on, non\-ASCII, 3 characters 5 bytes -\& Strings differ at index 2: a[2]=c, b[2]=\ex{263A} -.Ve -.PP -If \f(CW$a\fR and \f(CW$b\fR are identical in both the characters they contain \fIand\fR -their physical encoding then \fIdata_diff()\fR returns an empty string. -If \f(CW$logical\fR is true then physical encoding differences are ignored -(but are still reported if there is a difference in the characters). -.PP -The \fIdata_diff()\fR function was added in \s-1DBI 1.46.\s0 -.PP -\fI\f(CI\*(C`neat\*(C'\fI\fR -.IX Subsection "neat" -.PP -.Vb 2 -\& $str = neat($value); -\& $str = neat($value, $maxlen); -.Ve -.PP -Return a string containing a neat (and tidy) representation of the -supplied value. -.PP -Strings will be quoted, although internal quotes will \fInot\fR be escaped. -Values known to be numeric will be unquoted. Undefined (\s-1NULL\s0) values -will be shown as \f(CW\*(C`undef\*(C'\fR (without quotes). -.PP -If the string is flagged internally as utf8 then double quotes will -be used, otherwise single quotes are used and unprintable characters -will be replaced by dot (.). -.PP -For result strings longer than \f(CW$maxlen\fR the result string will be -truncated to \f(CW\*(C`$maxlen\-4\*(C'\fR and "\f(CW\*(C`...\*(Aq\*(C'\fR" will be appended. If \f(CW$maxlen\fR is 0 -or \f(CW\*(C`undef\*(C'\fR, it defaults to \f(CW$DBI::neat_maxlen\fR which, in turn, defaults to 400. -.PP -This function is designed to format values for human consumption. -It is used internally by the \s-1DBI\s0 for \*(L"trace\*(R" output. It should -typically \fInot\fR be used for formatting values for database use. -(See also \*(L"quote\*(R".) -.PP -\fI\f(CI\*(C`neat_list\*(C'\fI\fR -.IX Subsection "neat_list" -.PP -.Vb 1 -\& $str = neat_list(\e@listref, $maxlen, $field_sep); -.Ve -.PP -Calls \f(CW\*(C`neat\*(C'\fR on each element of the list and returns a string -containing the results joined with \f(CW$field_sep\fR. \f(CW$field_sep\fR defaults -to \f(CW", "\fR. -.PP -\fI\f(CI\*(C`looks_like_number\*(C'\fI\fR -.IX Subsection "looks_like_number" -.PP -.Vb 1 -\& @bool = looks_like_number(@array); -.Ve -.PP -Returns true for each element that looks like a number. -Returns false for each element that does not look like a number. -Returns \f(CW\*(C`undef\*(C'\fR for each element that is undefined or empty. -.PP -\fI\f(CI\*(C`hash\*(C'\fI\fR -.IX Subsection "hash" -.PP -.Vb 1 -\& $hash_value = DBI::hash($buffer, $type); -.Ve -.PP -Return a 32\-bit integer 'hash' value corresponding to the contents of \f(CW$buffer\fR. -The \f(CW$type\fR parameter selects which kind of hash algorithm should be used. -.PP -For the technically curious, type 0 (which is the default if \f(CW$type\fR -isn't specified) is based on the Perl 5.1 hash except that the value -is forced to be negative (for obscure historical reasons). -Type 1 is the better \*(L"Fowler / Noll / Vo\*(R" (\s-1FNV\s0) hash. See - for more information. -Both types are implemented in C and are very fast. -.PP -This function doesn't have much to do with databases, except that -it can sometimes be handy to store such values in a database. -It also doesn't have much to do with perl hashes, like \f(CW%foo\fR. -.PP -\fI\f(CI\*(C`sql_type_cast\*(C'\fI\fR -.IX Subsection "sql_type_cast" -.PP -.Vb 1 -\& $sts = DBI::sql_type_cast($sv, $sql_type, $flags); -.Ve -.PP -sql_type_cast attempts to cast \f(CW$sv\fR to the \s-1SQL\s0 type (see \s-1DBI\s0 -Constants) specified in \f(CW$sql_type\fR. At present only the \s-1SQL\s0 types -\&\f(CW\*(C`SQL_INTEGER\*(C'\fR, \f(CW\*(C`SQL_DOUBLE\*(C'\fR and \f(CW\*(C`SQL_NUMERIC\*(C'\fR are supported. -.PP -For \f(CW\*(C`SQL_INTEGER\*(C'\fR the effect is similar to using the value in an expression -that requires an integer. It gives the perl scalar an 'integer aspect'. -(Technically the value gains an \s-1IV,\s0 or possibly a \s-1UV\s0 or \s-1NV\s0 if the value is too -large for an \s-1IV.\s0) -.PP -For \f(CW\*(C`SQL_DOUBLE\*(C'\fR the effect is similar to using the value in an expression -that requires a general numeric value. It gives the perl scalar a 'numeric -aspect'. (Technically the value gains an \s-1NV.\s0) -.PP -\&\f(CW\*(C`SQL_NUMERIC\*(C'\fR is similar to \f(CW\*(C`SQL_INTEGER\*(C'\fR or \f(CW\*(C`SQL_DOUBLE\*(C'\fR but more -general and more cautious. It will look at the string first and if it -looks like an integer (that will fit in an \s-1IV\s0 or \s-1UV\s0) it will act like -\&\f(CW\*(C`SQL_INTEGER\*(C'\fR, if it looks like a floating point value it will act -like \f(CW\*(C`SQL_DOUBLE\*(C'\fR, if it looks like neither then it will do nothing \- -and thereby avoid the warnings that would be generated by -\&\f(CW\*(C`SQL_INTEGER\*(C'\fR and \f(CW\*(C`SQL_DOUBLE\*(C'\fR when given non-numeric data. -.PP -\&\f(CW$flags\fR may be: -.ie n .IP """DBIstcf_DISCARD_STRING""" 4 -.el .IP "\f(CWDBIstcf_DISCARD_STRING\fR" 4 -.IX Item "DBIstcf_DISCARD_STRING" -If this flag is specified then when the driver successfully casts the -bound perl scalar to a non-string type then the string portion of the -scalar will be discarded. -.ie n .IP """DBIstcf_STRICT""" 4 -.el .IP "\f(CWDBIstcf_STRICT\fR" 4 -.IX Item "DBIstcf_STRICT" -If \f(CW$sv\fR cannot be cast to the requested \f(CW$sql_type\fR then by default -it is left untouched and no error is generated. If you specify -\&\f(CW\*(C`DBIstcf_STRICT\*(C'\fR and the cast fails, this will generate an error. -.PP -The returned \f(CW$sts\fR value is: -.PP -.Vb 5 -\& \-2 sql_type is not handled -\& \-1 sv is undef so unchanged -\& 0 sv could not be cast cleanly and DBIstcf_STRICT was used -\& 1 sv could not be cast and DBIstcf_STRICT was not used -\& 2 sv was cast successfully -.Ve -.PP -This method is exported by the :utils tag and was introduced in \s-1DBI -1.611.\s0 -.SS "\s-1DBI\s0 Dynamic Attributes" -.IX Subsection "DBI Dynamic Attributes" -Dynamic attributes are always associated with the \fIlast handle used\fR -(that handle is represented by \f(CW$h\fR in the descriptions below). -.PP -Where an attribute is equivalent to a method call, then refer to -the method call for all related documentation. -.PP -Warning: these attributes are provided as a convenience but they -do have limitations. Specifically, they have a short lifespan: -because they are associated with -the last handle used, they should only be used \fIimmediately\fR after -calling the method that \*(L"sets\*(R" them. -If in any doubt, use the corresponding method call. -.PP -\fI\f(CI$DBI::err\fI\fR -.IX Subsection "$DBI::err" -.PP -Equivalent to \f(CW\*(C`$h\->err\*(C'\fR. -.PP -\fI\f(CI$DBI::errstr\fI\fR -.IX Subsection "$DBI::errstr" -.PP -Equivalent to \f(CW\*(C`$h\->errstr\*(C'\fR. -.PP -\fI\f(CI$DBI::state\fI\fR -.IX Subsection "$DBI::state" -.PP -Equivalent to \f(CW\*(C`$h\->state\*(C'\fR. -.PP -\fI\f(CI$DBI::rows\fI\fR -.IX Subsection "$DBI::rows" -.PP -Equivalent to \f(CW\*(C`$h\->rows\*(C'\fR. Please refer to the documentation -for the \*(L"rows\*(R" method. -.PP -\fI\f(CI$DBI::lasth\fI\fR -.IX Subsection "$DBI::lasth" -.PP -Returns the \s-1DBI\s0 object handle used for the most recent \s-1DBI\s0 method call. -If the last \s-1DBI\s0 method call was a \s-1DESTROY\s0 then \f(CW$DBI::lasth\fR will return -the handle of the parent of the destroyed handle, if there is one. -.SH "METHODS COMMON TO ALL HANDLES" -.IX Header "METHODS COMMON TO ALL HANDLES" -The following methods can be used by all types of \s-1DBI\s0 handles. -.PP -\fI\f(CI\*(C`err\*(C'\fI\fR -.IX Subsection "err" -.PP -.Vb 1 -\& $rv = $h\->err; -.Ve -.PP -Returns the \fInative\fR database engine error code from the last driver -method called. The code is typically an integer but you should not -assume that. -.PP -The \s-1DBI\s0 resets \f(CW$h\fR\->err to undef before almost all \s-1DBI\s0 method calls, so the -value only has a short lifespan. Also, for most drivers, the statement -handles share the same error variable as the parent database handle, -so calling a method on one handle may reset the error on the -related handles. -.PP -(Methods which don't reset err before being called include \fIerr()\fR and \fIerrstr()\fR, -obviously, \fIstate()\fR, \fIrows()\fR, \fIfunc()\fR, \fItrace()\fR, \fItrace_msg()\fR, \fIping()\fR, and the -tied hash attribute \s-1\fIFETCH\s0()\fR and \s-1\fISTORE\s0()\fR methods.) -.PP -If you need to test for specific error conditions \fIand\fR have your program be -portable to different database engines, then you'll need to determine what the -corresponding error codes are for all those engines and test for all of them. -.PP -The \s-1DBI\s0 uses the value of \f(CW$DBI::stderr\fR as the \f(CW\*(C`err\*(C'\fR value for internal errors. -Drivers should also do likewise. The default value for \f(CW$DBI::stderr\fR is 2000000000. -.PP -A driver may return \f(CW0\fR from \fIerr()\fR to indicate a warning condition -after a method call. Similarly, a driver may return an empty string -to indicate a 'success with information' condition. In both these -cases the value is false but not undef. The \fIerrstr()\fR and \fIstate()\fR -methods may be used to retrieve extra information in these cases. -.PP -See \*(L"set_err\*(R" for more information. -.PP -\fI\f(CI\*(C`errstr\*(C'\fI\fR -.IX Subsection "errstr" -.PP -.Vb 1 -\& $str = $h\->errstr; -.Ve -.PP -Returns the native database engine error message from the last \s-1DBI\s0 -method called. This has the same lifespan issues as the \*(L"err\*(R" method -described above. -.PP -The returned string may contain multiple messages separated by -newline characters. -.PP -The \fIerrstr()\fR method should not be used to test for errors, use \fIerr()\fR -for that, because drivers may return 'success with information' or -warning messages via \fIerrstr()\fR for methods that have not 'failed'. -.PP -See \*(L"set_err\*(R" for more information. -.PP -\fI\f(CI\*(C`state\*(C'\fI\fR -.IX Subsection "state" -.PP -.Vb 1 -\& $str = $h\->state; -.Ve -.PP -Returns a state code in the standard \s-1SQLSTATE\s0 five character format. -Note that the specific success code \f(CW00000\fR is translated to any empty string -(false). If the driver does not support \s-1SQLSTATE \s0(and most don't), -then \fIstate()\fR will return \f(CW\*(C`S1000\*(C'\fR (General Error) for all errors. -.PP -The driver is free to return any value via \f(CW\*(C`state\*(C'\fR, e.g., warning -codes, even if it has not declared an error by returning a true value -via the \*(L"err\*(R" method described above. -.PP -The \fIstate()\fR method should not be used to test for errors, use \fIerr()\fR -for that, because drivers may return a 'success with information' or -warning state code via \fIstate()\fR for methods that have not 'failed'. -.PP -\fI\f(CI\*(C`set_err\*(C'\fI\fR -.IX Subsection "set_err" -.PP -.Vb 4 -\& $rv = $h\->set_err($err, $errstr); -\& $rv = $h\->set_err($err, $errstr, $state); -\& $rv = $h\->set_err($err, $errstr, $state, $method); -\& $rv = $h\->set_err($err, $errstr, $state, $method, $rv); -.Ve -.PP -Set the \f(CW\*(C`err\*(C'\fR, \f(CW\*(C`errstr\*(C'\fR, and \f(CW\*(C`state\*(C'\fR values for the handle. -This method is typically only used by \s-1DBI\s0 drivers and \s-1DBI\s0 subclasses. -.PP -If the \*(L"HandleSetErr\*(R" attribute holds a reference to a subroutine -it is called first. The subroutine can alter the \f(CW$err\fR, \f(CW$errstr\fR, \f(CW$state\fR, -and \f(CW$method\fR values. See \*(L"HandleSetErr\*(R" for full details. -If the subroutine returns a true value then the handle \f(CW\*(C`err\*(C'\fR, -\&\f(CW\*(C`errstr\*(C'\fR, and \f(CW\*(C`state\*(C'\fR values are not altered and \fIset_err()\fR returns -an empty list (it normally returns \f(CW$rv\fR which defaults to undef, see below). -.PP -Setting \f(CW\*(C`err\*(C'\fR to a \fItrue\fR value indicates an error and will trigger -the normal \s-1DBI\s0 error handling mechanisms, such as \f(CW\*(C`RaiseError\*(C'\fR and -\&\f(CW\*(C`HandleError\*(C'\fR, if they are enabled, when execution returns from -the \s-1DBI\s0 back to the application. -.PP -Setting \f(CW\*(C`err\*(C'\fR to \f(CW""\fR indicates an 'information' state, and setting -it to \f(CW"0"\fR indicates a 'warning' state. Setting \f(CW\*(C`err\*(C'\fR to \f(CW\*(C`undef\*(C'\fR -also sets \f(CW\*(C`errstr\*(C'\fR to undef, and \f(CW\*(C`state\*(C'\fR to \f(CW""\fR, irrespective -of the values of the \f(CW$errstr\fR and \f(CW$state\fR parameters. -.PP -The \f(CW$method\fR parameter provides an alternate method name for the -\&\f(CW\*(C`RaiseError\*(C'\fR/\f(CW\*(C`PrintError\*(C'\fR/\f(CW\*(C`PrintWarn\*(C'\fR error string instead of -the fairly unhelpful '\f(CW\*(C`set_err\*(C'\fR'. -.PP -The \f(CW\*(C`set_err\*(C'\fR method normally returns undef. The \f(CW$rv\fR parameter -provides an alternate return value. -.PP -Some special rules apply if the \f(CW\*(C`err\*(C'\fR or \f(CW\*(C`errstr\*(C'\fR -values for the handle are \fIalready\fR set... -.PP -If \f(CW\*(C`errstr\*(C'\fR is true then: "\f(CW\*(C` [err was %s now %s]\*(C'\fR" is appended if \f(CW$err\fR is -true and \f(CW\*(C`err\*(C'\fR is already true and the new err value differs from the original -one. Similarly "\f(CW\*(C` [state was %s now %s]\*(C'\fR" is appended if \f(CW$state\fR is true and \f(CW\*(C`state\*(C'\fR is -already true and the new state value differs from the original one. Finally -"\f(CW\*(C`\en\*(C'\fR" and the new \f(CW$errstr\fR are appended if \f(CW$errstr\fR differs from the existing -errstr value. Obviously the \f(CW%s\fR's above are replaced by the corresponding values. -.PP -The handle \f(CW\*(C`err\*(C'\fR value is set to \f(CW$err\fR if: \f(CW$err\fR is true; or handle -\&\f(CW\*(C`err\*(C'\fR value is undef; or \f(CW$err\fR is defined and the length is greater -than the handle \f(CW\*(C`err\*(C'\fR length. The effect is that an 'information' -state only overrides undef; a 'warning' overrides undef or 'information', -and an 'error' state overrides anything. -.PP -The handle \f(CW\*(C`state\*(C'\fR value is set to \f(CW$state\fR if \f(CW$state\fR is true and -the handle \f(CW\*(C`err\*(C'\fR value was set (by the rules above). -.PP -Support for warning and information states was added in \s-1DBI 1.41.\s0 -.PP -\fI\f(CI\*(C`trace\*(C'\fI\fR -.IX Subsection "trace" -.PP -.Vb 3 -\& $h\->trace($trace_settings); -\& $h\->trace($trace_settings, $trace_filename); -\& $trace_settings = $h\->trace; -.Ve -.PP -The \fItrace()\fR method is used to alter the trace settings for a handle -(and any future children of that handle). It can also be used to -change where the trace output is sent. -.PP -There's a similar method, \f(CW\*(C`DBI\->trace\*(C'\fR, which sets the global -default trace settings. -.PP -See the \*(L"\s-1TRACING\*(R"\s0 section for full details about the \s-1DBI\s0's powerful -tracing facilities. -.PP -\fI\f(CI\*(C`trace_msg\*(C'\fI\fR -.IX Subsection "trace_msg" -.PP -.Vb 2 -\& $h\->trace_msg($message_text); -\& $h\->trace_msg($message_text, $min_level); -.Ve -.PP -Writes \f(CW$message_text\fR to the trace file if the trace level is -greater than or equal to \f(CW$min_level\fR (which defaults to 1). -Can also be called as \f(CW\*(C`DBI\->trace_msg($msg)\*(C'\fR. -.PP -See \*(L"\s-1TRACING\*(R"\s0 for more details. -.PP -\fI\f(CI\*(C`func\*(C'\fI\fR -.IX Subsection "func" -.PP -.Vb 1 -\& $h\->func(@func_arguments, $func_name) or die ...; -.Ve -.PP -The \f(CW\*(C`func\*(C'\fR method can be used to call private non-standard and -non-portable methods implemented by the driver. Note that the function -name is given as the \fIlast\fR argument. -.PP -It's also important to note that the \fIfunc()\fR method does not clear -a previous error ($DBI::err etc.) and it does not trigger automatic -error detection (RaiseError etc.) so you must check the return -status and/or \f(CW$h\fR\->err to detect errors. -.PP -(This method is not directly related to calling stored procedures. -Calling stored procedures is currently not defined by the \s-1DBI.\s0 -Some drivers, such as DBD::Oracle, support it in non-portable ways. -See driver documentation for more details.) -.PP -See also \fIinstall_method()\fR in \s-1DBI::DBD\s0 for how you can avoid needing to -use \fIfunc()\fR and gain direct access to driver-private methods. -.PP -\fI\f(CI\*(C`can\*(C'\fI\fR -.IX Subsection "can" -.PP -.Vb 1 -\& $is_implemented = $h\->can($method_name); -.Ve -.PP -Returns true if \f(CW$method_name\fR is implemented by the driver or a -default method is provided by the \s-1DBI\s0's driver base class. -It returns false where a driver hasn't implemented a method and the -default method is provided by the \s-1DBI\s0's driver base class is just an empty stub. -.PP -\fI\f(CI\*(C`parse_trace_flags\*(C'\fI\fR -.IX Subsection "parse_trace_flags" -.PP -.Vb 1 -\& $trace_settings_integer = $h\->parse_trace_flags($trace_settings); -.Ve -.PP -Parses a string containing trace settings and returns the corresponding -integer value used internally by the \s-1DBI\s0 and drivers. -.PP -The \f(CW$trace_settings\fR argument is a string containing a trace level -between 0 and 15 and/or trace flag names separated by vertical bar -("\f(CW\*(C`|\*(C'\fR\*(L") or comma (\*(R"\f(CW\*(C`,\*(C'\fR") characters. For example: \f(CW"SQL|3|foo"\fR. -.PP -It uses the \fIparse_trace_flag()\fR method, described below, to process -the individual trace flag names. -.PP -The \fIparse_trace_flags()\fR method was added in \s-1DBI 1.42.\s0 -.PP -\fI\f(CI\*(C`parse_trace_flag\*(C'\fI\fR -.IX Subsection "parse_trace_flag" -.PP -.Vb 1 -\& $bit_flag = $h\->parse_trace_flag($trace_flag_name); -.Ve -.PP -Returns the bit flag corresponding to the trace flag name in -\&\f(CW$trace_flag_name\fR. Drivers are expected to override this method and -check if \f(CW$trace_flag_name\fR is a driver specific trace flags and, if -not, then call the \s-1DBI\s0's default \fIparse_trace_flag()\fR. -.PP -The \fIparse_trace_flag()\fR method was added in \s-1DBI 1.42.\s0 -.PP -\fI\f(CI\*(C`private_attribute_info\*(C'\fI\fR -.IX Subsection "private_attribute_info" -.PP -.Vb 1 -\& $hash_ref = $h\->private_attribute_info(); -.Ve -.PP -Returns a reference to a hash whose keys are the names of driver-private -handle attributes available for the kind of handle (driver, database, statement) -that the method was called on. -.PP -For example, the return value when called with a DBD::Sybase \f(CW$dbh\fR could look like this: -.PP -.Vb 6 -\& { -\& syb_dynamic_supported => undef, -\& syb_oc_version => undef, -\& syb_server_version => undef, -\& syb_server_version_string => undef, -\& } -.Ve -.PP -and when called with a DBD::Sybase \f(CW$sth\fR they could look like this: -.PP -.Vb 5 -\& { -\& syb_types => undef, -\& syb_proc_status => undef, -\& syb_result_type => undef, -\& } -.Ve -.PP -The values should be undef. Meanings may be assigned to particular values in future. -.PP -\fI\f(CI\*(C`swap_inner_handle\*(C'\fI\fR -.IX Subsection "swap_inner_handle" -.PP -.Vb 2 -\& $rc = $h1\->swap_inner_handle( $h2 ); -\& $rc = $h1\->swap_inner_handle( $h2, $allow_reparent ); -.Ve -.PP -Brain transplants for handles. You don't need to know about this -unless you want to become a handle surgeon. -.PP -A \s-1DBI\s0 handle is a reference to a tied hash. A tied hash has an -\&\fIinner\fR hash that actually holds the contents. The \fIswap_inner_handle()\fR -method swaps the inner hashes between two handles. The \f(CW$h1\fR and \f(CW$h2\fR -handles still point to the same tied hashes, but what those hashes -are tied to has been swapped. In effect \f(CW$h1\fR \fIbecomes\fR \f(CW$h2\fR and -vice-versa. This is powerful stuff, expect problems. Use with care. -.PP -As a small safety measure, the two handles, \f(CW$h1\fR and \f(CW$h2\fR, have to -share the same parent unless \f(CW$allow_reparent\fR is true. -.PP -The \fIswap_inner_handle()\fR method was added in \s-1DBI 1.44.\s0 -.PP -Here's a quick kind of 'diagram' as a worked example to help think about what's -happening: -.PP -.Vb 4 -\& Original state: -\& dbh1o \-> dbh1i -\& sthAo \-> sthAi(dbh1i) -\& dbh2o \-> dbh2i -\& -\& swap_inner_handle dbh1o with dbh2o: -\& dbh2o \-> dbh1i -\& sthAo \-> sthAi(dbh1i) -\& dbh1o \-> dbh2i -\& -\& create new sth from dbh1o: -\& dbh2o \-> dbh1i -\& sthAo \-> sthAi(dbh1i) -\& dbh1o \-> dbh2i -\& sthBo \-> sthBi(dbh2i) -\& -\& swap_inner_handle sthAo with sthBo: -\& dbh2o \-> dbh1i -\& sthBo \-> sthAi(dbh1i) -\& dbh1o \-> dbh2i -\& sthAo \-> sthBi(dbh2i) -.Ve -.PP -\fI\f(CI\*(C`visit_child_handles\*(C'\fI\fR -.IX Subsection "visit_child_handles" -.PP -.Vb 2 -\& $h\->visit_child_handles( $coderef ); -\& $h\->visit_child_handles( $coderef, $info ); -.Ve -.PP -Where \f(CW$coderef\fR is a reference to a subroutine and \f(CW$info\fR is an arbitrary value -which, if undefined, defaults to a reference to an empty hash. Returns \f(CW$info\fR. -.PP -For each child handle of \f(CW$h\fR, if any, \f(CW$coderef\fR is invoked as: -.PP -.Vb 1 -\& $coderef\->($child_handle, $info); -.Ve -.PP -If the execution of \f(CW$coderef\fR returns a true value then \f(CW\*(C`visit_child_handles\*(C'\fR -is called on that child handle and passed the returned value as \f(CW$info\fR. -.PP -For example: -.PP -.Vb 7 -\& # count database connections with names (DSN) matching a pattern -\& my $connections = 0; -\& $dbh\->{Driver}\->visit_child_handles(sub { -\& my ($h, $info) = @_; -\& ++$connections if $h\->{Name} =~ /foo/; -\& return 0; # don\*(Aqt visit kids -\& }) -.Ve -.PP -See also \*(L"visit_handles\*(R". -.SH "ATTRIBUTES COMMON TO ALL HANDLES" -.IX Header "ATTRIBUTES COMMON TO ALL HANDLES" -These attributes are common to all types of \s-1DBI\s0 handles. -.PP -Some attributes are inherited by child handles. That is, the value -of an inherited attribute in a newly created statement handle is the -same as the value in the parent database handle. Changes to attributes -in the new statement handle do not affect the parent database handle -and changes to the database handle do not affect existing statement -handles, only future ones. -.PP -Attempting to set or get the value of an unknown attribute generates a warning, -except for private driver specific attributes (which all have names -starting with a lowercase letter). -.PP -Example: -.PP -.Vb 2 -\& $h\->{AttributeName} = ...; # set/write -\& ... = $h\->{AttributeName}; # get/read -.Ve -.PP -\fI\f(CI\*(C`Warn\*(C'\fI\fR -.IX Subsection "Warn" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`Warn\*(C'\fR attribute enables useful warnings for certain bad -practices. It is enabled by default and should only be disabled in -rare circumstances. Since warnings are generated using the Perl -\&\f(CW\*(C`warn\*(C'\fR function, they can be intercepted using the Perl \f(CW$SIG{_\|_WARN_\|_}\fR -hook. -.PP -The \f(CW\*(C`Warn\*(C'\fR attribute is not related to the \f(CW\*(C`PrintWarn\*(C'\fR attribute. -.PP -\fI\f(CI\*(C`Active\*(C'\fI\fR -.IX Subsection "Active" -.PP -Type: boolean, read-only -.PP -The \f(CW\*(C`Active\*(C'\fR attribute is true if the handle object is \*(L"active\*(R". This is rarely used in -applications. The exact meaning of active is somewhat vague at the -moment. For a database handle it typically means that the handle is -connected to a database (\f(CW\*(C`$dbh\->disconnect\*(C'\fR sets \f(CW\*(C`Active\*(C'\fR off). For -a statement handle it typically means that the handle is a \f(CW\*(C`SELECT\*(C'\fR -that may have more data to fetch. (Fetching all the data or calling \f(CW\*(C`$sth\->finish\*(C'\fR -sets \f(CW\*(C`Active\*(C'\fR off.) -.PP -\fI\f(CI\*(C`Executed\*(C'\fI\fR -.IX Subsection "Executed" -.PP -Type: boolean -.PP -The \f(CW\*(C`Executed\*(C'\fR attribute is true if the handle object has been \*(L"executed\*(R". -Currently only the \f(CW$dbh\fR \fIdo()\fR method and the \f(CW$sth\fR \fIexecute()\fR, \fIexecute_array()\fR, -and \fIexecute_for_fetch()\fR methods set the \f(CW\*(C`Executed\*(C'\fR attribute. -.PP -When it's set on a handle it is also set on the parent handle at the -same time. So calling \fIexecute()\fR on a \f(CW$sth\fR also sets the \f(CW\*(C`Executed\*(C'\fR -attribute on the parent \f(CW$dbh\fR. -.PP -The \f(CW\*(C`Executed\*(C'\fR attribute for a database handle is cleared by the \fIcommit()\fR and -\&\fIrollback()\fR methods (even if they fail). The \f(CW\*(C`Executed\*(C'\fR attribute of a -statement handle is not cleared by the \s-1DBI\s0 under any circumstances and so acts -as a permanent record of whether the statement handle was ever used. -.PP -The \f(CW\*(C`Executed\*(C'\fR attribute was added in \s-1DBI 1.41.\s0 -.PP -\fI\f(CI\*(C`Kids\*(C'\fI\fR -.IX Subsection "Kids" -.PP -Type: integer, read-only -.PP -For a driver handle, \f(CW\*(C`Kids\*(C'\fR is the number of currently existing database -handles that were created from that driver handle. For a database -handle, \f(CW\*(C`Kids\*(C'\fR is the number of currently existing statement handles that -were created from that database handle. -For a statement handle, the value is zero. -.PP -\fI\f(CI\*(C`ActiveKids\*(C'\fI\fR -.IX Subsection "ActiveKids" -.PP -Type: integer, read-only -.PP -Like \f(CW\*(C`Kids\*(C'\fR, but only counting those that are \f(CW\*(C`Active\*(C'\fR (as above). -.PP -\fI\f(CI\*(C`CachedKids\*(C'\fI\fR -.IX Subsection "CachedKids" -.PP -Type: hash ref -.PP -For a database handle, \f(CW\*(C`CachedKids\*(C'\fR returns a reference to the cache (hash) of -statement handles created by the \*(L"prepare_cached\*(R" method. For a -driver handle, returns a reference to the cache (hash) of -database handles created by the \*(L"connect_cached\*(R" method. -.PP -\fI\f(CI\*(C`Type\*(C'\fI\fR -.IX Subsection "Type" -.PP -Type: scalar, read-only -.PP -The \f(CW\*(C`Type\*(C'\fR attribute identifies the type of a \s-1DBI\s0 handle. Returns -\&\*(L"dr\*(R" for driver handles, \*(L"db\*(R" for database handles and \*(L"st\*(R" for -statement handles. -.PP -\fI\f(CI\*(C`ChildHandles\*(C'\fI\fR -.IX Subsection "ChildHandles" -.PP -Type: array ref -.PP -The ChildHandles attribute contains a reference to an array of all the -handles created by this handle which are still accessible. The -contents of the array are weak-refs and will become undef when the -handle goes out of scope. (They're cleared out occasionally.) -.PP -\&\f(CW\*(C`ChildHandles\*(C'\fR returns undef if your perl version does not support weak -references (check the Scalar::Util module). The referenced -array returned should be treated as read-only. -.PP -For example, to enumerate all driver handles, database handles and -statement handles: -.PP -.Vb 6 -\& sub show_child_handles { -\& my ($h, $level) = @_; -\& printf "%sh %s %s\en", $h\->{Type}, "\et" x $level, $h; -\& show_child_handles($_, $level + 1) -\& for (grep { defined } @{$h\->{ChildHandles}}); -\& } -\& -\& my %drivers = DBI\->installed_drivers(); -\& show_child_handles($_, 0) for (values %drivers); -.Ve -.PP -\fI\f(CI\*(C`CompatMode\*(C'\fI\fR -.IX Subsection "CompatMode" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`CompatMode\*(C'\fR attribute is used by emulation layers (such as -Oraperl) to enable compatible behaviour in the underlying driver -(e.g., DBD::Oracle) for this handle. Not normally set by application code. -.PP -It also has the effect of disabling the 'quick \s-1FETCH\s0' of attribute -values from the handles attribute cache. So all attribute values -are handled by the drivers own \s-1FETCH\s0 method. This makes them slightly -slower but is useful for special-purpose drivers like DBD::Multiplex. -.PP -\fI\f(CI\*(C`InactiveDestroy\*(C'\fI\fR -.IX Subsection "InactiveDestroy" -.PP -Type: boolean -.PP -The default value, false, means a handle will be fully destroyed -as normal when the last reference to it is removed, just as you'd expect. -.PP -If set true then the handle will be treated by the \s-1DESTROY\s0 as if it was no -longer Active, and so the \fIdatabase engine\fR related effects of DESTROYing a -handle will be skipped. Think of the name as meaning 'treat the handle as -not-Active in the \s-1DESTROY\s0 method'. -.PP -For a database handle, this attribute does not disable an \fIexplicit\fR -call to the disconnect method, only the implicit call from \s-1DESTROY\s0 -that happens if the handle is still marked as \f(CW\*(C`Active\*(C'\fR. -.PP -This attribute is specifically designed for use in Unix applications -that \*(L"fork\*(R" child processes. For some drivers, when the child process exits -the destruction of inherited handles cause the corresponding handles in the -parent process to cease working. -.PP -Either the parent or the child process, but not both, should set -\&\f(CW\*(C`InactiveDestroy\*(C'\fR true on all their shared handles. Alternatively, and -preferably, the \*(L"AutoInactiveDestroy\*(R" can be set in the parent on connect. -.PP -To help tracing applications using fork the process id is shown in -the trace log whenever a \s-1DBI\s0 or handle \fItrace()\fR method is called. -The process id also shown for \fIevery\fR method call if the \s-1DBI\s0 trace -level (not handle trace level) is set high enough to show the trace -from the \s-1DBI\s0's method dispatcher, e.g. >= 9. -.PP -\fI\f(CI\*(C`AutoInactiveDestroy\*(C'\fI\fR -.IX Subsection "AutoInactiveDestroy" -.PP -Type: boolean, inherited -.PP -The \*(L"InactiveDestroy\*(R" attribute, described above, needs to be explicitly set -in the child process after a \fIfork()\fR, on every active database and statement handle. -This is a problem if the code that performs the \fIfork()\fR is not under your -control, perhaps in a third-party module. Use \f(CW\*(C`AutoInactiveDestroy\*(C'\fR to get -around this situation. -.PP -If set true, the \s-1DESTROY\s0 method will check the process id of the handle and, if -different from the current process id, it will set the \fIInactiveDestroy\fR attribute. -It is strongly recommended that \f(CW\*(C`AutoInactiveDestroy\*(C'\fR is enabled on all new code -(it's only not enabled by default to avoid backwards compatibility problems). -.PP -This is the example it's designed to deal with: -.PP -.Vb 4 -\& my $dbh = DBI\->connect(...); -\& some_code_that_forks(); # Perhaps without your knowledge -\& # Child process dies, destroying the inherited dbh -\& $dbh\->do(...); # Breaks because parent $dbh is now broken -.Ve -.PP -The \f(CW\*(C`AutoInactiveDestroy\*(C'\fR attribute was added in \s-1DBI 1.614.\s0 -.PP -\fI\f(CI\*(C`PrintWarn\*(C'\fI\fR -.IX Subsection "PrintWarn" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`PrintWarn\*(C'\fR attribute controls the printing of warnings recorded -by the driver. When set to a true value (the default) the \s-1DBI\s0 will check method -calls to see if a warning condition has been set. If so, the \s-1DBI\s0 -will effectively do a \f(CW\*(C`warn("$class $method warning: $DBI::errstr")\*(C'\fR -where \f(CW$class\fR is the driver class and \f(CW$method\fR is the name of -the method which failed. E.g., -.PP -.Vb 1 -\& DBD::Oracle::db execute warning: ... warning text here ... -.Ve -.PP -If desired, the warnings can be caught and processed using a \f(CW$SIG{_\|_WARN_\|_}\fR -handler or modules like CGI::Carp and CGI::ErrorWrap. -.PP -See also \*(L"set_err\*(R" for how warnings are recorded and \*(L"HandleSetErr\*(R" -for how to influence it. -.PP -Fetching the full details of warnings can require an extra round-trip -to the database server for some drivers. In which case the driver -may opt to only fetch the full details of warnings if the \f(CW\*(C`PrintWarn\*(C'\fR -attribute is true. If \f(CW\*(C`PrintWarn\*(C'\fR is false then these drivers should -still indicate the fact that there were warnings by setting the -warning string to, for example: \*(L"3 warnings\*(R". -.PP -\fI\f(CI\*(C`PrintError\*(C'\fI\fR -.IX Subsection "PrintError" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`PrintError\*(C'\fR attribute can be used to force errors to generate warnings (using -\&\f(CW\*(C`warn\*(C'\fR) in addition to returning error codes in the normal way. When set -\&\*(L"on\*(R", any method which results in an error occurring will cause the \s-1DBI\s0 to -effectively do a \f(CW\*(C`warn("$class $method failed: $DBI::errstr")\*(C'\fR where \f(CW$class\fR -is the driver class and \f(CW$method\fR is the name of the method which failed. E.g., -.PP -.Vb 1 -\& DBD::Oracle::db prepare failed: ... error text here ... -.Ve -.PP -By default, \f(CW\*(C`DBI\->connect\*(C'\fR sets \f(CW\*(C`PrintError\*(C'\fR \*(L"on\*(R". -.PP -If desired, the warnings can be caught and processed using a \f(CW$SIG{_\|_WARN_\|_}\fR -handler or modules like CGI::Carp and CGI::ErrorWrap. -.PP -\fI\f(CI\*(C`RaiseError\*(C'\fI\fR -.IX Subsection "RaiseError" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`RaiseError\*(C'\fR attribute can be used to force errors to raise exceptions rather -than simply return error codes in the normal way. It is \*(L"off\*(R" by default. -When set \*(L"on\*(R", any method which results in an error will cause -the \s-1DBI\s0 to effectively do a \f(CW\*(C`die("$class $method failed: $DBI::errstr")\*(C'\fR, -where \f(CW$class\fR is the driver class and \f(CW$method\fR is the name of the method -that failed. E.g., -.PP -.Vb 1 -\& DBD::Oracle::db prepare failed: ... error text here ... -.Ve -.PP -If you turn \f(CW\*(C`RaiseError\*(C'\fR on then you'd normally turn \f(CW\*(C`PrintError\*(C'\fR off. -If \f(CW\*(C`PrintError\*(C'\fR is also on, then the \f(CW\*(C`PrintError\*(C'\fR is done first (naturally). -.PP -Typically \f(CW\*(C`RaiseError\*(C'\fR is used in conjunction with \f(CW\*(C`eval\*(C'\fR, -or a module like Try::Tiny or TryCatch, -to catch the exception that's been thrown and handle it. -For example: -.PP -.Vb 1 -\& use Try::Tiny; -\& -\& try { -\& ... -\& $sth\->execute(); -\& ... -\& } catch { -\& # $sth\->err and $DBI::err will be true if error was from DBI -\& warn $_; # print the error (which Try::Tiny puts into $_) -\& ... # do whatever you need to deal with the error -\& }; -.Ve -.PP -In the catch block the \f(CW$DBI::lasth\fR variable can be useful for -diagnosis and reporting if you can't be sure which handle triggered -the error. For example, \f(CW$DBI::lasth\fR\->{Type} and \f(CW$DBI::lasth\fR\->{Statement}. -.PP -See also \*(L"Transactions\*(R". -.PP -If you want to temporarily turn \f(CW\*(C`RaiseError\*(C'\fR off (inside a library function -that is likely to fail, for example), the recommended way is like this: -.PP -.Vb 4 -\& { -\& local $h\->{RaiseError}; # localize and turn off for this block -\& ... -\& } -.Ve -.PP -The original value will automatically and reliably be restored by Perl, -regardless of how the block is exited. -The same logic applies to other attributes, including \f(CW\*(C`PrintError\*(C'\fR. -.PP -\fI\f(CI\*(C`HandleError\*(C'\fI\fR -.IX Subsection "HandleError" -.PP -Type: code ref, inherited -.PP -The \f(CW\*(C`HandleError\*(C'\fR attribute can be used to provide your own alternative behaviour -in case of errors. If set to a reference to a subroutine then that -subroutine is called when an error is detected (at the same point that -\&\f(CW\*(C`RaiseError\*(C'\fR and \f(CW\*(C`PrintError\*(C'\fR are handled). -.PP -The subroutine is called with three parameters: the error message -string that \f(CW\*(C`RaiseError\*(C'\fR and \f(CW\*(C`PrintError\*(C'\fR would use, -the \s-1DBI\s0 handle being used, and the first value being returned by -the method that failed (typically undef). -.PP -If the subroutine returns a false value then the \f(CW\*(C`RaiseError\*(C'\fR -and/or \f(CW\*(C`PrintError\*(C'\fR attributes are checked and acted upon as normal. -.PP -For example, to \f(CW\*(C`die\*(C'\fR with a full stack trace for any error: -.PP -.Vb 2 -\& use Carp; -\& $h\->{HandleError} = sub { confess(shift) }; -.Ve -.PP -Or to turn errors into exceptions: -.PP -.Vb 2 -\& use Exception; # or your own favourite exception module -\& $h\->{HandleError} = sub { Exception\->new(\*(AqDBI\*(Aq)\->raise($_[0]) }; -.Ve -.PP -It is possible to 'stack' multiple HandleError handlers by using -closures: -.PP -.Vb 7 -\& sub your_subroutine { -\& my $previous_handler = $h\->{HandleError}; -\& $h\->{HandleError} = sub { -\& return 1 if $previous_handler and &$previous_handler(@_); -\& ... your code here ... -\& }; -\& } -.Ve -.PP -Using a \f(CW\*(C`my\*(C'\fR inside a subroutine to store the previous \f(CW\*(C`HandleError\*(C'\fR -value is important. See perlsub and perlref for more information -about \fIclosures\fR. -.PP -It is possible for \f(CW\*(C`HandleError\*(C'\fR to alter the error message that -will be used by \f(CW\*(C`RaiseError\*(C'\fR and \f(CW\*(C`PrintError\*(C'\fR if it returns false. -It can do that by altering the value of \f(CW$_\fR[0]. This example appends -a stack trace to all errors and, unlike the previous example using -Carp::confess, this will work \f(CW\*(C`PrintError\*(C'\fR as well as \f(CW\*(C`RaiseError\*(C'\fR: -.PP -.Vb 1 -\& $h\->{HandleError} = sub { $_[0]=Carp::longmess($_[0]); 0; }; -.Ve -.PP -It is also possible for \f(CW\*(C`HandleError\*(C'\fR to hide an error, to a limited -degree, by using \*(L"set_err\*(R" to reset \f(CW$DBI::err\fR and \f(CW$DBI::errstr\fR, -and altering the return value of the failed method. For example: -.PP -.Vb 7 -\& $h\->{HandleError} = sub { -\& return 0 unless $_[0] =~ /^\eS+ fetchrow_arrayref failed:/; -\& return 0 unless $_[1]\->err == 1234; # the error to \*(Aqhide\*(Aq -\& $h\->set_err(undef,undef); # turn off the error -\& $_[2] = [ ... ]; # supply alternative return value -\& return 1; -\& }; -.Ve -.PP -This only works for methods which return a single value and is hard -to make reliable (avoiding infinite loops, for example) and so isn't -recommended for general use! If you find a \fIgood\fR use for it then -please let me know. -.PP -\fI\f(CI\*(C`HandleSetErr\*(C'\fI\fR -.IX Subsection "HandleSetErr" -.PP -Type: code ref, inherited -.PP -The \f(CW\*(C`HandleSetErr\*(C'\fR attribute can be used to intercept -the setting of handle \f(CW\*(C`err\*(C'\fR, \f(CW\*(C`errstr\*(C'\fR, and \f(CW\*(C`state\*(C'\fR values. -If set to a reference to a subroutine then that subroutine is called -whenever \fIset_err()\fR is called, typically by the driver or a subclass. -.PP -The subroutine is called with five arguments, the first five that -were passed to \fIset_err()\fR: the handle, the \f(CW\*(C`err\*(C'\fR, \f(CW\*(C`errstr\*(C'\fR, and -\&\f(CW\*(C`state\*(C'\fR values being set, and the method name. These can be altered -by changing the values in the \f(CW@_\fR array. The return value affects -\&\fIset_err()\fR behaviour, see \*(L"set_err\*(R" for details. -.PP -It is possible to 'stack' multiple HandleSetErr handlers by using -closures. See \*(L"HandleError\*(R" for an example. -.PP -The \f(CW\*(C`HandleSetErr\*(C'\fR and \f(CW\*(C`HandleError\*(C'\fR subroutines differ in subtle -but significant ways. HandleError is only invoked at the point where -the \s-1DBI\s0 is about to return to the application with \f(CW\*(C`err\*(C'\fR set true. -It's not invoked by the failure of a method that's been called by -another \s-1DBI\s0 method. HandleSetErr, on the other hand, is called -whenever \fIset_err()\fR is called with a defined \f(CW\*(C`err\*(C'\fR value, even if false. -So it's not just for errors, despite the name, but also warn and info states. -The \fIset_err()\fR method, and thus HandleSetErr, may be called multiple -times within a method and is usually invoked from deep within driver code. -.PP -In theory a driver can use the return value from HandleSetErr via -\&\fIset_err()\fR to decide whether to continue or not. If \fIset_err()\fR returns -an empty list, indicating that the HandleSetErr code has 'handled' -the 'error', the driver could then continue instead of failing (if -that's a reasonable thing to do). This isn't excepted to be -common and any such cases should be clearly marked in the driver -documentation and discussed on the dbi-dev mailing list. -.PP -The \f(CW\*(C`HandleSetErr\*(C'\fR attribute was added in \s-1DBI 1.41.\s0 -.PP -\fI\f(CI\*(C`ErrCount\*(C'\fI\fR -.IX Subsection "ErrCount" -.PP -Type: unsigned integer -.PP -The \f(CW\*(C`ErrCount\*(C'\fR attribute is incremented whenever the \fIset_err()\fR -method records an error. It isn't incremented by warnings or -information states. It is not reset by the \s-1DBI\s0 at any time. -.PP -The \f(CW\*(C`ErrCount\*(C'\fR attribute was added in \s-1DBI 1.41.\s0 Older drivers may -not have been updated to use \fIset_err()\fR to record errors and so this -attribute may not be incremented when using them. -.PP -\fI\f(CI\*(C`ShowErrorStatement\*(C'\fI\fR -.IX Subsection "ShowErrorStatement" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`ShowErrorStatement\*(C'\fR attribute can be used to cause the relevant -Statement text to be appended to the error messages generated by -the \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`PrintError\*(C'\fR, and \f(CW\*(C`PrintWarn\*(C'\fR attributes. -Only applies to errors on statement handles -plus the \fIprepare()\fR, \fIdo()\fR, and the various \f(CW\*(C`select*()\*(C'\fR database handle methods. -(The exact format of the appended text is subject to change.) -.PP -If \f(CW\*(C`$h\->{ParamValues}\*(C'\fR returns a hash reference of parameter -(placeholder) values then those are formatted and appended to the -end of the Statement text in the error message. -.PP -\fI\f(CI\*(C`TraceLevel\*(C'\fI\fR -.IX Subsection "TraceLevel" -.PP -Type: integer, inherited -.PP -The \f(CW\*(C`TraceLevel\*(C'\fR attribute can be used as an alternative to the -\&\*(L"trace\*(R" method to set the \s-1DBI\s0 trace level and trace flags for a -specific handle. See \*(L"\s-1TRACING\*(R"\s0 for more details. -.PP -The \f(CW\*(C`TraceLevel\*(C'\fR attribute is especially useful combined with -\&\f(CW\*(C`local\*(C'\fR to alter the trace settings for just a single block of code. -.PP -\fI\f(CI\*(C`FetchHashKeyName\*(C'\fI\fR -.IX Subsection "FetchHashKeyName" -.PP -Type: string, inherited -.PP -The \f(CW\*(C`FetchHashKeyName\*(C'\fR attribute is used to specify whether the \fIfetchrow_hashref()\fR -method should perform case conversion on the field names used for -the hash keys. For historical reasons it defaults to '\f(CW\*(C`NAME\*(C'\fR' but -it is recommended to set it to '\f(CW\*(C`NAME_lc\*(C'\fR' (convert to lower case) -or '\f(CW\*(C`NAME_uc\*(C'\fR' (convert to upper case) according to your preference. -It can only be set for driver and database handles. For statement -handles the value is frozen when \fIprepare()\fR is called. -.PP -\fI\f(CI\*(C`ChopBlanks\*(C'\fI\fR -.IX Subsection "ChopBlanks" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`ChopBlanks\*(C'\fR attribute can be used to control the trimming of trailing space -characters from fixed width character (\s-1CHAR\s0) fields. No other field -types are affected, even where field values have trailing spaces. -.PP -The default is false (although it is possible that the default may change). -Applications that need specific behaviour should set the attribute as -needed. -.PP -Drivers are not required to support this attribute, but any driver which -does not support it must arrange to return \f(CW\*(C`undef\*(C'\fR as the attribute value. -.PP -\fI\f(CI\*(C`LongReadLen\*(C'\fI\fR -.IX Subsection "LongReadLen" -.PP -Type: unsigned integer, inherited -.PP -The \f(CW\*(C`LongReadLen\*(C'\fR attribute may be used to control the maximum -length of 'long' type fields (\s-1LONG, BLOB, CLOB, MEMO,\s0 etc.) which the driver will -read from the database automatically when it fetches each row of data. -.PP -The \f(CW\*(C`LongReadLen\*(C'\fR attribute only relates to fetching and reading -long values; it is not involved in inserting or updating them. -.PP -A value of 0 means not to automatically fetch any long data. -Drivers may return undef or an empty string for long fields when -\&\f(CW\*(C`LongReadLen\*(C'\fR is 0. -.PP -The default is typically 0 (zero) or 80 bytes but may vary between drivers. -Applications fetching long fields should set this value to slightly -larger than the longest long field value to be fetched. -.PP -Some databases return some long types encoded as pairs of hex digits. -For these types, \f(CW\*(C`LongReadLen\*(C'\fR relates to the underlying data -length and not the doubled-up length of the encoded string. -.PP -Changing the value of \f(CW\*(C`LongReadLen\*(C'\fR for a statement handle after it -has been \f(CW\*(C`prepare\*(C'\fR'd will typically have no effect, so it's common to -set \f(CW\*(C`LongReadLen\*(C'\fR on the \f(CW$dbh\fR before calling \f(CW\*(C`prepare\*(C'\fR. -.PP -For most drivers the value used here has a direct effect on the -memory used by the statement handle while it's active, so don't be -too generous. If you can't be sure what value to use you could -execute an extra select statement to determine the longest value. -For example: -.PP -.Vb 7 -\& $dbh\->{LongReadLen} = $dbh\->selectrow_array(qq{ -\& SELECT MAX(OCTET_LENGTH(long_column_name)) -\& FROM table WHERE ... -\& }); -\& $sth = $dbh\->prepare(qq{ -\& SELECT long_column_name, ... FROM table WHERE ... -\& }); -.Ve -.PP -You may need to take extra care if the table can be modified between -the first select and the second being executed. You may also need to -use a different function if \s-1\fIOCTET_LENGTH\s0()\fR does not work for long -types in your database. For example, for Sybase use \s-1\fIDATALENGTH\s0()\fR and -for Oracle use \s-1\fILENGTHB\s0()\fR. -.PP -See also \*(L"LongTruncOk\*(R" for information on truncation of long types. -.PP -\fI\f(CI\*(C`LongTruncOk\*(C'\fI\fR -.IX Subsection "LongTruncOk" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`LongTruncOk\*(C'\fR attribute may be used to control the effect of -fetching a long field value which has been truncated (typically -because it's longer than the value of the \f(CW\*(C`LongReadLen\*(C'\fR attribute). -.PP -By default, \f(CW\*(C`LongTruncOk\*(C'\fR is false and so fetching a long value that -needs to be truncated will cause the fetch to fail. -(Applications should always be sure to -check for errors after a fetch loop in case an error, such as a divide -by zero or long field truncation, caused the fetch to terminate -prematurely.) -.PP -If a fetch fails due to a long field truncation when \f(CW\*(C`LongTruncOk\*(C'\fR is -false, many drivers will allow you to continue fetching further rows. -.PP -See also \*(L"LongReadLen\*(R". -.PP -\fI\f(CI\*(C`TaintIn\*(C'\fI\fR -.IX Subsection "TaintIn" -.PP -Type: boolean, inherited -.PP -If the \f(CW\*(C`TaintIn\*(C'\fR attribute is set to a true value \fIand\fR Perl is running in -taint mode (e.g., started with the \f(CW\*(C`\-T\*(C'\fR option), then all the arguments -to most \s-1DBI\s0 method calls are checked for being tainted. \fIThis may change.\fR -.PP -The attribute defaults to off, even if Perl is in taint mode. -See perlsec for more about taint mode. If Perl is not -running in taint mode, this attribute has no effect. -.PP -When fetching data that you trust you can turn off the TaintIn attribute, -for that statement handle, for the duration of the fetch loop. -.PP -The \f(CW\*(C`TaintIn\*(C'\fR attribute was added in \s-1DBI 1.31.\s0 -.PP -\fI\f(CI\*(C`TaintOut\*(C'\fI\fR -.IX Subsection "TaintOut" -.PP -Type: boolean, inherited -.PP -If the \f(CW\*(C`TaintOut\*(C'\fR attribute is set to a true value \fIand\fR Perl is running in -taint mode (e.g., started with the \f(CW\*(C`\-T\*(C'\fR option), then most data fetched -from the database is considered tainted. \fIThis may change.\fR -.PP -The attribute defaults to off, even if Perl is in taint mode. -See perlsec for more about taint mode. If Perl is not -running in taint mode, this attribute has no effect. -.PP -When fetching data that you trust you can turn off the TaintOut attribute, -for that statement handle, for the duration of the fetch loop. -.PP -Currently only fetched data is tainted. It is possible that the results -of other \s-1DBI\s0 method calls, and the value of fetched attributes, may -also be tainted in future versions. That change may well break your -applications unless you take great care now. If you use \s-1DBI\s0 Taint mode, -please report your experience and any suggestions for changes. -.PP -The \f(CW\*(C`TaintOut\*(C'\fR attribute was added in \s-1DBI 1.31.\s0 -.PP -\fI\f(CI\*(C`Taint\*(C'\fI\fR -.IX Subsection "Taint" -.PP -Type: boolean, inherited -.PP -The \f(CW\*(C`Taint\*(C'\fR attribute is a shortcut for \*(L"TaintIn\*(R" and \*(L"TaintOut\*(R" (it is also present -for backwards compatibility). -.PP -Setting this attribute sets both \*(L"TaintIn\*(R" and \*(L"TaintOut\*(R", and retrieving -it returns a true value if and only if \*(L"TaintIn\*(R" and \*(L"TaintOut\*(R" are -both set to true values. -.PP -\fI\f(CI\*(C`Profile\*(C'\fI\fR -.IX Subsection "Profile" -.PP -Type: inherited -.PP -The \f(CW\*(C`Profile\*(C'\fR attribute enables the collection and reporting of -method call timing statistics. See the DBI::Profile module -documentation for \fImuch\fR more detail. -.PP -The \f(CW\*(C`Profile\*(C'\fR attribute was added in \s-1DBI 1.24.\s0 -.PP -\fI\f(CI\*(C`ReadOnly\*(C'\fI\fR -.IX Subsection "ReadOnly" -.PP -Type: boolean, inherited -.PP -An application can set the \f(CW\*(C`ReadOnly\*(C'\fR attribute of a handle to a true value to -indicate that it will not be attempting to make any changes using that handle -or any children of it. -.PP -Note that the exact definition of 'read only' is rather fuzzy. -For more details see the documentation for the driver you're using. -.PP -If the driver can make the handle truly read-only then it should -(unless doing so would have unpleasant side effect, like changing the -consistency level from per-statement to per-session). -Otherwise the attribute is simply advisory. -.PP -A driver can set the \f(CW\*(C`ReadOnly\*(C'\fR attribute itself to indicate that the data it -is connected to cannot be changed for some reason. -.PP -If the driver cannot ensure the \f(CW\*(C`ReadOnly\*(C'\fR attribute is adhered to it -will record a warning. In this case reading the \f(CW\*(C`ReadOnly\*(C'\fR attribute -back after it is set true will return true even if the underlying -driver cannot ensure this (so any application knows the application -declared itself ReadOnly). -.PP -Library modules and proxy drivers can use the attribute to influence -their behavior. For example, the DBD::Gofer driver considers the -\&\f(CW\*(C`ReadOnly\*(C'\fR attribute when making a decision about whether to retry an -operation that failed. -.PP -The attribute should be set to 1 or 0 (or undef). Other values are reserved. -.PP -\fI\f(CI\*(C`Callbacks\*(C'\fI\fR -.IX Subsection "Callbacks" -.PP -Type: hash ref -.PP -The \s-1DBI\s0 callback mechanism lets you intercept, and optionally replace, any -method call on a \s-1DBI\s0 handle. At the extreme, it lets you become a puppet -master, deceiving the application in any way you want. -.PP -The \f(CW\*(C`Callbacks\*(C'\fR attribute is a hash reference where the keys are \s-1DBI\s0 method -names and the values are code references. For each key naming a method, the -\&\s-1DBI\s0 will execute the associated code reference before executing the method. -.PP -The arguments to the code reference will be the same as to the method, -including the invocant (a database handle or statement handle). For example, -say that to callback to some code on a call to \f(CW\*(C`prepare()\*(C'\fR: -.PP -.Vb 6 -\& $dbh\->{Callbacks} = { -\& prepare => sub { -\& my ($dbh, $query, $attrs) = @_; -\& print "Preparing q{$query}\en" -\& }, -\& }; -.Ve -.PP -The callback would then be executed when you called the \f(CW\*(C`prepare()\*(C'\fR method: -.PP -.Vb 1 -\& $dbh\->prepare(\*(AqSELECT 1\*(Aq); -.Ve -.PP -And the output of course would be: -.PP -.Vb 1 -\& Preparing q{SELECT 1} -.Ve -.PP -Because callbacks are executed \fIbefore\fR the methods -they're associated with, you can modify the arguments before they're passed on -to the method call. For example, to make sure that all calls to \f(CW\*(C`prepare()\*(C'\fR -are immediately prepared by DBD::Pg, add a callback that makes sure that -the \f(CW\*(C`pg_prepare_now\*(C'\fR attribute is always set: -.PP -.Vb 9 -\& my $dbh = DBI\->connect($dsn, $username, $auth, { -\& Callbacks => { -\& prepare => sub { -\& $_[2] ||= {}; -\& $_[2]\->{pg_prepare_now} = 1; -\& return; # must return nothing -\& }, -\& } -\& }); -.Ve -.PP -Note that we are editing the contents of \f(CW@_\fR directly. In this case we've -created the attributes hash if it's not passed to the \f(CW\*(C`prepare\*(C'\fR call. -.PP -You can also prevent the associated method from ever executing. While a -callback executes, \f(CW$_\fR holds the method name. (This allows multiple callbacks -to share the same code reference and still know what method was called.) -To prevent the method from -executing, simply \f(CW\*(C`undef $_\*(C'\fR. For example, if you wanted to disable calls to -\&\f(CW\*(C`ping()\*(C'\fR, you could do this: -.PP -.Vb 8 -\& $dbh\->{Callbacks} = { -\& ping => sub { -\& # tell dispatch to not call the method: -\& undef $_; -\& # return this value instead: -\& return "42 bells"; -\& } -\& }; -.Ve -.PP -As with other attributes, Callbacks can be specified on a handle or via the -attributes to \f(CW\*(C`connect()\*(C'\fR. Callbacks can also be applied to a statement -methods on a statement handle. For example: -.PP -.Vb 5 -\& $sth\->{Callbacks} = { -\& execute => sub { -\& print "Executing ", shift\->{Statement}, "\en"; -\& } -\& }; -.Ve -.PP -The \f(CW\*(C`Callbacks\*(C'\fR attribute of a database handle isn't copied to any statement -handles it creates. So setting callbacks for a statement handle requires you to -set the \f(CW\*(C`Callbacks\*(C'\fR attribute on the statement handle yourself, as in the -example above, or use the special \f(CW\*(C`ChildCallbacks\*(C'\fR key described below. -.PP -\&\fBSpecial Keys in Callbacks Attribute\fR -.PP -In addition to \s-1DBI\s0 handle method names, the \f(CW\*(C`Callbacks\*(C'\fR hash reference -supports four additional keys. -.PP -The first is the \f(CW\*(C`ChildCallbacks\*(C'\fR key. When a statement handle is created from -a database handle the \f(CW\*(C`ChildCallbacks\*(C'\fR key of the database handle's -\&\f(CW\*(C`Callbacks\*(C'\fR attribute, if any, becomes the new \f(CW\*(C`Callbacks\*(C'\fR attribute of the -statement handle. -This allows you to define callbacks for all statement handles created from a -database handle. For example, if you wanted to count how many times \f(CW\*(C`execute\*(C'\fR -was called in your application, you could write: -.PP -.Vb 8 -\& my $exec_count = 0; -\& my $dbh = DBI\->connect( $dsn, $username, $auth, { -\& Callbacks => { -\& ChildCallbacks => { -\& execute => sub { $exec_count++; return; } -\& } -\& } -\& }); -\& -\& END { -\& print "The execute method was called $exec_count times\en"; -\& } -.Ve -.PP -The other three special keys are \f(CW\*(C`connect_cached.new\*(C'\fR, -\&\f(CW\*(C`connect_cached.connected\*(C'\fR, and \f(CW\*(C`connect_cached.reused\*(C'\fR. These keys define -callbacks that are called when \f(CW\*(C`connect_cached()\*(C'\fR is called, but allow -different behaviors depending on whether a new handle is created or a handle -is returned. The callback is invoked with these arguments: -\&\f(CW\*(C`$dbh, $dsn, $user, $auth, $attr\*(C'\fR. -.PP -For example, some applications uses \f(CW\*(C`connect_cached()\*(C'\fR to connect with -\&\f(CW\*(C`AutoCommit\*(C'\fR enabled and then disable \f(CW\*(C`AutoCommit\*(C'\fR temporarily for -transactions. If \f(CW\*(C`connect_cached()\*(C'\fR is called during a transaction, perhaps in -a utility method, then it might select the same cached handle and then force -\&\f(CW\*(C`AutoCommit\*(C'\fR on, forcing a commit of the transaction. See the \*(L"connect_cached\*(R" -documentation for one way to deal with that. Here we'll describe an alternative -approach using a callback. -.PP -Because the \f(CW\*(C`connect_cached.new\*(C'\fR and \f(CW\*(C`connect_cached.reused\*(C'\fR callbacks are -invoked before \f(CW\*(C`connect_cached()\*(C'\fR has applied the connect attributes, you can -use them to edit the attributes that will be applied. To prevent a cached -handle from having its transactions committed before it's returned, you can -eliminate the \f(CW\*(C`AutoCommit\*(C'\fR attribute in a \f(CW\*(C`connect_cached.reused\*(C'\fR callback, -like so: -.PP -.Vb 3 -\& my $cb = { -\& \*(Aqconnect_cached.reused\*(Aq => sub { delete $_[4]\->{AutoCommit} }, -\& }; -\& -\& sub dbh { -\& my $self = shift; -\& DBI\->connect_cached( $dsn, $username, $auth, { -\& PrintError => 0, -\& RaiseError => 1, -\& AutoCommit => 1, -\& Callbacks => $cb, -\& }); -\& } -.Ve -.PP -The upshot is that new database handles are created with \f(CW\*(C`AutoCommit\*(C'\fR -enabled, while cached database handles are left in whatever transaction state -they happened to be in when retrieved from the cache. -.PP -Note that we've also used a lexical for the callbacks hash reference. This is -because \f(CW\*(C`connect_cached()\*(C'\fR returns a new database handle if any of the -attributes passed to is have changed. If we used an inline hash reference, -\&\f(CW\*(C`connect_cached()\*(C'\fR would return a new database handle every time. Which would -rather defeat the purpose. -.PP -A more common application for callbacks is setting connection state only when -a new connection is made (by \fIconnect()\fR or \fIconnect_cached()\fR). Adding a callback -to the connected method (when using \f(CW\*(C`connect\*(C'\fR) or via -\&\f(CW\*(C`connect_cached.connected\*(C'\fR (when useing \fIconnect_cached()\fR>) makes this easy. -The \fIconnected()\fR method is a no-op by default (unless you subclass the \s-1DBI\s0 and -change it). The \s-1DBI\s0 calls it to indicate that a new connection has been made -and the connection attributes have all been set. You can give it a bit of -added functionality by applying a callback to it. For example, to make sure -that MySQL understands your application's ANSI-compliant \s-1SQL,\s0 set it up like -so: -.PP -.Vb 10 -\& my $dbh = DBI\->connect($dsn, $username, $auth, { -\& Callbacks => { -\& connected => sub { -\& shift\->do(q{ -\& SET SESSION sql_mode=\*(Aqansi,strict_trans_tables,no_auto_value_on_zero\*(Aq; -\& }); -\& return; -\& }, -\& } -\& }); -.Ve -.PP -If you're using \f(CW\*(C`connect_cached()\*(C'\fR, use the \f(CW\*(C`connect_cached.connected\*(C'\fR -callback, instead. This is because \f(CW\*(C`connected()\*(C'\fR is called for both new and -reused database handles, but you want to execute a callback only the when a -new database handle is returned. For example, to set the time zone on -connection to a PostgreSQL database, try this: -.PP -.Vb 5 -\& my $cb = { -\& \*(Aqconnect_cached.connected\*(Aq => sub { -\& shift\->do(\*(AqSET timezone = UTC\*(Aq); -\& } -\& }; -\& -\& sub dbh { -\& my $self = shift; -\& DBI\->connect_cached( $dsn, $username, $auth, { Callbacks => $cb }); -\& } -.Ve -.PP -One significant limitation with callbacks is that there can only be one per -method per handle. This means it's easy for one use of callbacks to interfere -with, or typically simply overwrite, another use of callbacks. For this reason -modules using callbacks should document the fact clearly so application authors -can tell if use of callbacks by the module will clash with use of callbacks by -the application. -.PP -You might be able to work around this issue by taking a copy of the original -callback and calling it within your own. For example: -.PP -.Vb 8 -\& my $prev_cb = $h\->{Callbacks}{method_name}; -\& $h\->{Callbacks}{method_name} = sub { -\& if ($prev_cb) { -\& my @result = $prev_cb\->(@_); -\& return @result if not $_; # $prev_cb vetoed call -\& } -\& ... your callback logic here ... -\& }; -.Ve -.PP -\fI\f(CI\*(C`private_your_module_name_*\*(C'\fI\fR -.IX Subsection "private_your_module_name_*" -.PP -The \s-1DBI\s0 provides a way to store extra information in a \s-1DBI\s0 handle as -\&\*(L"private\*(R" attributes. The \s-1DBI\s0 will allow you to store and retrieve any -attribute which has a name starting with "\f(CW\*(C`private_\*(C'\fR". -.PP -It is \fIstrongly\fR recommended that you use just \fIone\fR private -attribute (e.g., use a hash ref) \fIand\fR give it a long and unambiguous -name that includes the module or application name that the attribute -relates to (e.g., "\f(CW\*(C`private_YourFullModuleName_thingy\*(C'\fR"). -.PP -Because of the way the Perl tie mechanism works you cannot reliably -use the \f(CW\*(C`||=\*(C'\fR operator directly to initialise the attribute, like this: -.PP -.Vb 1 -\& my $foo = $dbh\->{private_yourmodname_foo} ||= { ... }; # WRONG -.Ve -.PP -you should use a two step approach like this: -.PP -.Vb 2 -\& my $foo = $dbh\->{private_yourmodname_foo}; -\& $foo ||= $dbh\->{private_yourmodname_foo} = { ... }; -.Ve -.PP -This attribute is primarily of interest to people sub-classing \s-1DBI,\s0 -or for applications to piggy-back extra information onto \s-1DBI\s0 handles. -.SH "DBI DATABASE HANDLE OBJECTS" -.IX Header "DBI DATABASE HANDLE OBJECTS" -This section covers the methods and attributes associated with -database handles. -.SS "Database Handle Methods" -.IX Subsection "Database Handle Methods" -The following methods are specified for \s-1DBI\s0 database handles: -.PP -\fI\f(CI\*(C`clone\*(C'\fI\fR -.IX Subsection "clone" -.PP -.Vb 1 -\& $new_dbh = $dbh\->clone(\e%attr); -.Ve -.PP -The \f(CW\*(C`clone\*(C'\fR method duplicates the \f(CW$dbh\fR connection by connecting -with the same parameters ($dsn, \f(CW$user\fR, \f(CW$password\fR) as originally used. -.PP -The attributes for the cloned connect are the same as those used -for the \fIoriginal\fR connect, with any other attributes in \f(CW\*(C`\e%attr\*(C'\fR -merged over them. Effectively the same as doing: -.PP -.Vb 1 -\& %attributes_used = ( %original_attributes, %attr ); -.Ve -.PP -If \e%attr is not given then it defaults to a hash containing all -the attributes in the attribute cache of \f(CW$dbh\fR excluding any non-code -references, plus the main boolean attributes (RaiseError, PrintError, -AutoCommit, etc.). \fIThis behaviour is unreliable and so use of clone without -an argument is deprecated and may cause a warning in a future release.\fR -.PP -The clone method can be used even if the database handle is disconnected. -.PP -The \f(CW\*(C`clone\*(C'\fR method was added in \s-1DBI 1.33.\s0 -.PP -\fI\f(CI\*(C`data_sources\*(C'\fI\fR -.IX Subsection "data_sources" -.PP -.Vb 2 -\& @ary = $dbh\->data_sources(); -\& @ary = $dbh\->data_sources(\e%attr); -.Ve -.PP -Returns a list of data sources (databases) available via the \f(CW$dbh\fR -driver's \fIdata_sources()\fR method, plus any extra data sources that -the driver can discover via the connected \f(CW$dbh\fR. Typically the extra -data sources are other databases managed by the same server process -that the \f(CW$dbh\fR is connected to. -.PP -Data sources are returned in a form suitable for passing to the -\&\*(L"connect\*(R" method (that is, they will include the "\f(CW\*(C`dbi:$driver:\*(C'\fR" prefix). -.PP -The \fIdata_sources()\fR method, for a \f(CW$dbh\fR, was added in \s-1DBI 1.38.\s0 -.PP -\fI\f(CI\*(C`do\*(C'\fI\fR -.IX Subsection "do" -.PP -.Vb 3 -\& $rows = $dbh\->do($statement) or die $dbh\->errstr; -\& $rows = $dbh\->do($statement, \e%attr) or die $dbh\->errstr; -\& $rows = $dbh\->do($statement, \e%attr, @bind_values) or die ... -.Ve -.PP -Prepare and execute a single statement. Returns the number of rows -affected or \f(CW\*(C`undef\*(C'\fR on error. A return value of \f(CW\*(C`\-1\*(C'\fR means the -number of rows is not known, not applicable, or not available. -.PP -This method is typically most useful for \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR statements that -either cannot be prepared in advance (due to a limitation of the -driver) or do not need to be executed repeatedly. It should not -be used for \f(CW\*(C`SELECT\*(C'\fR statements because it does not return a statement -handle (so you can't fetch any data). -.PP -The default \f(CW\*(C`do\*(C'\fR method is logically similar to: -.PP -.Vb 7 -\& sub do { -\& my($dbh, $statement, $attr, @bind_values) = @_; -\& my $sth = $dbh\->prepare($statement, $attr) or return undef; -\& $sth\->execute(@bind_values) or return undef; -\& my $rows = $sth\->rows; -\& ($rows == 0) ? "0E0" : $rows; # always return true if no error -\& } -.Ve -.PP -For example: -.PP -.Vb 4 -\& my $rows_deleted = $dbh\->do(q{ -\& DELETE FROM table -\& WHERE status = ? -\& }, undef, \*(AqDONE\*(Aq) or die $dbh\->errstr; -.Ve -.PP -Using placeholders and \f(CW@bind_values\fR with the \f(CW\*(C`do\*(C'\fR method can be -useful because it avoids the need to correctly quote any variables -in the \f(CW$statement\fR. But if you'll be executing the statement many -times then it's more efficient to \f(CW\*(C`prepare\*(C'\fR it once and call -\&\f(CW\*(C`execute\*(C'\fR many times instead. -.PP -The \f(CW\*(C`q{...}\*(C'\fR style quoting used in this example avoids clashing with -quotes that may be used in the \s-1SQL\s0 statement. Use the double-quote-like -\&\f(CW\*(C`qq{...}\*(C'\fR operator if you want to interpolate variables into the string. -See \*(L"Quote and Quote-like Operators\*(R" in perlop for more details. -.PP -Note drivers are free to avoid the overhead of creating an \s-1DBI\s0 -statement handle for \fIdo()\fR, especially if there are no parameters. In -this case error handlers, if invoked during \fIdo()\fR, will be passed the -database handle. -.PP -\fI\f(CI\*(C`last_insert_id\*(C'\fI\fR -.IX Subsection "last_insert_id" -.PP -.Vb 2 -\& $rv = $dbh\->last_insert_id($catalog, $schema, $table, $field); -\& $rv = $dbh\->last_insert_id($catalog, $schema, $table, $field, \e%attr); -.Ve -.PP -Returns a value 'identifying' the row just inserted, if possible. -Typically this would be a value assigned by the database server -to a column with an \fIauto_increment\fR or \fIserial\fR type. -Returns undef if the driver does not support the method or can't -determine the value. -.PP -The \f(CW$catalog\fR, \f(CW$schema\fR, \f(CW$table\fR, and \f(CW$field\fR parameters may be required -for some drivers (see below). If you don't know the parameter values -and your driver does not need them, then use \f(CW\*(C`undef\*(C'\fR for each. -.PP -There are several caveats to be aware of with this method if you want -to use it for portable applications: -.PP -\&\fB*\fR For some drivers the value may only available immediately after -the insert statement has executed (e.g., mysql, Informix). -.PP -\&\fB*\fR For some drivers the \f(CW$catalog\fR, \f(CW$schema\fR, \f(CW$table\fR, and \f(CW$field\fR parameters -are required, for others they are ignored (e.g., mysql). -.PP -\&\fB*\fR Drivers may return an indeterminate value if no insert has -been performed yet. -.PP -\&\fB*\fR For some drivers the value may only be available if placeholders -have \fInot\fR been used (e.g., Sybase, \s-1MS SQL\s0). In this case the value -returned would be from the last non-placeholder insert statement. -.PP -\&\fB*\fR Some drivers may need driver-specific hints about how to get -the value. For example, being told the name of the database 'sequence' -object that holds the value. Any such hints are passed as driver-specific -attributes in the \e%attr parameter. -.PP -\&\fB*\fR If the underlying database offers nothing better, then some -drivers may attempt to implement this method by executing -"\f(CW\*(C`select max($field) from $table\*(C'\fR". Drivers using any approach -like this should issue a warning if \f(CW\*(C`AutoCommit\*(C'\fR is true because -it is generally unsafe \- another process may have modified the table -between your insert and the select. For situations where you know -it is safe, such as when you have locked the table, you can silence -the warning by passing \f(CW\*(C`Warn\*(C'\fR => 0 in \e%attr. -.PP -\&\fB*\fR If no insert has been performed yet, or the last insert failed, -then the value is implementation defined. -.PP -Given all the caveats above, it's clear that this method must be -used with care. -.PP -The \f(CW\*(C`last_insert_id\*(C'\fR method was added in \s-1DBI 1.38.\s0 -.PP -\fI\f(CI\*(C`selectrow_array\*(C'\fI\fR -.IX Subsection "selectrow_array" -.PP -.Vb 3 -\& @row_ary = $dbh\->selectrow_array($statement); -\& @row_ary = $dbh\->selectrow_array($statement, \e%attr); -\& @row_ary = $dbh\->selectrow_array($statement, \e%attr, @bind_values); -.Ve -.PP -This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and -\&\*(L"fetchrow_array\*(R" into a single call. If called in a list context, it -returns the first row of data from the statement. The \f(CW$statement\fR -parameter can be a previously prepared statement handle, in which case -the \f(CW\*(C`prepare\*(C'\fR is skipped. -.PP -If any method fails, and \*(L"RaiseError\*(R" is not set, \f(CW\*(C`selectrow_array\*(C'\fR -will return an empty list. -.PP -If called in a scalar context for a statement handle that has more -than one column, it is undefined whether the driver will return -the value of the first column or the last. So don't do that. -Also, in a scalar context, an \f(CW\*(C`undef\*(C'\fR is returned if there are no -more rows or if an error occurred. That \f(CW\*(C`undef\*(C'\fR can't be distinguished -from an \f(CW\*(C`undef\*(C'\fR returned because the first field value was \s-1NULL.\s0 -For these reasons you should exercise some caution if you use -\&\f(CW\*(C`selectrow_array\*(C'\fR in a scalar context, or just don't do that. -.PP -\fI\f(CI\*(C`selectrow_arrayref\*(C'\fI\fR -.IX Subsection "selectrow_arrayref" -.PP -.Vb 3 -\& $ary_ref = $dbh\->selectrow_arrayref($statement); -\& $ary_ref = $dbh\->selectrow_arrayref($statement, \e%attr); -\& $ary_ref = $dbh\->selectrow_arrayref($statement, \e%attr, @bind_values); -.Ve -.PP -This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and -\&\*(L"fetchrow_arrayref\*(R" into a single call. It returns the first row of -data from the statement. The \f(CW$statement\fR parameter can be a previously -prepared statement handle, in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. -.PP -If any method fails, and \*(L"RaiseError\*(R" is not set, \f(CW\*(C`selectrow_arrayref\*(C'\fR -will return undef. -.PP -\fI\f(CI\*(C`selectrow_hashref\*(C'\fI\fR -.IX Subsection "selectrow_hashref" -.PP -.Vb 3 -\& $hash_ref = $dbh\->selectrow_hashref($statement); -\& $hash_ref = $dbh\->selectrow_hashref($statement, \e%attr); -\& $hash_ref = $dbh\->selectrow_hashref($statement, \e%attr, @bind_values); -.Ve -.PP -This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and -\&\*(L"fetchrow_hashref\*(R" into a single call. It returns the first row of -data from the statement. The \f(CW$statement\fR parameter can be a previously -prepared statement handle, in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. -.PP -If any method fails, and \*(L"RaiseError\*(R" is not set, \f(CW\*(C`selectrow_hashref\*(C'\fR -will return undef. -.PP -\fI\f(CI\*(C`selectall_arrayref\*(C'\fI\fR -.IX Subsection "selectall_arrayref" -.PP -.Vb 3 -\& $ary_ref = $dbh\->selectall_arrayref($statement); -\& $ary_ref = $dbh\->selectall_arrayref($statement, \e%attr); -\& $ary_ref = $dbh\->selectall_arrayref($statement, \e%attr, @bind_values); -.Ve -.PP -This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and -\&\*(L"fetchall_arrayref\*(R" into a single call. It returns a reference to an -array containing a reference to an array (or hash, see below) for each row of -data fetched. -.PP -The \f(CW$statement\fR parameter can be a previously prepared statement handle, -in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. This is recommended if the -statement is going to be executed many times. -.PP -If \*(L"RaiseError\*(R" is not set and any method except \f(CW\*(C`fetchall_arrayref\*(C'\fR -fails then \f(CW\*(C`selectall_arrayref\*(C'\fR will return \f(CW\*(C`undef\*(C'\fR; if -\&\f(CW\*(C`fetchall_arrayref\*(C'\fR fails then it will return with whatever data -has been fetched thus far. You should check \f(CW\*(C`$dbh\->err\*(C'\fR -afterwards (or use the \f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the data is -complete or was truncated due to an error. -.PP -The \*(L"fetchall_arrayref\*(R" method called by \f(CW\*(C`selectall_arrayref\*(C'\fR -supports a \f(CW$max_rows\fR parameter. You can specify a value for \f(CW$max_rows\fR -by including a '\f(CW\*(C`MaxRows\*(C'\fR' attribute in \e%attr. In which case \fIfinish()\fR -is called for you after \fIfetchall_arrayref()\fR returns. -.PP -The \*(L"fetchall_arrayref\*(R" method called by \f(CW\*(C`selectall_arrayref\*(C'\fR -also supports a \f(CW$slice\fR parameter. You can specify a value for \f(CW$slice\fR by -including a '\f(CW\*(C`Slice\*(C'\fR' or '\f(CW\*(C`Columns\*(C'\fR' attribute in \e%attr. The only -difference between the two is that if \f(CW\*(C`Slice\*(C'\fR is not defined and -\&\f(CW\*(C`Columns\*(C'\fR is an array ref, then the array is assumed to contain column -index values (which count from 1), rather than perl array index values. -In which case the array is copied and each value decremented before -passing to \f(CW\*(C`/fetchall_arrayref\*(C'\fR. -.PP -You may often want to fetch an array of rows where each row is stored as a -hash. That can be done simply using: -.PP -.Vb 7 -\& my $emps = $dbh\->selectall_arrayref( -\& "SELECT ename FROM emp ORDER BY ename", -\& { Slice => {} } -\& ); -\& foreach my $emp ( @$emps ) { -\& print "Employee: $emp\->{ename}\en"; -\& } -.Ve -.PP -Or, to fetch into an array instead of an array ref: -.PP -.Vb 1 -\& @result = @{ $dbh\->selectall_arrayref($sql, { Slice => {} }) }; -.Ve -.PP -See \*(L"fetchall_arrayref\*(R" method for more details. -.PP -\fI\f(CI\*(C`selectall_array\*(C'\fI\fR -.IX Subsection "selectall_array" -.PP -.Vb 3 -\& @ary = $dbh\->selectall_array($statement); -\& @ary = $dbh\->selectall_array($statement, \e%attr); -\& @ary = $dbh\->selectall_array($statement, \e%attr, @bind_values); -.Ve -.PP -This is a convenience wrapper around selectall_arrayref that returns -the rows directly as a list, rather than a reference to an array of rows. -.PP -Note that if \*(L"RaiseError\*(R" is not set then you can't tell the difference -between returning no rows and an error. Using RaiseError is best practice. -.PP -\fI\f(CI\*(C`selectall_hashref\*(C'\fI\fR -.IX Subsection "selectall_hashref" -.PP -.Vb 3 -\& $hash_ref = $dbh\->selectall_hashref($statement, $key_field); -\& $hash_ref = $dbh\->selectall_hashref($statement, $key_field, \e%attr); -\& $hash_ref = $dbh\->selectall_hashref($statement, $key_field, \e%attr, @bind_values); -.Ve -.PP -This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and -\&\*(L"fetchall_hashref\*(R" into a single call. It returns a reference to a -hash containing one entry, at most, for each row, as returned by \fIfetchall_hashref()\fR. -.PP -The \f(CW$statement\fR parameter can be a previously prepared statement handle, -in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. This is recommended if the -statement is going to be executed many times. -.PP -The \f(CW$key_field\fR parameter defines which column, or columns, are used as keys -in the returned hash. It can either be the name of a single field, or a -reference to an array containing multiple field names. Using multiple names -yields a tree of nested hashes. -.PP -If a row has the same key as an earlier row then it replaces the earlier row. -.PP -If any method except \f(CW\*(C`fetchrow_hashref\*(C'\fR fails, and \*(L"RaiseError\*(R" is not set, -\&\f(CW\*(C`selectall_hashref\*(C'\fR will return \f(CW\*(C`undef\*(C'\fR. If \f(CW\*(C`fetchrow_hashref\*(C'\fR fails and -\&\*(L"RaiseError\*(R" is not set, then it will return with whatever data it -has fetched thus far. \f(CW$DBI::err\fR should be checked to catch that. -.PP -See \fIfetchall_hashref()\fR for more details. -.PP -\fI\f(CI\*(C`selectcol_arrayref\*(C'\fI\fR -.IX Subsection "selectcol_arrayref" -.PP -.Vb 3 -\& $ary_ref = $dbh\->selectcol_arrayref($statement); -\& $ary_ref = $dbh\->selectcol_arrayref($statement, \e%attr); -\& $ary_ref = $dbh\->selectcol_arrayref($statement, \e%attr, @bind_values); -.Ve -.PP -This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R", and fetching one -column from all the rows, into a single call. It returns a reference to -an array containing the values of the first column from each row. -.PP -The \f(CW$statement\fR parameter can be a previously prepared statement handle, -in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. This is recommended if the -statement is going to be executed many times. -.PP -If any method except \f(CW\*(C`fetch\*(C'\fR fails, and \*(L"RaiseError\*(R" is not set, -\&\f(CW\*(C`selectcol_arrayref\*(C'\fR will return \f(CW\*(C`undef\*(C'\fR. If \f(CW\*(C`fetch\*(C'\fR fails and -\&\*(L"RaiseError\*(R" is not set, then it will return with whatever data it -has fetched thus far. \f(CW$DBI::err\fR should be checked to catch that. -.PP -The \f(CW\*(C`selectcol_arrayref\*(C'\fR method defaults to pushing a single column -value (the first) from each row into the result array. However, it can -also push another column, or even multiple columns per row, into the -result array. This behaviour can be specified via a '\f(CW\*(C`Columns\*(C'\fR' -attribute which must be a ref to an array containing the column number -or numbers to use. For example: -.PP -.Vb 3 -\& # get array of id and name pairs: -\& my $ary_ref = $dbh\->selectcol_arrayref("select id, name from table", { Columns=>[1,2] }); -\& my %hash = @$ary_ref; # build hash from key\-value pairs so $hash{$id} => name -.Ve -.PP -You can specify a maximum number of rows to fetch by including a -\&'\f(CW\*(C`MaxRows\*(C'\fR' attribute in \e%attr. -.PP -\fI\f(CI\*(C`prepare\*(C'\fI\fR -.IX Subsection "prepare" -.PP -.Vb 2 -\& $sth = $dbh\->prepare($statement) or die $dbh\->errstr; -\& $sth = $dbh\->prepare($statement, \e%attr) or die $dbh\->errstr; -.Ve -.PP -Prepares a statement for later execution by the database -engine and returns a reference to a statement handle object. -.PP -The returned statement handle can be used to get attributes of the -statement and invoke the \*(L"execute\*(R" method. See \*(L"Statement Handle Methods\*(R". -.PP -Drivers for engines without the concept of preparing a -statement will typically just store the statement in the returned -handle and process it when \f(CW\*(C`$sth\->execute\*(C'\fR is called. Such drivers are -unlikely to give much useful information about the -statement, such as \f(CW\*(C`$sth\->{NUM_OF_FIELDS}\*(C'\fR, until after \f(CW\*(C`$sth\->execute\*(C'\fR -has been called. Portable applications should take this into account. -.PP -In general, \s-1DBI\s0 drivers do not parse the contents of the statement -(other than simply counting any Placeholders). -The statement is -passed directly to the database engine, sometimes known as pass-thru -mode. This has advantages and disadvantages. On the plus side, you can -access all the functionality of the engine being used. On the downside, -you're limited if you're using a simple engine, and you need to take extra care if -writing applications intended to be portable between engines. -.PP -Portable applications should not assume that a new statement can be -prepared and/or executed while still fetching results from a previous -statement. -.PP -Some command-line \s-1SQL\s0 tools use statement terminators, like a semicolon, -to indicate the end of a statement. Such terminators should not normally -be used with the \s-1DBI.\s0 -.PP -\fI\f(CI\*(C`prepare_cached\*(C'\fI\fR -.IX Subsection "prepare_cached" -.PP -.Vb 3 -\& $sth = $dbh\->prepare_cached($statement) -\& $sth = $dbh\->prepare_cached($statement, \e%attr) -\& $sth = $dbh\->prepare_cached($statement, \e%attr, $if_active) -.Ve -.PP -Like \*(L"prepare\*(R" except that the statement handle returned will be -stored in a hash associated with the \f(CW$dbh\fR. If another call is made to -\&\f(CW\*(C`prepare_cached\*(C'\fR with the same \f(CW$statement\fR and \f(CW%attr\fR parameter values, -then the corresponding cached \f(CW$sth\fR will be returned without contacting the -database server. Be sure to understand the cautions and caveats noted below. -.PP -The \f(CW$if_active\fR parameter lets you adjust the behaviour if an -already cached statement handle is still Active. There are several -alternatives: -.ie n .IP "\fB0\fR: A warning will be generated, and \fIfinish()\fR will be called on the statement handle before it is returned. This is the default behaviour if $if_active is not passed." 4 -.el .IP "\fB0\fR: A warning will be generated, and \fIfinish()\fR will be called on the statement handle before it is returned. This is the default behaviour if \f(CW$if_active\fR is not passed." 4 -.IX Item "0: A warning will be generated, and finish() will be called on the statement handle before it is returned. This is the default behaviour if $if_active is not passed." -.PD 0 -.IP "\fB1\fR: \fIfinish()\fR will be called on the statement handle, but the warning is suppressed." 4 -.IX Item "1: finish() will be called on the statement handle, but the warning is suppressed." -.IP "\fB2\fR: Disables any checking." 4 -.IX Item "2: Disables any checking." -.IP "\fB3\fR: The existing active statement handle will be removed from the cache and a new statement handle prepared and cached in its place. This is the safest option because it doesn't affect the state of the old handle, it just removes it from the cache. [Added in \s-1DBI 1.40\s0]" 4 -.IX Item "3: The existing active statement handle will be removed from the cache and a new statement handle prepared and cached in its place. This is the safest option because it doesn't affect the state of the old handle, it just removes it from the cache. [Added in DBI 1.40]" -.PD -.PP -Here are some examples of \f(CW\*(C`prepare_cached\*(C'\fR: -.PP -.Vb 10 -\& sub insert_hash { -\& my ($table, $field_values) = @_; -\& # sort to keep field order, and thus sql, stable for prepare_cached -\& my @fields = sort keys %$field_values; -\& my @values = @{$field_values}{@fields}; -\& my $sql = sprintf "insert into %s (%s) values (%s)", -\& $table, join(",", @fields), join(",", ("?")x@fields); -\& my $sth = $dbh\->prepare_cached($sql); -\& return $sth\->execute(@values); -\& } -\& -\& sub search_hash { -\& my ($table, $field_values) = @_; -\& # sort to keep field order, and thus sql, stable for prepare_cached -\& my @fields = sort keys %$field_values; -\& my @values = @{$field_values}{@fields}; -\& my $qualifier = ""; -\& $qualifier = "where ".join(" and ", map { "$_=?" } @fields) if @fields; -\& $sth = $dbh\->prepare_cached("SELECT * FROM $table $qualifier"); -\& return $dbh\->selectall_arrayref($sth, {}, @values); -\& } -.Ve -.PP -\&\fICaveat emptor:\fR This caching can be useful in some applications, -but it can also cause problems and should be used with care. Here -is a contrived case where caching would cause a significant problem: -.PP -.Vb 3 -\& my $sth = $dbh\->prepare_cached(\*(AqSELECT * FROM foo WHERE bar=?\*(Aq); -\& $sth\->execute(...); -\& while (my $data = $sth\->fetchrow_hashref) { -\& -\& # later, in some other code called within the loop... -\& my $sth2 = $dbh\->prepare_cached(\*(AqSELECT * FROM foo WHERE bar=?\*(Aq); -\& $sth2\->execute(...); -\& while (my $data2 = $sth2\->fetchrow_arrayref) { -\& do_stuff(...); -\& } -\& } -.Ve -.PP -In this example, since both handles are preparing the exact same statement, -\&\f(CW$sth2\fR will not be its own statement handle, but a duplicate of \f(CW$sth\fR -returned from the cache. The results will certainly not be what you expect. -Typically the inner fetch loop will work normally, fetching all -the records and terminating when there are no more, but now that \f(CW$sth\fR -is the same as \f(CW$sth2\fR the outer fetch loop will also terminate. -.PP -You'll know if you run into this problem because \fIprepare_cached()\fR -will generate a warning by default (when \f(CW$if_active\fR is false). -.PP -The cache used by \fIprepare_cached()\fR is keyed by both the statement -and any attributes so you can also avoid this issue by doing something -like: -.PP -.Vb 1 -\& $sth = $dbh\->prepare_cached("...", { dbi_dummy => _\|_FILE_\|_._\|_LINE_\|_ }); -.Ve -.PP -which will ensure that prepare_cached only returns statements cached -by that line of code in that source file. -.PP -Also, to ensure the attributes passed are always the same, avoid passing -references inline. For example, the Slice attribute is specified as a -reference. Be sure to declare it external to the call to \fIprepare_cached()\fR, such -that a new hash reference is not created on every call. See \*(L"connect_cached\*(R" -for more details and examples. -.PP -If you'd like the cache to managed intelligently, you can tie the -hashref returned by \f(CW\*(C`CachedKids\*(C'\fR to an appropriate caching module, -such as Tie::Cache::LRU: -.PP -.Vb 3 -\& my $cache; -\& tie %$cache, \*(AqTie::Cache::LRU\*(Aq, 500; -\& $dbh\->{CachedKids} = $cache; -.Ve -.PP -\fI\f(CI\*(C`commit\*(C'\fI\fR -.IX Subsection "commit" -.PP -.Vb 1 -\& $rc = $dbh\->commit or die $dbh\->errstr; -.Ve -.PP -Commit (make permanent) the most recent series of database changes -if the database supports transactions and AutoCommit is off. -.PP -If \f(CW\*(C`AutoCommit\*(C'\fR is on, then calling -\&\f(CW\*(C`commit\*(C'\fR will issue a \*(L"commit ineffective with AutoCommit\*(R" warning. -.PP -See also \*(L"Transactions\*(R" in the \*(L"\s-1FURTHER INFORMATION\*(R"\s0 section below. -.PP -\fI\f(CI\*(C`rollback\*(C'\fI\fR -.IX Subsection "rollback" -.PP -.Vb 1 -\& $rc = $dbh\->rollback or die $dbh\->errstr; -.Ve -.PP -Rollback (undo) the most recent series of uncommitted database -changes if the database supports transactions and AutoCommit is off. -.PP -If \f(CW\*(C`AutoCommit\*(C'\fR is on, then calling -\&\f(CW\*(C`rollback\*(C'\fR will issue a \*(L"rollback ineffective with AutoCommit\*(R" warning. -.PP -See also \*(L"Transactions\*(R" in the \*(L"\s-1FURTHER INFORMATION\*(R"\s0 section below. -.PP -\fI\f(CI\*(C`begin_work\*(C'\fI\fR -.IX Subsection "begin_work" -.PP -.Vb 1 -\& $rc = $dbh\->begin_work or die $dbh\->errstr; -.Ve -.PP -Enable transactions (by turning \f(CW\*(C`AutoCommit\*(C'\fR off) until the next call -to \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR. After the next \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR, -\&\f(CW\*(C`AutoCommit\*(C'\fR will automatically be turned on again. -.PP -If \f(CW\*(C`AutoCommit\*(C'\fR is already off when \f(CW\*(C`begin_work\*(C'\fR is called then -it does nothing except return an error. If the driver does not support -transactions then when \f(CW\*(C`begin_work\*(C'\fR attempts to set \f(CW\*(C`AutoCommit\*(C'\fR off -the driver will trigger a fatal error. -.PP -See also \*(L"Transactions\*(R" in the \*(L"\s-1FURTHER INFORMATION\*(R"\s0 section below. -.PP -\fI\f(CI\*(C`disconnect\*(C'\fI\fR -.IX Subsection "disconnect" -.PP -.Vb 1 -\& $rc = $dbh\->disconnect or warn $dbh\->errstr; -.Ve -.PP -Disconnects the database from the database handle. \f(CW\*(C`disconnect\*(C'\fR is typically only used -before exiting the program. The handle is of little use after disconnecting. -.PP -The transaction behaviour of the \f(CW\*(C`disconnect\*(C'\fR method is, sadly, -undefined. Some database systems (such as Oracle and Ingres) will -automatically commit any outstanding changes, but others (such as -Informix) will rollback any outstanding changes. Applications not -using \f(CW\*(C`AutoCommit\*(C'\fR should explicitly call \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR before -calling \f(CW\*(C`disconnect\*(C'\fR. -.PP -The database is automatically disconnected by the \f(CW\*(C`DESTROY\*(C'\fR method if -still connected when there are no longer any references to the handle. -The \f(CW\*(C`DESTROY\*(C'\fR method for each driver should implicitly call \f(CW\*(C`rollback\*(C'\fR to -undo any uncommitted changes. This is vital behaviour to ensure that -incomplete transactions don't get committed simply because Perl calls -\&\f(CW\*(C`DESTROY\*(C'\fR on every object before exiting. Also, do not rely on the order -of object destruction during \*(L"global destruction\*(R", as it is undefined. -.PP -Generally, if you want your changes to be committed or rolled back when -you disconnect, then you should explicitly call \*(L"commit\*(R" or \*(L"rollback\*(R" -before disconnecting. -.PP -If you disconnect from a database while you still have active -statement handles (e.g., \s-1SELECT\s0 statement handles that may have -more data to fetch), you will get a warning. The warning may indicate -that a fetch loop terminated early, perhaps due to an uncaught error. -To avoid the warning call the \f(CW\*(C`finish\*(C'\fR method on the active handles. -.PP -\fI\f(CI\*(C`ping\*(C'\fI\fR -.IX Subsection "ping" -.PP -.Vb 1 -\& $rc = $dbh\->ping; -.Ve -.PP -Attempts to determine, in a reasonably efficient way, if the database -server is still running and the connection to it is still working. -Individual drivers should implement this function in the most suitable -manner for their database engine. -.PP -The current \fIdefault\fR implementation always returns true without -actually doing anything. Actually, it returns "\f(CW\*(C`0 but true\*(C'\fR" which is -true but zero. That way you can tell if the return value is genuine or -just the default. Drivers should override this method with one that -does the right thing for their type of database. -.PP -Few applications would have direct use for this method. See the specialized -Apache::DBI module for one example usage. -.PP -\fI\f(CI\*(C`get_info\*(C'\fI\fR -.IX Subsection "get_info" -.PP -.Vb 1 -\& $value = $dbh\->get_info( $info_type ); -.Ve -.PP -Returns information about the implementation, i.e. driver and data -source capabilities, restrictions etc. It returns \f(CW\*(C`undef\*(C'\fR for -unknown or unimplemented information types. For example: -.PP -.Vb 2 -\& $database_version = $dbh\->get_info( 18 ); # SQL_DBMS_VER -\& $max_select_tables = $dbh\->get_info( 106 ); # SQL_MAXIMUM_TABLES_IN_SELECT -.Ve -.PP -See \*(L"Standards Reference Information\*(R" for more detailed information -about the information types and their meanings and possible return values. -.PP -The DBI::Const::GetInfoType module exports a \f(CW%GetInfoType\fR hash that -can be used to map info type names to numbers. For example: -.PP -.Vb 1 -\& $database_version = $dbh\->get_info( $GetInfoType{SQL_DBMS_VER} ); -.Ve -.PP -The names are a merging of the \s-1ANSI\s0 and \s-1ODBC\s0 standards (which differ -in some cases). See DBI::Const::GetInfoType for more details. -.PP -Because some \s-1DBI\s0 methods make use of \fIget_info()\fR, drivers are strongly -encouraged to support \fIat least\fR the following very minimal set -of information types to ensure the \s-1DBI\s0 itself works properly: -.PP -.Vb 7 -\& Type Name Example A Example B -\& \-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- -\& 17 SQL_DBMS_NAME \*(AqACCESS\*(Aq \*(AqOracle\*(Aq -\& 18 SQL_DBMS_VER \*(Aq03.50.0000\*(Aq \*(Aq08.01.0721 ...\*(Aq -\& 29 SQL_IDENTIFIER_QUOTE_CHAR \*(Aq\`\*(Aq \*(Aq"\*(Aq -\& 41 SQL_CATALOG_NAME_SEPARATOR \*(Aq.\*(Aq \*(Aq@\*(Aq -\& 114 SQL_CATALOG_LOCATION 1 2 -.Ve -.PP -Values from 9000 to 9999 for get_info are officially reserved for use by Perl \s-1DBI.\s0 -Values in that range which have been assigned a meaning are defined here: -.PP -\&\f(CW9000\fR: true if a backslash character (\f(CW\*(C`\e\*(C'\fR) before placeholder-like text -(e.g. \f(CW\*(C`?\*(C'\fR, \f(CW\*(C`:foo\*(C'\fR) will prevent it being treated as a placeholder by the driver. -The backslash will be removed before the text is passed to the backend. -.PP -\fI\f(CI\*(C`table_info\*(C'\fI\fR -.IX Subsection "table_info" -.PP -.Vb 2 -\& $sth = $dbh\->table_info( $catalog, $schema, $table, $type ); -\& $sth = $dbh\->table_info( $catalog, $schema, $table, $type, \e%attr ); -\& -\& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc -.Ve -.PP -Returns an active statement handle that can be used to fetch -information about tables and views that exist in the database. -.PP -The arguments \f(CW$catalog\fR, \f(CW$schema\fR and \f(CW$table\fR may accept search patterns -according to the database/driver, for example: \f(CW$table\fR = '%FOO%'; -Remember that the underscore character ('\f(CW\*(C`_\*(C'\fR') is a search pattern -that means match any character, so 'FOO_%' is the same as 'FOO%' -and 'FOO_BAR%' will match names like '\s-1FOO1BAR\s0'. -.PP -The value of \f(CW$type\fR is a comma-separated list of one or more types of -tables to be returned in the result set. Each value may optionally be -quoted, e.g.: -.PP -.Vb 2 -\& $type = "TABLE"; -\& $type = "\*(AqTABLE\*(Aq,\*(AqVIEW\*(Aq"; -.Ve -.PP -In addition the following special cases may also be supported by some drivers: -.IP "\(bu" 4 -If the value of \f(CW$catalog\fR is '%' and \f(CW$schema\fR and \f(CW$table\fR name -are empty strings, the result set contains a list of catalog names. -For example: -.Sp -.Vb 1 -\& $sth = $dbh\->table_info(\*(Aq%\*(Aq, \*(Aq\*(Aq, \*(Aq\*(Aq); -.Ve -.IP "\(bu" 4 -If the value of \f(CW$schema\fR is '%' and \f(CW$catalog\fR and \f(CW$table\fR are empty -strings, the result set contains a list of schema names. -.IP "\(bu" 4 -If the value of \f(CW$type\fR is '%' and \f(CW$catalog\fR, \f(CW$schema\fR, and \f(CW$table\fR are all -empty strings, the result set contains a list of table types. -.PP -If your driver doesn't support one or more of the selection filter -parameters then you may get back more than you asked for and can -do the filtering yourself. -.PP -This method can be expensive, and can return a large amount of data. -(For example, small Oracle installation returns over 2000 rows.) -So it's a good idea to use the filters to limit the data as much as possible. -.PP -The statement handle returned has at least the following fields in the -order show below. Other fields, after these, may also be present. -.PP -\&\fB\s-1TABLE_CAT\s0\fR: Table catalog identifier. This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not -applicable to the data source, which is usually the case. This field -is empty if not applicable to the table. -.PP -\&\fB\s-1TABLE_SCHEM\s0\fR: The name of the schema containing the \s-1TABLE_NAME\s0 value. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to data source, and -empty if not applicable to the table. -.PP -\&\fB\s-1TABLE_NAME\s0\fR: Name of the table (or view, synonym, etc). -.PP -\&\fB\s-1TABLE_TYPE\s0\fR: One of the following: \*(L"\s-1TABLE\*(R", \*(L"VIEW\*(R", \*(L"SYSTEM TABLE\*(R", -\&\*(L"GLOBAL TEMPORARY\*(R", \*(L"LOCAL TEMPORARY\*(R", \*(L"ALIAS\*(R", \*(L"SYNONYM\*(R"\s0 or a type -identifier that is specific to the data -source. -.PP -\&\fB\s-1REMARKS\s0\fR: A description of the table. May be \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR). -.PP -Note that \f(CW\*(C`table_info\*(C'\fR might not return records for all tables. -Applications can use any valid table regardless of whether it's -returned by \f(CW\*(C`table_info\*(C'\fR. -.PP -See also \*(L"tables\*(R", \*(L"Catalog Methods\*(R" and -\&\*(L"Standards Reference Information\*(R". -.PP -\fI\f(CI\*(C`column_info\*(C'\fI\fR -.IX Subsection "column_info" -.PP -.Vb 1 -\& $sth = $dbh\->column_info( $catalog, $schema, $table, $column ); -\& -\& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc -.Ve -.PP -Returns an active statement handle that can be used to fetch -information about columns in specified tables. -.PP -The arguments \f(CW$schema\fR, \f(CW$table\fR and \f(CW$column\fR may accept search patterns -according to the database/driver, for example: \f(CW$table\fR = '%FOO%'; -.PP -Note: The support for the selection criteria is driver specific. If the -driver doesn't support one or more of them then you may get back more -than you asked for and can do the filtering yourself. -.PP -Note: If your driver does not support column_info an undef is -returned. This is distinct from asking for something which does not -exist in a driver which supports column_info as a valid statement -handle to an empty result-set will be returned in this case. -.PP -If the arguments don't match any tables then you'll still get a statement -handle, it'll just return no rows. -.PP -The statement handle returned has at least the following fields in the -order shown below. Other fields, after these, may also be present. -.PP -\&\fB\s-1TABLE_CAT\s0\fR: The catalog identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -which is often the case. This field is empty if not applicable to the -table. -.PP -\&\fB\s-1TABLE_SCHEM\s0\fR: The schema identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -and empty if not applicable to the table. -.PP -\&\fB\s-1TABLE_NAME\s0\fR: The table identifier. -Note: A driver may provide column metadata not only for base tables, but -also for derived objects like \s-1SYNONYMS\s0 etc. -.PP -\&\fB\s-1COLUMN_NAME\s0\fR: The column identifier. -.PP -\&\fB\s-1DATA_TYPE\s0\fR: The concise data type code. -.PP -\&\fB\s-1TYPE_NAME\s0\fR: A data source dependent data type name. -.PP -\&\fB\s-1COLUMN_SIZE\s0\fR: The column size. -This is the maximum length in characters for character data types, -the number of digits or bits for numeric data types or the length -in the representation of temporal types. -See the relevant specifications for detailed information. -.PP -\&\fB\s-1BUFFER_LENGTH\s0\fR: The length in bytes of transferred data. -.PP -\&\fB\s-1DECIMAL_DIGITS\s0\fR: The total number of significant digits to the right of -the decimal point. -.PP -\&\fB\s-1NUM_PREC_RADIX\s0\fR: The radix for numeric precision. -The value is 10 or 2 for numeric data types and \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not -applicable. -.PP -\&\fB\s-1NULLABLE\s0\fR: Indicates if a column can accept NULLs. -The following values are defined: -.PP -.Vb 3 -\& SQL_NO_NULLS 0 -\& SQL_NULLABLE 1 -\& SQL_NULLABLE_UNKNOWN 2 -.Ve -.PP -\&\fB\s-1REMARKS\s0\fR: A description of the column. -.PP -\&\fB\s-1COLUMN_DEF\s0\fR: The default value of the column, in a format that can be used -directly in an \s-1SQL\s0 statement. -.PP -Note that this may be an expression and not simply the text used for the -default value in the original \s-1CREATE TABLE\s0 statement. For example, given: -.PP -.Vb 2 -\& col1 char(30) default current_user \-\- a \*(Aqfunction\*(Aq -\& col2 char(30) default \*(Aqstring\*(Aq \-\- a string literal -.Ve -.PP -where \*(L"current_user\*(R" is the name of a function, the corresponding \f(CW\*(C`COLUMN_DEF\*(C'\fR -values would be: -.PP -.Vb 5 -\& Database col1 col2 -\& \-\-\-\-\-\-\-\- \-\-\-\- \-\-\-\- -\& Oracle: current_user \*(Aqstring\*(Aq -\& Postgres: "current_user"() \*(Aqstring\*(Aq::text -\& MS SQL: (user_name()) (\*(Aqstring\*(Aq) -.Ve -.PP -\&\fB\s-1SQL_DATA_TYPE\s0\fR: The \s-1SQL\s0 data type. -.PP -\&\fB\s-1SQL_DATETIME_SUB\s0\fR: The subtype code for datetime and interval data types. -.PP -\&\fB\s-1CHAR_OCTET_LENGTH\s0\fR: The maximum length in bytes of a character or binary -data type column. -.PP -\&\fB\s-1ORDINAL_POSITION\s0\fR: The column sequence number (starting with 1). -.PP -\&\fB\s-1IS_NULLABLE\s0\fR: Indicates if the column can accept NULLs. -Possible values are: '\s-1NO\s0', '\s-1YES\s0' and ''. -.PP -\&\s-1SQL/CLI\s0 defines the following additional columns: -.PP -.Vb 10 -\& CHAR_SET_CAT -\& CHAR_SET_SCHEM -\& CHAR_SET_NAME -\& COLLATION_CAT -\& COLLATION_SCHEM -\& COLLATION_NAME -\& UDT_CAT -\& UDT_SCHEM -\& UDT_NAME -\& DOMAIN_CAT -\& DOMAIN_SCHEM -\& DOMAIN_NAME -\& SCOPE_CAT -\& SCOPE_SCHEM -\& SCOPE_NAME -\& MAX_CARDINALITY -\& DTD_IDENTIFIER -\& IS_SELF_REF -.Ve -.PP -Drivers capable of supplying any of those values should do so in -the corresponding column and supply undef values for the others. -.PP -Drivers wishing to provide extra database/driver specific information -should do so in extra columns beyond all those listed above, and -use lowercase field names with the driver-specific prefix (i.e., -\&'ora_...'). Applications accessing such fields should do so by name -and not by column number. -.PP -The result set is ordered by \s-1TABLE_CAT, TABLE_SCHEM, TABLE_NAME\s0 -and \s-1ORDINAL_POSITION.\s0 -.PP -Note: There is some overlap with statement handle attributes (in perl) and -SQLDescribeCol (in \s-1ODBC\s0). However, SQLColumns provides more metadata. -.PP -See also \*(L"Catalog Methods\*(R" and \*(L"Standards Reference Information\*(R". -.PP -\fI\f(CI\*(C`primary_key_info\*(C'\fI\fR -.IX Subsection "primary_key_info" -.PP -.Vb 1 -\& $sth = $dbh\->primary_key_info( $catalog, $schema, $table ); -\& -\& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc -.Ve -.PP -Returns an active statement handle that can be used to fetch information -about columns that make up the primary key for a table. -The arguments don't accept search patterns (unlike \fItable_info()\fR). -.PP -The statement handle will return one row per column, ordered by -\&\s-1TABLE_CAT, TABLE_SCHEM, TABLE_NAME,\s0 and \s-1KEY_SEQ.\s0 -If there is no primary key then the statement handle will fetch no rows. -.PP -Note: The support for the selection criteria, such as \f(CW$catalog\fR, is -driver specific. If the driver doesn't support catalogs and/or -schemas, it may ignore these criteria. -.PP -The statement handle returned has at least the following fields in the -order shown below. Other fields, after these, may also be present. -.PP -\&\fB\s-1TABLE_CAT\s0\fR: The catalog identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -which is often the case. This field is empty if not applicable to the -table. -.PP -\&\fB\s-1TABLE_SCHEM\s0\fR: The schema identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -and empty if not applicable to the table. -.PP -\&\fB\s-1TABLE_NAME\s0\fR: The table identifier. -.PP -\&\fB\s-1COLUMN_NAME\s0\fR: The column identifier. -.PP -\&\fB\s-1KEY_SEQ\s0\fR: The column sequence number (starting with 1). -Note: This field is named \fB\s-1ORDINAL_POSITION\s0\fR in \s-1SQL/CLI.\s0 -.PP -\&\fB\s-1PK_NAME\s0\fR: The primary key constraint identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source. -.PP -See also \*(L"Catalog Methods\*(R" and \*(L"Standards Reference Information\*(R". -.PP -\fI\f(CI\*(C`primary_key\*(C'\fI\fR -.IX Subsection "primary_key" -.PP -.Vb 1 -\& @key_column_names = $dbh\->primary_key( $catalog, $schema, $table ); -.Ve -.PP -Simple interface to the \fIprimary_key_info()\fR method. Returns a list of -the column names that comprise the primary key of the specified table. -The list is in primary key column sequence order. -If there is no primary key then an empty list is returned. -.PP -\fI\f(CI\*(C`foreign_key_info\*(C'\fI\fR -.IX Subsection "foreign_key_info" -.PP -.Vb 2 -\& $sth = $dbh\->foreign_key_info( $pk_catalog, $pk_schema, $pk_table -\& , $fk_catalog, $fk_schema, $fk_table ); -\& -\& $sth = $dbh\->foreign_key_info( $pk_catalog, $pk_schema, $pk_table -\& , $fk_catalog, $fk_schema, $fk_table -\& , \e%attr ); -\& -\& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc -.Ve -.PP -Returns an active statement handle that can be used to fetch information -about foreign keys in and/or referencing the specified table(s). -The arguments don't accept search patterns (unlike \fItable_info()\fR). -.PP -\&\f(CW$pk_catalog\fR, \f(CW$pk_schema\fR, \f(CW$pk_table\fR -identify the primary (unique) key table (\fB\s-1PKT\s0\fR). -.PP -\&\f(CW$fk_catalog\fR, \f(CW$fk_schema\fR, \f(CW$fk_table\fR -identify the foreign key table (\fB\s-1FKT\s0\fR). -.PP -If both \fB\s-1PKT\s0\fR and \fB\s-1FKT\s0\fR are given, the function returns the foreign key, if -any, in table \fB\s-1FKT\s0\fR that refers to the primary (unique) key of table \fB\s-1PKT\s0\fR. -(Note: In \s-1SQL/CLI,\s0 the result is implementation-defined.) -.PP -If only \fB\s-1PKT\s0\fR is given, then the result set contains the primary key -of that table and all foreign keys that refer to it. -.PP -If only \fB\s-1FKT\s0\fR is given, then the result set contains all foreign keys -in that table and the primary keys to which they refer. -(Note: In \s-1SQL/CLI,\s0 the result includes unique keys too.) -.PP -For example: -.PP -.Vb 3 -\& $sth = $dbh\->foreign_key_info( undef, $user, \*(Aqmaster\*(Aq); -\& $sth = $dbh\->foreign_key_info( undef, undef, undef , undef, $user, \*(Aqdetail\*(Aq); -\& $sth = $dbh\->foreign_key_info( undef, $user, \*(Aqmaster\*(Aq, undef, $user, \*(Aqdetail\*(Aq); -\& -\& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc -.Ve -.PP -Note: The support for the selection criteria, such as \f(CW$catalog\fR, is -driver specific. If the driver doesn't support catalogs and/or -schemas, it may ignore these criteria. -.PP -The statement handle returned has the following fields in the order shown below. -Because \s-1ODBC\s0 never includes unique keys, they define different columns in the -result set than \s-1SQL/CLI. SQL/CLI\s0 column names are shown in parentheses. -.PP -\&\fB\s-1PKTABLE_CAT \s0( \s-1UK_TABLE_CAT \s0)\fR: -The primary (unique) key table catalog identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -which is often the case. This field is empty if not applicable to the -table. -.PP -\&\fB\s-1PKTABLE_SCHEM \s0( \s-1UK_TABLE_SCHEM \s0)\fR: -The primary (unique) key table schema identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -and empty if not applicable to the table. -.PP -\&\fB\s-1PKTABLE_NAME \s0( \s-1UK_TABLE_NAME \s0)\fR: -The primary (unique) key table identifier. -.PP -\&\fB\s-1PKCOLUMN_NAME \s0(\s-1UK_COLUMN_NAME \s0)\fR: -The primary (unique) key column identifier. -.PP -\&\fB\s-1FKTABLE_CAT \s0( \s-1FK_TABLE_CAT \s0)\fR: -The foreign key table catalog identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -which is often the case. This field is empty if not applicable to the -table. -.PP -\&\fB\s-1FKTABLE_SCHEM \s0( \s-1FK_TABLE_SCHEM \s0)\fR: -The foreign key table schema identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -and empty if not applicable to the table. -.PP -\&\fB\s-1FKTABLE_NAME \s0( \s-1FK_TABLE_NAME \s0)\fR: -The foreign key table identifier. -.PP -\&\fB\s-1FKCOLUMN_NAME \s0( \s-1FK_COLUMN_NAME \s0)\fR: -The foreign key column identifier. -.PP -\&\fB\s-1KEY_SEQ \s0( \s-1ORDINAL_POSITION \s0)\fR: -The column sequence number (starting with 1). -.PP -\&\fB\s-1UPDATE_RULE \s0( \s-1UPDATE_RULE \s0)\fR: -The referential action for the \s-1UPDATE\s0 rule. -The following codes are defined: -.PP -.Vb 5 -\& CASCADE 0 -\& RESTRICT 1 -\& SET NULL 2 -\& NO ACTION 3 -\& SET DEFAULT 4 -.Ve -.PP -\&\fB\s-1DELETE_RULE \s0( \s-1DELETE_RULE \s0)\fR: -The referential action for the \s-1DELETE\s0 rule. -The codes are the same as for \s-1UPDATE_RULE.\s0 -.PP -\&\fB\s-1FK_NAME \s0( \s-1FK_NAME \s0)\fR: -The foreign key name. -.PP -\&\fB\s-1PK_NAME \s0( \s-1UK_NAME \s0)\fR: -The primary (unique) key name. -.PP -\&\fB\s-1DEFERRABILITY \s0( \s-1DEFERABILITY \s0)\fR: -The deferrability of the foreign key constraint. -The following codes are defined: -.PP -.Vb 3 -\& INITIALLY DEFERRED 5 -\& INITIALLY IMMEDIATE 6 -\& NOT DEFERRABLE 7 -.Ve -.PP -\&\fB ( \s-1UNIQUE_OR_PRIMARY \s0)\fR: -This column is necessary if a driver includes all candidate (i.e. primary and -alternate) keys in the result set (as specified by \s-1SQL/CLI\s0). -The value of this column is \s-1UNIQUE\s0 if the foreign key references an alternate -key and \s-1PRIMARY\s0 if the foreign key references a primary key, or it -may be undefined if the driver doesn't have access to the information. -.PP -See also \*(L"Catalog Methods\*(R" and \*(L"Standards Reference Information\*(R". -.PP -\fI\f(CI\*(C`statistics_info\*(C'\fI\fR -.IX Subsection "statistics_info" -.PP -\&\fBWarning:\fR This method is experimental and may change. -.PP -.Vb 1 -\& $sth = $dbh\->statistics_info( $catalog, $schema, $table, $unique_only, $quick ); -\& -\& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc -.Ve -.PP -Returns an active statement handle that can be used to fetch statistical -information about a table and its indexes. -.PP -The arguments don't accept search patterns (unlike \*(L"table_info\*(R"). -.PP -If the boolean argument \f(CW$unique_only\fR is true, only \s-1UNIQUE\s0 indexes will be -returned in the result set, otherwise all indexes will be returned. -.PP -If the boolean argument \f(CW$quick\fR is set, the actual statistical information -columns (\s-1CARDINALITY\s0 and \s-1PAGES\s0) will only be returned if they are readily -available from the server, and might not be current. Some databases may -return stale statistics or no statistics at all with this flag set. -.PP -The statement handle will return at most one row per column name per index, -plus at most one row for the entire table itself, ordered by \s-1NON_UNIQUE, TYPE, -INDEX_QUALIFIER, INDEX_NAME,\s0 and \s-1ORDINAL_POSITION.\s0 -.PP -Note: The support for the selection criteria, such as \f(CW$catalog\fR, is -driver specific. If the driver doesn't support catalogs and/or -schemas, it may ignore these criteria. -.PP -The statement handle returned has at least the following fields in the -order shown below. Other fields, after these, may also be present. -.PP -\&\fB\s-1TABLE_CAT\s0\fR: The catalog identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -which is often the case. This field is empty if not applicable to the -table. -.PP -\&\fB\s-1TABLE_SCHEM\s0\fR: The schema identifier. -This field is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, -and empty if not applicable to the table. -.PP -\&\fB\s-1TABLE_NAME\s0\fR: The table identifier. -.PP -\&\fB\s-1NON_UNIQUE\s0\fR: Unique index indicator. -Returns 0 for unique indexes, 1 for non-unique indexes -.PP -\&\fB\s-1INDEX_QUALIFIER\s0\fR: Index qualifier identifier. -The identifier that is used to qualify the index name when doing a -\&\f(CW\*(C`DROP INDEX\*(C'\fR; \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned if an index qualifier is not -supported by the data source. -If a non-NULL (defined) value is returned in this column, it must be used -to qualify the index name on a \f(CW\*(C`DROP INDEX\*(C'\fR statement; otherwise, -the \s-1TABLE_SCHEM\s0 should be used to qualify the index name. -.PP -\&\fB\s-1INDEX_NAME\s0\fR: The index identifier. -.PP -\&\fB\s-1TYPE\s0\fR: The type of information being returned. Can be any of the -following values: 'table', 'btree', 'clustered', 'content', 'hashed', -or 'other'. -.PP -In the case that this field is 'table', all fields -other than \s-1TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TYPE, -CARDINALITY,\s0 and \s-1PAGES\s0 will be \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR). -.PP -\&\fB\s-1ORDINAL_POSITION\s0\fR: Column sequence number (starting with 1). -.PP -\&\fB\s-1COLUMN_NAME\s0\fR: The column identifier. -.PP -\&\fB\s-1ASC_OR_DESC\s0\fR: Column sort sequence. -\&\f(CW\*(C`A\*(C'\fR for Ascending, \f(CW\*(C`D\*(C'\fR for Descending, or \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) if -not supported for this index. -.PP -\&\fB\s-1CARDINALITY\s0\fR: Cardinality of the table or index. -For indexes, this is the number of unique values in the index. -For tables, this is the number of rows in the table. -If not supported, the value will be \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR). -.PP -\&\fB\s-1PAGES\s0\fR: Number of storage pages used by this table or index. -If not supported, the value will be \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR). -.PP -\&\fB\s-1FILTER_CONDITION\s0\fR: The index filter condition as a string. -If the index is not a filtered index, or it cannot be determined -whether the index is a filtered index, this value is \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR). -If the index is a filtered index, but the filter condition -cannot be determined, this value is the empty string \f(CW\*(Aq\*(Aq\fR. -Otherwise it will be the literal filter condition as a string, -such as \f(CW\*(C`SALARY <= 4500\*(C'\fR. -.PP -See also \*(L"Catalog Methods\*(R" and \*(L"Standards Reference Information\*(R". -.PP -\fI\f(CI\*(C`tables\*(C'\fI\fR -.IX Subsection "tables" -.PP -.Vb 2 -\& @names = $dbh\->tables( $catalog, $schema, $table, $type ); -\& @names = $dbh\->tables; # deprecated -.Ve -.PP -Simple interface to \fItable_info()\fR. Returns a list of matching -table names, possibly including a catalog/schema prefix. -.PP -See \*(L"table_info\*(R" for a description of the parameters. -.PP -If \f(CW\*(C`$dbh\->get_info(29)\*(C'\fR returns true (29 is \s-1SQL_IDENTIFIER_QUOTE_CHAR\s0) -then the table names are constructed and quoted by \*(L"quote_identifier\*(R" -to ensure they are usable even if they contain whitespace or reserved -words etc. This means that the table names returned will include -quote characters. -.PP -\fI\f(CI\*(C`type_info_all\*(C'\fI\fR -.IX Subsection "type_info_all" -.PP -.Vb 1 -\& $type_info_all = $dbh\->type_info_all; -.Ve -.PP -Returns a reference to an array which holds information about each data -type variant supported by the database and driver. The array and its -contents should be treated as read-only. -.PP -The first item is a reference to an 'index' hash of \f(CW\*(C`Name =\*(C'\fR> \f(CW\*(C`Index\*(C'\fR pairs. -The items following that are references to arrays, one per supported data -type variant. The leading index hash defines the names and order of the -fields within the arrays that follow it. -For example: -.PP -.Vb 10 -\& $type_info_all = [ -\& { TYPE_NAME => 0, -\& DATA_TYPE => 1, -\& COLUMN_SIZE => 2, # was PRECISION originally -\& LITERAL_PREFIX => 3, -\& LITERAL_SUFFIX => 4, -\& CREATE_PARAMS => 5, -\& NULLABLE => 6, -\& CASE_SENSITIVE => 7, -\& SEARCHABLE => 8, -\& UNSIGNED_ATTRIBUTE=> 9, -\& FIXED_PREC_SCALE => 10, # was MONEY originally -\& AUTO_UNIQUE_VALUE => 11, # was AUTO_INCREMENT originally -\& LOCAL_TYPE_NAME => 12, -\& MINIMUM_SCALE => 13, -\& MAXIMUM_SCALE => 14, -\& SQL_DATA_TYPE => 15, -\& SQL_DATETIME_SUB => 16, -\& NUM_PREC_RADIX => 17, -\& INTERVAL_PRECISION=> 18, -\& }, -\& [ \*(AqVARCHAR\*(Aq, SQL_VARCHAR, -\& undef, "\*(Aq","\*(Aq", undef,0, 1,1,0,0,0,undef,1,255, undef -\& ], -\& [ \*(AqINTEGER\*(Aq, SQL_INTEGER, -\& undef, "", "", undef,0, 0,1,0,0,0,undef,0, 0, 10 -\& ], -\& ]; -.Ve -.PP -More than one row may have the same value in the \f(CW\*(C`DATA_TYPE\*(C'\fR -field if there are different ways to spell the type name and/or there -are variants of the type with different attributes (e.g., with and -without \f(CW\*(C`AUTO_UNIQUE_VALUE\*(C'\fR set, with and without \f(CW\*(C`UNSIGNED_ATTRIBUTE\*(C'\fR, etc). -.PP -The rows are ordered by \f(CW\*(C`DATA_TYPE\*(C'\fR first and then by how closely each -type maps to the corresponding \s-1ODBC SQL\s0 data type, closest first. -.PP -The meaning of the fields is described in the documentation for -the \*(L"type_info\*(R" method. -.PP -An 'index' hash is provided so you don't need to rely on index -values defined above. However, using \s-1DBD::ODBC\s0 with some old \s-1ODBC\s0 -drivers may return older names, shown as comments in the example above. -Another issue with the index hash is that the lettercase of the -keys is not defined. It is usually uppercase, as show here, but -drivers may return names with any lettercase. -.PP -Drivers are also free to return extra driver-specific columns of -information \- though it's recommended that they start at column -index 50 to leave room for expansion of the \s-1DBI/ODBC\s0 specification. -.PP -The \fItype_info_all()\fR method is not normally used directly. -The \*(L"type_info\*(R" method provides a more usable and useful interface -to the data. -.PP -\fI\f(CI\*(C`type_info\*(C'\fI\fR -.IX Subsection "type_info" -.PP -.Vb 1 -\& @type_info = $dbh\->type_info($data_type); -.Ve -.PP -Returns a list of hash references holding information about one or more -variants of \f(CW$data_type\fR. The list is ordered by \f(CW\*(C`DATA_TYPE\*(C'\fR first and -then by how closely each type maps to the corresponding \s-1ODBC SQL\s0 data -type, closest first. If called in a scalar context then only the first -(best) element is returned. -.PP -If \f(CW$data_type\fR is undefined or \f(CW\*(C`SQL_ALL_TYPES\*(C'\fR, then the list will -contain hashes for all data type variants supported by the database and driver. -.PP -If \f(CW$data_type\fR is an array reference then \f(CW\*(C`type_info\*(C'\fR returns the -information for the \fIfirst\fR type in the array that has any matches. -.PP -The keys of the hash follow the same letter case conventions as the -rest of the \s-1DBI \s0(see \*(L"Naming Conventions and Name Space\*(R"). The -following uppercase items should always exist, though may be undef: -.IP "\s-1TYPE_NAME \s0(string)" 4 -.IX Item "TYPE_NAME (string)" -Data type name for use in \s-1CREATE TABLE\s0 statements etc. -.IP "\s-1DATA_TYPE \s0(integer)" 4 -.IX Item "DATA_TYPE (integer)" -\&\s-1SQL\s0 data type number. -.IP "\s-1COLUMN_SIZE \s0(integer)" 4 -.IX Item "COLUMN_SIZE (integer)" -For numeric types, this is either the total number of digits (if the -\&\s-1NUM_PREC_RADIX\s0 value is 10) or the total number of bits allowed in the -column (if \s-1NUM_PREC_RADIX\s0 is 2). -.Sp -For string types, this is the maximum size of the string in characters. -.Sp -For date and interval types, this is the maximum number of characters -needed to display the value. -.IP "\s-1LITERAL_PREFIX \s0(string)" 4 -.IX Item "LITERAL_PREFIX (string)" -Characters used to prefix a literal. A typical prefix is "\f(CW\*(C`\*(Aq\*(C'\fR\*(L" for characters, -or possibly \*(R"\f(CW\*(C`0x\*(C'\fR" for binary values passed as hexadecimal. \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is -returned for data types for which this is not applicable. -.IP "\s-1LITERAL_SUFFIX \s0(string)" 4 -.IX Item "LITERAL_SUFFIX (string)" -Characters used to suffix a literal. Typically "\f(CW\*(C`\*(Aq\*(C'\fR" for characters. -\&\s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned for data types where this is not applicable. -.IP "\s-1CREATE_PARAMS \s0(string)" 4 -.IX Item "CREATE_PARAMS (string)" -Parameter names for data type definition. For example, \f(CW\*(C`CREATE_PARAMS\*(C'\fR for a -\&\f(CW\*(C`DECIMAL\*(C'\fR would be "\f(CW\*(C`precision,scale\*(C'\fR" if the \s-1DECIMAL\s0 type should be -declared as \f(CW\*(C`DECIMAL(\*(C'\fR\fIprecision,scale\fR\f(CW\*(C`)\*(C'\fR where \fIprecision\fR and \fIscale\fR -are integer values. For a \f(CW\*(C`VARCHAR\*(C'\fR it would be "\f(CW\*(C`max length\*(C'\fR". -\&\s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned for data types for which this is not applicable. -.IP "\s-1NULLABLE \s0(integer)" 4 -.IX Item "NULLABLE (integer)" -Indicates whether the data type accepts a \s-1NULL\s0 value: -\&\f(CW0\fR or an empty string = no, \f(CW1\fR = yes, \f(CW2\fR = unknown. -.IP "\s-1CASE_SENSITIVE \s0(boolean)" 4 -.IX Item "CASE_SENSITIVE (boolean)" -Indicates whether the data type is case sensitive in collations and -comparisons. -.IP "\s-1SEARCHABLE \s0(integer)" 4 -.IX Item "SEARCHABLE (integer)" -Indicates how the data type can be used in a \s-1WHERE\s0 clause, as -follows: -.Sp -.Vb 4 -\& 0 \- Cannot be used in a WHERE clause -\& 1 \- Only with a LIKE predicate -\& 2 \- All comparison operators except LIKE -\& 3 \- Can be used in a WHERE clause with any comparison operator -.Ve -.IP "\s-1UNSIGNED_ATTRIBUTE \s0(boolean)" 4 -.IX Item "UNSIGNED_ATTRIBUTE (boolean)" -Indicates whether the data type is unsigned. \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned -for data types for which this is not applicable. -.IP "\s-1FIXED_PREC_SCALE \s0(boolean)" 4 -.IX Item "FIXED_PREC_SCALE (boolean)" -Indicates whether the data type always has the same precision and scale -(such as a money type). \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned for data types -for which -this is not applicable. -.IP "\s-1AUTO_UNIQUE_VALUE \s0(boolean)" 4 -.IX Item "AUTO_UNIQUE_VALUE (boolean)" -Indicates whether a column of this data type is automatically set to a -unique value whenever a new row is inserted. \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned -for data types for which this is not applicable. -.IP "\s-1LOCAL_TYPE_NAME \s0(string)" 4 -.IX Item "LOCAL_TYPE_NAME (string)" -Localized version of the \f(CW\*(C`TYPE_NAME\*(C'\fR for use in dialog with users. -\&\s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned if a localized name is not available (in which -case \f(CW\*(C`TYPE_NAME\*(C'\fR should be used). -.IP "\s-1MINIMUM_SCALE \s0(integer)" 4 -.IX Item "MINIMUM_SCALE (integer)" -The minimum scale of the data type. If a data type has a fixed scale, -then \f(CW\*(C`MAXIMUM_SCALE\*(C'\fR holds the same value. \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned for -data types for which this is not applicable. -.IP "\s-1MAXIMUM_SCALE \s0(integer)" 4 -.IX Item "MAXIMUM_SCALE (integer)" -The maximum scale of the data type. If a data type has a fixed scale, -then \f(CW\*(C`MINIMUM_SCALE\*(C'\fR holds the same value. \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned for -data types for which this is not applicable. -.IP "\s-1SQL_DATA_TYPE \s0(integer)" 4 -.IX Item "SQL_DATA_TYPE (integer)" -This column is the same as the \f(CW\*(C`DATA_TYPE\*(C'\fR column, except for interval -and datetime data types. For interval and datetime data types, the -\&\f(CW\*(C`SQL_DATA_TYPE\*(C'\fR field will return \f(CW\*(C`SQL_INTERVAL\*(C'\fR or \f(CW\*(C`SQL_DATETIME\*(C'\fR, and the -\&\f(CW\*(C`SQL_DATETIME_SUB\*(C'\fR field below will return the subcode for the specific -interval or datetime data type. If this field is \s-1NULL,\s0 then the driver -does not support or report on interval or datetime subtypes. -.IP "\s-1SQL_DATETIME_SUB \s0(integer)" 4 -.IX Item "SQL_DATETIME_SUB (integer)" -For interval or datetime data types, where the \f(CW\*(C`SQL_DATA_TYPE\*(C'\fR -field above is \f(CW\*(C`SQL_INTERVAL\*(C'\fR or \f(CW\*(C`SQL_DATETIME\*(C'\fR, this field will -hold the \fIsubcode\fR for the specific interval or datetime data type. -Otherwise it will be \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR). -.Sp -Although not mentioned explicitly in the standards, it seems there -is a simple relationship between these values: -.Sp -.Vb 1 -\& DATA_TYPE == (10 * SQL_DATA_TYPE) + SQL_DATETIME_SUB -.Ve -.IP "\s-1NUM_PREC_RADIX \s0(integer)" 4 -.IX Item "NUM_PREC_RADIX (integer)" -The radix value of the data type. For approximate numeric types, -\&\f(CW\*(C`NUM_PREC_RADIX\*(C'\fR -contains the value 2 and \f(CW\*(C`COLUMN_SIZE\*(C'\fR holds the number of bits. For -exact numeric types, \f(CW\*(C`NUM_PREC_RADIX\*(C'\fR contains the value 10 and \f(CW\*(C`COLUMN_SIZE\*(C'\fR holds -the number of decimal digits. \s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) is returned either for data types -for which this is not applicable or if the driver cannot report this information. -.IP "\s-1INTERVAL_PRECISION \s0(integer)" 4 -.IX Item "INTERVAL_PRECISION (integer)" -The interval leading precision for interval types. \s-1NULL\s0 is returned -either for data types for which this is not applicable or if the driver -cannot report this information. -.PP -For example, to find the type name for the fields in a select statement -you can do: -.PP -.Vb 1 -\& @names = map { scalar $dbh\->type_info($_)\->{TYPE_NAME} } @{ $sth\->{TYPE} } -.Ve -.PP -Since \s-1DBI\s0 and \s-1ODBC\s0 drivers vary in how they map their types into the -\&\s-1ISO\s0 standard types you may need to search for more than one type. -Here's an example looking for a usable type to store a date: -.PP -.Vb 1 -\& $my_date_type = $dbh\->type_info( [ SQL_DATE, SQL_TIMESTAMP ] ); -.Ve -.PP -Similarly, to more reliably find a type to store small integers, you could -use a list starting with \f(CW\*(C`SQL_SMALLINT\*(C'\fR, \f(CW\*(C`SQL_INTEGER\*(C'\fR, \f(CW\*(C`SQL_DECIMAL\*(C'\fR, etc. -.PP -See also \*(L"Standards Reference Information\*(R". -.PP -\fI\f(CI\*(C`quote\*(C'\fI\fR -.IX Subsection "quote" -.PP -.Vb 2 -\& $sql = $dbh\->quote($value); -\& $sql = $dbh\->quote($value, $data_type); -.Ve -.PP -Quote a string literal for use as a literal value in an \s-1SQL\s0 statement, -by escaping any special characters (such as quotation marks) -contained within the string and adding the required type of outer -quotation marks. -.PP -.Vb 2 -\& $sql = sprintf "SELECT foo FROM bar WHERE baz = %s", -\& $dbh\->quote("Don\*(Aqt"); -.Ve -.PP -For most database types, at least those that conform to \s-1SQL\s0 standards, quote -would return \f(CW\*(AqDon\*(Aq\*(Aqt\*(Aq\fR (including the outer quotation marks). For others it -may return something like \f(CW\*(AqDon\e\*(Aqt\*(Aq\fR -.PP -An undefined \f(CW$value\fR value will be returned as the string \f(CW\*(C`NULL\*(C'\fR (without -single quotation marks) to match how NULLs are represented in \s-1SQL.\s0 -.PP -If \f(CW$data_type\fR is supplied, it is used to try to determine the required -quoting behaviour by using the information returned by \*(L"type_info\*(R". -As a special case, the standard numeric types are optimized to return -\&\f(CW$value\fR without calling \f(CW\*(C`type_info\*(C'\fR. -.PP -Quote will probably \fInot\fR be able to deal with all possible input -(such as binary data or data containing newlines), and is not related in -any way with escaping or quoting shell meta-characters. -.PP -It is valid for the \fIquote()\fR method to return an \s-1SQL\s0 expression that -evaluates to the desired string. For example: -.PP -.Vb 1 -\& $quoted = $dbh\->quote("one\entwo\e0three") -.Ve -.PP -may return something like: -.PP -.Vb 1 -\& CONCAT(\*(Aqone\*(Aq, CHAR(12), \*(Aqtwo\*(Aq, CHAR(0), \*(Aqthree\*(Aq) -.Ve -.PP -The \fIquote()\fR method should \fInot\fR be used with \*(L"Placeholders and -Bind Values\*(R". -.PP -\fI\f(CI\*(C`quote_identifier\*(C'\fI\fR -.IX Subsection "quote_identifier" -.PP -.Vb 2 -\& $sql = $dbh\->quote_identifier( $name ); -\& $sql = $dbh\->quote_identifier( $catalog, $schema, $table, \e%attr ); -.Ve -.PP -Quote an identifier (table name etc.) for use in an \s-1SQL\s0 statement, -by escaping any special characters (such as double quotation marks) -it contains and adding the required type of outer quotation marks. -.PP -Undefined names are ignored and the remainder are quoted and then -joined together, typically with a dot (\f(CW\*(C`.\*(C'\fR) character. For example: -.PP -.Vb 1 -\& $id = $dbh\->quote_identifier( undef, \*(AqHer schema\*(Aq, \*(AqMy table\*(Aq ); -.Ve -.PP -would, for most database types, return \f(CW"Her schema"."My table"\fR -(including all the double quotation marks). -.PP -If three names are supplied then the first is assumed to be a -catalog name and special rules may be applied based on what \*(L"get_info\*(R" -returns for \s-1SQL_CATALOG_NAME_SEPARATOR \s0(41) and \s-1SQL_CATALOG_LOCATION \s0(114). -For example, for Oracle: -.PP -.Vb 1 -\& $id = $dbh\->quote_identifier( \*(Aqlink\*(Aq, \*(Aqschema\*(Aq, \*(Aqtable\*(Aq ); -.Ve -.PP -would return \f(CW"schema"."table"@"link"\fR. -.PP -\fI\f(CI\*(C`take_imp_data\*(C'\fI\fR -.IX Subsection "take_imp_data" -.PP -.Vb 1 -\& $imp_data = $dbh\->take_imp_data; -.Ve -.PP -Leaves the \f(CW$dbh\fR in an almost dead, zombie-like, state and returns -a binary string of raw implementation data from the driver which -describes the current database connection. Effectively it detaches -the underlying database \s-1API\s0 connection data from the \s-1DBI\s0 handle. -After calling \fItake_imp_data()\fR, all other methods except \f(CW\*(C`DESTROY\*(C'\fR -will generate a warning and return undef. -.PP -Why would you want to do this? You don't, forget I even mentioned it. -Unless, that is, you're implementing something advanced like a -multi-threaded connection pool. See DBI::Pool. -.PP -The returned \f(CW$imp_data\fR can be passed as a \f(CW\*(C`dbi_imp_data\*(C'\fR attribute -to a later \fIconnect()\fR call, even in a separate thread in the same -process, where the driver can use it to 'adopt' the existing -connection that the implementation data was taken from. -.PP -Some things to keep in mind... -.PP -\&\fB*\fR the \f(CW$imp_data\fR holds the only reference to the underlying -database \s-1API\s0 connection data. That connection is still 'live' and -won't be cleaned up properly unless the \f(CW$imp_data\fR is used to create -a new \f(CW$dbh\fR which is then allowed to \fIdisconnect()\fR normally. -.PP -\&\fB*\fR using the same \f(CW$imp_data\fR to create more than one other new -\&\f(CW$dbh\fR at a time may well lead to unpleasant problems. Don't do that. -.PP -Any child statement handles are effectively destroyed when \fItake_imp_data()\fR is -called. -.PP -The \f(CW\*(C`take_imp_data\*(C'\fR method was added in \s-1DBI 1.36\s0 but wasn't useful till 1.49. -.SS "Database Handle Attributes" -.IX Subsection "Database Handle Attributes" -This section describes attributes specific to database handles. -.PP -Changes to these database handle attributes do not affect any other -existing or future database handles. -.PP -Attempting to set or get the value of an unknown attribute generates a warning, -except for private driver-specific attributes (which all have names -starting with a lowercase letter). -.PP -Example: -.PP -.Vb 2 -\& $h\->{AutoCommit} = ...; # set/write -\& ... = $h\->{AutoCommit}; # get/read -.Ve -.PP -\fI\f(CI\*(C`AutoCommit\*(C'\fI\fR -.IX Subsection "AutoCommit" -.PP -Type: boolean -.PP -If true, then database changes cannot be rolled-back (undone). If false, -then database changes automatically occur within a \*(L"transaction\*(R", which -must either be committed or rolled back using the \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR -methods. -.PP -Drivers should always default to \f(CW\*(C`AutoCommit\*(C'\fR mode (an unfortunate -choice largely forced on the \s-1DBI\s0 by \s-1ODBC\s0 and \s-1JDBC\s0 conventions.) -.PP -Attempting to set \f(CW\*(C`AutoCommit\*(C'\fR to an unsupported value is a fatal error. -This is an important feature of the \s-1DBI.\s0 Applications that need -full transaction behaviour can set \f(CW\*(C`$dbh\->{AutoCommit} = 0\*(C'\fR (or -set \f(CW\*(C`AutoCommit\*(C'\fR to 0 via \*(L"connect\*(R") -without having to check that the value was assigned successfully. -.PP -For the purposes of this description, we can divide databases into three -categories: -.PP -.Vb 3 -\& Databases which don\*(Aqt support transactions at all. -\& Databases in which a transaction is always active. -\& Databases in which a transaction must be explicitly started (C<\*(AqBEGIN WORK\*(Aq>). -.Ve -.PP -\&\fB* Databases which don't support transactions at all\fR -.PP -For these databases, attempting to turn \f(CW\*(C`AutoCommit\*(C'\fR off is a fatal error. -\&\f(CW\*(C`commit\*(C'\fR and \f(CW\*(C`rollback\*(C'\fR both issue warnings about being ineffective while -\&\f(CW\*(C`AutoCommit\*(C'\fR is in effect. -.PP -\&\fB* Databases in which a transaction is always active\fR -.PP -These are typically mainstream commercial relational databases with -\&\*(L"\s-1ANSI\s0 standard\*(R" transaction behaviour. -If \f(CW\*(C`AutoCommit\*(C'\fR is off, then changes to the database won't have any -lasting effect unless \*(L"commit\*(R" is called (but see also -\&\*(L"disconnect\*(R"). If \*(L"rollback\*(R" is called then any changes since the -last commit are undone. -.PP -If \f(CW\*(C`AutoCommit\*(C'\fR is on, then the effect is the same as if the \s-1DBI\s0 -called \f(CW\*(C`commit\*(C'\fR automatically after every successful database -operation. So calling \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR explicitly while -\&\f(CW\*(C`AutoCommit\*(C'\fR is on would be ineffective because the changes would -have already been committed. -.PP -Changing \f(CW\*(C`AutoCommit\*(C'\fR from off to on will trigger a \*(L"commit\*(R". -.PP -For databases which don't support a specific auto-commit mode, the -driver has to commit each statement automatically using an explicit -\&\f(CW\*(C`COMMIT\*(C'\fR after it completes successfully (and roll it back using an -explicit \f(CW\*(C`ROLLBACK\*(C'\fR if it fails). The error information reported to the -application will correspond to the statement which was executed, unless -it succeeded and the commit or rollback failed. -.PP -\&\fB* Databases in which a transaction must be explicitly started\fR -.PP -For these databases, the intention is to have them act like databases in -which a transaction is always active (as described above). -.PP -To do this, the driver will automatically begin an explicit transaction -when \f(CW\*(C`AutoCommit\*(C'\fR is turned off, or after a \*(L"commit\*(R" or -\&\*(L"rollback\*(R" (or when the application issues the next database -operation after one of those events). -.PP -In this way, the application does not have to treat these databases -as a special case. -.PP -See \*(L"commit\*(R", \*(L"disconnect\*(R" and \*(L"Transactions\*(R" for other important -notes about transactions. -.PP -\fI\f(CI\*(C`Driver\*(C'\fI\fR -.IX Subsection "Driver" -.PP -Type: handle -.PP -Holds the handle of the parent driver. The only recommended use for this -is to find the name of the driver using: -.PP -.Vb 1 -\& $dbh\->{Driver}\->{Name} -.Ve -.PP -\fI\f(CI\*(C`Name\*(C'\fI\fR -.IX Subsection "Name" -.PP -Type: string -.PP -Holds the \*(L"name\*(R" of the database. Usually (and recommended to be) the -same as the "\f(CW\*(C`dbi:DriverName:...\*(C'\fR\*(L" string used to connect to the database, -but with the leading \*(R"\f(CW\*(C`dbi:DriverName:\*(C'\fR" removed. -.PP -\fI\f(CI\*(C`Statement\*(C'\fI\fR -.IX Subsection "Statement" -.PP -Type: string, read-only -.PP -Returns the statement string passed to the most recent \*(L"prepare\*(R" or -\&\*(L"do\*(R" method called in this database handle, even if that method -failed. This is especially useful where \f(CW\*(C`RaiseError\*(C'\fR is enabled and -the exception handler checks $@ and sees that a 'prepare' method call -failed. -.PP -\fI\f(CI\*(C`RowCacheSize\*(C'\fI\fR -.IX Subsection "RowCacheSize" -.PP -Type: integer -.PP -A hint to the driver indicating the size of the local row cache that the -application would like the driver to use for future \f(CW\*(C`SELECT\*(C'\fR statements. -If a row cache is not implemented, then setting \f(CW\*(C`RowCacheSize\*(C'\fR is ignored -and getting the value returns \f(CW\*(C`undef\*(C'\fR. -.PP -Some \f(CW\*(C`RowCacheSize\*(C'\fR values have special meaning, as follows: -.PP -.Vb 4 -\& 0 \- Automatically determine a reasonable cache size for each C. -.Ve -.PP -Note that large cache sizes may require a very large amount of memory -(\fIcached rows * maximum size of row\fR). Also, a large cache will cause -a longer delay not only for the first fetch, but also whenever the -cache needs refilling. -.PP -See also the \*(L"RowsInCache\*(R" statement handle attribute. -.PP -\fI\f(CI\*(C`Username\*(C'\fI\fR -.IX Subsection "Username" -.PP -Type: string -.PP -Returns the username used to connect to the database. -.SH "DBI STATEMENT HANDLE OBJECTS" -.IX Header "DBI STATEMENT HANDLE OBJECTS" -This section lists the methods and attributes associated with \s-1DBI\s0 -statement handles. -.SS "Statement Handle Methods" -.IX Subsection "Statement Handle Methods" -The \s-1DBI\s0 defines the following methods for use on \s-1DBI\s0 statement handles: -.PP -\fI\f(CI\*(C`bind_param\*(C'\fI\fR -.IX Subsection "bind_param" -.PP -.Vb 3 -\& $sth\->bind_param($p_num, $bind_value) -\& $sth\->bind_param($p_num, $bind_value, \e%attr) -\& $sth\->bind_param($p_num, $bind_value, $bind_type) -.Ve -.PP -The \f(CW\*(C`bind_param\*(C'\fR method takes a copy of \f(CW$bind_value\fR and associates it -(binds it) with a placeholder, identified by \f(CW$p_num\fR, embedded in -the prepared statement. Placeholders are indicated with question -mark character (\f(CW\*(C`?\*(C'\fR). For example: -.PP -.Vb 5 -\& $dbh\->{RaiseError} = 1; # save having to check each method call -\& $sth = $dbh\->prepare("SELECT name, age FROM people WHERE name LIKE ?"); -\& $sth\->bind_param(1, "John%"); # placeholders are numbered from 1 -\& $sth\->execute; -\& DBI::dump_results($sth); -.Ve -.PP -See \*(L"Placeholders and Bind Values\*(R" for more information. -.PP -\&\fBData Types for Placeholders\fR -.PP -The \f(CW\*(C`\e%attr\*(C'\fR parameter can be used to hint at the data type the -placeholder should have. This is rarely needed. Typically, the driver is only -interested in knowing if the placeholder should be bound as a number or a string. -.PP -.Vb 1 -\& $sth\->bind_param(1, $value, { TYPE => SQL_INTEGER }); -.Ve -.PP -As a short-cut for the common case, the data type can be passed -directly, in place of the \f(CW\*(C`\e%attr\*(C'\fR hash reference. This example is -equivalent to the one above: -.PP -.Vb 1 -\& $sth\->bind_param(1, $value, SQL_INTEGER); -.Ve -.PP -The \f(CW\*(C`TYPE\*(C'\fR value indicates the standard (non-driver-specific) type for -this parameter. To specify the driver-specific type, the driver may -support a driver-specific attribute, such as \f(CW\*(C`{ ora_type => 97 }\*(C'\fR. -.PP -The \s-1SQL_INTEGER\s0 and other related constants can be imported using -.PP -.Vb 1 -\& use DBI qw(:sql_types); -.Ve -.PP -See \*(L"\s-1DBI\s0 Constants\*(R" for more information. -.PP -The data type is 'sticky' in that bind values passed to \fIexecute()\fR are bound -with the data type specified by earlier \fIbind_param()\fR calls, if any. -Portable applications should not rely on being able to change the data type -after the first \f(CW\*(C`bind_param\*(C'\fR call. -.PP -Perl only has string and number scalar data types. All database types -that aren't numbers are bound as strings and must be in a format the -database will understand except where the \fIbind_param()\fR \s-1TYPE\s0 attribute -specifies a type that implies a particular format. For example, given: -.PP -.Vb 1 -\& $sth\->bind_param(1, $value, SQL_DATETIME); -.Ve -.PP -the driver should expect \f(CW$value\fR to be in the \s-1ODBC\s0 standard \s-1SQL_DATETIME\s0 -format, which is '\s-1YYYY\-MM\-DD HH:MM:SS\s0'. Similarly for \s-1SQL_DATE, SQL_TIME\s0 etc. -.PP -As an alternative to specifying the data type in the \f(CW\*(C`bind_param\*(C'\fR call, -you can let the driver pass the value as the default type (\f(CW\*(C`VARCHAR\*(C'\fR). -You can then use an \s-1SQL\s0 function to convert the type within the statement. -For example: -.PP -.Vb 1 -\& INSERT INTO price(code, price) VALUES (?, CONVERT(MONEY,?)) -.Ve -.PP -The \f(CW\*(C`CONVERT\*(C'\fR function used here is just an example. The actual function -and syntax will vary between different databases and is non-portable. -.PP -See also \*(L"Placeholders and Bind Values\*(R" for more information. -.PP -\fI\f(CI\*(C`bind_param_inout\*(C'\fI\fR -.IX Subsection "bind_param_inout" -.PP -.Vb 3 -\& $rc = $sth\->bind_param_inout($p_num, \e$bind_value, $max_len) or die $sth\->errstr; -\& $rv = $sth\->bind_param_inout($p_num, \e$bind_value, $max_len, \e%attr) or ... -\& $rv = $sth\->bind_param_inout($p_num, \e$bind_value, $max_len, $bind_type) or ... -.Ve -.PP -This method acts like \*(L"bind_param\*(R", but also enables values to be -updated by the statement. The statement is typically -a call to a stored procedure. The \f(CW$bind_value\fR must be passed as a -reference to the actual value to be used. -.PP -Note that unlike \*(L"bind_param\*(R", the \f(CW$bind_value\fR variable is not -copied when \f(CW\*(C`bind_param_inout\*(C'\fR is called. Instead, the value in the -variable is read at the time \*(L"execute\*(R" is called. -.PP -The additional \f(CW$max_len\fR parameter specifies the minimum amount of -memory to allocate to \f(CW$bind_value\fR for the new value. If the value -returned from the database is too -big to fit, then the execution should fail. If unsure what value to use, -pick a generous length, i.e., a length larger than the longest value that would ever be -returned. The only cost of using a larger value than needed is wasted memory. -.PP -Undefined values or \f(CW\*(C`undef\*(C'\fR are used to indicate null values. -See also \*(L"Placeholders and Bind Values\*(R" for more information. -.PP -\fI\f(CI\*(C`bind_param_array\*(C'\fI\fR -.IX Subsection "bind_param_array" -.PP -.Vb 3 -\& $rc = $sth\->bind_param_array($p_num, $array_ref_or_value) -\& $rc = $sth\->bind_param_array($p_num, $array_ref_or_value, \e%attr) -\& $rc = $sth\->bind_param_array($p_num, $array_ref_or_value, $bind_type) -.Ve -.PP -The \f(CW\*(C`bind_param_array\*(C'\fR method is used to bind an array of values -to a placeholder embedded in the prepared statement which is to be executed -with \*(L"execute_array\*(R". For example: -.PP -.Vb 6 -\& $dbh\->{RaiseError} = 1; # save having to check each method call -\& $sth = $dbh\->prepare("INSERT INTO staff (first_name, last_name, dept) VALUES(?, ?, ?)"); -\& $sth\->bind_param_array(1, [ \*(AqJohn\*(Aq, \*(AqMary\*(Aq, \*(AqTim\*(Aq ]); -\& $sth\->bind_param_array(2, [ \*(AqBooth\*(Aq, \*(AqTodd\*(Aq, \*(AqRobinson\*(Aq ]); -\& $sth\->bind_param_array(3, "SALES"); # scalar will be reused for each row -\& $sth\->execute_array( { ArrayTupleStatus => \emy @tuple_status } ); -.Ve -.PP -The \f(CW%attr\fR ($bind_type) argument is the same as defined for \*(L"bind_param\*(R". -Refer to \*(L"bind_param\*(R" for general details on using placeholders. -.PP -(Note that \fIbind_param_array()\fR can \fInot\fR be used to expand a -placeholder into a list of values for a statement like \*(L"\s-1SELECT\s0 foo -\&\s-1WHERE\s0 bar \s-1IN \s0(?)\*(R". A placeholder can only ever represent one value -per execution.) -.PP -Scalar values, including \f(CW\*(C`undef\*(C'\fR, may also be bound by -\&\f(CW\*(C`bind_param_array\*(C'\fR. In which case the same value will be used for each -\&\*(L"execute\*(R" call. Driver-specific implementations may behave -differently, e.g., when binding to a stored procedure call, some -databases may permit mixing scalars and arrays as arguments. -.PP -The default implementation provided by \s-1DBI \s0(for drivers that have -not implemented array binding) is to iteratively call \*(L"execute\*(R" for -each parameter tuple provided in the bound arrays. Drivers may -provide more optimized implementations using whatever bulk operation -support the database \s-1API\s0 provides. The default driver behaviour should -match the default \s-1DBI\s0 behaviour, but always consult your driver -documentation as there may be driver specific issues to consider. -.PP -Note that the default implementation currently only supports non-data -returning statements (\s-1INSERT, UPDATE,\s0 but not \s-1SELECT\s0). Also, -\&\f(CW\*(C`bind_param_array\*(C'\fR and \*(L"bind_param\*(R" cannot be mixed in the same -statement execution, and \f(CW\*(C`bind_param_array\*(C'\fR must be used with -\&\*(L"execute_array\*(R"; using \f(CW\*(C`bind_param_array\*(C'\fR will have no effect -for \*(L"execute\*(R". -.PP -The \f(CW\*(C`bind_param_array\*(C'\fR method was added in \s-1DBI 1.22.\s0 -.PP -\fI\f(CI\*(C`execute\*(C'\fI\fR -.IX Subsection "execute" -.PP -.Vb 2 -\& $rv = $sth\->execute or die $sth\->errstr; -\& $rv = $sth\->execute(@bind_values) or die $sth\->errstr; -.Ve -.PP -Perform whatever processing is necessary to execute the prepared -statement. An \f(CW\*(C`undef\*(C'\fR is returned if an error occurs. A successful -\&\f(CW\*(C`execute\*(C'\fR always returns true regardless of the number of rows affected, -even if it's zero (see below). It is always important to check the -return status of \f(CW\*(C`execute\*(C'\fR (and most other \s-1DBI\s0 methods) for errors -if you're not using \*(L"RaiseError\*(R". -.PP -For a \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR statement, \f(CW\*(C`execute\*(C'\fR returns the number of rows -affected, if known. If no rows were affected, then \f(CW\*(C`execute\*(C'\fR returns -"\f(CW0E0\fR", which Perl will treat as 0 but will regard as true. Note that it -is \fInot\fR an error for no rows to be affected by a statement. If the -number of rows affected is not known, then \f(CW\*(C`execute\*(C'\fR returns \-1. -.PP -For \f(CW\*(C`SELECT\*(C'\fR statements, execute simply \*(L"starts\*(R" the query within the -database engine. Use one of the fetch methods to retrieve the data after -calling \f(CW\*(C`execute\*(C'\fR. The \f(CW\*(C`execute\*(C'\fR method does \fInot\fR return the number of -rows that will be returned by the query (because most databases can't -tell in advance), it simply returns a true value. -.PP -You can tell if the statement was a \f(CW\*(C`SELECT\*(C'\fR statement by checking if -\&\f(CW\*(C`$sth\->{NUM_OF_FIELDS}\*(C'\fR is greater than zero after calling \f(CW\*(C`execute\*(C'\fR. -.PP -If any arguments are given, then \f(CW\*(C`execute\*(C'\fR will effectively call -\&\*(L"bind_param\*(R" for each value before executing the statement. Values -bound in this way are usually treated as \f(CW\*(C`SQL_VARCHAR\*(C'\fR types unless -the driver can determine the correct type (which is rare), or unless -\&\f(CW\*(C`bind_param\*(C'\fR (or \f(CW\*(C`bind_param_inout\*(C'\fR) has already been used to -specify the type. -.PP -Note that passing \f(CW\*(C`execute\*(C'\fR an empty array is the same as passing no arguments -at all, which will execute the statement with previously bound values. -That's probably not what you want. -.PP -If \fIexecute()\fR is called on a statement handle that's still active -($sth\->{Active} is true) then it should effectively call \fIfinish()\fR -to tidy up the previous execution results before starting this new -execution. -.PP -\fI\f(CI\*(C`execute_array\*(C'\fI\fR -.IX Subsection "execute_array" -.PP -.Vb 2 -\& $tuples = $sth\->execute_array(\e%attr) or die $sth\->errstr; -\& $tuples = $sth\->execute_array(\e%attr, @bind_values) or die $sth\->errstr; -\& -\& ($tuples, $rows) = $sth\->execute_array(\e%attr) or die $sth\->errstr; -\& ($tuples, $rows) = $sth\->execute_array(\e%attr, @bind_values) or die $sth\->errstr; -.Ve -.PP -Execute the prepared statement once for each parameter tuple -(group of values) provided either in the \f(CW@bind_values\fR, or by prior -calls to \*(L"bind_param_array\*(R", or via a reference passed in \e%attr. -.PP -When called in scalar context the \fIexecute_array()\fR method returns the -number of tuples executed, or \f(CW\*(C`undef\*(C'\fR if an error occurred. Like -\&\fIexecute()\fR, a successful \fIexecute_array()\fR always returns true regardless -of the number of tuples executed, even if it's zero. If there were any -errors the ArrayTupleStatus array can be used to discover which tuples -failed and with what errors. -.PP -When called in list context the \fIexecute_array()\fR method returns two scalars; -\&\f(CW$tuples\fR is the same as calling \fIexecute_array()\fR in scalar context and \f(CW$rows\fR is -the number of rows affected for each tuple, if available or -\&\-1 if the driver cannot determine this. \s-1NOTE,\s0 some drivers cannot determine -the number of rows affected per tuple but can provide the number of rows -affected for the batch. -If you are doing an update operation the returned rows affected may not be what -you expect if, for instance, one or more of the tuples affected the same row -multiple times. Some drivers may not yet support list context, in which case -\&\f(CW$rows\fR will be undef, or may not be able to provide the number of rows affected -when performing this batch operation, in which case \f(CW$rows\fR will be \-1. -.PP -Bind values for the tuples to be executed may be supplied row-wise -by an \f(CW\*(C`ArrayTupleFetch\*(C'\fR attribute, or else column-wise in the -\&\f(CW@bind_values\fR argument, or else column-wise by prior calls to -\&\*(L"bind_param_array\*(R". -.PP -Where column-wise binding is used (via the \f(CW@bind_values\fR argument -or calls to \fIbind_param_array()\fR) the maximum number of elements in -any one of the bound value arrays determines the number of tuples -executed. Placeholders with fewer values in their parameter arrays -are treated as if padded with undef (\s-1NULL\s0) values. -.PP -If a scalar value is bound, instead of an array reference, it is -treated as a \fIvariable\fR length array with all elements having the -same value. It does not influence the number of tuples executed, -so if all bound arrays have zero elements then zero tuples will -be executed. If \fIall\fR bound values are scalars then one tuple -will be executed, making \fIexecute_array()\fR act just like \fIexecute()\fR. -.PP -The \f(CW\*(C`ArrayTupleFetch\*(C'\fR attribute can be used to specify a reference -to a subroutine that will be called to provide the bind values for -each tuple execution. The subroutine should return an reference to -an array which contains the appropriate number of bind values, or -return an undef if there is no more data to execute. -.PP -As a convenience, the \f(CW\*(C`ArrayTupleFetch\*(C'\fR attribute can also be -used to specify a statement handle. In which case the \fIfetchrow_arrayref()\fR -method will be called on the given statement handle in order to -provide the bind values for each tuple execution. -.PP -The values specified via \fIbind_param_array()\fR or the \f(CW@bind_values\fR -parameter may be either scalars, or arrayrefs. If any \f(CW@bind_values\fR -are given, then \f(CW\*(C`execute_array\*(C'\fR will effectively call \*(L"bind_param_array\*(R" -for each value before executing the statement. Values bound in -this way are usually treated as \f(CW\*(C`SQL_VARCHAR\*(C'\fR types unless the -driver can determine the correct type (which is rare), or unless -\&\f(CW\*(C`bind_param\*(C'\fR, \f(CW\*(C`bind_param_inout\*(C'\fR, \f(CW\*(C`bind_param_array\*(C'\fR, or -\&\f(CW\*(C`bind_param_inout_array\*(C'\fR has already been used to specify the type. -See \*(L"bind_param_array\*(R" for details. -.PP -The \f(CW\*(C`ArrayTupleStatus\*(C'\fR attribute can be used to specify a -reference to an array which will receive the execute status of each -executed parameter tuple. Note the \f(CW\*(C`ArrayTupleStatus\*(C'\fR attribute was -mandatory until \s-1DBI 1.38.\s0 -.PP -For tuples which are successfully executed, the element at the same -ordinal position in the status array is the resulting rowcount (or \-1 -if unknown). -If the execution of a tuple causes an error, then the corresponding -status array element will be set to a reference to an array containing -\&\*(L"err\*(R", \*(L"errstr\*(R" and \*(L"state\*(R" set by the failed execution. -.PP -If \fBany\fR tuple execution returns an error, \f(CW\*(C`execute_array\*(C'\fR will -return \f(CW\*(C`undef\*(C'\fR. In that case, the application should inspect the -status array to determine which parameter tuples failed. -Some databases may not continue executing tuples beyond the first -failure. In this case the status array will either hold fewer -elements, or the elements beyond the failure will be undef. -.PP -If all parameter tuples are successfully executed, \f(CW\*(C`execute_array\*(C'\fR -returns the number tuples executed. If no tuples were executed, -then \fIexecute_array()\fR returns "\f(CW0E0\fR", just like \fIexecute()\fR does, -which Perl will treat as 0 but will regard as true. -.PP -For example: -.PP -.Vb 10 -\& $sth = $dbh\->prepare("INSERT INTO staff (first_name, last_name) VALUES (?, ?)"); -\& my $tuples = $sth\->execute_array( -\& { ArrayTupleStatus => \emy @tuple_status }, -\& \e@first_names, -\& \e@last_names, -\& ); -\& if ($tuples) { -\& print "Successfully inserted $tuples records\en"; -\& } -\& else { -\& for my $tuple (0..@last_names\-1) { -\& my $status = $tuple_status[$tuple]; -\& $status = [0, "Skipped"] unless defined $status; -\& next unless ref $status; -\& printf "Failed to insert (%s, %s): %s\en", -\& $first_names[$tuple], $last_names[$tuple], $status\->[1]; -\& } -\& } -.Ve -.PP -Support for data returning statements such as \s-1SELECT\s0 is driver-specific -and subject to change. At present, the default implementation -provided by \s-1DBI\s0 only supports non-data returning statements. -.PP -Transaction semantics when using array binding are driver and -database specific. If \f(CW\*(C`AutoCommit\*(C'\fR is on, the default \s-1DBI\s0 -implementation will cause each parameter tuple to be individually -committed (or rolled back in the event of an error). If \f(CW\*(C`AutoCommit\*(C'\fR -is off, the application is responsible for explicitly committing -the entire set of bound parameter tuples. Note that different -drivers and databases may have different behaviours when some -parameter tuples cause failures. In some cases, the driver or -database may automatically rollback the effect of all prior parameter -tuples that succeeded in the transaction; other drivers or databases -may retain the effect of prior successfully executed parameter -tuples. Be sure to check your driver and database for its specific -behaviour. -.PP -Note that, in general, performance will usually be better with -\&\f(CW\*(C`AutoCommit\*(C'\fR turned off, and using explicit \f(CW\*(C`commit\*(C'\fR after each -\&\f(CW\*(C`execute_array\*(C'\fR call. -.PP -The \f(CW\*(C`execute_array\*(C'\fR method was added in \s-1DBI 1.22,\s0 and ArrayTupleFetch -was added in 1.36. -.PP -\fI\f(CI\*(C`execute_for_fetch\*(C'\fI\fR -.IX Subsection "execute_for_fetch" -.PP -.Vb 2 -\& $tuples = $sth\->execute_for_fetch($fetch_tuple_sub); -\& $tuples = $sth\->execute_for_fetch($fetch_tuple_sub, \e@tuple_status); -\& -\& ($tuples, $rows) = $sth\->execute_for_fetch($fetch_tuple_sub); -\& ($tuples, $rows) = $sth\->execute_for_fetch($fetch_tuple_sub, \e@tuple_status); -.Ve -.PP -The \fIexecute_for_fetch()\fR method is used to perform bulk operations and -although it is most often used via the \fIexecute_array()\fR method you can -use it directly. The main difference between execute_array and -execute_for_fetch is the former does column or row-wise binding and -the latter uses row-wise binding. -.PP -The fetch subroutine, referenced by \f(CW$fetch_tuple_sub\fR, is expected -to return a reference to an array (known as a 'tuple') or undef. -.PP -The \fIexecute_for_fetch()\fR method calls \f(CW$fetch_tuple_sub\fR, without any -parameters, until it returns a false value. Each tuple returned is -used to provide bind values for an \f(CW$sth\fR\->execute(@$tuple) call. -.PP -In scalar context \fIexecute_for_fetch()\fR returns \f(CW\*(C`undef\*(C'\fR if there were any -errors and the number of tuples executed otherwise. Like \fIexecute()\fR and -\&\fIexecute_array()\fR a zero is returned as \*(L"0E0\*(R" so \fIexecute_for_fetch()\fR is -only false on error. If there were any errors the \f(CW@tuple_status\fR array -can be used to discover which tuples failed and with what errors. -.PP -When called in list context \fIexecute_for_fetch()\fR returns two scalars; -\&\f(CW$tuples\fR is the same as calling \fIexecute_for_fetch()\fR in scalar context and \f(CW$rows\fR is -the sum of the number of rows affected for each tuple, if available or \-1 -if the driver cannot determine this. -If you are doing an update operation the returned rows affected may not be what -you expect if, for instance, one or more of the tuples affected the same row -multiple times. Some drivers may not yet support list context, in which case -\&\f(CW$rows\fR will be undef, or may not be able to provide the number of rows affected -when performing this batch operation, in which case \f(CW$rows\fR will be \-1. -.PP -If \e@tuple_status is passed then the execute_for_fetch method uses -it to return status information. The tuple_status array holds one -element per tuple. If the corresponding \fIexecute()\fR did not fail then -the element holds the return value from \fIexecute()\fR, which is typically -a row count. If the \fIexecute()\fR did fail then the element holds a -reference to an array containing ($sth\->err, \f(CW$sth\fR\->errstr, \f(CW$sth\fR\->state). -.PP -If the driver detects an error that it knows means no further tuples can be -executed then it may return, with an error status, even though \f(CW$fetch_tuple_sub\fR -may still have more tuples to be executed. -.PP -Although each tuple returned by \f(CW$fetch_tuple_sub\fR is effectively used -to call \f(CW$sth\fR\->execute(@$tuple_array_ref) the exact timing may vary. -Drivers are free to accumulate sets of tuples to pass to the -database server in bulk group operations for more efficient execution. -However, the \f(CW$fetch_tuple_sub\fR is specifically allowed to return -the same array reference each time (which is what \fIfetchrow_arrayref()\fR -usually does). -.PP -For example: -.PP -.Vb 2 -\& my $sel = $dbh1\->prepare("select foo, bar from table1"); -\& $sel\->execute; -\& -\& my $ins = $dbh2\->prepare("insert into table2 (foo, bar) values (?,?)"); -\& my $fetch_tuple_sub = sub { $sel\->fetchrow_arrayref }; -\& -\& my @tuple_status; -\& $rc = $ins\->execute_for_fetch($fetch_tuple_sub, \e@tuple_status); -\& my @errors = grep { ref $_ } @tuple_status; -.Ve -.PP -Similarly, if you already have an array containing the data rows -to be processed you'd use a subroutine to shift off and return -each array ref in turn: -.PP -.Vb 1 -\& $ins\->execute_for_fetch( sub { shift @array_of_arrays }, \e@tuple_status); -.Ve -.PP -The \f(CW\*(C`execute_for_fetch\*(C'\fR method was added in \s-1DBI 1.38.\s0 -.PP -\fI\f(CI\*(C`fetchrow_arrayref\*(C'\fI\fR -.IX Subsection "fetchrow_arrayref" -.PP -.Vb 2 -\& $ary_ref = $sth\->fetchrow_arrayref; -\& $ary_ref = $sth\->fetch; # alias -.Ve -.PP -Fetches the next row of data and returns a reference to an array -holding the field values. Null fields are returned as \f(CW\*(C`undef\*(C'\fR -values in the array. -This is the fastest way to fetch data, particularly if used with -\&\f(CW\*(C`$sth\->bind_columns\*(C'\fR. -.PP -If there are no more rows or if an error occurs, then \f(CW\*(C`fetchrow_arrayref\*(C'\fR -returns an \f(CW\*(C`undef\*(C'\fR. You should check \f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use the -\&\f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the \f(CW\*(C`undef\*(C'\fR returned was due to an -error. -.PP -Note that the same array reference is returned for each fetch, so don't -store the reference and then use it after a later fetch. Also, the -elements of the array are also reused for each row, so take care if you -want to take a reference to an element. See also \*(L"bind_columns\*(R". -.PP -\fI\f(CI\*(C`fetchrow_array\*(C'\fI\fR -.IX Subsection "fetchrow_array" -.PP -.Vb 1 -\& @ary = $sth\->fetchrow_array; -.Ve -.PP -An alternative to \f(CW\*(C`fetchrow_arrayref\*(C'\fR. Fetches the next row of data -and returns it as a list containing the field values. Null fields -are returned as \f(CW\*(C`undef\*(C'\fR values in the list. -.PP -If there are no more rows or if an error occurs, then \f(CW\*(C`fetchrow_array\*(C'\fR -returns an empty list. You should check \f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use -the \f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the empty list returned was -due to an error. -.PP -If called in a scalar context for a statement handle that has more -than one column, it is undefined whether the driver will return -the value of the first column or the last. So don't do that. -Also, in a scalar context, an \f(CW\*(C`undef\*(C'\fR is returned if there are no -more rows or if an error occurred. That \f(CW\*(C`undef\*(C'\fR can't be distinguished -from an \f(CW\*(C`undef\*(C'\fR returned because the first field value was \s-1NULL.\s0 -For these reasons you should exercise some caution if you use -\&\f(CW\*(C`fetchrow_array\*(C'\fR in a scalar context. -.PP -\fI\f(CI\*(C`fetchrow_hashref\*(C'\fI\fR -.IX Subsection "fetchrow_hashref" -.PP -.Vb 2 -\& $hash_ref = $sth\->fetchrow_hashref; -\& $hash_ref = $sth\->fetchrow_hashref($name); -.Ve -.PP -An alternative to \f(CW\*(C`fetchrow_arrayref\*(C'\fR. Fetches the next row of data -and returns it as a reference to a hash containing field name and field -value pairs. Null fields are returned as \f(CW\*(C`undef\*(C'\fR values in the hash. -.PP -If there are no more rows or if an error occurs, then \f(CW\*(C`fetchrow_hashref\*(C'\fR -returns an \f(CW\*(C`undef\*(C'\fR. You should check \f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use the -\&\f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the \f(CW\*(C`undef\*(C'\fR returned was due to an -error. -.PP -The optional \f(CW$name\fR parameter specifies the name of the statement handle -attribute. For historical reasons it defaults to "\f(CW\*(C`NAME\*(C'\fR\*(L", however using -either \*(R"\f(CW\*(C`NAME_lc\*(C'\fR\*(L" or \*(R"\f(CW\*(C`NAME_uc\*(C'\fR" is recommended for portability. -.PP -The keys of the hash are the same names returned by \f(CW\*(C`$sth\->{$name}\*(C'\fR. If -more than one field has the same name, there will only be one entry in the -returned hash for those fields, so statements like "\f(CW\*(C`select foo, foo from bar\*(C'\fR" -will return only a single key from \f(CW\*(C`fetchrow_hashref\*(C'\fR. In these cases use -column aliases or \f(CW\*(C`fetchrow_arrayref\*(C'\fR. Note that it is the database server -(and not the \s-1DBD\s0 implementation) which provides the \fIname\fR for fields -containing functions like "\f(CWcount(*)\fR\*(L" or \*(R"\f(CW\*(C`max(c_foo)\*(C'\fR" and they may clash -with existing column names (most databases don't care about duplicate column -names in a result-set). If you want these to return as unique names that are -the same across databases, use \fIaliases\fR, as in "\f(CW\*(C`select count(*) as cnt\*(C'\fR\*(L" -or \*(R"\f(CW\*(C`select max(c_foo) mx_foo, ...\*(C'\fR" depending on the syntax your database -supports. -.PP -Because of the extra work \f(CW\*(C`fetchrow_hashref\*(C'\fR and Perl have to perform, it -is not as efficient as \f(CW\*(C`fetchrow_arrayref\*(C'\fR or \f(CW\*(C`fetchrow_array\*(C'\fR. -.PP -By default a reference to a new hash is returned for each row. -It is likely that a future version of the \s-1DBI\s0 will support an -attribute which will enable the same hash to be reused for each -row. This will give a significant performance boost, but it won't -be enabled by default because of the risk of breaking old code. -.PP -\fI\f(CI\*(C`fetchall_arrayref\*(C'\fI\fR -.IX Subsection "fetchall_arrayref" -.PP -.Vb 3 -\& $tbl_ary_ref = $sth\->fetchall_arrayref; -\& $tbl_ary_ref = $sth\->fetchall_arrayref( $slice ); -\& $tbl_ary_ref = $sth\->fetchall_arrayref( $slice, $max_rows ); -.Ve -.PP -The \f(CW\*(C`fetchall_arrayref\*(C'\fR method can be used to fetch all the data to be -returned from a prepared and executed statement handle. It returns a -reference to an array that contains one reference per row. -.PP -If called on an \fIinactive\fR statement handle, \f(CW\*(C`fetchall_arrayref\*(C'\fR returns undef. -.PP -If there are no rows left to return from an \fIactive\fR statement handle, \f(CW\*(C`fetchall_arrayref\*(C'\fR returns a reference -to an empty array. If an error occurs, \f(CW\*(C`fetchall_arrayref\*(C'\fR returns the -data fetched thus far, which may be none. You should check \f(CW\*(C`$sth\->err\*(C'\fR -afterwards (or use the \f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the data is -complete or was truncated due to an error. -.PP -If \f(CW$slice\fR is an array reference, \f(CW\*(C`fetchall_arrayref\*(C'\fR uses \*(L"fetchrow_arrayref\*(R" -to fetch each row as an array ref. If the \f(CW$slice\fR array is not empty -then it is used as a slice to select individual columns by perl array -index number (starting at 0, unlike column and parameter numbers which -start at 1). -.PP -With no parameters, or if \f(CW$slice\fR is undefined, \f(CW\*(C`fetchall_arrayref\*(C'\fR -acts as if passed an empty array ref. -.PP -For example, to fetch just the first column of every row: -.PP -.Vb 1 -\& $tbl_ary_ref = $sth\->fetchall_arrayref([0]); -.Ve -.PP -To fetch the second to last and last column of every row: -.PP -.Vb 1 -\& $tbl_ary_ref = $sth\->fetchall_arrayref([\-2,\-1]); -.Ve -.PP -Those two examples both return a reference to an array of array refs. -.PP -If \f(CW$slice\fR is a hash reference, \f(CW\*(C`fetchall_arrayref\*(C'\fR fetches each row as a hash -reference. If the \f(CW$slice\fR hash is empty then the keys in the hashes have -whatever name lettercase is returned by default. (See \*(L"FetchHashKeyName\*(R" -attribute.) If the \f(CW$slice\fR hash is \fInot\fR empty, then it is used as a slice to -select individual columns by name. The values of the hash should be set to 1. -The key names of the returned hashes match the letter case of the names in the -parameter hash, regardless of the \*(L"FetchHashKeyName\*(R" attribute. -.PP -For example, to fetch all fields of every row as a hash ref: -.PP -.Vb 1 -\& $tbl_ary_ref = $sth\->fetchall_arrayref({}); -.Ve -.PP -To fetch only the fields called \*(L"foo\*(R" and \*(L"bar\*(R" of every row as a hash ref -(with keys named \*(L"foo\*(R" and \*(L"\s-1BAR\*(R",\s0 regardless of the original capitalization): -.PP -.Vb 1 -\& $tbl_ary_ref = $sth\->fetchall_arrayref({ foo=>1, BAR=>1 }); -.Ve -.PP -Those two examples both return a reference to an array of hash refs. -.PP -If \f(CW$slice\fR is a \fIreference to a hash reference\fR, that hash is used to select -and rename columns. The keys are 0\-based column index numbers and the values -are the corresponding keys for the returned row hashes. -.PP -For example, to fetch only the first and second columns of every row as a hash -ref (with keys named \*(L"k\*(R" and \*(L"v\*(R" regardless of their original names): -.PP -.Vb 1 -\& $tbl_ary_ref = $sth\->fetchall_arrayref( \e{ 0 => \*(Aqk\*(Aq, 1 => \*(Aqv\*(Aq } ); -.Ve -.PP -If \f(CW$max_rows\fR is defined and greater than or equal to zero then it -is used to limit the number of rows fetched before returning. -\&\fIfetchall_arrayref()\fR can then be called again to fetch more rows. -This is especially useful when you need the better performance of -\&\fIfetchall_arrayref()\fR but don't have enough memory to fetch and return -all the rows in one go. -.PP -Here's an example (assumes RaiseError is enabled): -.PP -.Vb 6 -\& my $rows = []; # cache for batches of rows -\& while( my $row = ( shift(@$rows) || # get row from cache, or reload cache: -\& shift(@{$rows=$sth\->fetchall_arrayref(undef,10_000)||[]}) ) -\& ) { -\& ... -\& } -.Ve -.PP -That \fImight\fR be the fastest way to fetch and process lots of rows using the \s-1DBI,\s0 -but it depends on the relative cost of method calls vs memory allocation. -.PP -A standard \f(CW\*(C`while\*(C'\fR loop with column binding is often faster because -the cost of allocating memory for the batch of rows is greater than -the saving by reducing method calls. It's possible that the \s-1DBI\s0 may -provide a way to reuse the memory of a previous batch in future, which -would then shift the balance back towards \fIfetchall_arrayref()\fR. -.PP -\fI\f(CI\*(C`fetchall_hashref\*(C'\fI\fR -.IX Subsection "fetchall_hashref" -.PP -.Vb 1 -\& $hash_ref = $sth\->fetchall_hashref($key_field); -.Ve -.PP -The \f(CW\*(C`fetchall_hashref\*(C'\fR method can be used to fetch all the data to be -returned from a prepared and executed statement handle. It returns a reference -to a hash containing a key for each distinct value of the \f(CW$key_field\fR column -that was fetched. For each key the corresponding value is a reference to a hash -containing all the selected columns and their values, as returned by -\&\f(CW\*(C`fetchrow_hashref()\*(C'\fR. -.PP -If there are no rows to return, \f(CW\*(C`fetchall_hashref\*(C'\fR returns a reference -to an empty hash. If an error occurs, \f(CW\*(C`fetchall_hashref\*(C'\fR returns the -data fetched thus far, which may be none. You should check -\&\f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use the \f(CW\*(C`RaiseError\*(C'\fR attribute) to -discover if the data is complete or was truncated due to an error. -.PP -The \f(CW$key_field\fR parameter provides the name of the field that holds the -value to be used for the key for the returned hash. For example: -.PP -.Vb 5 -\& $dbh\->{FetchHashKeyName} = \*(AqNAME_lc\*(Aq; -\& $sth = $dbh\->prepare("SELECT FOO, BAR, ID, NAME, BAZ FROM TABLE"); -\& $sth\->execute; -\& $hash_ref = $sth\->fetchall_hashref(\*(Aqid\*(Aq); -\& print "Name for id 42 is $hash_ref\->{42}\->{name}\en"; -.Ve -.PP -The \f(CW$key_field\fR parameter can also be specified as an integer column -number (counting from 1). If \f(CW$key_field\fR doesn't match any column in -the statement, as a name first then as a number, then an error is -returned. -.PP -For queries returning more than one 'key' column, you can specify -multiple column names by passing \f(CW$key_field\fR as a reference to an -array containing one or more key column names (or index numbers). -For example: -.PP -.Vb 4 -\& $sth = $dbh\->prepare("SELECT foo, bar, baz FROM table"); -\& $sth\->execute; -\& $hash_ref = $sth\->fetchall_hashref( [ qw(foo bar) ] ); -\& print "For foo 42 and bar 38, baz is $hash_ref\->{42}\->{38}\->{baz}\en"; -.Ve -.PP -The \fIfetchall_hashref()\fR method is normally used only where the key -fields values for each row are unique. If multiple rows are returned -with the same values for the key fields then later rows overwrite -earlier ones. -.PP -\fI\f(CI\*(C`finish\*(C'\fI\fR -.IX Subsection "finish" -.PP -.Vb 1 -\& $rc = $sth\->finish; -.Ve -.PP -Indicate that no more data will be fetched from this statement handle -before it is either executed again or destroyed. You almost certainly -do \fInot\fR need to call this method. -.PP -Adding calls to \f(CW\*(C`finish\*(C'\fR after loop that fetches all rows is a common mistake, -don't do it, it can mask genuine problems like uncaught fetch errors. -.PP -When all the data has been fetched from a \f(CW\*(C`SELECT\*(C'\fR statement, the driver will -automatically call \f(CW\*(C`finish\*(C'\fR for you. So you should \fInot\fR call it explicitly -\&\fIexcept\fR when you know that you've not fetched all the data from a statement -handle \fIand\fR the handle won't be destroyed soon. -.PP -The most common example is when you only want to fetch just one row, -but in that case the \f(CW\*(C`selectrow_*\*(C'\fR methods are usually better anyway. -.PP -Consider a query like: -.PP -.Vb 1 -\& SELECT foo FROM table WHERE bar=? ORDER BY baz -.Ve -.PP -on a very large table. When executed, the database server will have to use -temporary buffer space to store the sorted rows. If, after executing -the handle and selecting just a few rows, the handle won't be re-executed for -some time and won't be destroyed, the \f(CW\*(C`finish\*(C'\fR method can be used to tell -the server that the buffer space can be freed. -.PP -Calling \f(CW\*(C`finish\*(C'\fR resets the \*(L"Active\*(R" attribute for the statement. It -may also make some statement handle attributes (such as \f(CW\*(C`NAME\*(C'\fR and \f(CW\*(C`TYPE\*(C'\fR) -unavailable if they have not already been accessed (and thus cached). -.PP -The \f(CW\*(C`finish\*(C'\fR method does not affect the transaction status of the -database connection. It has nothing to do with transactions. It's mostly an -internal \*(L"housekeeping\*(R" method that is rarely needed. -See also \*(L"disconnect\*(R" and the \*(L"Active\*(R" attribute. -.PP -The \f(CW\*(C`finish\*(C'\fR method should have been called \f(CW\*(C`discard_pending_rows\*(C'\fR. -.PP -\fI\f(CI\*(C`rows\*(C'\fI\fR -.IX Subsection "rows" -.PP -.Vb 1 -\& $rv = $sth\->rows; -.Ve -.PP -Returns the number of rows affected by the last row affecting command, -or \-1 if the number of rows is not known or not available. -.PP -Generally, you can only rely on a row count after a \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR -\&\f(CW\*(C`execute\*(C'\fR (for some specific operations like \f(CW\*(C`UPDATE\*(C'\fR and \f(CW\*(C`DELETE\*(C'\fR), or -after fetching all the rows of a \f(CW\*(C`SELECT\*(C'\fR statement. -.PP -For \f(CW\*(C`SELECT\*(C'\fR statements, it is generally not possible to know how many -rows will be returned except by fetching them all. Some drivers will -return the number of rows the application has fetched so far, but -others may return \-1 until all rows have been fetched. So use of the -\&\f(CW\*(C`rows\*(C'\fR method or \f(CW$DBI::rows\fR with \f(CW\*(C`SELECT\*(C'\fR statements is not -recommended. -.PP -One alternative method to get a row count for a \f(CW\*(C`SELECT\*(C'\fR is to execute a -\&\*(L"\s-1SELECT COUNT\s0(*) \s-1FROM ...\*(R" SQL\s0 statement with the same \*(L"...\*(R" as your -query and then fetch the row count from that. -.PP -\fI\f(CI\*(C`bind_col\*(C'\fI\fR -.IX Subsection "bind_col" -.PP -.Vb 3 -\& $rc = $sth\->bind_col($column_number, \e$var_to_bind); -\& $rc = $sth\->bind_col($column_number, \e$var_to_bind, \e%attr ); -\& $rc = $sth\->bind_col($column_number, \e$var_to_bind, $bind_type ); -.Ve -.PP -Binds a Perl variable and/or some attributes to an output column -(field) of a \f(CW\*(C`SELECT\*(C'\fR statement. Column numbers count up from 1. -You do not need to bind output columns in order to fetch data. -For maximum portability between drivers, \fIbind_col()\fR should be called -after \fIexecute()\fR and not before. -See also \*(L"bind_columns\*(R" for an example. -.PP -The binding is performed at a low level using Perl aliasing. -Whenever a row is fetched from the database \f(CW$var_to_bind\fR appears -to be automatically updated simply because it now refers to the same -memory location as the corresponding column value. This makes using -bound variables very efficient. -Binding a tied variable doesn't work, currently. -.PP -The \*(L"bind_param\*(R" method -performs a similar, but opposite, function for input variables. -.PP -\&\fBData Types for Column Binding\fR -.PP -The \f(CW\*(C`\e%attr\*(C'\fR parameter can be used to hint at the data type -formatting the column should have. For example, you can use: -.PP -.Vb 1 -\& $sth\->bind_col(1, undef, { TYPE => SQL_DATETIME }); -.Ve -.PP -to specify that you'd like the column (which presumably is some -kind of datetime type) to be returned in the standard format for -\&\s-1SQL_DATETIME,\s0 which is '\s-1YYYY\-MM\-DD HH:MM:SS\s0', rather than the -native formatting the database would normally use. -.PP -There's no \f(CW$var_to_bind\fR in that example to emphasize the point -that \fIbind_col()\fR works on the underlying column and not just -a particular bound variable. -.PP -As a short-cut for the common case, the data type can be passed -directly, in place of the \f(CW\*(C`\e%attr\*(C'\fR hash reference. This example is -equivalent to the one above: -.PP -.Vb 1 -\& $sth\->bind_col(1, undef, SQL_DATETIME); -.Ve -.PP -The \f(CW\*(C`TYPE\*(C'\fR value indicates the standard (non-driver-specific) type for -this parameter. To specify the driver-specific type, the driver may -support a driver-specific attribute, such as \f(CW\*(C`{ ora_type => 97 }\*(C'\fR. -.PP -The \s-1SQL_DATETIME\s0 and other related constants can be imported using -.PP -.Vb 1 -\& use DBI qw(:sql_types); -.Ve -.PP -See \*(L"\s-1DBI\s0 Constants\*(R" for more information. -.PP -Few drivers support specifying a data type via a \f(CW\*(C`bind_col\*(C'\fR call -(most will simply ignore the data type). Fewer still allow the data -type to be altered once set. If you do set a column type the type -should remain sticky through further calls to bind_col for the same -column if the type is not overridden (this is important for instance -when you are using a slice in fetchall_arrayref). -.PP -The \s-1TYPE\s0 attribute for \fIbind_col()\fR was first specified in \s-1DBI 1.41.\s0 -.PP -From \s-1DBI 1.611,\s0 drivers can use the \f(CW\*(C`TYPE\*(C'\fR attribute to attempt to -cast the bound scalar to a perl type which more closely matches -\&\f(CW\*(C`TYPE\*(C'\fR. At present \s-1DBI\s0 supports \f(CW\*(C`SQL_INTEGER\*(C'\fR, \f(CW\*(C`SQL_DOUBLE\*(C'\fR and -\&\f(CW\*(C`SQL_NUMERIC\*(C'\fR. See \*(L"sql_type_cast\*(R" for details of how types are -cast. -.PP -\&\fBOther attributes for Column Binding\fR -.PP -The \f(CW\*(C`\e%attr\*(C'\fR parameter may also contain the following attributes: -.ie n .IP """StrictlyTyped""" 4 -.el .IP "\f(CWStrictlyTyped\fR" 4 -.IX Item "StrictlyTyped" -If a \f(CW\*(C`TYPE\*(C'\fR attribute is passed to bind_col, then the driver will -attempt to change the bound perl scalar to match the type more -closely. If the bound value cannot be cast to the requested \f(CW\*(C`TYPE\*(C'\fR -then by default it is left untouched and no error is generated. If you -specify \f(CW\*(C`StrictlyTyped\*(C'\fR as 1 and the cast fails, this will generate -an error. -.Sp -This attribute was first added in \s-1DBI 1.611.\s0 When 1.611 was released -few drivers actually supported this attribute but DBD::Oracle and -\&\s-1DBD::ODBC\s0 should from versions 1.24. -.ie n .IP """DiscardString""" 4 -.el .IP "\f(CWDiscardString\fR" 4 -.IX Item "DiscardString" -When the \f(CW\*(C`TYPE\*(C'\fR attribute is passed to \*(L"bind_col\*(R" and the driver -successfully casts the bound perl scalar to a non-string type -then if \f(CW\*(C`DiscardString\*(C'\fR is set to 1, the string portion of the -scalar will be discarded. By default, \f(CW\*(C`DiscardString\*(C'\fR is not set. -.Sp -This attribute was first added in \s-1DBI 1.611.\s0 When 1.611 was released -few drivers actually supported this attribute but DBD::Oracle and -\&\s-1DBD::ODBC\s0 should from versions 1.24. -.PP -\fI\f(CI\*(C`bind_columns\*(C'\fI\fR -.IX Subsection "bind_columns" -.PP -.Vb 1 -\& $rc = $sth\->bind_columns(@list_of_refs_to_vars_to_bind); -.Ve -.PP -Calls \*(L"bind_col\*(R" for each column of the \f(CW\*(C`SELECT\*(C'\fR statement. -.PP -The list of references should have the same number of elements as the number of -columns in the \f(CW\*(C`SELECT\*(C'\fR statement. If it doesn't then \f(CW\*(C`bind_columns\*(C'\fR will -bind the elements given, up to the number of columns, and then return an error. -.PP -For maximum portability between drivers, \fIbind_columns()\fR should be called -after \fIexecute()\fR and not before. -.PP -For example: -.PP -.Vb 4 -\& $dbh\->{RaiseError} = 1; # do this, or check every call for errors -\& $sth = $dbh\->prepare(q{ SELECT region, sales FROM sales_by_region }); -\& $sth\->execute; -\& my ($region, $sales); -\& -\& # Bind Perl variables to columns: -\& $rv = $sth\->bind_columns(\e$region, \e$sales); -\& -\& # you can also use Perl\*(Aqs \e(...) syntax (see perlref docs): -\& # $sth\->bind_columns(\e($region, $sales)); -\& -\& # Column binding is the most efficient way to fetch data -\& while ($sth\->fetch) { -\& print "$region: $sales\en"; -\& } -.Ve -.PP -For compatibility with old scripts, the first parameter will be -ignored if it is \f(CW\*(C`undef\*(C'\fR or a hash reference. -.PP -Here's a more fancy example that binds columns to the values \fIinside\fR -a hash (thanks to H.Merijn Brand): -.PP -.Vb 6 -\& $sth\->execute; -\& my %row; -\& $sth\->bind_columns( \e( @row{ @{$sth\->{NAME_lc} } } )); -\& while ($sth\->fetch) { -\& print "$row{region}: $row{sales}\en"; -\& } -.Ve -.PP -\fI\f(CI\*(C`dump_results\*(C'\fI\fR -.IX Subsection "dump_results" -.PP -.Vb 1 -\& $rows = $sth\->dump_results($maxlen, $lsep, $fsep, $fh); -.Ve -.PP -Fetches all the rows from \f(CW$sth\fR, calls \f(CW\*(C`DBI::neat_list\*(C'\fR for each row, and -prints the results to \f(CW$fh\fR (defaults to \f(CW\*(C`STDOUT\*(C'\fR) separated by \f(CW$lsep\fR -(default \f(CW"\en"\fR). \f(CW$fsep\fR defaults to \f(CW", "\fR and \f(CW$maxlen\fR defaults to 35. -.PP -This method is designed as a handy utility for prototyping and -testing queries. Since it uses \*(L"neat_list\*(R" to -format and edit the string for reading by humans, it is not recommended -for data transfer applications. -.SS "Statement Handle Attributes" -.IX Subsection "Statement Handle Attributes" -This section describes attributes specific to statement handles. Most -of these attributes are read-only. -.PP -Changes to these statement handle attributes do not affect any other -existing or future statement handles. -.PP -Attempting to set or get the value of an unknown attribute generates a warning, -except for private driver specific attributes (which all have names -starting with a lowercase letter). -.PP -Example: -.PP -.Vb 1 -\& ... = $h\->{NUM_OF_FIELDS}; # get/read -.Ve -.PP -Some drivers cannot provide valid values for some or all of these -attributes until after \f(CW\*(C`$sth\->execute\*(C'\fR has been successfully -called. Typically the attribute will be \f(CW\*(C`undef\*(C'\fR in these situations. -.PP -Some attributes, like \s-1NAME,\s0 are not appropriate to some types of -statement, like \s-1SELECT.\s0 Typically the attribute will be \f(CW\*(C`undef\*(C'\fR -in these situations. -.PP -For drivers which support stored procedures and multiple result sets -(see \*(L"more_results\*(R") these attributes relate to the \fIcurrent\fR result set. -.PP -See also \*(L"finish\*(R" to learn more about the effect it -may have on some attributes. -.PP -\fI\f(CI\*(C`NUM_OF_FIELDS\*(C'\fI\fR -.IX Subsection "NUM_OF_FIELDS" -.PP -Type: integer, read-only -.PP -Number of fields (columns) in the data the prepared statement may return. -Statements that don't return rows of data, like \f(CW\*(C`DELETE\*(C'\fR and \f(CW\*(C`CREATE\*(C'\fR -set \f(CW\*(C`NUM_OF_FIELDS\*(C'\fR to 0 (though it may be undef in some drivers). -.PP -\fI\f(CI\*(C`NUM_OF_PARAMS\*(C'\fI\fR -.IX Subsection "NUM_OF_PARAMS" -.PP -Type: integer, read-only -.PP -The number of parameters (placeholders) in the prepared statement. -See \s-1SUBSTITUTION VARIABLES\s0 below for more details. -.PP -\fI\f(CI\*(C`NAME\*(C'\fI\fR -.IX Subsection "NAME" -.PP -Type: array-ref, read-only -.PP -Returns a reference to an array of field names for each column. The -names may contain spaces but should not be truncated or have any -trailing space. Note that the names have the letter case (upper, lower -or mixed) as returned by the driver being used. Portable applications -should use \*(L"NAME_lc\*(R" or \*(L"NAME_uc\*(R". -.PP -.Vb 1 -\& print "First column name: $sth\->{NAME}\->[0]\en"; -.Ve -.PP -Also note that the name returned for (aggregate) functions like \f(CWcount(*)\fR -or \f(CW\*(C`max(c_foo)\*(C'\fR is determined by the database server and not by \f(CW\*(C`DBI\*(C'\fR or -the \f(CW\*(C`DBD\*(C'\fR backend. -.PP -\fI\f(CI\*(C`NAME_lc\*(C'\fI\fR -.IX Subsection "NAME_lc" -.PP -Type: array-ref, read-only -.PP -Like \f(CW\*(C`/NAME\*(C'\fR but always returns lowercase names. -.PP -\fI\f(CI\*(C`NAME_uc\*(C'\fI\fR -.IX Subsection "NAME_uc" -.PP -Type: array-ref, read-only -.PP -Like \f(CW\*(C`/NAME\*(C'\fR but always returns uppercase names. -.PP -\fI\f(CI\*(C`NAME_hash\*(C'\fI\fR -.IX Subsection "NAME_hash" -.PP -Type: hash-ref, read-only -.PP -\fI\f(CI\*(C`NAME_lc_hash\*(C'\fI\fR -.IX Subsection "NAME_lc_hash" -.PP -Type: hash-ref, read-only -.PP -\fI\f(CI\*(C`NAME_uc_hash\*(C'\fI\fR -.IX Subsection "NAME_uc_hash" -.PP -Type: hash-ref, read-only -.PP -The \f(CW\*(C`NAME_hash\*(C'\fR, \f(CW\*(C`NAME_lc_hash\*(C'\fR, and \f(CW\*(C`NAME_uc_hash\*(C'\fR attributes -return column name information as a reference to a hash. -.PP -The keys of the hash are the names of the columns. The letter case of -the keys corresponds to the letter case returned by the \f(CW\*(C`NAME\*(C'\fR, -\&\f(CW\*(C`NAME_lc\*(C'\fR, and \f(CW\*(C`NAME_uc\*(C'\fR attributes respectively (as described above). -.PP -The value of each hash entry is the perl index number of the -corresponding column (counting from 0). For example: -.PP -.Vb 4 -\& $sth = $dbh\->prepare("select Id, Name from table"); -\& $sth\->execute; -\& @row = $sth\->fetchrow_array; -\& print "Name $row[ $sth\->{NAME_lc_hash}{name} ]\en"; -.Ve -.PP -\fI\f(CI\*(C`TYPE\*(C'\fI\fR -.IX Subsection "TYPE" -.PP -Type: array-ref, read-only -.PP -Returns a reference to an array of integer values for each -column. The value indicates the data type of the corresponding column. -.PP -The values correspond to the international standards (\s-1ANSI X3.135\s0 -and \s-1ISO/IEC 9075\s0) which, in general terms, means \s-1ODBC.\s0 Driver-specific -types that don't exactly match standard types should generally return -the same values as an \s-1ODBC\s0 driver supplied by the makers of the -database. That might include private type numbers in ranges the vendor -has officially registered with the \s-1ISO\s0 working group: -.PP -.Vb 1 -\& ftp://sqlstandards.org/SC32/SQL_Registry/ -.Ve -.PP -Where there's no vendor-supplied \s-1ODBC\s0 driver to be compatible with, -the \s-1DBI\s0 driver can use type numbers in the range that is now -officially reserved for use by the \s-1DBI: \-9999\s0 to \-9000. -.PP -All possible values for \f(CW\*(C`TYPE\*(C'\fR should have at least one entry in the -output of the \f(CW\*(C`type_info_all\*(C'\fR method (see \*(L"type_info_all\*(R"). -.PP -\fI\f(CI\*(C`PRECISION\*(C'\fI\fR -.IX Subsection "PRECISION" -.PP -Type: array-ref, read-only -.PP -Returns a reference to an array of integer values for each column. -.PP -For numeric columns, the value is the maximum number of digits -(without considering a sign character or decimal point). Note that -the \*(L"display size\*(R" for floating point types (\s-1REAL, FLOAT, DOUBLE\s0) -can be up to 7 characters greater than the precision (for the -sign + decimal point + the letter E + a sign + 2 or 3 digits). -.PP -For any character type column the value is the \s-1OCTET_LENGTH,\s0 -in other words the number of bytes, not characters. -.PP -(More recent standards refer to this as \s-1COLUMN_SIZE\s0 but we stick -with \s-1PRECISION\s0 for backwards compatibility.) -.PP -\fI\f(CI\*(C`SCALE\*(C'\fI\fR -.IX Subsection "SCALE" -.PP -Type: array-ref, read-only -.PP -Returns a reference to an array of integer values for each column. -\&\s-1NULL \s0(\f(CW\*(C`undef\*(C'\fR) values indicate columns where scale is not applicable. -.PP -\fI\f(CI\*(C`NULLABLE\*(C'\fI\fR -.IX Subsection "NULLABLE" -.PP -Type: array-ref, read-only -.PP -Returns a reference to an array indicating the possibility of each -column returning a null. Possible values are \f(CW0\fR -(or an empty string) = no, \f(CW1\fR = yes, \f(CW2\fR = unknown. -.PP -.Vb 1 -\& print "First column may return NULL\en" if $sth\->{NULLABLE}\->[0]; -.Ve -.PP -\fI\f(CI\*(C`CursorName\*(C'\fI\fR -.IX Subsection "CursorName" -.PP -Type: string, read-only -.PP -Returns the name of the cursor associated with the statement handle, if -available. If not available or if the database driver does not support the -\&\f(CW"where current of ..."\fR \s-1SQL\s0 syntax, then it returns \f(CW\*(C`undef\*(C'\fR. -.PP -\fI\f(CI\*(C`Database\*(C'\fI\fR -.IX Subsection "Database" -.PP -Type: dbh, read-only -.PP -Returns the parent \f(CW$dbh\fR of the statement handle. -.PP -\fI\f(CI\*(C`Statement\*(C'\fI\fR -.IX Subsection "Statement" -.PP -Type: string, read-only -.PP -Returns the statement string passed to the \*(L"prepare\*(R" method. -.PP -\fI\f(CI\*(C`ParamValues\*(C'\fI\fR -.IX Subsection "ParamValues" -.PP -Type: hash ref, read-only -.PP -Returns a reference to a hash containing the values currently bound -to placeholders. The keys of the hash are the 'names' of the -placeholders, typically integers starting at 1. Returns undef if -not supported by the driver. -.PP -See \*(L"ShowErrorStatement\*(R" for an example of how this is used. -.PP -* Keys: -.PP -If the driver supports \f(CW\*(C`ParamValues\*(C'\fR but no values have been bound -yet then the driver should return a hash with placeholders names -in the keys but all the values undef, but some drivers may return -a ref to an empty hash because they can't pre-determine the names. -.PP -It is possible that the keys in the hash returned by \f(CW\*(C`ParamValues\*(C'\fR -are not exactly the same as those implied by the prepared statement. -For example, DBD::Oracle translates '\f(CW\*(C`?\*(C'\fR' placeholders into '\f(CW\*(C`:pN\*(C'\fR' -where N is a sequence number starting at 1. -.PP -* Values: -.PP -It is possible that the values in the hash returned by \f(CW\*(C`ParamValues\*(C'\fR -are not \fIexactly\fR the same as those passed to \fIbind_param()\fR or \fIexecute()\fR. -The driver may have slightly modified values in some way based on the -\&\s-1TYPE\s0 the value was bound with. For example a floating point value -bound as an \s-1SQL_INTEGER\s0 type may be returned as an integer. -The values returned by \f(CW\*(C`ParamValues\*(C'\fR can be passed to another -\&\fIbind_param()\fR method with the same \s-1TYPE\s0 and will be seen by the -database as the same value. See also \*(L"ParamTypes\*(R" below. -.PP -The \f(CW\*(C`ParamValues\*(C'\fR attribute was added in \s-1DBI 1.28.\s0 -.PP -\fI\f(CI\*(C`ParamTypes\*(C'\fI\fR -.IX Subsection "ParamTypes" -.PP -Type: hash ref, read-only -.PP -Returns a reference to a hash containing the type information -currently bound to placeholders. -Returns undef if not supported by the driver. -.PP -* Keys: -.PP -See \*(L"ParamValues\*(R" above. -.PP -* Values: -.PP -The hash values are hashrefs of type information in the same form as that -passed to the various \fIbind_param()\fR methods (See \*(L"bind_param\*(R" for the format -and values). -.PP -It is possible that the values in the hash returned by \f(CW\*(C`ParamTypes\*(C'\fR -are not exactly the same as those passed to \fIbind_param()\fR or \fIexecute()\fR. -Param attributes specified using the abbreviated form, like this: -.PP -.Vb 1 -\& $sth\->bind_param(1, SQL_INTEGER); -.Ve -.PP -are returned in the expanded form, as if called like this: -.PP -.Vb 1 -\& $sth\->bind_param(1, { TYPE => SQL_INTEGER }); -.Ve -.PP -The driver may have modified the type information in some way based -on the bound values, other hints provided by the \fIprepare()\fR'd -\&\s-1SQL\s0 statement, or alternate type mappings required by the driver or target -database system. The driver may also add private keys (with names beginning -with the drivers reserved prefix, e.g., odbc_xxx). -.PP -* Example: -.PP -The keys and values in the returned hash can be passed to the various -\&\fIbind_param()\fR methods to effectively reproduce a previous param binding. -For example: -.PP -.Vb 7 -\& # assuming $sth1 is a previously prepared statement handle -\& my $sth2 = $dbh\->prepare( $sth1\->{Statement} ); -\& my $ParamValues = $sth1\->{ParamValues} || {}; -\& my $ParamTypes = $sth1\->{ParamTypes} || {}; -\& $sth2\->bind_param($_, $ParamValues\->{$_}, $ParamTypes\->{$_}) -\& for keys %{ {%$ParamValues, %$ParamTypes} }; -\& $sth2\->execute(); -.Ve -.PP -The \f(CW\*(C`ParamTypes\*(C'\fR attribute was added in \s-1DBI 1.49.\s0 Implementation -is the responsibility of individual drivers; the \s-1DBI\s0 layer default -implementation simply returns undef. -.PP -\fI\f(CI\*(C`ParamArrays\*(C'\fI\fR -.IX Subsection "ParamArrays" -.PP -Type: hash ref, read-only -.PP -Returns a reference to a hash containing the values currently bound to -placeholders with \*(L"execute_array\*(R" or \*(L"bind_param_array\*(R". The -keys of the hash are the 'names' of the placeholders, typically -integers starting at 1. Returns undef if not supported by the driver -or no arrays of parameters are bound. -.PP -Each key value is an array reference containing a list of the bound -parameters for that column. -.PP -For example: -.PP -.Vb 8 -\& $sth = $dbh\->prepare("INSERT INTO staff (id, name) values (?,?)"); -\& $sth\->execute_array({},[1,2], [\*(Aqfred\*(Aq,\*(Aqdave\*(Aq]); -\& if ($sth\->{ParamArrays}) { -\& foreach $param (keys %{$sth\->{ParamArrays}}) { -\& printf "Parameters for %s : %s\en", $param, -\& join(",", @{$sth\->{ParamArrays}\->{$param}}); -\& } -\& } -.Ve -.PP -It is possible that the values in the hash returned by \f(CW\*(C`ParamArrays\*(C'\fR -are not \fIexactly\fR the same as those passed to \*(L"bind_param_array\*(R" or -\&\*(L"execute_array\*(R". The driver may have slightly modified values in some -way based on the \s-1TYPE\s0 the value was bound with. For example a floating -point value bound as an \s-1SQL_INTEGER\s0 type may be returned as an -integer. -.PP -It is also possible that the keys in the hash returned by -\&\f(CW\*(C`ParamArrays\*(C'\fR are not exactly the same as those implied by the -prepared statement. For example, DBD::Oracle translates '\f(CW\*(C`?\*(C'\fR' -placeholders into '\f(CW\*(C`:pN\*(C'\fR' where N is a sequence number starting at 1. -.PP -\fI\f(CI\*(C`RowsInCache\*(C'\fI\fR -.IX Subsection "RowsInCache" -.PP -Type: integer, read-only -.PP -If the driver supports a local row cache for \f(CW\*(C`SELECT\*(C'\fR statements, then -this attribute holds the number of un-fetched rows in the cache. If the -driver doesn't, then it returns \f(CW\*(C`undef\*(C'\fR. Note that some drivers pre-fetch -rows on execute, whereas others wait till the first fetch. -.PP -See also the \*(L"RowCacheSize\*(R" database handle attribute. -.SH "FURTHER INFORMATION" -.IX Header "FURTHER INFORMATION" -.SS "Catalog Methods" -.IX Subsection "Catalog Methods" -An application can retrieve metadata information from the \s-1DBMS\s0 by issuing -appropriate queries on the views of the Information Schema. Unfortunately, -\&\f(CW\*(C`INFORMATION_SCHEMA\*(C'\fR views are seldom supported by the \s-1DBMS.\s0 -Special methods (catalog methods) are available to return result sets -for a small but important portion of that metadata: -.PP -.Vb 5 -\& column_info -\& foreign_key_info -\& primary_key_info -\& table_info -\& statistics_info -.Ve -.PP -All catalog methods accept arguments in order to restrict the result sets. -Passing \f(CW\*(C`undef\*(C'\fR to an optional argument does not constrain the search for -that argument. -However, an empty string ('') is treated as a regular search criteria -and will only match an empty value. -.PP -\&\fBNote\fR: \s-1SQL/CLI\s0 and \s-1ODBC\s0 differ in the handling of empty strings. An -empty string will not restrict the result set in \s-1SQL/CLI.\s0 -.PP -Most arguments in the catalog methods accept only \fIordinary values\fR, e.g. -the arguments of \f(CW\*(C`primary_key_info()\*(C'\fR. -Such arguments are treated as a literal string, i.e. the case is significant -and quote characters are taken literally. -.PP -Some arguments in the catalog methods accept \fIsearch patterns\fR (strings -containing '_' and/or '%'), e.g. the \f(CW$table\fR argument of \f(CW\*(C`column_info()\*(C'\fR. -Passing '%' is equivalent to leaving the argument \f(CW\*(C`undef\*(C'\fR. -.PP -\&\fBCaveat\fR: The underscore ('_') is valid and often used in \s-1SQL\s0 identifiers. -Passing such a value to a search pattern argument may return more rows than -expected! -To include pattern characters as literals, they must be preceded by an -escape character which can be achieved with -.PP -.Vb 2 -\& $esc = $dbh\->get_info( 14 ); # SQL_SEARCH_PATTERN_ESCAPE -\& $search_pattern =~ s/([_%])/$esc$1/g; -.Ve -.PP -The \s-1ODBC\s0 and \s-1SQL/CLI\s0 specifications define a way to change the default -behaviour described above: All arguments (except \fIlist value arguments\fR) -are treated as \fIidentifier\fR if the \f(CW\*(C`SQL_ATTR_METADATA_ID\*(C'\fR attribute is -set to \f(CW\*(C`SQL_TRUE\*(C'\fR. -\&\fIQuoted identifiers\fR are very similar to \fIordinary values\fR, i.e. their -body (the string within the quotes) is interpreted literally. -\&\fIUnquoted identifiers\fR are compared in \s-1UPPERCASE.\s0 -.PP -The \s-1DBI \s0(currently) does not support the \f(CW\*(C`SQL_ATTR_METADATA_ID\*(C'\fR attribute, -i.e. it behaves like an \s-1ODBC\s0 driver where \f(CW\*(C`SQL_ATTR_METADATA_ID\*(C'\fR is set to -\&\f(CW\*(C`SQL_FALSE\*(C'\fR. -.SS "Transactions" -.IX Subsection "Transactions" -Transactions are a fundamental part of any robust database system. They -protect against errors and database corruption by ensuring that sets of -related changes to the database take place in atomic (indivisible, -all-or-nothing) units. -.PP -This section applies to databases that support transactions and where -\&\f(CW\*(C`AutoCommit\*(C'\fR is off. See \*(L"AutoCommit\*(R" for details of using \f(CW\*(C`AutoCommit\*(C'\fR -with various types of databases. -.PP -The recommended way to implement robust transactions in Perl -applications is to enable \*(L"RaiseError\*(R" and catch the error that's 'thrown' as -an exception. For example, using Try::Tiny: -.PP -.Vb 10 -\& use Try::Tiny; -\& $dbh\->{AutoCommit} = 0; # enable transactions, if possible -\& $dbh\->{RaiseError} = 1; -\& try { -\& foo(...) # do lots of work here -\& bar(...) # including inserts -\& baz(...) # and updates -\& $dbh\->commit; # commit the changes if we get this far -\& } catch { -\& warn "Transaction aborted because $_"; # Try::Tiny copies $@ into $_ -\& # now rollback to undo the incomplete changes -\& # but do it in an eval{} as it may also fail -\& eval { $dbh\->rollback }; -\& # add other application on\-error\-clean\-up code here -\& }; -.Ve -.PP -If the \f(CW\*(C`RaiseError\*(C'\fR attribute is not set, then \s-1DBI\s0 calls would need to be -manually checked for errors, typically like this: -.PP -.Vb 1 -\& $h\->method(@args) or die $h\->errstr; -.Ve -.PP -With \f(CW\*(C`RaiseError\*(C'\fR set, the \s-1DBI\s0 will automatically \f(CW\*(C`die\*(C'\fR if any \s-1DBI\s0 method -call on that handle (or a child handle) fails, so you don't have to -test the return value of each method call. See \*(L"RaiseError\*(R" for more -details. -.PP -A major advantage of the \f(CW\*(C`eval\*(C'\fR approach is that the transaction will be -properly rolled back if \fIany\fR code (not just \s-1DBI\s0 calls) in the inner -application dies for any reason. The major advantage of using the -\&\f(CW\*(C`$h\->{RaiseError}\*(C'\fR attribute is that all \s-1DBI\s0 calls will be checked -automatically. Both techniques are strongly recommended. -.PP -After calling \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR many drivers will not let you -fetch from a previously active \f(CW\*(C`SELECT\*(C'\fR statement handle that's a child -of the same database handle. A typical way round this is to connect the -the database twice and use one connection for \f(CW\*(C`SELECT\*(C'\fR statements. -.PP -See \*(L"AutoCommit\*(R" and \*(L"disconnect\*(R" for other important information -about transactions. -.SS "Handling \s-1BLOB / LONG /\s0 Memo Fields" -.IX Subsection "Handling BLOB / LONG / Memo Fields" -Many databases support \*(L"blob\*(R" (binary large objects), \*(L"long\*(R", or similar -datatypes for holding very long strings or large amounts of binary -data in a single field. Some databases support variable length long -values over 2,000,000,000 bytes in length. -.PP -Since values of that size can't usually be held in memory, and because -databases can't usually know in advance the length of the longest long -that will be returned from a \f(CW\*(C`SELECT\*(C'\fR statement (unlike other data -types), some special handling is required. -.PP -In this situation, the value of the \f(CW\*(C`$h\->{LongReadLen}\*(C'\fR -attribute is used to determine how much buffer space to allocate -when fetching such fields. The \f(CW\*(C`$h\->{LongTruncOk}\*(C'\fR attribute -is used to determine how to behave if a fetched value can't fit -into the buffer. -.PP -See the description of \*(L"LongReadLen\*(R" for more information. -.PP -When trying to insert long or binary values, placeholders should be used -since there are often limits on the maximum size of an \f(CW\*(C`INSERT\*(C'\fR -statement and the \*(L"quote\*(R" method generally can't cope with binary -data. See \*(L"Placeholders and Bind Values\*(R". -.SS "Simple Examples" -.IX Subsection "Simple Examples" -Here's a complete example program to select and fetch some data: -.PP -.Vb 3 -\& my $data_source = "dbi::DriverName:db_name"; -\& my $dbh = DBI\->connect($data_source, $user, $password) -\& or die "Can\*(Aqt connect to $data_source: $DBI::errstr"; -\& -\& my $sth = $dbh\->prepare( q{ -\& SELECT name, phone -\& FROM mytelbook -\& }) or die "Can\*(Aqt prepare statement: $DBI::errstr"; -\& -\& my $rc = $sth\->execute -\& or die "Can\*(Aqt execute statement: $DBI::errstr"; -\& -\& print "Query will return $sth\->{NUM_OF_FIELDS} fields.\en\en"; -\& print "Field names: @{ $sth\->{NAME} }\en"; -\& -\& while (($name, $phone) = $sth\->fetchrow_array) { -\& print "$name: $phone\en"; -\& } -\& # check for problems which may have terminated the fetch early -\& die $sth\->errstr if $sth\->err; -\& -\& $dbh\->disconnect; -.Ve -.PP -Here's a complete example program to insert some data from a file. -(This example uses \f(CW\*(C`RaiseError\*(C'\fR to avoid needing to check each call). -.PP -.Vb 3 -\& my $dbh = DBI\->connect("dbi:DriverName:db_name", $user, $password, { -\& RaiseError => 1, AutoCommit => 0 -\& }); -\& -\& my $sth = $dbh\->prepare( q{ -\& INSERT INTO table (name, phone) VALUES (?, ?) -\& }); -\& -\& open FH, ") { -\& chomp; -\& my ($name, $phone) = split /,/; -\& $sth\->execute($name, $phone); -\& } -\& close FH; -\& -\& $dbh\->commit; -\& $dbh\->disconnect; -.Ve -.PP -Here's how to convert fetched NULLs (undefined values) into empty strings: -.PP -.Vb 5 -\& while($row = $sth\->fetchrow_arrayref) { -\& # this is a fast and simple way to deal with nulls: -\& foreach (@$row) { $_ = \*(Aq\*(Aq unless defined } -\& print "@$row\en"; -\& } -.Ve -.PP -The \f(CW\*(C`q{...}\*(C'\fR style quoting used in these examples avoids clashing with -quotes that may be used in the \s-1SQL\s0 statement. Use the double-quote like -\&\f(CW\*(C`qq{...}\*(C'\fR operator if you want to interpolate variables into the string. -See \*(L"Quote and Quote-like Operators\*(R" in perlop for more details. -.SS "Threads and Thread Safety" -.IX Subsection "Threads and Thread Safety" -Perl 5.7 and later support a new threading model called iThreads. -(The old \*(L"5.005 style\*(R" threads are not supported by the \s-1DBI.\s0) -.PP -In the iThreads model each thread has its own copy of the perl -interpreter. When a new thread is created the original perl -interpreter is 'cloned' to create a new copy for the new thread. -.PP -If the \s-1DBI\s0 and drivers are loaded and handles created before the -thread is created then it will get a cloned copy of the \s-1DBI,\s0 the -drivers and the handles. -.PP -However, the internal pointer data within the handles will refer -to the \s-1DBI\s0 and drivers in the original interpreter. Using those -handles in the new interpreter thread is not safe, so the \s-1DBI\s0 detects -this and croaks on any method call using handles that don't belong -to the current thread (except for \s-1DESTROY\s0). -.PP -Because of this (possibly temporary) restriction, newly created -threads must make their own connections to the database. Handles -can't be shared across threads. -.PP -But \s-1BEWARE,\s0 some underlying database APIs (the code the \s-1DBD\s0 driver -uses to talk to the database, often supplied by the database vendor) -are not thread safe. If it's not thread safe, then allowing more -than one thread to enter the code at the same time may cause -subtle/serious problems. In some cases allowing more than -one thread to enter the code, even if \fInot\fR at the same time, -can cause problems. You have been warned. -.PP -Using \s-1DBI\s0 with perl threads is not yet recommended for production -environments. For more information see - -.PP -Note: There is a bug in perl 5.8.2 when configured with threads -and debugging enabled (bug #24463) which causes a \s-1DBI\s0 test to fail. -.SS "Signal Handling and Canceling Operations" -.IX Subsection "Signal Handling and Canceling Operations" -[The following only applies to systems with unix-like signal handling. -I'd welcome additions for other systems, especially Windows.] -.PP -The first thing to say is that signal handling in Perl versions less -than 5.8 is \fInot\fR safe. There is always a small risk of Perl -crashing and/or core dumping when, or after, handling a signal -because the signal could arrive and be handled while internal data -structures are being changed. If the signal handling code -used those same internal data structures it could cause all manner -of subtle and not-so-subtle problems. The risk was reduced with -5.4.4 but was still present in all perls up through 5.8.0. -.PP -Beginning in perl 5.8.0 perl implements 'safe' signal handling if -your system has the \s-1POSIX\s0 \fIsigaction()\fR routine. Now when a signal -is delivered perl just makes a note of it but does \fInot\fR run the -\&\f(CW%SIG\fR handler. The handling is 'deferred' until a 'safe' moment. -.PP -Although this change made signal handling safe, it also lead to -a problem with signals being deferred for longer than you'd like. -If a signal arrived while executing a system call, such as waiting -for data on a network connection, the signal is noted and then the -system call that was executing returns with an \s-1EINTR\s0 error code -to indicate that it was interrupted. All fine so far. -.PP -The problem comes when the code that made the system call sees the -\&\s-1EINTR\s0 code and decides it's going to call it again. Perl doesn't -do that, but database code sometimes does. If that happens then the -signal handler doesn't get called until later. Maybe much later. -.PP -Fortunately there are ways around this which we'll discuss below. -Unfortunately they make signals unsafe again. -.PP -The two most common uses of signals in relation to the \s-1DBI\s0 are for -canceling operations when the user types Ctrl-C (interrupt), and for -implementing a timeout using \f(CW\*(C`alarm()\*(C'\fR and \f(CW$SIG{ALRM}\fR. -.IP "Cancel" 4 -.IX Item "Cancel" -The \s-1DBI\s0 provides a \f(CW\*(C`cancel\*(C'\fR method for statement handles. The -\&\f(CW\*(C`cancel\*(C'\fR method should abort the current operation and is designed -to be called from a signal handler. For example: -.Sp -.Vb 1 -\& $SIG{INT} = sub { $sth\->cancel }; -.Ve -.Sp -However, few drivers implement this (the \s-1DBI\s0 provides a default -method that just returns \f(CW\*(C`undef\*(C'\fR) and, even if implemented, there -is still a possibility that the statement handle, and even the -parent database handle, will not be usable afterwards. -.Sp -If \f(CW\*(C`cancel\*(C'\fR returns true, then it has successfully -invoked the database engine's own cancel function. If it returns false, -then \f(CW\*(C`cancel\*(C'\fR failed. If it returns \f(CW\*(C`undef\*(C'\fR, then the database -driver does not have cancel implemented \- very few do. -.IP "Timeout" 4 -.IX Item "Timeout" -The traditional way to implement a timeout is to set \f(CW$SIG{ALRM}\fR -to refer to some code that will be executed when an \s-1ALRM\s0 signal -arrives and then to call alarm($seconds) to schedule an \s-1ALRM\s0 signal -to be delivered \f(CW$seconds\fR in the future. For example: -.Sp -.Vb 10 -\& my $failed; -\& eval { -\& local $SIG{ALRM} = sub { die "TIMEOUT\en" }; # N.B. \en required -\& eval { -\& alarm($seconds); -\& ... code to execute with timeout here (which may die) ... -\& 1; -\& } or $failed = 1; -\& # outer eval catches alarm that might fire JUST before this alarm(0) -\& alarm(0); # cancel alarm (if code ran fast) -\& die "$@" if $failed; -\& 1; -\& } or $failed = 1; -\& if ( $failed ) { -\& if ( defined $@ and $@ eq "TIMEOUT\en" ) { ... } -\& else { ... } # some other error -\& } -.Ve -.Sp -The first (outer) eval is used to avoid the unlikely but possible -chance that the \*(L"code to execute\*(R" dies and the alarm fires before it -is cancelled. Without the outer eval, if this happened your program -will die if you have no \s-1ALRM\s0 handler or a non-local alarm handler -will be called. -.Sp -Unfortunately, as described above, this won't always work as expected, -depending on your perl version and the underlying database code. -.Sp -With Oracle for instance (DBD::Oracle), if the system which hosts -the database is down the \s-1DBI\-\s0>\fIconnect()\fR call will hang for several -minutes before returning an error. -.PP -The solution on these systems is to use the \f(CW\*(C`POSIX::sigaction()\*(C'\fR -routine to gain low level access to how the signal handler is installed. -.PP -The code would look something like this (for the DBD-Oracle \fIconnect()\fR): -.PP -.Vb 1 -\& use POSIX qw(:signal_h); -\& -\& my $mask = POSIX::SigSet\->new( SIGALRM ); # signals to mask in the handler -\& my $action = POSIX::SigAction\->new( -\& sub { die "connect timeout\en" }, # the handler code ref -\& $mask, -\& # not using (perl 5.8.2 and later) \*(Aqsafe\*(Aq switch or sa_flags -\& ); -\& my $oldaction = POSIX::SigAction\->new(); -\& sigaction( SIGALRM, $action, $oldaction ); -\& my $dbh; -\& my $failed; -\& eval { -\& eval { -\& alarm(5); # seconds before time out -\& $dbh = DBI\->connect("dbi:Oracle:$dsn" ... ); -\& 1; -\& } or $failed = 1; -\& alarm(0); # cancel alarm (if connect worked fast) -\& die "$@\en" if $failed; # connect died -\& 1; -\& } or $failed = 1; -\& sigaction( SIGALRM, $oldaction ); # restore original signal handler -\& if ( $failed ) { -\& if ( defined $@ and $@ eq "connect timeout\en" ) {...} -\& else { # connect died } -\& } -.Ve -.PP -See previous example for the reasoning around the double eval. -.PP -Similar techniques can be used for canceling statement execution. -.PP -Unfortunately, this solution is somewhat messy, and it does \fInot\fR work with -perl versions less than perl 5.8 where \f(CW\*(C`POSIX::sigaction()\*(C'\fR appears to be broken. -.PP -For a cleaner implementation that works across perl versions, see Lincoln Baxter's -Sys::SigAction module at Sys::SigAction. -The documentation for Sys::SigAction includes an longer discussion -of this problem, and a DBD::Oracle test script. -.PP -Be sure to read all the signal handling sections of the perlipc manual. -.PP -And finally, two more points to keep firmly in mind. Firstly, -remember that what we've done here is essentially revert to old -style \fIunsafe\fR handling of these signals. So do as little as -possible in the handler. Ideally just \fIdie()\fR. Secondly, the handles -in use at the time the signal is handled may not be safe to use -afterwards. -.SS "Subclassing the \s-1DBI\s0" -.IX Subsection "Subclassing the DBI" -\&\s-1DBI\s0 can be subclassed and extended just like any other object -oriented module. Before we talk about how to do that, it's important -to be clear about the various \s-1DBI\s0 classes and how they work together. -.PP -By default \f(CW\*(C`$dbh = DBI\->connect(...)\*(C'\fR returns a \f(CW$dbh\fR blessed -into the \f(CW\*(C`DBI::db\*(C'\fR class. And the \f(CW\*(C`$dbh\->prepare\*(C'\fR method -returns an \f(CW$sth\fR blessed into the \f(CW\*(C`DBI::st\*(C'\fR class (actually it -simply changes the last four characters of the calling handle class -to be \f(CW\*(C`::st\*(C'\fR). -.PP -The leading '\f(CW\*(C`DBI\*(C'\fR' is known as the 'root class' and the extra -\&'\f(CW\*(C`::db\*(C'\fR' or '\f(CW\*(C`::st\*(C'\fR' are the 'handle type suffixes'. If you want -to subclass the \s-1DBI\s0 you'll need to put your overriding methods into -the appropriate classes. For example, if you want to use a root class -of \f(CW\*(C`MySubDBI\*(C'\fR and override the \fIdo()\fR, \fIprepare()\fR and \fIexecute()\fR methods, -then your \fIdo()\fR and \fIprepare()\fR methods should be in the \f(CW\*(C`MySubDBI::db\*(C'\fR -class and the \fIexecute()\fR method should be in the \f(CW\*(C`MySubDBI::st\*(C'\fR class. -.PP -To setup the inheritance hierarchy the \f(CW@ISA\fR variable in \f(CW\*(C`MySubDBI::db\*(C'\fR -should include \f(CW\*(C`DBI::db\*(C'\fR and the \f(CW@ISA\fR variable in \f(CW\*(C`MySubDBI::st\*(C'\fR -should include \f(CW\*(C`DBI::st\*(C'\fR. The \f(CW\*(C`MySubDBI\*(C'\fR root class itself isn't -currently used for anything visible and so, apart from setting \f(CW@ISA\fR -to include \f(CW\*(C`DBI\*(C'\fR, it can be left empty. -.PP -So, having put your overriding methods into the right classes, and -setup the inheritance hierarchy, how do you get the \s-1DBI\s0 to use them? -You have two choices, either a static method call using the name -of your subclass: -.PP -.Vb 1 -\& $dbh = MySubDBI\->connect(...); -.Ve -.PP -or specifying a \f(CW\*(C`RootClass\*(C'\fR attribute: -.PP -.Vb 1 -\& $dbh = DBI\->connect(..., { RootClass => \*(AqMySubDBI\*(Aq }); -.Ve -.PP -If both forms are used then the attribute takes precedence. -.PP -The only differences between the two are that using an explicit -RootClass attribute will a) make the \s-1DBI\s0 automatically attempt to load -a module by that name if the class doesn't exist, and b) won't call -your \fIMySubDBI::connect()\fR method, if you have one. -.PP -When subclassing is being used then, after a successful new -connect, the \s-1DBI\-\s0>connect method automatically calls: -.PP -.Vb 1 -\& $dbh\->connected($dsn, $user, $pass, \e%attr); -.Ve -.PP -The default method does nothing. The call is made just to simplify -any post-connection setup that your subclass may want to perform. -The parameters are the same as passed to \s-1DBI\-\s0>connect. -If your subclass supplies a connected method, it should be part of the -MySubDBI::db package. -.PP -One more thing to note: you must let the \s-1DBI\s0 do the handle creation. If you -want to override the \fIconnect()\fR method in your *::dr class then it must still -call SUPER::connect to get a \f(CW$dbh\fR to work with. Similarly, an overridden -\&\fIprepare()\fR method in *::db must still call SUPER::prepare to get a \f(CW$sth\fR. -If you try to create your own handles using \fIbless()\fR then you'll find the \s-1DBI\s0 -will reject them with an \*(L"is not a \s-1DBI\s0 handle (has no magic)\*(R" error. -.PP -Here's a brief example of a \s-1DBI\s0 subclass. A more thorough example -can be found in \fIt/subclass.t\fR in the \s-1DBI\s0 distribution. -.PP -.Vb 1 -\& package MySubDBI; -\& -\& use strict; -\& -\& use DBI; -\& use vars qw(@ISA); -\& @ISA = qw(DBI); -\& -\& package MySubDBI::db; -\& use vars qw(@ISA); -\& @ISA = qw(DBI::db); -\& -\& sub prepare { -\& my ($dbh, @args) = @_; -\& my $sth = $dbh\->SUPER::prepare(@args) -\& or return; -\& $sth\->{private_mysubdbi_info} = { foo => \*(Aqbar\*(Aq }; -\& return $sth; -\& } -\& -\& package MySubDBI::st; -\& use vars qw(@ISA); -\& @ISA = qw(DBI::st); -\& -\& sub fetch { -\& my ($sth, @args) = @_; -\& my $row = $sth\->SUPER::fetch(@args) -\& or return; -\& do_something_magical_with_row_data($row) -\& or return $sth\->set_err(1234, "The magic failed", undef, "fetch"); -\& return $row; -\& } -.Ve -.PP -When calling a SUPER::method that returns a handle, be careful to -check the return value before trying to do other things with it in -your overridden method. This is especially important if you want to -set a hash attribute on the handle, as Perl's autovivification will -bite you by (in)conveniently creating an unblessed hashref, which your -method will then return with usually baffling results later on like -the error \*(L"dbih_getcom handle \s-1HASH\s0(0xa4451a8) is not a \s-1DBI\s0 handle (has -no magic\*(R". It's best to check right after the call and return undef -immediately on error, just like \s-1DBI\s0 would and just like the example -above. -.PP -If your method needs to record an error it should call the \fIset_err()\fR -method with the error code and error string, as shown in the example -above. The error code and error string will be recorded in the -handle and available via \f(CW\*(C`$h\->err\*(C'\fR and \f(CW$DBI::errstr\fR etc. -The \fIset_err()\fR method always returns an undef or empty list as -appropriate. Since your method should nearly always return an undef -or empty list as soon as an error is detected it's handy to simply -return what \fIset_err()\fR returns, as shown in the example above. -.PP -If the handle has \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`PrintError\*(C'\fR, or \f(CW\*(C`HandleError\*(C'\fR -etc. set then the \fIset_err()\fR method will honour them. This means -that if \f(CW\*(C`RaiseError\*(C'\fR is set then \fIset_err()\fR won't return in the -normal way but will 'throw an exception' that can be caught with -an \f(CW\*(C`eval\*(C'\fR block. -.PP -You can stash private data into \s-1DBI\s0 handles -via \f(CW\*(C`$h\->{private_..._*}\*(C'\fR. See the entry under \*(L"\s-1ATTRIBUTES -COMMON TO ALL HANDLES\*(R"\s0 for info and important caveats. -.SS "Memory Leaks" -.IX Subsection "Memory Leaks" -When tracking down memory leaks using tools like Devel::Leak -you'll find that some \s-1DBI\s0 internals are reported as 'leaking' memory. -This is very unlikely to be a real leak. The \s-1DBI\s0 has various caches to improve -performance and the apparrent leaks are simply the normal operation of these -caches. -.PP -The most frequent sources of the apparrent leaks are \*(L"ChildHandles\*(R", -\&\*(L"prepare_cached\*(R" and \*(L"connect_cached\*(R". -.PP -For example http://stackoverflow.com/questions/13338308/perl\-dbi\-memory\-leak -.PP -Given how widely the \s-1DBI\s0 is used, you can rest assured that if a new release of -the \s-1DBI\s0 did have a real leak it would be discovered, reported, and fixed -immediately. The leak you're looking for is probably elsewhere. Good luck! -.SH "TRACING" -.IX Header "TRACING" -The \s-1DBI\s0 has a powerful tracing mechanism built in. It enables you -to see what's going on 'behind the scenes', both within the \s-1DBI\s0 and -the drivers you're using. -.SS "Trace Settings" -.IX Subsection "Trace Settings" -Which details are written to the trace output is controlled by a -combination of a \fItrace level\fR, an integer from 0 to 15, and a set -of \fItrace flags\fR that are either on or off. Together these are known -as the \fItrace settings\fR and are stored together in a single integer. -For normal use you only need to set the trace level, and generally -only to a value between 1 and 4. -.PP -Each handle has its own trace settings, and so does the \s-1DBI.\s0 -When you call a method the \s-1DBI\s0 merges the handles settings into its -own for the duration of the call: the trace flags of the handle are -\&\s-1OR\s0'd into the trace flags of the \s-1DBI,\s0 and if the handle has a higher -trace level then the \s-1DBI\s0 trace level is raised to match it. -The previous \s-1DBI\s0 trace settings are restored when the called method -returns. -.SS "Trace Levels" -.IX Subsection "Trace Levels" -Trace \fIlevels\fR are as follows: -.PP -.Vb 8 -\& 0 \- Trace disabled. -\& 1 \- Trace top\-level DBI method calls returning with results or errors. -\& 2 \- As above, adding tracing of top\-level method entry with parameters. -\& 3 \- As above, adding some high\-level information from the driver -\& and some internal information from the DBI. -\& 4 \- As above, adding more detailed information from the driver. -\& This is the first level to trace all the rows being fetched. -\& 5 to 15 \- As above but with more and more internal information. -.Ve -.PP -Trace level 1 is best for a simple overview of what's happening. -Trace levels 2 thru 4 a good choice for general purpose tracing. -Levels 5 and above are best reserved for investigating a specific -problem, when you need to see \*(L"inside\*(R" the driver and \s-1DBI.\s0 -.PP -The trace output is detailed and typically very useful. Much of the -trace output is formatted using the \*(L"neat\*(R" function, so strings -in the trace output may be edited and truncated by that function. -.SS "Trace Flags" -.IX Subsection "Trace Flags" -Trace \fIflags\fR are used to enable tracing of specific activities -within the \s-1DBI\s0 and drivers. The \s-1DBI\s0 defines some trace flags and -drivers can define others. \s-1DBI\s0 trace flag names begin with a capital -letter and driver specific names begin with a lowercase letter, as -usual. -.PP -Currently the \s-1DBI\s0 defines these trace flags: -.PP -.Vb 10 -\& ALL \- turn on all DBI and driver flags (not recommended) -\& SQL \- trace SQL statements executed -\& (not yet implemented in DBI but implemented in some DBDs) -\& CON \- trace connection process -\& ENC \- trace encoding (unicode translations etc) -\& (not yet implemented in DBI but implemented in some DBDs) -\& DBD \- trace only DBD messages -\& (not implemented by all DBDs yet) -\& TXN \- trace transactions -\& (not implemented in all DBDs yet) -.Ve -.PP -The \*(L"parse_trace_flags\*(R" and \*(L"parse_trace_flag\*(R" methods are used -to convert trace flag names into the corresponding integer bit flags. -.SS "Enabling Trace" -.IX Subsection "Enabling Trace" -The \f(CW\*(C`$h\->trace\*(C'\fR method sets the trace settings for a handle -and \f(CW\*(C`DBI\->trace\*(C'\fR does the same for the \s-1DBI.\s0 -.PP -In addition to the \*(L"trace\*(R" method, you can enable the same trace -information, and direct the output to a file, by setting the -\&\f(CW\*(C`DBI_TRACE\*(C'\fR environment variable before starting Perl. -See \*(L"\s-1DBI_TRACE\*(R"\s0 for more information. -.PP -Finally, you can set, or get, the trace settings for a handle using -the \f(CW\*(C`TraceLevel\*(C'\fR attribute. -.PP -All of those methods use \fIparse_trace_flags()\fR and so allow you set -both the trace level and multiple trace flags by using a string -containing the trace level and/or flag names separated by vertical -bar ("\f(CW\*(C`|\*(C'\fR\*(L") or comma (\*(R"\f(CW\*(C`,\*(C'\fR") characters. For example: -.PP -.Vb 1 -\& local $h\->{TraceLevel} = "3|SQL|foo"; -.Ve -.SS "Trace Output" -.IX Subsection "Trace Output" -Initially trace output is written to \f(CW\*(C`STDERR\*(C'\fR. Both the -\&\f(CW\*(C`$h\->trace\*(C'\fR and \f(CW\*(C`DBI\->trace\*(C'\fR methods take an optional -\&\f(CW$trace_file\fR parameter, which may be either the name of a file to be -opened by \s-1DBI\s0 in append mode, or a reference to an existing writable -(possibly layered) filehandle. If \f(CW$trace_file\fR is a filename, -and can be opened in append mode, or \f(CW$trace_file\fR is a writable -filehandle, then \fIall\fR trace output (currently including that from -other handles) is redirected to that file. A warning is generated -if \f(CW$trace_file\fR can't be opened or is not writable. -.PP -Further calls to \fItrace()\fR without \f(CW$trace_file\fR do not alter where -the trace output is sent. If \f(CW$trace_file\fR is undefined, then -trace output is sent to \f(CW\*(C`STDERR\*(C'\fR and, if the prior trace was opened with -\&\f(CW$trace_file\fR as a filename, the previous trace file is closed; if \f(CW$trace_file\fR was -a filehandle, the filehandle is \fBnot\fR closed. -.PP -\&\fB\s-1NOTE\s0\fR: If \f(CW$trace_file\fR is specified as a filehandle, the filehandle -should not be closed until all \s-1DBI\s0 operations are completed, or the -application has reset the trace file via another call to -\&\f(CW\*(C`trace()\*(C'\fR that changes the trace file. -.SS "Tracing to Layered Filehandles" -.IX Subsection "Tracing to Layered Filehandles" -\&\fB\s-1NOTE\s0\fR: -.IP "\(bu" 4 -Tied filehandles are not currently supported, as -tie operations are not available to the PerlIO -methods used by the \s-1DBI.\s0 -.IP "\(bu" 4 -PerlIO layer support requires Perl version 5.8 or higher. -.PP -As of version 5.8, Perl provides the ability to layer various -\&\*(L"disciplines\*(R" on an open filehandle via the PerlIO module. -.PP -A simple example of using PerlIO layers is to use a scalar as the output: -.PP -.Vb 3 -\& my $scalar = \*(Aq\*(Aq; -\& open( my $fh, "+>:scalar", \e$scalar ); -\& $dbh\->trace( 2, $fh ); -.Ve -.PP -Now all trace output is simply appended to \f(CW$scalar\fR. -.PP -A more complex application of tracing to a layered filehandle is the -use of a custom layer (\fIRefer to \fRPerlio::via \fIfor details -on creating custom PerlIO layers.\fR). Consider an application with the -following logger module: -.PP -.Vb 1 -\& package MyFancyLogger; -\& -\& sub new -\& { -\& my $self = {}; -\& my $fh; -\& open $fh, \*(Aq>\*(Aq, \*(Aqfancylog.log\*(Aq; -\& $self\->{_fh} = $fh; -\& $self\->{_buf} = \*(Aq\*(Aq; -\& return bless $self, shift; -\& } -\& -\& sub log -\& { -\& my $self = shift; -\& return unless exists $self\->{_fh}; -\& my $fh = $self\->{_fh}; -\& $self\->{_buf} .= shift; -\& # -\& # DBI feeds us pieces at a time, so accumulate a complete line -\& # before outputing -\& # -\& print $fh "At ", scalar localtime(), \*(Aq:\*(Aq, $self\->{_buf}, "\en" and -\& $self\->{_buf} = \*(Aq\*(Aq -\& if $self\->{_buf}=~tr/\en//; -\& } -\& -\& sub close { -\& my $self = shift; -\& return unless exists $self\->{_fh}; -\& my $fh = $self\->{_fh}; -\& print $fh "At ", scalar localtime(), \*(Aq:\*(Aq, $self\->{_buf}, "\en" and -\& $self\->{_buf} = \*(Aq\*(Aq -\& if $self\->{_buf}; -\& close $fh; -\& delete $self\->{_fh}; -\& } -\& -\& 1; -.Ve -.PP -To redirect \s-1DBI\s0 traces to this logger requires creating -a package for the layer: -.PP -.Vb 1 -\& package PerlIO::via::MyFancyLogLayer; -\& -\& sub PUSHED -\& { -\& my ($class,$mode,$fh) = @_; -\& my $logger; -\& return bless \e$logger,$class; -\& } -\& -\& sub OPEN { -\& my ($self, $path, $mode, $fh) = @_; -\& # -\& # $path is actually our logger object -\& # -\& $$self = $path; -\& return 1; -\& } -\& -\& sub WRITE -\& { -\& my ($self, $buf, $fh) = @_; -\& $$self\->log($buf); -\& return length($buf); -\& } -\& -\& sub CLOSE { -\& my $self = shift; -\& $$self\->close(); -\& return 0; -\& } -\& -\& 1; -.Ve -.PP -The application can then cause \s-1DBI\s0 traces to be routed to the -logger using -.PP -.Vb 1 -\& use PerlIO::via::MyFancyLogLayer; -\& -\& open my $fh, \*(Aq>:via(MyFancyLogLayer)\*(Aq, MyFancyLogger\->new(); -\& -\& $dbh\->trace(\*(AqSQL\*(Aq, $fh); -.Ve -.PP -Now all trace output will be processed by MyFancyLogger's -\&\fIlog()\fR method. -.SS "Trace Content" -.IX Subsection "Trace Content" -Many of the values embedded in trace output are formatted using the \fIneat()\fR -utility function. This means they may be quoted, sanitized, and possibly -truncated if longer than \f(CW$DBI::neat_maxlen\fR. See \*(L"neat\*(R" for more details. -.SS "Tracing Tips" -.IX Subsection "Tracing Tips" -You can add tracing to your own application code using the \*(L"trace_msg\*(R" method. -.PP -It can sometimes be handy to compare trace files from two different runs of the -same script. However using a tool like \f(CW\*(C`diff\*(C'\fR on the original log output -doesn't work well because the trace file is full of object addresses that may -differ on each run. -.PP -The \s-1DBI\s0 includes a handy utility called dbilogstrip that can be used to -\&'normalize' the log content. It can be used as a filter like this: -.PP -.Vb 3 -\& DBI_TRACE=2 perl yourscript.pl ...args1... 2>&1 | dbilogstrip > dbitrace1.log -\& DBI_TRACE=2 perl yourscript.pl ...args2... 2>&1 | dbilogstrip > dbitrace2.log -\& diff \-u dbitrace1.log dbitrace2.log -.Ve -.PP -See dbilogstrip for more information. -.SH "DBI ENVIRONMENT VARIABLES" -.IX Header "DBI ENVIRONMENT VARIABLES" -The \s-1DBI\s0 module recognizes a number of environment variables, but most of -them should not be used most of the time. -It is better to be explicit about what you are doing to avoid the need -for environment variables, especially in a web serving system where web -servers are stingy about which environment variables are available. -.SS "\s-1DBI_DSN\s0" -.IX Subsection "DBI_DSN" -The \s-1DBI_DSN\s0 environment variable is used by \s-1DBI\-\s0>connect if you do not -specify a data source when you issue the connect. -It should have a format such as \*(L"dbi:Driver:databasename\*(R". -.SS "\s-1DBI_DRIVER\s0" -.IX Subsection "DBI_DRIVER" -The \s-1DBI_DRIVER\s0 environment variable is used to fill in the database -driver name in \s-1DBI\-\s0>connect if the data source string starts \*(L"dbi::\*(R" -(thereby omitting the driver). -If \s-1DBI_DSN\s0 omits the driver name, \s-1DBI_DRIVER\s0 can fill the gap. -.SS "\s-1DBI_AUTOPROXY\s0" -.IX Subsection "DBI_AUTOPROXY" -The \s-1DBI_AUTOPROXY\s0 environment variable takes a string value that starts -\&\*(L"dbi:Proxy:\*(R" and is typically followed by \*(L"hostname=...;port=...\*(R". -It is used to alter the behaviour of \s-1DBI\-\s0>connect. -For full details, see DBI::Proxy documentation. -.SS "\s-1DBI_USER\s0" -.IX Subsection "DBI_USER" -The \s-1DBI_USER\s0 environment variable takes a string value that is used as -the user name if the \s-1DBI\-\s0>connect call is given undef (as distinct from -an empty string) as the username argument. -Be wary of the security implications of using this. -.SS "\s-1DBI_PASS\s0" -.IX Subsection "DBI_PASS" -The \s-1DBI_PASS\s0 environment variable takes a string value that is used as -the password if the \s-1DBI\-\s0>connect call is given undef (as distinct from -an empty string) as the password argument. -Be extra wary of the security implications of using this. -.SS "\s-1DBI_DBNAME \s0(obsolete)" -.IX Subsection "DBI_DBNAME (obsolete)" -The \s-1DBI_DBNAME\s0 environment variable takes a string value that is used only when the -obsolescent style of \s-1DBI\-\s0>connect (with driver name as fourth parameter) is used, and -when no value is provided for the first (database name) argument. -.SS "\s-1DBI_TRACE\s0" -.IX Subsection "DBI_TRACE" -The \s-1DBI_TRACE\s0 environment variable specifies the global default -trace settings for the \s-1DBI\s0 at startup. Can also be used to direct -trace output to a file. When the \s-1DBI\s0 is loaded it does: -.PP -.Vb 1 -\& DBI\->trace(split /=/, $ENV{DBI_TRACE}, 2) if $ENV{DBI_TRACE}; -.Ve -.PP -So if \f(CW\*(C`DBI_TRACE\*(C'\fR contains an "\f(CW\*(C`=\*(C'\fR" character then what follows -it is used as the name of the file to append the trace to. -.PP -output appended to that file. If the name begins with a number -followed by an equal sign (\f(CW\*(C`=\*(C'\fR), then the number and the equal sign are -stripped off from the name, and the number is used to set the trace -level. For example: -.PP -.Vb 1 -\& DBI_TRACE=1=dbitrace.log perl your_test_script.pl -.Ve -.PP -On Unix-like systems using a Bourne-like shell, you can do this easily -on the command line: -.PP -.Vb 1 -\& DBI_TRACE=2 perl your_test_script.pl -.Ve -.PP -See \*(L"\s-1TRACING\*(R"\s0 for more information. -.SS "\s-1PERL_DBI_DEBUG \s0(obsolete)" -.IX Subsection "PERL_DBI_DEBUG (obsolete)" -An old variable that should no longer be used; equivalent to \s-1DBI_TRACE.\s0 -.SS "\s-1DBI_PROFILE\s0" -.IX Subsection "DBI_PROFILE" -The \s-1DBI_PROFILE\s0 environment variable can be used to enable profiling -of \s-1DBI\s0 method calls. See DBI::Profile for more information. -.SS "\s-1DBI_PUREPERL\s0" -.IX Subsection "DBI_PUREPERL" -The \s-1DBI_PUREPERL\s0 environment variable can be used to enable the -use of DBI::PurePerl. See DBI::PurePerl for more information. -.SH "WARNING AND ERROR MESSAGES" -.IX Header "WARNING AND ERROR MESSAGES" -.SS "Fatal Errors" -.IX Subsection "Fatal Errors" -.ie n .IP "Can't call method ""prepare"" without a package or object reference" 4 -.el .IP "Can't call method ``prepare'' without a package or object reference" 4 -.IX Item "Can't call method prepare without a package or object reference" -The \f(CW$dbh\fR handle you're using to call \f(CW\*(C`prepare\*(C'\fR is probably undefined because -the preceding \f(CW\*(C`connect\*(C'\fR failed. You should always check the return status of -\&\s-1DBI\s0 methods, or use the \*(L"RaiseError\*(R" attribute. -.ie n .IP "Can't call method ""execute"" without a package or object reference" 4 -.el .IP "Can't call method ``execute'' without a package or object reference" 4 -.IX Item "Can't call method execute without a package or object reference" -The \f(CW$sth\fR handle you're using to call \f(CW\*(C`execute\*(C'\fR is probably undefined because -the preceding \f(CW\*(C`prepare\*(C'\fR failed. You should always check the return status of -\&\s-1DBI\s0 methods, or use the \*(L"RaiseError\*(R" attribute. -.IP "\s-1DBI/DBD\s0 internal version mismatch" 4 -.IX Item "DBI/DBD internal version mismatch" -The \s-1DBD\s0 driver module was built with a different version of \s-1DBI\s0 than -the one currently being used. You should rebuild the \s-1DBD\s0 module under -the current version of \s-1DBI.\s0 -.Sp -(Some rare platforms require \*(L"static linking\*(R". On those platforms, there -may be an old \s-1DBI\s0 or \s-1DBD\s0 driver version actually embedded in the Perl -executable being used.) -.IP "\s-1DBD\s0 driver has not implemented the AutoCommit attribute" 4 -.IX Item "DBD driver has not implemented the AutoCommit attribute" -The \s-1DBD\s0 driver implementation is incomplete. Consult the author. -.ie n .IP "Can't [sg]et %s\->{%s}: unrecognised attribute" 4 -.el .IP "Can't [sg]et \f(CW%s\fR\->{%s}: unrecognised attribute" 4 -.IX Item "Can't [sg]et %s->{%s}: unrecognised attribute" -You attempted to set or get an unknown attribute of a handle. Make -sure you have spelled the attribute name correctly; case is significant -(e.g., \*(L"Autocommit\*(R" is not the same as \*(L"AutoCommit\*(R"). -.SH "Pure-Perl DBI" -.IX Header "Pure-Perl DBI" -A pure-perl emulation of the \s-1DBI\s0 is included in the distribution -for people using pure-perl drivers who, for whatever reason, can't -install the compiled \s-1DBI.\s0 See DBI::PurePerl. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -.SS "Driver and Database Documentation" -.IX Subsection "Driver and Database Documentation" -Refer to the documentation for the \s-1DBD\s0 driver that you are using. -.PP -Refer to the \s-1SQL\s0 Language Reference Manual for the database engine that you are using. -.SS "\s-1ODBC\s0 and \s-1SQL/CLI\s0 Standards Reference Information" -.IX Subsection "ODBC and SQL/CLI Standards Reference Information" -More detailed information about the semantics of certain \s-1DBI\s0 methods -that are based on \s-1ODBC\s0 and \s-1SQL/CLI\s0 standards is available on-line -via microsoft.com, for \s-1ODBC,\s0 and www.jtc1sc32.org for the \s-1SQL/CLI\s0 -standard: -.PP -.Vb 9 -\& DBI method ODBC function SQL/CLI Working Draft -\& \-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- -\& column_info SQLColumns Page 124 -\& foreign_key_info SQLForeignKeys Page 163 -\& get_info SQLGetInfo Page 214 -\& primary_key_info SQLPrimaryKeys Page 254 -\& table_info SQLTables Page 294 -\& type_info SQLGetTypeInfo Page 239 -\& statistics_info SQLStatistics -.Ve -.PP -To find documentation on the \s-1ODBC\s0 function you can use -the \s-1MSDN\s0 search facility at: -.PP -.Vb 1 -\& http://msdn.microsoft.com/Search -.Ve -.PP -and search for something like \f(CW"SQLColumns returns"\fR. -.PP -And for \s-1SQL/CLI\s0 standard information on SQLColumns you'd read page 124 of -the (very large) \s-1SQL/CLI\s0 Working Draft available from: -.PP -.Vb 1 -\& http://jtc1sc32.org/doc/N0701\-0750/32N0744T.pdf -.Ve -.SS "Standards Reference Information" -.IX Subsection "Standards Reference Information" -A hyperlinked, browsable version of the \s-1BNF\s0 syntax for \s-1SQL92 \s0(plus -Oracle 7 \s-1SQL\s0 and \s-1PL/SQL\s0) is available here: -.PP -.Vb 1 -\& http://cui.unige.ch/db\-research/Enseignement/analyseinfo/SQL92/BNFindex.html -.Ve -.PP -You can find more information about \s-1SQL\s0 standards online by searching for the -appropriate standard names and numbers. For example, searching for -\&\*(L"\s-1ANSI/ISO/IEC\s0 International Standard (\s-1IS\s0) Database Language \s-1SQL \-\s0 Part 1: -SQL/Framework\*(R" you'll find a copy at: -.PP -.Vb 1 -\& ftp://ftp.iks\-jena.de/mitarb/lutz/standards/sql/ansi\-iso\-9075\-1\-1999.pdf -.Ve -.SS "Books and Articles" -.IX Subsection "Books and Articles" -Programming the Perl \s-1DBI,\s0 by Alligator Descartes and Tim Bunce. - -.PP -Programming Perl 3rd Ed. by Larry Wall, Tom Christiansen & Jon Orwant. - -.PP -Learning Perl by Randal Schwartz. - -.PP -Details of many other books related to perl can be found at -.SS "Perl Modules" -.IX Subsection "Perl Modules" -Index of \s-1DBI\s0 related modules available from \s-1CPAN:\s0 -.PP -.Vb 3 -\& L -\& L -\& L -.Ve -.PP -For a good comparison of RDBMS-OO mappers and some OO-RDBMS mappers -(including Class::DBI, Alzabo, and DBIx::RecordSet in the former -category and Tangram and \s-1SPOPS\s0 in the latter) see the Perl -Object-Oriented Persistence project pages at: -.PP -.Vb 1 -\& http://poop.sourceforge.net -.Ve -.PP -A similar page for Java toolkits can be found at: -.PP -.Vb 1 -\& http://c2.com/cgi\-bin/wiki?ObjectRelationalToolComparison -.Ve -.SS "Mailing List" -.IX Subsection "Mailing List" -The \fIdbi-users\fR mailing list is the primary means of communication among -users of the \s-1DBI\s0 and its related modules. For details send email to: -.PP -.Vb 1 -\& L -.Ve -.PP -There are typically between 700 and 900 messages per month. You have -to subscribe in order to be able to post. However you can opt for a -\&'post\-only' subscription. -.PP -Mailing list archives (of variable quality) are held at: -.PP -.Vb 3 -\& http://groups.google.com/groups?group=perl.dbi.users -\& http://www.xray.mpe.mpg.de/mailing\-lists/dbi/ -\& http://www.mail\-archive.com/dbi\-users%40perl.org/ -.Ve -.SS "Assorted Related Links" -.IX Subsection "Assorted Related Links" -The \s-1DBI \s0\*(L"Home Page\*(R": -.PP -.Vb 1 -\& http://dbi.perl.org/ -.Ve -.PP -Other \s-1DBI\s0 related links: -.PP -.Vb 2 -\& http://www.perlmonks.org/?node=DBI%20recipes -\& http://www.perlmonks.org/?node=Speeding%20up%20the%20DBI -.Ve -.PP -Other database related links: -.PP -.Vb 1 -\& http://www.connectionstrings.com/ -.Ve -.PP -Security, especially the \*(L"\s-1SQL\s0 Injection\*(R" attack: -.PP -.Vb 2 -\& http://bobby\-tables.com/ -\& http://online.securityfocus.com/infocus/1644 -.Ve -.SS "\s-1FAQ\s0" -.IX Subsection "FAQ" -See -.SH "AUTHORS" -.IX Header "AUTHORS" -\&\s-1DBI\s0 by Tim Bunce, -.PP -This pod text by Tim Bunce, J. Douglas Dunlop, Jonathan Leffler and others. -Perl by Larry Wall and the \f(CW\*(C`perl5\-porters\*(C'\fR. -.SH "COPYRIGHT" -.IX Header "COPYRIGHT" -The \s-1DBI\s0 module is Copyright (c) 1994\-2012 Tim Bunce. Ireland. -All rights reserved. -.PP -You may distribute under the terms of either the \s-1GNU\s0 General Public -License or the Artistic License, as specified in the Perl 5.10.0 \s-1README\s0 file. -.SH "SUPPORT / WARRANTY" -.IX Header "SUPPORT / WARRANTY" -The \s-1DBI\s0 is free Open Source software. \s-1IT COMES WITHOUT WARRANTY OF ANY KIND.\s0 -.SS "Support" -.IX Subsection "Support" -My consulting company, Data Plan Services, offers annual and -multi-annual support contracts for the \s-1DBI.\s0 These provide sustained -support for \s-1DBI\s0 development, and sustained value for you in return. -Contact me for details. -.SS "Sponsor Enhancements" -.IX Subsection "Sponsor Enhancements" -If your company would benefit from a specific new \s-1DBI\s0 feature, -please consider sponsoring its development. Work is performed -rapidly, and usually on a fixed-price payment-on-delivery basis. -Contact me for details. -.PP -Using such targeted financing allows you to contribute to \s-1DBI\s0 -development, and rapidly get something specific and valuable in return. -.SH "ACKNOWLEDGEMENTS" -.IX Header "ACKNOWLEDGEMENTS" -I would like to acknowledge the valuable contributions of the many -people I have worked with on the \s-1DBI\s0 project, especially in the early -years (1992\-1994). In no particular order: Kevin Stock, Buzz Moschetti, -Kurt Andersen, Ted Lemon, William Hails, Garth Kennedy, Michael Peppler, -Neil S. Briscoe, Jeff Urlwin, David J. Hughes, Jeff Stander, -Forrest D Whitcher, Larry Wall, Jeff Fried, Roy Johnson, Paul Hudson, -Georg Rehfeld, Steve Sizemore, Ron Pool, Jon Meek, Tom Christiansen, -Steve Baumgarten, Randal Schwartz, and a whole lot more. -.PP -Then, of course, there are the poor souls who have struggled through -untold and undocumented obstacles to actually implement \s-1DBI\s0 drivers. -Among their ranks are Jochen Wiedmann, Alligator Descartes, Jonathan -Leffler, Jeff Urlwin, Michael Peppler, Henrik Tougaard, Edwin Pratomo, -Davide Migliavacca, Jan Pazdziora, Peter Haworth, Edmund Mergl, Steve -Williams, Thomas Lowery, and Phlip Plumlee. Without them, the \s-1DBI\s0 would -not be the practical reality it is today. I'm also especially grateful -to Alligator Descartes for starting work on the first edition of the -\&\*(L"Programming the Perl \s-1DBI\*(R"\s0 book and letting me jump on board. -.PP -The \s-1DBI\s0 and DBD::Oracle were originally developed while I was Technical -Director (\s-1CTO\s0) of the Paul Ingram Group in the \s-1UK. \s0 So I'd especially like -to thank Paul for his generosity and vision in supporting this work for many years. -.PP -A couple of specific \s-1DBI\s0 features have been sponsored by enlightened companies: -.PP -The development of the \fIswap_inner_handle()\fR method was sponsored by BizRate.com () -.PP -The development of DBD::Gofer and related modules was sponsored by -Shopzilla.com (), where I currently work. -.SH "CONTRIBUTING" -.IX Header "CONTRIBUTING" -As you can see above, many people have contributed to the \s-1DBI\s0 and -drivers in many ways over many years. -.PP -If you'd like to help then see . -.PP -If you'd like the \s-1DBI\s0 to do something new or different then a good way -to make that happen is to do it yourself and send me a patch to the -source code that shows the changes. (But read \*(L"Speak before you patch\*(R" -below.) -.SS "Browsing the source code repository" -.IX Subsection "Browsing the source code repository" -Use https://github.com/perl5\-dbi/dbi -.SS "How to create a patch using Git" -.IX Subsection "How to create a patch using Git" -The \s-1DBI\s0 source code is maintained using Git. To access the source -you'll need to install a Git client. Then, to get the source code, do: -.PP -.Vb 1 -\& git clone https://github.com/perl5\-dbi/dbi.git DBI\-git -.Ve -.PP -The source code will now be available in the new subdirectory \f(CW\*(C`DBI\-git\*(C'\fR. -.PP -When you want to synchronize later, issue the command -.PP -.Vb 1 -\& git pull \-\-all -.Ve -.PP -Make your changes, test them, test them again until everything passes. -If there are no tests for the new feature you added or a behaviour change, -the change should include a new test. Then commit the changes. Either use -.PP -.Vb 1 -\& git gui -.Ve -.PP -or -.PP -.Vb 1 -\& git commit \-a \-m \*(AqMessage to my changes\*(Aq -.Ve -.PP -If you get any conflicts reported you'll need to fix them first. -.PP -Then generate the patch file to be mailed: -.PP -.Vb 1 -\& git format\-patch \-1 \-\-attach -.Ve -.PP -which will create a file 0001\-*.patch (where * relates to the commit message). -Read the patch file, as a sanity check, and then email it to dbi\-dev@perl.org. -.PP -If you have a github account, you can also fork the -repository, commit your changes to the forked repository and then do a -pull request. -.SS "How to create a patch without Git" -.IX Subsection "How to create a patch without Git" -Unpack a fresh copy of the distribution: -.PP -.Vb 2 -\& wget http://cpan.metacpan.org/authors/id/T/TI/TIMB/DBI\-1.627.tar.gz -\& tar xfz DBI\-1.627.tar.gz -.Ve -.PP -Rename the newly created top level directory: -.PP -.Vb 1 -\& mv DBI\-1.627 DBI\-1.627.your_foo -.Ve -.PP -Edit the contents of \s-1DBI\-1.627\s0.your_foo/* till it does what you want. -.PP -Test your changes and then remove all temporary files: -.PP -.Vb 1 -\& make test && make distclean -.Ve -.PP -Go back to the directory you originally unpacked the distribution: -.PP -.Vb 1 -\& cd .. -.Ve -.PP -Unpack \fIanother\fR copy of the original distribution you started with: -.PP -.Vb 1 -\& tar xfz DBI\-1.627.tar.gz -.Ve -.PP -Then create a patch file by performing a recursive \f(CW\*(C`diff\*(C'\fR on the two -top level directories: -.PP -.Vb 1 -\& diff \-purd DBI\-1.627 DBI\-1.627.your_foo > DBI\-1.627.your_foo.patch -.Ve -.SS "Speak before you patch" -.IX Subsection "Speak before you patch" -For anything non-trivial or possibly controversial it's a good idea -to discuss (on dbi\-dev@perl.org) the changes you propose before -actually spending time working on them. Otherwise you run the risk -of them being rejected because they don't fit into some larger plans -you may not be aware of. -.PP -You can also reach the developers on \s-1IRC \s0(chat). If they are on-line, -the most likely place to talk to them is the #dbi channel on irc.perl.org -.SH "TRANSLATIONS" -.IX Header "TRANSLATIONS" -A German translation of this manual (possibly slightly out of date) is -available, thanks to O'Reilly, at: -.PP -.Vb 1 -\& http://www.oreilly.de/catalog/perldbiger/ -.Ve -.SH "TRAINING" -.IX Header "TRAINING" -References to \s-1DBI\s0 related training resources. No recommendation implied. -.PP -.Vb 2 -\& http://www.treepax.co.uk/ -\& http://www.keller.com/dbweb/ -.Ve -.PP -(If you offer professional \s-1DBI\s0 related training services, -please send me your details so I can add them here.) -.SH "OTHER RELATED WORK AND PERL MODULES" -.IX Header "OTHER RELATED WORK AND PERL MODULES" -.IP "Apache::DBI" 4 -.IX Item "Apache::DBI" -To be used with the Apache daemon together with an embedded Perl -interpreter like \f(CW\*(C`mod_perl\*(C'\fR. Establishes a database connection which -remains open for the lifetime of the \s-1HTTP\s0 daemon. This way the \s-1CGI\s0 -connect and disconnect for every database access becomes superfluous. -.IP "\s-1SQL\s0 Parser" 4 -.IX Item "SQL Parser" -See also the SQL::Statement module, \s-1SQL\s0 parser and engine. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfo::ANSI.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfo::ANSI.3pm deleted file mode 100644 index 96ef963..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfo::ANSI.3pm +++ /dev/null @@ -1,119 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Const::GetInfo::ANSI 3pm" -.TH DBI::Const::GetInfo::ANSI 3pm "2015-05-26" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Const::GetInfo::ANSI \- ISO/IEC SQL/CLI Constants for GetInfo -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& The API for this module is private and subject to change. -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Information requested by \fIGetInfo()\fR. -.PP -See: A.1 C header file \s-1SQLCLI.H,\s0 Page 316, 317. -.PP -The \s-1API\s0 for this module is private and subject to change. -.SH "REFERENCES" -.IX Header "REFERENCES" -.Vb 2 -\& ISO/IEC FCD 9075\-3:200x Information technology \- Database Languages \- -\& SQL \- Part 3: Call\-Level Interface (SQL/CLI) -\& -\& SC32 N00744 = WG3:VIE\-005 = H2\-2002\-007 -\& -\& Date: 2002\-01\-15 -.Ve -.ie n .SS "%ReturnTypes" -.el .SS "\f(CW%ReturnTypes\fP" -.IX Subsection "%ReturnTypes" -See: Codes and data types for implementation information (Table 28), Page 85, 86. -.PP -Mapped to \s-1ODBC\s0 datatype names. -.ie n .SS "%ReturnValues" -.el .SS "\f(CW%ReturnValues\fP" -.IX Subsection "%ReturnValues" -See: A.1 C header file \s-1SQLCLI.H,\s0 Page 317, 318. -.SH "TODO" -.IX Header "TODO" -Corrections, e.g.: -.PP -.Vb 1 -\& SQL_TRANSACTION_ISOLATION_OPTION vs. SQL_TRANSACTION_ISOLATION -.Ve diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfo::ODBC.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfo::ODBC.3pm deleted file mode 100644 index a952eb6..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfo::ODBC.3pm +++ /dev/null @@ -1,121 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Const::GetInfo::ODBC 3pm" -.TH DBI::Const::GetInfo::ODBC 3pm "2015-05-26" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Const::GetInfo::ODBC \- ODBC Constants for GetInfo -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& The API for this module is private and subject to change. -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Information requested by \fIGetInfo()\fR. -.PP -The \s-1API\s0 for this module is private and subject to change. -.SH "REFERENCES" -.IX Header "REFERENCES" -.Vb 2 -\& MDAC SDK 2.6 -\& ODBC version number (0x0351) -\& -\& sql.h -\& sqlext.h -.Ve -.ie n .SS "%ReturnTypes" -.el .SS "\f(CW%ReturnTypes\fP" -.IX Subsection "%ReturnTypes" -See: mk:@MSITStore:X:\edm\ecli\emdac\esdk26\eDocs\eodbc.chm::/htm/odbcsqlgetinfo.htm -.PP -.Vb 2 -\& => : alias -\& => !!! : edited -.Ve -.ie n .SS "%ReturnValues" -.el .SS "\f(CW%ReturnValues\fP" -.IX Subsection "%ReturnValues" -See: sql.h, sqlext.h -Edited: - \s-1SQL_TXN_ISOLATION_OPTION\s0 -.SH "TODO" -.IX Header "TODO" -.Vb 3 -\& Corrections? -\& SQL_NULL_COLLATION: ODBC vs ANSI -\& Unique values for $ReturnValues{...}?, e.g. SQL_FILE_USAGE -.Ve diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfoReturn.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfoReturn.3pm deleted file mode 100644 index 7246e42..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfoReturn.3pm +++ /dev/null @@ -1,86 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Const::GetInfoReturn 3pm" -.TH DBI::Const::GetInfoReturn 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Const::GetInfoReturn \- Data and functions for describing GetInfo results -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -The interface to this module is undocumented and liable to change. -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Data and functions for describing GetInfo results diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfoType.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfoType.3pm deleted file mode 100644 index a390611..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Const::GetInfoType.3pm +++ /dev/null @@ -1,96 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Const::GetInfoType 3pm" -.TH DBI::Const::GetInfoType 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Const::GetInfoType \- Data describing GetInfo type codes -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& use DBI::Const::GetInfoType; -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Imports a \f(CW%GetInfoType\fR hash which maps names for GetInfo Type Codes -into their corresponding numeric values. For example: -.PP -.Vb 1 -\& $database_version = $dbh\->get_info( $GetInfoType{SQL_DBMS_VER} ); -.Ve -.PP -The interface to this module is new and nothing beyond what is -written here is guaranteed. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD.3pm deleted file mode 100644 index d4ad5a1..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD.3pm +++ /dev/null @@ -1,3453 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::DBD 3pm" -.TH DBI::DBD 3pm "2016-04-21" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::DBD \- Perl DBI Database Driver Writer's Guide -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& perldoc DBI::DBD -.Ve -.SS "Version and volatility" -.IX Subsection "Version and volatility" -This document is \fIstill\fR a minimal draft which is in need of further work. -.PP -Please read the \fB\s-1DBI\s0\fR documentation first and fully. Then look at the -implementation of some high-profile and regularly maintained drivers like -DBD::Oracle, \s-1DBD::ODBC,\s0 DBD::Pg etc. (Those are no no particular order.) -.PP -Then reread the \fB\s-1DBI\s0\fR specification and the code of those drivers again as -you're reading this. It'll help. Where this document and the driver code -differ it's likely that the driver code is more correct, especially if multiple -drivers do the same thing. -.PP -This document is a patchwork of contributions from various authors. -More contributions (preferably as patches) are very welcome. -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This document is primarily intended to help people writing new -database drivers for the Perl Database Interface (Perl \s-1DBI\s0). -It may also help others interested in discovering why the internals of -a \fB\s-1DBD\s0\fR driver are written the way they are. -.PP -This is a guide. Few (if any) of the statements in it are completely -authoritative under all possible circumstances. This means you will -need to use judgement in applying the guidelines in this document. -If in \fIany\fR doubt at all, please do contact the \fIdbi-dev\fR mailing list -(details given below) where Tim Bunce and other driver authors can help. -.SH "CREATING A NEW DRIVER" -.IX Header "CREATING A NEW DRIVER" -The first rule for creating a new database driver for the Perl \s-1DBI\s0 is -very simple: \fB\s-1DON\s0'T!\fR -.PP -There is usually a driver already available for the database you want -to use, almost regardless of which database you choose. Very often, the -database will provide an \s-1ODBC\s0 driver interface, so you can often use -\&\fB\s-1DBD::ODBC\s0\fR to access the database. This is typically less convenient -on a Unix box than on a Microsoft Windows box, but there are numerous -options for \s-1ODBC\s0 driver managers on Unix too, and very often the \s-1ODBC\s0 -driver is provided by the database supplier. -.PP -Before deciding that you need to write a driver, do your homework to -ensure that you are not wasting your energies. -.PP -[As of December 2002, the consensus is that if you need an \s-1ODBC\s0 driver -manager on Unix, then the unixODBC driver (available from -) is the way to go.] -.PP -The second rule for creating a new database driver for the Perl \s-1DBI\s0 is -also very simple: \fBDon't \*(-- get someone else to do it for you!\fR -.PP -Nevertheless, there are occasions when it is necessary to write a new -driver, often to use a proprietary language or \s-1API\s0 to access the -database more swiftly, or more comprehensively, than an \s-1ODBC\s0 driver can. -Then you should read this document very carefully, but with a suitably -sceptical eye. -.PP -If there is something in here that does not make any sense, question it. -You might be right that the information is bogus, but don't come to that -conclusion too quickly. -.SS "URLs and mailing lists" -.IX Subsection "URLs and mailing lists" -The primary web-site for locating \fB\s-1DBI\s0\fR software and information is -.PP -.Vb 1 -\& http://dbi.perl.org/ -.Ve -.PP -There are two main and one auxiliary mailing lists for people working -with \fB\s-1DBI\s0\fR. The primary lists are \fIdbi\-users@perl.org\fR for general users -of \fB\s-1DBI\s0\fR and \fB\s-1DBD\s0\fR drivers, and \fIdbi\-dev@perl.org\fR mainly for \fB\s-1DBD\s0\fR driver -writers (don't join the \fIdbi-dev\fR list unless you have a good reason). -The auxiliary list is \fIdbi\-announce@perl.org\fR for announcing new -releases of \fB\s-1DBI\s0\fR or \fB\s-1DBD\s0\fR drivers. -.PP -You can join these lists by accessing the web-site . -The lists are closed so you cannot send email to any of the lists -unless you join the list first. -.PP -You should also consider monitoring the \fIcomp.lang.perl.*\fR newsgroups, -especially \fIcomp.lang.perl.modules\fR. -.SS "The Cheetah book" -.IX Subsection "The Cheetah book" -The definitive book on Perl \s-1DBI\s0 is the Cheetah book, so called because -of the picture on the cover. Its proper title is '\fIProgramming the -Perl \s-1DBI:\s0 Database programming with Perl\fR' by Alligator Descartes -and Tim Bunce, published by O'Reilly Associates, February 2000, \s-1ISBN -1\-56592\-699\-4.\s0 Buy it now if you have not already done so, and read it. -.SS "Locating drivers" -.IX Subsection "Locating drivers" -Before writing a new driver, it is in your interests to find out -whether there already is a driver for your database. If there is such -a driver, it would be much easier to make use of it than to write your -own! -.PP -The primary web-site for locating Perl software is -. You should look under the various -modules listings for the software you are after. For example: -.PP -.Vb 1 -\& http://search.cpan.org/modlist/Database_Interfaces -.Ve -.PP -Follow the \fB\s-1DBD::\s0\fR and \fBDBIx::\fR links at the top to see those subsets. -.PP -See the \fB\s-1DBI\s0\fR docs for information on \fB\s-1DBI\s0\fR web sites and mailing lists. -.SS "Registering a new driver" -.IX Subsection "Registering a new driver" -Before going through any official registration process, you will need -to establish that there is no driver already in the works. You'll do -that by asking the \fB\s-1DBI\s0\fR mailing lists whether there is such a driver -available, or whether anybody is working on one. -.PP -When you get the go ahead, you will need to establish the name of the -driver and a prefix for the driver. Typically, the name is based on the -name of the database software it uses, and the prefix is a contraction -of that. Hence, \fBDBD::Oracle\fR has the name \fIOracle\fR and the prefix -\&'\fIora_\fR'. The prefix must be lowercase and contain no underscores other -than the one at the end. -.PP -This information will be recorded in the \fB\s-1DBI\s0\fR module. Apart from -documentation purposes, registration is a prerequisite for -installing private methods. -.PP -If you are writing a driver which will not be distributed on \s-1CPAN,\s0 then -you should choose a prefix beginning with '\fIx_\fR', to avoid potential -prefix collisions with drivers registered in the future. Thus, if you -wrote a non-CPAN distributed driver called \fBDBD::CustomDB\fR, the prefix -might be '\fIx_cdb_\fR'. -.PP -This document assumes you are writing a driver called \fBDBD::Driver\fR, and -that the prefix '\fIdrv_\fR' is assigned to the driver. -.SS "Two styles of database driver" -.IX Subsection "Two styles of database driver" -There are two distinct styles of database driver that can be written to -work with the Perl \s-1DBI.\s0 -.PP -Your driver can be written in pure Perl, requiring no C compiler. -When feasible, this is the best solution, but most databases are not -written in such a way that this can be done. Some examples of pure -Perl drivers are \fBDBD::File\fR and \fB\s-1DBD::CSV\s0\fR. -.PP -Alternatively, and most commonly, your driver will need to use some C -code to gain access to the database. This will be classified as a C/XS -driver. -.SS "What code will you write?" -.IX Subsection "What code will you write?" -There are a number of files that need to be written for either a pure -Perl driver or a C/XS driver. There are no extra files needed only by -a pure Perl driver, but there are several extra files needed only by a -C/XS driver. -.PP -\fIFiles common to pure Perl and C/XS drivers\fR -.IX Subsection "Files common to pure Perl and C/XS drivers" -.PP -Assuming that your driver is called \fBDBD::Driver\fR, these files are: -.IP "\(bu" 4 -\&\fIMakefile.PL\fR -.IP "\(bu" 4 -\&\fI\s-1META\s0.yml\fR -.IP "\(bu" 4 -\&\fI\s-1README\s0\fR -.IP "\(bu" 4 -\&\fI\s-1MANIFEST\s0\fR -.IP "\(bu" 4 -\&\fIDriver.pm\fR -.IP "\(bu" 4 -\&\fIlib/Bundle/DBD/Driver.pm\fR -.IP "\(bu" 4 -\&\fIlib/DBD/Driver/Summary.pm\fR -.IP "\(bu" 4 -\&\fIt/*.t\fR -.PP -The first four files are mandatory. \fIMakefile.PL\fR is used to control -how the driver is built and installed. The \fI\s-1README\s0\fR file tells people -who download the file about how to build the module and any prerequisite -software that must be installed. The \fI\s-1MANIFEST\s0\fR file is used by the -standard Perl module distribution mechanism. It lists all the source -files that need to be distributed with your module. \fIDriver.pm\fR is what -is loaded by the \fB\s-1DBI\s0\fR code; it contains the methods peculiar to your -driver. -.PP -Although the \fI\s-1META\s0.yml\fR file is not \fBrequired\fR you are advised to -create one. Of particular importance are the \fIbuild_requires\fR and -\&\fIconfigure_requires\fR attributes which newer \s-1CPAN\s0 modules understand. -You use these to tell the \s-1CPAN\s0 module (and \s-1CPANPLUS\s0) that your build -and configure mechanisms require \s-1DBI.\s0 The best reference for \s-1META\s0.yml -(at the time of writing) is -. You can find -a reasonable example of a \fI\s-1META\s0.yml\fR in \s-1DBD::ODBC.\s0 -.PP -The \fIlib/Bundle/DBD/Driver.pm\fR file allows you to specify other Perl -modules on which yours depends in a format that allows someone to type a -simple command and ensure that all the pre-requisites are in place as -well as building your driver. -.PP -The \fIlib/DBD/Driver/Summary.pm\fR file contains (an updated version of) the -information that was included \- or that would have been included \- in -the appendices of the Cheetah book as a summary of the abilities of your -driver and the associated database. -.PP -The files in the \fIt\fR subdirectory are unit tests for your driver. -You should write your tests as stringently as possible, while taking -into account the diversity of installations that you can encounter: -.IP "\(bu" 4 -Your tests should not casually modify operational databases. -.IP "\(bu" 4 -You should never damage existing tables in a database. -.IP "\(bu" 4 -You should code your tests to use a constrained name space within the -database. For example, the tables (and all other named objects) that are -created could all begin with '\fIdbd_drv_\fR'. -.IP "\(bu" 4 -At the end of a test run, there should be no testing objects left behind -in the database. -.IP "\(bu" 4 -If you create any databases, you should remove them. -.IP "\(bu" 4 -If your database supports temporary tables that are automatically -removed at the end of a session, then exploit them as often as possible. -.IP "\(bu" 4 -Try to make your tests independent of each other. If you have a -test \fIt/t11dowhat.t\fR that depends upon the successful running -of \fIt/t10thingamy.t\fR, people cannot run the single test case -\&\fIt/t11dowhat.t\fR. Further, running \fIt/t11dowhat.t\fR twice in a row is -likely to fail (at least, if \fIt/t11dowhat.t\fR modifies the database at -all) because the database at the start of the second run is not what you -saw at the start of the first run. -.IP "\(bu" 4 -Document in your \fI\s-1README\s0\fR file what you do, and what privileges people -need to do it. -.IP "\(bu" 4 -You can, and probably should, sequence your tests by including a test -number before an abbreviated version of the test name; the tests are run -in the order in which the names are expanded by shell-style globbing. -.IP "\(bu" 4 -It is in your interests to ensure that your tests work as widely -as possible. -.PP -Many drivers also install sub-modules \fBDBD::Driver::SubModule\fR -for any of a variety of different reasons, such as to support -the metadata methods (see the discussion of \*(L"\s-1METADATA METHODS\*(R"\s0 -below). Such sub-modules are conventionally stored in the directory -\&\fIlib/DBD/Driver\fR. The module itself would usually be in a file -\&\fISubModule.pm\fR. All such sub-modules should themselves be version -stamped (see the discussions far below). -.PP -\fIExtra files needed by C/XS drivers\fR -.IX Subsection "Extra files needed by C/XS drivers" -.PP -The software for a C/XS driver will typically contain at least four -extra files that are not relevant to a pure Perl driver. -.IP "\(bu" 4 -\&\fIDriver.xs\fR -.IP "\(bu" 4 -\&\fIDriver.h\fR -.IP "\(bu" 4 -\&\fIdbdimp.h\fR -.IP "\(bu" 4 -\&\fIdbdimp.c\fR -.PP -The \fIDriver.xs\fR file is used to generate C code that Perl can call to gain -access to the C functions you write that will, in turn, call down onto -your database software. -.PP -The \fIDriver.h\fR header is a stylized header that ensures you can access the -necessary Perl and \fB\s-1DBI\s0\fR macros, types, and function declarations. -.PP -The \fIdbdimp.h\fR is used to specify which functions have been implemented by -your driver. -.PP -The \fIdbdimp.c\fR file is where you write the C code that does the real work -of translating between Perl-ish data types and what the database expects -to use and return. -.PP -There are some (mainly small, but very important) differences between -the contents of \fIMakefile.PL\fR and \fIDriver.pm\fR for pure Perl and C/XS -drivers, so those files are described both in the section on creating a -pure Perl driver and in the section on creating a C/XS driver. -.PP -Obviously, you can add extra source code files to the list. -.SS "Requirements on a driver and driver writer" -.IX Subsection "Requirements on a driver and driver writer" -To be remotely useful, your driver must be implemented in a format that -allows it to be distributed via \s-1CPAN,\s0 the Comprehensive Perl Archive -Network ( and ). -Of course, it is easier if you do not have to meet this criterion, but -you will not be able to ask for much help if you do not do so, and -no-one is likely to want to install your module if they have to learn a -new installation mechanism. -.SH "CREATING A PURE PERL DRIVER" -.IX Header "CREATING A PURE PERL DRIVER" -Writing a pure Perl driver is surprisingly simple. However, there are -some problems you should be aware of. The best option is of course -picking up an existing driver and carefully modifying one method -after the other. -.PP -Also look carefully at \fBDBD::AnyData\fR and \fBDBD::Template\fR. -.PP -As an example we take a look at the \fBDBD::File\fR driver, a driver for -accessing plain files as tables, which is part of the \fB\s-1DBD::CSV\s0\fR package. -.PP -The minimal set of files we have to implement are \fIMakefile.PL\fR, -\&\fI\s-1README\s0\fR, \fI\s-1MANIFEST\s0\fR and \fIDriver.pm\fR. -.SS "Pure Perl version of Makefile.PL" -.IX Subsection "Pure Perl version of Makefile.PL" -You typically start with writing \fIMakefile.PL\fR, a Makefile -generator. The contents of this file are described in detail in -the ExtUtils::MakeMaker man pages. It is definitely a good idea -if you start reading them. At least you should know about the -variables \fI\s-1CONFIGURE\s0\fR, \fI\s-1DEFINED\s0\fR, \fI\s-1PM\s0\fR, \fI\s-1DIR\s0\fR, \fI\s-1EXE_FILES\s0\fR, -\&\fI\s-1INC\s0\fR, \fI\s-1LIBS\s0\fR, \fI\s-1LINKTYPE\s0\fR, \fI\s-1NAME\s0\fR, \fI\s-1OPTIMIZE\s0\fR, \fI\s-1PL_FILES\s0\fR, -\&\fI\s-1VERSION\s0\fR, \fI\s-1VERSION_FROM\s0\fR, \fIclean\fR, \fIdepend\fR, \fIrealclean\fR from -the ExtUtils::MakeMaker man page: these are used in almost any -\&\fIMakefile.PL\fR. -.PP -Additionally read the section on \fIOverriding MakeMaker Methods\fR and the -descriptions of the \fIdistcheck\fR, \fIdisttest\fR and \fIdist\fR targets: They -will definitely be useful for you. -.PP -Of special importance for \fB\s-1DBI\s0\fR drivers is the \fIpostamble\fR method from -the ExtUtils::MM_Unix man page. -.PP -For Emacs users, I recommend the \fIlibscan\fR method, which removes -Emacs backup files (file names which end with a tilde '~') from lists of -files. -.PP -Now an example, I use the word \f(CW\*(C`Driver\*(C'\fR wherever you should insert -your driver's name: -.PP -.Vb 1 -\& # \-*\- perl \-*\- -\& -\& use ExtUtils::MakeMaker; -\& -\& WriteMakefile( -\& dbd_edit_mm_attribs( { -\& \*(AqNAME\*(Aq => \*(AqDBD::Driver\*(Aq, -\& \*(AqVERSION_FROM\*(Aq => \*(AqDriver.pm\*(Aq, -\& \*(AqINC\*(Aq => \*(Aq\*(Aq, -\& \*(Aqdist\*(Aq => { \*(AqSUFFIX\*(Aq => \*(Aq.gz\*(Aq, -\& \*(AqCOMPRESS\*(Aq => \*(Aqgzip \-9f\*(Aq }, -\& \*(Aqrealclean\*(Aq => { FILES => \*(Aq*.xsi\*(Aq }, -\& \*(AqPREREQ_PM\*(Aq => \*(Aq1.03\*(Aq, -\& \*(AqCONFIGURE\*(Aq => sub { -\& eval {require DBI::DBD;}; -\& if ($@) { -\& warn $@; -\& exit 0; -\& } -\& my $dbi_arch_dir = dbd_dbi_arch_dir(); -\& if (exists($opts{INC})) { -\& return {INC => "$opts{INC} \-I$dbi_arch_dir"}; -\& } else { -\& return {INC => "\-I$dbi_arch_dir"}; -\& } -\& } -\& }, -\& { create_pp_tests => 1}) -\& ); -\& -\& package MY; -\& sub postamble { return main::dbd_postamble(@_); } -\& sub libscan { -\& my ($self, $path) = @_; -\& ($path =~ m/\e~$/) ? undef : $path; -\& } -.Ve -.PP -Note the calls to \f(CW\*(C`dbd_edit_mm_attribs()\*(C'\fR and \f(CW\*(C`dbd_postamble()\*(C'\fR. -.PP -The second hash reference in the call to \f(CW\*(C`dbd_edit_mm_attribs()\*(C'\fR -(containing \f(CW\*(C`create_pp_tests()\*(C'\fR) is optional; you should not use it -unless your driver is a pure Perl driver (that is, it does not use C and -\&\s-1XS\s0 code). Therefore, the call to \f(CW\*(C`dbd_edit_mm_attribs()\*(C'\fR is not -relevant for C/XS drivers and may be omitted; simply use the (single) -hash reference containing \s-1NAME\s0 etc as the only argument to \f(CW\*(C`WriteMakefile()\*(C'\fR. -.PP -Note that the \f(CW\*(C`dbd_edit_mm_attribs()\*(C'\fR code will fail if you do not have a -\&\fIt\fR sub-directory containing at least one test case. -.PP -\&\fI\s-1PREREQ_PM\s0\fR tells MakeMaker that \s-1DBI \s0(version 1.03 in this case) is -required for this module. This will issue a warning that \s-1DBI 1.03\s0 is -missing if someone attempts to install your \s-1DBD\s0 without \s-1DBI 1.03.\s0 See -\&\fI\s-1CONFIGURE\s0\fR below for why this does not work reliably in stopping cpan -testers failing your module if \s-1DBI\s0 is not installed. -.PP -\&\fI\s-1CONFIGURE\s0\fR is a subroutine called by MakeMaker during -\&\f(CW\*(C`WriteMakefile\*(C'\fR. By putting the \f(CW\*(C`require DBI::DBD\*(C'\fR in this section -we can attempt to load \s-1DBI::DBD\s0 but if it is missing we exit with -success. As we exit successfully without creating a Makefile when -\&\s-1DBI::DBD\s0 is missing cpan testers will not report a failure. This may -seem at odds with \fI\s-1PREREQ_PM\s0\fR but \fI\s-1PREREQ_PM\s0\fR does not cause -\&\f(CW\*(C`WriteMakefile\*(C'\fR to fail (unless you also specify \s-1PREREQ_FATAL\s0 which -is strongly discouraged by MakeMaker) so \f(CW\*(C`WriteMakefile\*(C'\fR would -continue to call \f(CW\*(C`dbd_dbi_arch_dir\*(C'\fR and fail. -.PP -All drivers must use \f(CW\*(C`dbd_postamble()\*(C'\fR or risk running into problems. -.PP -Note the specification of \fI\s-1VERSION_FROM\s0\fR; the named file -(\fIDriver.pm\fR) will be scanned for the first line that looks like an -assignment to \fI\f(CI$VERSION\fI\fR, and the subsequent text will be used to -determine the version number. Note the commentary in -ExtUtils::MakeMaker on the subject of correctly formatted version -numbers. -.PP -If your driver depends upon external software (it usually will), you -will need to add code to ensure that your environment is workable -before the call to \f(CW\*(C`WriteMakefile()\*(C'\fR. If you need to check for the -existence of an external library and perhaps modify \fI\s-1INC\s0\fR to include -the paths to where the external library header files are located and -you cannot find the library or header files make sure you output a -message saying they cannot be found but \f(CW\*(C`exit 0\*(C'\fR (success) \fBbefore\fR -calling \f(CW\*(C`WriteMakefile\*(C'\fR or \s-1CPAN\s0 testers will fail your module if the -external library is not found. -.PP -A full-fledged \fIMakefile.PL\fR can be quite large (for example, the -files for \fBDBD::Oracle\fR and \fBDBD::Informix\fR are both over 1000 lines -long, and the Informix one uses \- and creates \- auxiliary modules -too). -.PP -See also ExtUtils::MakeMaker and ExtUtils::MM_Unix. Consider using -CPAN::MakeMaker in place of \fIExtUtils::MakeMaker\fR. -.SS "\s-1README\s0" -.IX Subsection "README" -The \s-1README\s0 file should describe what the driver is for, the -pre-requisites for the build process, the actual build process, how to -report errors, and who to report them to. -.PP -Users will find ways of breaking the driver build and test process -which you would never even have dreamed to be possible in your worst -nightmares. Therefore, you need to write this document defensively, -precisely and concisely. -.PP -As always, use the \fI\s-1README\s0\fR from one of the established drivers as a basis -for your own; the version in \fBDBD::Informix\fR is worth a look as it has -been quite successful in heading off problems. -.IP "\(bu" 4 -Note that users will have versions of Perl and \fB\s-1DBI\s0\fR that are both older -and newer than you expected, but this will seldom cause much trouble. -When it does, it will be because you are using features of \fB\s-1DBI\s0\fR that are -not supported in the version they are using. -.IP "\(bu" 4 -Note that users will have versions of the database software that are -both older and newer than you expected. You will save yourself time in -the long run if you can identify the range of versions which have been -tested and warn about versions which are not known to be \s-1OK.\s0 -.IP "\(bu" 4 -Note that many people trying to install your driver will not be experts -in the database software. -.IP "\(bu" 4 -Note that many people trying to install your driver will not be experts -in C or Perl. -.SS "\s-1MANIFEST\s0" -.IX Subsection "MANIFEST" -The \fI\s-1MANIFEST\s0\fR will be used by the Makefile's dist target to build the -distribution tar file that is uploaded to \s-1CPAN.\s0 It should list every -file that you want to include in your distribution, one per line. -.SS "lib/Bundle/DBD/Driver.pm" -.IX Subsection "lib/Bundle/DBD/Driver.pm" -The \s-1CPAN\s0 module provides an extremely powerful bundle mechanism that -allows you to specify pre-requisites for your driver. -.PP -The primary pre-requisite is \fBBundle::DBI\fR; you may want or need to add -some more. With the bundle set up correctly, the user can type: -.PP -.Vb 1 -\& perl \-MCPAN \-e \*(Aqinstall Bundle::DBD::Driver\*(Aq -.Ve -.PP -and Perl will download, compile, test and install all the Perl modules -needed to build your driver. -.PP -The prerequisite modules are listed in the \f(CW\*(C`CONTENTS\*(C'\fR section, with the -official name of the module followed by a dash and an informal name or -description. -.IP "\(bu" 4 -Listing \fBBundle::DBI\fR as the main pre-requisite simplifies life. -.IP "\(bu" 4 -Don't forget to list your driver. -.IP "\(bu" 4 -Note that unless the \s-1DBMS\s0 is itself a Perl module, you cannot list it as -a pre-requisite in this file. -.IP "\(bu" 4 -You should keep the version of the bundle the same as the version of -your driver. -.IP "\(bu" 4 -You should add configuration management, copyright, and licencing -information at the top. -.PP -A suitable skeleton for this file is shown below. -.PP -.Vb 1 -\& package Bundle::DBD::Driver; -\& -\& $VERSION = \*(Aq0.01\*(Aq; -\& -\& 1; -\& -\& _\|_END_\|_ -\& -\& =head1 NAME -\& -\& Bundle::DBD::Driver \- A bundle to install all DBD::Driver related modules -\& -\& =head1 SYNOPSIS -\& -\& C -\& -\& =head1 CONTENTS -\& -\& Bundle::DBI \- Bundle for DBI by TIMB (Tim Bunce) -\& -\& DBD::Driver \- DBD::Driver by YOU (Your Name) -\& -\& =head1 DESCRIPTION -\& -\& This bundle includes all the modules used by the Perl Database -\& Interface (DBI) driver for Driver (DBD::Driver), assuming the -\& use of DBI version 1.13 or later, created by Tim Bunce. -\& -\& If you\*(Aqve not previously used the CPAN module to install any -\& bundles, you will be interrogated during its setup phase. -\& But when you\*(Aqve done it once, it remembers what you told it. -\& You could start by running: -\& -\& C -\& -\& =head1 SEE ALSO -\& -\& Bundle::DBI -\& -\& =head1 AUTHOR -\& -\& Your Name EFE -\& -\& =head1 THANKS -\& -\& This bundle was created by ripping off Bundle::libnet created by -\& Graham Barr EFE, and radically simplified -\& with some information from Jochen Wiedmann EFE. -\& The template was then included in the DBI::DBD documentation by -\& Jonathan Leffler EFE. -\& -\& =cut -.Ve -.SS "lib/DBD/Driver/Summary.pm" -.IX Subsection "lib/DBD/Driver/Summary.pm" -There is no substitute for taking the summary file from a driver that -was documented in the Perl book (such as \fBDBD::Oracle\fR or \fBDBD::Informix\fR or -\&\fB\s-1DBD::ODBC\s0\fR, to name but three), and adapting it to describe the -facilities available via \fBDBD::Driver\fR when accessing the Driver database. -.SS "Pure Perl version of Driver.pm" -.IX Subsection "Pure Perl version of Driver.pm" -The \fIDriver.pm\fR file defines the Perl module \fBDBD::Driver\fR for your driver. -It will define a package \fBDBD::Driver\fR along with some version information, -some variable definitions, and a function \f(CW\*(C`driver()\*(C'\fR which will have a more -or less standard structure. -.PP -It will also define three sub-packages of \fBDBD::Driver\fR: -.IP "DBD::Driver::dr" 4 -.IX Item "DBD::Driver::dr" -with methods \f(CW\*(C`connect()\*(C'\fR, \f(CW\*(C`data_sources()\*(C'\fR and \f(CW\*(C`disconnect_all()\*(C'\fR; -.IP "DBD::Driver::db" 4 -.IX Item "DBD::Driver::db" -with methods such as \f(CW\*(C`prepare()\*(C'\fR; -.IP "DBD::Driver::st" 4 -.IX Item "DBD::Driver::st" -with methods such as \f(CW\*(C`execute()\*(C'\fR and \f(CW\*(C`fetch()\*(C'\fR. -.PP -The \fIDriver.pm\fR file will also contain the documentation specific to -\&\fBDBD::Driver\fR in the format used by perldoc. -.PP -In a pure Perl driver, the \fIDriver.pm\fR file is the core of the -implementation. You will need to provide all the key methods needed by \fB\s-1DBI\s0\fR. -.PP -Now let's take a closer look at an excerpt of \fIFile.pm\fR as an example. -We ignore things that are common to any module (even non-DBI modules) -or really specific to the \fBDBD::File\fR package. -.PP -\fIThe DBD::Driver package\fR -.IX Subsection "The DBD::Driver package" -.PP -The header -.IX Subsection "The header" -.PP -.Vb 1 -\& package DBD::File; -\& -\& use strict; -\& use vars qw($VERSION $drh); -\& -\& $VERSION = "1.23.00" # Version number of DBD::File -.Ve -.PP -This is where the version number of your driver is specified, and is -where \fIMakefile.PL\fR looks for this information. Please ensure that any -other modules added with your driver are also version stamped so that -\&\s-1CPAN\s0 does not get confused. -.PP -It is recommended that you use a two-part (1.23) or three-part (1.23.45) -version number. Also consider the \s-1CPAN\s0 system, which gets confused and -considers version 1.10 to precede version 1.9, so that using a raw \s-1CVS, -RCS\s0 or \s-1SCCS\s0 version number is probably not appropriate (despite being -very common). -.PP -For Subversion you could use: -.PP -.Vb 1 -\& $VERSION = "12.012346"; -.Ve -.PP -(use lots of leading zeros on the second portion so if you move the code to a -shared repository like svn.perl.org the much larger revision numbers won't -cause a problem, at least not for a few years). For \s-1RCS\s0 or \s-1CVS\s0 you can use: -.PP -.Vb 1 -\& $VERSION = "11.22"; -.Ve -.PP -which pads out the fractional part with leading zeros so all is well -(so long as you don't go past x.99) -.PP -.Vb 1 -\& $drh = undef; # holds driver handle once initialized -.Ve -.PP -This is where the driver handle will be stored, once created. -Note that you may assume there is only one handle for your driver. -.PP -The driver constructor -.IX Subsection "The driver constructor" -.PP -The \f(CW\*(C`driver()\*(C'\fR method is the driver handle constructor. Note that -the \f(CW\*(C`driver()\*(C'\fR method is in the \fBDBD::Driver\fR package, not in -one of the sub-packages \fBDBD::Driver::dr\fR, \fBDBD::Driver::db\fR, or -\&\fBDBD::Driver::db\fR. -.PP -.Vb 4 -\& sub driver -\& { -\& return $drh if $drh; # already created \- return same one -\& my ($class, $attr) = @_; -\& -\& $class .= "::dr"; -\& -\& DBD::Driver::db\->install_method(\*(Aqdrv_example_dbh_method\*(Aq); -\& DBD::Driver::st\->install_method(\*(Aqdrv_example_sth_method\*(Aq); -\& -\& # not a \*(Aqmy\*(Aq since we use it above to prevent multiple drivers -\& $drh = DBI::_new_drh($class, { -\& \*(AqName\*(Aq => \*(AqFile\*(Aq, -\& \*(AqVersion\*(Aq => $VERSION, -\& \*(AqAttribution\*(Aq => \*(AqDBD::File by Jochen Wiedmann\*(Aq, -\& }) -\& or return undef; -\& -\& return $drh; -\& } -.Ve -.PP -This is a reasonable example of how \fB\s-1DBI\s0\fR implements its handles. There -are three kinds: \fBdriver handles\fR (typically stored in \fI\f(CI$drh\fI\fR; from -now on called \fIdrh\fR or \fI\f(CI$drh\fI\fR), \fBdatabase handles\fR (from now on -called \fIdbh\fR or \fI\f(CI$dbh\fI\fR) and \fBstatement handles\fR (from now on called -\&\fIsth\fR or \fI\f(CI$sth\fI\fR). -.PP -The prototype of \f(CW\*(C`DBI::_new_drh()\*(C'\fR is -.PP -.Vb 1 -\& $drh = DBI::_new_drh($class, $public_attrs, $private_attrs); -.Ve -.PP -with the following arguments: -.ie n .IP "\fI\fI$class\fI\fR" 4 -.el .IP "\fI\f(CI$class\fI\fR" 4 -.IX Item "$class" -is typically the class for your driver, (for example, \*(L"DBD::File::dr\*(R"), -passed as the first argument to the \f(CW\*(C`driver()\*(C'\fR method. -.ie n .IP "\fI\fI$public_attrs\fI\fR" 4 -.el .IP "\fI\f(CI$public_attrs\fI\fR" 4 -.IX Item "$public_attrs" -is a hash ref to attributes like \fIName\fR, \fIVersion\fR, and \fIAttribution\fR. -These are processed and used by \fB\s-1DBI\s0\fR. You had better not make any -assumptions about them nor should you add private attributes here. -.ie n .IP "\fI\fI$private_attrs\fI\fR" 4 -.el .IP "\fI\f(CI$private_attrs\fI\fR" 4 -.IX Item "$private_attrs" -This is another (optional) hash ref with your private attributes. -\&\fB\s-1DBI\s0\fR will store them and otherwise leave them alone. -.PP -The \f(CW\*(C`DBI::_new_drh()\*(C'\fR method and the \f(CW\*(C`driver()\*(C'\fR method both return \f(CW\*(C`undef\*(C'\fR -for failure (in which case you must look at \fI\f(CI$DBI::err\fI\fR and \fI\f(CI$DBI::errstr\fI\fR -for the failure information, because you have no driver handle to use). -.PP -Using \fIinstall_method()\fR to expose driver-private methods -.IX Subsection "Using install_method() to expose driver-private methods" -.PP -.Vb 1 -\& DBD::Foo::db\->install_method($method_name, \e%attr); -.Ve -.PP -Installs the driver-private method named by \f(CW$method_name\fR into the -\&\s-1DBI\s0 method dispatcher so it can be called directly, avoiding the -need to use the \fIfunc()\fR method. -.PP -It is called as a static method on the driver class to which the -method belongs. The method name must begin with the corresponding -registered driver-private prefix. For example, for DBD::Oracle -\&\f(CW$method_name\fR must being with '\f(CW\*(C`ora_\*(C'\fR', and for DBD::AnyData it -must begin with '\f(CW\*(C`ad_\*(C'\fR'. -.PP -The \f(CW\*(C`\e%attr\*(C'\fR attributes can be used to provide fine control over how the \s-1DBI\s0 -dispatcher handles the dispatching of the method. However it's undocumented -at the moment. See the IMA_* #define's in \s-1DBI\s0.xs and the O=>0x000x values in -the initialization of \f(CW%DBI::DBI_methods\fR in \s-1DBI\s0.pm. (Volunteers to polish up -and document the interface are very welcome to get in touch via dbi\-dev@perl.org). -.PP -Methods installed using install_method default to the standard error -handling behaviour for \s-1DBI\s0 methods: clearing err and errstr before -calling the method, and checking for errors to trigger RaiseError -etc. on return. This differs from the default behaviour of \fIfunc()\fR. -.PP -Note for driver authors: The DBD::Foo::xx\->install_method call won't -work until the class-hierarchy has been setup. Normally the \s-1DBI\s0 -looks after that just after the driver is loaded. This means -\&\fIinstall_method()\fR can't be called at the time the driver is loaded -unless the class-hierarchy is set up first. The way to do that is -to call the \fIsetup_driver()\fR method: -.PP -.Vb 1 -\& DBI\->setup_driver(\*(AqDBD::Foo\*(Aq); -.Ve -.PP -before using \fIinstall_method()\fR. -.PP -The \s-1CLONE\s0 special subroutine -.IX Subsection "The CLONE special subroutine" -.PP -Also needed here, in the \fBDBD::Driver\fR package, is a \f(CW\*(C`CLONE()\*(C'\fR method -that will be called by perl when an interpreter is cloned. All your -\&\f(CW\*(C`CLONE()\*(C'\fR method needs to do, currently, is clear the cached \fI\f(CI$drh\fI\fR so -the new interpreter won't start using the cached \fI\f(CI$drh\fI\fR from the old -interpreter: -.PP -.Vb 3 -\& sub CLONE { -\& undef $drh; -\& } -.Ve -.PP -See -for details. -.PP -\fIThe DBD::Driver::dr package\fR -.IX Subsection "The DBD::Driver::dr package" -.PP -The next lines of code look as follows: -.PP -.Vb 1 -\& package DBD::Driver::dr; # ====== DRIVER ====== -\& -\& $DBD::Driver::dr::imp_data_size = 0; -.Ve -.PP -Note that no \fI\f(CI@ISA\fI\fR is needed here, or for the other \fBDBD::Driver::*\fR -classes, because the \fB\s-1DBI\s0\fR takes care of that for you when the driver is -loaded. -.PP -.Vb 2 -\& *FIX ME* Explain what the imp_data_size is, so that implementors aren\*(Aqt -\& practicing cargo\-cult programming. -.Ve -.PP -The database handle constructor -.IX Subsection "The database handle constructor" -.PP -The database handle constructor is the driver's (hence the changed -namespace) \f(CW\*(C`connect()\*(C'\fR method: -.PP -.Vb 3 -\& sub connect -\& { -\& my ($drh, $dr_dsn, $user, $auth, $attr) = @_; -\& -\& # Some database specific verifications, default settings -\& # and the like can go here. This should only include -\& # syntax checks or similar stuff where it\*(Aqs legal to -\& # \*(Aqdie\*(Aq in case of errors. -\& # For example, many database packages requires specific -\& # environment variables to be set; this could be where you -\& # validate that they are set, or default them if they are not set. -\& -\& my $driver_prefix = "drv_"; # the assigned prefix for this driver -\& -\& # Process attributes from the DSN; we assume ODBC syntax -\& # here, that is, the DSN looks like var1=val1;...;varN=valN -\& foreach my $var ( split /;/, $dr_dsn ) { -\& my ($attr_name, $attr_value) = split \*(Aq=\*(Aq, $var, 2; -\& return $drh\->set_err($DBI::stderr, "Can\*(Aqt parse DSN part \*(Aq$var\*(Aq") -\& unless defined $attr_value; -\& -\& # add driver prefix to attribute name if it doesn\*(Aqt have it already -\& $attr_name = $driver_prefix.$attr_name -\& unless $attr_name =~ /^$driver_prefix/o; -\& -\& # Store attribute into %$attr, replacing any existing value. -\& # The DBI will STORE() these into $dbh after we\*(Aqve connected -\& $attr\->{$attr_name} = $attr_value; -\& } -\& -\& # Get the attributes we\*(Aqll use to connect. -\& # We use delete here because these no need to STORE them -\& my $db = delete $attr\->{drv_database} || delete $attr\->{drv_db} -\& or return $drh\->set_err($DBI::stderr, "No database name given in DSN \*(Aq$dr_dsn\*(Aq"); -\& my $host = delete $attr\->{drv_host} || \*(Aqlocalhost\*(Aq; -\& my $port = delete $attr\->{drv_port} || 123456; -\& -\& # Assume you can attach to your database via drv_connect: -\& my $connection = drv_connect($db, $host, $port, $user, $auth) -\& or return $drh\->set_err($DBI::stderr, "Can\*(Aqt connect to $dr_dsn: ..."); -\& -\& # create a \*(Aqblank\*(Aq dbh (call superclass constructor) -\& my ($outer, $dbh) = DBI::_new_dbh($drh, { Name => $dr_dsn }); -\& -\& $dbh\->STORE(\*(AqActive\*(Aq, 1 ); -\& $dbh\->{drv_connection} = $connection; -\& -\& return $outer; -\& } -.Ve -.PP -This is mostly the same as in the \fIdriver handle constructor\fR above. -The arguments are described in \s-1DBI\s0. -.PP -The constructor \f(CW\*(C`DBI::_new_dbh()\*(C'\fR is called, returning a database handle. -The constructor's prototype is: -.PP -.Vb 1 -\& ($outer, $inner) = DBI::_new_dbh($drh, $public_attr, $private_attr); -.Ve -.PP -with similar arguments to those in the \fIdriver handle constructor\fR, -except that the \fI\f(CI$class\fI\fR is replaced by \fI\f(CI$drh\fI\fR. The \fIName\fR attribute -is a standard \fB\s-1DBI\s0\fR attribute (see \*(L"Database Handle Attributes\*(R" in \s-1DBI\s0). -.PP -In scalar context, only the outer handle is returned. -.PP -Note the use of the \f(CW\*(C`STORE()\*(C'\fR method for setting the \fIdbh\fR attributes. -That's because within the driver code, the handle object you have is -the 'inner' handle of a tied hash, not the outer handle that the -users of your driver have. -.PP -Because you have the inner handle, tie magic doesn't get invoked -when you get or set values in the hash. This is often very handy for -speed when you want to get or set simple non-special driver-specific -attributes. -.PP -However, some attribute values, such as those handled by the \fB\s-1DBI\s0\fR like -\&\fIPrintError\fR, don't actually exist in the hash and must be read via -\&\f(CW\*(C`$h\->FETCH($attrib)\*(C'\fR and set via \f(CW\*(C`$h\->STORE($attrib, $value)\*(C'\fR. -If in any doubt, use these methods. -.PP -The \fIdata_sources()\fR method -.IX Subsection "The data_sources() method" -.PP -The \f(CW\*(C`data_sources()\*(C'\fR method must populate and return a list of valid data -sources, prefixed with the "\fIdbi:Driver\fR" incantation that allows them to -be used in the first argument of the \f(CW\*(C`DBI\->connect()\*(C'\fR method. -An example of this might be scanning the \fI\f(CI$HOME\fI/.odbcini\fR file on Unix -for \s-1ODBC\s0 data sources (DSNs). -.PP -As a trivial example, consider a fixed list of data sources: -.PP -.Vb 11 -\& sub data_sources -\& { -\& my($drh, $attr) = @_; -\& my(@list) = (); -\& # You need more sophisticated code than this to set @list... -\& push @list, "dbi:Driver:abc"; -\& push @list, "dbi:Driver:def"; -\& push @list, "dbi:Driver:ghi"; -\& # End of code to set @list -\& return @list; -\& } -.Ve -.PP -The \fIdisconnect_all()\fR method -.IX Subsection "The disconnect_all() method" -.PP -If you need to release any resources when the driver is unloaded, you -can provide a disconnect_all method. -.PP -Other driver handle methods -.IX Subsection "Other driver handle methods" -.PP -If you need any other driver handle methods, they can follow here. -.PP -Error handling -.IX Subsection "Error handling" -.PP -It is quite likely that something fails in the connect method. -With \fBDBD::File\fR for example, you might catch an error when setting the -current directory to something not existent by using the -(driver-specific) \fIf_dir\fR attribute. -.PP -To report an error, you use the \f(CW\*(C`set_err()\*(C'\fR method: -.PP -.Vb 1 -\& $h\->set_err($err, $errmsg, $state); -.Ve -.PP -This will ensure that the error is recorded correctly and that -\&\fIRaiseError\fR and \fIPrintError\fR etc are handled correctly. -.PP -Typically you'll always use the method instance, aka your method's first -argument. -.PP -As \f(CW\*(C`set_err()\*(C'\fR always returns \f(CW\*(C`undef\*(C'\fR your error handling code can -usually be simplified to something like this: -.PP -.Vb 1 -\& return $h\->set_err($err, $errmsg, $state) if ...; -.Ve -.PP -\fIThe DBD::Driver::db package\fR -.IX Subsection "The DBD::Driver::db package" -.PP -.Vb 1 -\& package DBD::Driver::db; # ====== DATABASE ====== -\& -\& $DBD::Driver::db::imp_data_size = 0; -.Ve -.PP -The statement handle constructor -.IX Subsection "The statement handle constructor" -.PP -There's nothing much new in the statement handle constructor, which -is the \f(CW\*(C`prepare()\*(C'\fR method: -.PP -.Vb 3 -\& sub prepare -\& { -\& my ($dbh, $statement, @attribs) = @_; -\& -\& # create a \*(Aqblank\*(Aq sth -\& my ($outer, $sth) = DBI::_new_sth($dbh, { Statement => $statement }); -\& -\& $sth\->STORE(\*(AqNUM_OF_PARAMS\*(Aq, ($statement =~ tr/?//)); -\& -\& $sth\->{drv_params} = []; -\& -\& return $outer; -\& } -.Ve -.PP -This is still the same \*(-- check the arguments and call the super class -constructor \f(CW\*(C`DBI::_new_sth()\*(C'\fR. Again, in scalar context, only the outer -handle is returned. The \fIStatement\fR attribute should be cached as -shown. -.PP -Note the prefix \fIdrv_\fR in the attribute names: it is required that -all your private attributes use a lowercase prefix unique to your driver. -As mentioned earlier in this document, the \fB\s-1DBI\s0\fR contains a registry of -known driver prefixes and may one day warn about unknown attributes -that don't have a registered prefix. -.PP -Note that we parse the statement here in order to set the attribute -\&\fI\s-1NUM_OF_PARAMS\s0\fR. The technique illustrated is not very reliable; it can -be confused by question marks appearing in quoted strings, delimited -identifiers or in \s-1SQL\s0 comments that are part of the \s-1SQL\s0 statement. We -could set \fI\s-1NUM_OF_PARAMS\s0\fR in the \f(CW\*(C`execute()\*(C'\fR method instead because -the \fB\s-1DBI\s0\fR specification explicitly allows a driver to defer this, but then -the user could not call \f(CW\*(C`bind_param()\*(C'\fR. -.PP -Transaction handling -.IX Subsection "Transaction handling" -.PP -Pure Perl drivers will rarely support transactions. Thus your \f(CW\*(C`commit()\*(C'\fR -and \f(CW\*(C`rollback()\*(C'\fR methods will typically be quite simple: -.PP -.Vb 8 -\& sub commit -\& { -\& my ($dbh) = @_; -\& if ($dbh\->FETCH(\*(AqWarn\*(Aq)) { -\& warn("Commit ineffective while AutoCommit is on"); -\& } -\& 0; -\& } -\& -\& sub rollback { -\& my ($dbh) = @_; -\& if ($dbh\->FETCH(\*(AqWarn\*(Aq)) { -\& warn("Rollback ineffective while AutoCommit is on"); -\& } -\& 0; -\& } -.Ve -.PP -Or even simpler, just use the default methods provided by the \fB\s-1DBI\s0\fR that -do nothing except return \f(CW\*(C`undef\*(C'\fR. -.PP -The \fB\s-1DBI\s0\fR's default \f(CW\*(C`begin_work()\*(C'\fR method can be used by inheritance. -.PP -The \s-1\fISTORE\s0()\fR and \s-1\fIFETCH\s0()\fR methods -.IX Subsection "The STORE() and FETCH() methods" -.PP -These methods (that we have already used, see above) are called for -you, whenever the user does a: -.PP -.Vb 1 -\& $dbh\->{$attr} = $val; -.Ve -.PP -or, respectively, -.PP -.Vb 1 -\& $val = $dbh\->{$attr}; -.Ve -.PP -See perltie for details on tied hash refs to understand why these -methods are required. -.PP -The \fB\s-1DBI\s0\fR will handle most attributes for you, in particular attributes -like \fIRaiseError\fR or \fIPrintError\fR. All you have to do is handle your -driver's private attributes and any attributes, like \fIAutoCommit\fR and -\&\fIChopBlanks\fR, that the \fB\s-1DBI\s0\fR can't handle for you. -.PP -A good example might look like this: -.PP -.Vb 10 -\& sub STORE -\& { -\& my ($dbh, $attr, $val) = @_; -\& if ($attr eq \*(AqAutoCommit\*(Aq) { -\& # AutoCommit is currently the only standard attribute we have -\& # to consider. -\& if (!$val) { die "Can\*(Aqt disable AutoCommit"; } -\& return 1; -\& } -\& if ($attr =~ m/^drv_/) { -\& # Handle only our private attributes here -\& # Note that we could trigger arbitrary actions. -\& # Ideally we should warn about unknown attributes. -\& $dbh\->{$attr} = $val; # Yes, we are allowed to do this, -\& return 1; # but only for our private attributes -\& } -\& # Else pass up to DBI to handle for us -\& $dbh\->SUPER::STORE($attr, $val); -\& } -\& -\& sub FETCH -\& { -\& my ($dbh, $attr) = @_; -\& if ($attr eq \*(AqAutoCommit\*(Aq) { return 1; } -\& if ($attr =~ m/^drv_/) { -\& # Handle only our private attributes here -\& # Note that we could trigger arbitrary actions. -\& return $dbh\->{$attr}; # Yes, we are allowed to do this, -\& # but only for our private attributes -\& } -\& # Else pass up to DBI to handle -\& $dbh\->SUPER::FETCH($attr); -\& } -.Ve -.PP -The \fB\s-1DBI\s0\fR will actually store and fetch driver-specific attributes (with all -lowercase names) without warning or error, so there's actually no need to -implement driver-specific any code in your \f(CW\*(C`FETCH()\*(C'\fR and \f(CW\*(C`STORE()\*(C'\fR -methods unless you need extra logic/checks, beyond getting or setting -the value. -.PP -Unless your driver documentation indicates otherwise, the return value of -the \f(CW\*(C`STORE()\*(C'\fR method is unspecified and the caller shouldn't use that value. -.PP -Other database handle methods -.IX Subsection "Other database handle methods" -.PP -As with the driver package, other database handle methods may follow here. -In particular you should consider a (possibly empty) \f(CW\*(C`disconnect()\*(C'\fR -method and possibly a \f(CW\*(C`quote()\*(C'\fR method if \fB\s-1DBI\s0\fR's default isn't correct for -you. You may also need the \f(CW\*(C`type_info_all()\*(C'\fR and \f(CW\*(C`get_info()\*(C'\fR methods, -as described elsewhere in this document. -.PP -Where reasonable use \f(CW\*(C`$h\->SUPER::foo()\*(C'\fR to call the \fB\s-1DBI\s0\fR's method in -some or all cases and just wrap your custom behavior around that. -.PP -If you want to use private trace flags you'll probably want to be -able to set them by name. To do that you'll need to define a -\&\f(CW\*(C`parse_trace_flag()\*(C'\fR method (note that's \*(L"parse_trace_flag\*(R", singular, -not \*(L"parse_trace_flags\*(R", plural). -.PP -.Vb 9 -\& sub parse_trace_flag { -\& my ($h, $name) = @_; -\& return 0x01000000 if $name eq \*(Aqfoo\*(Aq; -\& return 0x02000000 if $name eq \*(Aqbar\*(Aq; -\& return 0x04000000 if $name eq \*(Aqbaz\*(Aq; -\& return 0x08000000 if $name eq \*(Aqboo\*(Aq; -\& return 0x10000000 if $name eq \*(Aqbop\*(Aq; -\& return $h\->SUPER::parse_trace_flag($name); -\& } -.Ve -.PP -All private flag names must be lowercase, and all private flags -must be in the top 8 of the 32 bits. -.PP -\fIThe DBD::Driver::st package\fR -.IX Subsection "The DBD::Driver::st package" -.PP -This package follows the same pattern the others do: -.PP -.Vb 1 -\& package DBD::Driver::st; -\& -\& $DBD::Driver::st::imp_data_size = 0; -.Ve -.PP -The \fIexecute()\fR and \fIbind_param()\fR methods -.IX Subsection "The execute() and bind_param() methods" -.PP -This is perhaps the most difficult method because we have to consider -parameter bindings here. In addition to that, there are a number of -statement attributes which must be set for inherited \fB\s-1DBI\s0\fR methods to -function correctly (see \*(L"Statement attributes\*(R" below). -.PP -We present a simplified implementation by using the \fIdrv_params\fR -attribute from above: -.PP -.Vb 12 -\& sub bind_param -\& { -\& my ($sth, $pNum, $val, $attr) = @_; -\& my $type = (ref $attr) ? $attr\->{TYPE} : $attr; -\& if ($type) { -\& my $dbh = $sth\->{Database}; -\& $val = $dbh\->quote($sth, $type); -\& } -\& my $params = $sth\->{drv_params}; -\& $params\->[$pNum\-1] = $val; -\& 1; -\& } -\& -\& sub execute -\& { -\& my ($sth, @bind_values) = @_; -\& -\& # start of by finishing any previous execution if still active -\& $sth\->finish if $sth\->FETCH(\*(AqActive\*(Aq); -\& -\& my $params = (@bind_values) ? -\& \e@bind_values : $sth\->{drv_params}; -\& my $numParam = $sth\->FETCH(\*(AqNUM_OF_PARAMS\*(Aq); -\& return $sth\->set_err($DBI::stderr, "Wrong number of parameters") -\& if @$params != $numParam; -\& my $statement = $sth\->{\*(AqStatement\*(Aq}; -\& for (my $i = 0; $i < $numParam; $i++) { -\& $statement =~ s/?/$params\->[$i]/; # XXX doesn\*(Aqt deal with quoting etc! -\& } -\& # Do anything ... we assume that an array ref of rows is -\& # created and store it: -\& $sth\->{\*(Aqdrv_data\*(Aq} = $data; -\& $sth\->{\*(Aqdrv_rows\*(Aq} = @$data; # number of rows -\& $sth\->STORE(\*(AqNUM_OF_FIELDS\*(Aq) = $numFields; -\& $sth\->{Active} = 1; -\& @$data || \*(Aq0E0\*(Aq; -\& } -.Ve -.PP -There are a number of things you should note here. -.PP -We initialize the \fI\s-1NUM_OF_FIELDS\s0\fR and \fIActive\fR attributes here, -because they are essential for \f(CW\*(C`bind_columns()\*(C'\fR to work. -.PP -We use attribute \f(CW\*(C`$sth\->{Statement}\*(C'\fR which we created -within \f(CW\*(C`prepare()\*(C'\fR. The attribute \f(CW\*(C`$sth\->{Database}\*(C'\fR, which is -nothing else than the \fIdbh\fR, was automatically created by \fB\s-1DBI\s0\fR. -.PP -Finally, note that (as specified in the \fB\s-1DBI\s0\fR specification) we return the -string \f(CW\*(Aq0E0\*(Aq\fR instead of the number 0, so that the result tests true but -equal to zero. -.PP -.Vb 1 -\& $sth\->execute() or die $sth\->errstr; -.Ve -.PP -The \fIexecute_array()\fR, \fIexecute_for_fetch()\fR and \fIbind_param_array()\fR methods -.IX Subsection "The execute_array(), execute_for_fetch() and bind_param_array() methods" -.PP -In general, \s-1DBD\s0's only need to implement \f(CW\*(C`execute_for_fetch()\*(C'\fR and -\&\f(CW\*(C`bind_param_array\*(C'\fR. \s-1DBI\s0's default \f(CW\*(C`execute_array()\*(C'\fR will invoke the -\&\s-1DBD\s0's \f(CW\*(C`execute_for_fetch()\*(C'\fR as needed. -.PP -The following sequence describes the interaction between -\&\s-1DBI \s0\f(CW\*(C`execute_array\*(C'\fR and a \s-1DBD\s0's \f(CW\*(C`execute_for_fetch\*(C'\fR: -.IP "1." 4 -App calls \f(CW\*(C`$sth\->execute_array(\e%attrs, @array_of_arrays)\*(C'\fR -.IP "2." 4 -If \f(CW@array_of_arrays\fR was specified, \s-1DBI\s0 processes \f(CW@array_of_arrays\fR by calling -\&\s-1DBD\s0's \f(CW\*(C`bind_param_array()\*(C'\fR. Alternately, App may have directly called -\&\f(CW\*(C`bind_param_array()\*(C'\fR -.IP "3." 4 -\&\s-1DBD\s0 validates and binds each array -.IP "4." 4 -\&\s-1DBI\s0 retrieves the validated param arrays from \s-1DBD\s0's ParamArray attribute -.IP "5." 4 -\&\s-1DBI\s0 calls \s-1DBD\s0's \f(CW\*(C`execute_for_fetch($fetch_tuple_sub, \e@tuple_status)\*(C'\fR, -where \f(CW&$fetch_tuple_sub\fR is a closure to iterate over the -returned ParamArray values, and \f(CW\*(C`\e@tuple_status\*(C'\fR is an array to receive -the disposition status of each tuple. -.IP "6." 4 -\&\s-1DBD\s0 iteratively calls \f(CW&$fetch_tuple_sub\fR to retrieve parameter tuples -to be added to its bulk database operation/request. -.IP "7." 4 -when \s-1DBD\s0 reaches the limit of tuples it can handle in a single database -operation/request, or the \f(CW&$fetch_tuple_sub\fR indicates no more -tuples by returning undef, the \s-1DBD\s0 executes the bulk operation, and -reports the disposition of each tuple in \e@tuple_status. -.IP "8." 4 -\&\s-1DBD\s0 repeats steps 6 and 7 until all tuples are processed. -.PP -E.g., here's the essence of DBD::Oracle's execute_for_fetch: -.PP -.Vb 10 -\& while (1) { -\& my @tuple_batch; -\& for (my $i = 0; $i < $batch_size; $i++) { -\& push @tuple_batch, [ @{$fetch_tuple_sub\->() || last} ]; -\& } -\& last unless @tuple_batch; -\& my $res = ora_execute_array($sth, \e@tuple_batch, -\& scalar(@tuple_batch), $tuple_batch_status); -\& push @$tuple_status, @$tuple_batch_status; -\& } -.Ve -.PP -Note that \s-1DBI\s0's default \fIexecute_array()\fR/\fIexecute_for_fetch()\fR implementation -requires the use of positional (i.e., '?') placeholders. Drivers -which \fBrequire\fR named placeholders must either emulate positional -placeholders (e.g., see DBD::Oracle), or must implement their own -\&\fIexecute_array()\fR/\fIexecute_for_fetch()\fR methods to properly sequence bound -parameter arrays. -.PP -Fetching data -.IX Subsection "Fetching data" -.PP -Only one method needs to be written for fetching data, \f(CW\*(C`fetchrow_arrayref()\*(C'\fR. -The other methods, \f(CW\*(C`fetchrow_array()\*(C'\fR, \f(CW\*(C`fetchall_arrayref()\*(C'\fR, etc, as well -as the database handle's \f(CW\*(C`select*\*(C'\fR methods are part of \fB\s-1DBI\s0\fR, and call -\&\f(CW\*(C`fetchrow_arrayref()\*(C'\fR as necessary. -.PP -.Vb 10 -\& sub fetchrow_arrayref -\& { -\& my ($sth) = @_; -\& my $data = $sth\->{drv_data}; -\& my $row = shift @$data; -\& if (!$row) { -\& $sth\->STORE(Active => 0); # mark as no longer active -\& return undef; -\& } -\& if ($sth\->FETCH(\*(AqChopBlanks\*(Aq)) { -\& map { $_ =~ s/\es+$//; } @$row; -\& } -\& return $sth\->_set_fbav($row); -\& } -\& *fetch = \e&fetchrow_arrayref; # required alias for fetchrow_arrayref -.Ve -.PP -Note the use of the method \f(CW\*(C`_set_fbav()\*(C'\fR \*(-- this is required so that -\&\f(CW\*(C`bind_col()\*(C'\fR and \f(CW\*(C`bind_columns()\*(C'\fR work. -.PP -If an error occurs which leaves the \fI\f(CI$sth\fI\fR in a state where remaining rows -can't be fetched then \fIActive\fR should be turned off before the method returns. -.PP -The \f(CW\*(C`rows()\*(C'\fR method for this driver can be implemented like this: -.PP -.Vb 1 -\& sub rows { shift\->{drv_rows} } -.Ve -.PP -because it knows in advance how many rows it has fetched. -Alternatively you could delete that method and so fallback -to the \fB\s-1DBI\s0\fR's own method which does the right thing based -on the number of calls to \f(CW\*(C`_set_fbav()\*(C'\fR. -.PP -The more_results method -.IX Subsection "The more_results method" -.PP -If your driver doesn't support multiple result sets, then don't even implement this method. -.PP -Otherwise, this method needs to get the statement handle ready to fetch results -from the next result set, if there is one. Typically you'd start with: -.PP -.Vb 1 -\& $sth\->finish; -.Ve -.PP -then you should delete all the attributes from the attribute cache that may no -longer be relevant for the new result set: -.PP -.Vb 2 -\& delete $sth\->{$_} -\& for qw(NAME TYPE PRECISION SCALE ...); -.Ve -.PP -for drivers written in C use: -.PP -.Vb 6 -\& hv_delete((HV*)SvRV(sth), "NAME", 4, G_DISCARD); -\& hv_delete((HV*)SvRV(sth), "NULLABLE", 8, G_DISCARD); -\& hv_delete((HV*)SvRV(sth), "NUM_OF_FIELDS", 13, G_DISCARD); -\& hv_delete((HV*)SvRV(sth), "PRECISION", 9, G_DISCARD); -\& hv_delete((HV*)SvRV(sth), "SCALE", 5, G_DISCARD); -\& hv_delete((HV*)SvRV(sth), "TYPE", 4, G_DISCARD); -.Ve -.PP -Don't forget to also delete, or update, any driver-private attributes that may -not be correct for the next resultset. -.PP -The \s-1NUM_OF_FIELDS\s0 attribute is a special case. It should be set using \s-1STORE:\s0 -.PP -.Vb 2 -\& $sth\->STORE(NUM_OF_FIELDS => 0); /* for DBI <= 1.53 */ -\& $sth\->STORE(NUM_OF_FIELDS => $new_value); -.Ve -.PP -for drivers written in C use this incantation: -.PP -.Vb 5 -\& /* Adjust NUM_OF_FIELDS \- which also adjusts the row buffer size */ -\& DBIc_NUM_FIELDS(imp_sth) = 0; /* for DBI <= 1.53 */ -\& DBIc_STATE(imp_xxh)\->set_attr_k(sth, sv_2mortal(newSVpvn("NUM_OF_FIELDS",13)), 0, -\& sv_2mortal(newSViv(mysql_num_fields(imp_sth\->result))) -\& ); -.Ve -.PP -For \s-1DBI\s0 versions prior to 1.54 you'll also need to explicitly adjust the -number of elements in the row buffer array (\f(CW\*(C`DBIc_FIELDS_AV(imp_sth)\*(C'\fR) -to match the new result set. Fill any new values with \fInewSV\fR\|(0) not &sv_undef. -Alternatively you could free DBIc_FIELDS_AV(imp_sth) and set it to null, -but that would mean \fIbind_columns()\fR wouldn't work across result sets. -.PP -Statement attributes -.IX Subsection "Statement attributes" -.PP -The main difference between \fIdbh\fR and \fIsth\fR attributes is, that you -should implement a lot of attributes here that are required by -the \fB\s-1DBI\s0\fR, such as \fI\s-1NAME\s0\fR, \fI\s-1NULLABLE\s0\fR, \fI\s-1TYPE\s0\fR, etc. See -\&\*(L"Statement Handle Attributes\*(R" in \s-1DBI\s0 for a complete list. -.PP -Pay attention to attributes which are marked as read only, such as -\&\fI\s-1NUM_OF_PARAMS\s0\fR. These attributes can only be set the first time -a statement is executed. If a statement is prepared, then executed -multiple times, warnings may be generated. -.PP -You can protect against these warnings, and prevent the recalculation -of attributes which might be expensive to calculate (such as the -\&\fI\s-1NAME\s0\fR and \fINAME_*\fR attributes): -.PP -.Vb 3 -\& my $storedNumParams = $sth\->FETCH(\*(AqNUM_OF_PARAMS\*(Aq); -\& if (!defined $storedNumParams or $storedNumFields < 0) { -\& $sth\->STORE(\*(AqNUM_OF_PARAMS\*(Aq) = $numParams; -\& -\& # Set other useful attributes that only need to be set once -\& # for a statement, like $sth\->{NAME} and $sth\->{TYPE} -\& } -.Ve -.PP -One particularly important attribute to set correctly (mentioned in -\&\*(L"\s-1ATTRIBUTES COMMON TO ALL HANDLES\*(R"\s0 in \s-1DBI\s0 is \fIActive\fR. Many \fB\s-1DBI\s0\fR methods, -including \f(CW\*(C`bind_columns()\*(C'\fR, depend on this attribute. -.PP -Besides that the \f(CW\*(C`STORE()\*(C'\fR and \f(CW\*(C`FETCH()\*(C'\fR methods are mainly the same -as above for \fIdbh\fR's. -.PP -Other statement methods -.IX Subsection "Other statement methods" -.PP -A trivial \f(CW\*(C`finish()\*(C'\fR method to discard stored data, reset any attributes -(such as \fIActive\fR) and do \f(CW\*(C`$sth\->SUPER::finish()\*(C'\fR. -.PP -If you've defined a \f(CW\*(C`parse_trace_flag()\*(C'\fR method in \fB::db\fR you'll also want -it in \fB::st\fR, so just alias it in: -.PP -.Vb 1 -\& *parse_trace_flag = \e&DBD::foo:db::parse_trace_flag; -.Ve -.PP -And perhaps some other methods that are not part of the \fB\s-1DBI\s0\fR -specification, in particular to make metadata available. -Remember that they must have names that begin with your drivers -registered prefix so they can be installed using \f(CW\*(C`install_method()\*(C'\fR. -.PP -If \f(CW\*(C`DESTROY()\*(C'\fR is called on a statement handle that's still active -(\f(CW\*(C`$sth\->{Active}\*(C'\fR is true) then it should effectively call \f(CW\*(C`finish()\*(C'\fR. -.PP -.Vb 4 -\& sub DESTROY { -\& my $sth = shift; -\& $sth\->finish if $sth\->FETCH(\*(AqActive\*(Aq); -\& } -.Ve -.SS "Tests" -.IX Subsection "Tests" -The test process should conform as closely as possibly to the Perl -standard test harness. -.PP -In particular, most (all) of the tests should be run in the \fIt\fR sub-directory, -and should simply produce an \f(CW\*(C`ok\*(C'\fR when run under \f(CW\*(C`make test\*(C'\fR. -For details on how this is done, see the Camel book and the section in -Chapter 7, \*(L"The Standard Perl Library\*(R" on Test::Harness. -.PP -The tests may need to adapt to the type of database which is being used -for testing, and to the privileges of the user testing the driver. For -example, the \fBDBD::Informix\fR test code has to adapt in a number of -places to the type of database to which it is connected as different -Informix databases have different capabilities: some of the tests are -for databases without transaction logs; others are for databases with a -transaction log; some versions of the server have support for blobs, or -stored procedures, or user-defined data types, and others do not. -.PP -When a complete file of tests must be skipped, you can provide a reason -in a pseudo-comment: -.PP -.Vb 5 -\& if ($no_transactions_available) -\& { -\& print "1..0 # Skip: No transactions available\en"; -\& exit 0; -\& } -.Ve -.PP -Consider downloading the \fBDBD::Informix\fR code and look at the code in -\&\fIDBD/Informix/TestHarness.pm\fR which is used throughout the -\&\fBDBD::Informix\fR tests in the \fIt\fR sub-directory. -.SH "CREATING A C/XS DRIVER" -.IX Header "CREATING A C/XS DRIVER" -Please also see the section under \*(L"\s-1CREATING A PURE PERL DRIVER\*(R"\s0 -regarding the creation of the \fIMakefile.PL\fR. -.PP -Creating a new C/XS driver from scratch will always be a daunting task. -You can and should greatly simplify your task by taking a good -reference driver implementation and modifying that to match the -database product for which you are writing a driver. -.PP -The de facto reference driver has been the one for \fBDBD::Oracle\fR written -by Tim Bunce, who is also the author of the \fB\s-1DBI\s0\fR package. The \fBDBD::Oracle\fR -module is a good example of a driver implemented around a C\-level \s-1API.\s0 -.PP -Nowadays it it seems better to base on \fB\s-1DBD::ODBC\s0\fR, another driver -maintained by Tim and Jeff Urlwin, because it offers a lot of metadata -and seems to become the guideline for the future development. (Also as -\&\fBDBD::Oracle\fR digs deeper into the Oracle 8 \s-1OCI\s0 interface it'll get even -more hairy than it is now.) -.PP -The \fBDBD::Informix\fR driver is one driver implemented using embedded \s-1SQL\s0 -instead of a function-based \s-1API. -\&\s0\fBDBD::Ingres\fR may also be worth a look. -.SS "C/XS version of Driver.pm" -.IX Subsection "C/XS version of Driver.pm" -A lot of the code in the \fIDriver.pm\fR file is very similar to the code for pure Perl modules -\&\- see above. However, -there are also some subtle (and not so subtle) differences, including: -.IP "\(bu" 8 -The variables \fI\f(CI$DBD::Driver::\fI{dr|db|st}::imp_data_size\fR are not defined -here, but in the \s-1XS\s0 code, because they declare the size of certain -C structures. -.IP "\(bu" 8 -Some methods are typically moved to the \s-1XS\s0 code, in particular -\&\f(CW\*(C`prepare()\*(C'\fR, \f(CW\*(C`execute()\*(C'\fR, \f(CW\*(C`disconnect()\*(C'\fR, \f(CW\*(C`disconnect_all()\*(C'\fR and the -\&\f(CW\*(C`STORE()\*(C'\fR and \f(CW\*(C`FETCH()\*(C'\fR methods. -.IP "\(bu" 8 -Other methods are still part of \fIDriver.pm\fR, but have callbacks to -the \s-1XS\s0 code. -.IP "\(bu" 8 -If the driver-specific parts of the \fIimp_drh_t\fR structure need to be -formally initialized (which does not seem to be a common requirement), -then you need to add a call to an appropriate \s-1XS\s0 function in the driver -method of \f(CW\*(C`DBD::Driver::driver()\*(C'\fR, and you define the corresponding function -in \fIDriver.xs\fR, and you define the C code in \fIdbdimp.c\fR and the prototype in -\&\fIdbdimp.h\fR. -.Sp -For example, \fBDBD::Informix\fR has such a requirement, and adds the -following call after the call to \f(CW\*(C`_new_drh()\*(C'\fR in \fIInformix.pm\fR: -.Sp -.Vb 1 -\& DBD::Informix::dr::driver_init($drh); -.Ve -.Sp -and the following code in \fIInformix.xs\fR: -.Sp -.Vb 6 -\& # Initialize the DBD::Informix driver data structure -\& void -\& driver_init(drh) -\& SV *drh -\& CODE: -\& ST(0) = dbd_ix_dr_driver_init(drh) ? &sv_yes : &sv_no; -.Ve -.Sp -and the code in \fIdbdimp.h\fR declares: -.Sp -.Vb 1 -\& extern int dbd_ix_dr_driver_init(SV *drh); -.Ve -.Sp -and the code in \fIdbdimp.ec\fR (equivalent to \fIdbdimp.c\fR) defines: -.Sp -.Vb 11 -\& /* Formally initialize the DBD::Informix driver structure */ -\& int -\& dbd_ix_dr_driver(SV *drh) -\& { -\& D_imp_drh(drh); -\& imp_drh\->n_connections = 0; /* No active connections */ -\& imp_drh\->current_connection = 0; /* No current connection */ -\& imp_drh\->multipleconnections = (ESQLC_VERSION >= 600) ? True : False; -\& dbd_ix_link_newhead(&imp_drh\->head); /* Empty linked list of connections */ -\& return 1; -\& } -.Ve -.Sp -\&\fBDBD::Oracle\fR has a similar requirement but gets around it by checking -whether the private data part of the driver handle is all zeroed out, -rather than add extra functions. -.PP -Now let's take a closer look at an excerpt from \fIOracle.pm\fR (revised -heavily to remove idiosyncrasies) as an example, ignoring things that -were already discussed for pure Perl drivers. -.PP -\fIThe connect method\fR -.IX Subsection "The connect method" -.PP -The connect method is the database handle constructor. -You could write either of two versions of this method: either one which -takes connection attributes (new code) and one which ignores them (old -code only). -.PP -If you ignore the connection attributes, then you omit all mention of -the \fI\f(CI$auth\fI\fR variable (which is a reference to a hash of attributes), and -the \s-1XS\s0 system manages the differences for you. -.PP -.Vb 3 -\& sub connect -\& { -\& my ($drh, $dbname, $user, $auth, $attr) = @_; -\& -\& # Some database specific verifications, default settings -\& # and the like following here. This should only include -\& # syntax checks or similar stuff where it\*(Aqs legal to -\& # \*(Aqdie\*(Aq in case of errors. -\& -\& my $dbh = DBI::_new_dbh($drh, { -\& \*(AqName\*(Aq => $dbname, -\& }) -\& or return undef; -\& -\& # Call the driver\-specific function _login in Driver.xs file which -\& # calls the DBMS\-specific function(s) to connect to the database, -\& # and populate internal handle data. -\& DBD::Driver::db::_login($dbh, $dbname, $user, $auth, $attr) -\& or return undef; -\& -\& $dbh; -\& } -.Ve -.PP -This is mostly the same as in the pure Perl case, the exception being -the use of the private \f(CW\*(C`_login()\*(C'\fR callback, which is the function -that will really connect to the database. It is implemented in -\&\fIDriver.xst\fR (you should not implement it) and calls -\&\f(CW\*(C`dbd_db_login6()\*(C'\fR or \f(CW\*(C`dbd_db_login6_sv\*(C'\fR from \fIdbdimp.c\fR. See below -for details. -.PP -If your driver has driver-specific attributes which may be passed in the -connect method and hence end up in \f(CW$attr\fR in \f(CW\*(C`dbd_db_login6\*(C'\fR then it -is best to delete any you process so \s-1DBI\s0 does not send them again -via \s-1STORE\s0 after connect. You can do this in C like this: -.PP -.Vb 2 -\& DBD_ATTRIB_DELETE(attr, "my_attribute_name", -\& strlen("my_attribute_name")); -.Ve -.PP -However, prior to \s-1DBI\s0 subversion version 11605 (and fixed post 1.607) -\&\s-1DBD_ATTRIB_DELETE\s0 segfaulted so if you cannot guarantee the \s-1DBI\s0 version -will be post 1.607 you need to use: -.PP -.Vb 2 -\& hv_delete((HV*)SvRV(attr), "my_attribute_name", -\& strlen("my_attribute_name"), G_DISCARD); -\& -\& *FIX ME* Discuss removing attributes in Perl code. -.Ve -.PP -\fIThe disconnect_all method\fR -.IX Subsection "The disconnect_all method" -.PP -.Vb 1 -\& *FIX ME* T.B.S -.Ve -.PP -\fIThe data_sources method\fR -.IX Subsection "The data_sources method" -.PP -If your \f(CW\*(C`data_sources()\*(C'\fR method can be implemented in pure Perl, then do -so because it is easier than doing it in \s-1XS\s0 code (see the section above -for pure Perl drivers). -.PP -If your \f(CW\*(C`data_sources()\*(C'\fR method must call onto compiled functions, then -you will need to define \fIdbd_dr_data_sources\fR in your \fIdbdimp.h\fR file, which -will trigger \fIDriver.xst\fR (in \fB\s-1DBI\s0\fR v1.33 or greater) to generate the \s-1XS\s0 -code that calls your actual C function (see the discussion below for -details) and you do not code anything in \fIDriver.pm\fR to handle it. -.PP -\fIThe prepare method\fR -.IX Subsection "The prepare method" -.PP -The prepare method is the statement handle constructor, and most of it -is not new. Like the \f(CW\*(C`connect()\*(C'\fR method, it now has a C callback: -.PP -.Vb 2 -\& package DBD::Driver::db; # ====== DATABASE ====== -\& use strict; -\& -\& sub prepare -\& { -\& my ($dbh, $statement, $attribs) = @_; -\& -\& # create a \*(Aqblank\*(Aq sth -\& my $sth = DBI::_new_sth($dbh, { -\& \*(AqStatement\*(Aq => $statement, -\& }) -\& or return undef; -\& -\& # Call the driver\-specific function _prepare in Driver.xs file -\& # which calls the DBMS\-specific function(s) to prepare a statement -\& # and populate internal handle data. -\& DBD::Driver::st::_prepare($sth, $statement, $attribs) -\& or return undef; -\& $sth; -\& } -.Ve -.PP -\fIThe execute method\fR -.IX Subsection "The execute method" -.PP -.Vb 1 -\& *FIX ME* T.B.S -.Ve -.PP -\fIThe fetchrow_arrayref method\fR -.IX Subsection "The fetchrow_arrayref method" -.PP -.Vb 1 -\& *FIX ME* T.B.S -.Ve -.PP -\fIOther methods?\fR -.IX Subsection "Other methods?" -.PP -.Vb 1 -\& *FIX ME* T.B.S -.Ve -.SS "Driver.xs" -.IX Subsection "Driver.xs" -\&\fIDriver.xs\fR should look something like this: -.PP -.Vb 1 -\& #include "Driver.h" -\& -\& DBISTATE_DECLARE; -\& -\& INCLUDE: Driver.xsi -\& -\& MODULE = DBD::Driver PACKAGE = DBD::Driver::dr -\& -\& /* Non\-standard drh XS methods following here, if any. */ -\& /* If none (the usual case), omit the MODULE line above too. */ -\& -\& MODULE = DBD::Driver PACKAGE = DBD::Driver::db -\& -\& /* Non\-standard dbh XS methods following here, if any. */ -\& /* Currently this includes things like _list_tables from */ -\& /* DBD::mSQL and DBD::mysql. */ -\& -\& MODULE = DBD::Driver PACKAGE = DBD::Driver::st -\& -\& /* Non\-standard sth XS methods following here, if any. */ -\& /* In particular this includes things like _list_fields from */ -\& /* DBD::mSQL and DBD::mysql for accessing metadata. */ -.Ve -.PP -Note especially the include of \fIDriver.xsi\fR here: \fB\s-1DBI\s0\fR inserts stub -functions for almost all private methods here which will typically do -much work for you. -.PP -Wherever you really have to implement something, it will call a private -function in \fIdbdimp.c\fR, and this is what you have to implement. -.PP -You need to set up an extra routine if your driver needs to export -constants of its own, analogous to the \s-1SQL\s0 types available when you say: -.PP -.Vb 1 -\& use DBI qw(:sql_types); -\& -\& *FIX ME* T.B.S -.Ve -.SS "Driver.h" -.IX Subsection "Driver.h" -\&\fIDriver.h\fR is very simple and the operational contents should look like this: -.PP -.Vb 2 -\& #ifndef DRIVER_H_INCLUDED -\& #define DRIVER_H_INCLUDED -\& -\& #define NEED_DBIXS_VERSION 93 /* 93 for DBI versions 1.00 to 1.51+ */ -\& #define PERL_NO_GET_CONTEXT /* if used require DBI 1.51+ */ -\& -\& #include /* installed by the DBI module */ -\& -\& #include "dbdimp.h" -\& -\& #include "dbivport.h" /* see below */ -\& -\& #include /* installed by the DBI module */ -\& -\& #endif /* DRIVER_H_INCLUDED */ -.Ve -.PP -The \fI\s-1DBIXS\s0.h\fR header defines most of the interesting information that -the writer of a driver needs. -.PP -The file \fIdbd_xsh.h\fR header provides prototype declarations for the C -functions that you might decide to implement. Note that you should -normally only define one of \f(CW\*(C`dbd_db_login()\*(C'\fR, \f(CW\*(C`dbd_db_login6()\*(C'\fR or -\&\f(CW\*(C`dbd_db_login6_sv\*(C'\fR unless you are intent on supporting really old -versions of \fB\s-1DBI\s0\fR (prior to \fB\s-1DBI\s0\fR 1.06) as well as modern -versions. The only standard, \fB\s-1DBI\s0\fR\-mandated functions that you need -write are those specified in the \fIdbd_xsh.h\fR header. You might also -add extra driver-specific functions in \fIDriver.xs\fR. -.PP -The \fIdbivport.h\fR file should be \fIcopied\fR from the latest \fB\s-1DBI\s0\fR release -into your distribution each time you modify your driver. Its job is to -allow you to enhance your code to work with the latest \fB\s-1DBI\s0\fR \s-1API\s0 while -still allowing your driver to be compiled and used with older versions -of the \fB\s-1DBI\s0\fR (for example, when the \f(CW\*(C`DBIh_SET_ERR_CHAR()\*(C'\fR macro was added -to \fB\s-1DBI\s0\fR 1.41, an emulation of it was added to \fIdbivport.h\fR). This makes -users happy and your life easier. Always read the notes in \fIdbivport.h\fR -to check for any limitations in the emulation that you should be aware -of. -.PP -With \fB\s-1DBI\s0\fR v1.51 or better I recommend that the driver defines -\&\fI\s-1PERL_NO_GET_CONTEXT\s0\fR before \fI\s-1DBIXS\s0.h\fR is included. This can significantly -improve efficiency when running under a thread enabled perl. (Remember that -the standard perl in most Linux distributions is built with threads enabled. -So is ActiveState perl for Windows, and perl built for Apache mod_perl2.) -If you do this there are some things to keep in mind: -.IP "\(bu" 4 -If \fI\s-1PERL_NO_GET_CONTEXT\s0\fR is defined, then every function that calls the Perl -\&\s-1API\s0 will need to start out with a \f(CW\*(C`dTHX;\*(C'\fR declaration. -.IP "\(bu" 4 -You'll know which functions need this, because the C compiler will -complain that the undeclared identifier \f(CW\*(C`my_perl\*(C'\fR is used if \fIand only if\fR -the perl you are using to develop and test your driver has threads enabled. -.IP "\(bu" 4 -If you don't remember to test with a thread-enabled perl before making -a release it's likely that you'll get failure reports from users who are. -.IP "\(bu" 4 -For driver private functions it is possible to gain even more -efficiency by replacing \f(CW\*(C`dTHX;\*(C'\fR with \f(CW\*(C`pTHX_\*(C'\fR prepended to the -parameter list and then \f(CW\*(C`aTHX_\*(C'\fR prepended to the argument list where -the function is called. -.PP -See \*(L"How multiple interpreters and concurrency are supported\*(R" in perlguts for -additional information about \fI\s-1PERL_NO_GET_CONTEXT\s0\fR. -.SS "Implementation header dbdimp.h" -.IX Subsection "Implementation header dbdimp.h" -This header file has two jobs: -.PP -First it defines data structures for your private part of the handles. -Note that the \s-1DBI\s0 provides many common fields for you. For example -the statement handle (imp_sth) already has a row_count field with an \s-1IV\s0 type -that accessed via the DBIc_ROW_COUNT(imp_sth) macro. Using this is strongly -recommended as it's built in to some \s-1DBI\s0 internals so the \s-1DBI\s0 can 'just work' -in more cases and you'll have less driver-specific code to write. -Study \s-1DBIXS\s0.h to see what's included with each type of handle. -.PP -Second it defines macros that rename the generic names like -\&\f(CW\*(C`dbd_db_login()\*(C'\fR to database specific names like \f(CW\*(C`ora_db_login()\*(C'\fR. This -avoids name clashes and enables use of different drivers when you work -with a statically linked perl. -.PP -It also will have the important task of disabling \s-1XS\s0 methods that you -don't want to implement. -.PP -Finally, the macros will also be used to select alternate -implementations of some functions. For example, the \f(CW\*(C`dbd_db_login()\*(C'\fR -function is not passed the attribute hash. -.PP -Since \fB\s-1DBI\s0\fR v1.06, if a \f(CW\*(C`dbd_db_login6()\*(C'\fR macro is defined (for a function -with 6 arguments), it will be used instead with the attribute hash -passed as the sixth argument. -.PP -Since \fB\s-1DBI\s0\fR post v1.607, if a \f(CW\*(C`dbd_db_login6_sv()\*(C'\fR macro is defined (for -a function like dbd_db_login6 but with scalar pointers for the dbname, -username and password), it will be used instead. This will allow your -login6 function to see if there are any Unicode characters in the -dbname. -.PP -Similarly defining dbd_db_do4_iv is preferred over dbd_db_do4, dbd_st_rows_iv -over dbd_st_rows, and dbd_st_execute_iv over dbd_st_execute. The *_iv forms are -declared to return the \s-1IV\s0 type instead of an int. -.PP -People used to just pick Oracle's \fIdbdimp.c\fR and use the same names, -structures and types. I strongly recommend against that. At first glance -this saves time, but your implementation will be less readable. It was -just hell when I had to separate \fB\s-1DBI\s0\fR specific parts, Oracle specific -parts, mSQL specific parts and mysql specific parts in \fBDBD::mysql\fR's -\&\fIdbdimp.h\fR and \fIdbdimp.c\fR. (\fBDBD::mysql\fR was a port of \fBDBD::mSQL\fR -which was based on \fBDBD::Oracle\fR.) [Seconded, based on the experience -taking \fBDBD::Informix\fR apart, even though the version inherited in 1996 -was only based on \fBDBD::Oracle\fR.] -.PP -This part of the driver is \fIyour exclusive part\fR. Rewrite it from -scratch, so it will be clean and short: in other words, a better piece -of code. (Of course keep an eye on other people's work.) -.PP -.Vb 4 -\& struct imp_drh_st { -\& dbih_drc_t com; /* MUST be first element in structure */ -\& /* Insert your driver handle attributes here */ -\& }; -\& -\& struct imp_dbh_st { -\& dbih_dbc_t com; /* MUST be first element in structure */ -\& /* Insert your database handle attributes here */ -\& }; -\& -\& struct imp_sth_st { -\& dbih_stc_t com; /* MUST be first element in structure */ -\& /* Insert your statement handle attributes here */ -\& }; -\& -\& /* Rename functions for avoiding name clashes; prototypes are */ -\& /* in dbd_xsh.h */ -\& #define dbd_init drv_dr_init -\& #define dbd_db_login6_sv drv_db_login_sv -\& #define dbd_db_do drv_db_do -\& ... many more here ... -.Ve -.PP -These structures implement your private part of the handles. -.PP -You \fIhave\fR to use the name \f(CW\*(C`imp_dbh_{dr|db|st}\*(C'\fR and the first field -\&\fImust\fR be of type \fIdbih_drc_t|_dbc_t|_stc_t\fR and \fImust\fR be called -\&\f(CW\*(C`com\*(C'\fR. -.PP -You should never access these fields directly, except by using the -\&\fI\fIDBIc_xxx()\fI\fR macros below. -.SS "Implementation source dbdimp.c" -.IX Subsection "Implementation source dbdimp.c" -Conventionally, \fIdbdimp.c\fR is the main implementation file (but -\&\fBDBD::Informix\fR calls the file \fIdbdimp.ec\fR). This section includes a -short note on each function that is used in the \fIDriver.xsi\fR template -and thus \fIhas\fR to be implemented. -.PP -Of course, you will probably also need to implement other support -functions, which should usually be file static if they are placed in -\&\fIdbdimp.c\fR. If they are placed in other files, you need to list those -files in \fIMakefile.PL\fR (and \fI\s-1MANIFEST\s0\fR) to handle them correctly. -.PP -It is wise to adhere to a namespace convention for your functions to -avoid conflicts. For example, for a driver with prefix \fIdrv_\fR, you -might call externally visible functions \fIdbd_drv_xxxx\fR. You should also -avoid non-constant global variables as much as possible to improve the -support for threading. -.PP -Since Perl requires support for function prototypes (\s-1ANSI\s0 or \s-1ISO\s0 or -Standard C), you should write your code using function prototypes too. -.PP -It is possible to use either the unmapped names such as \f(CW\*(C`dbd_init()\*(C'\fR or -the mapped names such as \f(CW\*(C`dbd_ix_dr_init()\*(C'\fR in the \fIdbdimp.c\fR file. -\&\fBDBD::Informix\fR uses the mapped names which makes it easier to identify -where to look for linkage problems at runtime (which will report errors -using the mapped names). -.PP -Most other drivers, and in particular \fBDBD::Oracle\fR, use the unmapped -names in the source code which makes it a little easier to compare code -between drivers and eases discussions on the \fIdbi-dev\fR mailing list. -The majority of the code fragments here will use the unmapped names. -.PP -Ultimately, you should provide implementations for most of the -functions listed in the \fIdbd_xsh.h\fR header. The exceptions are -optional functions (such as \f(CW\*(C`dbd_st_rows()\*(C'\fR) and those functions with -alternative signatures, such as \f(CW\*(C`dbd_db_login6_sv\*(C'\fR, -\&\f(CW\*(C`dbd_db_login6()\*(C'\fR and \fI\fIdbd_db_login()\fI\fR. Then you should only -implement one of the alternatives, and generally the newer one of the -alternatives. -.PP -\fIThe dbd_init method\fR -.IX Subsection "The dbd_init method" -.PP -.Vb 1 -\& #include "Driver.h" -\& -\& DBISTATE_DECLARE; -\& -\& void dbd_init(dbistate_t* dbistate) -\& { -\& DBISTATE_INIT; /* Initialize the DBI macros */ -\& } -.Ve -.PP -The \f(CW\*(C`dbd_init()\*(C'\fR function will be called when your driver is first -loaded; the bootstrap command in \f(CW\*(C`DBD::Driver::dr::driver()\*(C'\fR triggers this, -and the call is generated in the \fI\s-1BOOT\s0\fR section of \fIDriver.xst\fR. -These statements are needed to allow your driver to use the \fB\s-1DBI\s0\fR macros. -They will include your private header file \fIdbdimp.h\fR in turn. -Note that \fI\s-1DBISTATE_INIT\s0\fR requires the name of the argument to \f(CW\*(C`dbd_init()\*(C'\fR -to be called \f(CW\*(C`dbistate()\*(C'\fR. -.PP -\fIThe dbd_drv_error method\fR -.IX Subsection "The dbd_drv_error method" -.PP -You need a function to record errors so \fB\s-1DBI\s0\fR can access them properly. -You can call it whatever you like, but we'll call it \f(CW\*(C`dbd_drv_error()\*(C'\fR -here. -.PP -The argument list depends on your database software; different systems -provide different ways to get at error information. -.PP -.Vb 2 -\& static void dbd_drv_error(SV *h, int rc, const char *what) -\& { -.Ve -.PP -Note that \fIh\fR is a generic handle, may it be a driver handle, a -database or a statement handle. -.PP -.Vb 1 -\& D_imp_xxh(h); -.Ve -.PP -This macro will declare and initialize a variable \fIimp_xxh\fR with -a pointer to your private handle pointer. You may cast this to -to \fIimp_drh_t\fR, \fIimp_dbh_t\fR or \fIimp_sth_t\fR. -.PP -To record the error correctly, equivalent to the \f(CW\*(C`set_err()\*(C'\fR method, -use one of the \f(CW\*(C`DBIh_SET_ERR_CHAR(...)\*(C'\fR or \f(CW\*(C`DBIh_SET_ERR_SV(...)\*(C'\fR macros, -which were added in \fB\s-1DBI\s0\fR 1.41: -.PP -.Vb 2 -\& DBIh_SET_ERR_SV(h, imp_xxh, err, errstr, state, method); -\& DBIh_SET_ERR_CHAR(h, imp_xxh, err_c, err_i, errstr, state, method); -.Ve -.PP -For \f(CW\*(C`DBIh_SET_ERR_SV\*(C'\fR the \fIerr\fR, \fIerrstr\fR, \fIstate\fR, and \fImethod\fR -parameters are \f(CW\*(C`SV*\*(C'\fR (use &sv_undef instead of \s-1NULL\s0). -.PP -For \f(CW\*(C`DBIh_SET_ERR_CHAR\*(C'\fR the \fIerr_c\fR, \fIerrstr\fR, \fIstate\fR, \fImethod\fR -parameters are \f(CW\*(C`char*\*(C'\fR. -.PP -The \fIerr_i\fR parameter is an \f(CW\*(C`IV\*(C'\fR that's used instead of \fIerr_c\fR if -\&\fIerr_c\fR is \f(CW\*(C`Null\*(C'\fR. -.PP -The \fImethod\fR parameter can be ignored. -.PP -The \f(CW\*(C`DBIh_SET_ERR_CHAR\*(C'\fR macro is usually the simplest to use when you -just have an integer error code and an error message string: -.PP -.Vb 1 -\& DBIh_SET_ERR_CHAR(h, imp_xxh, Nullch, rc, what, Nullch, Nullch); -.Ve -.PP -As you can see, any parameters that aren't relevant to you can be \f(CW\*(C`Null\*(C'\fR. -.PP -To make drivers compatible with \fB\s-1DBI\s0\fR < 1.41 you should be using \fIdbivport.h\fR -as described in \*(L"Driver.h\*(R" above. -.PP -The (obsolete) macros such as \f(CW\*(C`DBIh_EVENT2\*(C'\fR should be removed from drivers. -.PP -The names \f(CW\*(C`dbis\*(C'\fR and \f(CW\*(C`DBIS\*(C'\fR, which were used in previous versions of -this document, should be replaced with the \f(CW\*(C`DBIc_DBISTATE(imp_xxh)\*(C'\fR macro. -.PP -The name \f(CW\*(C`DBILOGFP\*(C'\fR, which was also used in previous versions of this -document, should be replaced by \f(CW\*(C`DBIc_LOGPIO(imp_xxh)\*(C'\fR. -.PP -Your code should not call the C \f(CW\*(C`\*(C'\fR I/O functions; you -should use \f(CW\*(C`PerlIO_printf()\*(C'\fR as shown: -.PP -.Vb 3 -\& if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) -\& PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar %s: %s\en", -\& foo, neatsvpv(errstr,0)); -.Ve -.PP -That's the first time we see how tracing works within a \fB\s-1DBI\s0\fR driver. Make -use of this as often as you can, but don't output anything at a trace -level less than 3. Levels 1 and 2 are reserved for the \fB\s-1DBI\s0\fR. -.PP -You can define up to 8 private trace flags using the top 8 bits -of \f(CW\*(C`DBIc_TRACE_FLAGS(imp)\*(C'\fR, that is: \f(CW0xFF000000\fR. See the -\&\f(CW\*(C`parse_trace_flag()\*(C'\fR method elsewhere in this document. -.PP -\fIThe dbd_dr_data_sources method\fR -.IX Subsection "The dbd_dr_data_sources method" -.PP -This method is optional; the support for it was added in \fB\s-1DBI\s0\fR v1.33. -.PP -As noted in the discussion of \fIDriver.pm\fR, if the data sources -can be determined by pure Perl code, do it that way. If, as in -\&\fBDBD::Informix\fR, the information is obtained by a C function call, then -you need to define a function that matches the prototype: -.PP -.Vb 1 -\& extern AV *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attrs); -.Ve -.PP -An outline implementation for \fBDBD::Informix\fR follows, assuming that the -\&\f(CW\*(C`sqgetdbs()\*(C'\fR function call shown will return up to 100 databases names, -with the pointers to each name in the array dbsname and the name strings -themselves being stores in dbsarea. -.PP -.Vb 7 -\& AV *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attr) -\& { -\& int ndbs; -\& int i; -\& char *dbsname[100]; -\& char dbsarea[10000]; -\& AV *av = Nullav; -\& -\& if (sqgetdbs(&ndbs, dbsname, 100, dbsarea, sizeof(dbsarea)) == 0) -\& { -\& av = NewAV(); -\& av_extend(av, (I32)ndbs); -\& sv_2mortal((SV *)av); -\& for (i = 0; i < ndbs; i++) -\& av_store(av, i, newSVpvf("dbi:Informix:%s", dbsname[i])); -\& } -\& return(av); -\& } -.Ve -.PP -The actual \fBDBD::Informix\fR implementation has a number of extra lines of -code, logs function entry and exit, reports the error from \f(CW\*(C`sqgetdbs()\*(C'\fR, -and uses \f(CW\*(C`#define\*(C'\fR'd constants for the array sizes. -.PP -\fIThe dbd_db_login6 method\fR -.IX Subsection "The dbd_db_login6 method" -.PP -.Vb 2 -\& int dbd_db_login6_sv(SV* dbh, imp_dbh_t* imp_dbh, SV* dbname, -\& SV* user, SV* auth, SV *attr); -\& -\& or -\& -\& int dbd_db_login6(SV* dbh, imp_dbh_t* imp_dbh, char* dbname, -\& char* user, char* auth, SV *attr); -.Ve -.PP -This function will really connect to the database. The argument \fIdbh\fR -is the database handle. \fIimp_dbh\fR is the pointer to the handles private -data, as is \fIimp_xxx\fR in \f(CW\*(C`dbd_drv_error()\*(C'\fR above. The arguments -\&\fIdbname\fR, \fIuser\fR, \fIauth\fR and \fIattr\fR correspond to the arguments of -the driver handle's \f(CW\*(C`connect()\*(C'\fR method. -.PP -You will quite often use database specific attributes here, that are -specified in the \s-1DSN. I\s0 recommend you parse the \s-1DSN \s0(using Perl) within -the \f(CW\*(C`connect()\*(C'\fR method and pass the segments of the \s-1DSN\s0 via the -attributes parameter through \f(CW\*(C`_login()\*(C'\fR to \f(CW\*(C`dbd_db_login6()\*(C'\fR. -.PP -Here's how you fetch them; as an example we use \fIhostname\fR attribute, -which can be up to 12 characters long excluding null terminator: -.PP -.Vb 3 -\& SV** svp; -\& STRLEN len; -\& char* hostname; -\& -\& if ( (svp = DBD_ATTRIB_GET_SVP(attr, "drv_hostname", 12)) && SvTRUE(*svp)) { -\& hostname = SvPV(*svp, len); -\& DBD_ATTRIB_DELETE(attr, "drv_hostname", 12); /* avoid later STORE */ -\& } else { -\& hostname = "localhost"; -\& } -.Ve -.PP -If you handle any driver specific attributes in the dbd_db_login6 -method you probably want to delete them from \f(CW\*(C`attr\*(C'\fR (as above with -\&\s-1DBD_ATTRIB_DELETE\s0). If you don't delete your handled attributes \s-1DBI\s0 -will call \f(CW\*(C`STORE\*(C'\fR for each attribute after the connect/login and this -is at best redundant for attributes you have already processed. -.PP -\&\fBNote: Until revision 11605 (post \s-1DBI 1.607\s0), there was a problem with -\&\s-1DBD_ATTRIBUTE_DELETE\s0 so unless you require a \s-1DBI\s0 version after 1.607 -you need to replace each \s-1DBD_ATTRIBUTE_DELETE\s0 call with:\fR -.PP -.Vb 1 -\& hv_delete((HV*)SvRV(attr), key, key_len, G_DISCARD) -.Ve -.PP -Note that you can also obtain standard attributes such as \fIAutoCommit\fR and -\&\fIChopBlanks\fR from the attributes parameter, using \f(CW\*(C`DBD_ATTRIB_GET_IV\*(C'\fR for -integer attributes. -.PP -If, for example, your database does not support transactions but -\&\fIAutoCommit\fR is set off (requesting transaction support), then you can -emulate a 'failure to connect'. -.PP -Now you should really connect to the database. In general, if the -connection fails, it is best to ensure that all allocated resources are -released so that the handle does not need to be destroyed separately. If -you are successful (and possibly even if you fail but you have allocated -some resources), you should use the following macros: -.PP -.Vb 1 -\& DBIc_IMPSET_on(imp_dbh); -.Ve -.PP -This indicates that the driver (implementor) has allocated resources in -the \fIimp_dbh\fR structure and that the implementors private \f(CW\*(C`dbd_db_destroy()\*(C'\fR -function should be called when the handle is destroyed. -.PP -.Vb 1 -\& DBIc_ACTIVE_on(imp_dbh); -.Ve -.PP -This indicates that the handle has an active connection to the server -and that the \f(CW\*(C`dbd_db_disconnect()\*(C'\fR function should be called before the -handle is destroyed. -.PP -Note that if you do need to fail, you should report errors via the \fIdrh\fR -or \fIimp_drh\fR rather than via \fIdbh\fR or \fIimp_dbh\fR because \fIimp_dbh\fR will be -destroyed by the failure, so errors recorded in that handle will not be -visible to \fB\s-1DBI\s0\fR, and hence not the user either. -.PP -Note too, that the function is passed \fIdbh\fR and \fIimp_dbh\fR, and there -is a macro \f(CW\*(C`D_imp_drh_from_dbh\*(C'\fR which can recover the \fIimp_drh\fR from -the \fIimp_dbh\fR. However, there is no \fB\s-1DBI\s0\fR macro to provide you with the -\&\fIdrh\fR given either the \fIimp_dbh\fR or the \fIdbh\fR or the \fIimp_drh\fR (and -there's no way to recover the \fIdbh\fR given just the \fIimp_dbh\fR). -.PP -This suggests that, despite the above notes about \f(CW\*(C`dbd_drv_error()\*(C'\fR -taking an \f(CW\*(C`SV *\*(C'\fR, it may be better to have two error routines, one -taking \fIimp_dbh\fR and one taking \fIimp_drh\fR instead. With care, you can -factor most of the formatting code out so that these are small routines -calling a common error formatter. See the code in \fBDBD::Informix\fR -1.05.00 for more information. -.PP -The \f(CW\*(C`dbd_db_login6()\*(C'\fR function should return \fI\s-1TRUE\s0\fR for success, -\&\fI\s-1FALSE\s0\fR otherwise. -.PP -Drivers implemented long ago may define the five-argument function -\&\f(CW\*(C`dbd_db_login()\*(C'\fR instead of \f(CW\*(C`dbd_db_login6()\*(C'\fR. The missing argument is -the attributes. There are ways to work around the missing attributes, -but they are ungainly; it is much better to use the 6\-argument form. -Even later drivers will use \f(CW\*(C`dbd_db_login6_sv()\*(C'\fR which provides the -dbname, username and password as SVs. -.PP -\fIThe dbd_db_commit and dbd_db_rollback methods\fR -.IX Subsection "The dbd_db_commit and dbd_db_rollback methods" -.PP -.Vb 2 -\& int dbd_db_commit(SV *dbh, imp_dbh_t *imp_dbh); -\& int dbd_db_rollback(SV* dbh, imp_dbh_t* imp_dbh); -.Ve -.PP -These are used for commit and rollback. They should return \fI\s-1TRUE\s0\fR for -success, \fI\s-1FALSE\s0\fR for error. -.PP -The arguments \fIdbh\fR and \fIimp_dbh\fR are the same as for \f(CW\*(C`dbd_db_login6()\*(C'\fR -above; I will omit describing them in what follows, as they appear -always. -.PP -These functions should return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise. -.PP -\fIThe dbd_db_disconnect method\fR -.IX Subsection "The dbd_db_disconnect method" -.PP -This is your private part of the \f(CW\*(C`disconnect()\*(C'\fR method. Any \fIdbh\fR with -the \fI\s-1ACTIVE\s0\fR flag on must be disconnected. (Note that you have to set -it in \f(CW\*(C`dbd_db_connect()\*(C'\fR above.) -.PP -.Vb 1 -\& int dbd_db_disconnect(SV* dbh, imp_dbh_t* imp_dbh); -.Ve -.PP -The database handle will return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise. -In any case it should do a: -.PP -.Vb 1 -\& DBIc_ACTIVE_off(imp_dbh); -.Ve -.PP -before returning so \fB\s-1DBI\s0\fR knows that \f(CW\*(C`dbd_db_disconnect()\*(C'\fR was executed. -.PP -Note that there's nothing to stop a \fIdbh\fR being \fIdisconnected\fR while -it still have active children. If your database \s-1API\s0 reacts badly to -trying to use an \fIsth\fR in this situation then you'll need to add code -like this to all \fIsth\fR methods: -.PP -.Vb 2 -\& if (!DBIc_ACTIVE(DBIc_PARENT_COM(imp_sth))) -\& return 0; -.Ve -.PP -Alternatively, you can add code to your driver to keep explicit track of -the statement handles that exist for each database handle and arrange -to destroy those handles before disconnecting from the database. There -is code to do this in \fBDBD::Informix\fR. Similar comments apply to the -driver handle keeping track of all the database handles. -.PP -Note that the code which destroys the subordinate handles should only -release the associated database resources and mark the handles inactive; -it does not attempt to free the actual handle structures. -.PP -This function should return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise, but -it is not clear what anything can do about a failure. -.PP -\fIThe dbd_db_discon_all method\fR -.IX Subsection "The dbd_db_discon_all method" -.PP -.Vb 1 -\& int dbd_discon_all (SV *drh, imp_drh_t *imp_drh); -.Ve -.PP -This function may be called at shutdown time. It should make -best-efforts to disconnect all database handles \- if possible. Some -databases don't support that, in which case you can do nothing -but return 'success'. -.PP -This function should return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise, but -it is not clear what anything can do about a failure. -.PP -\fIThe dbd_db_destroy method\fR -.IX Subsection "The dbd_db_destroy method" -.PP -This is your private part of the database handle destructor. Any \fIdbh\fR with -the \fI\s-1IMPSET\s0\fR flag on must be destroyed, so that you can safely free -resources. (Note that you have to set it in \f(CW\*(C`dbd_db_connect()\*(C'\fR above.) -.PP -.Vb 4 -\& void dbd_db_destroy(SV* dbh, imp_dbh_t* imp_dbh) -\& { -\& DBIc_IMPSET_off(imp_dbh); -\& } -.Ve -.PP -The \fB\s-1DBI\s0\fR \fIDriver.xst\fR code will have called \f(CW\*(C`dbd_db_disconnect()\*(C'\fR for you, -if the handle is still 'active', before calling \f(CW\*(C`dbd_db_destroy()\*(C'\fR. -.PP -Before returning the function must switch \fI\s-1IMPSET\s0\fR to off, so \fB\s-1DBI\s0\fR knows -that the destructor was called. -.PP -A \fB\s-1DBI\s0\fR handle doesn't keep references to its children. But children -do keep references to their parents. So a database handle won't be -\&\f(CW\*(C`DESTROY\*(C'\fR'd until all its children have been \f(CW\*(C`DESTROY\*(C'\fR'd. -.PP -\fIThe dbd_db_STORE_attrib method\fR -.IX Subsection "The dbd_db_STORE_attrib method" -.PP -This function handles -.PP -.Vb 1 -\& $dbh\->{$key} = $value; -.Ve -.PP -Its prototype is: -.PP -.Vb 2 -\& int dbd_db_STORE_attrib(SV* dbh, imp_dbh_t* imp_dbh, SV* keysv, -\& SV* valuesv); -.Ve -.PP -You do not handle all attributes; on the contrary, you should not handle -\&\fB\s-1DBI\s0\fR attributes here: leave this to \fB\s-1DBI\s0\fR. (There are two exceptions, -\&\fIAutoCommit\fR and \fIChopBlanks\fR, which you should care about.) -.PP -The return value is \fI\s-1TRUE\s0\fR if you have handled the attribute or \fI\s-1FALSE\s0\fR -otherwise. If you are handling an attribute and something fails, you -should call \f(CW\*(C`dbd_drv_error()\*(C'\fR, so \fB\s-1DBI\s0\fR can raise exceptions, if desired. -If \f(CW\*(C`dbd_drv_error()\*(C'\fR returns, however, you have a problem: the user will -never know about the error, because he typically will not check -\&\f(CW\*(C`$dbh\->errstr()\*(C'\fR. -.PP -I cannot recommend a general way of going on, if \f(CW\*(C`dbd_drv_error()\*(C'\fR returns, -but there are examples where even the \fB\s-1DBI\s0\fR specification expects that -you \f(CW\*(C`croak()\*(C'\fR. (See the \fIAutoCommit\fR method in \s-1DBI\s0.) -.PP -If you have to store attributes, you should either use your private -data structure \fIimp_xxx\fR, the handle hash (via \f(CW\*(C`(HV*)SvRV(dbh)\*(C'\fR), or use -the private \fIimp_data\fR. -.PP -The first is best for internal C values like integers or pointers and -where speed is important within the driver. The handle hash is best for -values the user may want to get/set via driver-specific attributes. -The private \fIimp_data\fR is an additional \f(CW\*(C`SV\*(C'\fR attached to the handle. You -could think of it as an unnamed handle attribute. It's not normally used. -.PP -\fIThe dbd_db_FETCH_attrib method\fR -.IX Subsection "The dbd_db_FETCH_attrib method" -.PP -This is the counterpart of \f(CW\*(C`dbd_db_STORE_attrib()\*(C'\fR, needed for: -.PP -.Vb 1 -\& $value = $dbh\->{$key}; -.Ve -.PP -Its prototype is: -.PP -.Vb 1 -\& SV* dbd_db_FETCH_attrib(SV* dbh, imp_dbh_t* imp_dbh, SV* keysv); -.Ve -.PP -Unlike all previous methods this returns an \f(CW\*(C`SV\*(C'\fR with the value. Note -that you should normally execute \f(CW\*(C`sv_2mortal()\*(C'\fR, if you return a nonconstant -value. (Constant values are \f(CW&sv_undef\fR, \f(CW&sv_no\fR and \f(CW&sv_yes\fR.) -.PP -Note, that \fB\s-1DBI\s0\fR implements a caching algorithm for attribute values. -If you think, that an attribute may be fetched, you store it in the -\&\fIdbh\fR itself: -.PP -.Vb 2 -\& if (cacheit) /* cache value for later DBI \*(Aqquick\*(Aq fetch? */ -\& hv_store((HV*)SvRV(dbh), key, kl, cachesv, 0); -.Ve -.PP -\fIThe dbd_st_prepare method\fR -.IX Subsection "The dbd_st_prepare method" -.PP -This is the private part of the \f(CW\*(C`prepare()\*(C'\fR method. Note that you -\&\fBmust not\fR really execute the statement here. You may, however, -preparse and validate the statement, or do similar things. -.PP -.Vb 2 -\& int dbd_st_prepare(SV* sth, imp_sth_t* imp_sth, char* statement, -\& SV* attribs); -.Ve -.PP -A typical, simple, possibility is to do nothing and rely on the perl -\&\f(CW\*(C`prepare()\*(C'\fR code that set the \fIStatement\fR attribute on the handle. This -attribute can then be used by \f(CW\*(C`dbd_st_execute()\*(C'\fR. -.PP -If the driver supports placeholders then the \fI\s-1NUM_OF_PARAMS\s0\fR attribute -must be set correctly by \f(CW\*(C`dbd_st_prepare()\*(C'\fR: -.PP -.Vb 1 -\& DBIc_NUM_PARAMS(imp_sth) = ... -.Ve -.PP -If you can, you should also setup attributes like \fI\s-1NUM_OF_FIELDS\s0\fR, \fI\s-1NAME\s0\fR, -etc. here, but \fB\s-1DBI\s0\fR doesn't require that \- they can be deferred until -\&\fIexecute()\fR is called. However, if you do, document it. -.PP -In any case you should set the \fI\s-1IMPSET\s0\fR flag, as you did in -\&\f(CW\*(C`dbd_db_connect()\*(C'\fR above: -.PP -.Vb 1 -\& DBIc_IMPSET_on(imp_sth); -.Ve -.PP -\fIThe dbd_st_execute method\fR -.IX Subsection "The dbd_st_execute method" -.PP -This is where a statement will really be executed. -.PP -.Vb 1 -\& int dbd_st_execute(SV* sth, imp_sth_t* imp_sth); -.Ve -.PP -\&\f(CW\*(C`dbd_st_execute\*(C'\fR should return \-2 for any error, \-1 if the number of -rows affected is unknown else it should be the number of affected -(updated, inserted) rows. -.PP -Note that you must be aware a statement may be executed repeatedly. -Also, you should not expect that \f(CW\*(C`finish()\*(C'\fR will be called between two -executions, so you might need code, like the following, near the start -of the function: -.PP -.Vb 2 -\& if (DBIc_ACTIVE(imp_sth)) -\& dbd_st_finish(h, imp_sth); -.Ve -.PP -If your driver supports the binding of parameters (it should!), but the -database doesn't, you must do it here. This can be done as follows: -.PP -.Vb 4 -\& SV *svp; -\& char* statement = DBD_ATTRIB_GET_PV(h, "Statement", 9, svp, ""); -\& int numParam = DBIc_NUM_PARAMS(imp_sth); -\& int i; -\& -\& for (i = 0; i < numParam; i++) -\& { -\& char* value = dbd_db_get_param(sth, imp_sth, i); -\& /* It is your drivers task to implement dbd_db_get_param, */ -\& /* it must be setup as a counterpart of dbd_bind_ph. */ -\& /* Look for \*(Aq?\*(Aq and replace it with \*(Aqvalue\*(Aq. Difficult */ -\& /* task, note that you may have question marks inside */ -\& /* quotes and comments the like ... :\-( */ -\& /* See DBD::mysql for an example. (Don\*(Aqt look too deep into */ -\& /* the example, you will notice where I was lazy ...) */ -\& } -.Ve -.PP -The next thing is to really execute the statement. -.PP -Note that you must set the attributes \fI\s-1NUM_OF_FIELDS\s0\fR, \fI\s-1NAME\s0\fR, etc -when the statement is successfully executed if the driver has not -already done so: they may be used even before a potential \f(CW\*(C`fetchrow()\*(C'\fR. -In particular you have to tell \fB\s-1DBI\s0\fR the number of fields that the -statement has, because it will be used by \fB\s-1DBI\s0\fR internally. Thus the -function will typically ends with: -.PP -.Vb 4 -\& if (isSelectStatement) { -\& DBIc_NUM_FIELDS(imp_sth) = numFields; -\& DBIc_ACTIVE_on(imp_sth); -\& } -.Ve -.PP -It is important that the \fI\s-1ACTIVE\s0\fR flag only be set for \f(CW\*(C`SELECT\*(C'\fR -statements (or any other statements that can return many -values from the database using a cursor-like mechanism). See -\&\f(CW\*(C`dbd_db_connect()\*(C'\fR above for more explanations. -.PP -There plans for a preparse function to be provided by \fB\s-1DBI\s0\fR, but this has -not reached fruition yet. -Meantime, if you want to know how ugly it can get, try looking at the -\&\f(CW\*(C`dbd_ix_preparse()\*(C'\fR in \fBDBD::Informix\fR \fIdbdimp.ec\fR and the related -functions in \fIiustoken.c\fR and \fIsqltoken.c\fR. -.PP -\fIThe dbd_st_fetch method\fR -.IX Subsection "The dbd_st_fetch method" -.PP -This function fetches a row of data. The row is stored in in an array, -of \f(CW\*(C`SV\*(C'\fR's that \fB\s-1DBI\s0\fR prepares for you. This has two advantages: it is fast -(you even reuse the \f(CW\*(C`SV\*(C'\fR's, so they don't have to be created after the -first \f(CW\*(C`fetchrow()\*(C'\fR), and it guarantees that \fB\s-1DBI\s0\fR handles \f(CW\*(C`bind_cols()\*(C'\fR for -you. -.PP -What you do is the following: -.PP -.Vb 6 -\& AV* av; -\& int numFields = DBIc_NUM_FIELDS(imp_sth); /* Correct, if NUM_FIELDS -\& is constant for this statement. There are drivers where this is -\& not the case! */ -\& int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks); -\& int i; -\& -\& if (!fetch_new_row_of_data(...)) { -\& ... /* check for error or end\-of\-data */ -\& DBIc_ACTIVE_off(imp_sth); /* turn off Active flag automatically */ -\& return Nullav; -\& } -\& /* get the fbav (field buffer array value) for this row */ -\& /* it is very important to only call this after you know */ -\& /* that you have a row of data to return. */ -\& av = DBIc_DBISTATE(imp_sth)\->get_fbav(imp_sth); -\& for (i = 0; i < numFields; i++) { -\& SV* sv = fetch_a_field(..., i); -\& if (chopBlanks && SvOK(sv) && type_is_blank_padded(field_type[i])) { -\& /* Remove white space from end (only) of sv */ -\& } -\& sv_setsv(AvARRAY(av)[i], sv); /* Note: (re)use! */ -\& } -\& return av; -.Ve -.PP -There's no need to use a \f(CW\*(C`fetch_a_field()\*(C'\fR function returning an \f(CW\*(C`SV*\*(C'\fR. -It's more common to use your database \s-1API\s0 functions to fetch the -data as character strings and use code like this: -.PP -.Vb 1 -\& sv_setpvn(AvARRAY(av)[i], char_ptr, char_count); -.Ve -.PP -\&\f(CW\*(C`NULL\*(C'\fR values must be returned as \f(CW\*(C`undef\*(C'\fR. You can use code like this: -.PP -.Vb 1 -\& SvOK_off(AvARRAY(av)[i]); -.Ve -.PP -The function returns the \f(CW\*(C`AV\*(C'\fR prepared by \fB\s-1DBI\s0\fR for success or \f(CW\*(C`Nullav\*(C'\fR -otherwise. -.PP -.Vb 3 -\& *FIX ME* Discuss what happens when there\*(Aqs no more data to fetch. -\& Are errors permitted if another fetch occurs after the first fetch -\& that reports no more data. (Permitted, not required.) -.Ve -.PP -If an error occurs which leaves the \fI\f(CI$sth\fI\fR in a state where remaining -rows can't be fetched then \fIActive\fR should be turned off before the -method returns. -.PP -\fIThe dbd_st_finish3 method\fR -.IX Subsection "The dbd_st_finish3 method" -.PP -The \f(CW\*(C`$sth\->finish()\*(C'\fR method can be called if the user wishes to -indicate that no more rows will be fetched even if the database has more -rows to offer, and the \fB\s-1DBI\s0\fR code can call the function when handles are -being destroyed. See the \fB\s-1DBI\s0\fR specification for more background details. -.PP -In both circumstances, the \fB\s-1DBI\s0\fR code ends up calling the -\&\f(CW\*(C`dbd_st_finish3()\*(C'\fR method (if you provide a mapping for -\&\f(CW\*(C`dbd_st_finish3()\*(C'\fR in \fIdbdimp.h\fR), or \f(CW\*(C`dbd_st_finish()\*(C'\fR otherwise. -The difference is that \f(CW\*(C`dbd_st_finish3()\*(C'\fR takes a third argument which -is an \f(CW\*(C`int\*(C'\fR with the value 1 if it is being called from a \f(CW\*(C`destroy()\*(C'\fR -method and 0 otherwise. -.PP -Note that \fB\s-1DBI\s0\fR v1.32 and earlier test on \f(CW\*(C`dbd_db_finish3()\*(C'\fR to call -\&\f(CW\*(C`dbd_st_finish3()\*(C'\fR; if you provide \f(CW\*(C`dbd_st_finish3()\*(C'\fR, either define -\&\f(CW\*(C`dbd_db_finish3()\*(C'\fR too, or insist on \fB\s-1DBI\s0\fR v1.33 or later. -.PP -All it \fIneeds\fR to do is turn off the \fIActive\fR flag for the \fIsth\fR. -It will only be called by \fIDriver.xst\fR code, if the driver has set \fI\s-1ACTIVE\s0\fR -to on for the \fIsth\fR. -.PP -Outline example: -.PP -.Vb 8 -\& int dbd_st_finish3(SV* sth, imp_sth_t* imp_sth, int from_destroy) { -\& if (DBIc_ACTIVE(imp_sth)) -\& { -\& /* close cursor or equivalent action */ -\& DBIc_ACTIVE_off(imp_sth); -\& } -\& return 1; -\& } -.Ve -.PP -The from_destroy parameter is true if \f(CW\*(C`dbd_st_finish3()\*(C'\fR is being called -from \f(CW\*(C`DESTROY()\*(C'\fR \- and so the statement is about to be destroyed. -For many drivers there is no point in doing anything more than turning off -the \fIActive\fR flag in this case. -.PP -The function returns \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise, but there isn't -a lot anyone can do to recover if there is an error. -.PP -\fIThe dbd_st_destroy method\fR -.IX Subsection "The dbd_st_destroy method" -.PP -This function is the private part of the statement handle destructor. -.PP -.Vb 4 -\& void dbd_st_destroy(SV* sth, imp_sth_t* imp_sth) { -\& ... /* any clean\-up that\*(Aqs needed */ -\& DBIc_IMPSET_off(imp_sth); /* let DBI know we\*(Aqve done it */ -\& } -.Ve -.PP -The \fB\s-1DBI\s0\fR \fIDriver.xst\fR code will call \f(CW\*(C`dbd_st_finish()\*(C'\fR for you, if the -\&\fIsth\fR has the \fI\s-1ACTIVE\s0\fR flag set, before calling \f(CW\*(C`dbd_st_destroy()\*(C'\fR. -.PP -\fIThe dbd_st_STORE_attrib and dbd_st_FETCH_attrib methods\fR -.IX Subsection "The dbd_st_STORE_attrib and dbd_st_FETCH_attrib methods" -.PP -These functions correspond to \f(CW\*(C`dbd_db_STORE()\*(C'\fR and \f(CW\*(C`dbd_db_FETCH()\*(C'\fR attrib -above, except that they are for statement handles. -See above. -.PP -.Vb 3 -\& int dbd_st_STORE_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv, -\& SV* valuesv); -\& SV* dbd_st_FETCH_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv); -.Ve -.PP -\fIThe dbd_bind_ph method\fR -.IX Subsection "The dbd_bind_ph method" -.PP -This function is internally used by the \f(CW\*(C`bind_param()\*(C'\fR method, the -\&\f(CW\*(C`bind_param_inout()\*(C'\fR method and by the \fB\s-1DBI\s0\fR \fIDriver.xst\fR code if -\&\f(CW\*(C`execute()\*(C'\fR is called with any bind parameters. -.PP -.Vb 3 -\& int dbd_bind_ph (SV *sth, imp_sth_t *imp_sth, SV *param, -\& SV *value, IV sql_type, SV *attribs, -\& int is_inout, IV maxlen); -.Ve -.PP -The \fIparam\fR argument holds an \f(CW\*(C`IV\*(C'\fR with the parameter number (1, 2, ...). -The \fIvalue\fR argument is the parameter value and \fIsql_type\fR is its type. -.PP -If your driver does not support \f(CW\*(C`bind_param_inout()\*(C'\fR then you should -ignore \fImaxlen\fR and croak if \fIis_inout\fR is \fI\s-1TRUE\s0\fR. -.PP -If your driver \fIdoes\fR support \f(CW\*(C`bind_param_inout()\*(C'\fR then you should -note that \fIvalue\fR is the \f(CW\*(C`SV\*(C'\fR \fIafter\fR dereferencing the reference -passed to \f(CW\*(C`bind_param_inout()\*(C'\fR. -.PP -In drivers of simple databases the function will, for example, store -the value in a parameter array and use it later in \f(CW\*(C`dbd_st_execute()\*(C'\fR. -See the \fBDBD::mysql\fR driver for an example. -.PP -\fIImplementing bind_param_inout support\fR -.IX Subsection "Implementing bind_param_inout support" -.PP -To provide support for parameters bound by reference rather than by -value, the driver must do a number of things. First, and most -importantly, it must note the references and stash them in its own -driver structure. Secondly, when a value is bound to a column, the -driver must discard any previous reference bound to the column. On -each execute, the driver must evaluate the references and internally -bind the values resulting from the references. This is only applicable -if the user writes: -.PP -.Vb 1 -\& $sth\->execute; -.Ve -.PP -If the user writes: -.PP -.Vb 1 -\& $sth\->execute(@values); -.Ve -.PP -then \fB\s-1DBI\s0\fR automatically calls the binding code for each element of -\&\fI\f(CI@values\fI\fR. These calls are indistinguishable from explicit user calls to -\&\f(CW\*(C`bind_param()\*(C'\fR. -.SS "C/XS version of Makefile.PL" -.IX Subsection "C/XS version of Makefile.PL" -The \fIMakefile.PL\fR file for a C/XS driver is similar to the code needed -for a pure Perl driver, but there are a number of extra bits of -information needed by the build system. -.PP -For example, the attributes list passed to \f(CW\*(C`WriteMakefile()\*(C'\fR needs -to specify the object files that need to be compiled and built into -the shared object (\s-1DLL\s0). This is often, but not necessarily, just -\&\fIdbdimp.o\fR (unless that should be \fIdbdimp.obj\fR because you're building -on \s-1MS\s0 Windows). -.PP -Note that you can reliably determine the extension of the object files -from the \fI\f(CI$Config\fI{obj_ext}\fR values, and there are many other useful pieces -of configuration information lurking in that hash. -You get access to it with: -.PP -.Vb 1 -\& use Config; -.Ve -.SS "Methods which do not need to be written" -.IX Subsection "Methods which do not need to be written" -The \fB\s-1DBI\s0\fR code implements the majority of the methods which are accessed -using the notation \f(CW\*(C`DBI\->function()\*(C'\fR, the only exceptions being -\&\f(CW\*(C`DBI\->connect()\*(C'\fR and \f(CW\*(C`DBI\->data_sources()\*(C'\fR which require -support from the driver. -.PP -The \fB\s-1DBI\s0\fR code implements the following documented driver, database and -statement functions which do not need to be written by the \fB\s-1DBD\s0\fR driver -writer. -.ie n .IP "$dbh\->\fIdo()\fR" 4 -.el .IP "\f(CW$dbh\fR\->\fIdo()\fR" 4 -.IX Item "$dbh->do()" -The default implementation of this function prepares, executes and -destroys the statement. This can be replaced if there is a better -way to implement this, such as \f(CW\*(C`EXECUTE IMMEDIATE\*(C'\fR which can -sometimes be used if there are no parameters. -.ie n .IP "$h\->\fIerrstr()\fR" 4 -.el .IP "\f(CW$h\fR\->\fIerrstr()\fR" 4 -.IX Item "$h->errstr()" -.PD 0 -.ie n .IP "$h\->\fIerr()\fR" 4 -.el .IP "\f(CW$h\fR\->\fIerr()\fR" 4 -.IX Item "$h->err()" -.ie n .IP "$h\->\fIstate()\fR" 4 -.el .IP "\f(CW$h\fR\->\fIstate()\fR" 4 -.IX Item "$h->state()" -.ie n .IP "$h\->\fItrace()\fR" 4 -.el .IP "\f(CW$h\fR\->\fItrace()\fR" 4 -.IX Item "$h->trace()" -.PD -The \fB\s-1DBD\s0\fR driver does not need to worry about these routines at all. -.ie n .IP "$h\->{ChopBlanks}" 4 -.el .IP "\f(CW$h\fR\->{ChopBlanks}" 4 -.IX Item "$h->{ChopBlanks}" -This attribute needs to be honored during \f(CW\*(C`fetch()\*(C'\fR operations, but does -not need to be handled by the attribute handling code. -.ie n .IP "$h\->{RaiseError}" 4 -.el .IP "\f(CW$h\fR\->{RaiseError}" 4 -.IX Item "$h->{RaiseError}" -The \fB\s-1DBD\s0\fR driver does not need to worry about this attribute at all. -.ie n .IP "$h\->{PrintError}" 4 -.el .IP "\f(CW$h\fR\->{PrintError}" 4 -.IX Item "$h->{PrintError}" -The \fB\s-1DBD\s0\fR driver does not need to worry about this attribute at all. -.ie n .IP "$sth\->\fIbind_col()\fR" 4 -.el .IP "\f(CW$sth\fR\->\fIbind_col()\fR" 4 -.IX Item "$sth->bind_col()" -Assuming the driver uses the \f(CW\*(C`DBIc_DBISTATE(imp_xxh)\->get_fbav()\*(C'\fR -function (C drivers, see below), or the \f(CW\*(C`$sth\->_set_fbav($data)\*(C'\fR -method (Perl drivers) the driver does not need to do anything about this -routine. -.ie n .IP "$sth\->\fIbind_columns()\fR" 4 -.el .IP "\f(CW$sth\fR\->\fIbind_columns()\fR" 4 -.IX Item "$sth->bind_columns()" -Regardless of whether the driver uses -\&\f(CW\*(C`DBIc_DBISTATE(imp_xxh)\->get_fbav()\*(C'\fR, the driver does not need -to do anything about this routine as it simply iteratively calls -\&\f(CW\*(C`$sth\->bind_col()\*(C'\fR. -.PP -The \fB\s-1DBI\s0\fR code implements a default implementation of the following -functions which do not need to be written by the \fB\s-1DBD\s0\fR driver writer -unless the default implementation is incorrect for the Driver. -.ie n .IP "$dbh\->\fIquote()\fR" 4 -.el .IP "\f(CW$dbh\fR\->\fIquote()\fR" 4 -.IX Item "$dbh->quote()" -This should only be written if the database does not accept the \s-1ANSI -SQL\s0 standard for quoting strings, with the string enclosed in single -quotes and any embedded single quotes replaced by two consecutive -single quotes. -.Sp -For the two argument form of quote, you need to implement the -\&\f(CW\*(C`type_info()\*(C'\fR method to provide the information that quote needs. -.ie n .IP "$dbh\->\fIping()\fR" 4 -.el .IP "\f(CW$dbh\fR\->\fIping()\fR" 4 -.IX Item "$dbh->ping()" -This should be implemented as a simple efficient way to determine -whether the connection to the database is still alive. Typically -code like this: -.Sp -.Vb 9 -\& sub ping { -\& my $dbh = shift; -\& $sth = $dbh\->prepare_cached(q{ -\& select * from A_TABLE_NAME where 1=0 -\& }) or return 0; -\& $sth\->execute or return 0; -\& $sth\->finish; -\& return 1; -\& } -.Ve -.Sp -where \fIA_TABLE_NAME\fR is the name of a table that always exists (such as a -database system catalogue). -.ie n .IP "$drh\->default_user" 4 -.el .IP "\f(CW$drh\fR\->default_user" 4 -.IX Item "$drh->default_user" -The default implementation of default_user will get the database -username and password fields from \f(CW$ENV{DBI_USER}\fR and -\&\f(CW$ENV{DBI_PASS}\fR. You can override this method. It is called as -follows: -.Sp -.Vb 1 -\& ($user, $pass) = $drh\->default_user($user, $pass, $attr) -.Ve -.SH "METADATA METHODS" -.IX Header "METADATA METHODS" -The exposition above ignores the \fB\s-1DBI\s0\fR MetaData methods. -The metadata methods are all associated with a database handle. -.SS "Using DBI::DBD::Metadata" -.IX Subsection "Using DBI::DBD::Metadata" -The \fBDBI::DBD::Metadata\fR module is a good semi-automatic way for the -developer of a \fB\s-1DBD\s0\fR module to write the \f(CW\*(C`get_info()\*(C'\fR and \f(CW\*(C`type_info()\*(C'\fR -functions quickly and accurately. -.PP -\fIGenerating the get_info method\fR -.IX Subsection "Generating the get_info method" -.PP -Prior to \fB\s-1DBI\s0\fR v1.33, this existed as the method \f(CW\*(C`write_getinfo_pm()\*(C'\fR -in the \fB\s-1DBI::DBD\s0\fR module. From \fB\s-1DBI\s0\fR v1.33, it exists as the method -\&\f(CW\*(C`write_getinfo_pm()\*(C'\fR in the \fBDBI::DBD::Metadata\fR module. This -discussion assumes you have \fB\s-1DBI\s0\fR v1.33 or later. -.PP -You examine the documentation for \f(CW\*(C`write_getinfo_pm()\*(C'\fR using: -.PP -.Vb 1 -\& perldoc DBI::DBD::Metadata -.Ve -.PP -To use it, you need a Perl \fB\s-1DBI\s0\fR driver for your database which implements -the \f(CW\*(C`get_info()\*(C'\fR method. In practice, this means you need to install -\&\fB\s-1DBD::ODBC\s0\fR, an \s-1ODBC\s0 driver manager, and an \s-1ODBC\s0 driver for your -database. -.PP -With the pre-requisites in place, you might type: -.PP -.Vb 2 -\& perl \-MDBI::DBD::Metadata \-we \e -\& "write_getinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })" -.Ve -.PP -The procedure writes to standard output the code that should be added to -your \fIDriver.pm\fR file and the code that should be written to -\&\fIlib/DBD/Driver/GetInfo.pm\fR. -.PP -You should review the output to ensure that it is sensible. -.PP -\fIGenerating the type_info method\fR -.IX Subsection "Generating the type_info method" -.PP -Given the idea of the \f(CW\*(C`write_getinfo_pm()\*(C'\fR method, it was not hard -to devise a parallel method, \f(CW\*(C`write_typeinfo_pm()\*(C'\fR, which does the -analogous job for the \fB\s-1DBI\s0\fR \f(CW\*(C`type_info_all()\*(C'\fR metadata method. The -\&\f(CW\*(C`write_typeinfo_pm()\*(C'\fR method was added to \fB\s-1DBI\s0\fR v1.33. -.PP -You examine the documentation for \f(CW\*(C`write_typeinfo_pm()\*(C'\fR using: -.PP -.Vb 1 -\& perldoc DBI::DBD::Metadata -.Ve -.PP -The setup is exactly analogous to the mechanism described in -\&\*(L"Generating the get_info method\*(R". -.PP -With the pre-requisites in place, you might type: -.PP -.Vb 2 -\& perl \-MDBI::DBD::Metadata \-we \e -\& "write_typeinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })" -.Ve -.PP -The procedure writes to standard output the code that should be added to -your \fIDriver.pm\fR file and the code that should be written to -\&\fIlib/DBD/Driver/TypeInfo.pm\fR. -.PP -You should review the output to ensure that it is sensible. -.SS "Writing DBD::Driver::db::get_info" -.IX Subsection "Writing DBD::Driver::db::get_info" -If you use the \fBDBI::DBD::Metadata\fR module, then the code you need is -generated for you. -.PP -If you decide not to use the \fBDBI::DBD::Metadata\fR module, you -should probably borrow the code from a driver that has done so (eg -\&\fBDBD::Informix\fR from version 1.05 onwards) and crib the code from -there, or look at the code that generates that module and follow -that. The method in \fIDriver.pm\fR will be very simple; the method in -\&\fIlib/DBD/Driver/GetInfo.pm\fR is not very much more complex unless your -\&\s-1DBMS\s0 itself is much more complex. -.PP -Note that some of the \fB\s-1DBI\s0\fR utility methods rely on information from the -\&\f(CW\*(C`get_info()\*(C'\fR method to perform their operations correctly. See, for -example, the \f(CW\*(C`quote_identifier()\*(C'\fR and quote methods, discussed below. -.SS "Writing DBD::Driver::db::type_info_all" -.IX Subsection "Writing DBD::Driver::db::type_info_all" -If you use the \f(CW\*(C`DBI::DBD::Metadata\*(C'\fR module, then the code you need is -generated for you. -.PP -If you decide not to use the \f(CW\*(C`DBI::DBD::Metadata\*(C'\fR module, you -should probably borrow the code from a driver that has done so (eg -\&\f(CW\*(C`DBD::Informix\*(C'\fR from version 1.05 onwards) and crib the code from -there, or look at the code that generates that module and follow -that. The method in \fIDriver.pm\fR will be very simple; the method in -\&\fIlib/DBD/Driver/TypeInfo.pm\fR is not very much more complex unless your -\&\s-1DBMS\s0 itself is much more complex. -.SS "Writing DBD::Driver::db::type_info" -.IX Subsection "Writing DBD::Driver::db::type_info" -The guidelines on writing this method are still not really clear. -No sample implementation is available. -.SS "Writing DBD::Driver::db::table_info" -.IX Subsection "Writing DBD::Driver::db::table_info" -.Vb 2 -\& *FIX ME* The guidelines on writing this method have not been written yet. -\& No sample implementation is available. -.Ve -.SS "Writing DBD::Driver::db::column_info" -.IX Subsection "Writing DBD::Driver::db::column_info" -.Vb 2 -\& *FIX ME* The guidelines on writing this method have not been written yet. -\& No sample implementation is available. -.Ve -.SS "Writing DBD::Driver::db::primary_key_info" -.IX Subsection "Writing DBD::Driver::db::primary_key_info" -.Vb 2 -\& *FIX ME* The guidelines on writing this method have not been written yet. -\& No sample implementation is available. -.Ve -.SS "Writing DBD::Driver::db::primary_key" -.IX Subsection "Writing DBD::Driver::db::primary_key" -.Vb 2 -\& *FIX ME* The guidelines on writing this method have not been written yet. -\& No sample implementation is available. -.Ve -.SS "Writing DBD::Driver::db::foreign_key_info" -.IX Subsection "Writing DBD::Driver::db::foreign_key_info" -.Vb 2 -\& *FIX ME* The guidelines on writing this method have not been written yet. -\& No sample implementation is available. -.Ve -.SS "Writing DBD::Driver::db::tables" -.IX Subsection "Writing DBD::Driver::db::tables" -This method generates an array of names in a format suitable for being -embedded in \s-1SQL\s0 statements in places where a table name is expected. -.PP -If your database hews close enough to the \s-1SQL\s0 standard or if you have -implemented an appropriate \f(CW\*(C`table_info()\*(C'\fR function and and the appropriate -\&\f(CW\*(C`quote_identifier()\*(C'\fR function, then the \fB\s-1DBI\s0\fR default version of this method -will work for your driver too. -.PP -Otherwise, you have to write a function yourself, such as: -.PP -.Vb 12 -\& sub tables -\& { -\& my($dbh, $cat, $sch, $tab, $typ) = @_; -\& my(@res); -\& my($sth) = $dbh\->table_info($cat, $sch, $tab, $typ); -\& my(@arr); -\& while (@arr = $sth\->fetchrow_array) -\& { -\& push @res, $dbh\->quote_identifier($arr[0], $arr[1], $arr[2]); -\& } -\& return @res; -\& } -.Ve -.PP -See also the default implementation in \fI\s-1DBI\s0.pm\fR. -.SS "Writing DBD::Driver::db::quote" -.IX Subsection "Writing DBD::Driver::db::quote" -This method takes a value and converts it into a string suitable for -embedding in an \s-1SQL\s0 statement as a string literal. -.PP -If your \s-1DBMS\s0 accepts the \s-1SQL\s0 standard notation for strings (single -quotes around the string as a whole with any embedded single quotes -doubled up), then you do not need to write this method as \fB\s-1DBI\s0\fR provides a -default method that does it for you. -.PP -If your \s-1DBMS\s0 uses an alternative notation or escape mechanism, then you -need to provide an equivalent function. For example, suppose your \s-1DBMS\s0 -used C notation with double quotes around the string and backslashes -escaping both double quotes and backslashes themselves. Then you might -write the function as: -.PP -.Vb 6 -\& sub quote -\& { -\& my($dbh, $str) = @_; -\& $str =~ s/["\e\e]/\e\e$&/gmo; -\& return qq{"$str"}; -\& } -.Ve -.PP -Handling newlines and other control characters is left as an exercise -for the reader. -.PP -This sample method ignores the \fI\f(CI$data_type\fI\fR indicator which is the -optional second argument to the method. -.SS "Writing DBD::Driver::db::quote_identifier" -.IX Subsection "Writing DBD::Driver::db::quote_identifier" -This method is called to ensure that the name of the given table (or -other database object) can be embedded into an \s-1SQL\s0 statement without -danger of misinterpretation. The result string should be usable in the -text of an \s-1SQL\s0 statement as the identifier for a table. -.PP -If your \s-1DBMS\s0 accepts the \s-1SQL\s0 standard notation for quoted identifiers -(which uses double quotes around the identifier as a whole, with any -embedded double quotes doubled up) and accepts \fI\*(L"schema\*(R".\*(L"identifier\*(R"\fR -(and \fI\*(L"catalog\*(R".\*(L"schema\*(R".\*(L"identifier\*(R"\fR when a catalog is specified), then -you do not need to write this method as \fB\s-1DBI\s0\fR provides a default method -that does it for you. -.PP -In fact, even if your \s-1DBMS\s0 does not handle exactly that notation but -you have implemented the \f(CW\*(C`get_info()\*(C'\fR method and it gives the correct -responses, then it will work for you. If your database is fussier, then -you need to implement your own version of the function. -.PP -For example, \fBDBD::Informix\fR has to deal with an environment variable -\&\fI\s-1DELIMIDENT\s0\fR. If it is not set, then the \s-1DBMS\s0 treats names enclosed in -double quotes as strings rather than names, which is usually a syntax -error. Additionally, the catalog portion of the name is separated from -the schema and table by a different delimiter (colon instead of dot), -and the catalog portion is never enclosed in quotes. (Fortunately, -valid strings for the catalog will never contain weird characters that -might need to be escaped, unless you count dots, dashes, slashes and -at-signs as weird.) Finally, an Informix database can contain objects -that cannot be accessed because they were created by a user with the -\&\fI\s-1DELIMIDENT\s0\fR environment variable set, but the current user does not -have it set. By design choice, the \f(CW\*(C`quote_identifier()\*(C'\fR method encloses -those identifiers in double quotes anyway, which generally triggers a -syntax error, and the metadata methods which generate lists of tables -etc omit those identifiers from the result sets. -.PP -.Vb 10 -\& sub quote_identifier -\& { -\& my($dbh, $cat, $sch, $obj) = @_; -\& my($rv) = ""; -\& my($qq) = (defined $ENV{DELIMIDENT}) ? \*(Aq"\*(Aq : \*(Aq\*(Aq; -\& $rv .= qq{$cat:} if (defined $cat); -\& if (defined $sch) -\& { -\& if ($sch !~ m/^\ew+$/o) -\& { -\& $qq = \*(Aq"\*(Aq; -\& $sch =~ s/$qq/$qq$qq/gm; -\& } -\& $rv .= qq{$qq$sch$qq.}; -\& } -\& if (defined $obj) -\& { -\& if ($obj !~ m/^\ew+$/o) -\& { -\& $qq = \*(Aq"\*(Aq; -\& $obj =~ s/$qq/$qq$qq/gm; -\& } -\& $rv .= qq{$qq$obj$qq}; -\& } -\& return $rv; -\& } -.Ve -.PP -Handling newlines and other control characters is left as an exercise -for the reader. -.PP -Note that there is an optional fourth parameter to this function which -is a reference to a hash of attributes; this sample implementation -ignores that. -.PP -This sample implementation also ignores the single-argument variant of -the method. -.SH "TRACING" -.IX Header "TRACING" -Tracing in \s-1DBI\s0 is controlled with a combination of a trace level and a -set of flags which together are known as the trace settings. The trace -settings are stored in a single integer and divided into levels and -flags by a set of masks (\f(CW\*(C`DBIc_TRACE_LEVEL_MASK\*(C'\fR and -\&\f(CW\*(C`DBIc_TRACE_FLAGS_MASK\*(C'\fR). -.PP -Each handle has it's own trace settings and so does the \s-1DBI.\s0 When you -call a method the \s-1DBI\s0 merges the handles settings into its own for the -duration of the call: the trace flags of the handle are \s-1OR\s0'd into the -trace flags of the \s-1DBI,\s0 and if the handle has a higher trace level -then the \s-1DBI\s0 trace level is raised to match it. The previous \s-1DBI\s0 trace -settings are restored when the called method returns. -.SS "Trace Level" -.IX Subsection "Trace Level" -The trace level is the first 4 bits of the trace settings (masked by -\&\f(CW\*(C`DBIc_TRACE_FLAGS_MASK\*(C'\fR) and represents trace levels of 1 to 15. Do -not output anything at trace levels less than 3 as they are reserved -for \s-1DBI.\s0 -.PP -For advice on what to output at each level see \*(L"Trace Levels\*(R" in -\&\s-1DBI\s0. -.PP -To test for a trace level you can use the \f(CW\*(C`DBIc_TRACE_LEVEL\*(C'\fR macro -like this: -.PP -.Vb 3 -\& if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) { -\& PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar"); -\& } -.Ve -.PP -Also \fBnote\fR the use of PerlIO_printf which you should always use for -tracing and never the C \f(CW\*(C`stdio.h\*(C'\fR I/O functions. -.SS "Trace Flags" -.IX Subsection "Trace Flags" -Trace flags are used to enable tracing of specific activities within -the \s-1DBI\s0 and drivers. The \s-1DBI\s0 defines some trace flags and drivers can -define others. \s-1DBI\s0 trace flag names begin with a capital letter and -driver specific names begin with a lowercase letter. For a list of \s-1DBI\s0 -defined trace flags see \*(L"Trace Flags\*(R" in \s-1DBI\s0. -.PP -If you want to use private trace flags you'll probably want to be able -to set them by name. Drivers are expected to override the -parse_trace_flag (note the singular) and check if \f(CW$trace_flag_name\fR is -a driver specific trace flags and, if not, then call the DBIs default -\&\fIparse_trace_flag()\fR. To do that you'll need to define a -\&\fIparse_trace_flag()\fR method like this: -.PP -.Vb 9 -\& sub parse_trace_flag { -\& my ($h, $name) = @_; -\& return 0x01000000 if $name eq \*(Aqfoo\*(Aq; -\& return 0x02000000 if $name eq \*(Aqbar\*(Aq; -\& return 0x04000000 if $name eq \*(Aqbaz\*(Aq; -\& return 0x08000000 if $name eq \*(Aqboo\*(Aq; -\& return 0x10000000 if $name eq \*(Aqbop\*(Aq; -\& return $h\->SUPER::parse_trace_flag($name); -\& } -.Ve -.PP -All private flag names must be lowercase, and all private flags must -be in the top 8 of the 32 bits of \f(CW\*(C`DBIc_TRACE_FLAGS(imp)\*(C'\fR i.e., -0xFF000000. -.PP -If you've defined a \fIparse_trace_flag()\fR method in ::db you'll also want -it in ::st, so just alias it in: -.PP -.Vb 1 -\& *parse_trace_flag = \e&DBD::foo:db::parse_trace_flag; -.Ve -.PP -You may want to act on the current '\s-1SQL\s0' trace flag that \s-1DBI\s0 defines -to output \s-1SQL\s0 prepared/executed as \s-1DBI\s0 currently does not do \s-1SQL\s0 -tracing. -.SS "Trace Macros" -.IX Subsection "Trace Macros" -Access to the trace level and trace flags is via a set of macros. -.PP -.Vb 4 -\& DBIc_TRACE_SETTINGS(imp) returns the trace settings -\& DBIc_TRACE_LEVEL(imp) returns the trace level -\& DBIc_TRACE_FLAGS(imp) returns the trace flags -\& DBIc_TRACE(imp, flags, flaglevel, level) -\& -\& e.g., -\& -\& DBIc_TRACE(imp, 0, 0, 4) -\& if level >= 4 -\& -\& DBIc_TRACE(imp, DBDtf_FOO, 2, 4) -\& if tracing DBDtf_FOO & level>=2 or level>=4 -\& -\& DBIc_TRACE(imp, DBDtf_FOO, 2, 0) -\& as above but never trace just due to level -.Ve -.SH "WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE" -.IX Header "WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE" -Study \fIOraperl.pm\fR (supplied with \fBDBD::Oracle\fR) and \fIIngperl.pm\fR (supplied -with \fBDBD::Ingres\fR) and the corresponding \fIdbdimp.c\fR files for ideas. -.PP -Note that the emulation code sets \f(CW\*(C`$dbh\->{CompatMode} = 1;\*(C'\fR for each -connection so that the internals of the driver can implement behaviour -compatible with the old interface when dealing with those handles. -.SS "Setting emulation perl variables" -.IX Subsection "Setting emulation perl variables" -For example, ingperl has a \fI\f(CI$sql_rowcount\fI\fR variable. Rather than try -to manually update this in \fIIngperl.pm\fR it can be done faster in C code. -In \f(CW\*(C`dbd_init()\*(C'\fR: -.PP -.Vb 1 -\& sql_rowcount = perl_get_sv("Ingperl::sql_rowcount", GV_ADDMULTI); -.Ve -.PP -In the relevant places do: -.PP -.Vb 2 -\& if (DBIc_COMPAT(imp_sth)) /* only do this for compatibility mode handles */ -\& sv_setiv(sql_rowcount, the_row_count); -.Ve -.SH "OTHER MISCELLANEOUS INFORMATION" -.IX Header "OTHER MISCELLANEOUS INFORMATION" -.SS "The imp_xyz_t types" -.IX Subsection "The imp_xyz_t types" -Any handle has a corresponding C structure filled with private data. -Some of this data is reserved for use by \fB\s-1DBI\s0\fR (except for using the -DBIc macros below), some is for you. See the description of the -\&\fIdbdimp.h\fR file above for examples. Most functions in \fIdbdimp.c\fR -are passed both the handle \f(CW\*(C`xyz\*(C'\fR and a pointer to \f(CW\*(C`imp_xyz\*(C'\fR. In -rare cases, however, you may use the following macros: -.IP "D_imp_dbh(dbh)" 4 -.IX Item "D_imp_dbh(dbh)" -Given a function argument \fIdbh\fR, declare a variable \fIimp_dbh\fR and -initialize it with a pointer to the handles private data. Note: This -must be a part of the function header, because it declares a variable. -.IP "D_imp_sth(sth)" 4 -.IX Item "D_imp_sth(sth)" -Likewise for statement handles. -.IP "D_imp_xxx(h)" 4 -.IX Item "D_imp_xxx(h)" -Given any handle, declare a variable \fIimp_xxx\fR and initialize it -with a pointer to the handles private data. It is safe, for example, -to cast \fIimp_xxx\fR to \f(CW\*(C`imp_dbh_t*\*(C'\fR, if \f(CW\*(C`DBIc_TYPE(imp_xxx) == DBIt_DB\*(C'\fR. -(You can also call \f(CW\*(C`sv_derived_from(h, "DBI::db")\*(C'\fR, but that's much -slower.) -.IP "D_imp_dbh_from_sth" 4 -.IX Item "D_imp_dbh_from_sth" -Given a \fIimp_sth\fR, declare a variable \fIimp_dbh\fR and initialize it with a -pointer to the parent database handle's implementors structure. -.SS "Using DBIc_IMPSET_on" -.IX Subsection "Using DBIc_IMPSET_on" -The driver code which initializes a handle should use \f(CW\*(C`DBIc_IMPSET_on()\*(C'\fR -as soon as its state is such that the cleanup code must be called. -When this happens is determined by your driver code. -.PP -\&\fBFailure to call this can lead to corruption of data structures.\fR -.PP -For example, \fBDBD::Informix\fR maintains a linked list of database -handles in the driver, and within each handle, a linked list of -statements. Once a statement is added to the linked list, it is crucial -that it is cleaned up (removed from the list). When \fI\fIDBIc_IMPSET_on()\fI\fR -was being called too late, it was able to cause all sorts of problems. -.SS "Using \fIDBIc_is()\fP, \fIDBIc_has()\fP, \fIDBIc_on()\fP and \fIDBIc_off()\fP" -.IX Subsection "Using DBIc_is(), DBIc_has(), DBIc_on() and DBIc_off()" -Once upon a long time ago, the only way of handling the internal \fB\s-1DBI\s0\fR -boolean flags/attributes was through macros such as: -.PP -.Vb 2 -\& DBIc_WARN DBIc_WARN_on DBIc_WARN_off -\& DBIc_COMPAT DBIc_COMPAT_on DBIc_COMPAT_off -.Ve -.PP -Each of these took an \fIimp_xxh\fR pointer as an argument. -.PP -Since then, new attributes have been added such as \fIChopBlanks\fR, -\&\fIRaiseError\fR and \fIPrintError\fR, and these do not have the full set of -macros. The approved method for handling these is now the four macros: -.PP -.Vb 5 -\& DBIc_is(imp, flag) -\& DBIc_has(imp, flag) an alias for DBIc_is -\& DBIc_on(imp, flag) -\& DBIc_off(imp, flag) -\& DBIc_set(imp, flag, on) set if on is true, else clear -.Ve -.PP -Consequently, the \f(CW\*(C`DBIc_XXXXX\*(C'\fR family of macros is now mostly deprecated -and new drivers should avoid using them, even though the older drivers -will probably continue to do so for quite a while yet. However... -.PP -There is an \fIimportant exception\fR to that. The \fI\s-1ACTIVE\s0\fR and \fI\s-1IMPSET\s0\fR -flags should be set via the \f(CW\*(C`DBIc_ACTIVE_on()\*(C'\fR and \f(CW\*(C`DBIc_IMPSET_on()\*(C'\fR macros, -and unset via the \f(CW\*(C`DBIc_ACTIVE_off()\*(C'\fR and \f(CW\*(C`DBIc_IMPSET_off()\*(C'\fR macros. -.SS "Using the \fIget_fbav()\fP method" -.IX Subsection "Using the get_fbav() method" -\&\fB\s-1THIS IS CRITICAL\s0 for C/XS drivers\fR. -.PP -The \f(CW\*(C`$sth\->bind_col()\*(C'\fR and \f(CW\*(C`$sth\->bind_columns()\*(C'\fR documented -in the \fB\s-1DBI\s0\fR specification do not have to be implemented by the driver -writer because \fB\s-1DBI\s0\fR takes care of the details for you. -.PP -However, the key to ensuring that bound columns work is to call the -function \f(CW\*(C`DBIc_DBISTATE(imp_xxh)\->get_fbav()\*(C'\fR in the code which -fetches a row of data. -.PP -This returns an \f(CW\*(C`AV\*(C'\fR, and each element of the \f(CW\*(C`AV\*(C'\fR contains the \f(CW\*(C`SV\*(C'\fR which -should be set to contain the returned data. -.PP -The pure Perl equivalent is the \f(CW\*(C`$sth\->_set_fbav($data)\*(C'\fR method, as -described in the part on pure Perl drivers. -.SS "Casting strings to Perl types based on a \s-1SQL\s0 type" -.IX Subsection "Casting strings to Perl types based on a SQL type" -\&\s-1DBI\s0 from 1.611 (and \s-1DBIXS_REVISION 13606\s0) defines the -sql_type_cast_svpv method which may be used to cast a string -representation of a value to a more specific Perl type based on a \s-1SQL\s0 -type. You should consider using this method when processing bound -column data as it provides some support for the \s-1TYPE\s0 bind_col -attribute which is rarely used in drivers. -.PP -.Vb 1 -\& int sql_type_cast_svpv(pTHX_ SV *sv, int sql_type, U32 flags, void *v) -.Ve -.PP -\&\f(CW\*(C`sv\*(C'\fR is what you would like cast, \f(CW\*(C`sql_type\*(C'\fR is one of the \s-1DBI\s0 defined -\&\s-1SQL\s0 types (e.g., \f(CW\*(C`SQL_INTEGER\*(C'\fR) and \f(CW\*(C`flags\*(C'\fR is a bitmask as follows: -.IP "DBIstcf_STRICT" 4 -.IX Item "DBIstcf_STRICT" -If set this indicates you want an error state returned if the cast -cannot be performed. -.IP "DBIstcf_DISCARD_STRING" 4 -.IX Item "DBIstcf_DISCARD_STRING" -If set and the pv portion of the \f(CW\*(C`sv\*(C'\fR is cast then this will cause -sv's pv to be freed up. -.PP -sql_type_cast_svpv returns the following states: -.PP -.Vb 5 -\& \-2 sql_type is not handled \- sv not changed -\& \-1 sv is undef, sv not changed -\& 0 sv could not be cast cleanly and DBIstcf_STRICT was specified -\& 1 sv could not be case cleanly and DBIstcf_STRICT was not specified -\& 2 sv was cast ok -.Ve -.PP -The current implementation of sql_type_cast_svpv supports -\&\f(CW\*(C`SQL_INTEGER\*(C'\fR, \f(CW\*(C`SQL_DOUBLE\*(C'\fR and \f(CW\*(C`SQL_NUMERIC\*(C'\fR. \f(CW\*(C`SQL_INTEGER\*(C'\fR uses -sv_2iv and hence may set \s-1IV, UV\s0 or \s-1NV\s0 depending on the -number. \f(CW\*(C`SQL_DOUBLE\*(C'\fR uses sv_2nv so may set \s-1NV\s0 and \f(CW\*(C`SQL_NUMERIC\*(C'\fR -will set \s-1IV\s0 or \s-1UV\s0 or \s-1NV.\s0 -.PP -DBIstcf_STRICT should be implemented as the StrictlyTyped attribute -and DBIstcf_DISCARD_STRING implemented as the DiscardString attribute -to the bind_col method and both default to off. -.PP -See DBD::Oracle for an example of how this is used. -.SH "SUBCLASSING DBI DRIVERS" -.IX Header "SUBCLASSING DBI DRIVERS" -This is definitely an open subject. It can be done, as demonstrated by -the \fBDBD::File\fR driver, but it is not as simple as one might think. -.PP -(Note that this topic is different from subclassing the \fB\s-1DBI\s0\fR. For an -example of that, see the \fIt/subclass.t\fR file supplied with the \fB\s-1DBI\s0\fR.) -.PP -The main problem is that the \fIdbh\fR's and \fIsth\fR's that your \f(CW\*(C`connect()\*(C'\fR and -\&\f(CW\*(C`prepare()\*(C'\fR methods return are not instances of your \fBDBD::Driver::db\fR -or \fBDBD::Driver::st\fR packages, they are not even derived from it. -Instead they are instances of the \fBDBI::db\fR or \fBDBI::st\fR classes or -a derived subclass. Thus, if you write a method \f(CW\*(C`mymethod()\*(C'\fR and do a -.PP -.Vb 1 -\& $dbh\->mymethod() -.Ve -.PP -then the autoloader will search for that method in the package \fBDBI::db\fR. -Of course you can instead to a -.PP -.Vb 1 -\& $dbh\->func(\*(Aqmymethod\*(Aq) -.Ve -.PP -and that will indeed work, even if \f(CW\*(C`mymethod()\*(C'\fR is inherited, but not -without additional work. Setting \fI\f(CI@ISA\fI\fR is not sufficient. -.SS "Overwriting methods" -.IX Subsection "Overwriting methods" -The first problem is, that the \f(CW\*(C`connect()\*(C'\fR method has no idea of -subclasses. For example, you cannot implement base class and subclass -in the same file: The \f(CW\*(C`install_driver()\*(C'\fR method wants to do a -.PP -.Vb 1 -\& require DBD::Driver; -.Ve -.PP -In particular, your subclass \fBhas\fR to be a separate driver, from -the view of \fB\s-1DBI\s0\fR, and you cannot share driver handles. -.PP -Of course that's not much of a problem. You should even be able -to inherit the base classes \f(CW\*(C`connect()\*(C'\fR method. But you cannot -simply overwrite the method, unless you do something like this, -quoted from \fB\s-1DBD::CSV\s0\fR: -.PP -.Vb 2 -\& sub connect ($$;$$$) { -\& my ($drh, $dbname, $user, $auth, $attr) = @_; -\& -\& my $this = $drh\->DBD::File::dr::connect($dbname, $user, $auth, $attr); -\& if (!exists($this\->{csv_tables})) { -\& $this\->{csv_tables} = {}; -\& } -\& -\& $this; -\& } -.Ve -.PP -Note that we cannot do a -.PP -.Vb 1 -\& $drh\->SUPER::connect($dbname, $user, $auth, $attr); -.Ve -.PP -as we would usually do in a an \s-1OO\s0 environment, because \fI\f(CI$drh\fI\fR is an instance -of \fBDBI::dr\fR. And note, that the \f(CW\*(C`connect()\*(C'\fR method of \fBDBD::File\fR is -able to handle subclass attributes. See the description of Pure Perl -drivers above. -.PP -It is essential that you always call superclass method in the above -manner. However, that should do. -.SS "Attribute handling" -.IX Subsection "Attribute handling" -Fortunately the \fB\s-1DBI\s0\fR specifications allow a simple, but still -performant way of handling attributes. The idea is based on the -convention that any driver uses a prefix \fIdriver_\fR for its private -methods. Thus it's always clear whether to pass attributes to the super -class or not. For example, consider this \f(CW\*(C`STORE()\*(C'\fR method from the -\&\fB\s-1DBD::CSV\s0\fR class: -.PP -.Vb 8 -\& sub STORE { -\& my ($dbh, $attr, $val) = @_; -\& if ($attr !~ /^driver_/) { -\& return $dbh\->DBD::File::db::STORE($attr, $val); -\& } -\& if ($attr eq \*(Aqdriver_foo\*(Aq) { -\& ... -\& } -.Ve -.SH "AUTHORS" -.IX Header "AUTHORS" -Jonathan Leffler (previously ), -Jochen Wiedmann , -Steffen Goeldner , -and Tim Bunce . diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::Metadata.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::Metadata.3pm deleted file mode 100644 index 38fd52d..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::Metadata.3pm +++ /dev/null @@ -1,199 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::DBD::Metadata 3pm" -.TH DBI::DBD::Metadata 3pm "2015-05-26" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::DBD::Metadata \- Generate the code and data for some DBI metadata methods -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -The idea is to extract metadata information from a good quality -\&\s-1ODBC\s0 driver and use it to generate code and data to use in your own -\&\s-1DBI\s0 driver for the same database. -.PP -To generate code to support the get_info method: -.PP -.Vb 1 -\& perl \-MDBI::DBD::Metadata \-e "write_getinfo_pm(\*(Aqdbi:ODBC:dsn\-name\*(Aq,\*(Aquser\*(Aq,\*(Aqpass\*(Aq,\*(AqDriver\*(Aq)" -\& -\& perl \-MDBI::DBD::Metadata \-e write_getinfo_pm dbi:ODBC:foo_db username password Driver -.Ve -.PP -To generate code to support the type_info method: -.PP -.Vb 1 -\& perl \-MDBI::DBD::Metadata \-e "write_typeinfo_pm(\*(Aqdbi:ODBC:dsn\-name\*(Aq,\*(Aquser\*(Aq,\*(Aqpass\*(Aq,\*(AqDriver\*(Aq)" -\& -\& perl \-MDBI::DBD::Metadata \-e write_typeinfo_pm dbi:ODBC:dsn\-name user pass Driver -.Ve -.PP -Where \f(CW\*(C`dbi:ODBC:dsn\-name\*(C'\fR is the connection to use to extract the -data, and \f(CW\*(C`Driver\*(C'\fR is the name of the driver you want the code -generated for (the driver name gets embedded into the output in -numerous places). -.SH "Generating a GetInfo package for a driver" -.IX Header "Generating a GetInfo package for a driver" -The \f(CW\*(C`write_getinfo_pm\*(C'\fR in the DBI::DBD::Metadata module generates a -DBD::Driver::GetInfo package on standard output. -.PP -This method generates a DBD::Driver::GetInfo package from the data -source you specified in the parameter list or in the environment -variable \s-1DBI_DSN.\s0 -DBD::Driver::GetInfo should help a \s-1DBD\s0 author implement the \s-1DBI\s0 -\&\fIget_info()\fR method. -Because you are just creating this package, it is very unlikely that -DBD::Driver already provides a good implementation for \fIget_info()\fR. -Thus you will probably connect via \s-1DBD::ODBC.\s0 -.PP -Once you are sure that it is producing reasonably sane data, you should -typically redirect the standard output to lib/DBD/Driver/GetInfo.pm, and -then hand edit the result. -Do not forget to update your Makefile.PL and \s-1MANIFEST\s0 to include this as -an extra \s-1PM\s0 file that should be installed. -.PP -If you connect via \s-1DBD::ODBC,\s0 you should use version 0.38 or greater; -.PP -Please take a critical look at the data returned! -\&\s-1ODBC\s0 drivers vary dramatically in their quality. -.PP -The generator assumes that most values are static and places these -values directly in the \f(CW%info\fR hash. -A few examples show the use of \s-1CODE\s0 references and the implementation -via subroutines. -It is very likely that you will have to write additional subroutines for -values depending on the session state or server version, e.g. -\&\s-1SQL_DBMS_VER.\s0 -.PP -A possible implementation of \fIDBD::Driver::db::get_info()\fR may look like: -.PP -.Vb 7 -\& sub get_info { -\& my($dbh, $info_type) = @_; -\& require DBD::Driver::GetInfo; -\& my $v = $DBD::Driver::GetInfo::info{int($info_type)}; -\& $v = $v\->($dbh) if ref $v eq \*(AqCODE\*(Aq; -\& return $v; -\& } -.Ve -.PP -Please replace Driver (or \*(L"\*(R") with the name of your driver. -Note that this stub function is generated for you by write_getinfo_pm -function, but you must manually transfer the code to Driver.pm. -.SH "Generating a TypeInfo package for a driver" -.IX Header "Generating a TypeInfo package for a driver" -The \f(CW\*(C`write_typeinfo_pm\*(C'\fR function in the DBI::DBD::Metadata module generates -on standard output the data needed for a driver's type_info_all method. -It also provides default implementations of the type_info_all -method for inclusion in the driver's main implementation file. -.PP -The driver parameter is the name of the driver for which the methods -will be generated; for the sake of examples, this will be \*(L"Driver\*(R". -Typically, the dsn parameter will be of the form \*(L"dbi:ODBC:odbc_dsn\*(R", -where the odbc_dsn is a \s-1DSN\s0 for one of the driver's databases. -The user and pass parameters are the other optional connection -parameters that will be provided to the \s-1DBI\s0 connect method. -.PP -Once you are sure that it is producing reasonably sane data, you should -typically redirect the standard output to lib/DBD/Driver/TypeInfo.pm, -and then hand edit the result if necessary. -Do not forget to update your Makefile.PL and \s-1MANIFEST\s0 to include this as -an extra \s-1PM\s0 file that should be installed. -.PP -Please take a critical look at the data returned! -\&\s-1ODBC\s0 drivers vary dramatically in their quality. -.PP -The generator assumes that all the values are static and places these -values directly in the \f(CW%info\fR hash. -.PP -A possible implementation of \fIDBD::Driver::type_info_all()\fR may look like: -.PP -.Vb 5 -\& sub type_info_all { -\& my ($dbh) = @_; -\& require DBD::Driver::TypeInfo; -\& return [ @$DBD::Driver::TypeInfo::type_info_all ]; -\& } -.Ve -.PP -Please replace Driver (or \*(L"\*(R") with the name of your driver. -Note that this stub function is generated for you by the write_typeinfo_pm -function, but you must manually transfer the code to Driver.pm. -.SH "AUTHORS" -.IX Header "AUTHORS" -Jonathan Leffler (previously ), -Jochen Wiedmann , -Steffen Goeldner , -and Tim Bunce . diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine.3pm deleted file mode 100644 index 0bcf384..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine.3pm +++ /dev/null @@ -1,701 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::DBD::SqlEngine 3pm" -.TH DBI::DBD::SqlEngine 3pm "2016-04-21" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::DBD::SqlEngine \- Base class for DBI drivers without their own SQL engine -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& package DBD::myDriver; -\& -\& use base qw(DBI::DBD::SqlEngine); -\& -\& sub driver -\& { -\& ... -\& my $drh = $proto\->SUPER::driver($attr); -\& ... -\& return $drh\->{class}; -\& } -\& -\& package DBD::myDriver::dr; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::dr); -\& -\& sub data_sources { ... } -\& ... -\& -\& package DBD::myDriver::db; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::db); -\& -\& sub init_valid_attributes { ... } -\& sub init_default_attributes { ... } -\& sub set_versions { ... } -\& sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } -\& sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } -\& sub get_myd_versions { ... } -\& sub get_avail_tables { ... } -\& -\& package DBD::myDriver::st; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::st); -\& -\& sub FETCH { ... } -\& sub STORE { ... } -\& -\& package DBD::myDriver::Statement; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::Statement); -\& -\& sub open_table { ... } -\& -\& package DBD::myDriver::Table; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::Table); -\& -\& sub new { ... } -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBI::DBD::SqlEngine abstracts the usage of \s-1SQL\s0 engines from the -\&\s-1DBD. DBD\s0 authors can concentrate on the data retrieval they want to -provide. -.PP -It is strongly recommended that you read DBD::File::Developers and -DBD::File::Roadmap, because many of the DBD::File \s-1API\s0 is provided -by DBI::DBD::SqlEngine. -.PP -Currently the \s-1API\s0 of DBI::DBD::SqlEngine is experimental and will -likely change in the near future to provide the table meta data basics -like DBD::File. -.PP -DBI::DBD::SqlEngine expects that any driver in inheritance chain has -a \s-1DBI\s0 prefix. -.SS "Metadata" -.IX Subsection "Metadata" -The following attributes are handled by \s-1DBI\s0 itself and not by -DBI::DBD::SqlEngine, thus they all work as expected: -.PP -.Vb 10 -\& Active -\& ActiveKids -\& CachedKids -\& CompatMode (Not used) -\& InactiveDestroy -\& AutoInactiveDestroy -\& Kids -\& PrintError -\& RaiseError -\& Warn (Not used) -.Ve -.PP -\fIThe following \s-1DBI\s0 attributes are handled by DBI::DBD::SqlEngine:\fR -.IX Subsection "The following DBI attributes are handled by DBI::DBD::SqlEngine:" -.PP -AutoCommit -.IX Subsection "AutoCommit" -.PP -Always on. -.PP -ChopBlanks -.IX Subsection "ChopBlanks" -.PP -Works. -.PP -\s-1NUM_OF_FIELDS\s0 -.IX Subsection "NUM_OF_FIELDS" -.PP -Valid after \f(CW\*(C`$sth\->execute\*(C'\fR. -.PP -\s-1NUM_OF_PARAMS\s0 -.IX Subsection "NUM_OF_PARAMS" -.PP -Valid after \f(CW\*(C`$sth\->prepare\*(C'\fR. -.PP -\s-1NAME\s0 -.IX Subsection "NAME" -.PP -Valid after \f(CW\*(C`$sth\->execute\*(C'\fR; probably undef for Non-Select statements. -.PP -\s-1NULLABLE\s0 -.IX Subsection "NULLABLE" -.PP -Not really working, always returns an array ref of ones, as \s-1DBD::CSV\s0 -does not verify input data. Valid after \f(CW\*(C`$sth\->execute\*(C'\fR; undef for -non-select statements. -.PP -\fIThe following \s-1DBI\s0 attributes and methods are not supported:\fR -.IX Subsection "The following DBI attributes and methods are not supported:" -.IP "bind_param_inout" 4 -.IX Item "bind_param_inout" -.PD 0 -.IP "CursorName" 4 -.IX Item "CursorName" -.IP "LongReadLen" 4 -.IX Item "LongReadLen" -.IP "LongTruncOk" 4 -.IX Item "LongTruncOk" -.PD -.PP -\fIDBI::DBD::SqlEngine specific attributes\fR -.IX Subsection "DBI::DBD::SqlEngine specific attributes" -.PP -In addition to the \s-1DBI\s0 attributes, you can use the following dbh -attributes: -.PP -sql_engine_version -.IX Subsection "sql_engine_version" -.PP -Contains the module version of this driver (\fBreadonly\fR) -.PP -sql_nano_version -.IX Subsection "sql_nano_version" -.PP -Contains the module version of DBI::SQL::Nano (\fBreadonly\fR) -.PP -sql_statement_version -.IX Subsection "sql_statement_version" -.PP -Contains the module version of SQL::Statement, if available (\fBreadonly\fR) -.PP -sql_handler -.IX Subsection "sql_handler" -.PP -Contains the \s-1SQL\s0 Statement engine, either DBI::SQL::Nano or SQL::Statement -(\fBreadonly\fR). -.PP -sql_parser_object -.IX Subsection "sql_parser_object" -.PP -Contains an instantiated instance of SQL::Parser (\fBreadonly\fR). -This is filled when used first time (only when used with SQL::Statement). -.PP -sql_sponge_driver -.IX Subsection "sql_sponge_driver" -.PP -Contains an internally used DBD::Sponge handle (\fBreadonly\fR). -.PP -sql_valid_attrs -.IX Subsection "sql_valid_attrs" -.PP -Contains the list of valid attributes for each DBI::DBD::SqlEngine based -driver (\fBreadonly\fR). -.PP -sql_readonly_attrs -.IX Subsection "sql_readonly_attrs" -.PP -Contains the list of those attributes which are readonly (\fBreadonly\fR). -.PP -sql_identifier_case -.IX Subsection "sql_identifier_case" -.PP -Contains how DBI::DBD::SqlEngine deals with non-quoted \s-1SQL\s0 identifiers: -.PP -.Vb 5 -\& * SQL_IC_UPPER (1) means all identifiers are internally converted -\& into upper\-cased pendants -\& * SQL_IC_LOWER (2) means all identifiers are internally converted -\& into lower\-cased pendants -\& * SQL_IC_MIXED (4) means all identifiers are taken as they are -.Ve -.PP -These conversions happen if (and only if) no existing identifier matches. -Once existing identifier is used as known. -.PP -The \s-1SQL\s0 statement execution classes doesn't have to care, so don't expect -\&\f(CW\*(C`sql_identifier_case\*(C'\fR affects column names in statements like -.PP -.Vb 1 -\& SELECT * FROM foo -.Ve -.PP -sql_quoted_identifier_case -.IX Subsection "sql_quoted_identifier_case" -.PP -Contains how DBI::DBD::SqlEngine deals with quoted \s-1SQL\s0 identifiers -(\fBreadonly\fR). It's fixated to \s-1SQL_IC_SENSITIVE \\fIs0\fR\|(3), which is interpreted -as \s-1SQL_IC_MIXED.\s0 -.PP -sql_flags -.IX Subsection "sql_flags" -.PP -Contains additional flags to instantiate an SQL::Parser. Because an -SQL::Parser is instantiated only once, it's recommended to set this flag -before any statement is executed. -.PP -sql_dialect -.IX Subsection "sql_dialect" -.PP -Controls the dialect understood by SQL::Parser. Possible values (delivery -state of SQL::Statement): -.PP -.Vb 3 -\& * ANSI -\& * CSV -\& * AnyData -.Ve -.PP -Defaults to \*(L"\s-1CSV\*(R". \s0 Because an SQL::Parser is instantiated only once and -SQL::Parser doesn't allow one to modify the dialect once instantiated, -it's strongly recommended to set this flag before any statement is -executed (best place is connect attribute hash). -.PP -sql_engine_in_gofer -.IX Subsection "sql_engine_in_gofer" -.PP -This value has a true value in case of this driver is operated via -DBD::Gofer. The impact of being operated via Gofer is a read-only -driver (not read-only databases!), so you cannot modify any attributes -later \- neither any table settings. \fBBut\fR you won't get an error in -cases you modify table attributes, so please carefully watch -\&\f(CW\*(C`sql_engine_in_gofer\*(C'\fR. -.PP -sql_meta -.IX Subsection "sql_meta" -.PP -Private data area which contains information about the tables this -module handles. Table meta data might not be available until the -table has been accessed for the first time e.g., by issuing a select -on it however it is possible to pre-initialize attributes for each table -you use. -.PP -DBI::DBD::SqlEngine recognizes the (public) attributes \f(CW\*(C`col_names\*(C'\fR, -\&\f(CW\*(C`table_name\*(C'\fR, \f(CW\*(C`readonly\*(C'\fR, \f(CW\*(C`sql_data_source\*(C'\fR and \f(CW\*(C`sql_identifier_case\*(C'\fR. -Be very careful when modifying attributes you do not know, the consequence -might be a destroyed or corrupted table. -.PP -While \f(CW\*(C`sql_meta\*(C'\fR is a private and readonly attribute (which means, you -cannot modify it's values), derived drivers might provide restricted -write access through another attribute. Well known accessors are -\&\f(CW\*(C`csv_tables\*(C'\fR for \s-1DBD::CSV\s0, \f(CW\*(C`ad_tables\*(C'\fR for DBD::AnyData and -\&\f(CW\*(C`dbm_tables\*(C'\fR for \s-1DBD::DBM\s0. -.PP -sql_table_source -.IX Subsection "sql_table_source" -.PP -Controls the class which will be used for fetching available tables. -.PP -See \*(L"DBI::DBD::SqlEngine::TableSource\*(R" for details. -.PP -sql_data_source -.IX Subsection "sql_data_source" -.PP -Contains the class name to be used for opening tables. -.PP -See \*(L"DBI::DBD::SqlEngine::DataSource\*(R" for details. -.SS "Driver private methods" -.IX Subsection "Driver private methods" -\fIDefault \s-1DBI\s0 methods\fR -.IX Subsection "Default DBI methods" -.PP -data_sources -.IX Subsection "data_sources" -.PP -The \f(CW\*(C`data_sources\*(C'\fR method returns a list of subdirectories of the current -directory in the form \*(L"dbi:CSV:f_dir=$dirname\*(R". -.PP -If you want to read the subdirectories of another directory, use -.PP -.Vb 2 -\& my ($drh) = DBI\->install_driver ("CSV"); -\& my (@list) = $drh\->data_sources (f_dir => "/usr/local/csv_data"); -.Ve -.PP -list_tables -.IX Subsection "list_tables" -.PP -This method returns a list of file names inside \f(CW$dbh\fR\->{f_dir}. -Example: -.PP -.Vb 2 -\& my ($dbh) = DBI\->connect ("dbi:CSV:f_dir=/usr/local/csv_data"); -\& my (@list) = $dbh\->func ("list_tables"); -.Ve -.PP -Note that the list includes all files contained in the directory, even -those that have non-valid table names, from the view of \s-1SQL.\s0 -.PP -\fIAdditional methods\fR -.IX Subsection "Additional methods" -.PP -The following methods are only available via their documented name when -DBI::DBD::SQlEngine is used directly. Because this is only reasonable for -testing purposes, the real names must be used instead. Those names can be -computed by replacing the \f(CW\*(C`sql_\*(C'\fR in the method name with the driver prefix. -.PP -sql_versions -.IX Subsection "sql_versions" -.PP -Signature: -.PP -.Vb 5 -\& sub sql_versions (;$) { -\& my ($table_name) = @_; -\& $table_name ||= "."; -\& ... -\& } -.Ve -.PP -Returns the versions of the driver, including the \s-1DBI\s0 version, the Perl -version, DBI::PurePerl version (if DBI::PurePerl is active) and the version -of the \s-1SQL\s0 engine in use. -.PP -.Vb 8 -\& my $dbh = DBI\->connect ("dbi:File:"); -\& my $sql_versions = $dbh\->func( "sql_versions" ); -\& print "$sql_versions\en"; -\& _\|_END_\|_ -\& # DBI::DBD::SqlEngine 0.05 using SQL::Statement 1.402 -\& # DBI 1.623 -\& # OS netbsd (6.99.12) -\& # Perl 5.016002 (x86_64\-netbsd\-thread\-multi) -.Ve -.PP -Called in list context, sql_versions will return an array containing each -line as single entry. -.PP -Some drivers might use the optional (table name) argument and modify -version information related to the table (e.g. \s-1DBD::DBM\s0 provides storage -backend information for the requested table, when it has a table name). -.PP -sql_get_meta -.IX Subsection "sql_get_meta" -.PP -Signature: -.PP -.Vb 5 -\& sub sql_get_meta ($$) -\& { -\& my ($table_name, $attrib) = @_; -\& ... -\& } -.Ve -.PP -Returns the value of a meta attribute set for a specific table, if any. -See sql_meta for the possible attributes. -.PP -A table name of \f(CW"."\fR (single dot) is interpreted as the default table. -This will retrieve the appropriate attribute globally from the dbh. -This has the same restrictions as \f(CW\*(C`$dbh\->{$attrib}\*(C'\fR. -.PP -sql_set_meta -.IX Subsection "sql_set_meta" -.PP -Signature: -.PP -.Vb 5 -\& sub sql_set_meta ($$$) -\& { -\& my ($table_name, $attrib, $value) = @_; -\& ... -\& } -.Ve -.PP -Sets the value of a meta attribute set for a specific table. -See sql_meta for the possible attributes. -.PP -A table name of \f(CW"."\fR (single dot) is interpreted as the default table -which will set the specified attribute globally for the dbh. -This has the same restrictions as \f(CW\*(C`$dbh\->{$attrib} = $value\*(C'\fR. -.PP -sql_clear_meta -.IX Subsection "sql_clear_meta" -.PP -Signature: -.PP -.Vb 5 -\& sub sql_clear_meta ($) -\& { -\& my ($table_name) = @_; -\& ... -\& } -.Ve -.PP -Clears the table specific meta information in the private storage of the -dbh. -.SS "Extensibility" -.IX Subsection "Extensibility" -\fIDBI::DBD::SqlEngine::TableSource\fR -.IX Subsection "DBI::DBD::SqlEngine::TableSource" -.PP -Provides data sources and table information on database driver and database -handle level. -.PP -.Vb 1 -\& package DBI::DBD::SqlEngine::TableSource; -\& -\& sub data_sources ($;$) -\& { -\& my ( $class, $drh, $attrs ) = @_; -\& ... -\& } -\& -\& sub avail_tables -\& { -\& my ( $class, $drh ) = @_; -\& ... -\& } -.Ve -.PP -The \f(CW\*(C`data_sources\*(C'\fR method is called when the user invokes any of the -following: -.PP -.Vb 2 -\& @ary = DBI\->data_sources($driver); -\& @ary = DBI\->data_sources($driver, \e%attr); -\& -\& @ary = $dbh\->data_sources(); -\& @ary = $dbh\->data_sources(\e%attr); -.Ve -.PP -The \f(CW\*(C`avail_tables\*(C'\fR method is called when the user invokes any of the -following: -.PP -.Vb 1 -\& @names = $dbh\->tables( $catalog, $schema, $table, $type ); -\& -\& $sth = $dbh\->table_info( $catalog, $schema, $table, $type ); -\& $sth = $dbh\->table_info( $catalog, $schema, $table, $type, \e%attr ); -\& -\& $dbh\->func( "list_tables" ); -.Ve -.PP -Every time where an \f(CW\*(C`\e%attr\*(C'\fR argument can be specified, this \f(CW\*(C`\e%attr\*(C'\fR -object's \f(CW\*(C`sql_table_source\*(C'\fR attribute is preferred over the \f(CW$dbh\fR -attribute or the driver default, eg. -.PP -.Vb 6 -\& @ary = DBI\->data_sources("dbi:CSV:", { -\& f_dir => "/your/csv/tables", -\& # note: this class doesn\*(Aqt comes with DBI -\& sql_table_source => "DBD::File::Archive::Tar::TableSource", -\& # scan tarballs instead of directories -\& }); -.Ve -.PP -When you're going to implement such a DBD::File::Archive::Tar::TableSource -class, remember to add correct attributes (including \f(CW\*(C`sql_table_source\*(C'\fR -and \f(CW\*(C`sql_data_source\*(C'\fR) to the returned \s-1DSN\s0's. -.PP -\fIDBI::DBD::SqlEngine::DataSource\fR -.IX Subsection "DBI::DBD::SqlEngine::DataSource" -.PP -Provides base functionality for dealing with tables. It is primarily -designed for allowing transparent access to files on disk or already -opened (file\-)streams (eg. for \s-1DBD::CSV\s0). -.PP -Derived classes shall be restricted to similar functionality, too (eg. -opening streams from an archive, transparently compress/uncompress -log files before parsing them, -.PP -.Vb 1 -\& package DBI::DBD::SqlEngine::DataSource; -\& -\& sub complete_table_name ($$;$) -\& { -\& my ( $self, $meta, $table, $respect_case ) = @_; -\& ... -\& } -.Ve -.PP -The method \f(CW\*(C`complete_table_name\*(C'\fR is called when first setting up the -\&\fImeta information\fR for a table: -.PP -.Vb 1 -\& "SELECT user.id, user.name, user.shell FROM user WHERE ..." -.Ve -.PP -results in opening the table \f(CW\*(C`user\*(C'\fR. First step of the table open -process is completing the name. Let's imagine you're having a \s-1DBD::CSV\s0 -handle with following settings: -.PP -.Vb 3 -\& $dbh\->{sql_identifier_case} = SQL_IC_LOWER; -\& $dbh\->{f_ext} = \*(Aq.lst\*(Aq; -\& $dbh\->{f_dir} = \*(Aq/data/web/adrmgr\*(Aq; -.Ve -.PP -Those settings will result in looking for files matching -\&\f(CW\*(C`[Uu][Ss][Ee][Rr](\e.lst)?$\*(C'\fR in \f(CW\*(C`/data/web/adrmgr/\*(C'\fR. The scanning of the -directory \f(CW\*(C`/data/web/adrmgr/\*(C'\fR and the pattern match check will be done -in \f(CW\*(C`DBD::File::DataSource::File\*(C'\fR by the \f(CW\*(C`complete_table_name\*(C'\fR method. -.PP -If you intend to provide other sources of data streams than files, in -addition to provide an appropriate \f(CW\*(C`complete_table_name\*(C'\fR method, a method -to open the resource is required: -.PP -.Vb 1 -\& package DBI::DBD::SqlEngine::DataSource; -\& -\& sub open_data ($) -\& { -\& my ( $self, $meta, $attrs, $flags ) = @_; -\& ... -\& } -.Ve -.PP -After the method \f(CW\*(C`open_data\*(C'\fR has been run successfully, the table's meta -information are in a state which allowes the table's data accessor methods -will be able to fetch/store row information. Implementation details heavily -depends on the table implementation, whereby the most famous is surely -DBD::File::Table. -.SH "SQL ENGINES" -.IX Header "SQL ENGINES" -DBI::DBD::SqlEngine currently supports two \s-1SQL\s0 engines: -SQL::Statement and -DBI::SQL::Nano::Statement_. DBI::SQL::Nano supports a -\&\fIvery\fR limited subset of \s-1SQL\s0 statements, but it might be faster for some -very simple tasks. SQL::Statement in contrast supports a much larger subset -of \s-1ANSI SQL.\s0 -.PP -To use SQL::Statement, you need at least version 1.401 of -SQL::Statement and the environment variable \f(CW\*(C`DBI_SQL_NANO\*(C'\fR must not -be set to a true value. -.SH "SUPPORT" -.IX Header "SUPPORT" -You can find documentation for this module with the perldoc command. -.PP -.Vb 1 -\& perldoc DBI::DBD::SqlEngine -.Ve -.PP -You can also look for information at: -.IP "\(bu" 4 -\&\s-1RT: CPAN\s0's request tracker -.Sp - - -.IP "\(bu" 4 -AnnoCPAN: Annotated \s-1CPAN\s0 documentation -.Sp - - -.IP "\(bu" 4 -\&\s-1CPAN\s0 Ratings -.Sp - -.IP "\(bu" 4 -Search \s-1CPAN\s0 -.Sp - -.SS "Where can I go for more help?" -.IX Subsection "Where can I go for more help?" -For questions about installation or usage, please ask on the -dbi\-dev@perl.org mailing list. -.PP -If you have a bug report, patch or suggestion, please open -a new report ticket on \s-1CPAN,\s0 if there is not already one for -the issue you want to report. Of course, you can mail any of the -module maintainers, but it is less likely to be missed if -it is reported on \s-1RT.\s0 -.PP -Report tickets should contain a detailed description of the bug or -enhancement request you want to report and at least an easy way to -verify/reproduce the issue and any supplied fix. Patches are always -welcome, too. -.SH "ACKNOWLEDGEMENTS" -.IX Header "ACKNOWLEDGEMENTS" -Thanks to Tim Bunce, Martin Evans and H.Merijn Brand for their continued -support while developing DBD::File, \s-1DBD::DBM\s0 and DBD::AnyData. -Their support, hints and feedback helped to design and implement this -module. -.SH "AUTHOR" -.IX Header "AUTHOR" -This module is currently maintained by -.PP -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > -.PP -The original authors are Jochen Wiedmann and Jeff Zucker. -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -.Vb 3 -\& Copyright (C) 2009\-2013 by H.Merijn Brand & Jens Rehsack -\& Copyright (C) 2004\-2009 by Jeff Zucker -\& Copyright (C) 1998\-2004 by Jochen Wiedmann -.Ve -.PP -All rights reserved. -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as -specified in the Perl \s-1README\s0 file. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -\&\s-1DBI\s0, DBD::File, DBD::AnyData and DBD::Sys. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine::Developers.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine::Developers.3pm deleted file mode 100644 index ada1a24..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine::Developers.3pm +++ /dev/null @@ -1,896 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::DBD::SqlEngine::Developers 3pm" -.TH DBI::DBD::SqlEngine::Developers 3pm "2016-04-21" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::DBD::SqlEngine::Developers \- Developers documentation for DBI::DBD::SqlEngine -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& package DBD::myDriver; -\& -\& use base qw(DBI::DBD::SqlEngine); -\& -\& sub driver -\& { -\& ... -\& my $drh = $proto\->SUPER::driver($attr); -\& ... -\& return $drh\->{class}; -\& } -\& -\& sub CLONE { ... } -\& -\& package DBD::myDriver::dr; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::dr); -\& -\& sub data_sources { ... } -\& ... -\& -\& package DBD::myDriver::db; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::db); -\& -\& sub init_valid_attributes { ... } -\& sub init_default_attributes { ... } -\& sub set_versions { ... } -\& sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } -\& sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } -\& sub get_myd_versions { ... } -\& sub get_avail_tables { ... } -\& -\& package DBD::myDriver::st; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::st); -\& -\& sub FETCH { ... } -\& sub STORE { ... } -\& -\& package DBD::myDriver::Statement; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::Statement); -\& -\& sub open_table { ... } -\& -\& package DBD::myDriver::Table; -\& -\& @ISA = qw(DBI::DBD::SqlEngine::Table); -\& -\& my %reset_on_modify = ( -\& myd_abc => "myd_foo", -\& myd_mno => "myd_bar", -\& ); -\& _\|_PACKAGE_\|_\->register_reset_on_modify( \e%reset_on_modify ); -\& my %compat_map = ( -\& abc => \*(Aqfoo_abc\*(Aq, -\& xyz => \*(Aqfoo_xyz\*(Aq, -\& ); -\& _\|_PACKAGE_\|_\->register_compat_map( \e%compat_map ); -\& -\& sub bootstrap_table_meta { ... } -\& sub init_table_meta { ... } -\& sub table_meta_attr_changed { ... } -\& sub open_data { ... } -\& -\& sub new { ... } -\& -\& sub fetch_row { ... } -\& sub push_row { ... } -\& sub push_names { ... } -\& sub seek { ... } -\& sub truncate { ... } -\& sub drop { ... } -\& -\& # optimize the SQL engine by add one or more of -\& sub update_current_row { ... } -\& # or -\& sub update_specific_row { ... } -\& # or -\& sub update_one_row { ... } -\& # or -\& sub insert_new_row { ... } -\& # or -\& sub delete_current_row { ... } -\& # or -\& sub delete_one_row { ... } -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This document describes the interface of DBI::DBD::SqlEngine for \s-1DBD\s0 -developers who write DBI::DBD::SqlEngine based \s-1DBI\s0 drivers. It supplements -\&\s-1DBI::DBD\s0 and DBI::DBD::SqlEngine::HowTo, which you should read first. -.SH "CLASSES" -.IX Header "CLASSES" -Each \s-1DBI\s0 driver must provide a package global \f(CW\*(C`driver\*(C'\fR method and -three \s-1DBI\s0 related classes: -.IP "DBI::DBD::SqlEngine::dr" 4 -.IX Item "DBI::DBD::SqlEngine::dr" -Driver package, contains the methods \s-1DBI\s0 calls indirectly via \s-1DBI\s0 -interface: -.Sp -.Vb 1 -\& DBI\->connect (\*(AqDBI:DBM:\*(Aq, undef, undef, {}) -\& -\& # invokes -\& package DBD::DBM::dr; -\& @DBD::DBM::dr::ISA = qw(DBI::DBD::SqlEngine::dr); -\& -\& sub connect ($$;$$$) -\& { -\& ... -\& } -.Ve -.Sp -Similar for \f(CW\*(C`data_sources ()\*(C'\fR and \f(CW\*(C`disconnect_all()\*(C'\fR. -.Sp -Pure Perl \s-1DBI\s0 drivers derived from DBI::DBD::SqlEngine usually don't need to -override any of the methods provided through the DBD::XXX::dr package. -However if you need additional initialization not fitting in -\&\f(CW\*(C`init_valid_attributes()\*(C'\fR and \f(CW\*(C`init_default_attributes()\*(C'\fR of you're ::db -class, the connect method might be the final place to be modified. -.IP "DBI::DBD::SqlEngine::db" 4 -.IX Item "DBI::DBD::SqlEngine::db" -Contains the methods which are called through \s-1DBI\s0 database handles -(\f(CW$dbh\fR). e.g., -.Sp -.Vb 3 -\& $sth = $dbh\->prepare ("select * from foo"); -\& # returns the f_encoding setting for table foo -\& $dbh\->csv_get_meta ("foo", "f_encoding"); -.Ve -.Sp -DBI::DBD::SqlEngine provides the typical methods required here. Developers who -write \s-1DBI\s0 drivers based on DBI::DBD::SqlEngine need to override the methods -\&\f(CW\*(C`set_versions\*(C'\fR and \f(CW\*(C`init_valid_attributes\*(C'\fR. -.IP "DBI::DBD::SqlEngine::TieMeta;" 4 -.IX Item "DBI::DBD::SqlEngine::TieMeta;" -Provides the tie-magic for \f(CW\*(C`$dbh\->{$drv_pfx . "_meta"}\*(C'\fR. Routes -\&\f(CW\*(C`STORE\*(C'\fR through \f(CW\*(C`$drv\->set_sql_engine_meta()\*(C'\fR and \f(CW\*(C`FETCH\*(C'\fR through -\&\f(CW\*(C`$drv\->get_sql_engine_meta()\*(C'\fR. \f(CW\*(C`DELETE\*(C'\fR is not supported, you have -to execute a \f(CW\*(C`DROP TABLE\*(C'\fR statement, where applicable. -.IP "DBI::DBD::SqlEngine::TieTables;" 4 -.IX Item "DBI::DBD::SqlEngine::TieTables;" -Provides the tie-magic for tables in \f(CW\*(C`$dbh\->{$drv_pfx . "_meta"}\*(C'\fR. -Routes \f(CW\*(C`STORE\*(C'\fR though \f(CW\*(C`$tblClass\->set_table_meta_attr()\*(C'\fR and \f(CW\*(C`FETCH\*(C'\fR -though \f(CW\*(C`$tblClass\->get_table_meta_attr()\*(C'\fR. \f(CW\*(C`DELETE\*(C'\fR removes an -attribute from the \fImeta object\fR retrieved by -\&\f(CW\*(C`$tblClass\->get_table_meta()\*(C'\fR. -.IP "DBI::DBD::SqlEngine::st" 4 -.IX Item "DBI::DBD::SqlEngine::st" -Contains the methods to deal with prepared statement handles. e.g., -.Sp -.Vb 1 -\& $sth\->execute () or die $sth\->errstr; -.Ve -.IP "DBI::DBD::SqlEngine::TableSource;" 4 -.IX Item "DBI::DBD::SqlEngine::TableSource;" -Base class for 3rd party table sources: -.Sp -.Vb 1 -\& $dbh\->{sql_table_source} = "DBD::Foo::TableSource"; -.Ve -.IP "DBI::DBD::SqlEngine::DataSource;" 4 -.IX Item "DBI::DBD::SqlEngine::DataSource;" -Base class for 3rd party data sources: -.Sp -.Vb 1 -\& $dbh\->{sql_data_source} = "DBD::Foo::DataSource"; -.Ve -.IP "DBI::DBD::SqlEngine::Statement;" 4 -.IX Item "DBI::DBD::SqlEngine::Statement;" -Base class for derived drivers statement engine. Implements \f(CW\*(C`open_table\*(C'\fR. -.IP "DBI::DBD::SqlEngine::Table;" 4 -.IX Item "DBI::DBD::SqlEngine::Table;" -Contains tailoring between \s-1SQL\s0 engine's requirements and -\&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR magic for finding the right tables and storage. -Builds bridges between \f(CW\*(C`sql_meta\*(C'\fR handling of \f(CW\*(C`DBI::DBD::SqlEngine::db\*(C'\fR, -table initialization for \s-1SQL\s0 engines and \fImeta object\fR's attribute -management for derived drivers. -.SS "DBI::DBD::SqlEngine" -.IX Subsection "DBI::DBD::SqlEngine" -This is the main package containing the routines to initialize -DBI::DBD::SqlEngine based \s-1DBI\s0 drivers. Primarily the -\&\f(CW\*(C`DBI::DBD::SqlEngine::driver\*(C'\fR method is invoked, either directly -from \s-1DBI\s0 when the driver is initialized or from the derived class. -.PP -.Vb 1 -\& package DBD::DBM; -\& -\& use base qw( DBI::DBD::SqlEngine ); -\& -\& sub driver -\& { -\& my ( $class, $attr ) = @_; -\& ... -\& my $drh = $class\->SUPER::driver( $attr ); -\& ... -\& return $drh; -\& } -.Ve -.PP -It is not necessary to implement your own driver method as long as -additional initialization (e.g. installing more private driver -methods) is not required. You do not need to call \f(CW\*(C`setup_driver\*(C'\fR -as DBI::DBD::SqlEngine takes care of it. -.SS "DBI::DBD::SqlEngine::dr" -.IX Subsection "DBI::DBD::SqlEngine::dr" -The driver package contains the methods \s-1DBI\s0 calls indirectly via the \s-1DBI\s0 -interface (see \*(L"\s-1DBI\s0 Class Methods\*(R" in \s-1DBI\s0). -.PP -DBI::DBD::SqlEngine based \s-1DBI\s0 drivers usually do not need to implement anything here, -it is enough to do the basic initialization: -.PP -.Vb 1 -\& package DBD:XXX::dr; -\& -\& @DBD::XXX::dr::ISA = qw (DBI::DBD::SqlEngine::dr); -\& $DBD::XXX::dr::imp_data_size = 0; -\& $DBD::XXX::dr::data_sources_attr = undef; -\& $DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann"; -.Ve -.PP -\fIMethods provided by \f(CI\*(C`DBI::DBD::SqlEngine::dr\*(C'\fI:\fR -.IX Subsection "Methods provided by DBI::DBD::SqlEngine::dr:" -.IP "connect" 4 -.IX Item "connect" -Supervises the driver bootstrap when calling -.Sp -.Vb 1 -\& DBI\->connect( "dbi:Foo", , , { ... } ); -.Ve -.Sp -First it instantiates a new driver using \f(CW\*(C`DBI::_new_dbh\*(C'\fR. After that, -initial bootstrap of the newly instantiated driver is done by -.Sp -.Vb 1 -\& $dbh\->func( 0, "init_default_attributes" ); -.Ve -.Sp -The first argument (\f(CW0\fR) signals that this is the very first call to -\&\f(CW\*(C`init_default_attributes\*(C'\fR. Modern drivers understand that and do early -stage setup here after calling -.Sp -.Vb 2 -\& package DBD::Foo::db; -\& our @DBD::Foo::db::ISA = qw(DBI::DBD::SqlEngine::db); -\& -\& sub init_default_attributes -\& { -\& my ($dbh, $phase) = @_; -\& $dbh\->SUPER::init_default_attributes($phase); -\& ...; # own setup code, maybe separated by phases -\& } -.Ve -.Sp -When the \f(CW$phase\fR argument is passed down until -\&\f(CW\*(C`DBI::DBD::SqlEngine::db::init_default_attributes\*(C'\fR, \f(CW\*(C`connect()\*(C'\fR recognizes -a \fImodern\fR driver and initializes the attributes from \fI\s-1DSN\s0\fR and \fI\f(CI$attr\fI\fR -arguments passed via \f(CW\*(C`DBI\->connect( $dsn, $user, $pass, \e%attr )\*(C'\fR. -.Sp -At the end of the attribute initialization after \fIphase 0\fR, \f(CW\*(C`connect()\*(C'\fR -invoked \f(CW\*(C`init_default_attributes\*(C'\fR again for \fIphase 1\fR: -.Sp -.Vb 1 -\& $dbh\->func( 1, "init_default_attributes" ); -.Ve -.IP "data_sources" 4 -.IX Item "data_sources" -Returns a list of \fI\s-1DSN\s0\fR's using the \f(CW\*(C`data_sources\*(C'\fR method of the -class specified in \f(CW\*(C`$dbh\->{sql_table_source}\*(C'\fR or via \f(CW\*(C`\e%attr\*(C'\fR: -.Sp -.Vb 2 -\& @ary = DBI\->data_sources($driver); -\& @ary = DBI\->data_sources($driver, \e%attr); -.Ve -.IP "disconnect_all" 4 -.IX Item "disconnect_all" -\&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR doesn't have an overall driver cache, so nothing -happens here at all. -.SS "DBI::DBD::SqlEngine::db" -.IX Subsection "DBI::DBD::SqlEngine::db" -This package defines the database methods, which are called via the \s-1DBI\s0 -database handle \f(CW$dbh\fR. -.PP -\fIMethods provided by \f(CI\*(C`DBI::DBD::SqlEngine::db\*(C'\fI:\fR -.IX Subsection "Methods provided by DBI::DBD::SqlEngine::db:" -.IP "ping" 4 -.IX Item "ping" -Simply returns the content of the \f(CW\*(C`Active\*(C'\fR attribute. Override -when your driver needs more complicated actions here. -.IP "prepare" 4 -.IX Item "prepare" -Prepares a new \s-1SQL\s0 statement to execute. Returns a statement handle, -\&\f(CW$sth\fR \- instance of the DBD:XXX::st. It is neither required nor -recommended to override this method. -.IP "validate_FETCH_attr" 4 -.IX Item "validate_FETCH_attr" -Called by \f(CW\*(C`FETCH\*(C'\fR to allow inherited drivers do their own attribute -name validation. Calling convention is similar to \f(CW\*(C`FETCH\*(C'\fR and the -return value is the approved attribute name. -.Sp -.Vb 1 -\& return $validated_attribute_name; -.Ve -.Sp -In case of validation fails (e.g. accessing private attribute or similar), -\&\f(CW\*(C`validate_FETCH_attr\*(C'\fR is permitted to throw an exception. -.IP "\s-1FETCH\s0" 4 -.IX Item "FETCH" -Fetches an attribute of a \s-1DBI\s0 database object. Private handle attributes -must have a prefix (this is mandatory). If a requested attribute is -detected as a private attribute without a valid prefix, the driver prefix -(written as \f(CW$drv_prefix\fR) is added. -.Sp -The driver prefix is extracted from the attribute name and verified against -\&\f(CW\*(C`$dbh\->{ $drv_prefix . "valid_attrs" }\*(C'\fR (when it exists). If the -requested attribute value is not listed as a valid attribute, this method -croaks. If the attribute is valid and readonly (listed in \f(CW\*(C`$dbh\->{ -$drv_prefix . "readonly_attrs" }\*(C'\fR when it exists), a real copy of the -attribute value is returned. So it's not possible to modify -\&\f(CW\*(C`f_valid_attrs\*(C'\fR from outside of DBI::DBD::SqlEngine::db or a derived class. -.IP "validate_STORE_attr" 4 -.IX Item "validate_STORE_attr" -Called by \f(CW\*(C`STORE\*(C'\fR to allow inherited drivers do their own attribute -name validation. Calling convention is similar to \f(CW\*(C`STORE\*(C'\fR and the -return value is the approved attribute name followed by the approved -new value. -.Sp -.Vb 1 -\& return ($validated_attribute_name, $validated_attribute_value); -.Ve -.Sp -In case of validation fails (e.g. accessing private attribute or similar), -\&\f(CW\*(C`validate_STORE_attr\*(C'\fR is permitted to throw an exception -(\f(CW\*(C`DBI::DBD::SqlEngine::db::validate_STORE_attr\*(C'\fR throws an exception when -someone tries to assign value other than \f(CW\*(C`SQL_IC_UPPER .. SQL_IC_MIXED\*(C'\fR -to \f(CW\*(C`$dbh\->{sql_identifier_case}\*(C'\fR or -\&\f(CW\*(C`$dbh\->{sql_quoted_identifier_case}\*(C'\fR). -.IP "\s-1STORE\s0" 4 -.IX Item "STORE" -Stores a database private attribute. Private handle attributes must have a -prefix (this is mandatory). If a requested attribute is detected as a private -attribute without a valid prefix, the driver prefix (written as -\&\f(CW$drv_prefix\fR) is added. If the database handle has an attribute -\&\f(CW\*(C`${drv_prefix}_valid_attrs\*(C'\fR \- for attribute names which are not listed in -that hash, this method croaks. If the database handle has an attribute -\&\f(CW\*(C`${drv_prefix}_readonly_attrs\*(C'\fR, only attributes which are not listed there -can be stored (once they are initialized). Trying to overwrite such an -immutable attribute forces this method to croak. -.Sp -An example of a valid attributes list can be found in -\&\f(CW\*(C`DBI::DBD::SqlEngine::db::init_valid_attributes\*(C'\fR. -.IP "set_versions" 4 -.IX Item "set_versions" -This method sets the attributes \f(CW\*(C`f_version\*(C'\fR, \f(CW\*(C`sql_nano_version\*(C'\fR, -\&\f(CW\*(C`sql_statement_version\*(C'\fR and (if not prohibited by a restrictive -\&\f(CW\*(C`${prefix}_valid_attrs\*(C'\fR) \f(CW\*(C`${prefix}_version\*(C'\fR. -.Sp -This method is called at the end of the \f(CW\*(C`connect ()\*(C'\fR phase. -.Sp -When overriding this method, do not forget to invoke the superior one. -.IP "init_valid_attributes" 4 -.IX Item "init_valid_attributes" -This method is called after the database handle is instantiated as the -first attribute initialization. -.Sp -\&\f(CW\*(C`DBI::DBD::SqlEngine::db::init_valid_attributes\*(C'\fR initializes the -attributes \f(CW\*(C`sql_valid_attrs\*(C'\fR and \f(CW\*(C`sql_readonly_attrs\*(C'\fR. -.Sp -When overriding this method, do not forget to invoke the superior one, -preferably before doing anything else. -.IP "init_default_attributes" 4 -.IX Item "init_default_attributes" -This method is called after the database handle is instantiated to -initialize the default attributes. It expects one argument: \f(CW$phase\fR. -If \f(CW$phase\fR is not given, \f(CW\*(C`connect\*(C'\fR of \f(CW\*(C`DBI::DBD::SqlEngine::dr\*(C'\fR -expects this is an old-fashioned driver which isn't capable of multi-phased -initialization. -.Sp -\&\f(CW\*(C`DBI::DBD::SqlEngine::db::init_default_attributes\*(C'\fR initializes the -attributes \f(CW\*(C`sql_identifier_case\*(C'\fR, \f(CW\*(C`sql_quoted_identifier_case\*(C'\fR, -\&\f(CW\*(C`sql_handler\*(C'\fR, \f(CW\*(C`sql_init_order\*(C'\fR, \f(CW\*(C`sql_meta\*(C'\fR, \f(CW\*(C`sql_engine_version\*(C'\fR, -\&\f(CW\*(C`sql_nano_version\*(C'\fR and \f(CW\*(C`sql_statement_version\*(C'\fR when SQL::Statement -is available. -.Sp -It sets \f(CW\*(C`sql_init_order\*(C'\fR to the given \f(CW$phase\fR. -.Sp -When the derived implementor class provides the attribute to validate -attributes (e.g. \f(CW\*(C`$dbh\->{dbm_valid_attrs} = {...};\*(C'\fR) or the attribute -containing the immutable attributes (e.g. \f(CW\*(C`$dbh\->{dbm_readonly_attrs} -= {...};\*(C'\fR), the attributes \f(CW\*(C`drv_valid_attrs\*(C'\fR, \f(CW\*(C`drv_readonly_attrs\*(C'\fR and -\&\f(CW\*(C`drv_version\*(C'\fR are added (when available) to the list of valid and -immutable attributes (where \f(CW\*(C`drv_\*(C'\fR is interpreted as the driver prefix). -.IP "get_versions" 4 -.IX Item "get_versions" -This method is called by the code injected into the instantiated driver to -provide the user callable driver method \f(CW\*(C`${prefix}versions\*(C'\fR (e.g. -\&\f(CW\*(C`dbm_versions\*(C'\fR, \f(CW\*(C`csv_versions\*(C'\fR, ...). -.Sp -The DBI::DBD::SqlEngine implementation returns all version information known by -DBI::DBD::SqlEngine (e.g. \s-1DBI\s0 version, Perl version, DBI::DBD::SqlEngine version and -the \s-1SQL\s0 handler version). -.Sp -\&\f(CW\*(C`get_versions\*(C'\fR takes the \f(CW$dbh\fR as the first argument and optionally a -second argument containing a table name. The second argument is not -evaluated in \f(CW\*(C`DBI::DBD::SqlEngine::db::get_versions\*(C'\fR itself \- but -might be in the future. -.Sp -If the derived implementor class provides a method named -\&\f(CW\*(C`get_${drv_prefix}versions\*(C'\fR, this is invoked and the return value of -it is associated to the derived driver name: -.Sp -.Vb 4 -\& if (my $dgv = $dbh\->{ImplementorClass}\->can ("get_" . $drv_prefix . "versions") { -\& (my $derived_driver = $dbh\->{ImplementorClass}) =~ s/::db$//; -\& $versions{$derived_driver} = &$dgv ($dbh, $table); -\& } -.Ve -.Sp -Override it to add more version information about your module, (e.g. -some kind of parser version in case of \s-1DBD::CSV, ...\s0), if one line is not -enough room to provide all relevant information. -.IP "sql_parser_object" 4 -.IX Item "sql_parser_object" -Returns a SQL::Parser instance, when \f(CW\*(C`sql_handler\*(C'\fR is set to -\&\*(L"SQL::Statement\*(R". The parser instance is stored in \f(CW\*(C`sql_parser_object\*(C'\fR. -.Sp -It is not recommended to override this method. -.IP "disconnect" 4 -.IX Item "disconnect" -Disconnects from a database. All local table information is discarded and -the \f(CW\*(C`Active\*(C'\fR attribute is set to 0. -.IP "type_info_all" 4 -.IX Item "type_info_all" -Returns information about all the types supported by DBI::DBD::SqlEngine. -.IP "table_info" 4 -.IX Item "table_info" -Returns a statement handle which is prepared to deliver information about -all known tables. -.IP "list_tables" 4 -.IX Item "list_tables" -Returns a list of all known table names. -.IP "quote" 4 -.IX Item "quote" -Quotes a string for use in \s-1SQL\s0 statements. -.IP "commit" 4 -.IX Item "commit" -Warns about a useless call (if warnings enabled) and returns. -DBI::DBD::SqlEngine is typically a driver which commits every action -instantly when executed. -.IP "rollback" 4 -.IX Item "rollback" -Warns about a useless call (if warnings enabled) and returns. -DBI::DBD::SqlEngine is typically a driver which commits every action -instantly when executed. -.PP -\fIAttributes used by \f(CI\*(C`DBI::DBD::SqlEngine::db\*(C'\fI:\fR -.IX Subsection "Attributes used by DBI::DBD::SqlEngine::db:" -.PP -This section describes attributes which are important to developers of \s-1DBI\s0 -Database Drivers derived from \f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR. -.IP "sql_init_order" 4 -.IX Item "sql_init_order" -This attribute contains a hash with priorities as key and an array -containing the \f(CW$dbh\fR attributes to be initialized during before/after -other attributes. -.Sp -\&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR initializes following attributes: -.Sp -.Vb 4 -\& $dbh\->{sql_init_order} = { -\& 0 => [qw( Profile RaiseError PrintError AutoCommit )], -\& 90 => [ "sql_meta", $dbh\->{$drv_pfx_meta} ? $dbh\->{$drv_pfx_meta} : () ] -\& } -.Ve -.Sp -The default priority of not listed attribute keys is \f(CW50\fR. It is well -known that a lot of attributes needed to be set before some table settings -are initialized. For example, for \s-1DBD::DBM\s0, when using -.Sp -.Vb 11 -\& my $dbh = DBI\->connect( "dbi:DBM:", undef, undef, { -\& f_dir => "/path/to/dbm/databases", -\& dbm_type => "BerkeleyDB", -\& dbm_mldbm => "JSON", # use MLDBM::Serializer::JSON -\& dbm_tables => { -\& quick => { -\& dbm_type => "GDBM_File", -\& dbm_MLDBM => "FreezeThaw" -\& } -\& } -\& }); -.Ve -.Sp -This defines a known table \f(CW\*(C`quick\*(C'\fR which uses the GDBM_File backend and -FreezeThaw as serializer instead of the overall default BerkeleyDB and -\&\s-1JSON\s0. \fBBut\fR all files containing the table data have to be searched in -\&\f(CW\*(C`$dbh\->{f_dir}\*(C'\fR, which requires \f(CW\*(C`$dbh\->{f_dir}\*(C'\fR must be initialized -before \f(CW\*(C`$dbh\->{sql_meta}\->{quick}\*(C'\fR is initialized by -\&\f(CW\*(C`bootstrap_table_meta\*(C'\fR method of \*(L"DBI::DBD::SqlEngine::Table\*(R" to get -\&\f(CW\*(C`$dbh\->{sql_meta}\->{quick}\->{f_dir}\*(C'\fR being initialized properly. -.IP "sql_init_phase" 4 -.IX Item "sql_init_phase" -This attribute is only set during the initialization steps of the \s-1DBI\s0 -Database Driver. It contains the value of the currently run initialization -phase. Currently supported phases are \fIphase 0\fR and \fIphase 1\fR. This -attribute is set in \f(CW\*(C`init_default_attributes\*(C'\fR and removed in \f(CW\*(C`init_done\*(C'\fR. -.IP "sql_engine_in_gofer" 4 -.IX Item "sql_engine_in_gofer" -This value has a true value in case of this driver is operated via -DBD::Gofer. The impact of being operated via Gofer is a read-only -driver (not read-only databases!), so you cannot modify any attributes -later \- neither any table settings. \fBBut\fR you won't get an error in -cases you modify table attributes, so please carefully watch -\&\f(CW\*(C`sql_engine_in_gofer\*(C'\fR. -.IP "sql_table_source" 4 -.IX Item "sql_table_source" -Names a class which is responsible for delivering \fIdata sources\fR and -\&\fIavailable tables\fR (Database Driver related). \fIdata sources\fR here -refers to \*(L"data_sources\*(R" in \s-1DBI\s0, not \f(CW\*(C`sql_data_source\*(C'\fR. -.Sp -See \*(L"DBI::DBD::SqlEngine::TableSource\*(R" for details. -.IP "sql_data_source" 4 -.IX Item "sql_data_source" -Name a class which is responsible for handling table resources open -and completing table names requested via \s-1SQL\s0 statements. -.Sp -See \*(L"DBI::DBD::SqlEngine::DataSource\*(R" for details. -.IP "sql_dialect" 4 -.IX Item "sql_dialect" -Controls the dialect understood by SQL::Parser. Possible values (delivery -state of SQL::Statement): -.Sp -.Vb 3 -\& * ANSI -\& * CSV -\& * AnyData -.Ve -.Sp -Defaults to \*(L"\s-1CSV\*(R". \s0 Because an SQL::Parser is instantiated only once and -SQL::Parser doesn't allow one to modify the dialect once instantiated, -it's strongly recommended to set this flag before any statement is -executed (best place is connect attribute hash). -.SS "DBI::DBD::SqlEngine::st" -.IX Subsection "DBI::DBD::SqlEngine::st" -Contains the methods to deal with prepared statement handles: -.IP "bind_param" 4 -.IX Item "bind_param" -Common routine to bind placeholders to a statement for execution. It -is dangerous to override this method without detailed knowledge about -the DBI::DBD::SqlEngine internal storage structure. -.IP "execute" 4 -.IX Item "execute" -Executes a previously prepared statement (with placeholders, if any). -.IP "finish" 4 -.IX Item "finish" -Finishes a statement handle, discards all buffered results. The prepared -statement is not discarded so the statement can be executed again. -.IP "fetch" 4 -.IX Item "fetch" -Fetches the next row from the result-set. This method may be rewritten -in a later version and if it's overridden in a derived class, the -derived implementation should not rely on the storage details. -.IP "fetchrow_arrayref" 4 -.IX Item "fetchrow_arrayref" -Alias for \f(CW\*(C`fetch\*(C'\fR. -.IP "\s-1FETCH\s0" 4 -.IX Item "FETCH" -Fetches statement handle attributes. Supported attributes (for full overview -see \*(L"Statement Handle Attributes\*(R" in \s-1DBI\s0) are \f(CW\*(C`NAME\*(C'\fR, \f(CW\*(C`TYPE\*(C'\fR, \f(CW\*(C`PRECISION\*(C'\fR -and \f(CW\*(C`NULLABLE\*(C'\fR. Each column is returned as \f(CW\*(C`NULLABLE\*(C'\fR which might be wrong -depending on the derived backend storage. If the statement handle has -private attributes, they can be fetched using this method, too. \fBNote\fR that -statement attributes are not associated with any table used in this statement. -.Sp -This method usually requires extending in a derived implementation. -See \s-1DBD::CSV\s0 or \s-1DBD::DBM\s0 for some example. -.IP "\s-1STORE\s0" 4 -.IX Item "STORE" -Allows storing of statement private attributes. No special handling is -currently implemented here. -.IP "rows" 4 -.IX Item "rows" -Returns the number of rows affected by the last execute. This method might -return \f(CW\*(C`undef\*(C'\fR. -.SS "DBI::DBD::SqlEngine::TableSource" -.IX Subsection "DBI::DBD::SqlEngine::TableSource" -Provides data sources and table information on database driver and database -handle level. -.PP -.Vb 1 -\& package DBI::DBD::SqlEngine::TableSource; -\& -\& sub data_sources ($;$) -\& { -\& my ( $class, $drh, $attrs ) = @_; -\& ... -\& } -\& -\& sub avail_tables -\& { -\& my ( $class, $drh ) = @_; -\& ... -\& } -.Ve -.PP -The \f(CW\*(C`data_sources\*(C'\fR method is called when the user invokes any of the -following: -.PP -.Vb 2 -\& @ary = DBI\->data_sources($driver); -\& @ary = DBI\->data_sources($driver, \e%attr); -\& -\& @ary = $dbh\->data_sources(); -\& @ary = $dbh\->data_sources(\e%attr); -.Ve -.PP -The \f(CW\*(C`avail_tables\*(C'\fR method is called when the user invokes any of the -following: -.PP -.Vb 1 -\& @names = $dbh\->tables( $catalog, $schema, $table, $type ); -\& -\& $sth = $dbh\->table_info( $catalog, $schema, $table, $type ); -\& $sth = $dbh\->table_info( $catalog, $schema, $table, $type, \e%attr ); -\& -\& $dbh\->func( "list_tables" ); -.Ve -.PP -Every time where an \f(CW\*(C`\e%attr\*(C'\fR argument can be specified, this \f(CW\*(C`\e%attr\*(C'\fR -object's \f(CW\*(C`sql_table_source\*(C'\fR attribute is preferred over the \f(CW$dbh\fR -attribute or the driver default. -.SS "DBI::DBD::SqlEngine::DataSource" -.IX Subsection "DBI::DBD::SqlEngine::DataSource" -Provides base functionality for dealing with tables. It is primarily -designed for allowing transparent access to files on disk or already -opened (file\-)streams (e.g. for \s-1DBD::CSV\s0). -.PP -Derived classes shall be restricted to similar functionality, too (e.g. -opening streams from an archive, transparently compress/uncompress -log files before parsing them, -.PP -.Vb 1 -\& package DBI::DBD::SqlEngine::DataSource; -\& -\& sub complete_table_name ($$;$) -\& { -\& my ( $self, $meta, $table, $respect_case ) = @_; -\& ... -\& } -.Ve -.PP -The method \f(CW\*(C`complete_table_name\*(C'\fR is called when first setting up the -\&\fImeta information\fR for a table: -.PP -.Vb 1 -\& "SELECT user.id, user.name, user.shell FROM user WHERE ..." -.Ve -.PP -results in opening the table \f(CW\*(C`user\*(C'\fR. First step of the table open -process is completing the name. Let's imagine you're having a \s-1DBD::CSV\s0 -handle with following settings: -.PP -.Vb 3 -\& $dbh\->{sql_identifier_case} = SQL_IC_LOWER; -\& $dbh\->{f_ext} = \*(Aq.lst\*(Aq; -\& $dbh\->{f_dir} = \*(Aq/data/web/adrmgr\*(Aq; -.Ve -.PP -Those settings will result in looking for files matching -\&\f(CW\*(C`[Uu][Ss][Ee][Rr](\e.lst)?$\*(C'\fR in \f(CW\*(C`/data/web/adrmgr/\*(C'\fR. The scanning of the -directory \f(CW\*(C`/data/web/adrmgr/\*(C'\fR and the pattern match check will be done -in \f(CW\*(C`DBD::File::DataSource::File\*(C'\fR by the \f(CW\*(C`complete_table_name\*(C'\fR method. -.PP -If you intend to provide other sources of data streams than files, in -addition to provide an appropriate \f(CW\*(C`complete_table_name\*(C'\fR method, a method -to open the resource is required: -.PP -.Vb 1 -\& package DBI::DBD::SqlEngine::DataSource; -\& -\& sub open_data ($) -\& { -\& my ( $self, $meta, $attrs, $flags ) = @_; -\& ... -\& } -.Ve -.PP -After the method \f(CW\*(C`open_data\*(C'\fR has been run successfully, the table's meta -information are in a state which allows the table's data accessor methods -will be able to fetch/store row information. Implementation details heavily -depends on the table implementation, whereby the most famous is surely -DBD::File::Table. -.SS "DBI::DBD::SqlEngine::Statement" -.IX Subsection "DBI::DBD::SqlEngine::Statement" -Derives from DBI::SQL::Nano::Statement for unified naming when deriving -new drivers. No additional feature is provided from here. -.SS "DBI::DBD::SqlEngine::Table" -.IX Subsection "DBI::DBD::SqlEngine::Table" -Derives from DBI::SQL::Nano::Table for unified naming when deriving -new drivers. -.PP -You should consult the documentation of \f(CW\*(C`SQL::Eval::Table\*(C'\fR (see -SQL::Eval) to get more information about the abstract methods of the -table's base class you have to override and a description of the table -meta information expected by the \s-1SQL\s0 engines. -.IP "bootstrap_table_meta" 4 -.IX Item "bootstrap_table_meta" -Initializes a table meta structure. Can be safely overridden in a -derived class, as long as the \f(CW\*(C`SUPER\*(C'\fR method is called at the end -of the overridden method. -.Sp -It copies the following attributes from the database into the table meta data -\&\f(CW\*(C`$dbh\->{ReadOnly}\*(C'\fR into \f(CW\*(C`$meta\->{readonly}\*(C'\fR, \f(CW\*(C`sql_identifier_case\*(C'\fR -and \f(CW\*(C`sql_data_source\*(C'\fR and makes them sticky to the table. -.Sp -This method should be called before you attempt to map between file -name and table name to ensure the correct directory, extension etc. are -used. -.IP "init_table_meta" 4 -.IX Item "init_table_meta" -Initializes more attributes of the table meta data \- usually more -expensive ones (e.g. those which require class instantiations) \- when -the file name and the table name could mapped. -.IP "get_table_meta" 4 -.IX Item "get_table_meta" -Returns the table meta data. If there are none for the required table, -a new one is initialized. When after bootstrapping a new \fItable_meta\fR -and completing the table name a -mapping can be established between an existing \fItable_meta\fR and the -new bootstrapped one, the already existing is used and a mapping -shortcut between the recent used table name and the already known -table name is hold in \f(CW\*(C`$dbh\->{sql_meta_map}\*(C'\fR. When it fails, -nothing is returned. On success, the name of the table and the meta data -structure is returned. -.IP "get_table_meta_attr" 4 -.IX Item "get_table_meta_attr" -Returns a single attribute from the table meta data. If the attribute -name appears in \f(CW%compat_map\fR, the attribute name is updated from -there. -.IP "set_table_meta_attr" 4 -.IX Item "set_table_meta_attr" -Sets a single attribute in the table meta data. If the attribute -name appears in \f(CW%compat_map\fR, the attribute name is updated from -there. -.IP "table_meta_attr_changed" 4 -.IX Item "table_meta_attr_changed" -Called when an attribute of the meta data is modified. -.Sp -If the modified attribute requires to reset a calculated attribute, the -calculated attribute is reset (deleted from meta data structure) and -the \fIinitialized\fR flag is removed, too. The decision is made based on -\&\f(CW%register_reset_on_modify\fR. -.IP "register_reset_on_modify" 4 -.IX Item "register_reset_on_modify" -Allows \f(CW\*(C`set_table_meta_attr\*(C'\fR to reset meta attributes when special -attributes are modified. For DBD::File, modifying one of \f(CW\*(C`f_file\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, -\&\f(CW\*(C`f_ext\*(C'\fR or \f(CW\*(C`f_lockfile\*(C'\fR will reset \f(CW\*(C`f_fqfn\*(C'\fR. \s-1DBD::DBM\s0 extends the -list for \f(CW\*(C`dbm_type\*(C'\fR and \f(CW\*(C`dbm_mldbm\*(C'\fR to reset the value of \f(CW\*(C`dbm_tietype\*(C'\fR. -.Sp -If your \s-1DBD\s0 has calculated values in the meta data area, then call -\&\f(CW\*(C`register_reset_on_modify\*(C'\fR: -.Sp -.Vb 2 -\& my %reset_on_modify = ( "xxx_foo" => "xxx_bar" ); -\& _\|_PACKAGE_\|_\->register_reset_on_modify( \e%reset_on_modify ); -.Ve -.IP "register_compat_map" 4 -.IX Item "register_compat_map" -Allows \f(CW\*(C`get_table_meta_attr\*(C'\fR and \f(CW\*(C`set_table_meta_attr\*(C'\fR to update the -attribute name to the current favored one: -.Sp -.Vb 3 -\& # from DBD::DBM -\& my %compat_map = ( "dbm_ext" => "f_ext" ); -\& _\|_PACKAGE_\|_\->register_compat_map( \e%compat_map ); -.Ve -.IP "open_data" 4 -.IX Item "open_data" -Called to open the table's data storage. This is silently forwarded -to \f(CW\*(C`$meta\->{sql_data_source}\->open_data()\*(C'\fR. -.Sp -After this is done, a derived class might add more steps in an overridden -\&\f(CW\*(C`open_file\*(C'\fR method. -.IP "new" 4 -.IX Item "new" -Instantiates the table. This is done in 3 steps: -.Sp -.Vb 3 -\& 1. get the table meta data -\& 2. open the data file -\& 3. bless the table data structure using inherited constructor new -.Ve -.Sp -It is not recommended to override the constructor of the table class. -Find a reasonable place to add you extensions in one of the above four -methods. -.SH "AUTHOR" -.IX Header "AUTHOR" -The module DBI::DBD::SqlEngine is currently maintained by -.PP -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack -.PP -All rights reserved. -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as -specified in the Perl \s-1README\s0 file. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine::HowTo.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine::HowTo.3pm deleted file mode 100644 index d36d463..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::DBD::SqlEngine::HowTo.3pm +++ /dev/null @@ -1,424 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::DBD::SqlEngine::HowTo 3pm" -.TH DBI::DBD::SqlEngine::HowTo 3pm "2016-04-21" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::DBD::SqlEngine::HowTo \- Guide to create DBI::DBD::SqlEngine based driver -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 8 -\& perldoc DBI::DBD::SqlEngine::HowTo -\& perldoc DBI -\& perldoc DBI::DBD -\& perldoc DBI::DBD::SqlEngine::Developers -\& perldoc SQL::Eval -\& perldoc DBI::DBD::SqlEngine -\& perldoc DBI::DBD::SqlEngine::HowTo -\& perldoc SQL::Statement::Embed -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This document provides a step-by-step guide, how to create a new -\&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR based \s-1DBD.\s0 It expects that you carefully read the -\&\s-1DBI\s0 documentation and that you're familiar with \s-1DBI::DBD\s0 and had -read and understood DBD::ExampleP. -.PP -This document addresses experienced developers who are really sure that -they need to invest time when writing a new \s-1DBI\s0 Driver. Writing a \s-1DBI\s0 -Driver is neither a weekend project nor an easy job for hobby coders -after work. Expect one or two man-month of time for the first start. -.PP -Those who are still reading, should be able to sing the rules of -\&\*(L"\s-1CREATING A NEW DRIVER\*(R"\s0 in \s-1DBI::DBD\s0. -.SH "CREATING DRIVER CLASSES" -.IX Header "CREATING DRIVER CLASSES" -Do you have an entry in \s-1DBI\s0's \s-1DBD\s0 registry? DBI::DBD::SqlEngine expect -having a unique prefix for every driver class in inheritance chain. -.PP -It's easy to get a prefix \- just drop the \s-1DBI\s0 team a note -(\*(L"\s-1GETTING_HELP\*(R"\s0 in \s-1DBI\s0). If you want for some reason hide your work, take -a look at Class::Method::Modifiers how to wrap a private prefix method -around existing \f(CW\*(C`driver_prefix\*(C'\fR. -.PP -For this guide, a prefix of \f(CW\*(C`foo_\*(C'\fR is assumed. -.SS "Sample Skeleton" -.IX Subsection "Sample Skeleton" -.Vb 1 -\& package DBD::Foo; -\& -\& use strict; -\& use warnings; -\& use vars qw($VERSION); -\& use base qw(DBI::DBD::SqlEngine); -\& -\& use DBI (); -\& -\& $VERSION = "0.001"; -\& -\& package DBD::Foo::dr; -\& -\& use vars qw(@ISA $imp_data_size); -\& -\& @ISA = qw(DBI::DBD::SqlEngine::dr); -\& $imp_data_size = 0; -\& -\& package DBD::Foo::db; -\& -\& use vars qw(@ISA $imp_data_size); -\& -\& @ISA = qw(DBI::DBD::SqlEngine::db); -\& $imp_data_size = 0; -\& -\& package DBD::Foo::st; -\& -\& use vars qw(@ISA $imp_data_size); -\& -\& @ISA = qw(DBI::DBD::SqlEngine::st); -\& $imp_data_size = 0; -\& -\& package DBD::Foo::Statement; -\& -\& use vars qw(@ISA); -\& -\& @ISA = qw(DBI::DBD::SqlEngine::Statement); -\& -\& package DBD::Foo::Table; -\& -\& use vars qw(@ISA); -\& -\& @ISA = qw(DBI::DBD::SqlEngine::Table); -\& -\& 1; -.Ve -.PP -Tiny, eh? And all you have now is a \s-1DBD\s0 named foo which will is able to -deal with temporary tables, as long as you use SQL::Statement. In -DBI::SQL::Nano environments, this \s-1DBD\s0 can do nothing. -.SS "Deal with own attributes" -.IX Subsection "Deal with own attributes" -Before we start doing usable stuff with our \s-1DBI\s0 driver, we need to think -about what we want to do and how we want to do it. -.PP -Do we need tunable knobs accessible by users? Do we need status -information? All this is handled in attributes of the database handles (be -careful when your \s-1DBD\s0 is running \*(L"behind\*(R" a DBD::Gofer proxy). -.PP -How come the attributes into the \s-1DBD\s0 and how are they fetchable by the -user? Good question, but you should know because you've read the \s-1DBI\s0 -documentation. -.PP -\&\f(CW\*(C`DBI::DBD::SqlEngine::db::FETCH\*(C'\fR and \f(CW\*(C`DBI::DBD::SqlEngine::db::STORE\*(C'\fR -taking care for you \- all they need to know is which attribute names -are valid and mutable or immutable. Tell them by adding -\&\f(CW\*(C`init_valid_attributes\*(C'\fR to your db class: -.PP -.Vb 3 -\& sub init_valid_attributes -\& { -\& my $dbh = $_[0]; -\& -\& $dbh\->SUPER::init_valid_attributes (); -\& -\& $dbh\->{foo_valid_attrs} = { -\& foo_version => 1, # contains version of this driver -\& foo_valid_attrs => 1, # contains the valid attributes of foo drivers -\& foo_readonly_attrs => 1, # contains immutable attributes of foo drivers -\& foo_bar => 1, # contains the bar attribute -\& foo_baz => 1, # contains the baz attribute -\& foo_manager => 1, # contains the manager of the driver instance -\& foo_manager_type => 1, # contains the manager class of the driver instance -\& }; -\& $dbh\->{foo_readonly_attrs} = { -\& foo_version => 1, # ensure no\-one modifies the driver version -\& foo_valid_attrs => 1, # do not permit one to add more valid attributes ... -\& foo_readonly_attrs => 1, # ... or make the immutable mutable -\& foo_manager => 1, # manager is set internally only -\& }; -\& -\& return $dbh; -\& } -.Ve -.PP -Woooho \- but now the user cannot assign new managers? This is intended, -overwrite \f(CW\*(C`STORE\*(C'\fR to handle it! -.PP -.Vb 3 -\& sub STORE ($$$) -\& { -\& my ( $dbh, $attrib, $value ) = @_; -\& -\& $dbh\->SUPER::STORE( $attrib, $value ); -\& -\& # we\*(Aqre still alive, so no exception is thrown ... -\& # by DBI::DBD::SqlEngine::db::STORE -\& if ( $attrib eq "foo_manager_type" ) -\& { -\& $dbh\->{foo_manager} = $dbh\->{foo_manager_type}\->new(); -\& # ... probably correct some states based on the new -\& # foo_manager_type \- see DBD::Sys for an example -\& } -\& } -.Ve -.PP -But ... my driver runs without a manager until someone first assignes -a \f(CW\*(C`foo_manager_type\*(C'\fR. Well, no \- there're two places where you can -initialize defaults: -.PP -.Vb 3 -\& sub init_default_attributes -\& { -\& my ($dbh, $phase) = @_; -\& -\& $dbh\->SUPER::init_default_attributes($phase); -\& -\& if( 0 == $phase ) -\& { -\& # init all attributes which have no knowledge about -\& # user settings from DSN or the attribute hash -\& $dbh\->{foo_manager_type} = "DBD::Foo::Manager"; -\& } -\& elsif( 1 == $phase ) -\& { -\& # init phase with more knowledge from DSN or attribute -\& # hash -\& $dbh\->{foo_manager} = $dbh\->{foo_manager_type}\->new(); -\& } -\& -\& return $dbh; -\& } -.Ve -.PP -So far we can prevent the users to use our database driver as data -storage for anything and everything. We care only about the real important -stuff for peace on earth and alike attributes. But in fact, the driver -still can't do anything. It can do less than nothing \- meanwhile it's -not a stupid storage area anymore. -.SS "User comfort" -.IX Subsection "User comfort" -\&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR since \f(CW0.05\fR consolidates all persistent meta data -of a table into a single structure stored in \f(CW\*(C`$dbh\->{sql_meta}\*(C'\fR. While -DBI::DBD::SqlEngine provides only readonly access to this structure, -modifications are still allowed. -.PP -Primarily DBI::DBD::SqlEngine provides access via the setters -\&\f(CW\*(C`new_sql_engine_meta\*(C'\fR, \f(CW\*(C`get_sql_engine_meta\*(C'\fR, \f(CW\*(C`get_single_table_meta\*(C'\fR, -\&\f(CW\*(C`set_single_table_meta\*(C'\fR, \f(CW\*(C`set_sql_engine_meta\*(C'\fR and \f(CW\*(C`clear_sql_engine_meta\*(C'\fR. -Those methods are easily accessible by the users via the \f(CW\*(C`$dbh\->func ()\*(C'\fR -interface provided by \s-1DBI.\s0 Well, many users don't feel comfortize when calling -.PP -.Vb 2 -\& # don\*(Aqt require extension for tables cars -\& $dbh\->func ("cars", "f_ext", ".csv", "set_sql_engine_meta"); -.Ve -.PP -DBI::DBD::SqlEngine will inject a method into your driver to increase the -user comfort to allow: -.PP -.Vb 2 -\& # don\*(Aqt require extension for tables cars -\& $dbh\->foo_set_meta ("cars", "f_ext", ".csv"); -.Ve -.PP -Better, but here and there users likes to do: -.PP -.Vb 2 -\& # don\*(Aqt require extension for tables cars -\& $dbh\->{foo_tables}\->{cars}\->{f_ext} = ".csv"; -.Ve -.PP -This interface is provided when derived \s-1DBD\s0's define following in -\&\f(CW\*(C`init_valid_attributes\*(C'\fR (re-capture \*(L"Deal with own attributes\*(R"): -.PP -.Vb 3 -\& sub init_valid_attributes -\& { -\& my $dbh = $_[0]; -\& -\& $dbh\->SUPER::init_valid_attributes (); -\& -\& $dbh\->{foo_valid_attrs} = { -\& foo_version => 1, # contains version of this driver -\& foo_valid_attrs => 1, # contains the valid attributes of foo drivers -\& foo_readonly_attrs => 1, # contains immutable attributes of foo drivers -\& foo_bar => 1, # contains the bar attribute -\& foo_baz => 1, # contains the baz attribute -\& foo_manager => 1, # contains the manager of the driver instance -\& foo_manager_type => 1, # contains the manager class of the driver instance -\& foo_meta => 1, # contains the public interface to modify table meta attributes -\& }; -\& $dbh\->{foo_readonly_attrs} = { -\& foo_version => 1, # ensure no\-one modifies the driver version -\& foo_valid_attrs => 1, # do not permit one to add more valid attributes ... -\& foo_readonly_attrs => 1, # ... or make the immutable mutable -\& foo_manager => 1, # manager is set internally only -\& foo_meta => 1, # ensure public interface to modify table meta attributes are immutable -\& }; -\& -\& $dbh\->{foo_meta} = "foo_tables"; -\& -\& return $dbh; -\& } -.Ve -.PP -This provides a tied hash in \f(CW\*(C`$dbh\->{foo_tables}\*(C'\fR and a tied hash for -each table's meta data in \f(CW\*(C`$dbh\->{foo_tables}\->{$table_name}\*(C'\fR. -Modifications on the table meta attributes are done using the table -methods: -.PP -.Vb 2 -\& sub get_table_meta_attr { ... } -\& sub set_table_meta_attr { ... } -.Ve -.PP -Both methods can adjust the attribute name for compatibility reasons, e.g. -when former versions of the \s-1DBD\s0 allowed different names to be used for the -same flag: -.PP -.Vb 5 -\& my %compat_map = ( -\& abc => \*(Aqfoo_abc\*(Aq, -\& xyz => \*(Aqfoo_xyz\*(Aq, -\& ); -\& _\|_PACKAGE_\|_\->register_compat_map( \e%compat_map ); -.Ve -.PP -If any user modification on a meta attribute needs reinitialization of -the meta structure (in case of \f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR these are the attributes -\&\f(CW\*(C`f_file\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, \f(CW\*(C`f_ext\*(C'\fR and \f(CW\*(C`f_lockfile\*(C'\fR), inform DBI::DBD::SqlEngine by -doing -.PP -.Vb 5 -\& my %reset_on_modify = ( -\& foo_xyz => "foo_bar", -\& foo_abc => "foo_bar", -\& ); -\& _\|_PACKAGE_\|_\->register_reset_on_modify( \e%reset_on_modify ); -.Ve -.PP -The next access to the table meta data will force DBI::DBD::SqlEngine to re-do the -entire meta initialization process. -.PP -Any further action which needs to be taken can handled in -\&\f(CW\*(C`table_meta_attr_changed\*(C'\fR: -.PP -.Vb 6 -\& sub table_meta_attr_changed -\& { -\& my ($class, $meta, $attrib, $value) = @_; -\& ... -\& $class\->SUPER::table_meta_attr_changed ($meta, $attrib, $value); -\& } -.Ve -.PP -This is done before the new value is set in \f(CW$meta\fR, so the attribute -changed handler can act depending on the old value. -.SS "Dealing with Tables" -.IX Subsection "Dealing with Tables" -Let's put some life into it \- it's going to be time for it. -.PP -This is a good point where a quick side step to SQL::Statement::Embed -will help to shorten the next paragraph. The documentation in -SQL::Statement::Embed regarding embedding in own \s-1DBD\s0's works pretty -fine with SQL::Statement and DBI::SQL::Nano. -.PP -Second look should go to DBI::DBD::SqlEngine::Developers to get a -picture over the driver part of the table \s-1API.\s0 Usually there isn't much -to do for an easy driver. -.SS "Testing" -.IX Subsection "Testing" -Now you should have your first own \s-1DBD.\s0 Was easy, wasn't it? But does -it work well? Prove it by writing tests and remember to use -dbd_edit_mm_attribs from \s-1DBI::DBD\s0 to ensure testing even rare cases. -.SH "AUTHOR" -.IX Header "AUTHOR" -This guide is written by Jens Rehsack. DBI::DBD::SqlEngine is written by -Jens Rehsack using code from DBD::File originally written by Jochen -Wiedmann and Jeff Zucker. -.PP -The module DBI::DBD::SqlEngine is currently maintained by -.PP -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack -.PP -All rights reserved. -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as -specified in the Perl \s-1README\s0 file. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Execute.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Execute.3pm deleted file mode 100644 index 6fe5c72..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Execute.3pm +++ /dev/null @@ -1,242 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Execute 3pm" -.TH DBI::Gofer::Execute 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Execute \- Executes Gofer requests and returns Gofer responses -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& $executor = DBI::Gofer::Execute\->new( { ...config... }); -\& -\& $response = $executor\->execute_request( $request ); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Accepts a DBI::Gofer::Request object, executes the requested \s-1DBI\s0 method calls, -and returns a DBI::Gofer::Response object. -.PP -Any error, including any internal 'fatal' errors are caught and converted into -a DBI::Gofer::Response object. -.PP -This module is usually invoked by a 'server\-side' Gofer transport module. -They usually have names in the "\f(CW\*(C`DBI::Gofer::Transport::*\*(C'\fR" namespace. -Examples include: DBI::Gofer::Transport::stream and DBI::Gofer::Transport::mod_perl. -.SH "CONFIGURATION" -.IX Header "CONFIGURATION" -.SS "check_request_sub" -.IX Subsection "check_request_sub" -If defined, it must be a reference to a subroutine that will 'check' the request. -It is passed the request object and the executor as its only arguments. -.PP -The subroutine can either return the original request object or die with a -suitable error message (which will be turned into a Gofer response). -.PP -It can also construct and return a new request that should be executed instead -of the original request. -.SS "check_response_sub" -.IX Subsection "check_response_sub" -If defined, it must be a reference to a subroutine that will 'check' the response. -It is passed the response object, the executor, and the request object. -The sub may alter the response object and return undef, or return a new response object. -.PP -This mechanism can be used to, for example, terminate the service if specific -database errors are seen. -.SS "forced_connect_dsn" -.IX Subsection "forced_connect_dsn" -If set, this \s-1DSN\s0 is always used instead of the one in the request. -.SS "default_connect_dsn" -.IX Subsection "default_connect_dsn" -If set, this \s-1DSN\s0 is used if \f(CW\*(C`forced_connect_dsn\*(C'\fR is not set and the request does not contain a \s-1DSN\s0 itself. -.SS "forced_connect_attributes" -.IX Subsection "forced_connect_attributes" -A reference to a hash of \fIconnect()\fR attributes. Individual attributes in -\&\f(CW\*(C`forced_connect_attributes\*(C'\fR will take precedence over corresponding attributes -in the request. -.SS "default_connect_attributes" -.IX Subsection "default_connect_attributes" -A reference to a hash of \fIconnect()\fR attributes. Individual attributes in the -request take precedence over corresponding attributes in \f(CW\*(C`default_connect_attributes\*(C'\fR. -.SS "max_cached_dbh_per_drh" -.IX Subsection "max_cached_dbh_per_drh" -If set, the loaded drivers will be checked to ensure they don't have more than -this number of cached connections. There is no default value. This limit is not -enforced for every request. -.SS "max_cached_sth_per_dbh" -.IX Subsection "max_cached_sth_per_dbh" -If set, all the cached statement handles will be cleared once the number of -cached statement handles rises above this limit. The default is 1000. -.SS "forced_single_resultset" -.IX Subsection "forced_single_resultset" -If true, then only the first result set will be fetched and returned in the response. -.SS "forced_response_attributes" -.IX Subsection "forced_response_attributes" -A reference to a data structure that can specify extra attributes to be returned in responses. -.PP -.Vb 6 -\& forced_response_attributes => { -\& DriverName => { -\& dbh => [ qw(dbh_attrib_name) ], -\& sth => [ qw(sth_attrib_name) ], -\& }, -\& }, -.Ve -.PP -This can be useful in cases where the driver has not implemented the -\&\fIprivate_attribute_info()\fR method and DBI::Gofer::Execute's own fallback list of -private attributes doesn't include the driver or attributes you need. -.SS "track_recent" -.IX Subsection "track_recent" -If set, specifies the number of recent requests and responses that should be -kept by the \fIupdate_stats()\fR method for diagnostics. See DBI::Gofer::Transport::mod_perl. -.PP -Note that this setting can significantly increase memory use. Use with caution. -.SS "forced_gofer_random" -.IX Subsection "forced_gofer_random" -Enable forced random failures and/or delays for testing. See \*(L"\s-1DBI_GOFER_RANDOM\*(R"\s0 below. -.SH "DRIVER-SPECIFIC ISSUES" -.IX Header "DRIVER-SPECIFIC ISSUES" -Gofer needs to know about any driver-private attributes that should have their -values sent back to the client. -.PP -If the driver doesn't support \fIprivate_attribute_info()\fR method, and very few do, -then the module fallsback to using some hard-coded details, if available, for -the driver being used. Currently hard-coded details are available for the -mysql, Pg, Sybase, and SQLite drivers. -.SH "TESTING" -.IX Header "TESTING" -DBD::Gofer, DBD::Execute and related packages are well tested by executing the -\&\s-1DBI\s0 test suite with \s-1DBI_AUTOPROXY\s0 configured to route all \s-1DBI\s0 calls via DBD::Gofer. -.PP -Because Gofer includes timeout and 'retry on error' mechanisms there is a need -for some way to trigger delays and/or errors. This can be done via the -\&\f(CW\*(C`forced_gofer_random\*(C'\fR configuration item, or else the \s-1DBI_GOFER_RANDOM\s0 environment -variable. -.SS "\s-1DBI_GOFER_RANDOM\s0" -.IX Subsection "DBI_GOFER_RANDOM" -The value of the \f(CW\*(C`forced_gofer_random\*(C'\fR configuration item (or else the -\&\s-1DBI_GOFER_RANDOM\s0 environment variable) is treated as a series of tokens -separated by commas. -.PP -The tokens can be one of three types: -.IP "fail=R%" 4 -.IX Item "fail=R%" -Set the current failure rate to R where R is a percentage. -The value R can be floating point, e.g., \f(CW\*(C`fail=0.05%\*(C'\fR. -Negative values for R have special meaning, see below. -.IP "err=N" 4 -.IX Item "err=N" -Sets the current failure err value to N (instead of the \s-1DBI\s0's default 'standard -err value' of 2000000000). This is useful when you want to simulate a -specific error. -.IP "delayN=R%" 4 -.IX Item "delayN=R%" -Set the current random delay rate to R where R is a percentage, and set the -current delay duration to N seconds. The values of R and N can be floating point, -e.g., \f(CW\*(C`delay0.5=0.2%\*(C'\fR. Negative values for R have special meaning, see below. -.Sp -If R is an odd number (R % 2 == 1) then a message is logged via \fIwarn()\fR which -will be returned to, and echoed at, the client. -.IP "methodname" 4 -.IX Item "methodname" -Applies the current fail, err, and delay values to the named method. -If neither a fail nor delay have been set yet then a warning is generated. -.PP -For example: -.PP -.Vb 3 -\& $executor = DBI::Gofer::Execute\->new( { -\& forced_gofer_random => "fail=0.01%,do,delay60=1%,execute", -\& }); -.Ve -.PP -will cause the \fIdo()\fR method to fail for 0.01% of calls, and the \fIexecute()\fR method to -fail 0.01% of calls and be delayed by 60 seconds on 1% of calls. -.PP -If the percentage value (\f(CW\*(C`R\*(C'\fR) is negative then instead of the failures being -triggered randomly (via the \fIrand()\fR function) they are triggered via a sequence -number. In other words "\f(CW\*(C`fail=\-20%\*(C'\fR" will mean every fifth call will fail. -Each method has a distinct sequence number. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Request.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Request.3pm deleted file mode 100644 index 3a9f7b8..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Request.3pm +++ /dev/null @@ -1,92 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Request 3pm" -.TH DBI::Gofer::Request 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Request \- Encapsulate a request from DBD::Gofer to DBI::Gofer::Execute -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This is an internal class. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Response.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Response.3pm deleted file mode 100644 index 1eeae16..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Response.3pm +++ /dev/null @@ -1,92 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Response 3pm" -.TH DBI::Gofer::Response 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Response \- Encapsulate a response from DBI::Gofer::Execute to DBD::Gofer -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This is an internal class. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::Base.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::Base.3pm deleted file mode 100644 index 9d4cbba..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::Base.3pm +++ /dev/null @@ -1,96 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Serializer::Base 3pm" -.TH DBI::Gofer::Serializer::Base 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Serializer::Base \- base class for Gofer serialization -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& $serializer = $serializer_class\->new(); -\& -\& $string = $serializer\->serialize( $data ); -\& ($string, $deserializer_class) = $serializer\->serialize( $data ); -\& -\& $data = $serializer\->deserialize( $string ); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBI::Gofer::Serializer::* classes implement a very minimal subset of the Data::Serializer \s-1API.\s0 -.PP -Gofer serializers are expected to be very fast and are not required to deal -with anything other than non-blessed references to arrays and hashes, and plain scalars. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::DataDumper.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::DataDumper.3pm deleted file mode 100644 index 15ee4fc..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::DataDumper.3pm +++ /dev/null @@ -1,93 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Serializer::DataDumper 3pm" -.TH DBI::Gofer::Serializer::DataDumper 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Serializer::DataDumper \- Gofer serialization using DataDumper -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& $serializer = DBI::Gofer::Serializer::DataDumper\->new(); -\& -\& $string = $serializer\->serialize( $data ); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Uses DataDumper to serialize. Deserialization is not supported. -The output of this class is only meant for human consumption. -.PP -See also DBI::Gofer::Serializer::Base. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::Storable.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::Storable.3pm deleted file mode 100644 index 1afb792..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Serializer::Storable.3pm +++ /dev/null @@ -1,98 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Serializer::Storable 3pm" -.TH DBI::Gofer::Serializer::Storable 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Serializer::Storable \- Gofer serialization using Storable -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& $serializer = DBI::Gofer::Serializer::Storable\->new(); -\& -\& $string = $serializer\->serialize( $data ); -\& ($string, $deserializer_class) = $serializer\->serialize( $data ); -\& -\& $data = $serializer\->deserialize( $string ); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Uses \fIStorable::nfreeze()\fR to serialize and \fIStorable::thaw()\fR to deserialize. -.PP -The \fIserialize()\fR method sets local \f(CW$Storable::forgive_me\fR = 1; so it doesn't -croak if it encounters any data types that can't be serialized, such as code refs. -.PP -See also DBI::Gofer::Serializer::Base. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::Base.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::Base.3pm deleted file mode 100644 index 6404f96..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::Base.3pm +++ /dev/null @@ -1,96 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Transport::Base 3pm" -.TH DBI::Gofer::Transport::Base 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Transport::Base \- Base class for Gofer transports -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This is the base class for server-side Gofer transports. -.PP -It's also the base class for the client-side base class DBD::Gofer::Transport::Base. -.PP -This is an internal class. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::pipeone.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::pipeone.3pm deleted file mode 100644 index ad28cfb..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::pipeone.3pm +++ /dev/null @@ -1,92 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Transport::pipeone 3pm" -.TH DBI::Gofer::Transport::pipeone 3pm "2016-04-21" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Transport::pipeone \- DBD::Gofer server\-side transport for pipeone -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -See DBD::Gofer::Transport::pipeone. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::stream.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::stream.3pm deleted file mode 100644 index 0314432..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Gofer::Transport::stream.3pm +++ /dev/null @@ -1,92 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Gofer::Transport::stream 3pm" -.TH DBI::Gofer::Transport::stream 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Gofer::Transport::stream \- DBD::Gofer server\-side transport for stream -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -See DBD::Gofer::Transport::stream. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tim Bunce, -.SH "LICENCE AND COPYRIGHT" -.IX Header "LICENCE AND COPYRIGHT" -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. -.PP -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See perlartistic. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Profile.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Profile.3pm deleted file mode 100644 index 4f0e437..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Profile.3pm +++ /dev/null @@ -1,791 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Profile 3pm" -.TH DBI::Profile 3pm "2016-04-21" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Profile \- Performance profiling and benchmarking for the DBI -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -The easiest way to enable \s-1DBI\s0 profiling is to set the \s-1DBI_PROFILE\s0 -environment variable to 2 and then run your code as usual: -.PP -.Vb 1 -\& DBI_PROFILE=2 prog.pl -.Ve -.PP -This will profile your program and then output a textual summary -grouped by query when the program exits. You can also enable profiling by -setting the Profile attribute of any \s-1DBI\s0 handle: -.PP -.Vb 1 -\& $dbh\->{Profile} = 2; -.Ve -.PP -Then the summary will be printed when the handle is destroyed. -.PP -Many other values apart from are possible \- see \*(L"\s-1ENABLING A PROFILE\*(R"\s0 below. -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -The DBI::Profile module provides a simple interface to collect and -report performance and benchmarking data from the \s-1DBI.\s0 -.PP -For a more elaborate interface, suitable for larger programs, see -DBI::ProfileDumper and dbiprof. -For Apache/mod_perl applications see -DBI::ProfileDumper::Apache. -.SH "OVERVIEW" -.IX Header "OVERVIEW" -Performance data collection for the \s-1DBI\s0 is built around several -concepts which are important to understand clearly. -.IP "Method Dispatch" 4 -.IX Item "Method Dispatch" -Every method call on a \s-1DBI\s0 handle passes through a single 'dispatch' -function which manages all the common aspects of \s-1DBI\s0 method calls, -such as handling the RaiseError attribute. -.IP "Data Collection" 4 -.IX Item "Data Collection" -If profiling is enabled for a handle then the dispatch code takes -a high-resolution timestamp soon after it is entered. Then, after -calling the appropriate method and just before returning, it takes -another high-resolution timestamp and calls a function to record -the information. That function is passed the two timestamps -plus the \s-1DBI\s0 handle and the name of the method that was called. -That data about a single \s-1DBI\s0 method call is called a \fIprofile sample\fR. -.IP "Data Filtering" 4 -.IX Item "Data Filtering" -If the method call was invoked by the \s-1DBI\s0 or by a driver then the call is -ignored for profiling because the time spent will be accounted for by the -original 'outermost' call for your code. -.Sp -For example, the calls that the \fIselectrow_arrayref()\fR method makes -to \fIprepare()\fR and \fIexecute()\fR etc. are not counted individually -because the time spent in those methods is going to be allocated -to the \fIselectrow_arrayref()\fR method when it returns. If this was not -done then it would be very easy to double count time spent inside -the \s-1DBI.\s0 -.IP "Data Storage Tree" 4 -.IX Item "Data Storage Tree" -The profile data is accumulated as 'leaves on a tree'. The 'path' through the -branches of the tree to a particular leaf is determined dynamically for each sample. -This is a key feature of \s-1DBI\s0 profiling. -.Sp -For each profiled method call the \s-1DBI\s0 walks along the Path and uses each value -in the Path to step into and grow the Data tree. -.Sp -For example, if the Path is -.Sp -.Vb 1 -\& [ \*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq ] -.Ve -.Sp -then the new profile sample data will be \fImerged\fR into the tree at -.Sp -.Vb 1 -\& $h\->{Profile}\->{Data}\->{foo}\->{bar}\->{baz} -.Ve -.Sp -But it's not very useful to merge all the call data into one leaf node (except -to get an overall 'time spent inside the \s-1DBI\s0' total). It's more common to want -the Path to include dynamic values such as the current statement text and/or -the name of the method called to show what the time spent inside the \s-1DBI\s0 was for. -.Sp -The Path can contain some 'magic cookie' values that are automatically replaced -by corresponding dynamic values when they're used. These magic cookies always -start with a punctuation character. -.Sp -For example a value of '\f(CW\*(C`!MethodName\*(C'\fR' in the Path causes the corresponding -entry in the Data to be the name of the method that was called. -For example, if the Path was: -.Sp -.Vb 1 -\& [ \*(Aqfoo\*(Aq, \*(Aq!MethodName\*(Aq, \*(Aqbar\*(Aq ] -.Ve -.Sp -and the \fIselectall_arrayref()\fR method was called, then the profile sample data -for that call will be merged into the tree at: -.Sp -.Vb 1 -\& $h\->{Profile}\->{Data}\->{foo}\->{selectall_arrayref}\->{bar} -.Ve -.IP "Profile Data" 4 -.IX Item "Profile Data" -Profile data is stored at the 'leaves' of the tree as references -to an array of numeric values. For example: -.Sp -.Vb 9 -\& [ -\& 106, # 0: count of samples at this node -\& 0.0312958955764771, # 1: total duration -\& 0.000490069389343262, # 2: first duration -\& 0.000176072120666504, # 3: shortest duration -\& 0.00140702724456787, # 4: longest duration -\& 1023115819.83019, # 5: time of first sample -\& 1023115819.86576, # 6: time of last sample -\& ] -.Ve -.Sp -After the first sample, later samples always update elements 0, 1, and 6, and -may update 3 or 4 depending on the duration of the sampled call. -.SH "ENABLING A PROFILE" -.IX Header "ENABLING A PROFILE" -Profiling is enabled for a handle by assigning to the Profile -attribute. For example: -.PP -.Vb 1 -\& $h\->{Profile} = DBI::Profile\->new(); -.Ve -.PP -The Profile attribute holds a blessed reference to a hash object -that contains the profile data and attributes relating to it. -.PP -The class the Profile object is blessed into is expected to -provide at least a \s-1DESTROY\s0 method which will dump the profile data -to the \s-1DBI\s0 trace file handle (\s-1STDERR\s0 by default). -.PP -All these examples have the same effect as each other: -.PP -.Vb 5 -\& $h\->{Profile} = 0; -\& $h\->{Profile} = "/DBI::Profile"; -\& $h\->{Profile} = DBI::Profile\->new(); -\& $h\->{Profile} = {}; -\& $h\->{Profile} = { Path => [] }; -.Ve -.PP -Similarly, these examples have the same effect as each other: -.PP -.Vb 4 -\& $h\->{Profile} = 6; -\& $h\->{Profile} = "6/DBI::Profile"; -\& $h\->{Profile} = "!Statement:!MethodName/DBI::Profile"; -\& $h\->{Profile} = { Path => [ \*(Aq!Statement\*(Aq, \*(Aq!MethodName\*(Aq ] }; -.Ve -.PP -If a non-blessed hash reference is given then the DBI::Profile -module is automatically \f(CW\*(C`require\*(C'\fR'd and the reference is blessed -into that class. -.PP -If a string is given then it is processed like this: -.PP -.Vb 1 -\& ($path, $module, $args) = split /\e//, $string, 3 -\& -\& @path = split /:/, $path -\& @args = split /:/, $args -\& -\& eval "require $module" if $module -\& $module ||= "DBI::Profile" -\& -\& $module\->new( Path => \e@Path, @args ) -.Ve -.PP -So the first value is used to select the Path to be used (see below). -The second value, if present, is used as the name of a module which -will be loaded and it's \f(CW\*(C`new\*(C'\fR method called. If not present it -defaults to DBI::Profile. Any other values are passed as arguments -to the \f(CW\*(C`new\*(C'\fR method. For example: "\f(CW\*(C`2/DBIx::OtherProfile/Foo:42\*(C'\fR". -.PP -Numbers can be used as a shorthand way to enable common Path values. -The simplest way to explain how the values are interpreted is to show the code: -.PP -.Vb 5 -\& push @Path, "DBI" if $path_elem & 0x01; -\& push @Path, "!Statement" if $path_elem & 0x02; -\& push @Path, "!MethodName" if $path_elem & 0x04; -\& push @Path, "!MethodClass" if $path_elem & 0x08; -\& push @Path, "!Caller2" if $path_elem & 0x10; -.Ve -.PP -So \*(L"2\*(R" is the same as \*(L"!Statement\*(R" and \*(L"6\*(R" (2+4) is the same as -\&\*(L"!Statement:!Method\*(R". Those are the two most commonly used values. Using a -negative number will reverse the path. Thus \*(L"\-6\*(R" will group by method name then -statement. -.PP -The splitting and parsing of string values assigned to the Profile -attribute may seem a little odd, but there's a good reason for it. -Remember that attributes can be embedded in the Data Source Name -string which can be passed in to a script as a parameter. For -example: -.PP -.Vb 2 -\& dbi:DriverName(Profile=>2):dbname -\& dbi:DriverName(Profile=>{Username}:!Statement/MyProfiler/Foo:42):dbname -.Ve -.PP -And also, if the \f(CW\*(C`DBI_PROFILE\*(C'\fR environment variable is set then -The \s-1DBI\s0 arranges for every driver handle to share the same profile -object. When perl exits a single profile summary will be generated -that reflects (as nearly as practical) the total use of the \s-1DBI\s0 by -the application. -.SH "THE PROFILE OBJECT" -.IX Header "THE PROFILE OBJECT" -The \s-1DBI\s0 core expects the Profile attribute value to be a hash -reference and if the following values don't exist it will create -them as needed: -.SS "Data" -.IX Subsection "Data" -A reference to a hash containing the collected profile data. -.SS "Path" -.IX Subsection "Path" -The Path value is a reference to an array. Each element controls the -value to use at the corresponding level of the profile Data tree. -.PP -If the value of Path is anything other than an array reference, -it is treated as if it was: -.PP -.Vb 1 -\& [ \*(Aq!Statement\*(Aq ] -.Ve -.PP -The elements of Path array can be one of the following types: -.PP -\fISpecial Constant\fR -.IX Subsection "Special Constant" -.PP -\&\fB!Statement\fR -.PP -Use the current Statement text. Typically that's the value of the Statement -attribute for the handle the method was called with. Some methods, like -\&\fIcommit()\fR and \fIrollback()\fR, are unrelated to a particular statement. For those -methods !Statement records an empty string. -.PP -For statement handles this is always simply the string that was -given to \fIprepare()\fR when the handle was created. For database handles -this is the statement that was last prepared or executed on that -database handle. That can lead to a little 'fuzzyness' because, for -example, calls to the \fIquote()\fR method to build a new statement will -typically be associated with the previous statement. In practice -this isn't a significant issue and the dynamic Path mechanism can -be used to setup your own rules. -.PP -\&\fB!MethodName\fR -.PP -Use the name of the \s-1DBI\s0 method that the profile sample relates to. -.PP -\&\fB!MethodClass\fR -.PP -Use the fully qualified name of the \s-1DBI\s0 method, including -the package, that the profile sample relates to. This shows you -where the method was implemented. For example: -.PP -.Vb 4 -\& \*(AqDBD::_::db::selectrow_arrayref\*(Aq => -\& 0.022902s -\& \*(AqDBD::mysql::db::selectrow_arrayref\*(Aq => -\& 2.244521s / 99 = 0.022445s avg (first 0.022813s, min 0.022051s, max 0.028932s) -.Ve -.PP -The \*(L"DBD::_::db::selectrow_arrayref\*(R" shows that the driver has -inherited the selectrow_arrayref method provided by the \s-1DBI.\s0 -.PP -But you'll note that there is only one call to -DBD::_::db::selectrow_arrayref but another 99 to -DBD::mysql::db::selectrow_arrayref. Currently the first -call doesn't record the true location. That may change. -.PP -\&\fB!Caller\fR -.PP -Use a string showing the filename and line number of the code calling the method. -.PP -\&\fB!Caller2\fR -.PP -Use a string showing the filename and line number of the code calling the -method, as for !Caller, but also include filename and line number of the code -that called that. Calls from \s-1DBI::\s0 and \s-1DBD::\s0 packages are skipped. -.PP -\&\fB!File\fR -.PP -Same as !Caller above except that only the filename is included, not the line number. -.PP -\&\fB!File2\fR -.PP -Same as !Caller2 above except that only the filenames are included, not the line number. -.PP -\&\fB!Time\fR -.PP -Use the current value of \fItime()\fR. Rarely used. See the more useful \f(CW\*(C`!Time~N\*(C'\fR below. -.PP -\&\fB!Time~N\fR -.PP -Where \f(CW\*(C`N\*(C'\fR is an integer. Use the current value of \fItime()\fR but with reduced precision. -The value used is determined in this way: -.PP -.Vb 1 -\& int( time() / N ) * N -.Ve -.PP -This is a useful way to segregate a profile into time slots. For example: -.PP -.Vb 1 -\& [ \*(Aq!Time~60\*(Aq, \*(Aq!Statement\*(Aq ] -.Ve -.PP -\fICode Reference\fR -.IX Subsection "Code Reference" -.PP -The subroutine is passed the handle it was called on and the \s-1DBI\s0 method name. -The current Statement is in \f(CW$_\fR. The statement string should not be modified, -so most subs start with \f(CW\*(C`local $_ = $_;\*(C'\fR. -.PP -The list of values it returns is used at that point in the Profile Path. -Any undefined values are treated as the string "\f(CW\*(C`undef\*(C'\fR". -.PP -The sub can 'veto' (reject) a profile sample by including a reference to undef -(\f(CW\*(C`\eundef\*(C'\fR) in the returned list. That can be useful when you want to only profile -statements that match a certain pattern, or only profile certain methods. -.PP -\fISubroutine Specifier\fR -.IX Subsection "Subroutine Specifier" -.PP -A Path element that begins with '\f(CW\*(C`&\*(C'\fR' is treated as the name of a subroutine -in the DBI::ProfileSubs namespace and replaced with the corresponding code reference. -.PP -Currently this only works when the Path is specified by the \f(CW\*(C`DBI_PROFILE\*(C'\fR -environment variable. -.PP -Also, currently, the only subroutine in the DBI::ProfileSubs namespace is -\&\f(CW\*(Aq&norm_std_n3\*(Aq\fR. That's a very handy subroutine when profiling code that -doesn't use placeholders. See DBI::ProfileSubs for more information. -.PP -\fIAttribute Specifier\fR -.IX Subsection "Attribute Specifier" -.PP -A string enclosed in braces, such as '\f(CW\*(C`{Username}\*(C'\fR', specifies that the current -value of the corresponding database handle attribute should be used at that -point in the Path. -.PP -\fIReference to a Scalar\fR -.IX Subsection "Reference to a Scalar" -.PP -Specifies that the current value of the referenced scalar be used at that point -in the Path. This provides an efficient way to get 'contextual' values into -your profile. -.PP -\fIOther Values\fR -.IX Subsection "Other Values" -.PP -Any other values are stringified and used literally. -.PP -(References, and values that begin with punctuation characters are reserved.) -.SH "REPORTING" -.IX Header "REPORTING" -.SS "Report Format" -.IX Subsection "Report Format" -The current accumulated profile data can be formatted and output using -.PP -.Vb 1 -\& print $h\->{Profile}\->format; -.Ve -.PP -To discard the profile data and start collecting fresh data -you can do: -.PP -.Vb 1 -\& $h\->{Profile}\->{Data} = undef; -.Ve -.PP -The default results format looks like this: -.PP -.Vb 5 -\& DBI::Profile: 0.001015s 42.7% (5 calls) programname @ YYYY\-MM\-DD HH:MM:SS -\& \*(Aq\*(Aq => -\& 0.000024s / 2 = 0.000012s avg (first 0.000015s, min 0.000009s, max 0.000015s) -\& \*(AqSELECT mode,size,name FROM table\*(Aq => -\& 0.000991s / 3 = 0.000330s avg (first 0.000678s, min 0.000009s, max 0.000678s) -.Ve -.PP -Which shows the total time spent inside the \s-1DBI,\s0 with a count of -the total number of method calls and the name of the script being -run, then a formatted version of the profile data tree. -.PP -If the results are being formatted when the perl process is exiting -(which is usually the case when the \s-1DBI_PROFILE\s0 environment variable -is used) then the percentage of time the process spent inside the -\&\s-1DBI\s0 is also shown. If the process is not exiting then the percentage is -calculated using the time between the first and last call to the \s-1DBI.\s0 -.PP -In the example above the paths in the tree are only one level deep and -use the Statement text as the value (that's the default behaviour). -.PP -The merged profile data at the 'leaves' of the tree are presented -as total time spent, count, average time spent (which is simply total -time divided by the count), then the time spent on the first call, -the time spent on the fastest call, and finally the time spent on -the slowest call. -.PP -The 'avg', 'first', 'min' and 'max' times are not particularly -useful when the profile data path only contains the statement text. -Here's an extract of a more detailed example using both statement -text and method name in the path: -.PP -.Vb 5 -\& \*(AqSELECT mode,size,name FROM table\*(Aq => -\& \*(AqFETCH\*(Aq => -\& 0.000076s -\& \*(Aqfetchrow_hashref\*(Aq => -\& 0.036203s / 108 = 0.000335s avg (first 0.000490s, min 0.000152s, max 0.002786s) -.Ve -.PP -Here you can see the 'avg', 'first', 'min' and 'max' for the -108 calls to \fIfetchrow_hashref()\fR become rather more interesting. -Also the data for \s-1FETCH\s0 just shows a time value because it was only -called once. -.PP -Currently the profile data is output sorted by branch names. That -may change in a later version so the leaf nodes are sorted by total -time per leaf node. -.SS "Report Destination" -.IX Subsection "Report Destination" -The default method of reporting is for the \s-1DESTROY\s0 method of the -Profile object to format the results and write them using: -.PP -.Vb 1 -\& DBI\->trace_msg($results, 0); # see $ON_DESTROY_DUMP below -.Ve -.PP -to write them to the \s-1DBI\s0 \fItrace()\fR filehandle (which defaults to -\&\s-1STDERR\s0). To direct the \s-1DBI\s0 trace filehandle to write to a file -without enabling tracing the \fItrace()\fR method can be called with a -trace level of 0. For example: -.PP -.Vb 1 -\& DBI\->trace(0, $filename); -.Ve -.PP -The same effect can be achieved without changing the code by -setting the \f(CW\*(C`DBI_TRACE\*(C'\fR environment variable to \f(CW\*(C`0=filename\*(C'\fR. -.PP -The \f(CW$DBI::Profile::ON_DESTROY_DUMP\fR variable holds a code ref -that's called to perform the output of the formatted results. -The default value is: -.PP -.Vb 1 -\& $ON_DESTROY_DUMP = sub { DBI\->trace_msg($results, 0) }; -.Ve -.PP -Apart from making it easy to send the dump elsewhere, it can also -be useful as a simple way to disable dumping results. -.SH "CHILD HANDLES" -.IX Header "CHILD HANDLES" -Child handles inherit a reference to the Profile attribute value -of their parent. So if profiling is enabled for a database handle -then by default the statement handles created from it all contribute -to the same merged profile data tree. -.SH "PROFILE OBJECT METHODS" -.IX Header "PROFILE OBJECT METHODS" -.SS "format" -.IX Subsection "format" -See \*(L"\s-1REPORTING\*(R"\s0. -.SS "as_node_path_list" -.IX Subsection "as_node_path_list" -.Vb 2 -\& @ary = $dbh\->{Profile}\->as_node_path_list(); -\& @ary = $dbh\->{Profile}\->as_node_path_list($node, $path); -.Ve -.PP -Returns the collected data ($dbh\->{Profile}{Data}) restructured into a list of -array refs, one for each leaf node in the Data tree. This 'flat' structure is -often much simpler for applications to work with. -.PP -The first element of each array ref is a reference to the leaf node. -The remaining elements are the 'path' through the data tree to that node. -.PP -For example, given a data tree like this: -.PP -.Vb 3 -\& {key1a}{key2a}[node1] -\& {key1a}{key2b}[node2] -\& {key1b}{key2a}{key3a}[node3] -.Ve -.PP -The \fIas_node_path_list()\fR method will return this list: -.PP -.Vb 3 -\& [ [node1], \*(Aqkey1a\*(Aq, \*(Aqkey2a\*(Aq ] -\& [ [node2], \*(Aqkey1a\*(Aq, \*(Aqkey2b\*(Aq ] -\& [ [node3], \*(Aqkey1b\*(Aq, \*(Aqkey2a\*(Aq, \*(Aqkey3a\*(Aq ] -.Ve -.PP -The nodes are ordered by key, depth-first. -.PP -The \f(CW$node\fR argument can be used to focus on a sub-tree. -If not specified it defaults to \f(CW$dbh\fR\->{Profile}{Data}. -.PP -The \f(CW$path\fR argument can be used to specify a list of path elements that will be -added to each element of the returned list. If not specified it defaults to a -ref to an empty array. -.SS "as_text" -.IX Subsection "as_text" -.Vb 8 -\& @txt = $dbh\->{Profile}\->as_text(); -\& $txt = $dbh\->{Profile}\->as_text({ -\& node => undef, -\& path => [], -\& separator => " > ", -\& format => \*(Aq%1$s: %11$fs / %10$d = %2$fs avg (first %12$fs, min %13$fs, max %14$fs)\*(Aq."\en"; -\& sortsub => sub { ... }, -\& ); -.Ve -.PP -Returns the collected data ($dbh\->{Profile}{Data}) reformatted into a list of formatted strings. -In scalar context the list is returned as a single concatenated string. -.PP -A hashref can be used to pass in arguments, the default values are shown in the example above. -.PP -The \f(CW\*(C`node\*(C'\fR and arguments are passed to \fIas_node_path_list()\fR. -.PP -The \f(CW\*(C`separator\*(C'\fR argument is used to join the elements of the path for each leaf node. -.PP -The \f(CW\*(C`sortsub\*(C'\fR argument is used to pass in a ref to a sub that will order the list. -The subroutine will be passed a reference to the array returned by -\&\fIas_node_path_list()\fR and should sort the contents of the array in place. -The return value from the sub is ignored. For example, to sort the nodes by the -second level key you could use: -.PP -.Vb 1 -\& sortsub => sub { my $ary=shift; @$ary = sort { $a\->[2] cmp $b\->[2] } @$ary } -.Ve -.PP -The \f(CW\*(C`format\*(C'\fR argument is a \f(CW\*(C`sprintf\*(C'\fR format string that specifies the format -to use for each leaf node. It uses the explicit format parameter index -mechanism to specify which of the arguments should appear where in the string. -The arguments to sprintf are: -.PP -.Vb 10 -\& 1: path to node, joined with the separator -\& 2: average duration (total duration/count) -\& (3 thru 9 are currently unused) -\& 10: count -\& 11: total duration -\& 12: first duration -\& 13: smallest duration -\& 14: largest duration -\& 15: time of first call -\& 16: time of first call -.Ve -.SH "CUSTOM DATA MANIPULATION" -.IX Header "CUSTOM DATA MANIPULATION" -Recall that \f(CW\*(C`$h\->{Profile}\->{Data}\*(C'\fR is a reference to the collected data. -Either to a 'leaf' array (when the Path is empty, i.e., \s-1DBI_PROFILE\s0 env var is 1), -or a reference to hash containing values that are either further hash -references or leaf array references. -.PP -Sometimes it's useful to be able to summarise some or all of the collected data. -The \fIdbi_profile_merge_nodes()\fR function can be used to merge leaf node values. -.SS "dbi_profile_merge_nodes" -.IX Subsection "dbi_profile_merge_nodes" -.Vb 1 -\& use DBI qw(dbi_profile_merge_nodes); -\& -\& $time_in_dbi = dbi_profile_merge_nodes(my $totals=[], @$leaves); -.Ve -.PP -Merges profile data node. Given a reference to a destination array, and zero or -more references to profile data, merges the profile data into the destination array. -For example: -.PP -.Vb 5 -\& $time_in_dbi = dbi_profile_merge_nodes( -\& my $totals=[], -\& [ 10, 0.51, 0.11, 0.01, 0.22, 1023110000, 1023110010 ], -\& [ 15, 0.42, 0.12, 0.02, 0.23, 1023110005, 1023110009 ], -\& ); -.Ve -.PP -\&\f(CW$totals\fR will then contain -.PP -.Vb 1 -\& [ 25, 0.93, 0.11, 0.01, 0.23, 1023110000, 1023110010 ] -.Ve -.PP -and \f(CW$time_in_dbi\fR will be 0.93; -.PP -The second argument need not be just leaf nodes. If given a reference to a hash -then the hash is recursively searched for leaf nodes and all those found -are merged. -.PP -For example, to get the time spent 'inside' the \s-1DBI\s0 during an http request, -your logging code run at the end of the request (i.e. mod_perl LogHandler) -could use: -.PP -.Vb 5 -\& my $time_in_dbi = 0; -\& if (my $Profile = $dbh\->{Profile}) { # if DBI profiling is enabled -\& $time_in_dbi = dbi_profile_merge_nodes(my $total=[], $Profile\->{Data}); -\& $Profile\->{Data} = {}; # reset the profile data -\& } -.Ve -.PP -If profiling has been enabled then \f(CW$time_in_dbi\fR will hold the time spent inside -the \s-1DBI\s0 for that handle (and any other handles that share the same profile data) -since the last request. -.PP -Prior to \s-1DBI 1.56\s0 the \fIdbi_profile_merge_nodes()\fR function was called \fIdbi_profile_merge()\fR. -That name still exists as an alias. -.SH "CUSTOM DATA COLLECTION" -.IX Header "CUSTOM DATA COLLECTION" -.SS "Using The Path Attribute" -.IX Subsection "Using The Path Attribute" -.Vb 6 -\& XXX example to be added later using a selectall_arrayref call -\& XXX nested inside a fetch loop where the first column of the -\& XXX outer loop is bound to the profile Path using -\& XXX bind_column(1, \e${ $dbh\->{Profile}\->{Path}\->[0] }) -\& XXX so you end up with separate profiles for each loop -\& XXX (patches welcome to add this to the docs :) -.Ve -.SS "Adding Your Own Samples" -.IX Subsection "Adding Your Own Samples" -The \fIdbi_profile()\fR function can be used to add extra sample data -into the profile data tree. For example: -.PP -.Vb 2 -\& use DBI; -\& use DBI::Profile (dbi_profile dbi_time); -\& -\& my $t1 = dbi_time(); # floating point high\-resolution time -\& -\& ... execute code you want to profile here ... -\& -\& my $t2 = dbi_time(); -\& dbi_profile($h, $statement, $method, $t1, $t2); -.Ve -.PP -The \f(CW$h\fR parameter is the handle the extra profile sample should be -associated with. The \f(CW$statement\fR parameter is the string to use where -the Path specifies !Statement. If \f(CW$statement\fR is undef -then \f(CW$h\fR\->{Statement} will be used. Similarly \f(CW$method\fR is the string -to use if the Path specifies !MethodName. There is no -default value for \f(CW$method\fR. -.PP -The \f(CW$h\fR\->{Profile}{Path} attribute is processed by \fIdbi_profile()\fR in -the usual way. -.PP -The \f(CW$h\fR parameter is usually a \s-1DBI\s0 handle but it can also be a reference to a -hash, in which case the \fIdbi_profile()\fR acts on each defined value in the hash. -This is an efficient way to update multiple profiles with a single sample, -and is used by the DashProfiler module. -.SH "SUBCLASSING" -.IX Header "SUBCLASSING" -Alternate profile modules must subclass DBI::Profile to help ensure -they work with future versions of the \s-1DBI.\s0 -.SH "CAVEATS" -.IX Header "CAVEATS" -Applications which generate many different statement strings -(typically because they don't use placeholders) and profile with -!Statement in the Path (the default) will consume memory -in the Profile Data structure for each statement. Use a code ref -in the Path to return an edited (simplified) form of the statement. -.PP -If a method throws an exception itself (not via RaiseError) then -it won't be counted in the profile. -.PP -If a HandleError subroutine throws an exception (rather than returning -0 and letting RaiseError do it) then the method call won't be counted -in the profile. -.PP -Time spent in \s-1DESTROY\s0 is added to the profile of the parent handle. -.PP -Time spent in \s-1DBI\-\s0>*() methods is not counted. The time spent in -the driver connect method, \f(CW$drh\fR\->\fIconnect()\fR, when it's called by -\&\s-1DBI\-\s0>connect is counted if the \s-1DBI_PROFILE\s0 environment variable is set. -.PP -Time spent fetching tied variables, \f(CW$DBI::errstr\fR, is counted. -.PP -Time spent in \s-1FETCH\s0 for \f(CW$h\fR\->{Profile} is not counted, so getting the profile -data doesn't alter it. -.PP -DBI::PurePerl does not support profiling (though it could in theory). -.PP -For asynchronous queries, time spent while the query is running on the -backend is not counted. -.PP -A few platforms don't support the \fIgettimeofday()\fR high resolution -time function used by the \s-1DBI \s0(and available via the \fIdbi_time()\fR function). -In which case you'll get integer resolution time which is mostly useless. -.PP -On Windows platforms the \fIdbi_time()\fR function is limited to millisecond -resolution. Which isn't sufficiently fine for our needs, but still -much better than integer resolution. This limited resolution means -that fast method calls will often register as taking 0 time. And -timings in general will have much more 'jitter' depending on where -within the 'current millisecond' the start and end timing was taken. -.PP -This documentation could be more clear. Probably needs to be reordered -to start with several examples and build from there. Trying to -explain the concepts first seems painful and to lead to just as -many forward references. (Patches welcome!) diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileData.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileData.3pm deleted file mode 100644 index 0a75d64..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileData.3pm +++ /dev/null @@ -1,337 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::ProfileData 3pm" -.TH DBI::ProfileData 3pm "2017-08-13" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::ProfileData \- manipulate DBI::ProfileDumper data dumps -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -The easiest way to use this module is through the dbiprof frontend -(see dbiprof for details): -.PP -.Vb 1 -\& dbiprof \-\-number 15 \-\-sort count -.Ve -.PP -This module can also be used to roll your own profile analysis: -.PP -.Vb 2 -\& # load data from dbi.prof -\& $prof = DBI::ProfileData\->new(File => "dbi.prof"); -\& -\& # get a count of the records (unique paths) in the data set -\& $count = $prof\->count(); -\& -\& # sort by longest overall time -\& $prof\->sort(field => "longest"); -\& -\& # sort by longest overall time, least to greatest -\& $prof\->sort(field => "longest", reverse => 1); -\& -\& # exclude records with key2 eq \*(Aqdisconnect\*(Aq -\& $prof\->exclude(key2 => \*(Aqdisconnect\*(Aq); -\& -\& # exclude records with key1 matching /^UPDATE/i -\& $prof\->exclude(key1 => qr/^UPDATE/i); -\& -\& # remove all records except those where key1 matches /^SELECT/i -\& $prof\->match(key1 => qr/^SELECT/i); -\& -\& # produce a formatted report with the given number of items -\& $report = $prof\->report(number => 10); -\& -\& # clone the profile data set -\& $clone = $prof\->clone(); -\& -\& # get access to hash of header values -\& $header = $prof\->header(); -\& -\& # get access to sorted array of nodes -\& $nodes = $prof\->nodes(); -\& -\& # format a single node in the same style as report() -\& $text = $prof\->format($nodes\->[0]); -\& -\& # get access to Data hash in DBI::Profile format -\& $Data = $prof\->Data(); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This module offers the ability to read, manipulate and format -DBI::ProfileDumper profile data. -.PP -Conceptually, a profile consists of a series of records, or nodes, -each of each has a set of statistics and set of keys. Each record -must have a unique set of keys, but there is no requirement that every -record have the same number of keys. -.SH "METHODS" -.IX Header "METHODS" -The following methods are supported by DBI::ProfileData objects. -.ie n .SS "$prof = DBI::ProfileData\->new(File => ""dbi.prof"")" -.el .SS "\f(CW$prof\fP = DBI::ProfileData\->new(File => ``dbi.prof'')" -.IX Subsection "$prof = DBI::ProfileData->new(File => dbi.prof)" -.ie n .SS "$prof = DBI::ProfileData\->new(File => ""dbi.prof"", Filter => sub { ... })" -.el .SS "\f(CW$prof\fP = DBI::ProfileData\->new(File => ``dbi.prof'', Filter => sub { ... })" -.IX Subsection "$prof = DBI::ProfileData->new(File => dbi.prof, Filter => sub { ... })" -.ie n .SS "$prof = DBI::ProfileData\->new(Files => [ ""dbi.prof.1"", ""dbi.prof.2"" ])" -.el .SS "\f(CW$prof\fP = DBI::ProfileData\->new(Files => [ ``dbi.prof.1'', ``dbi.prof.2'' ])" -.IX Subsection "$prof = DBI::ProfileData->new(Files => [ dbi.prof.1, dbi.prof.2 ])" -Creates a new DBI::ProfileData object. Takes either a single file -through the File option or a list of Files in an array ref. If -multiple files are specified then the header data from the first file -is used. -.PP -\fIFiles\fR -.IX Subsection "Files" -.PP -Reference to an array of file names to read. -.PP -\fIFile\fR -.IX Subsection "File" -.PP -Name of file to read. Takes precedence over \f(CW\*(C`Files\*(C'\fR. -.PP -\fIDeleteFiles\fR -.IX Subsection "DeleteFiles" -.PP -If true, the files are deleted after being read. -.PP -Actually the files are renamed with a \f(CW\*(C`deleteme\*(C'\fR suffix before being read, -and then, after reading all the files, they're all deleted together. -.PP -The files are locked while being read which, combined with the rename, makes it -safe to 'consume' files that are still being generated by DBI::ProfileDumper. -.PP -\fIFilter\fR -.IX Subsection "Filter" -.PP -The \f(CW\*(C`Filter\*(C'\fR parameter can be used to supply a code reference that can -manipulate the profile data as it is being read. This is most useful for -editing \s-1SQL\s0 statements so that slightly different statements in the raw data -will be merged and aggregated in the loaded data. For example: -.PP -.Vb 4 -\& Filter => sub { -\& my ($path_ref, $data_ref) = @_; -\& s/foo = \*(Aq.*?\*(Aq/foo = \*(Aq...\*(Aq/ for @$path_ref; -\& } -.Ve -.PP -Here's an example that performs some normalization on the \s-1SQL.\s0 It converts all -numbers to \f(CW\*(C`N\*(C'\fR and all quoted strings to \f(CW\*(C`S\*(C'\fR. It can also convert digits to -N within names. Finally, it summarizes long \*(L"\s-1IN \s0(...)\*(R" clauses. -.PP -It's aggressive and simplistic, but it's often sufficient, and serves as an -example that you can tailor to suit your own needs: -.PP -.Vb 12 -\& Filter => sub { -\& my ($path_ref, $data_ref) = @_; -\& local $_ = $path_ref\->[0]; # whichever element contains the SQL Statement -\& s/\eb\ed+\eb/N/g; # 42 \-> N -\& s/\eb0x[0\-9A\-Fa\-f]+\eb/N/g; # 0xFE \-> N -\& s/\*(Aq.*?\*(Aq/\*(AqS\*(Aq/g; # single quoted strings (doesn\*(Aqt handle escapes) -\& s/".*?"/"S"/g; # double quoted strings (doesn\*(Aqt handle escapes) -\& # convert names like log_20001231 into log_NNNNNNNN, controlled by $opt{n} -\& s/([a\-z_]+)(\ed{$opt{n},})/$1.(\*(AqN\*(Aq x length($2))/ieg if $opt{n}; -\& # abbreviate massive "in (...)" statements and similar -\& s!(([NS],){100,})!sprintf("$2,{repeated %d times}",length($1)/2)!eg; -\& } -.Ve -.PP -It's often better to perform this kinds of normalization in the \s-1DBI\s0 while the -data is being collected, to avoid too much memory being used by storing profile -data for many different \s-1SQL\s0 statement. See DBI::Profile. -.ie n .SS "$copy = $prof\->\fIclone()\fP;" -.el .SS "\f(CW$copy\fP = \f(CW$prof\fP\->\fIclone()\fP;" -.IX Subsection "$copy = $prof->clone();" -Clone a profile data set creating a new object. -.ie n .SS "$header = $prof\->\fIheader()\fP;" -.el .SS "\f(CW$header\fP = \f(CW$prof\fP\->\fIheader()\fP;" -.IX Subsection "$header = $prof->header();" -Returns a reference to a hash of header values. These are the key -value pairs included in the header section of the DBI::ProfileDumper -data format. For example: -.PP -.Vb 4 -\& $header = { -\& Path => [ \*(Aq!Statement\*(Aq, \*(Aq!MethodName\*(Aq ], -\& Program => \*(Aqt/42profile_data.t\*(Aq, -\& }; -.Ve -.PP -Note that modifying this hash will modify the header data stored -inside the profile object. -.ie n .SS "$nodes = $prof\->\fInodes()\fP" -.el .SS "\f(CW$nodes\fP = \f(CW$prof\fP\->\fInodes()\fP" -.IX Subsection "$nodes = $prof->nodes()" -Returns a reference the sorted nodes array. Each element in the array -is a single record in the data set. The first seven elements are the -same as the elements provided by DBI::Profile. After that each key is -in a separate element. For example: -.PP -.Vb 10 -\& $nodes = [ -\& [ -\& 2, # 0, count -\& 0.0312958955764771, # 1, total duration -\& 0.000490069389343262, # 2, first duration -\& 0.000176072120666504, # 3, shortest duration -\& 0.00140702724456787, # 4, longest duration -\& 1023115819.83019, # 5, time of first event -\& 1023115819.86576, # 6, time of last event -\& \*(AqSELECT foo FROM bar\*(Aq # 7, key1 -\& \*(Aqexecute\*(Aq # 8, key2 -\& # 6+N, keyN -\& ], -\& # ... -\& ]; -.Ve -.PP -Note that modifying this array will modify the node data stored inside -the profile object. -.ie n .SS "$count = $prof\->\fIcount()\fP" -.el .SS "\f(CW$count\fP = \f(CW$prof\fP\->\fIcount()\fP" -.IX Subsection "$count = $prof->count()" -Returns the number of items in the profile data set. -.ie n .SS "$prof\->sort(field => ""field"")" -.el .SS "\f(CW$prof\fP\->sort(field => ``field'')" -.IX Subsection "$prof->sort(field => field)" -.ie n .SS "$prof\->sort(field => ""field"", reverse => 1)" -.el .SS "\f(CW$prof\fP\->sort(field => ``field'', reverse => 1)" -.IX Subsection "$prof->sort(field => field, reverse => 1)" -Sorts data by the given field. Available fields are: -.PP -.Vb 4 -\& longest -\& total -\& count -\& shortest -.Ve -.PP -The default sort is greatest to smallest, which is the opposite of the -normal Perl meaning. This, however, matches the expected behavior of -the dbiprof frontend. -.ie n .SS "$count = $prof\->exclude(key2 => ""disconnect"")" -.el .SS "\f(CW$count\fP = \f(CW$prof\fP\->exclude(key2 => ``disconnect'')" -.IX Subsection "$count = $prof->exclude(key2 => disconnect)" -.ie n .SS "$count = $prof\->exclude(key2 => ""disconnect"", case_sensitive => 1)" -.el .SS "\f(CW$count\fP = \f(CW$prof\fP\->exclude(key2 => ``disconnect'', case_sensitive => 1)" -.IX Subsection "$count = $prof->exclude(key2 => disconnect, case_sensitive => 1)" -.ie n .SS "$count = $prof\->exclude(key1 => qr/^SELECT/i)" -.el .SS "\f(CW$count\fP = \f(CW$prof\fP\->exclude(key1 => qr/^SELECT/i)" -.IX Subsection "$count = $prof->exclude(key1 => qr/^SELECT/i)" -Removes records from the data set that match the given string or -regular expression. This method modifies the data in a permanent -fashion \- use \fIclone()\fR first to maintain the original data after -\&\fIexclude()\fR. Returns the number of nodes left in the profile data set. -.ie n .SS "$count = $prof\->match(key2 => ""disconnect"")" -.el .SS "\f(CW$count\fP = \f(CW$prof\fP\->match(key2 => ``disconnect'')" -.IX Subsection "$count = $prof->match(key2 => disconnect)" -.ie n .SS "$count = $prof\->match(key2 => ""disconnect"", case_sensitive => 1)" -.el .SS "\f(CW$count\fP = \f(CW$prof\fP\->match(key2 => ``disconnect'', case_sensitive => 1)" -.IX Subsection "$count = $prof->match(key2 => disconnect, case_sensitive => 1)" -.ie n .SS "$count = $prof\->match(key1 => qr/^SELECT/i)" -.el .SS "\f(CW$count\fP = \f(CW$prof\fP\->match(key1 => qr/^SELECT/i)" -.IX Subsection "$count = $prof->match(key1 => qr/^SELECT/i)" -Removes records from the data set that do not match the given string -or regular expression. This method modifies the data in a permanent -fashion \- use \fIclone()\fR first to maintain the original data after -\&\fImatch()\fR. Returns the number of nodes left in the profile data set. -.ie n .SS "$Data = $prof\->\fIData()\fP" -.el .SS "\f(CW$Data\fP = \f(CW$prof\fP\->\fIData()\fP" -.IX Subsection "$Data = $prof->Data()" -Returns the same Data hash structure as seen in DBI::Profile. This -structure is not sorted. The \fInodes()\fR structure probably makes more -sense for most analysis. -.ie n .SS "$text = $prof\->format($nodes\->[0])" -.el .SS "\f(CW$text\fP = \f(CW$prof\fP\->format($nodes\->[0])" -.IX Subsection "$text = $prof->format($nodes->[0])" -Formats a single node into a human-readable block of text. -.ie n .SS "$text = $prof\->report(number => 10)" -.el .SS "\f(CW$text\fP = \f(CW$prof\fP\->report(number => 10)" -.IX Subsection "$text = $prof->report(number => 10)" -Produces a report with the given number of items. -.SH "AUTHOR" -.IX Header "AUTHOR" -Sam Tregar -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -Copyright (C) 2002 Sam Tregar -.PP -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileDumper.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileDumper.3pm deleted file mode 100644 index 8ac518a..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileDumper.3pm +++ /dev/null @@ -1,256 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::ProfileDumper 3pm" -.TH DBI::ProfileDumper 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::ProfileDumper \- profile DBI usage and output data to a file -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -To profile an existing program using DBI::ProfileDumper, set the -\&\s-1DBI_PROFILE\s0 environment variable and run your program as usual. For -example, using bash: -.PP -.Vb 1 -\& DBI_PROFILE=2/DBI::ProfileDumper program.pl -.Ve -.PP -Then analyze the generated file (\fIdbi.prof\fR) with dbiprof: -.PP -.Vb 1 -\& dbiprof -.Ve -.PP -You can also activate DBI::ProfileDumper from within your code: -.PP -.Vb 1 -\& use DBI; -\& -\& # profile with default path (2) and output file (dbi.prof) -\& $dbh\->{Profile} = "!Statement/DBI::ProfileDumper"; -\& -\& # same thing, spelled out -\& $dbh\->{Profile} = "!Statement/DBI::ProfileDumper/File:dbi.prof"; -\& -\& # another way to say it -\& use DBI::ProfileDumper; -\& $dbh\->{Profile} = DBI::ProfileDumper\->new( -\& Path => [ \*(Aq!Statement\*(Aq ], -\& File => \*(Aqdbi.prof\*(Aq ); -\& -\& # using a custom path -\& $dbh\->{Profile} = DBI::ProfileDumper\->new( -\& Path => [ "foo", "bar" ], -\& File => \*(Aqdbi.prof\*(Aq, -\& ); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBI::ProfileDumper is a subclass of DBI::Profile which -dumps profile data to disk instead of printing a summary to your -screen. You can then use dbiprof to analyze the data in -a number of interesting ways, or you can roll your own analysis using -DBI::ProfileData. -.PP -\&\fB\s-1NOTE:\s0\fR For Apache/mod_perl applications, use -DBI::ProfileDumper::Apache. -.SH "USAGE" -.IX Header "USAGE" -One way to use this module is just to enable it in your \f(CW$dbh\fR: -.PP -.Vb 1 -\& $dbh\->{Profile} = "1/DBI::ProfileDumper"; -.Ve -.PP -This will write out profile data by statement into a file called -\&\fIdbi.prof\fR. If you want to modify either of these properties, you -can construct the DBI::ProfileDumper object yourself: -.PP -.Vb 5 -\& use DBI::ProfileDumper; -\& $dbh\->{Profile} = DBI::ProfileDumper\->new( -\& Path => [ \*(Aq!Statement\*(Aq ], -\& File => \*(Aqdbi.prof\*(Aq -\& ); -.Ve -.PP -The \f(CW\*(C`Path\*(C'\fR option takes the same values as in -DBI::Profile. The \f(CW\*(C`File\*(C'\fR option gives the name of the -file where results will be collected. If it already exists it will be -overwritten. -.PP -You can also activate this module by setting the \s-1DBI_PROFILE\s0 -environment variable: -.PP -.Vb 1 -\& $ENV{DBI_PROFILE} = "!Statement/DBI::ProfileDumper"; -.Ve -.PP -This will cause all \s-1DBI\s0 handles to share the same profiling object. -.SH "METHODS" -.IX Header "METHODS" -The following methods are available to be called using the profile -object. You can get access to the profile object from the Profile key -in any \s-1DBI\s0 handle: -.PP -.Vb 1 -\& my $profile = $dbh\->{Profile}; -.Ve -.SS "flush_to_disk" -.IX Subsection "flush_to_disk" -.Vb 1 -\& $profile\->flush_to_disk() -.Ve -.PP -Flushes all collected profile data to disk and empties the Data hash. Returns -the filename written to. If no profile data has been collected then the file is -not written and \fIflush_to_disk()\fR returns undef. -.PP -The file is locked while it's being written. A process 'consuming' the files -while they're being written to, should rename the file first, then lock it, -then read it, then close and delete it. The \f(CW\*(C`DeleteFiles\*(C'\fR option to -DBI::ProfileData does the right thing. -.PP -This method may be called multiple times during a program run. -.SS "empty" -.IX Subsection "empty" -.Vb 1 -\& $profile\->empty() -.Ve -.PP -Clears the Data hash without writing to disk. -.SS "filename" -.IX Subsection "filename" -.Vb 1 -\& $filename = $profile\->filename(); -.Ve -.PP -Get or set the filename. -.PP -The filename can be specified as a \s-1CODE\s0 reference, in which case the referenced -code should return the filename to be used. The code will be called with the -profile object as its first argument. -.SH "DATA FORMAT" -.IX Header "DATA FORMAT" -The data format written by DBI::ProfileDumper starts with a header -containing the version number of the module used to generate it. Then -a block of variable declarations describes the profile. After two -newlines, the profile data forms the body of the file. For example: -.PP -.Vb 3 -\& DBI::ProfileDumper 2.003762 -\& Path = [ \*(Aq!Statement\*(Aq, \*(Aq!MethodName\*(Aq ] -\& Program = t/42profile_data.t -\& -\& + 1 SELECT name FROM users WHERE id = ? -\& + 2 prepare -\& = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 -\& + 2 execute -\& 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 -\& + 2 fetchrow_hashref -\& = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 -\& + 1 UPDATE users SET name = ? WHERE id = ? -\& + 2 prepare -\& = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 -\& + 2 execute -\& = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 -.Ve -.PP -The lines beginning with \f(CW\*(C`+\*(C'\fR signs signify keys. The number after -the \f(CW\*(C`+\*(C'\fR sign shows the nesting level of the key. Lines beginning -with \f(CW\*(C`=\*(C'\fR are the actual profile data, in the same order as -in DBI::Profile. -.PP -Note that the same path may be present multiple times in the data file -since \f(CW\*(C`format()\*(C'\fR may be called more than once. When read by -DBI::ProfileData the data points will be merged to produce a single -data set for each distinct path. -.PP -The key strings are transformed in three ways. First, all backslashes -are doubled. Then all newlines and carriage-returns are transformed -into \f(CW\*(C`\en\*(C'\fR and \f(CW\*(C`\er\*(C'\fR respectively. Finally, any \s-1NULL\s0 bytes (\f(CW\*(C`\e0\*(C'\fR) -are entirely removed. When DBI::ProfileData reads the file the first -two transformations will be reversed, but \s-1NULL\s0 bytes will not be -restored. -.SH "AUTHOR" -.IX Header "AUTHOR" -Sam Tregar -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -Copyright (C) 2002 Sam Tregar -.PP -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileDumper::Apache.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileDumper::Apache.3pm deleted file mode 100644 index 8e4921b..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileDumper::Apache.3pm +++ /dev/null @@ -1,250 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::ProfileDumper::Apache 3pm" -.TH DBI::ProfileDumper::Apache 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::ProfileDumper::Apache \- capture DBI profiling data from Apache/mod_perl -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -Add this line to your \fIhttpd.conf\fR: -.PP -.Vb 1 -\& PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache -.Ve -.PP -(If you're using mod_perl2, see \*(L"When using mod_perl2\*(R" for some additional notes.) -.PP -Then restart your server. Access the code you wish to test using a -web browser, then shutdown your server. This will create a set of -\&\fIdbi.prof.*\fR files in your Apache log directory. -.PP -Get a profiling report with dbiprof: -.PP -.Vb 1 -\& dbiprof /path/to/your/apache/logs/dbi.prof.* -.Ve -.PP -When you're ready to perform another profiling run, delete the old files and start again. -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This module interfaces DBI::ProfileDumper to Apache/mod_perl. Using -this module you can collect profiling data from mod_perl applications. -It works by creating a DBI::ProfileDumper data file for each Apache -process. These files are created in your Apache log directory. You -can then use the dbiprof utility to analyze the profile files. -.SH "USAGE" -.IX Header "USAGE" -.SS "\s-1LOADING THE MODULE\s0" -.IX Subsection "LOADING THE MODULE" -The easiest way to use this module is just to set the \s-1DBI_PROFILE\s0 -environment variable in your \fIhttpd.conf\fR: -.PP -.Vb 1 -\& PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache -.Ve -.PP -The \s-1DBI\s0 will look after loading and using the module when the first \s-1DBI\s0 handle -is created. -.PP -It's also possible to use this module by setting the Profile attribute -of any \s-1DBI\s0 handle: -.PP -.Vb 1 -\& $dbh\->{Profile} = "2/DBI::ProfileDumper::Apache"; -.Ve -.PP -See DBI::ProfileDumper for more possibilities, and DBI::Profile for full -details of the \s-1DBI\s0's profiling mechanism. -.SS "\s-1WRITING PROFILE DATA\s0" -.IX Subsection "WRITING PROFILE DATA" -The profile data files will be written to your Apache log directory by default. -.PP -The user that the httpd processes run as will need write access to the -directory. So, for example, if you're running the child httpds as user 'nobody' -and using chronolog to write to the logs directory, then you'll need to change -the default. -.PP -You can change the destination directory either by specifying a \f(CW\*(C`Dir\*(C'\fR value -when creating the profile (like \f(CW\*(C`File\*(C'\fR in the DBI::ProfileDumper docs), -or you can use the \f(CW\*(C`DBI_PROFILE_APACHE_LOG_DIR\*(C'\fR env var to change that. For example: -.PP -.Vb 1 -\& PerlSetEnv DBI_PROFILE_APACHE_LOG_DIR /server_root/logs -.Ve -.PP -\fIWhen using mod_perl2\fR -.IX Subsection "When using mod_perl2" -.PP -Under mod_perl2 you'll need to either set the \f(CW\*(C`DBI_PROFILE_APACHE_LOG_DIR\*(C'\fR env var, -or enable the mod_perl2 \f(CW\*(C`GlobalRequest\*(C'\fR option, like this: -.PP -.Vb 1 -\& PerlOptions +GlobalRequest -.Ve -.PP -to the global config section you're about test with DBI::ProfileDumper::Apache. -If you don't do one of those then you'll see messages in your error_log similar to: -.PP -.Vb 2 -\& DBI::ProfileDumper::Apache on_destroy failed: Global $r object is not available. Set: -\& PerlOptions +GlobalRequest in httpd.conf at ..../DBI/ProfileDumper/Apache.pm line 144 -.Ve -.PP -\fINaming the files\fR -.IX Subsection "Naming the files" -.PP -The default file name is inherited from DBI::ProfileDumper via the -\&\fIfilename()\fR method, but DBI::ProfileDumper::Apache appends the parent pid and -the current pid, separated by dots, to that name. -.PP -\fISilencing the log\fR -.IX Subsection "Silencing the log" -.PP -By default a message is written to \s-1STDERR \s0(i.e., the apache error_log file) -when \fIflush_to_disk()\fR is called (either explicitly, or implicitly via \s-1DESTROY\s0). -.PP -That's usually very useful. If you don't want the log message you can silence -it by setting the \f(CW\*(C`Quiet\*(C'\fR attribute true. -.PP -.Vb 1 -\& PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache/Quiet:1 -\& -\& $dbh\->{Profile} = "!Statement/DBI::ProfileDumper/Quiet:1"; -\& -\& $dbh\->{Profile} = DBI::ProfileDumper\->new( -\& Path => [ \*(Aq!Statement\*(Aq ] -\& Quiet => 1 -\& ); -.Ve -.SS "\s-1GATHERING PROFILE DATA\s0" -.IX Subsection "GATHERING PROFILE DATA" -Once you have the module loaded, use your application as you normally -would. Stop the webserver when your tests are complete. Profile data -files will be produced when Apache exits and you'll see something like -this in your error_log: -.PP -.Vb 1 -\& DBI::ProfileDumper::Apache writing to /usr/local/apache/logs/dbi.prof.2604.2619 -.Ve -.PP -Now you can use dbiprof to examine the data: -.PP -.Vb 1 -\& dbiprof /usr/local/apache/logs/dbi.prof.2604.* -.Ve -.PP -By passing dbiprof a list of all generated files, dbiprof will -automatically merge them into one result set. You can also pass -dbiprof sorting and querying options, see dbiprof for details. -.SS "\s-1CLEANING UP\s0" -.IX Subsection "CLEANING UP" -Once you've made some code changes, you're ready to start again. -First, delete the old profile data files: -.PP -.Vb 1 -\& rm /usr/local/apache/logs/dbi.prof.* -.Ve -.PP -Then restart your server and get back to work. -.SH "OTHER ISSUES" -.IX Header "OTHER ISSUES" -.SS "Memory usage" -.IX Subsection "Memory usage" -DBI::Profile can use a lot of memory for very active applications because it -collects profiling data in memory for each distinct query run. -Calling \f(CW\*(C`flush_to_disk()\*(C'\fR will write the current data to disk and free the -memory it's using. For example: -.PP -.Vb 1 -\& $dbh\->{Profile}\->flush_to_disk() if $dbh\->{Profile}; -.Ve -.PP -or, rather than flush every time, you could flush less often: -.PP -.Vb 2 -\& $dbh\->{Profile}\->flush_to_disk() -\& if $dbh\->{Profile} and ++$i % 100; -.Ve -.SH "AUTHOR" -.IX Header "AUTHOR" -Sam Tregar -.SH "COPYRIGHT AND LICENSE" -.IX Header "COPYRIGHT AND LICENSE" -Copyright (C) 2002 Sam Tregar -.PP -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileSubs.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileSubs.3pm deleted file mode 100644 index d959bf6..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProfileSubs.3pm +++ /dev/null @@ -1,90 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::ProfileSubs 3pm" -.TH DBI::ProfileSubs 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::ProfileSubs \- Subroutines for dynamic profile Path -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& DBI_PROFILE=\*(Aq&norm_std_n3\*(Aq prog.pl -.Ve -.PP -This is new and still experimental. -.SH "TO DO" -.IX Header "TO DO" -Define come kind of naming convention for the subs. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProxyServer.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::ProxyServer.3pm deleted file mode 100644 index 11a122d..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::ProxyServer.3pm +++ /dev/null @@ -1,591 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::ProxyServer 3pm" -.TH DBI::ProxyServer 3pm "2016-04-21" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::ProxyServer \- a server for the DBD::Proxy driver -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 2 -\& use DBI::ProxyServer; -\& DBI::ProxyServer::main(@ARGV); -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -DBI::Proxy Server is a module for implementing a proxy for the \s-1DBI\s0 proxy -driver, DBD::Proxy. It allows access to databases over the network if the -\&\s-1DBMS\s0 does not offer networked operations. But the proxy server might be -useful for you, even if you have a \s-1DBMS\s0 with integrated network -functionality: It can be used as a \s-1DBI\s0 proxy in a firewalled environment. -.PP -DBI::ProxyServer runs as a daemon on the machine with the \s-1DBMS\s0 or on the -firewall. The client connects to the agent using the \s-1DBI\s0 driver DBD::Proxy, -thus in the exactly same way than using DBD::mysql, DBD::mSQL or any other -\&\s-1DBI\s0 driver. -.PP -The agent is implemented as a RPC::PlServer application. Thus you have -access to all the possibilities of this module, in particular encryption -and a similar configuration file. DBI::ProxyServer adds the possibility of -query restrictions: You can define a set of queries that a client may -execute and restrict access to those. (Requires a \s-1DBI\s0 driver that supports -parameter binding.) See \*(L"\s-1CONFIGURATION FILE\*(R"\s0. -.PP -The provided driver script, dbiproxy, may either be used as it is or -used as the basis for a local version modified to meet your needs. -.SH "OPTIONS" -.IX Header "OPTIONS" -When calling the \fIDBI::ProxyServer::main()\fR function, you supply an -array of options. These options are parsed by the Getopt::Long module. -The ProxyServer inherits all of RPC::PlServer's and hence Net::Daemon's -options and option handling, in particular the ability to read -options from either the command line or a config file. See -RPC::PlServer. See Net::Daemon. Available options include -.IP "\fIchroot\fR (\fB\-\-chroot=dir\fR)" 4 -.IX Item "chroot (--chroot=dir)" -(\s-1UNIX\s0 only) After doing a \fIbind()\fR, change root directory to the given -directory by doing a \fIchroot()\fR. This is useful for security, but it -restricts the environment a lot. For example, you need to load \s-1DBI\s0 -drivers in the config file or you have to create hard links to Unix -sockets, if your drivers are using them. For example, with MySQL, a -config file might contain the following lines: -.Sp -.Vb 9 -\& my $rootdir = \*(Aq/var/dbiproxy\*(Aq; -\& my $unixsockdir = \*(Aq/tmp\*(Aq; -\& my $unixsockfile = \*(Aqmysql.sock\*(Aq; -\& foreach $dir ($rootdir, "$rootdir$unixsockdir") { -\& mkdir 0755, $dir; -\& } -\& link("$unixsockdir/$unixsockfile", -\& "$rootdir$unixsockdir/$unixsockfile"); -\& require DBD::mysql; -\& -\& { -\& \*(Aqchroot\*(Aq => $rootdir, -\& ... -\& } -.Ve -.Sp -If you don't know \fIchroot()\fR, think of an \s-1FTP\s0 server where you can see a -certain directory tree only after logging in. See also the \-\-group and -\&\-\-user options. -.IP "\fIclients\fR" 4 -.IX Item "clients" -An array ref with a list of clients. Clients are hash refs, the attributes -\&\fIaccept\fR (0 for denying access and 1 for permitting) and \fImask\fR, a Perl -regular expression for the clients \s-1IP\s0 number or its host name. -.IP "\fIconfigfile\fR (\fB\-\-configfile=file\fR)" 4 -.IX Item "configfile (--configfile=file)" -Config files are assumed to return a single hash ref that overrides the -arguments of the new method. However, command line arguments in turn take -precedence over the config file. See the \*(L"\s-1CONFIGURATION FILE\*(R"\s0 section -below for details on the config file. -.IP "\fIdebug\fR (\fB\-\-debug\fR)" 4 -.IX Item "debug (--debug)" -Turn debugging mode on. Mainly this asserts that logging messages of -level \*(L"debug\*(R" are created. -.IP "\fIfacility\fR (\fB\-\-facility=mode\fR)" 4 -.IX Item "facility (--facility=mode)" -(\s-1UNIX\s0 only) Facility to use for Sys::Syslog. The default is -\&\fBdaemon\fR. -.IP "\fIgroup\fR (\fB\-\-group=gid\fR)" 4 -.IX Item "group (--group=gid)" -After doing a \fIbind()\fR, change the real and effective \s-1GID\s0 to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the \-\-user option. -.Sp -\&\s-1GID\s0's can be passed as group names or numeric values. -.IP "\fIlocaladdr\fR (\fB\-\-localaddr=ip\fR)" 4 -.IX Item "localaddr (--localaddr=ip)" -By default a daemon is listening to any \s-1IP\s0 number that a machine -has. This attribute allows one to restrict the server to the given -\&\s-1IP\s0 number. -.IP "\fIlocalport\fR (\fB\-\-localport=port\fR)" 4 -.IX Item "localport (--localport=port)" -This attribute sets the port on which the daemon is listening. It -must be given somehow, as there's no default. -.IP "\fIlogfile\fR (\fB\-\-logfile=file\fR)" 4 -.IX Item "logfile (--logfile=file)" -Be default logging messages will be written to the syslog (Unix) or -to the event log (Windows \s-1NT\s0). On other operating systems you need to -specify a log file. The special value \*(L"\s-1STDERR\*(R"\s0 forces logging to -stderr. See Net::Daemon::Log for details. -.IP "\fImode\fR (\fB\-\-mode=modename\fR)" 4 -.IX Item "mode (--mode=modename)" -The server can run in three different modes, depending on the environment. -.Sp -If you are running Perl 5.005 and did compile it for threads, then the -server will create a new thread for each connection. The thread will -execute the server's \fIRun()\fR method and then terminate. This mode is the -default, you can force it with \*(L"\-\-mode=threads\*(R". -.Sp -If threads are not available, but you have a working \fIfork()\fR, then the -server will behave similar by creating a new process for each connection. -This mode will be used automatically in the absence of threads or if -you use the \*(L"\-\-mode=fork\*(R" option. -.Sp -Finally there's a single-connection mode: If the server has accepted a -connection, he will enter the \fIRun()\fR method. No other connections are -accepted until the \fIRun()\fR method returns (if the client disconnects). -This operation mode is useful if you have neither threads nor \fIfork()\fR, -for example on the Macintosh. For debugging purposes you can force this -mode with \*(L"\-\-mode=single\*(R". -.IP "\fIpidfile\fR (\fB\-\-pidfile=file\fR)" 4 -.IX Item "pidfile (--pidfile=file)" -(\s-1UNIX\s0 only) If this option is present, a \s-1PID\s0 file will be created at the -given location. Default is to not create a pidfile. -.IP "\fIuser\fR (\fB\-\-user=uid\fR)" 4 -.IX Item "user (--user=uid)" -After doing a \fIbind()\fR, change the real and effective \s-1UID\s0 to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the \-\-group and the \-\-chroot options. -.Sp -\&\s-1UID\s0's can be passed as group names or numeric values. -.IP "\fIversion\fR (\fB\-\-version\fR)" 4 -.IX Item "version (--version)" -Suppresses startup of the server; instead the version string will -be printed and the program exits immediately. -.SH "SHUTDOWN" -.IX Header "SHUTDOWN" -DBI::ProxyServer is built on RPC::PlServer which is, in turn, built on Net::Daemon. -.PP -You should refer to Net::Daemon for how to shutdown the server, except that -you can't because it's not currently documented there (as of v0.43). -The bottom-line is that it seems that there's no support for graceful shutdown. -.SH "CONFIGURATION FILE" -.IX Header "CONFIGURATION FILE" -The configuration file is just that of \fIRPC::PlServer\fR or \fINet::Daemon\fR -with some additional attributes in the client list. -.PP -The config file is a Perl script. At the top of the file you may include -arbitrary Perl source, for example load drivers at the start (useful -to enhance performance), prepare a chroot environment and so on. -.PP -The important thing is that you finally return a hash ref of option -name/value pairs. The possible options are listed above. -.PP -All possibilities of Net::Daemon and RPC::PlServer apply, in particular -.IP "Host and/or User dependent access control" 4 -.IX Item "Host and/or User dependent access control" -.PD 0 -.IP "Host and/or User dependent encryption" 4 -.IX Item "Host and/or User dependent encryption" -.IP "Changing \s-1UID\s0 and/or \s-1GID\s0 after binding to the port" 4 -.IX Item "Changing UID and/or GID after binding to the port" -.IP "Running in a \fIchroot()\fR environment" 4 -.IX Item "Running in a chroot() environment" -.PD -.PP -Additionally the server offers you query restrictions. Suggest the -following client list: -.PP -.Vb 10 -\& \*(Aqclients\*(Aq => [ -\& { \*(Aqmask\*(Aq => \*(Aq^admin\e.company\e.com$\*(Aq, -\& \*(Aqaccept\*(Aq => 1, -\& \*(Aqusers\*(Aq => [ \*(Aqroot\*(Aq, \*(Aqwwwrun\*(Aq ], -\& }, -\& { -\& \*(Aqmask\*(Aq => \*(Aq^admin\e.company\e.com$\*(Aq, -\& \*(Aqaccept\*(Aq => 1, -\& \*(Aqusers\*(Aq => [ \*(Aqroot\*(Aq, \*(Aqwwwrun\*(Aq ], -\& \*(Aqsql\*(Aq => { -\& \*(Aqselect\*(Aq => \*(AqSELECT * FROM foo\*(Aq, -\& \*(Aqinsert\*(Aq => \*(AqINSERT INTO foo VALUES (?, ?, ?)\*(Aq -\& } -\& } -.Ve -.PP -then only the users root and wwwrun may connect from admin.company.com, -executing arbitrary queries, but only wwwrun may connect from other -hosts and is restricted to -.PP -.Vb 1 -\& $sth\->prepare("select"); -.Ve -.PP -or -.PP -.Vb 1 -\& $sth\->prepare("insert"); -.Ve -.PP -which in fact are \*(L"\s-1SELECT\s0 * \s-1FROM\s0 foo\*(R" or \*(L"\s-1INSERT INTO\s0 foo \s-1VALUES \s0(?, ?, ?)\*(R". -.SH "Proxyserver Configuration file (bigger example)" -.IX Header "Proxyserver Configuration file (bigger example)" -This section tells you how to restrict a DBI-Proxy: Not every user from -every workstation shall be able to execute every query. -.PP -There is a perl program \*(L"dbiproxy\*(R" which runs on a machine which is able -to connect to all the databases we wish to reach. All Perl-DBD-drivers must -be installed on this machine. You can also reach databases for which drivers -are not available on the machine where you run the program querying the -database, e.g. ask MS-Access-database from Linux. -.PP -Create a configuration file \*(L"proxy_oracle.cfg\*(R" at the dbproxy-server: -.PP -.Vb 8 -\& { -\& # This shall run in a shell or a DOS\-window -\& # facility => \*(Aqdaemon\*(Aq, -\& pidfile => \*(Aqyour_dbiproxy.pid\*(Aq, -\& logfile => 1, -\& debug => 0, -\& mode => \*(Aqsingle\*(Aq, -\& localport => \*(Aq12400\*(Aq, -\& -\& # Access control, the first match in this list wins! -\& # So the order is important -\& clients => [ -\& # hint to organize: -\& # the most specialized rules for single machines/users are 1st -\& # then the denying rules -\& # then the rules about whole networks -\& -\& # rule: internal_webserver -\& # desc: to get statistical information -\& { -\& # this IP\-address only is meant -\& mask => \*(Aq^10\e.95\e.81\e.243$\*(Aq, -\& # accept (not defer) connections like this -\& accept => 1, -\& # only users from this list -\& # are allowed to log on -\& users => [ \*(Aqinformationdesk\*(Aq ], -\& # only this statistical query is allowed -\& # to get results for a web\-query -\& sql => { -\& alive => \*(Aqselect count(*) from dual\*(Aq, -\& statistic_area => \*(Aqselect count(*) from e01admin.e01e203 where geb_bezei like ?\*(Aq, -\& } -\& }, -\& -\& # rule: internal_bad_guy_1 -\& { -\& mask => \*(Aq^10\e.95\e.81\e.1$\*(Aq, -\& accept => 0, -\& }, -\& -\& # rule: employee_workplace -\& # desc: get detailed information -\& { -\& # any IP\-address is meant here -\& mask => \*(Aq^10\e.95\e.81\e.(\ed+)$\*(Aq, -\& # accept (not defer) connections like this -\& accept => 1, -\& # only users from this list -\& # are allowed to log on -\& users => [ \*(Aqinformationdesk\*(Aq, \*(Aqlippmann\*(Aq ], -\& # all these queries are allowed: -\& sql => { -\& search_city => \*(Aqselect ort_nr, plz, ort from e01admin.e01e200 where plz like ?\*(Aq, -\& search_area => \*(Aqselect gebiettyp, geb_bezei from e01admin.e01e203 where geb_bezei like ? or geb_bezei like ?\*(Aq, -\& } -\& }, -\& -\& # rule: internal_bad_guy_2 -\& # This does NOT work, because rule "employee_workplace" hits -\& # with its ip\-address\-mask of the whole network -\& { -\& # don\*(Aqt accept connection from this ip\-address -\& mask => \*(Aq^10\e.95\e.81\e.5$\*(Aq, -\& accept => 0, -\& } -\& ] -\& } -.Ve -.PP -Start the proxyserver like this: -.PP -.Vb 3 -\& rem well\-set Oracle_home needed for Oracle -\& set ORACLE_HOME=d:\eoracle\eora81 -\& dbiproxy \-\-configfile proxy_oracle.cfg -.Ve -.SS "Testing the connection from a remote machine" -.IX Subsection "Testing the connection from a remote machine" -Call a program \*(L"dbish\*(R" from your commandline. I take the machine from rule \*(L"internal_webserver\*(R" -.PP -.Vb 1 -\& dbish "dbi:Proxy:hostname=oracle.zdf;port=12400;dsn=dbi:Oracle:e01" informationdesk xxx -.Ve -.PP -There will be a shell-prompt: -.PP -.Vb 1 -\& informationdesk@dbi...> alive -\& -\& Current statement buffer (enter \*(Aq/\*(Aq...): -\& alive -\& -\& informationdesk@dbi...> / -\& COUNT(*) -\& \*(Aq1\*(Aq -\& [1 rows of 1 fields returned] -.Ve -.SS "Testing the connection with a perl-script" -.IX Subsection "Testing the connection with a perl-script" -Create a perl-script like this: -.PP -.Vb 2 -\& # file: oratest.pl -\& # call me like this: perl oratest.pl user password -\& -\& use strict; -\& use DBI; -\& -\& my $user = shift || die "Usage: $0 user password"; -\& my $pass = shift || die "Usage: $0 user password"; -\& my $config = { -\& dsn_at_proxy => "dbi:Oracle:e01", -\& proxy => "hostname=oechsle.zdf;port=12400", -\& }; -\& my $dsn = sprintf "dbi:Proxy:%s;dsn=%s", -\& $config\->{proxy}, -\& $config\->{dsn_at_proxy}; -\& -\& my $dbh = DBI\->connect( $dsn, $user, $pass ) -\& || die "connect did not work: $DBI::errstr"; -\& -\& my $sql = "search_city"; -\& printf "%s\en%s\en%s\en", "="x40, $sql, "="x40; -\& my $cur = $dbh\->prepare($sql); -\& $cur\->bind_param(1,\*(Aq905%\*(Aq); -\& &show_result ($cur); -\& -\& my $sql = "search_area"; -\& printf "%s\en%s\en%s\en", "="x40, $sql, "="x40; -\& my $cur = $dbh\->prepare($sql); -\& $cur\->bind_param(1,\*(AqPfarr%\*(Aq); -\& $cur\->bind_param(2,\*(AqBronnamberg%\*(Aq); -\& &show_result ($cur); -\& -\& my $sql = "statistic_area"; -\& printf "%s\en%s\en%s\en", "="x40, $sql, "="x40; -\& my $cur = $dbh\->prepare($sql); -\& $cur\->bind_param(1,\*(AqPfarr%\*(Aq); -\& &show_result ($cur); -\& -\& $dbh\->disconnect; -\& exit; -\& -\& -\& sub show_result { -\& my $cur = shift; -\& unless ($cur\->execute()) { -\& print "Could not execute\en"; -\& return; -\& } -\& -\& my $rownum = 0; -\& while (my @row = $cur\->fetchrow_array()) { -\& printf "Row is: %s\en", join(", ",@row); -\& if ($rownum++ > 5) { -\& print "... and so on\en"; -\& last; -\& } -\& } -\& $cur\->finish; -\& } -.Ve -.PP -The result -.PP -.Vb 10 -\& C:\e>perl oratest.pl informationdesk xxx -\& ======================================== -\& search_city -\& ======================================== -\& Row is: 3322, 9050, Chemnitz -\& Row is: 3678, 9051, Chemnitz -\& Row is: 10447, 9051, Chemnitz -\& Row is: 12128, 9051, Chemnitz -\& Row is: 10954, 90513, Zirndorf -\& Row is: 5808, 90513, Zirndorf -\& Row is: 5715, 90513, Zirndorf -\& ... and so on -\& ======================================== -\& search_area -\& ======================================== -\& Row is: 101, Bronnamberg -\& Row is: 400, Pfarramt Zirndorf -\& Row is: 400, Pfarramt Rosstal -\& Row is: 400, Pfarramt Oberasbach -\& Row is: 401, Pfarramt Zirndorf -\& Row is: 401, Pfarramt Rosstal -\& ======================================== -\& statistic_area -\& ======================================== -\& DBD::Proxy::st execute failed: Server returned error: Failed to execute method CallMethod: Unknown SQL query: statistic_area at E:/Perl/site/lib/DBI/ProxyServer.pm line 258. -\& Could not execute -.Ve -.SS "How the configuration works" -.IX Subsection "How the configuration works" -The most important section to control access to your dbi-proxy is \*(L"client=>\*(R" -in the file \*(L"proxy_oracle.cfg\*(R": -.PP -Controlling which person at which machine is allowed to access -.IP "\(bu" 4 -\&\*(L"mask\*(R" is a perl regular expression against the plain ip-address of the machine which wishes to connect _or_ the reverse-lookup from a nameserver. -.IP "\(bu" 4 -\&\*(L"accept\*(R" tells the dbiproxy-server whether ip-adresse like in \*(L"mask\*(R" are allowed to connect or not (0/1) -.IP "\(bu" 4 -\&\*(L"users\*(R" is a reference to a list of usernames which must be matched, this is \s-1NOT\s0 a regular expression. -.PP -Controlling which SQL-statements are allowed -.PP -You can put every SQL-statement you like in simply omitting \*(L"sql => ...\*(R", but the more important thing is to restrict the connection so that only allowed queries are possible. -.PP -If you include an sql-section in your config-file like this: -.PP -.Vb 4 -\& sql => { -\& alive => \*(Aqselect count(*) from dual\*(Aq, -\& statistic_area => \*(Aqselect count(*) from e01admin.e01e203 where geb_bezei like ?\*(Aq, -\& } -.Ve -.PP -The user is allowed to put two queries against the dbi-proxy. The queries are _not_ \*(L"select count(*)...\*(R", the queries are \*(L"alive\*(R" and \*(L"statistic_area\*(R"! These keywords are replaced by the real query. So you can run a query for \*(L"alive\*(R": -.PP -.Vb 3 -\& my $sql = "alive"; -\& my $cur = $dbh\->prepare($sql); -\& ... -.Ve -.PP -The flexibility is that you can put parameters in the where-part of the query so the query are not static. Simply replace a value in the where-part of the query through a question mark and bind it as a parameter to the query. -.PP -.Vb 5 -\& my $sql = "statistic_area"; -\& my $cur = $dbh\->prepare($sql); -\& $cur\->bind_param(1,\*(Aq905%\*(Aq); -\& # A second parameter would be called like this: -\& # $cur\->bind_param(2,\*(Aq98%\*(Aq); -.Ve -.PP -The result is this query: -.PP -.Vb 2 -\& select count(*) from e01admin.e01e203 -\& where geb_bezei like \*(Aq905%\*(Aq -.Ve -.PP -Don't try to put parameters into the sql-query like this: -.PP -.Vb 7 -\& # Does not work like you think. -\& # Only the first word of the query is parsed, -\& # so it\*(Aqs changed to "statistic_area", the rest is omitted. -\& # You _have_ to work with $cur\->bind_param. -\& my $sql = "statistic_area 905%"; -\& my $cur = $dbh\->prepare($sql); -\& ... -.Ve -.SS "Problems" -.IX Subsection "Problems" -.IP "\(bu" 4 -I don't know how to restrict users to special databases. -.IP "\(bu" 4 -I don't know how to pass query-parameters via dbish -.SH "SECURITY WARNING" -.IX Header "SECURITY WARNING" -RPC::PlServer used underneath is not secure due to serializing and -deserializing data with Storable module. Use the proxy driver only in -trusted environment. -.SH "AUTHOR" -.IX Header "AUTHOR" -.Vb 4 -\& Copyright (c) 1997 Jochen Wiedmann -\& Am Eisteich 9 -\& 72555 Metzingen -\& Germany -\& -\& Email: joe@ispsoft.de -\& Phone: +49 7123 14881 -.Ve -.PP -The DBI::ProxyServer module is free software; you can redistribute it -and/or modify it under the same terms as Perl itself. In particular -permission is granted to Tim Bunce for distributing this as a part of -the \s-1DBI.\s0 -.SH "SEE ALSO" -.IX Header "SEE ALSO" -dbiproxy, DBD::Proxy, \s-1DBI\s0, RPC::PlServer, -RPC::PlClient, Net::Daemon, Net::Daemon::Log, -Sys::Syslog, Win32::EventLog, syslog diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::PurePerl.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::PurePerl.3pm deleted file mode 100644 index 03e1f52..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::PurePerl.3pm +++ /dev/null @@ -1,243 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::PurePerl 3pm" -.TH DBI::PurePerl 3pm "2016-04-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::PurePerl \-\- a DBI emulation using pure perl (no C/XS compilation required) -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 2 -\& BEGIN { $ENV{DBI_PUREPERL} = 2 } -\& use DBI; -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This is a pure perl emulation of the \s-1DBI\s0 internals. In almost all -cases you will be better off using standard \s-1DBI\s0 since the portions -of the standard version written in C make it *much* faster. -.PP -However, if you are in a situation where it isn't possible to install -a compiled version of standard \s-1DBI,\s0 and you're using pure-perl \s-1DBD\s0 -drivers, then this module allows you to use most common features -of \s-1DBI\s0 without needing any changes in your scripts. -.SH "EXPERIMENTAL STATUS" -.IX Header "EXPERIMENTAL STATUS" -DBI::PurePerl is new so please treat it as experimental pending -more extensive testing. So far it has passed all tests with \s-1DBD::CSV,\s0 -DBD::AnyData, DBD::XBase, DBD::Sprite, DBD::mysqlPP. Please send -bug reports to Jeff Zucker at with a cc to -. -.SH "USAGE" -.IX Header "USAGE" -The usage is the same as for standard \s-1DBI\s0 with the exception -that you need to set the environment variable \s-1DBI_PUREPERL\s0 if -you want to use the PurePerl version. -.PP -.Vb 2 -\& DBI_PUREPERL == 0 (the default) Always use compiled DBI, die -\& if it isn\*(Aqt properly compiled & installed -\& -\& DBI_PUREPERL == 1 Use compiled DBI if it is properly compiled -\& & installed, otherwise use PurePerl -\& -\& DBI_PUREPERL == 2 Always use PurePerl -.Ve -.PP -You may set the environment variable in your shell (e.g. with -set or setenv or export, etc) or else set it in your script like -this: -.PP -.Vb 1 -\& BEGIN { $ENV{DBI_PUREPERL}=2 } -.Ve -.PP -before you \f(CW\*(C`use DBI;\*(C'\fR. -.SH "INSTALLATION" -.IX Header "INSTALLATION" -In most situations simply install \s-1DBI \s0(see the \s-1DBI\s0 pod for details). -.PP -In the situation in which you can not install \s-1DBI\s0 itself, you -may manually copy \s-1DBI\s0.pm and PurePerl.pm into the appropriate -directories. -.PP -For example: -.PP -.Vb 2 -\& cp DBI.pm /usr/jdoe/mylibs/. -\& cp PurePerl.pm /usr/jdoe/mylibs/DBI/. -.Ve -.PP -Then add this to the top of scripts: -.PP -.Vb 4 -\& BEGIN { -\& $ENV{DBI_PUREPERL} = 1; # or =2 -\& unshift @INC, \*(Aq/usr/jdoe/mylibs\*(Aq; -\& } -.Ve -.PP -(Or should we perhaps patch Makefile.PL so that if \s-1DBI_PUREPERL\s0 -is set to 2 prior to make, the normal compile process is skipped -and the files are installed automatically?) -.SH "DIFFERENCES BETWEEN DBI AND DBI::PurePerl" -.IX Header "DIFFERENCES BETWEEN DBI AND DBI::PurePerl" -.SS "Attributes" -.IX Subsection "Attributes" -Boolean attributes still return boolean values but the actual values -used may be different, i.e., 0 or undef instead of an empty string. -.PP -Some handle attributes are either not supported or have very limited -functionality: -.PP -.Vb 7 -\& ActiveKids -\& InactiveDestroy -\& AutoInactiveDestroy -\& Kids -\& Taint -\& TaintIn -\& TaintOut -.Ve -.PP -(and probably others) -.SS "Tracing" -.IX Subsection "Tracing" -Trace functionality is more limited and the code to handle tracing is -only embedded into DBI:PurePerl if the \s-1DBI_TRACE\s0 environment variable -is defined. To enable total tracing you can set the \s-1DBI_TRACE\s0 -environment variable as usual. But to enable individual handle -tracing using the \fItrace()\fR method you also need to set the \s-1DBI_TRACE\s0 -environment variable, but set it to 0. -.SS "Parameter Usage Checking" -.IX Subsection "Parameter Usage Checking" -The \s-1DBI\s0 does some basic parameter count checking on method calls. -DBI::PurePerl doesn't. -.SS "Speed" -.IX Subsection "Speed" -DBI::PurePerl is slower. Although, with some drivers in some -contexts this may not be very significant for you. -.PP -By way of example... the test.pl script in the \s-1DBI\s0 source -distribution has a simple benchmark that just does: -.PP -.Vb 3 -\& my $null_dbh = DBI\->connect(\*(Aqdbi:NullP:\*(Aq,\*(Aq\*(Aq,\*(Aq\*(Aq); -\& my $i = 10_000; -\& $null_dbh\->prepare(\*(Aq\*(Aq) while $i\-\-; -.Ve -.PP -In other words just prepares a statement, creating and destroying -a statement handle, over and over again. Using the real \s-1DBI\s0 this -runs at ~4550 handles per second whereas DBI::PurePerl manages -~2800 per second on the same machine (not too bad really). -.SS "May not fully support \fIhash()\fP" -.IX Subsection "May not fully support hash()" -If you want to use type 1 hash, i.e., \f(CW\*(C`hash($string,1)\*(C'\fR with -DBI::PurePerl, you'll need version 1.56 or higher of Math::BigInt -(available on \s-1CPAN\s0). -.SS "Doesn't support \fIpreparse()\fP" -.IX Subsection "Doesn't support preparse()" -The \s-1DBI\-\s0>\fIpreparse()\fR method isn't supported in DBI::PurePerl. -.SS "Doesn't support DBD::Proxy" -.IX Subsection "Doesn't support DBD::Proxy" -There's a subtle problem somewhere I've not been able to identify. -DBI::ProxyServer seem to work fine with DBI::PurePerl but DBD::Proxy -does not work 100% (which is sad because that would be far more useful :) -Try re-enabling t/80proxy.t for DBI::PurePerl to see if the problem -that remains will affect you're usage. -.SS "Others" -.IX Subsection "Others" -.Vb 1 -\& can() \- doesn\*(Aqt have any special behaviour -.Ve -.PP -Please let us know if you find any other differences between \s-1DBI\s0 -and DBI::PurePerl. -.SH "AUTHORS" -.IX Header "AUTHORS" -Tim Bunce and Jeff Zucker. -.PP -Tim provided the direction and basis for the code. The original -idea for the module and most of the brute force porting from C to -Perl was by Jeff. Tim then reworked some core parts to boost the -performance and accuracy of the emulation. Thanks also to Randal -Schwartz and John Tobey for patches. -.SH "COPYRIGHT" -.IX Header "COPYRIGHT" -Copyright (c) 2002 Tim Bunce Ireland. -.PP -See \s-1COPYRIGHT\s0 section in \s-1DBI\s0.pm for usage and distribution rights. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::SQL::Nano.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::SQL::Nano.3pm deleted file mode 100644 index 2791ddf..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::SQL::Nano.3pm +++ /dev/null @@ -1,279 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::SQL::Nano 3pm" -.TH DBI::SQL::Nano 3pm "2016-04-23" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::SQL::Nano \- a very tiny SQL engine -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 7 -\& BEGIN { $ENV{DBI_SQL_NANO}=1 } # forces use of Nano rather than SQL::Statement -\& use DBI::SQL::Nano; -\& use Data::Dumper; -\& my $stmt = DBI::SQL::Nano::Statement\->new( -\& "SELECT bar,baz FROM foo WHERE qux = 1" -\& ) or die "Couldn\*(Aqt parse"; -\& print Dumper $stmt; -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\f(CW\*(C`DBI::SQL::Nano\*(C'\fR is meant as a \fIvery\fR minimal \s-1SQL\s0 engine for use in -situations where SQL::Statement is not available. In most situations you are -better off installing SQL::Statement although DBI::SQL::Nano may be faster -for some \fBvery\fR simple tasks. -.PP -DBI::SQL::Nano, like SQL::Statement is primarily intended to provide a \s-1SQL\s0 -engine for use with some pure perl DBDs including \s-1DBD::DBM\s0, \s-1DBD::CSV\s0, -DBD::AnyData, and DBD::Excel. It is not of much use in and of itself. -You can dump out the structure of a parsed \s-1SQL\s0 statement, but that is about -it. -.SH "USAGE" -.IX Header "USAGE" -.SS "Setting the \s-1DBI_SQL_NANO\s0 flag" -.IX Subsection "Setting the DBI_SQL_NANO flag" -By default, when a \f(CW\*(C`DBD\*(C'\fR uses \f(CW\*(C`DBI::SQL::Nano\*(C'\fR, the module will -look to see if \f(CW\*(C`SQL::Statement\*(C'\fR is installed. If it is, SQL::Statement -objects are used. If SQL::Statement is not available, DBI::SQL::Nano -objects are used. -.PP -In some cases, you may wish to use DBI::SQL::Nano objects even if -SQL::Statement is available. To force usage of DBI::SQL::Nano objects -regardless of the availability of SQL::Statement, set the environment -variable \s-1DBI_SQL_NANO\s0 to 1. -.PP -You can set the environment variable in your shell prior to running your -script (with \s-1SET\s0 or \s-1EXPORT\s0 or whatever), or else you can set it in your -script by putting this at the top of the script: -.PP -.Vb 1 -\& BEGIN { $ENV{DBI_SQL_NANO} = 1 } -.Ve -.SS "Supported \s-1SQL\s0 syntax" -.IX Subsection "Supported SQL syntax" -.Vb 2 -\& Here\*(Aqs a pseudo\-BNF. Square brackets [] indicate optional items; -\& Angle brackets <> indicate items defined elsewhere in the BNF. -\& -\& statement ::= -\& DROP TABLE [IF EXISTS] -\& | CREATE TABLE -\& | INSERT INTO [] VALUES -\& | DELETE FROM [] -\& | UPDATE SET -\& | SELECT FROM [] -\& [] -\& -\& the optional IF EXISTS clause ::= -\& * similar to MySQL \- prevents errors when trying to drop -\& a table that doesn\*(Aqt exist -\& -\& identifiers ::= -\& * table and column names should be valid SQL identifiers -\& * especially avoid using spaces and commas in identifiers -\& * note: there is no error checking for invalid names, some -\& will be accepted, others will cause parse failures -\& -\& table_name ::= -\& * only one table (no multiple table operations) -\& * see identifier for valid table names -\& -\& col_def_list ::= -\& * a parens delimited, comma\-separated list of column names -\& * see identifier for valid column names -\& * column types and column constraints may be included but are ignored -\& e.g. these are all the same: -\& (id,phrase) -\& (id INT, phrase VARCHAR(40)) -\& (id INT PRIMARY KEY, phrase VARCHAR(40) NOT NULL) -\& * you are *strongly* advised to put in column types even though -\& they are ignored ... it increases portability -\& -\& insert_col_list ::= -\& * a parens delimited, comma\-separated list of column names -\& * as in standard SQL, this is optional -\& -\& select_col_list ::= -\& * a comma\-separated list of column names -\& * or an asterisk denoting all columns -\& -\& val_list ::= -\& * a parens delimited, comma\-separated list of values which can be: -\& * placeholders (an unquoted question mark) -\& * numbers (unquoted numbers) -\& * column names (unquoted strings) -\& * nulls (unquoted word NULL) -\& * strings (delimited with single quote marks); -\& * note: leading and trailing percent mark (%) and underscore (_) -\& can be used as wildcards in quoted strings for use with -\& the LIKE and CLIKE operators -\& * note: escaped single quotation marks within strings are not -\& supported, neither are embedded commas, use placeholders instead -\& -\& set_clause ::= -\& * a comma\-separated list of column = value pairs -\& * see val_list for acceptable value formats -\& -\& where_clause ::= -\& * a single "column/value column/value" predicate, optionally -\& preceded by "NOT" -\& * note: multiple predicates combined with ORs or ANDs are not supported -\& * see val_list for acceptable value formats -\& * op may be one of: -\& < > >= <= = <> LIKE CLIKE IS -\& * CLIKE is a case insensitive LIKE -\& -\& order_clause ::= column_name [ASC|DESC] -\& * a single column optional ORDER BY clause is supported -\& * as in standard SQL, if neither ASC (ascending) nor -\& DESC (descending) is specified, ASC becomes the default -.Ve -.SH "TABLES" -.IX Header "TABLES" -DBI::SQL::Nano::Statement operates on exactly one table. This table will be -opened by inherit from DBI::SQL::Nano::Statement and implements the -\&\f(CW\*(C`open_table\*(C'\fR method. -.PP -.Vb 5 -\& sub open_table ($$$$$) -\& { -\& ... -\& return Your::Table\->new( \e%attributes ); -\& } -.Ve -.PP -DBI::SQL::Nano::Statement_ expects a rudimentary interface is implemented by -the table object, as well as SQL::Statement expects. -.PP -.Vb 1 -\& package Your::Table; -\& -\& use vars qw(@ISA); -\& @ISA = qw(DBI::SQL::Nano::Table); -\& -\& sub drop ($$) { ... } -\& sub fetch_row ($$$) { ... } -\& sub push_row ($$$) { ... } -\& sub push_names ($$$) { ... } -\& sub truncate ($$) { ... } -\& sub seek ($$$$) { ... } -.Ve -.PP -The base class interfaces are provided by DBI::SQL::Nano::Table_ in case of -relying on DBI::SQL::Nano or SQL::Eval::Table (see SQL::Eval for details) -otherwise. -.SH "BUGS AND LIMITATIONS" -.IX Header "BUGS AND LIMITATIONS" -There are no known bugs in DBI::SQL::Nano::Statement. If you find a one -and want to report, please see \s-1DBI\s0 for how to report bugs. -.PP -DBI::SQL::Nano::Statement is designed to provide a minimal subset for -executing \s-1SQL\s0 statements. -.PP -The most important limitation might be the restriction on one table per -statement. This implies, that no JOINs are supported and there cannot be -any foreign key relation between tables. -.PP -The where clause evaluation of DBI::SQL::Nano::Statement is very slow -(SQL::Statement uses a precompiled evaluation). -.PP -\&\s-1INSERT\s0 can handle only one row per statement. To insert multiple rows, -use placeholders as explained in \s-1DBI.\s0 -.PP -The DBI::SQL::Nano parser is very limited and does not support any -additional syntax such as brackets, comments, functions, aggregations -etc. -.PP -In contrast to SQL::Statement, temporary tables are not supported. -.SH "ACKNOWLEDGEMENTS" -.IX Header "ACKNOWLEDGEMENTS" -Tim Bunce provided the original idea for this module, helped me out of the -tangled trap of namespaces, and provided help and advice all along the way. -Although I wrote it from the ground up, it is based on Jochen Wiedmann's -original design of SQL::Statement, so much of the credit for the \s-1API\s0 goes -to him. -.SH "AUTHOR AND COPYRIGHT" -.IX Header "AUTHOR AND COPYRIGHT" -This module is originally written by Jeff Zucker < jzucker \s-1AT\s0 cpan.org > -.PP -This module is currently maintained by Jens Rehsack < jrehsack \s-1AT\s0 cpan.org > -.PP -Copyright (C) 2010 by Jens Rehsack, all rights reserved. -Copyright (C) 2004 by Jeff Zucker, all rights reserved. -.PP -You may freely distribute and/or modify this module under the terms of -either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, -as specified in the Perl \s-1README\s0 file. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::Util::CacheMemory.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::Util::CacheMemory.3pm deleted file mode 100644 index b4b65b3..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::Util::CacheMemory.3pm +++ /dev/null @@ -1,117 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::Util::CacheMemory 3pm" -.TH DBI::Util::CacheMemory 3pm "2013-06-24" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::Util::CacheMemory \- a very fast but very minimal subset of Cache::Memory -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Like Cache::Memory (part of the Cache distribution) but doesn't support any fancy features. -.PP -This module aims to be a very fast compatible strict sub-set for simple cases, -such as basic client-side caching for DBD::Gofer. -.PP -Like Cache::Memory, and other caches in the Cache and Cache::Cache -distributions, the data will remain in the cache until cleared, it expires, -or the process dies. The cache object simply going out of scope will \fInot\fR -destroy the data. -.SH "METHODS WITH CHANGES" -.IX Header "METHODS WITH CHANGES" -.SS "new" -.IX Subsection "new" -All options except \f(CW\*(C`namespace\*(C'\fR are ignored. -.SS "set" -.IX Subsection "set" -Doesn't support expiry. -.SS "purge" -.IX Subsection "purge" -Same as \fIclear()\fR \- deletes everything in the namespace. -.SH "METHODS WITHOUT CHANGES" -.IX Header "METHODS WITHOUT CHANGES" -.IP "clear" 4 -.IX Item "clear" -.PD 0 -.IP "count" 4 -.IX Item "count" -.IP "exists" 4 -.IX Item "exists" -.IP "remove" 4 -.IX Item "remove" -.PD -.SH "UNSUPPORTED METHODS" -.IX Header "UNSUPPORTED METHODS" -If it's not listed above, it's not supported. diff --git a/dbLifeLog/DBI-1.641/blib/man3/DBI::W32ODBC.3pm b/dbLifeLog/DBI-1.641/blib/man3/DBI::W32ODBC.3pm deleted file mode 100644 index 771d1d8..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/DBI::W32ODBC.3pm +++ /dev/null @@ -1,103 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "DBI::W32ODBC 3pm" -.TH DBI::W32ODBC 3pm "2013-05-23" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -DBI::W32ODBC \- An experimental DBI emulation layer for Win32::ODBC -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& use DBI::W32ODBC; -\& -\& # apart from the line above everything is just the same as with -\& # the real DBI when using a basic driver with few features. -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This is an experimental pure perl \s-1DBI\s0 emulation layer for Win32::ODBC -.PP -If you can improve this code I'd be interested in hearing about it. If -you are having trouble using it please respect the fact that it's very -experimental. Ideally fix it yourself and send me the details. -.SS "Some Things Not Yet Implemented" -.IX Subsection "Some Things Not Yet Implemented" -.Vb 2 -\& Most attributes including PrintError & RaiseError. -\& type_info and table_info -.Ve -.PP -Volunteers welcome! diff --git a/dbLifeLog/DBI-1.641/blib/man3/Win32::DBIODBC.3pm b/dbLifeLog/DBI-1.641/blib/man3/Win32::DBIODBC.3pm deleted file mode 100644 index 7004e24..0000000 --- a/dbLifeLog/DBI-1.641/blib/man3/Win32::DBIODBC.3pm +++ /dev/null @@ -1,112 +0,0 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" ======================================================================== -.\" -.IX Title "Win32::DBIODBC 3pm" -.TH Win32::DBIODBC 3pm "2015-05-26" "perl v5.22.1" "User Contributed Perl Documentation" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -Win32::DBIODBC \- Win32::ODBC emulation layer for the DBI -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& use Win32::DBIODBC; # instead of use Win32::ODBC -.Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -This is a \fIvery\fR basic \fIvery\fR alpha quality Win32::ODBC emulation -for the \s-1DBI.\s0 To use it just replace -.PP -.Vb 1 -\& use Win32::ODBC; -.Ve -.PP -in your scripts with -.PP -.Vb 1 -\& use Win32::DBIODBC; -.Ve -.PP -or, while experimenting, you can pre-load this module without changing your -scripts by doing -.PP -.Vb 1 -\& perl \-MWin32::DBIODBC your_script_name -.Ve -.SH "TO DO" -.IX Header "TO DO" -Error handling is virtually non-existent. -.SH "AUTHOR" -.IX Header "AUTHOR" -Tom Horen diff --git a/dbLifeLog/DBI-1.641/blib/script/.exists b/dbLifeLog/DBI-1.641/blib/script/.exists deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBI-1.641/blib/script/dbilogstrip b/dbLifeLog/DBI-1.641/blib/script/dbilogstrip deleted file mode 100755 index 1e8c682..0000000 --- a/dbLifeLog/DBI-1.641/blib/script/dbilogstrip +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/perl - -=head1 NAME - -dbilogstrip - filter to normalize DBI trace logs for diff'ing - -=head1 SYNOPSIS - -Read DBI trace file C and write out a stripped version to C - - dbilogstrip dbitrace.log > dbitrace_stripped.log - -Run C twice, each with different sets of arguments, with -DBI_TRACE enabled. Filter the output and trace through C into a -separate file for each run. Then compare using diff. (This example assumes -you're using a standard shell.) - - DBI_TRACE=2 perl yourscript.pl ...args1... 2>&1 | dbilogstrip > dbitrace1.log - DBI_TRACE=2 perl yourscript.pl ...args2... 2>&1 | dbilogstrip > dbitrace2.log - diff -u dbitrace1.log dbitrace2.log - -=head1 DESCRIPTION - -Replaces any hex addresses, e.g, C<0x128f72ce> with C<0xN>. - -Replaces any references to process id or thread id, like C with C. - -So a DBI trace line like this: - - -> STORE for DBD::DBM::st (DBI::st=HASH(0x19162a0)~0x191f9c8 'f_params' ARRAY(0x1922018)) thr#1800400 - -will look like this: - - -> STORE for DBD::DBM::st (DBI::st=HASH(0xN)~0xN 'f_params' ARRAY(0xN)) thrN - -=cut - -use strict; - -while (<>) { - # normalize hex addresses: 0xDEADHEAD => 0xN - s/ \b 0x [0-9a-f]+ /0xN/gx; - # normalize process and thread id number - s/ \b (pid|tid|thr) \W? \d+ /${1}N/gx; - -} continue { - print or die "-p destination: $!\n"; -} - - diff --git a/dbLifeLog/DBI-1.641/blib/script/dbiprof b/dbLifeLog/DBI-1.641/blib/script/dbiprof deleted file mode 100755 index 0306a99..0000000 --- a/dbLifeLog/DBI-1.641/blib/script/dbiprof +++ /dev/null @@ -1,263 +0,0 @@ -#!/usr/bin/perl - -use strict; - -my $VERSION = sprintf("1.%06d", q$Revision$ =~ /(\d+)/o); - -use Data::Dumper; -use DBI::ProfileData; -use Getopt::Long; - -# default options -my $number = 10; -my $sort = 'total'; -my $filename = 'dbi.prof'; -my $reverse = 0; -my $case_sensitive = 0; -my (%match, %exclude); - -# get options from command line -GetOptions( - 'version' => sub { die "dbiprof $VERSION\n" }, - 'help' => sub { exit usage() }, - 'number=i' => \$number, - 'sort=s' => \$sort, - 'dumpnodes!' => \my $dumpnodes, - 'reverse' => \$reverse, - 'match=s' => \%match, - 'exclude=s' => \%exclude, - 'case-sensitive' => \$case_sensitive, - 'delete!' => \my $opt_delete, -) or exit usage(); - -sub usage { - print <new( - Files => \@files, - DeleteFiles => $opt_delete, - ); -}; -die "Unable to load profile data: $@\n" if $@; - -if (%match) { # handle matches - while (my ($key, $val) = each %match) { - if ($val =~ m!^/(.+)/$!) { - $val = $case_sensitive ? qr/$1/ : qr/$1/i; - } - $prof->match($key, $val, case_sensitive => $case_sensitive); - } -} - -if (%exclude) { # handle excludes - while (my ($key, $val) = each %exclude) { - if ($val =~ m!^/(.+)/$!) { - $val = $case_sensitive ? qr/$1/ : qr/$1/i; - } - $prof->exclude($key, $val, case_sensitive => $case_sensitive); - } -} - -# sort the data -$prof->sort(field => $sort, reverse => $reverse); - -# all done, print it out -if ($dumpnodes) { - $Data::Dumper::Indent = 1; - $Data::Dumper::Terse = 1; - $Data::Dumper::Useqq = 1; - $Data::Dumper::Deparse = 0; - print Dumper($prof->nodes); -} -else { - print $prof->report(number => $number); -} -exit 0; - -__END__ - -=head1 NAME - -dbiprof - command-line client for DBI::ProfileData - -=head1 SYNOPSIS - -See a report of the ten queries with the longest total runtime in the -profile dump file F: - - dbiprof prof1.out - -See the top 10 most frequently run queries in the profile file -F (the default): - - dbiprof --sort count - -See the same report with 15 entries: - - dbiprof --sort count --number 15 - -=head1 DESCRIPTION - -This tool is a command-line client for the DBI::ProfileData. It -allows you to analyze the profile data file produced by -DBI::ProfileDumper and produce various useful reports. - -=head1 OPTIONS - -This program accepts the following options: - -=over 4 - -=item --number N - -Produce this many items in the report. Defaults to 10. If set to -"all" then all results are shown. - -=item --sort field - -Sort results by the given field. Sorting by multiple fields isn't currently -supported (patches welcome). The available sort fields are: - -=over 4 - -=item total - -Sorts by total time run time across all runs. This is the default -sort. - -=item longest - -Sorts by the longest single run. - -=item count - -Sorts by total number of runs. - -=item first - -Sorts by the time taken in the first run. - -=item shortest - -Sorts by the shortest single run. - -=item key1 - -Sorts by the value of the first element in the Path, which should be numeric. -You can also sort by C and C. - -=back - -=item --reverse - -Reverses the selected sort. For example, to see a report of the -shortest overall time: - - dbiprof --sort total --reverse - -=item --match keyN=value - -Consider only items where the specified key matches the given value. -Keys are numbered from 1. For example, let's say you used a -DBI::Profile Path of: - - [ DBIprofile_Statement, DBIprofile_Methodname ] - -And called dbiprof as in: - - dbiprof --match key2=execute - -Your report would only show execute queries, leaving out prepares, -fetches, etc. - -If the value given starts and ends with slashes (C) then it will be -treated as a regular expression. For example, to only include SELECT -queries where key1 is the statement: - - dbiprof --match key1=/^SELECT/ - -By default the match expression is matched case-insensitively, but -this can be changed with the --case-sensitive option. - -=item --exclude keyN=value - -Remove items for where the specified key matches the given value. For -example, to exclude all prepare entries where key2 is the method name: - - dbiprof --exclude key2=prepare - -Like C<--match>, If the value given starts and ends with slashes -(C) then it will be treated as a regular expression. For example, -to exclude UPDATE queries where key1 is the statement: - - dbiprof --match key1=/^UPDATE/ - -By default the exclude expression is matched case-insensitively, but -this can be changed with the --case-sensitive option. - -=item --case-sensitive - -Using this option causes --match and --exclude to work -case-sensitively. Defaults to off. - -=item --delete - -Sets the C option to L which causes the -files to be deleted after reading. See L for more details. - -=item --dumpnodes - -Print the list of nodes in the form of a perl data structure. -Use the C<-sort> option if you want the list sorted. - -=item --version - -Print the dbiprof version number and exit. - -=back - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=head1 SEE ALSO - -L, -L, L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/blib/script/dbiproxy b/dbLifeLog/DBI-1.641/blib/script/dbiproxy deleted file mode 100755 index c705764..0000000 --- a/dbLifeLog/DBI-1.641/blib/script/dbiproxy +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/perl - -use strict; - -my $VERSION = sprintf("1.%06d", q$Revision$ =~ /(\d+)/o); - -my $arg_test = shift(@ARGV) if $ARGV[0] eq '--test'; -$ENV{DBI_TRACE} = shift(@ARGV) || 2 if $ARGV[0] =~ s/^--dbitrace=?//; - -require DBI::ProxyServer; - -# XXX these should probably be moved into DBI::ProxyServer -delete $ENV{IFS}; -delete $ENV{CDPATH}; -delete $ENV{ENV}; -delete $ENV{BASH_ENV}; - -if ($arg_test) { - require RPC::PlServer::Test; - @DBI::ProxyServer::ISA = qw(RPC::PlServer::Test DBI); -} - -DBI::ProxyServer::main(@ARGV); - -exit(0); - - -__END__ - -=head1 NAME - -dbiproxy - A proxy server for the DBD::Proxy driver - -=head1 SYNOPSIS - - dbiproxy --localport= - - -=head1 DESCRIPTION - -This tool is just a front end for the DBI::ProxyServer package. All it -does is picking options from the command line and calling -DBI::ProxyServer::main(). See L for details. - -Available options include: - -=over 4 - -=item B<--chroot=dir> - -(UNIX only) After doing a bind(), change root directory to the given -directory by doing a chroot(). This is useful for security, but it -restricts the environment a lot. For example, you need to load DBI -drivers in the config file or you have to create hard links to Unix -sockets, if your drivers are using them. For example, with MySQL, a -config file might contain the following lines: - - my $rootdir = '/var/dbiproxy'; - my $unixsockdir = '/tmp'; - my $unixsockfile = 'mysql.sock'; - foreach $dir ($rootdir, "$rootdir$unixsockdir") { - mkdir 0755, $dir; - } - link("$unixsockdir/$unixsockfile", - "$rootdir$unixsockdir/$unixsockfile"); - require DBD::mysql; - - { - 'chroot' => $rootdir, - ... - } - -If you don't know chroot(), think of an FTP server where you can see a -certain directory tree only after logging in. See also the --group and ---user options. - -=item B<--configfile=file> - -Config files are assumed to return a single hash ref that overrides the -arguments of the new method. However, command line arguments in turn take -precedence over the config file. See the "CONFIGURATION FILE" section -in the L documentation for details on the config file. - -=item B<--debug> - -Turn debugging mode on. Mainly this asserts that logging messages of -level "debug" are created. - -=item B<--facility=mode> - -(UNIX only) Facility to use for L. The default is -B. - -=item B<--group=gid> - -After doing a bind(), change the real and effective GID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --user option. - -GID's can be passed as group names or numeric values. - -=item B<--localaddr=ip> - -By default a daemon is listening to any IP number that a machine -has. This attribute allows one to restrict the server to the given -IP number. - -=item B<--localport=port> - -This attribute sets the port on which the daemon is listening. It -must be given somehow, as there's no default. - -=item B<--logfile=file> - -Be default logging messages will be written to the syslog (Unix) or -to the event log (Windows NT). On other operating systems you need to -specify a log file. The special value "STDERR" forces logging to -stderr. See L for details. - -=item B<--mode=modename> - -The server can run in three different modes, depending on the environment. - -If you are running Perl 5.005 and did compile it for threads, then the -server will create a new thread for each connection. The thread will -execute the server's Run() method and then terminate. This mode is the -default, you can force it with "--mode=threads". - -If threads are not available, but you have a working fork(), then the -server will behave similar by creating a new process for each connection. -This mode will be used automatically in the absence of threads or if -you use the "--mode=fork" option. - -Finally there's a single-connection mode: If the server has accepted a -connection, he will enter the Run() method. No other connections are -accepted until the Run() method returns (if the client disconnects). -This operation mode is useful if you have neither threads nor fork(), -for example on the Macintosh. For debugging purposes you can force this -mode with "--mode=single". - -=item B<--pidfile=file> - -(UNIX only) If this option is present, a PID file will be created at the -given location. Default is to not create a pidfile. - -=item B<--user=uid> - -After doing a bind(), change the real and effective UID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --group and the --chroot options. - -UID's can be passed as group names or numeric values. - -=item B<--version> - -Suppresses startup of the server; instead the version string will -be printed and the program exits immediately. - -=back - - -=head1 AUTHOR - - Copyright (c) 1997 Jochen Wiedmann - Am Eisteich 9 - 72555 Metzingen - Germany - - Email: joe@ispsoft.de - Phone: +49 7123 14881 - -The DBI::ProxyServer module is free software; you can redistribute it -and/or modify it under the same terms as Perl itself. In particular -permission is granted to Tim Bunce for distributing this as a part of -the DBI. - - -=head1 SEE ALSO - -L, L, L - -=cut diff --git a/dbLifeLog/DBI-1.641/dbd_xsh.h b/dbLifeLog/DBI-1.641/dbd_xsh.h deleted file mode 100644 index 2c7f2d6..0000000 --- a/dbLifeLog/DBI-1.641/dbd_xsh.h +++ /dev/null @@ -1,61 +0,0 @@ -/* @(#)$Id$ - * - * Copyright 2000-2002 Tim Bunce - * Copyright 2002 Jonathan Leffler - * - * These prototypes are for dbdimp.c funcs used in the XS file. - * These names are #defined to driver specific names by the - * dbdimp.h file in the driver source. - */ - -#ifndef DBI_DBD_XSH_H -#define DBI_DBD_XSH_H - -void dbd_init _((dbistate_t *dbistate)); - -int dbd_discon_all _((SV *drh, imp_drh_t *imp_drh)); -SV *dbd_take_imp_data _((SV *h, imp_xxh_t *imp_xxh, void *foo)); - -/* Support for dbd_dr_data_sources and dbd_db_do added to Driver.xst in DBI v1.33 */ -/* dbd_dr_data_sources: optional: defined by a driver that calls a C */ -/* function to get the list of data sources */ -AV *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attrs); - -int dbd_db_login6_sv _((SV *dbh, imp_dbh_t *imp_dbh, SV *dbname, SV *uid, SV *pwd, SV*attribs)); -int dbd_db_login6 _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, SV*attribs)); -int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd)); /* deprecated */ -/* Note: interface of dbd_db_do changed in v1.33 */ -/* Old prototype: dbd_db_do _((SV *sv, char *statement)); */ -/* dbd_db_do: optional: defined by a driver if the DBI default version is too slow */ -int dbd_db_do4 _((SV *dbh, imp_dbh_t *imp_dbh, char *statement, SV *params)); -IV dbd_db_do4_iv _((SV *dbh, imp_dbh_t *imp_dbh, char *statement, SV *params)); -int dbd_db_commit _((SV *dbh, imp_dbh_t *imp_dbh)); -int dbd_db_rollback _((SV *dbh, imp_dbh_t *imp_dbh)); -int dbd_db_disconnect _((SV *dbh, imp_dbh_t *imp_dbh)); -void dbd_db_destroy _((SV *dbh, imp_dbh_t *imp_dbh)); -int dbd_db_STORE_attrib _((SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)); -SV *dbd_db_FETCH_attrib _((SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)); -SV *dbd_db_last_insert_id _((SV *dbh, imp_dbh_t *imp_dbh, SV *catalog, SV *schema, SV *table, SV *field, SV *attr)); -AV *dbd_db_data_sources _((SV *dbh, imp_dbh_t *imp_dbh, SV *attr)); - -int dbd_st_prepare _((SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs)); -int dbd_st_prepare_sv _((SV *sth, imp_sth_t *imp_sth, SV *statement, SV *attribs)); -int dbd_st_rows _((SV *sth, imp_sth_t *imp_sth)); -IV dbd_st_rows_iv _((SV *sth, imp_sth_t *imp_sth)); -int dbd_st_execute _((SV *sth, imp_sth_t *imp_sth)); -IV dbd_st_execute_iv _((SV *sth, imp_sth_t *imp_sth)); -AV *dbd_st_fetch _((SV *sth, imp_sth_t *imp_sth)); -int dbd_st_finish3 _((SV *sth, imp_sth_t *imp_sth, int from_destroy)); -int dbd_st_finish _((SV *sth, imp_sth_t *imp_sth)); /* deprecated */ -void dbd_st_destroy _((SV *sth, imp_sth_t *imp_sth)); -int dbd_st_blob_read _((SV *sth, imp_sth_t *imp_sth, - int field, long offset, long len, SV *destrv, long destoffset)); -int dbd_st_STORE_attrib _((SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)); -SV *dbd_st_FETCH_attrib _((SV *sth, imp_sth_t *imp_sth, SV *keysv)); -SV *dbd_st_execute_for_fetch _((SV *sth, imp_sth_t *imp_sth, SV *fetch_tuple_sub, SV *tuple_status)); - -int dbd_bind_ph _((SV *sth, imp_sth_t *imp_sth, - SV *param, SV *value, IV sql_type, SV *attribs, - int is_inout, IV maxlen)); - -#endif /* end of dbd_xsh.h */ diff --git a/dbLifeLog/DBI-1.641/dbi_sql.h b/dbLifeLog/DBI-1.641/dbi_sql.h deleted file mode 100644 index 22b5b77..0000000 --- a/dbLifeLog/DBI-1.641/dbi_sql.h +++ /dev/null @@ -1,96 +0,0 @@ -/* $Id$ - * - * Copyright (c) 1997,1998,1999 Tim Bunce England - * - * See COPYRIGHT section in DBI.pm for usage and distribution rights. - */ - - -/* Some core SQL CLI standard (ODBC) declarations */ -#ifndef SQL_SUCCESS /* don't clash with ODBC based drivers */ - -/* SQL datatype codes */ -#define SQL_GUID (-11) -#define SQL_WLONGVARCHAR (-10) -#define SQL_WVARCHAR (-9) -#define SQL_WCHAR (-8) -#define SQL_BIT (-7) -#define SQL_TINYINT (-6) -#define SQL_BIGINT (-5) -#define SQL_LONGVARBINARY (-4) -#define SQL_VARBINARY (-3) -#define SQL_BINARY (-2) -#define SQL_LONGVARCHAR (-1) -#define SQL_UNKNOWN_TYPE 0 -#define SQL_ALL_TYPES 0 -#define SQL_CHAR 1 -#define SQL_NUMERIC 2 -#define SQL_DECIMAL 3 -#define SQL_INTEGER 4 -#define SQL_SMALLINT 5 -#define SQL_FLOAT 6 -#define SQL_REAL 7 -#define SQL_DOUBLE 8 -#define SQL_DATETIME 9 -#define SQL_DATE 9 -#define SQL_INTERVAL 10 -#define SQL_TIME 10 -#define SQL_TIMESTAMP 11 -#define SQL_VARCHAR 12 -#define SQL_BOOLEAN 16 -#define SQL_UDT 17 -#define SQL_UDT_LOCATOR 18 -#define SQL_ROW 19 -#define SQL_REF 20 -#define SQL_BLOB 30 -#define SQL_BLOB_LOCATOR 31 -#define SQL_CLOB 40 -#define SQL_CLOB_LOCATOR 41 -#define SQL_ARRAY 50 -#define SQL_ARRAY_LOCATOR 51 -#define SQL_MULTISET 55 -#define SQL_MULTISET_LOCATOR 56 -#define SQL_TYPE_DATE 91 -#define SQL_TYPE_TIME 92 -#define SQL_TYPE_TIMESTAMP 93 -#define SQL_TYPE_TIME_WITH_TIMEZONE 94 -#define SQL_TYPE_TIMESTAMP_WITH_TIMEZONE 95 -#define SQL_INTERVAL_YEAR 101 -#define SQL_INTERVAL_MONTH 102 -#define SQL_INTERVAL_DAY 103 -#define SQL_INTERVAL_HOUR 104 -#define SQL_INTERVAL_MINUTE 105 -#define SQL_INTERVAL_SECOND 106 -#define SQL_INTERVAL_YEAR_TO_MONTH 107 -#define SQL_INTERVAL_DAY_TO_HOUR 108 -#define SQL_INTERVAL_DAY_TO_MINUTE 109 -#define SQL_INTERVAL_DAY_TO_SECOND 110 -#define SQL_INTERVAL_HOUR_TO_MINUTE 111 -#define SQL_INTERVAL_HOUR_TO_SECOND 112 -#define SQL_INTERVAL_MINUTE_TO_SECOND 113 - - -/* Main return codes */ -#define SQL_ERROR (-1) -#define SQL_SUCCESS 0 -#define SQL_SUCCESS_WITH_INFO 1 -#define SQL_NO_DATA_FOUND 100 - -/* - * for ODBC SQL Cursor Types - */ -#define SQL_CURSOR_FORWARD_ONLY 0UL -#define SQL_CURSOR_KEYSET_DRIVEN 1UL -#define SQL_CURSOR_DYNAMIC 2UL -#define SQL_CURSOR_STATIC 3UL -#define SQL_CURSOR_TYPE_DEFAULT SQL_CURSOR_FORWARD_ONLY - -#endif /* SQL_SUCCESS */ - -/* Handy macro for testing for success and success with info. */ -/* BEWARE that this macro can have side effects since rc appears twice! */ -/* So DONT use it as if(SQL_ok(func(...))) { ... } */ -#define SQL_ok(rc) ((rc)==SQL_SUCCESS || (rc)==SQL_SUCCESS_WITH_INFO) - - -/* end of dbi_sql.h */ diff --git a/dbLifeLog/DBI-1.641/dbilogstrip b/dbLifeLog/DBI-1.641/dbilogstrip deleted file mode 100755 index 1e8c682..0000000 --- a/dbLifeLog/DBI-1.641/dbilogstrip +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/perl - -=head1 NAME - -dbilogstrip - filter to normalize DBI trace logs for diff'ing - -=head1 SYNOPSIS - -Read DBI trace file C and write out a stripped version to C - - dbilogstrip dbitrace.log > dbitrace_stripped.log - -Run C twice, each with different sets of arguments, with -DBI_TRACE enabled. Filter the output and trace through C into a -separate file for each run. Then compare using diff. (This example assumes -you're using a standard shell.) - - DBI_TRACE=2 perl yourscript.pl ...args1... 2>&1 | dbilogstrip > dbitrace1.log - DBI_TRACE=2 perl yourscript.pl ...args2... 2>&1 | dbilogstrip > dbitrace2.log - diff -u dbitrace1.log dbitrace2.log - -=head1 DESCRIPTION - -Replaces any hex addresses, e.g, C<0x128f72ce> with C<0xN>. - -Replaces any references to process id or thread id, like C with C. - -So a DBI trace line like this: - - -> STORE for DBD::DBM::st (DBI::st=HASH(0x19162a0)~0x191f9c8 'f_params' ARRAY(0x1922018)) thr#1800400 - -will look like this: - - -> STORE for DBD::DBM::st (DBI::st=HASH(0xN)~0xN 'f_params' ARRAY(0xN)) thrN - -=cut - -use strict; - -while (<>) { - # normalize hex addresses: 0xDEADHEAD => 0xN - s/ \b 0x [0-9a-f]+ /0xN/gx; - # normalize process and thread id number - s/ \b (pid|tid|thr) \W? \d+ /${1}N/gx; - -} continue { - print or die "-p destination: $!\n"; -} - - diff --git a/dbLifeLog/DBI-1.641/dbilogstrip.PL b/dbLifeLog/DBI-1.641/dbilogstrip.PL deleted file mode 100644 index 3bad633..0000000 --- a/dbLifeLog/DBI-1.641/dbilogstrip.PL +++ /dev/null @@ -1,71 +0,0 @@ -# -*- perl -*- -my $file = $ARGV[0] || 'dbilogstrip'; - -my $script = <<'SCRIPT'; -~startperl~ - -=head1 NAME - -dbilogstrip - filter to normalize DBI trace logs for diff'ing - -=head1 SYNOPSIS - -Read DBI trace file C and write out a stripped version to C - - dbilogstrip dbitrace.log > dbitrace_stripped.log - -Run C twice, each with different sets of arguments, with -DBI_TRACE enabled. Filter the output and trace through C into a -separate file for each run. Then compare using diff. (This example assumes -you're using a standard shell.) - - DBI_TRACE=2 perl yourscript.pl ...args1... 2>&1 | dbilogstrip > dbitrace1.log - DBI_TRACE=2 perl yourscript.pl ...args2... 2>&1 | dbilogstrip > dbitrace2.log - diff -u dbitrace1.log dbitrace2.log - -=head1 DESCRIPTION - -Replaces any hex addresses, e.g, C<0x128f72ce> with C<0xN>. - -Replaces any references to process id or thread id, like C with C. - -So a DBI trace line like this: - - -> STORE for DBD::DBM::st (DBI::st=HASH(0x19162a0)~0x191f9c8 'f_params' ARRAY(0x1922018)) thr#1800400 - -will look like this: - - -> STORE for DBD::DBM::st (DBI::st=HASH(0xN)~0xN 'f_params' ARRAY(0xN)) thrN - -=cut - -use strict; - -while (<>) { - # normalize hex addresses: 0xDEADHEAD => 0xN - s/ \b 0x [0-9a-f]+ /0xN/gx; - # normalize process and thread id number - s/ \b (pid|tid|thr) \W? \d+ /${1}N/gx; - -} continue { - print or die "-p destination: $!\n"; -} - - -SCRIPT - -require Config; -my $config = {}; -$config->{'startperl'} = $Config::Config{'startperl'}; - -$script =~ s/\~(\w+)\~/$config->{$1}/eg; -if (!(open(FILE, ">$file")) || - !(print FILE $script) || - !(close(FILE))) { - die "Error while writing $file: $!\n"; -} -chmod 0755, $file; -print "Extracted $file from ",__FILE__," with variable substitutions.\n"; -# syntax check resulting file, but only for developers -exit 1 if -d ".svn" and system($^X, '-wc', '-Mblib', $file) != 0; - diff --git a/dbLifeLog/DBI-1.641/dbipport.h b/dbLifeLog/DBI-1.641/dbipport.h deleted file mode 100644 index 858612e..0000000 --- a/dbLifeLog/DBI-1.641/dbipport.h +++ /dev/null @@ -1,7748 +0,0 @@ -#if 0 -<<'SKIP'; -#endif -/* ----------------------------------------------------------------------- - - ppport.h -- Perl/Pollution/Portability Version 3.32 - - Automatically created by Devel::PPPort running under perl 5.018002. - - Do NOT edit this file directly! -- Edit PPPort_pm.PL and the - includes in parts/inc/ instead. - - Use 'perldoc ppport.h' to view the documentation below. - ----------------------------------------------------------------------- - -SKIP - -=pod - -=head1 NAME - -ppport.h - Perl/Pollution/Portability version 3.32 - -=head1 SYNOPSIS - - perl ppport.h [options] [source files] - - Searches current directory for files if no [source files] are given - - --help show short help - - --version show version - - --patch=file write one patch file with changes - --copy=suffix write changed copies with suffix - --diff=program use diff program and options - - --compat-version=version provide compatibility with Perl version - --cplusplus accept C++ comments - - --quiet don't output anything except fatal errors - --nodiag don't show diagnostics - --nohints don't show hints - --nochanges don't suggest changes - --nofilter don't filter input files - - --strip strip all script and doc functionality from - ppport.h - - --list-provided list provided API - --list-unsupported list unsupported API - --api-info=name show Perl API portability information - -=head1 COMPATIBILITY - -This version of F is designed to support operation with Perl -installations back to 5.003, and has been tested up to 5.20. - -=head1 OPTIONS - -=head2 --help - -Display a brief usage summary. - -=head2 --version - -Display the version of F. - -=head2 --patch=I - -If this option is given, a single patch file will be created if -any changes are suggested. This requires a working diff program -to be installed on your system. - -=head2 --copy=I - -If this option is given, a copy of each file will be saved with -the given suffix that contains the suggested changes. This does -not require any external programs. Note that this does not -automagically add a dot between the original filename and the -suffix. If you want the dot, you have to include it in the option -argument. - -If neither C<--patch> or C<--copy> are given, the default is to -simply print the diffs for each file. This requires either -C or a C program to be installed. - -=head2 --diff=I - -Manually set the diff program and options to use. The default -is to use C, when installed, and output unified -context diffs. - -=head2 --compat-version=I - -Tell F to check for compatibility with the given -Perl version. The default is to check for compatibility with Perl -version 5.003. You can use this option to reduce the output -of F if you intend to be backward compatible only -down to a certain Perl version. - -=head2 --cplusplus - -Usually, F will detect C++ style comments and -replace them with C style comments for portability reasons. -Using this option instructs F to leave C++ -comments untouched. - -=head2 --quiet - -Be quiet. Don't print anything except fatal errors. - -=head2 --nodiag - -Don't output any diagnostic messages. Only portability -alerts will be printed. - -=head2 --nohints - -Don't output any hints. Hints often contain useful portability -notes. Warnings will still be displayed. - -=head2 --nochanges - -Don't suggest any changes. Only give diagnostic output and hints -unless these are also deactivated. - -=head2 --nofilter - -Don't filter the list of input files. By default, files not looking -like source code (i.e. not *.xs, *.c, *.cc, *.cpp or *.h) are skipped. - -=head2 --strip - -Strip all script and documentation functionality from F. -This reduces the size of F dramatically and may be useful -if you want to include F in smaller modules without -increasing their distribution size too much. - -The stripped F will have a C<--unstrip> option that allows -you to undo the stripping, but only if an appropriate C -module is installed. - -=head2 --list-provided - -Lists the API elements for which compatibility is provided by -F. Also lists if it must be explicitly requested, -if it has dependencies, and if there are hints or warnings for it. - -=head2 --list-unsupported - -Lists the API elements that are known not to be supported by -F and below which version of Perl they probably -won't be available or work. - -=head2 --api-info=I - -Show portability information for API elements matching I. -If I is surrounded by slashes, it is interpreted as a regular -expression. - -=head1 DESCRIPTION - -In order for a Perl extension (XS) module to be as portable as possible -across differing versions of Perl itself, certain steps need to be taken. - -=over 4 - -=item * - -Including this header is the first major one. This alone will give you -access to a large part of the Perl API that hasn't been available in -earlier Perl releases. Use - - perl ppport.h --list-provided - -to see which API elements are provided by ppport.h. - -=item * - -You should avoid using deprecated parts of the API. For example, using -global Perl variables without the C prefix is deprecated. Also, -some API functions used to have a C prefix. Using this form is -also deprecated. You can safely use the supported API, as F -will provide wrappers for older Perl versions. - -=item * - -If you use one of a few functions or variables that were not present in -earlier versions of Perl, and that can't be provided using a macro, you -have to explicitly request support for these functions by adding one or -more C<#define>s in your source code before the inclusion of F. - -These functions or variables will be marked C in the list shown -by C<--list-provided>. - -Depending on whether you module has a single or multiple files that -use such functions or variables, you want either C or global -variants. - -For a C function or variable (used only in a single source -file), use: - - #define NEED_function - #define NEED_variable - -For a global function or variable (used in multiple source files), -use: - - #define NEED_function_GLOBAL - #define NEED_variable_GLOBAL - -Note that you mustn't have more than one global request for the -same function or variable in your project. - - Function / Variable Static Request Global Request - ----------------------------------------------------------------------------------------- - PL_parser NEED_PL_parser NEED_PL_parser_GLOBAL - PL_signals NEED_PL_signals NEED_PL_signals_GLOBAL - caller_cx() NEED_caller_cx NEED_caller_cx_GLOBAL - eval_pv() NEED_eval_pv NEED_eval_pv_GLOBAL - grok_bin() NEED_grok_bin NEED_grok_bin_GLOBAL - grok_hex() NEED_grok_hex NEED_grok_hex_GLOBAL - grok_number() NEED_grok_number NEED_grok_number_GLOBAL - grok_numeric_radix() NEED_grok_numeric_radix NEED_grok_numeric_radix_GLOBAL - grok_oct() NEED_grok_oct NEED_grok_oct_GLOBAL - load_module() NEED_load_module NEED_load_module_GLOBAL - mg_findext() NEED_mg_findext NEED_mg_findext_GLOBAL - my_snprintf() NEED_my_snprintf NEED_my_snprintf_GLOBAL - my_sprintf() NEED_my_sprintf NEED_my_sprintf_GLOBAL - my_strlcat() NEED_my_strlcat NEED_my_strlcat_GLOBAL - my_strlcpy() NEED_my_strlcpy NEED_my_strlcpy_GLOBAL - newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL - newRV_noinc() NEED_newRV_noinc NEED_newRV_noinc_GLOBAL - newSV_type() NEED_newSV_type NEED_newSV_type_GLOBAL - newSVpvn_flags() NEED_newSVpvn_flags NEED_newSVpvn_flags_GLOBAL - newSVpvn_share() NEED_newSVpvn_share NEED_newSVpvn_share_GLOBAL - pv_display() NEED_pv_display NEED_pv_display_GLOBAL - pv_escape() NEED_pv_escape NEED_pv_escape_GLOBAL - pv_pretty() NEED_pv_pretty NEED_pv_pretty_GLOBAL - sv_2pv_flags() NEED_sv_2pv_flags NEED_sv_2pv_flags_GLOBAL - sv_2pvbyte() NEED_sv_2pvbyte NEED_sv_2pvbyte_GLOBAL - sv_catpvf_mg() NEED_sv_catpvf_mg NEED_sv_catpvf_mg_GLOBAL - sv_catpvf_mg_nocontext() NEED_sv_catpvf_mg_nocontext NEED_sv_catpvf_mg_nocontext_GLOBAL - sv_pvn_force_flags() NEED_sv_pvn_force_flags NEED_sv_pvn_force_flags_GLOBAL - sv_setpvf_mg() NEED_sv_setpvf_mg NEED_sv_setpvf_mg_GLOBAL - sv_setpvf_mg_nocontext() NEED_sv_setpvf_mg_nocontext NEED_sv_setpvf_mg_nocontext_GLOBAL - sv_unmagicext() NEED_sv_unmagicext NEED_sv_unmagicext_GLOBAL - vload_module() NEED_vload_module NEED_vload_module_GLOBAL - vnewSVpvf() NEED_vnewSVpvf NEED_vnewSVpvf_GLOBAL - warner() NEED_warner NEED_warner_GLOBAL - -To avoid namespace conflicts, you can change the namespace of the -explicitly exported functions / variables using the C -macro. Just C<#define> the macro before including C: - - #define DPPP_NAMESPACE MyOwnNamespace_ - #include "ppport.h" - -The default namespace is C. - -=back - -The good thing is that most of the above can be checked by running -F on your source code. See the next section for -details. - -=head1 EXAMPLES - -To verify whether F is needed for your module, whether you -should make any changes to your code, and whether any special defines -should be used, F can be run as a Perl script to check your -source code. Simply say: - - perl ppport.h - -The result will usually be a list of patches suggesting changes -that should at least be acceptable, if not necessarily the most -efficient solution, or a fix for all possible problems. - -If you know that your XS module uses features only available in -newer Perl releases, if you're aware that it uses C++ comments, -and if you want all suggestions as a single patch file, you could -use something like this: - - perl ppport.h --compat-version=5.6.0 --cplusplus --patch=test.diff - -If you only want your code to be scanned without any suggestions -for changes, use: - - perl ppport.h --nochanges - -You can specify a different C program or options, using -the C<--diff> option: - - perl ppport.h --diff='diff -C 10' - -This would output context diffs with 10 lines of context. - -If you want to create patched copies of your files instead, use: - - perl ppport.h --copy=.new - -To display portability information for the C function, -use: - - perl ppport.h --api-info=newSVpvn - -Since the argument to C<--api-info> can be a regular expression, -you can use - - perl ppport.h --api-info=/_nomg$/ - -to display portability information for all C<_nomg> functions or - - perl ppport.h --api-info=/./ - -to display information for all known API elements. - -=head1 BUGS - -If this version of F is causing failure during -the compilation of this module, please check if newer versions -of either this module or C are available on CPAN -before sending a bug report. - -If F was generated using the latest version of -C and is causing failure of this module, please -file a bug report here: L - -Please include the following information: - -=over 4 - -=item 1. - -The complete output from running "perl -V" - -=item 2. - -This file. - -=item 3. - -The name and version of the module you were trying to build. - -=item 4. - -A full log of the build that failed. - -=item 5. - -Any other information that you think could be relevant. - -=back - -For the latest version of this code, please get the C -module from CPAN. - -=head1 COPYRIGHT - -Version 3.x, Copyright (c) 2004-2013, Marcus Holland-Moritz. - -Version 2.x, Copyright (C) 2001, Paul Marquess. - -Version 1.x, Copyright (C) 1999, Kenneth Albanowski. - -This program is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -See L. - -=cut - -use strict; - -# Disable broken TRIE-optimization -BEGIN { eval '${^RE_TRIE_MAXBUF} = -1' if $] >= 5.009004 && $] <= 5.009005 } - -my $VERSION = 3.32; - -my %opt = ( - quiet => 0, - diag => 1, - hints => 1, - changes => 1, - cplusplus => 0, - filter => 1, - strip => 0, - version => 0, -); - -my($ppport) = $0 =~ /([\w.]+)$/; -my $LF = '(?:\r\n|[\r\n])'; # line feed -my $HS = "[ \t]"; # horizontal whitespace - -# Never use C comments in this file! -my $ccs = '/'.'*'; -my $cce = '*'.'/'; -my $rccs = quotemeta $ccs; -my $rcce = quotemeta $cce; - -eval { - require Getopt::Long; - Getopt::Long::GetOptions(\%opt, qw( - help quiet diag! filter! hints! changes! cplusplus strip version - patch=s copy=s diff=s compat-version=s - list-provided list-unsupported api-info=s - )) or usage(); -}; - -if ($@ and grep /^-/, @ARGV) { - usage() if "@ARGV" =~ /^--?h(?:elp)?$/; - die "Getopt::Long not found. Please don't use any options.\n"; -} - -if ($opt{version}) { - print "This is $0 $VERSION.\n"; - exit 0; -} - -usage() if $opt{help}; -strip() if $opt{strip}; - -if (exists $opt{'compat-version'}) { - my($r,$v,$s) = eval { parse_version($opt{'compat-version'}) }; - if ($@) { - die "Invalid version number format: '$opt{'compat-version'}'\n"; - } - die "Only Perl 5 is supported\n" if $r != 5; - die "Invalid version number: $opt{'compat-version'}\n" if $v >= 1000 || $s >= 1000; - $opt{'compat-version'} = sprintf "%d.%03d%03d", $r, $v, $s; -} -else { - $opt{'compat-version'} = 5; -} - -my %API = map { /^(\w+)\|([^|]*)\|([^|]*)\|(\w*)$/ - ? ( $1 => { - ($2 ? ( base => $2 ) : ()), - ($3 ? ( todo => $3 ) : ()), - (index($4, 'v') >= 0 ? ( varargs => 1 ) : ()), - (index($4, 'p') >= 0 ? ( provided => 1 ) : ()), - (index($4, 'n') >= 0 ? ( nothxarg => 1 ) : ()), - } ) - : die "invalid spec: $_" } qw( -ASCII_TO_NEED||5.007001|n -AvFILLp|5.004050||p -AvFILL||| -BhkDISABLE||5.021008| -BhkENABLE||5.021008| -BhkENTRY_set||5.021008| -BhkENTRY||| -BhkFLAGS||| -CALL_BLOCK_HOOKS||| -CLASS|||n -CPERLscope|5.005000||p -CX_CURPAD_SAVE||| -CX_CURPAD_SV||| -CopFILEAV|5.006000||p -CopFILEGV_set|5.006000||p -CopFILEGV|5.006000||p -CopFILESV|5.006000||p -CopFILE_set|5.006000||p -CopFILE|5.006000||p -CopSTASHPV_set|5.006000||p -CopSTASHPV|5.006000||p -CopSTASH_eq|5.006000||p -CopSTASH_set|5.006000||p -CopSTASH|5.006000||p -CopyD|5.009002|5.004050|p -Copy||| -CvPADLIST||5.008001| -CvSTASH||| -CvWEAKOUTSIDE||| -DEFSV_set|5.010001||p -DEFSV|5.004050||p -END_EXTERN_C|5.005000||p -ENTER||| -ERRSV|5.004050||p -EXTEND||| -EXTERN_C|5.005000||p -F0convert|||n -FREETMPS||| -GIMME_V||5.004000|n -GIMME|||n -GROK_NUMERIC_RADIX|5.007002||p -G_ARRAY||| -G_DISCARD||| -G_EVAL||| -G_METHOD|5.006001||p -G_NOARGS||| -G_SCALAR||| -G_VOID||5.004000| -GetVars||| -GvAV||| -GvCV||| -GvHV||| -GvSVn|5.009003||p -GvSV||| -Gv_AMupdate||5.011000| -HEf_SVKEY|5.003070||p -HeHASH||5.003070| -HeKEY||5.003070| -HeKLEN||5.003070| -HePV||5.004000| -HeSVKEY_force||5.003070| -HeSVKEY_set||5.004000| -HeSVKEY||5.003070| -HeUTF8|5.010001|5.008000|p -HeVAL||5.003070| -HvENAMELEN||5.015004| -HvENAMEUTF8||5.015004| -HvENAME||5.013007| -HvNAMELEN_get|5.009003||p -HvNAMELEN||5.015004| -HvNAMEUTF8||5.015004| -HvNAME_get|5.009003||p -HvNAME||| -INT2PTR|5.006000||p -IN_LOCALE_COMPILETIME|5.007002||p -IN_LOCALE_RUNTIME|5.007002||p -IN_LOCALE|5.007002||p -IN_PERL_COMPILETIME|5.008001||p -IS_NUMBER_GREATER_THAN_UV_MAX|5.007002||p -IS_NUMBER_INFINITY|5.007002||p -IS_NUMBER_IN_UV|5.007002||p -IS_NUMBER_NAN|5.007003||p -IS_NUMBER_NEG|5.007002||p -IS_NUMBER_NOT_INT|5.007002||p -IVSIZE|5.006000||p -IVTYPE|5.006000||p -IVdf|5.006000||p -LEAVE||| -LINKLIST||5.013006| -LVRET||| -MARK||| -MULTICALL||5.021008| -MUTABLE_PTR|5.010001||p -MUTABLE_SV|5.010001||p -MY_CXT_CLONE|5.009002||p -MY_CXT_INIT|5.007003||p -MY_CXT|5.007003||p -MoveD|5.009002|5.004050|p -Move||| -NATIVE_TO_NEED||5.007001|n -NOOP|5.005000||p -NUM2PTR|5.006000||p -NVTYPE|5.006000||p -NVef|5.006001||p -NVff|5.006001||p -NVgf|5.006001||p -Newxc|5.009003||p -Newxz|5.009003||p -Newx|5.009003||p -Nullav||| -Nullch||| -Nullcv||| -Nullhv||| -Nullsv||| -OP_CLASS||5.013007| -OP_DESC||5.007003| -OP_NAME||5.007003| -OP_TYPE_IS_OR_WAS||5.019010| -OP_TYPE_IS||5.019007| -ORIGMARK||| -OpHAS_SIBLING||5.021007| -OpSIBLING_set||5.021007| -OpSIBLING||5.021007| -PAD_BASE_SV||| -PAD_CLONE_VARS||| -PAD_COMPNAME_FLAGS||| -PAD_COMPNAME_GEN_set||| -PAD_COMPNAME_GEN||| -PAD_COMPNAME_OURSTASH||| -PAD_COMPNAME_PV||| -PAD_COMPNAME_TYPE||| -PAD_RESTORE_LOCAL||| -PAD_SAVE_LOCAL||| -PAD_SAVE_SETNULLPAD||| -PAD_SETSV||| -PAD_SET_CUR_NOSAVE||| -PAD_SET_CUR||| -PAD_SVl||| -PAD_SV||| -PERLIO_FUNCS_CAST|5.009003||p -PERLIO_FUNCS_DECL|5.009003||p -PERL_ABS|5.008001||p -PERL_BCDVERSION|5.021008||p -PERL_GCC_BRACE_GROUPS_FORBIDDEN|5.008001||p -PERL_HASH|5.003070||p -PERL_INT_MAX|5.003070||p -PERL_INT_MIN|5.003070||p -PERL_LONG_MAX|5.003070||p -PERL_LONG_MIN|5.003070||p -PERL_MAGIC_arylen|5.007002||p -PERL_MAGIC_backref|5.007002||p -PERL_MAGIC_bm|5.007002||p -PERL_MAGIC_collxfrm|5.007002||p -PERL_MAGIC_dbfile|5.007002||p -PERL_MAGIC_dbline|5.007002||p -PERL_MAGIC_defelem|5.007002||p -PERL_MAGIC_envelem|5.007002||p -PERL_MAGIC_env|5.007002||p -PERL_MAGIC_ext|5.007002||p -PERL_MAGIC_fm|5.007002||p -PERL_MAGIC_glob|5.021008||p -PERL_MAGIC_isaelem|5.007002||p -PERL_MAGIC_isa|5.007002||p -PERL_MAGIC_mutex|5.021008||p -PERL_MAGIC_nkeys|5.007002||p -PERL_MAGIC_overload_elem|5.021008||p -PERL_MAGIC_overload_table|5.007002||p -PERL_MAGIC_overload|5.021008||p -PERL_MAGIC_pos|5.007002||p -PERL_MAGIC_qr|5.007002||p -PERL_MAGIC_regdata|5.007002||p -PERL_MAGIC_regdatum|5.007002||p -PERL_MAGIC_regex_global|5.007002||p -PERL_MAGIC_shared_scalar|5.007003||p -PERL_MAGIC_shared|5.007003||p -PERL_MAGIC_sigelem|5.007002||p -PERL_MAGIC_sig|5.007002||p -PERL_MAGIC_substr|5.007002||p -PERL_MAGIC_sv|5.007002||p -PERL_MAGIC_taint|5.007002||p -PERL_MAGIC_tiedelem|5.007002||p -PERL_MAGIC_tiedscalar|5.007002||p -PERL_MAGIC_tied|5.007002||p -PERL_MAGIC_utf8|5.008001||p -PERL_MAGIC_uvar_elem|5.007003||p -PERL_MAGIC_uvar|5.007002||p -PERL_MAGIC_vec|5.007002||p -PERL_MAGIC_vstring|5.008001||p -PERL_PV_ESCAPE_ALL|5.009004||p -PERL_PV_ESCAPE_FIRSTCHAR|5.009004||p -PERL_PV_ESCAPE_NOBACKSLASH|5.009004||p -PERL_PV_ESCAPE_NOCLEAR|5.009004||p -PERL_PV_ESCAPE_QUOTE|5.009004||p -PERL_PV_ESCAPE_RE|5.009005||p -PERL_PV_ESCAPE_UNI_DETECT|5.009004||p -PERL_PV_ESCAPE_UNI|5.009004||p -PERL_PV_PRETTY_DUMP|5.009004||p -PERL_PV_PRETTY_ELLIPSES|5.010000||p -PERL_PV_PRETTY_LTGT|5.009004||p -PERL_PV_PRETTY_NOCLEAR|5.010000||p -PERL_PV_PRETTY_QUOTE|5.009004||p -PERL_PV_PRETTY_REGPROP|5.009004||p -PERL_QUAD_MAX|5.003070||p -PERL_QUAD_MIN|5.003070||p -PERL_REVISION|5.006000||p -PERL_SCAN_ALLOW_UNDERSCORES|5.007003||p -PERL_SCAN_DISALLOW_PREFIX|5.007003||p -PERL_SCAN_GREATER_THAN_UV_MAX|5.007003||p -PERL_SCAN_SILENT_ILLDIGIT|5.008001||p -PERL_SHORT_MAX|5.003070||p -PERL_SHORT_MIN|5.003070||p -PERL_SIGNALS_UNSAFE_FLAG|5.008001||p -PERL_SUBVERSION|5.006000||p -PERL_SYS_INIT3||5.006000| -PERL_SYS_INIT||| -PERL_SYS_TERM||5.021008| -PERL_UCHAR_MAX|5.003070||p -PERL_UCHAR_MIN|5.003070||p -PERL_UINT_MAX|5.003070||p -PERL_UINT_MIN|5.003070||p -PERL_ULONG_MAX|5.003070||p -PERL_ULONG_MIN|5.003070||p -PERL_UNUSED_ARG|5.009003||p -PERL_UNUSED_CONTEXT|5.009004||p -PERL_UNUSED_DECL|5.007002||p -PERL_UNUSED_VAR|5.007002||p -PERL_UQUAD_MAX|5.003070||p -PERL_UQUAD_MIN|5.003070||p -PERL_USE_GCC_BRACE_GROUPS|5.009004||p -PERL_USHORT_MAX|5.003070||p -PERL_USHORT_MIN|5.003070||p -PERL_VERSION|5.006000||p -PL_DBsignal|5.005000||p -PL_DBsingle|||pn -PL_DBsub|||pn -PL_DBtrace|||pn -PL_Sv|5.005000||p -PL_bufend|5.021008||p -PL_bufptr|5.021008||p -PL_check||5.006000| -PL_compiling|5.004050||p -PL_comppad_name||5.017004| -PL_comppad||5.008001| -PL_copline|5.021008||p -PL_curcop|5.004050||p -PL_curpad||5.005000| -PL_curstash|5.004050||p -PL_debstash|5.004050||p -PL_defgv|5.004050||p -PL_diehook|5.004050||p -PL_dirty|5.004050||p -PL_dowarn|||pn -PL_errgv|5.004050||p -PL_error_count|5.021008||p -PL_expect|5.021008||p -PL_hexdigit|5.005000||p -PL_hints|5.005000||p -PL_in_my_stash|5.021008||p -PL_in_my|5.021008||p -PL_keyword_plugin||5.011002| -PL_last_in_gv|||n -PL_laststatval|5.005000||p -PL_lex_state|5.021008||p -PL_lex_stuff|5.021008||p -PL_linestr|5.021008||p -PL_modglobal||5.005000|n -PL_na|5.004050||pn -PL_no_modify|5.006000||p -PL_ofsgv|||n -PL_opfreehook||5.011000|n -PL_parser|5.009005||p -PL_peepp||5.007003|n -PL_perl_destruct_level|5.004050||p -PL_perldb|5.004050||p -PL_ppaddr|5.006000||p -PL_rpeepp||5.013005|n -PL_rsfp_filters|5.021008||p -PL_rsfp|5.021008||p -PL_rs|||n -PL_signals|5.008001||p -PL_stack_base|5.004050||p -PL_stack_sp|5.004050||p -PL_statcache|5.005000||p -PL_stdingv|5.004050||p -PL_sv_arenaroot|5.004050||p -PL_sv_no|5.004050||pn -PL_sv_undef|5.004050||pn -PL_sv_yes|5.004050||pn -PL_tainted|5.004050||p -PL_tainting|5.004050||p -PL_tokenbuf|5.021008||p -POP_MULTICALL||5.021008| -POPi|||n -POPl|||n -POPn|||n -POPpbytex||5.007001|n -POPpx||5.005030|n -POPp|||n -POPs|||n -PTR2IV|5.006000||p -PTR2NV|5.006000||p -PTR2UV|5.006000||p -PTR2nat|5.009003||p -PTR2ul|5.007001||p -PTRV|5.006000||p -PUSHMARK||| -PUSH_MULTICALL||5.021008| -PUSHi||| -PUSHmortal|5.009002||p -PUSHn||| -PUSHp||| -PUSHs||| -PUSHu|5.004000||p -PUTBACK||| -PadARRAY||5.021008| -PadMAX||5.021008| -PadlistARRAY||5.021008| -PadlistMAX||5.021008| -PadlistNAMESARRAY||5.021008| -PadlistNAMESMAX||5.021008| -PadlistNAMES||5.021008| -PadlistREFCNT||5.017004| -PadnameIsOUR||| -PadnameIsSTATE||| -PadnameLEN||5.021008| -PadnameOURSTASH||| -PadnameOUTER||| -PadnamePV||5.021008| -PadnameREFCNT_dec||5.021008| -PadnameREFCNT||5.021008| -PadnameSV||5.021008| -PadnameTYPE||| -PadnameUTF8||5.021007| -PadnamelistARRAY||5.021008| -PadnamelistMAX||5.021008| -PadnamelistREFCNT_dec||5.021008| -PadnamelistREFCNT||5.021008| -PerlIO_clearerr||5.007003| -PerlIO_close||5.007003| -PerlIO_context_layers||5.009004| -PerlIO_eof||5.007003| -PerlIO_error||5.007003| -PerlIO_fileno||5.007003| -PerlIO_fill||5.007003| -PerlIO_flush||5.007003| -PerlIO_get_base||5.007003| -PerlIO_get_bufsiz||5.007003| -PerlIO_get_cnt||5.007003| -PerlIO_get_ptr||5.007003| -PerlIO_read||5.007003| -PerlIO_restore_errno||| -PerlIO_save_errno||| -PerlIO_seek||5.007003| -PerlIO_set_cnt||5.007003| -PerlIO_set_ptrcnt||5.007003| -PerlIO_setlinebuf||5.007003| -PerlIO_stderr||5.007003| -PerlIO_stdin||5.007003| -PerlIO_stdout||5.007003| -PerlIO_tell||5.007003| -PerlIO_unread||5.007003| -PerlIO_write||5.007003| -Perl_signbit||5.009005|n -PoisonFree|5.009004||p -PoisonNew|5.009004||p -PoisonWith|5.009004||p -Poison|5.008000||p -READ_XDIGIT||5.017006| -RETVAL|||n -Renewc||| -Renew||| -SAVECLEARSV||| -SAVECOMPPAD||| -SAVEPADSV||| -SAVETMPS||| -SAVE_DEFSV|5.004050||p -SPAGAIN||| -SP||| -START_EXTERN_C|5.005000||p -START_MY_CXT|5.007003||p -STMT_END|||p -STMT_START|||p -STR_WITH_LEN|5.009003||p -ST||| -SV_CONST_RETURN|5.009003||p -SV_COW_DROP_PV|5.008001||p -SV_COW_SHARED_HASH_KEYS|5.009005||p -SV_GMAGIC|5.007002||p -SV_HAS_TRAILING_NUL|5.009004||p -SV_IMMEDIATE_UNREF|5.007001||p -SV_MUTABLE_RETURN|5.009003||p -SV_NOSTEAL|5.009002||p -SV_SMAGIC|5.009003||p -SV_UTF8_NO_ENCODING|5.008001||p -SVfARG|5.009005||p -SVf_UTF8|5.006000||p -SVf|5.006000||p -SVt_INVLIST||5.019002| -SVt_IV||| -SVt_NULL||| -SVt_NV||| -SVt_PVAV||| -SVt_PVCV||| -SVt_PVFM||| -SVt_PVGV||| -SVt_PVHV||| -SVt_PVIO||| -SVt_PVIV||| -SVt_PVLV||| -SVt_PVMG||| -SVt_PVNV||| -SVt_PV||| -SVt_REGEXP||5.011000| -Safefree||| -Slab_Alloc||| -Slab_Free||| -Slab_to_ro||| -Slab_to_rw||| -StructCopy||| -SvCUR_set||| -SvCUR||| -SvEND||| -SvGAMAGIC||5.006001| -SvGETMAGIC|5.004050||p -SvGROW||| -SvIOK_UV||5.006000| -SvIOK_notUV||5.006000| -SvIOK_off||| -SvIOK_only_UV||5.006000| -SvIOK_only||| -SvIOK_on||| -SvIOKp||| -SvIOK||| -SvIVX||| -SvIV_nomg|5.009001||p -SvIV_set||| -SvIVx||| -SvIV||| -SvIsCOW_shared_hash||5.008003| -SvIsCOW||5.008003| -SvLEN_set||| -SvLEN||| -SvLOCK||5.007003| -SvMAGIC_set|5.009003||p -SvNIOK_off||| -SvNIOKp||| -SvNIOK||| -SvNOK_off||| -SvNOK_only||| -SvNOK_on||| -SvNOKp||| -SvNOK||| -SvNVX||| -SvNV_nomg||5.013002| -SvNV_set||| -SvNVx||| -SvNV||| -SvOK||| -SvOOK_offset||5.011000| -SvOOK||| -SvPOK_off||| -SvPOK_only_UTF8||5.006000| -SvPOK_only||| -SvPOK_on||| -SvPOKp||| -SvPOK||| -SvPVX_const|5.009003||p -SvPVX_mutable|5.009003||p -SvPVX||| -SvPV_const|5.009003||p -SvPV_flags_const_nolen|5.009003||p -SvPV_flags_const|5.009003||p -SvPV_flags_mutable|5.009003||p -SvPV_flags|5.007002||p -SvPV_force_flags_mutable|5.009003||p -SvPV_force_flags_nolen|5.009003||p -SvPV_force_flags|5.007002||p -SvPV_force_mutable|5.009003||p -SvPV_force_nolen|5.009003||p -SvPV_force_nomg_nolen|5.009003||p -SvPV_force_nomg|5.007002||p -SvPV_force|||p -SvPV_mutable|5.009003||p -SvPV_nolen_const|5.009003||p -SvPV_nolen|5.006000||p -SvPV_nomg_const_nolen|5.009003||p -SvPV_nomg_const|5.009003||p -SvPV_nomg_nolen|5.013007||p -SvPV_nomg|5.007002||p -SvPV_renew|5.009003||p -SvPV_set||| -SvPVbyte_force||5.009002| -SvPVbyte_nolen||5.006000| -SvPVbytex_force||5.006000| -SvPVbytex||5.006000| -SvPVbyte|5.006000||p -SvPVutf8_force||5.006000| -SvPVutf8_nolen||5.006000| -SvPVutf8x_force||5.006000| -SvPVutf8x||5.006000| -SvPVutf8||5.006000| -SvPVx||| -SvPV||| -SvREFCNT_dec_NN||5.017007| -SvREFCNT_dec||| -SvREFCNT_inc_NN|5.009004||p -SvREFCNT_inc_simple_NN|5.009004||p -SvREFCNT_inc_simple_void_NN|5.009004||p -SvREFCNT_inc_simple_void|5.009004||p -SvREFCNT_inc_simple|5.009004||p -SvREFCNT_inc_void_NN|5.009004||p -SvREFCNT_inc_void|5.009004||p -SvREFCNT_inc|||p -SvREFCNT||| -SvROK_off||| -SvROK_on||| -SvROK||| -SvRV_set|5.009003||p -SvRV||| -SvRXOK||5.009005| -SvRX||5.009005| -SvSETMAGIC||| -SvSHARED_HASH|5.009003||p -SvSHARE||5.007003| -SvSTASH_set|5.009003||p -SvSTASH||| -SvSetMagicSV_nosteal||5.004000| -SvSetMagicSV||5.004000| -SvSetSV_nosteal||5.004000| -SvSetSV||| -SvTAINTED_off||5.004000| -SvTAINTED_on||5.004000| -SvTAINTED||5.004000| -SvTAINT||| -SvTHINKFIRST||| -SvTRUE_nomg||5.013006| -SvTRUE||| -SvTYPE||| -SvUNLOCK||5.007003| -SvUOK|5.007001|5.006000|p -SvUPGRADE||| -SvUTF8_off||5.006000| -SvUTF8_on||5.006000| -SvUTF8||5.006000| -SvUVXx|5.004000||p -SvUVX|5.004000||p -SvUV_nomg|5.009001||p -SvUV_set|5.009003||p -SvUVx|5.004000||p -SvUV|5.004000||p -SvVOK||5.008001| -SvVSTRING_mg|5.009004||p -THIS|||n -UNDERBAR|5.009002||p -UTF8_MAXBYTES|5.009002||p -UVSIZE|5.006000||p -UVTYPE|5.006000||p -UVXf|5.007001||p -UVof|5.006000||p -UVuf|5.006000||p -UVxf|5.006000||p -WARN_ALL|5.006000||p -WARN_AMBIGUOUS|5.006000||p -WARN_ASSERTIONS|5.021008||p -WARN_BAREWORD|5.006000||p -WARN_CLOSED|5.006000||p -WARN_CLOSURE|5.006000||p -WARN_DEBUGGING|5.006000||p -WARN_DEPRECATED|5.006000||p -WARN_DIGIT|5.006000||p -WARN_EXEC|5.006000||p -WARN_EXITING|5.006000||p -WARN_GLOB|5.006000||p -WARN_INPLACE|5.006000||p -WARN_INTERNAL|5.006000||p -WARN_IO|5.006000||p -WARN_LAYER|5.008000||p -WARN_MALLOC|5.006000||p -WARN_MISC|5.006000||p -WARN_NEWLINE|5.006000||p -WARN_NUMERIC|5.006000||p -WARN_ONCE|5.006000||p -WARN_OVERFLOW|5.006000||p -WARN_PACK|5.006000||p -WARN_PARENTHESIS|5.006000||p -WARN_PIPE|5.006000||p -WARN_PORTABLE|5.006000||p -WARN_PRECEDENCE|5.006000||p -WARN_PRINTF|5.006000||p -WARN_PROTOTYPE|5.006000||p -WARN_QW|5.006000||p -WARN_RECURSION|5.006000||p -WARN_REDEFINE|5.006000||p -WARN_REGEXP|5.006000||p -WARN_RESERVED|5.006000||p -WARN_SEMICOLON|5.006000||p -WARN_SEVERE|5.006000||p -WARN_SIGNAL|5.006000||p -WARN_SUBSTR|5.006000||p -WARN_SYNTAX|5.006000||p -WARN_TAINT|5.006000||p -WARN_THREADS|5.008000||p -WARN_UNINITIALIZED|5.006000||p -WARN_UNOPENED|5.006000||p -WARN_UNPACK|5.006000||p -WARN_UNTIE|5.006000||p -WARN_UTF8|5.006000||p -WARN_VOID|5.006000||p -WIDEST_UTYPE|5.015004||p -XCPT_CATCH|5.009002||p -XCPT_RETHROW|5.009002||p -XCPT_TRY_END|5.009002||p -XCPT_TRY_START|5.009002||p -XPUSHi||| -XPUSHmortal|5.009002||p -XPUSHn||| -XPUSHp||| -XPUSHs||| -XPUSHu|5.004000||p -XSPROTO|5.010000||p -XSRETURN_EMPTY||| -XSRETURN_IV||| -XSRETURN_NO||| -XSRETURN_NV||| -XSRETURN_PV||| -XSRETURN_UNDEF||| -XSRETURN_UV|5.008001||p -XSRETURN_YES||| -XSRETURN|||p -XST_mIV||| -XST_mNO||| -XST_mNV||| -XST_mPV||| -XST_mUNDEF||| -XST_mUV|5.008001||p -XST_mYES||| -XS_APIVERSION_BOOTCHECK||5.021008| -XS_EXTERNAL||5.021008| -XS_INTERNAL||5.021008| -XS_VERSION_BOOTCHECK||5.021008| -XS_VERSION||| -XSprePUSH|5.006000||p -XS||| -XopDISABLE||5.021008| -XopENABLE||5.021008| -XopENTRYCUSTOM||5.021008| -XopENTRY_set||5.021008| -XopENTRY||5.021008| -XopFLAGS||5.013007| -ZeroD|5.009002||p -Zero||| -_aMY_CXT|5.007003||p -_add_range_to_invlist||| -_append_range_to_invlist||| -_core_swash_init||| -_get_encoding||| -_get_regclass_nonbitmap_data||| -_get_swash_invlist||| -_invlist_array_init|||n -_invlist_contains_cp|||n -_invlist_contents||| -_invlist_dump||| -_invlist_intersection_maybe_complement_2nd||| -_invlist_intersection||| -_invlist_invert||| -_invlist_len|||n -_invlist_populate_swatch|||n -_invlist_search|||n -_invlist_subtract||| -_invlist_union_maybe_complement_2nd||| -_invlist_union||| -_is_cur_LC_category_utf8||| -_is_in_locale_category||5.021001| -_is_uni_FOO||5.017008| -_is_uni_perl_idcont||5.017008| -_is_uni_perl_idstart||5.017007| -_is_utf8_FOO||5.017008| -_is_utf8_char_slow||5.021001|n -_is_utf8_idcont||5.021001| -_is_utf8_idstart||5.021001| -_is_utf8_mark||5.017008| -_is_utf8_perl_idcont||5.017008| -_is_utf8_perl_idstart||5.017007| -_is_utf8_xidcont||5.021001| -_is_utf8_xidstart||5.021001| -_load_PL_utf8_foldclosures||| -_make_exactf_invlist||| -_new_invlist_C_array||| -_new_invlist||| -_pMY_CXT|5.007003||p -_setup_canned_invlist||| -_swash_inversion_hash||| -_swash_to_invlist||| -_to_fold_latin1||| -_to_uni_fold_flags||5.014000| -_to_upper_title_latin1||| -_to_utf8_fold_flags||5.019009| -_to_utf8_lower_flags||5.019009| -_to_utf8_title_flags||5.019009| -_to_utf8_upper_flags||5.019009| -_warn_problematic_locale|||n -aMY_CXT_|5.007003||p -aMY_CXT|5.007003||p -aTHXR_|5.021008||p -aTHXR|5.021008||p -aTHX_|5.006000||p -aTHX|5.006000||p -aassign_common_vars||| -add_above_Latin1_folds||| -add_cp_to_invlist||| -add_data|||n -add_multi_match||| -add_utf16_textfilter||| -adjust_size_and_find_bucket|||n -advance_one_SB||| -advance_one_WB||| -alloc_maybe_populate_EXACT||| -alloccopstash||| -allocmy||| -amagic_call||| -amagic_cmp_locale||| -amagic_cmp||| -amagic_deref_call||5.013007| -amagic_i_ncmp||| -amagic_is_enabled||| -amagic_ncmp||| -anonymise_cv_maybe||| -any_dup||| -ao||| -append_utf8_from_native_byte||5.019004|n -apply_attrs_my||| -apply_attrs_string||5.006001| -apply_attrs||| -apply||| -assert_uft8_cache_coherent||| -assignment_type||| -atfork_lock||5.007003|n -atfork_unlock||5.007003|n -av_arylen_p||5.009003| -av_clear||| -av_create_and_push||5.009005| -av_create_and_unshift_one||5.009005| -av_delete||5.006000| -av_exists||5.006000| -av_extend_guts||| -av_extend||| -av_fetch||| -av_fill||| -av_iter_p||5.011000| -av_len||| -av_make||| -av_pop||| -av_push||| -av_reify||| -av_shift||| -av_store||| -av_tindex||5.017009| -av_top_index||5.017009| -av_undef||| -av_unshift||| -ax|||n -backup_one_SB||| -backup_one_WB||| -bad_type_gv||| -bad_type_pv||| -bind_match||| -block_end||5.004000| -block_gimme||5.004000| -block_start||5.004000| -blockhook_register||5.013003| -boolSV|5.004000||p -boot_core_PerlIO||| -boot_core_UNIVERSAL||| -boot_core_mro||| -bytes_cmp_utf8||5.013007| -bytes_from_utf8||5.007001| -bytes_to_utf8||5.006001| -call_argv|5.006000||p -call_atexit||5.006000| -call_list||5.004000| -call_method|5.006000||p -call_pv|5.006000||p -call_sv|5.006000||p -caller_cx|5.013005|5.006000|p -calloc||5.007002|n -cando||| -cast_i32||5.006000|n -cast_iv||5.006000|n -cast_ulong||5.006000|n -cast_uv||5.006000|n -check_locale_boundary_crossing||| -check_type_and_open||| -check_uni||| -check_utf8_print||| -checkcomma||| -ckWARN|5.006000||p -ck_entersub_args_core||| -ck_entersub_args_list||5.013006| -ck_entersub_args_proto_or_list||5.013006| -ck_entersub_args_proto||5.013006| -ck_warner_d||5.011001|v -ck_warner||5.011001|v -ckwarn_common||| -ckwarn_d||5.009003| -ckwarn||5.009003| -clear_placeholders||| -clear_special_blocks||| -clone_params_del|||n -clone_params_new|||n -closest_cop||| -cntrl_to_mnemonic|||n -compute_EXACTish|||n -construct_ahocorasick_from_trie||| -cop_fetch_label||5.015001| -cop_free||| -cop_hints_2hv||5.013007| -cop_hints_fetch_pvn||5.013007| -cop_hints_fetch_pvs||5.013007| -cop_hints_fetch_pv||5.013007| -cop_hints_fetch_sv||5.013007| -cop_store_label||5.015001| -cophh_2hv||5.013007| -cophh_copy||5.013007| -cophh_delete_pvn||5.013007| -cophh_delete_pvs||5.013007| -cophh_delete_pv||5.013007| -cophh_delete_sv||5.013007| -cophh_fetch_pvn||5.013007| -cophh_fetch_pvs||5.013007| -cophh_fetch_pv||5.013007| -cophh_fetch_sv||5.013007| -cophh_free||5.013007| -cophh_new_empty||5.021008| -cophh_store_pvn||5.013007| -cophh_store_pvs||5.013007| -cophh_store_pv||5.013007| -cophh_store_sv||5.013007| -core_prototype||| -coresub_op||| -could_it_be_a_POSIX_class|||n -cr_textfilter||| -create_eval_scope||| -croak_memory_wrap||5.019003|n -croak_no_mem|||n -croak_no_modify||5.013003|n -croak_nocontext|||vn -croak_popstack|||n -croak_sv||5.013001| -croak_xs_usage||5.010001|n -croak|||v -csighandler||5.009003|n -current_re_engine||| -curse||| -custom_op_desc||5.007003| -custom_op_get_field||| -custom_op_name||5.007003| -custom_op_register||5.013007| -custom_op_xop||5.013007| -cv_ckproto_len_flags||| -cv_clone_into||| -cv_clone||| -cv_const_sv_or_av|||n -cv_const_sv||5.003070|n -cv_dump||| -cv_forget_slab||| -cv_get_call_checker||5.013006| -cv_name||5.021005| -cv_set_call_checker_flags||5.021004| -cv_set_call_checker||5.013006| -cv_undef_flags||| -cv_undef||| -cvgv_from_hek||| -cvgv_set||| -cvstash_set||| -cx_dump||5.005000| -cx_dup||| -cxinc||| -dAXMARK|5.009003||p -dAX|5.007002||p -dITEMS|5.007002||p -dMARK||| -dMULTICALL||5.009003| -dMY_CXT_SV|5.007003||p -dMY_CXT|5.007003||p -dNOOP|5.006000||p -dORIGMARK||| -dSP||| -dTHR|5.004050||p -dTHXR|5.021008||p -dTHXa|5.006000||p -dTHXoa|5.006000||p -dTHX|5.006000||p -dUNDERBAR|5.009002||p -dVAR|5.009003||p -dXCPT|5.009002||p -dXSARGS||| -dXSI32||| -dXSTARG|5.006000||p -deb_curcv||| -deb_nocontext|||vn -deb_stack_all||| -deb_stack_n||| -debop||5.005000| -debprofdump||5.005000| -debprof||| -debstackptrs||5.007003| -debstack||5.007003| -debug_start_match||| -deb||5.007003|v -defelem_target||| -del_sv||| -delete_eval_scope||| -delimcpy||5.004000|n -deprecate_commaless_var_list||| -despatch_signals||5.007001| -destroy_matcher||| -die_nocontext|||vn -die_sv||5.013001| -die_unwind||| -die|||v -dirp_dup||| -div128||| -djSP||| -do_aexec5||| -do_aexec||| -do_aspawn||| -do_binmode||5.004050| -do_chomp||| -do_close||| -do_delete_local||| -do_dump_pad||| -do_eof||| -do_exec3||| -do_execfree||| -do_exec||| -do_gv_dump||5.006000| -do_gvgv_dump||5.006000| -do_hv_dump||5.006000| -do_ipcctl||| -do_ipcget||| -do_join||| -do_magic_dump||5.006000| -do_msgrcv||| -do_msgsnd||| -do_ncmp||| -do_oddball||| -do_op_dump||5.006000| -do_open6||| -do_open9||5.006000| -do_open_raw||| -do_openn||5.007001| -do_open||5.003070| -do_pmop_dump||5.006000| -do_print||| -do_readline||| -do_seek||| -do_semop||| -do_shmio||| -do_smartmatch||| -do_spawn_nowait||| -do_spawn||| -do_sprintf||| -do_sv_dump||5.006000| -do_sysseek||| -do_tell||| -do_trans_complex_utf8||| -do_trans_complex||| -do_trans_count_utf8||| -do_trans_count||| -do_trans_simple_utf8||| -do_trans_simple||| -do_trans||| -do_vecget||| -do_vecset||| -do_vop||| -docatch||| -doeval||| -dofile||| -dofindlabel||| -doform||| -doing_taint||5.008001|n -dooneliner||| -doopen_pm||| -doparseform||| -dopoptoeval||| -dopoptogiven||| -dopoptolabel||| -dopoptoloop||| -dopoptosub_at||| -dopoptowhen||| -doref||5.009003| -dounwind||| -dowantarray||| -drand48_init_r|||n -drand48_r|||n -dump_all_perl||| -dump_all||5.006000| -dump_c_backtrace||| -dump_eval||5.006000| -dump_exec_pos||| -dump_form||5.006000| -dump_indent||5.006000|v -dump_mstats||| -dump_packsubs_perl||| -dump_packsubs||5.006000| -dump_sub_perl||| -dump_sub||5.006000| -dump_sv_child||| -dump_trie_interim_list||| -dump_trie_interim_table||| -dump_trie||| -dump_vindent||5.006000| -dumpuntil||| -dup_attrlist||| -emulate_cop_io||| -eval_pv|5.006000||p -eval_sv|5.006000||p -exec_failed||| -expect_number||| -fbm_compile||5.005000| -fbm_instr||5.005000| -feature_is_enabled||| -filter_add||| -filter_del||| -filter_gets||| -filter_read||| -finalize_optree||| -finalize_op||| -find_and_forget_pmops||| -find_array_subscript||| -find_beginning||| -find_byclass||| -find_default_stash||| -find_hash_subscript||| -find_in_my_stash||| -find_lexical_cv||| -find_runcv_where||| -find_runcv||5.008001| -find_rundefsv2||| -find_rundefsvoffset||5.009002| -find_rundefsv||5.013002| -find_script||| -find_uninit_var||| -first_symbol|||n -fixup_errno_string||| -foldEQ_latin1||5.013008|n -foldEQ_locale||5.013002|n -foldEQ_utf8_flags||5.013010| -foldEQ_utf8||5.013002| -foldEQ||5.013002|n -fold_constants||| -forbid_setid||| -force_ident_maybe_lex||| -force_ident||| -force_list||| -force_next||| -force_strict_version||| -force_version||| -force_word||| -forget_pmop||| -form_nocontext|||vn -form_short_octal_warning||| -form||5.004000|v -fp_dup||| -fprintf_nocontext|||vn -free_c_backtrace||| -free_global_struct||| -free_tied_hv_pool||| -free_tmps||| -gen_constant_list||| -get_ANYOF_cp_list_for_ssc||| -get_and_check_backslash_N_name||| -get_aux_mg||| -get_av|5.006000||p -get_c_backtrace_dump||| -get_c_backtrace||| -get_context||5.006000|n -get_cvn_flags|5.009005||p -get_cvs|5.011000||p -get_cv|5.006000||p -get_db_sub||| -get_debug_opts||| -get_hash_seed||| -get_hv|5.006000||p -get_invlist_iter_addr|||n -get_invlist_offset_addr|||n -get_invlist_previous_index_addr|||n -get_mstats||| -get_no_modify||| -get_num||| -get_op_descs||5.005000| -get_op_names||5.005000| -get_opargs||| -get_ppaddr||5.006000| -get_re_arg||| -get_sv|5.006000||p -get_vtbl||5.005030| -getcwd_sv||5.007002| -getenv_len||| -glob_2number||| -glob_assign_glob||| -gp_dup||| -gp_free||| -gp_ref||| -grok_atoUV|||n -grok_bin|5.007003||p -grok_bslash_N||| -grok_bslash_c||| -grok_bslash_o||| -grok_bslash_x||| -grok_hex|5.007003||p -grok_infnan||5.021004| -grok_number_flags||5.021002| -grok_number|5.007002||p -grok_numeric_radix|5.007002||p -grok_oct|5.007003||p -group_end||| -gv_AVadd||| -gv_HVadd||| -gv_IOadd||| -gv_SVadd||| -gv_add_by_type||5.011000| -gv_autoload4||5.004000| -gv_autoload_pvn||5.015004| -gv_autoload_pv||5.015004| -gv_autoload_sv||5.015004| -gv_check||| -gv_const_sv||5.009003| -gv_dump||5.006000| -gv_efullname3||5.003070| -gv_efullname4||5.006001| -gv_efullname||| -gv_fetchfile_flags||5.009005| -gv_fetchfile||| -gv_fetchmeth_autoload||5.007003| -gv_fetchmeth_internal||| -gv_fetchmeth_pv_autoload||5.015004| -gv_fetchmeth_pvn_autoload||5.015004| -gv_fetchmeth_pvn||5.015004| -gv_fetchmeth_pv||5.015004| -gv_fetchmeth_sv_autoload||5.015004| -gv_fetchmeth_sv||5.015004| -gv_fetchmethod_autoload||5.004000| -gv_fetchmethod_pv_flags||5.015004| -gv_fetchmethod_pvn_flags||5.015004| -gv_fetchmethod_sv_flags||5.015004| -gv_fetchmethod||| -gv_fetchmeth||| -gv_fetchpvn_flags|5.009002||p -gv_fetchpvs|5.009004||p -gv_fetchpv||| -gv_fetchsv|5.009002||p -gv_fullname3||5.003070| -gv_fullname4||5.006001| -gv_fullname||| -gv_handler||5.007001| -gv_init_pvn||5.015004| -gv_init_pv||5.015004| -gv_init_svtype||| -gv_init_sv||5.015004| -gv_init||| -gv_is_in_main||| -gv_magicalize_isa||| -gv_magicalize||| -gv_name_set||5.009004| -gv_override||| -gv_setref||| -gv_stashpvn_internal||| -gv_stashpvn|5.003070||p -gv_stashpvs|5.009003||p -gv_stashpv||| -gv_stashsvpvn_cached||| -gv_stashsv||| -gv_try_downgrade||| -handle_regex_sets||| -he_dup||| -hek_dup||| -hfree_next_entry||| -hfreeentries||| -hsplit||| -hv_assert||| -hv_auxinit_internal|||n -hv_auxinit||| -hv_backreferences_p||| -hv_clear_placeholders||5.009001| -hv_clear||| -hv_common_key_len||5.010000| -hv_common||5.010000| -hv_copy_hints_hv||5.009004| -hv_delayfree_ent||5.004000| -hv_delete_common||| -hv_delete_ent||5.003070| -hv_delete||| -hv_eiter_p||5.009003| -hv_eiter_set||5.009003| -hv_ename_add||| -hv_ename_delete||| -hv_exists_ent||5.003070| -hv_exists||| -hv_fetch_ent||5.003070| -hv_fetchs|5.009003||p -hv_fetch||| -hv_fill||5.013002| -hv_free_ent_ret||| -hv_free_ent||5.004000| -hv_iterinit||| -hv_iterkeysv||5.003070| -hv_iterkey||| -hv_iternext_flags||5.008000| -hv_iternextsv||| -hv_iternext||| -hv_iterval||| -hv_kill_backrefs||| -hv_ksplit||5.003070| -hv_magic_check|||n -hv_magic||| -hv_name_set||5.009003| -hv_notallowed||| -hv_placeholders_get||5.009003| -hv_placeholders_p||| -hv_placeholders_set||5.009003| -hv_rand_set||5.018000| -hv_riter_p||5.009003| -hv_riter_set||5.009003| -hv_scalar||5.009001| -hv_store_ent||5.003070| -hv_store_flags||5.008000| -hv_stores|5.009004||p -hv_store||| -hv_undef_flags||| -hv_undef||| -ibcmp_locale||5.004000| -ibcmp_utf8||5.007003| -ibcmp||| -incline||| -incpush_if_exists||| -incpush_use_sep||| -incpush||| -ingroup||| -init_argv_symbols||| -init_constants||| -init_dbargs||| -init_debugger||| -init_global_struct||| -init_i18nl10n||5.006000| -init_i18nl14n||5.006000| -init_ids||| -init_interp||| -init_main_stash||| -init_perllib||| -init_postdump_symbols||| -init_predump_symbols||| -init_stacks||5.005000| -init_tm||5.007002| -inplace_aassign||| -instr|||n -intro_my||5.004000| -intuit_method||| -intuit_more||| -invert||| -invlist_array|||n -invlist_clone||| -invlist_extend||| -invlist_highest|||n -invlist_is_iterating|||n -invlist_iterfinish|||n -invlist_iterinit|||n -invlist_iternext|||n -invlist_max|||n -invlist_previous_index|||n -invlist_set_len||| -invlist_set_previous_index|||n -invlist_trim|||n -invoke_exception_hook||| -io_close||| -isALNUMC|5.006000||p -isALNUM_lazy||5.021001| -isALPHANUMERIC||5.017008| -isALPHA||| -isASCII|5.006000||p -isBLANK|5.006001||p -isCNTRL|5.006000||p -isDIGIT||| -isFOO_lc||| -isFOO_utf8_lc||| -isGCB|||n -isGRAPH|5.006000||p -isGV_with_GP|5.009004||p -isIDCONT||5.017008| -isIDFIRST_lazy||5.021001| -isIDFIRST||| -isLOWER||| -isOCTAL||5.013005| -isPRINT|5.004000||p -isPSXSPC|5.006001||p -isPUNCT|5.006000||p -isSB||| -isSPACE||| -isUPPER||| -isUTF8_CHAR||5.021001| -isWB||| -isWORDCHAR||5.013006| -isXDIGIT|5.006000||p -is_an_int||| -is_ascii_string||5.011000| -is_handle_constructor|||n -is_invariant_string||5.021007|n -is_lvalue_sub||5.007001| -is_safe_syscall||5.019004| -is_ssc_worth_it|||n -is_uni_alnum_lc||5.006000| -is_uni_alnumc_lc||5.017007| -is_uni_alnumc||5.017007| -is_uni_alnum||5.006000| -is_uni_alpha_lc||5.006000| -is_uni_alpha||5.006000| -is_uni_ascii_lc||5.006000| -is_uni_ascii||5.006000| -is_uni_blank_lc||5.017002| -is_uni_blank||5.017002| -is_uni_cntrl_lc||5.006000| -is_uni_cntrl||5.006000| -is_uni_digit_lc||5.006000| -is_uni_digit||5.006000| -is_uni_graph_lc||5.006000| -is_uni_graph||5.006000| -is_uni_idfirst_lc||5.006000| -is_uni_idfirst||5.006000| -is_uni_lower_lc||5.006000| -is_uni_lower||5.006000| -is_uni_print_lc||5.006000| -is_uni_print||5.006000| -is_uni_punct_lc||5.006000| -is_uni_punct||5.006000| -is_uni_space_lc||5.006000| -is_uni_space||5.006000| -is_uni_upper_lc||5.006000| -is_uni_upper||5.006000| -is_uni_xdigit_lc||5.006000| -is_uni_xdigit||5.006000| -is_utf8_alnumc||5.017007| -is_utf8_alnum||5.006000| -is_utf8_alpha||5.006000| -is_utf8_ascii||5.006000| -is_utf8_blank||5.017002| -is_utf8_char_buf||5.015008|n -is_utf8_char||5.006000|n -is_utf8_cntrl||5.006000| -is_utf8_common||| -is_utf8_digit||5.006000| -is_utf8_graph||5.006000| -is_utf8_idcont||5.008000| -is_utf8_idfirst||5.006000| -is_utf8_lower||5.006000| -is_utf8_mark||5.006000| -is_utf8_perl_space||5.011001| -is_utf8_perl_word||5.011001| -is_utf8_posix_digit||5.011001| -is_utf8_print||5.006000| -is_utf8_punct||5.006000| -is_utf8_space||5.006000| -is_utf8_string_loclen||5.009003|n -is_utf8_string_loc||5.008001|n -is_utf8_string||5.006001|n -is_utf8_upper||5.006000| -is_utf8_xdigit||5.006000| -is_utf8_xidcont||5.013010| -is_utf8_xidfirst||5.013010| -isa_lookup||| -isinfnansv||| -isinfnan||5.021004|n -items|||n -ix|||n -jmaybe||| -join_exact||| -keyword_plugin_standard||| -keyword||| -leave_common||| -leave_scope||| -lex_bufutf8||5.011002| -lex_discard_to||5.011002| -lex_grow_linestr||5.011002| -lex_next_chunk||5.011002| -lex_peek_unichar||5.011002| -lex_read_space||5.011002| -lex_read_to||5.011002| -lex_read_unichar||5.011002| -lex_start||5.009005| -lex_stuff_pvn||5.011002| -lex_stuff_pvs||5.013005| -lex_stuff_pv||5.013006| -lex_stuff_sv||5.011002| -lex_unstuff||5.011002| -listkids||| -list||| -load_module_nocontext|||vn -load_module|5.006000||pv -localize||| -looks_like_bool||| -looks_like_number||| -lop||| -mPUSHi|5.009002||p -mPUSHn|5.009002||p -mPUSHp|5.009002||p -mPUSHs|5.010001||p -mPUSHu|5.009002||p -mXPUSHi|5.009002||p -mXPUSHn|5.009002||p -mXPUSHp|5.009002||p -mXPUSHs|5.010001||p -mXPUSHu|5.009002||p -magic_clear_all_env||| -magic_cleararylen_p||| -magic_clearenv||| -magic_clearhints||| -magic_clearhint||| -magic_clearisa||| -magic_clearpack||| -magic_clearsig||| -magic_copycallchecker||| -magic_dump||5.006000| -magic_existspack||| -magic_freearylen_p||| -magic_freeovrld||| -magic_getarylen||| -magic_getdebugvar||| -magic_getdefelem||| -magic_getnkeys||| -magic_getpack||| -magic_getpos||| -magic_getsig||| -magic_getsubstr||| -magic_gettaint||| -magic_getuvar||| -magic_getvec||| -magic_get||| -magic_killbackrefs||| -magic_methcall1||| -magic_methcall|||v -magic_methpack||| -magic_nextpack||| -magic_regdata_cnt||| -magic_regdatum_get||| -magic_regdatum_set||| -magic_scalarpack||| -magic_set_all_env||| -magic_setarylen||| -magic_setcollxfrm||| -magic_setdbline||| -magic_setdebugvar||| -magic_setdefelem||| -magic_setenv||| -magic_sethint||| -magic_setisa||| -magic_setlvref||| -magic_setmglob||| -magic_setnkeys||| -magic_setpack||| -magic_setpos||| -magic_setregexp||| -magic_setsig||| -magic_setsubstr||| -magic_settaint||| -magic_setutf8||| -magic_setuvar||| -magic_setvec||| -magic_set||| -magic_sizepack||| -magic_wipepack||| -make_matcher||| -make_trie||| -malloc_good_size|||n -malloced_size|||n -malloc||5.007002|n -markstack_grow||5.021001| -matcher_matches_sv||| -maybe_multimagic_gv||| -mayberelocate||| -measure_struct||| -memEQs|5.009005||p -memEQ|5.004000||p -memNEs|5.009005||p -memNE|5.004000||p -mem_collxfrm||| -mem_log_common|||n -mess_alloc||| -mess_nocontext|||vn -mess_sv||5.013001| -mess||5.006000|v -mfree||5.007002|n -mg_clear||| -mg_copy||| -mg_dup||| -mg_find_mglob||| -mg_findext|5.013008||pn -mg_find|||n -mg_free_type||5.013006| -mg_free||| -mg_get||| -mg_length||5.005000| -mg_localize||| -mg_magical|||n -mg_set||| -mg_size||5.005000| -mini_mktime||5.007002|n -minus_v||| -missingterm||| -mode_from_discipline||| -modkids||| -more_bodies||| -more_sv||| -moreswitches||| -move_proto_attr||| -mro_clean_isarev||| -mro_gather_and_rename||| -mro_get_from_name||5.010001| -mro_get_linear_isa_dfs||| -mro_get_linear_isa||5.009005| -mro_get_private_data||5.010001| -mro_isa_changed_in||| -mro_meta_dup||| -mro_meta_init||| -mro_method_changed_in||5.009005| -mro_package_moved||| -mro_register||5.010001| -mro_set_mro||5.010001| -mro_set_private_data||5.010001| -mul128||| -mulexp10|||n -multideref_stringify||| -my_atof2||5.007002| -my_atof||5.006000| -my_attrs||| -my_bcopy|||n -my_bytes_to_utf8|||n -my_bzero|||n -my_chsize||| -my_clearenv||| -my_cxt_index||| -my_cxt_init||| -my_dirfd||5.009005|n -my_exit_jump||| -my_exit||| -my_failure_exit||5.004000| -my_fflush_all||5.006000| -my_fork||5.007003|n -my_kid||| -my_lstat_flags||| -my_lstat||5.021008| -my_memcmp|||n -my_memset|||n -my_pclose||5.003070| -my_popen_list||5.007001| -my_popen||5.003070| -my_setenv||| -my_setlocale||| -my_snprintf|5.009004||pvn -my_socketpair||5.007003|n -my_sprintf|5.009003||pvn -my_stat_flags||| -my_stat||5.021008| -my_strerror||5.021001| -my_strftime||5.007002| -my_strlcat|5.009004||pn -my_strlcpy|5.009004||pn -my_unexec||| -my_vsnprintf||5.009004|n -need_utf8|||n -newANONATTRSUB||5.006000| -newANONHASH||| -newANONLIST||| -newANONSUB||| -newASSIGNOP||| -newATTRSUB_x||| -newATTRSUB||5.006000| -newAVREF||| -newAV||| -newBINOP||| -newCONDOP||| -newCONSTSUB_flags||5.015006| -newCONSTSUB|5.004050||p -newCVREF||| -newDEFSVOP||5.021006| -newFORM||| -newFOROP||5.013007| -newGIVENOP||5.009003| -newGIVWHENOP||| -newGP||| -newGVOP||| -newGVREF||| -newGVgen_flags||5.015004| -newGVgen||| -newHVREF||| -newHVhv||5.005000| -newHV||| -newIO||| -newLISTOP||| -newLOGOP||| -newLOOPEX||| -newLOOPOP||| -newMETHOP_internal||| -newMETHOP_named||5.021005| -newMETHOP||5.021005| -newMYSUB||5.017004| -newNULLLIST||| -newOP||| -newPADNAMELIST||5.021007|n -newPADNAMEouter||5.021007|n -newPADNAMEpvn||5.021007|n -newPADOP||| -newPMOP||| -newPROG||| -newPVOP||| -newRANGE||| -newRV_inc|5.004000||p -newRV_noinc|5.004000||p -newRV||| -newSLICEOP||| -newSTATEOP||| -newSTUB||| -newSUB||| -newSVOP||| -newSVREF||| -newSV_type|5.009005||p -newSVavdefelem||| -newSVhek||5.009003| -newSViv||| -newSVnv||| -newSVpadname||5.017004| -newSVpv_share||5.013006| -newSVpvf_nocontext|||vn -newSVpvf||5.004000|v -newSVpvn_flags|5.010001||p -newSVpvn_share|5.007001||p -newSVpvn_utf8|5.010001||p -newSVpvn|5.004050||p -newSVpvs_flags|5.010001||p -newSVpvs_share|5.009003||p -newSVpvs|5.009003||p -newSVpv||| -newSVrv||| -newSVsv||| -newSVuv|5.006000||p -newSV||| -newUNOP_AUX||5.021007| -newUNOP||| -newWHENOP||5.009003| -newWHILEOP||5.013007| -newXS_deffile||| -newXS_flags||5.009004| -newXS_len_flags||| -newXSproto||5.006000| -newXS||5.006000| -new_collate||5.006000| -new_constant||| -new_ctype||5.006000| -new_he||| -new_logop||| -new_numeric||5.006000| -new_stackinfo||5.005000| -new_version||5.009000| -new_warnings_bitfield||| -next_symbol||| -nextargv||| -nextchar||| -ninstr|||n -no_bareword_allowed||| -no_fh_allowed||| -no_op||| -noperl_die|||vn -not_a_number||| -not_incrementable||| -nothreadhook||5.008000| -nuke_stacks||| -num_overflow|||n -oopsAV||| -oopsHV||| -op_append_elem||5.013006| -op_append_list||5.013006| -op_clear||| -op_contextualize||5.013006| -op_convert_list||5.021006| -op_dump||5.006000| -op_free||| -op_integerize||| -op_linklist||5.013006| -op_lvalue_flags||| -op_lvalue||5.013007| -op_null||5.007002| -op_parent||5.021002|n -op_prepend_elem||5.013006| -op_refcnt_dec||| -op_refcnt_inc||| -op_refcnt_lock||5.009002| -op_refcnt_unlock||5.009002| -op_relocate_sv||| -op_scope||5.013007| -op_sibling_splice||5.021002|n -op_std_init||| -op_unscope||| -open_script||| -openn_cleanup||| -openn_setup||| -opmethod_stash||| -opslab_force_free||| -opslab_free_nopad||| -opslab_free||| -pMY_CXT_|5.007003||p -pMY_CXT|5.007003||p -pTHX_|5.006000||p -pTHX|5.006000||p -packWARN|5.007003||p -pack_cat||5.007003| -pack_rec||| -package_version||| -package||| -packlist||5.008001| -pad_add_anon||5.008001| -pad_add_name_pvn||5.015001| -pad_add_name_pvs||5.015001| -pad_add_name_pv||5.015001| -pad_add_name_sv||5.015001| -pad_add_weakref||| -pad_alloc_name||| -pad_alloc||| -pad_block_start||| -pad_check_dup||| -pad_compname_type||5.009003| -pad_findlex||| -pad_findmy_pvn||5.015001| -pad_findmy_pvs||5.015001| -pad_findmy_pv||5.015001| -pad_findmy_sv||5.015001| -pad_fixup_inner_anons||| -pad_free||| -pad_leavemy||| -pad_new||5.008001| -pad_push||| -pad_reset||| -pad_setsv||| -pad_sv||| -pad_swipe||| -pad_tidy||5.008001| -padlist_dup||| -padlist_store||| -padname_dup||| -padname_free||| -padnamelist_dup||| -padnamelist_fetch||5.021007|n -padnamelist_free||| -padnamelist_store||5.021007| -parse_arithexpr||5.013008| -parse_barestmt||5.013007| -parse_block||5.013007| -parse_body||| -parse_fullexpr||5.013008| -parse_fullstmt||5.013005| -parse_gv_stash_name||| -parse_ident||| -parse_label||5.013007| -parse_listexpr||5.013008| -parse_lparen_question_flags||| -parse_stmtseq||5.013006| -parse_subsignature||| -parse_termexpr||5.013008| -parse_unicode_opts||| -parser_dup||| -parser_free_nexttoke_ops||| -parser_free||| -path_is_searchable|||n -peep||| -pending_ident||| -perl_alloc_using|||n -perl_alloc|||n -perl_clone_using|||n -perl_clone|||n -perl_construct|||n -perl_destruct||5.007003|n -perl_free|||n -perl_parse||5.006000|n -perl_run|||n -pidgone||| -pm_description||| -pmop_dump||5.006000| -pmruntime||| -pmtrans||| -pop_scope||| -populate_ANYOF_from_invlist||| -populate_isa|||v -pregcomp||5.009005| -pregexec||| -pregfree2||5.011000| -pregfree||| -prescan_version||5.011004| -printbuf||| -printf_nocontext|||vn -process_special_blocks||| -ptr_hash|||n -ptr_table_clear||5.009005| -ptr_table_fetch||5.009005| -ptr_table_find|||n -ptr_table_free||5.009005| -ptr_table_new||5.009005| -ptr_table_split||5.009005| -ptr_table_store||5.009005| -push_scope||| -put_charclass_bitmap_innards||| -put_code_point||| -put_range||| -pv_display|5.006000||p -pv_escape|5.009004||p -pv_pretty|5.009004||p -pv_uni_display||5.007003| -qerror||| -qsortsvu||| -quadmath_format_needed|||n -quadmath_format_single|||n -re_compile||5.009005| -re_croak2||| -re_dup_guts||| -re_intuit_start||5.019001| -re_intuit_string||5.006000| -re_op_compile||| -realloc||5.007002|n -reentrant_free||5.021008| -reentrant_init||5.021008| -reentrant_retry||5.021008|vn -reentrant_size||5.021008| -ref_array_or_hash||| -refcounted_he_chain_2hv||| -refcounted_he_fetch_pvn||| -refcounted_he_fetch_pvs||| -refcounted_he_fetch_pv||| -refcounted_he_fetch_sv||| -refcounted_he_free||| -refcounted_he_inc||| -refcounted_he_new_pvn||| -refcounted_he_new_pvs||| -refcounted_he_new_pv||| -refcounted_he_new_sv||| -refcounted_he_value||| -refkids||| -refto||| -ref||5.021008| -reg2Lanode||| -reg_check_named_buff_matched|||n -reg_named_buff_all||5.009005| -reg_named_buff_exists||5.009005| -reg_named_buff_fetch||5.009005| -reg_named_buff_firstkey||5.009005| -reg_named_buff_iter||| -reg_named_buff_nextkey||5.009005| -reg_named_buff_scalar||5.009005| -reg_named_buff||| -reg_node||| -reg_numbered_buff_fetch||| -reg_numbered_buff_length||| -reg_numbered_buff_store||| -reg_qr_package||| -reg_recode||| -reg_scan_name||| -reg_skipcomment|||n -reg_temp_copy||| -reganode||| -regatom||| -regbranch||| -regclass_swash||5.009004| -regclass||| -regcppop||| -regcppush||| -regcurly|||n -regdump_extflags||| -regdump_intflags||| -regdump||5.005000| -regdupe_internal||| -regexec_flags||5.005000| -regfree_internal||5.009005| -reghop3|||n -reghop4|||n -reghopmaybe3|||n -reginclass||| -reginitcolors||5.006000| -reginsert||| -regmatch||| -regnext||5.005000| -regnode_guts||| -regpatws|||n -regpiece||| -regpposixcc||| -regprop||| -regrepeat||| -regtail_study||| -regtail||| -regtry||| -reg||| -repeatcpy|||n -report_evil_fh||| -report_redefined_cv||| -report_uninit||| -report_wrongway_fh||| -require_pv||5.006000| -require_tie_mod||| -restore_magic||| -rninstr|||n -rpeep||| -rsignal_restore||| -rsignal_save||| -rsignal_state||5.004000| -rsignal||5.004000| -run_body||| -run_user_filter||| -runops_debug||5.005000| -runops_standard||5.005000| -rv2cv_op_cv||5.013006| -rvpv_dup||| -rxres_free||| -rxres_restore||| -rxres_save||| -safesyscalloc||5.006000|n -safesysfree||5.006000|n -safesysmalloc||5.006000|n -safesysrealloc||5.006000|n -same_dirent||| -save_I16||5.004000| -save_I32||| -save_I8||5.006000| -save_adelete||5.011000| -save_aelem_flags||5.011000| -save_aelem||5.004050| -save_aliased_sv||| -save_alloc||5.006000| -save_aptr||| -save_ary||| -save_bool||5.008001| -save_clearsv||| -save_delete||| -save_destructor_x||5.006000| -save_destructor||5.006000| -save_freeop||| -save_freepv||| -save_freesv||| -save_generic_pvref||5.006001| -save_generic_svref||5.005030| -save_gp||5.004000| -save_hash||| -save_hdelete||5.011000| -save_hek_flags|||n -save_helem_flags||5.011000| -save_helem||5.004050| -save_hints||5.010001| -save_hptr||| -save_int||| -save_item||| -save_iv||5.005000| -save_lines||| -save_list||| -save_long||| -save_magic_flags||| -save_mortalizesv||5.007001| -save_nogv||| -save_op||5.005000| -save_padsv_and_mortalize||5.010001| -save_pptr||| -save_pushi32ptr||5.010001| -save_pushptri32ptr||| -save_pushptrptr||5.010001| -save_pushptr||5.010001| -save_re_context||5.006000| -save_scalar_at||| -save_scalar||| -save_set_svflags||5.009000| -save_shared_pvref||5.007003| -save_sptr||| -save_strlen||| -save_svref||| -save_vptr||5.006000| -savepvn||| -savepvs||5.009003| -savepv||| -savesharedpvn||5.009005| -savesharedpvs||5.013006| -savesharedpv||5.007003| -savesharedsvpv||5.013006| -savestack_grow_cnt||5.008001| -savestack_grow||| -savesvpv||5.009002| -sawparens||| -scalar_mod_type|||n -scalarboolean||| -scalarkids||| -scalarseq||| -scalarvoid||| -scalar||| -scan_bin||5.006000| -scan_commit||| -scan_const||| -scan_formline||| -scan_heredoc||| -scan_hex||| -scan_ident||| -scan_inputsymbol||| -scan_num||5.007001| -scan_oct||| -scan_pat||| -scan_str||| -scan_subst||| -scan_trans||| -scan_version||5.009001| -scan_vstring||5.009005| -scan_word||| -search_const||| -seed||5.008001| -sequence_num||| -set_ANYOF_arg||| -set_caret_X||| -set_context||5.006000|n -set_numeric_local||5.006000| -set_numeric_radix||5.006000| -set_numeric_standard||5.006000| -set_padlist|||n -setdefout||| -share_hek_flags||| -share_hek||5.004000| -should_warn_nl|||n -si_dup||| -sighandler|||n -simplify_sort||| -skipspace_flags||| -softref2xv||| -sortcv_stacked||| -sortcv_xsub||| -sortcv||| -sortsv_flags||5.009003| -sortsv||5.007003| -space_join_names_mortal||| -ss_dup||| -ssc_add_range||| -ssc_and||| -ssc_anything||| -ssc_clear_locale|||n -ssc_cp_and||| -ssc_finalize||| -ssc_init||| -ssc_intersection||| -ssc_is_anything|||n -ssc_is_cp_posixl_init|||n -ssc_or||| -ssc_union||| -stack_grow||| -start_glob||| -start_subparse||5.004000| -stdize_locale||| -strEQ||| -strGE||| -strGT||| -strLE||| -strLT||| -strNE||| -str_to_version||5.006000| -strip_return||| -strnEQ||| -strnNE||| -study_chunk||| -sub_crush_depth||| -sublex_done||| -sublex_push||| -sublex_start||| -sv_2bool_flags||5.013006| -sv_2bool||| -sv_2cv||| -sv_2io||| -sv_2iuv_common||| -sv_2iuv_non_preserve||| -sv_2iv_flags||5.009001| -sv_2iv||| -sv_2mortal||| -sv_2num||| -sv_2nv_flags||5.013001| -sv_2pv_flags|5.007002||p -sv_2pv_nolen|5.006000||p -sv_2pvbyte_nolen|5.006000||p -sv_2pvbyte|5.006000||p -sv_2pvutf8_nolen||5.006000| -sv_2pvutf8||5.006000| -sv_2pv||| -sv_2uv_flags||5.009001| -sv_2uv|5.004000||p -sv_add_arena||| -sv_add_backref||| -sv_backoff|||n -sv_bless||| -sv_buf_to_ro||| -sv_buf_to_rw||| -sv_cat_decode||5.008001| -sv_catpv_flags||5.013006| -sv_catpv_mg|5.004050||p -sv_catpv_nomg||5.013006| -sv_catpvf_mg_nocontext|||pvn -sv_catpvf_mg|5.006000|5.004000|pv -sv_catpvf_nocontext|||vn -sv_catpvf||5.004000|v -sv_catpvn_flags||5.007002| -sv_catpvn_mg|5.004050||p -sv_catpvn_nomg|5.007002||p -sv_catpvn||| -sv_catpvs_flags||5.013006| -sv_catpvs_mg||5.013006| -sv_catpvs_nomg||5.013006| -sv_catpvs|5.009003||p -sv_catpv||| -sv_catsv_flags||5.007002| -sv_catsv_mg|5.004050||p -sv_catsv_nomg|5.007002||p -sv_catsv||| -sv_chop||| -sv_clean_all||| -sv_clean_objs||| -sv_clear||| -sv_cmp_flags||5.013006| -sv_cmp_locale_flags||5.013006| -sv_cmp_locale||5.004000| -sv_cmp||| -sv_collxfrm_flags||5.013006| -sv_collxfrm||| -sv_copypv_flags||5.017002| -sv_copypv_nomg||5.017002| -sv_copypv||| -sv_dec_nomg||5.013002| -sv_dec||| -sv_del_backref||| -sv_derived_from_pvn||5.015004| -sv_derived_from_pv||5.015004| -sv_derived_from_sv||5.015004| -sv_derived_from||5.004000| -sv_destroyable||5.010000| -sv_display||| -sv_does_pvn||5.015004| -sv_does_pv||5.015004| -sv_does_sv||5.015004| -sv_does||5.009004| -sv_dump||| -sv_dup_common||| -sv_dup_inc_multiple||| -sv_dup_inc||| -sv_dup||| -sv_eq_flags||5.013006| -sv_eq||| -sv_exp_grow||| -sv_force_normal_flags||5.007001| -sv_force_normal||5.006000| -sv_free2||| -sv_free_arenas||| -sv_free||| -sv_get_backrefs||5.021008|n -sv_gets||5.003070| -sv_grow||| -sv_i_ncmp||| -sv_inc_nomg||5.013002| -sv_inc||| -sv_insert_flags||5.010001| -sv_insert||| -sv_isa||| -sv_isobject||| -sv_iv||5.005000| -sv_kill_backrefs||| -sv_len_utf8_nomg||| -sv_len_utf8||5.006000| -sv_len||| -sv_magic_portable|5.021008|5.004000|p -sv_magicext_mglob||| -sv_magicext||5.007003| -sv_magic||| -sv_mortalcopy_flags||| -sv_mortalcopy||| -sv_ncmp||| -sv_newmortal||| -sv_newref||| -sv_nolocking||5.007003| -sv_nosharing||5.007003| -sv_nounlocking||| -sv_nv||5.005000| -sv_only_taint_gmagic|||n -sv_or_pv_pos_u2b||| -sv_peek||5.005000| -sv_pos_b2u_flags||5.019003| -sv_pos_b2u_midway||| -sv_pos_b2u||5.006000| -sv_pos_u2b_cached||| -sv_pos_u2b_flags||5.011005| -sv_pos_u2b_forwards|||n -sv_pos_u2b_midway|||n -sv_pos_u2b||5.006000| -sv_pvbyten_force||5.006000| -sv_pvbyten||5.006000| -sv_pvbyte||5.006000| -sv_pvn_force_flags|5.007002||p -sv_pvn_force||| -sv_pvn_nomg|5.007003|5.005000|p -sv_pvn||5.005000| -sv_pvutf8n_force||5.006000| -sv_pvutf8n||5.006000| -sv_pvutf8||5.006000| -sv_pv||5.006000| -sv_recode_to_utf8||5.007003| -sv_reftype||| -sv_ref||| -sv_release_COW||| -sv_replace||| -sv_report_used||| -sv_resetpvn||| -sv_reset||| -sv_rvweaken||5.006000| -sv_sethek||| -sv_setiv_mg|5.004050||p -sv_setiv||| -sv_setnv_mg|5.006000||p -sv_setnv||| -sv_setpv_mg|5.004050||p -sv_setpvf_mg_nocontext|||pvn -sv_setpvf_mg|5.006000|5.004000|pv -sv_setpvf_nocontext|||vn -sv_setpvf||5.004000|v -sv_setpviv_mg||5.008001| -sv_setpviv||5.008001| -sv_setpvn_mg|5.004050||p -sv_setpvn||| -sv_setpvs_mg||5.013006| -sv_setpvs|5.009004||p -sv_setpv||| -sv_setref_iv||| -sv_setref_nv||| -sv_setref_pvn||| -sv_setref_pvs||5.021008| -sv_setref_pv||| -sv_setref_uv||5.007001| -sv_setsv_cow||| -sv_setsv_flags||5.007002| -sv_setsv_mg|5.004050||p -sv_setsv_nomg|5.007002||p -sv_setsv||| -sv_setuv_mg|5.004050||p -sv_setuv|5.004000||p -sv_tainted||5.004000| -sv_taint||5.004000| -sv_true||5.005000| -sv_unglob||| -sv_uni_display||5.007003| -sv_unmagicext|5.013008||p -sv_unmagic||| -sv_unref_flags||5.007001| -sv_unref||| -sv_untaint||5.004000| -sv_upgrade||| -sv_usepvn_flags||5.009004| -sv_usepvn_mg|5.004050||p -sv_usepvn||| -sv_utf8_decode||5.006000| -sv_utf8_downgrade||5.006000| -sv_utf8_encode||5.006000| -sv_utf8_upgrade_flags_grow||5.011000| -sv_utf8_upgrade_flags||5.007002| -sv_utf8_upgrade_nomg||5.007002| -sv_utf8_upgrade||5.007001| -sv_uv|5.005000||p -sv_vcatpvf_mg|5.006000|5.004000|p -sv_vcatpvfn_flags||5.017002| -sv_vcatpvfn||5.004000| -sv_vcatpvf|5.006000|5.004000|p -sv_vsetpvf_mg|5.006000|5.004000|p -sv_vsetpvfn||5.004000| -sv_vsetpvf|5.006000|5.004000|p -svtype||| -swallow_bom||| -swash_fetch||5.007002| -swash_init||5.006000| -swash_scan_list_line||| -swatch_get||| -sync_locale||5.021004| -sys_init3||5.010000|n -sys_init||5.010000|n -sys_intern_clear||| -sys_intern_dup||| -sys_intern_init||| -sys_term||5.010000|n -taint_env||| -taint_proper||| -tied_method|||v -tmps_grow_p||| -toFOLD_uni||5.007003| -toFOLD_utf8||5.019001| -toFOLD||5.019001| -toLOWER_L1||5.019001| -toLOWER_LC||5.004000| -toLOWER_uni||5.007003| -toLOWER_utf8||5.015007| -toLOWER||| -toTITLE_uni||5.007003| -toTITLE_utf8||5.015007| -toTITLE||5.019001| -toUPPER_uni||5.007003| -toUPPER_utf8||5.015007| -toUPPER||| -to_byte_substr||| -to_lower_latin1|||n -to_uni_fold||5.007003| -to_uni_lower_lc||5.006000| -to_uni_lower||5.007003| -to_uni_title_lc||5.006000| -to_uni_title||5.007003| -to_uni_upper_lc||5.006000| -to_uni_upper||5.007003| -to_utf8_case||5.007003| -to_utf8_fold||5.015007| -to_utf8_lower||5.015007| -to_utf8_substr||| -to_utf8_title||5.015007| -to_utf8_upper||5.015007| -tokenize_use||| -tokeq||| -tokereport||| -too_few_arguments_pv||| -too_many_arguments_pv||| -translate_substr_offsets|||n -try_amagic_bin||| -try_amagic_un||| -uiv_2buf|||n -unlnk||| -unpack_rec||| -unpack_str||5.007003| -unpackstring||5.008001| -unreferenced_to_tmp_stack||| -unshare_hek_or_pvn||| -unshare_hek||| -unsharepvn||5.003070| -unwind_handler_stack||| -update_debugger_info||| -upg_version||5.009005| -usage||| -utf16_textfilter||| -utf16_to_utf8_reversed||5.006001| -utf16_to_utf8||5.006001| -utf8_distance||5.006000| -utf8_hop||5.006000|n -utf8_length||5.007001| -utf8_mg_len_cache_update||| -utf8_mg_pos_cache_update||| -utf8_to_bytes||5.006001| -utf8_to_uvchr_buf||5.015009| -utf8_to_uvchr||5.007001| -utf8_to_uvuni_buf||5.015009| -utf8_to_uvuni||5.007001| -utf8n_to_uvchr||5.007001| -utf8n_to_uvuni||5.007001| -utilize||| -uvchr_to_utf8_flags||5.007003| -uvchr_to_utf8||5.007001| -uvoffuni_to_utf8_flags||5.019004| -uvuni_to_utf8_flags||5.007003| -uvuni_to_utf8||5.007001| -valid_utf8_to_uvchr||5.015009| -valid_utf8_to_uvuni||5.015009| -validate_proto||| -validate_suid||| -varname||| -vcmp||5.009000| -vcroak||5.006000| -vdeb||5.007003| -vform||5.006000| -visit||| -vivify_defelem||| -vivify_ref||| -vload_module|5.006000||p -vmess||5.006000| -vnewSVpvf|5.006000|5.004000|p -vnormal||5.009002| -vnumify||5.009000| -vstringify||5.009000| -vverify||5.009003| -vwarner||5.006000| -vwarn||5.006000| -wait4pid||| -warn_nocontext|||vn -warn_sv||5.013001| -warner_nocontext|||vn -warner|5.006000|5.004000|pv -warn|||v -was_lvalue_sub||| -watch||| -whichsig_pvn||5.015004| -whichsig_pv||5.015004| -whichsig_sv||5.015004| -whichsig||| -win32_croak_not_implemented|||n -with_queued_errors||| -wrap_op_checker||5.015008| -write_to_stderr||| -xs_boot_epilog||| -xs_handshake|||vn -xs_version_bootcheck||| -yyerror_pvn||| -yyerror_pv||| -yyerror||| -yylex||| -yyparse||| -yyunlex||| -yywarn||| -); - -if (exists $opt{'list-unsupported'}) { - my $f; - for $f (sort { lc $a cmp lc $b } keys %API) { - next unless $API{$f}{todo}; - print "$f ", '.'x(40-length($f)), " ", format_version($API{$f}{todo}), "\n"; - } - exit 0; -} - -# Scan for possible replacement candidates - -my(%replace, %need, %hints, %warnings, %depends); -my $replace = 0; -my($hint, $define, $function); - -sub find_api -{ - my $code = shift; - $code =~ s{ - / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*) - | "[^"\\]*(?:\\.[^"\\]*)*" - | '[^'\\]*(?:\\.[^'\\]*)*' }{}egsx; - grep { exists $API{$_} } $code =~ /(\w+)/mg; -} - -while () { - if ($hint) { - my $h = $hint->[0] eq 'Hint' ? \%hints : \%warnings; - if (m{^\s*\*\s(.*?)\s*$}) { - for (@{$hint->[1]}) { - $h->{$_} ||= ''; # suppress warning with older perls - $h->{$_} .= "$1\n"; - } - } - else { undef $hint } - } - - $hint = [$1, [split /,?\s+/, $2]] - if m{^\s*$rccs\s+(Hint|Warning):\s+(\w+(?:,?\s+\w+)*)\s*$}; - - if ($define) { - if ($define->[1] =~ /\\$/) { - $define->[1] .= $_; - } - else { - if (exists $API{$define->[0]} && $define->[1] !~ /^DPPP_\(/) { - my @n = find_api($define->[1]); - push @{$depends{$define->[0]}}, @n if @n - } - undef $define; - } - } - - $define = [$1, $2] if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(.*)}; - - if ($function) { - if (/^}/) { - if (exists $API{$function->[0]}) { - my @n = find_api($function->[1]); - push @{$depends{$function->[0]}}, @n if @n - } - undef $function; - } - else { - $function->[1] .= $_; - } - } - - $function = [$1, ''] if m{^DPPP_\(my_(\w+)\)}; - - $replace = $1 if m{^\s*$rccs\s+Replace:\s+(\d+)\s+$rcce\s*$}; - $replace{$2} = $1 if $replace and m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+)}; - $replace{$2} = $1 if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+).*$rccs\s+Replace\s+$rcce}; - $replace{$1} = $2 if m{^\s*$rccs\s+Replace (\w+) with (\w+)\s+$rcce\s*$}; - - if (m{^\s*$rccs\s+(\w+(\s*,\s*\w+)*)\s+depends\s+on\s+(\w+(\s*,\s*\w+)*)\s+$rcce\s*$}) { - my @deps = map { s/\s+//g; $_ } split /,/, $3; - my $d; - for $d (map { s/\s+//g; $_ } split /,/, $1) { - push @{$depends{$d}}, @deps; - } - } - - $need{$1} = 1 if m{^#if\s+defined\(NEED_(\w+)(?:_GLOBAL)?\)}; -} - -for (values %depends) { - my %s; - $_ = [sort grep !$s{$_}++, @$_]; -} - -if (exists $opt{'api-info'}) { - my $f; - my $count = 0; - my $match = $opt{'api-info'} =~ m!^/(.*)/$! ? $1 : "^\Q$opt{'api-info'}\E\$"; - for $f (sort { lc $a cmp lc $b } keys %API) { - next unless $f =~ /$match/; - print "\n=== $f ===\n\n"; - my $info = 0; - if ($API{$f}{base} || $API{$f}{todo}) { - my $base = format_version($API{$f}{base} || $API{$f}{todo}); - print "Supported at least starting from perl-$base.\n"; - $info++; - } - if ($API{$f}{provided}) { - my $todo = $API{$f}{todo} ? format_version($API{$f}{todo}) : "5.003"; - print "Support by $ppport provided back to perl-$todo.\n"; - print "Support needs to be explicitly requested by NEED_$f.\n" if exists $need{$f}; - print "Depends on: ", join(', ', @{$depends{$f}}), ".\n" if exists $depends{$f}; - print "\n$hints{$f}" if exists $hints{$f}; - print "\nWARNING:\n$warnings{$f}" if exists $warnings{$f}; - $info++; - } - print "No portability information available.\n" unless $info; - $count++; - } - $count or print "Found no API matching '$opt{'api-info'}'."; - print "\n"; - exit 0; -} - -if (exists $opt{'list-provided'}) { - my $f; - for $f (sort { lc $a cmp lc $b } keys %API) { - next unless $API{$f}{provided}; - my @flags; - push @flags, 'explicit' if exists $need{$f}; - push @flags, 'depend' if exists $depends{$f}; - push @flags, 'hint' if exists $hints{$f}; - push @flags, 'warning' if exists $warnings{$f}; - my $flags = @flags ? ' ['.join(', ', @flags).']' : ''; - print "$f$flags\n"; - } - exit 0; -} - -my @files; -my @srcext = qw( .xs .c .h .cc .cpp -c.inc -xs.inc ); -my $srcext = join '|', map { quotemeta $_ } @srcext; - -if (@ARGV) { - my %seen; - for (@ARGV) { - if (-e) { - if (-f) { - push @files, $_ unless $seen{$_}++; - } - else { warn "'$_' is not a file.\n" } - } - else { - my @new = grep { -f } glob $_ - or warn "'$_' does not exist.\n"; - push @files, grep { !$seen{$_}++ } @new; - } - } -} -else { - eval { - require File::Find; - File::Find::find(sub { - $File::Find::name =~ /($srcext)$/i - and push @files, $File::Find::name; - }, '.'); - }; - if ($@) { - @files = map { glob "*$_" } @srcext; - } -} - -if (!@ARGV || $opt{filter}) { - my(@in, @out); - my %xsc = map { /(.*)\.xs$/ ? ("$1.c" => 1, "$1.cc" => 1) : () } @files; - for (@files) { - my $out = exists $xsc{$_} || /\b\Q$ppport\E$/i || !/($srcext)$/i; - push @{ $out ? \@out : \@in }, $_; - } - if (@ARGV && @out) { - warning("Skipping the following files (use --nofilter to avoid this):\n| ", join "\n| ", @out); - } - @files = @in; -} - -die "No input files given!\n" unless @files; - -my(%files, %global, %revreplace); -%revreplace = reverse %replace; -my $filename; -my $patch_opened = 0; - -for $filename (@files) { - unless (open IN, "<$filename") { - warn "Unable to read from $filename: $!\n"; - next; - } - - info("Scanning $filename ..."); - - my $c = do { local $/; }; - close IN; - - my %file = (orig => $c, changes => 0); - - # Temporarily remove C/XS comments and strings from the code - my @ccom; - - $c =~ s{ - ( ^$HS*\#$HS*include\b[^\r\n]+\b(?:\Q$ppport\E|XSUB\.h)\b[^\r\n]* - | ^$HS*\#$HS*(?:define|elif|if(?:def)?)\b[^\r\n]* ) - | ( ^$HS*\#[^\r\n]* - | "[^"\\]*(?:\\.[^"\\]*)*" - | '[^'\\]*(?:\\.[^'\\]*)*' - | / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]* ) ) - }{ defined $2 and push @ccom, $2; - defined $1 ? $1 : "$ccs$#ccom$cce" }mgsex; - - $file{ccom} = \@ccom; - $file{code} = $c; - $file{has_inc_ppport} = $c =~ /^$HS*#$HS*include[^\r\n]+\b\Q$ppport\E\b/m; - - my $func; - - for $func (keys %API) { - my $match = $func; - $match .= "|$revreplace{$func}" if exists $revreplace{$func}; - if ($c =~ /\b(?:Perl_)?($match)\b/) { - $file{uses_replace}{$1}++ if exists $revreplace{$func} && $1 eq $revreplace{$func}; - $file{uses_Perl}{$func}++ if $c =~ /\bPerl_$func\b/; - if (exists $API{$func}{provided}) { - $file{uses_provided}{$func}++; - if (!exists $API{$func}{base} || $API{$func}{base} > $opt{'compat-version'}) { - $file{uses}{$func}++; - my @deps = rec_depend($func); - if (@deps) { - $file{uses_deps}{$func} = \@deps; - for (@deps) { - $file{uses}{$_} = 0 unless exists $file{uses}{$_}; - } - } - for ($func, @deps) { - $file{needs}{$_} = 'static' if exists $need{$_}; - } - } - } - if (exists $API{$func}{todo} && $API{$func}{todo} > $opt{'compat-version'}) { - if ($c =~ /\b$func\b/) { - $file{uses_todo}{$func}++; - } - } - } - } - - while ($c =~ /^$HS*#$HS*define$HS+(NEED_(\w+?)(_GLOBAL)?)\b/mg) { - if (exists $need{$2}) { - $file{defined $3 ? 'needed_global' : 'needed_static'}{$2}++; - } - else { warning("Possibly wrong #define $1 in $filename") } - } - - for (qw(uses needs uses_todo needed_global needed_static)) { - for $func (keys %{$file{$_}}) { - push @{$global{$_}{$func}}, $filename; - } - } - - $files{$filename} = \%file; -} - -# Globally resolve NEED_'s -my $need; -for $need (keys %{$global{needs}}) { - if (@{$global{needs}{$need}} > 1) { - my @targets = @{$global{needs}{$need}}; - my @t = grep $files{$_}{needed_global}{$need}, @targets; - @targets = @t if @t; - @t = grep /\.xs$/i, @targets; - @targets = @t if @t; - my $target = shift @targets; - $files{$target}{needs}{$need} = 'global'; - for (@{$global{needs}{$need}}) { - $files{$_}{needs}{$need} = 'extern' if $_ ne $target; - } - } -} - -for $filename (@files) { - exists $files{$filename} or next; - - info("=== Analyzing $filename ==="); - - my %file = %{$files{$filename}}; - my $func; - my $c = $file{code}; - my $warnings = 0; - - for $func (sort keys %{$file{uses_Perl}}) { - if ($API{$func}{varargs}) { - unless ($API{$func}{nothxarg}) { - my $changes = ($c =~ s{\b(Perl_$func\s*\(\s*)(?!aTHX_?)(\)|[^\s)]*\))} - { $1 . ($2 eq ')' ? 'aTHX' : 'aTHX_ ') . $2 }ge); - if ($changes) { - warning("Doesn't pass interpreter argument aTHX to Perl_$func"); - $file{changes} += $changes; - } - } - } - else { - warning("Uses Perl_$func instead of $func"); - $file{changes} += ($c =~ s{\bPerl_$func(\s*)\((\s*aTHX_?)?\s*} - {$func$1(}g); - } - } - - for $func (sort keys %{$file{uses_replace}}) { - warning("Uses $func instead of $replace{$func}"); - $file{changes} += ($c =~ s/\b$func\b/$replace{$func}/g); - } - - for $func (sort keys %{$file{uses_provided}}) { - if ($file{uses}{$func}) { - if (exists $file{uses_deps}{$func}) { - diag("Uses $func, which depends on ", join(', ', @{$file{uses_deps}{$func}})); - } - else { - diag("Uses $func"); - } - } - $warnings += hint($func); - } - - unless ($opt{quiet}) { - for $func (sort keys %{$file{uses_todo}}) { - print "*** WARNING: Uses $func, which may not be portable below perl ", - format_version($API{$func}{todo}), ", even with '$ppport'\n"; - $warnings++; - } - } - - for $func (sort keys %{$file{needed_static}}) { - my $message = ''; - if (not exists $file{uses}{$func}) { - $message = "No need to define NEED_$func if $func is never used"; - } - elsif (exists $file{needs}{$func} && $file{needs}{$func} ne 'static') { - $message = "No need to define NEED_$func when already needed globally"; - } - if ($message) { - diag($message); - $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_$func\b.*$LF//mg); - } - } - - for $func (sort keys %{$file{needed_global}}) { - my $message = ''; - if (not exists $global{uses}{$func}) { - $message = "No need to define NEED_${func}_GLOBAL if $func is never used"; - } - elsif (exists $file{needs}{$func}) { - if ($file{needs}{$func} eq 'extern') { - $message = "No need to define NEED_${func}_GLOBAL when already needed globally"; - } - elsif ($file{needs}{$func} eq 'static') { - $message = "No need to define NEED_${func}_GLOBAL when only used in this file"; - } - } - if ($message) { - diag($message); - $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_${func}_GLOBAL\b.*$LF//mg); - } - } - - $file{needs_inc_ppport} = keys %{$file{uses}}; - - if ($file{needs_inc_ppport}) { - my $pp = ''; - - for $func (sort keys %{$file{needs}}) { - my $type = $file{needs}{$func}; - next if $type eq 'extern'; - my $suffix = $type eq 'global' ? '_GLOBAL' : ''; - unless (exists $file{"needed_$type"}{$func}) { - if ($type eq 'global') { - diag("Files [@{$global{needs}{$func}}] need $func, adding global request"); - } - else { - diag("File needs $func, adding static request"); - } - $pp .= "#define NEED_$func$suffix\n"; - } - } - - if ($pp && ($c =~ s/^(?=$HS*#$HS*define$HS+NEED_\w+)/$pp/m)) { - $pp = ''; - $file{changes}++; - } - - unless ($file{has_inc_ppport}) { - diag("Needs to include '$ppport'"); - $pp .= qq(#include "$ppport"\n) - } - - if ($pp) { - $file{changes} += ($c =~ s/^($HS*#$HS*define$HS+NEED_\w+.*?)^/$1$pp/ms) - || ($c =~ s/^(?=$HS*#$HS*include.*\Q$ppport\E)/$pp/m) - || ($c =~ s/^($HS*#$HS*include.*XSUB.*\s*?)^/$1$pp/m) - || ($c =~ s/^/$pp/); - } - } - else { - if ($file{has_inc_ppport}) { - diag("No need to include '$ppport'"); - $file{changes} += ($c =~ s/^$HS*?#$HS*include.*\Q$ppport\E.*?$LF//m); - } - } - - # put back in our C comments - my $ix; - my $cppc = 0; - my @ccom = @{$file{ccom}}; - for $ix (0 .. $#ccom) { - if (!$opt{cplusplus} && $ccom[$ix] =~ s!^//!!) { - $cppc++; - $file{changes} += $c =~ s/$rccs$ix$rcce/$ccs$ccom[$ix] $cce/; - } - else { - $c =~ s/$rccs$ix$rcce/$ccom[$ix]/; - } - } - - if ($cppc) { - my $s = $cppc != 1 ? 's' : ''; - warning("Uses $cppc C++ style comment$s, which is not portable"); - } - - my $s = $warnings != 1 ? 's' : ''; - my $warn = $warnings ? " ($warnings warning$s)" : ''; - info("Analysis completed$warn"); - - if ($file{changes}) { - if (exists $opt{copy}) { - my $newfile = "$filename$opt{copy}"; - if (-e $newfile) { - error("'$newfile' already exists, refusing to write copy of '$filename'"); - } - else { - local *F; - if (open F, ">$newfile") { - info("Writing copy of '$filename' with changes to '$newfile'"); - print F $c; - close F; - } - else { - error("Cannot open '$newfile' for writing: $!"); - } - } - } - elsif (exists $opt{patch} || $opt{changes}) { - if (exists $opt{patch}) { - unless ($patch_opened) { - if (open PATCH, ">$opt{patch}") { - $patch_opened = 1; - } - else { - error("Cannot open '$opt{patch}' for writing: $!"); - delete $opt{patch}; - $opt{changes} = 1; - goto fallback; - } - } - mydiff(\*PATCH, $filename, $c); - } - else { -fallback: - info("Suggested changes:"); - mydiff(\*STDOUT, $filename, $c); - } - } - else { - my $s = $file{changes} == 1 ? '' : 's'; - info("$file{changes} potentially required change$s detected"); - } - } - else { - info("Looks good"); - } -} - -close PATCH if $patch_opened; - -exit 0; - - -sub try_use { eval "use @_;"; return $@ eq '' } - -sub mydiff -{ - local *F = shift; - my($file, $str) = @_; - my $diff; - - if (exists $opt{diff}) { - $diff = run_diff($opt{diff}, $file, $str); - } - - if (!defined $diff and try_use('Text::Diff')) { - $diff = Text::Diff::diff($file, \$str, { STYLE => 'Unified' }); - $diff = <
$tmp") { - print F $str; - close F; - - if (open F, "$prog $file $tmp |") { - while () { - s/\Q$tmp\E/$file.patched/; - $diff .= $_; - } - close F; - unlink $tmp; - return $diff; - } - - unlink $tmp; - } - else { - error("Cannot open '$tmp' for writing: $!"); - } - - return undef; -} - -sub rec_depend -{ - my($func, $seen) = @_; - return () unless exists $depends{$func}; - $seen = {%{$seen||{}}}; - return () if $seen->{$func}++; - my %s; - grep !$s{$_}++, map { ($_, rec_depend($_, $seen)) } @{$depends{$func}}; -} - -sub parse_version -{ - my $ver = shift; - - if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) { - return ($1, $2, $3); - } - elsif ($ver !~ /^\d+\.[\d_]+$/) { - die "cannot parse version '$ver'\n"; - } - - $ver =~ s/_//g; - $ver =~ s/$/000000/; - - my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/; - - $v = int $v; - $s = int $s; - - if ($r < 5 || ($r == 5 && $v < 6)) { - if ($s % 10) { - die "cannot parse version '$ver'\n"; - } - } - - return ($r, $v, $s); -} - -sub format_version -{ - my $ver = shift; - - $ver =~ s/$/000000/; - my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/; - - $v = int $v; - $s = int $s; - - if ($r < 5 || ($r == 5 && $v < 6)) { - if ($s % 10) { - die "invalid version '$ver'\n"; - } - $s /= 10; - - $ver = sprintf "%d.%03d", $r, $v; - $s > 0 and $ver .= sprintf "_%02d", $s; - - return $ver; - } - - return sprintf "%d.%d.%d", $r, $v, $s; -} - -sub info -{ - $opt{quiet} and return; - print @_, "\n"; -} - -sub diag -{ - $opt{quiet} and return; - $opt{diag} and print @_, "\n"; -} - -sub warning -{ - $opt{quiet} and return; - print "*** ", @_, "\n"; -} - -sub error -{ - print "*** ERROR: ", @_, "\n"; -} - -my %given_hints; -my %given_warnings; -sub hint -{ - $opt{quiet} and return; - my $func = shift; - my $rv = 0; - if (exists $warnings{$func} && !$given_warnings{$func}++) { - my $warn = $warnings{$func}; - $warn =~ s!^!*** !mg; - print "*** WARNING: $func\n", $warn; - $rv++; - } - if ($opt{hints} && exists $hints{$func} && !$given_hints{$func}++) { - my $hint = $hints{$func}; - $hint =~ s/^/ /mg; - print " --- hint for $func ---\n", $hint; - } - $rv; -} - -sub usage -{ - my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms; - my %M = ( 'I' => '*' ); - $usage =~ s/^\s*perl\s+\S+/$^X $0/; - $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g; - - print < }; - my($copy) = $self =~ /^=head\d\s+COPYRIGHT\s*^(.*?)^=\w+/ms; - $copy =~ s/^(?=\S+)/ /gms; - $self =~ s/^$HS+Do NOT edit.*?(?=^-)/$copy/ms; - $self =~ s/^SKIP.*(?=^__DATA__)/SKIP -if (\@ARGV && \$ARGV[0] eq '--unstrip') { - eval { require Devel::PPPort }; - \$@ and die "Cannot require Devel::PPPort, please install.\\n"; - if (eval \$Devel::PPPort::VERSION < $VERSION) { - die "$0 was originally generated with Devel::PPPort $VERSION.\\n" - . "Your Devel::PPPort is only version \$Devel::PPPort::VERSION.\\n" - . "Please install a newer version, or --unstrip will not work.\\n"; - } - Devel::PPPort::WriteFile(\$0); - exit 0; -} -print <$0" or die "cannot strip $0: $!\n"; - print OUT "$pl$c\n"; - - exit 0; -} - -__DATA__ -*/ - -#ifndef _P_P_PORTABILITY_H_ -#define _P_P_PORTABILITY_H_ - -#ifndef DPPP_NAMESPACE -# define DPPP_NAMESPACE DPPP_ -#endif - -#define DPPP_CAT2(x,y) CAT2(x,y) -#define DPPP_(name) DPPP_CAT2(DPPP_NAMESPACE, name) - -#ifndef PERL_REVISION -# if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION)) -# define PERL_PATCHLEVEL_H_IMPLICIT -# include -# endif -# if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL))) -# include -# endif -# ifndef PERL_REVISION -# define PERL_REVISION (5) - /* Replace: 1 */ -# define PERL_VERSION PATCHLEVEL -# define PERL_SUBVERSION SUBVERSION - /* Replace PERL_PATCHLEVEL with PERL_VERSION */ - /* Replace: 0 */ -# endif -#endif - -#define _dpppDEC2BCD(dec) ((((dec)/100)<<8)|((((dec)%100)/10)<<4)|((dec)%10)) -#define PERL_BCDVERSION ((_dpppDEC2BCD(PERL_REVISION)<<24)|(_dpppDEC2BCD(PERL_VERSION)<<12)|_dpppDEC2BCD(PERL_SUBVERSION)) - -/* It is very unlikely that anyone will try to use this with Perl 6 - (or greater), but who knows. - */ -#if PERL_REVISION != 5 -# error ppport.h only works with Perl version 5 -#endif /* PERL_REVISION != 5 */ -#ifndef dTHR -# define dTHR dNOOP -#endif -#ifndef dTHX -# define dTHX dNOOP -#endif - -#ifndef dTHXa -# define dTHXa(x) dNOOP -#endif -#ifndef pTHX -# define pTHX void -#endif - -#ifndef pTHX_ -# define pTHX_ -#endif - -#ifndef aTHX -# define aTHX -#endif - -#ifndef aTHX_ -# define aTHX_ -#endif - -#if (PERL_BCDVERSION < 0x5006000) -# ifdef USE_THREADS -# define aTHXR thr -# define aTHXR_ thr, -# else -# define aTHXR -# define aTHXR_ -# endif -# define dTHXR dTHR -#else -# define aTHXR aTHX -# define aTHXR_ aTHX_ -# define dTHXR dTHX -#endif -#ifndef dTHXoa -# define dTHXoa(x) dTHXa(x) -#endif - -#ifdef I_LIMITS -# include -#endif - -#ifndef PERL_UCHAR_MIN -# define PERL_UCHAR_MIN ((unsigned char)0) -#endif - -#ifndef PERL_UCHAR_MAX -# ifdef UCHAR_MAX -# define PERL_UCHAR_MAX ((unsigned char)UCHAR_MAX) -# else -# ifdef MAXUCHAR -# define PERL_UCHAR_MAX ((unsigned char)MAXUCHAR) -# else -# define PERL_UCHAR_MAX ((unsigned char)~(unsigned)0) -# endif -# endif -#endif - -#ifndef PERL_USHORT_MIN -# define PERL_USHORT_MIN ((unsigned short)0) -#endif - -#ifndef PERL_USHORT_MAX -# ifdef USHORT_MAX -# define PERL_USHORT_MAX ((unsigned short)USHORT_MAX) -# else -# ifdef MAXUSHORT -# define PERL_USHORT_MAX ((unsigned short)MAXUSHORT) -# else -# ifdef USHRT_MAX -# define PERL_USHORT_MAX ((unsigned short)USHRT_MAX) -# else -# define PERL_USHORT_MAX ((unsigned short)~(unsigned)0) -# endif -# endif -# endif -#endif - -#ifndef PERL_SHORT_MAX -# ifdef SHORT_MAX -# define PERL_SHORT_MAX ((short)SHORT_MAX) -# else -# ifdef MAXSHORT /* Often used in */ -# define PERL_SHORT_MAX ((short)MAXSHORT) -# else -# ifdef SHRT_MAX -# define PERL_SHORT_MAX ((short)SHRT_MAX) -# else -# define PERL_SHORT_MAX ((short) (PERL_USHORT_MAX >> 1)) -# endif -# endif -# endif -#endif - -#ifndef PERL_SHORT_MIN -# ifdef SHORT_MIN -# define PERL_SHORT_MIN ((short)SHORT_MIN) -# else -# ifdef MINSHORT -# define PERL_SHORT_MIN ((short)MINSHORT) -# else -# ifdef SHRT_MIN -# define PERL_SHORT_MIN ((short)SHRT_MIN) -# else -# define PERL_SHORT_MIN (-PERL_SHORT_MAX - ((3 & -1) == 3)) -# endif -# endif -# endif -#endif - -#ifndef PERL_UINT_MAX -# ifdef UINT_MAX -# define PERL_UINT_MAX ((unsigned int)UINT_MAX) -# else -# ifdef MAXUINT -# define PERL_UINT_MAX ((unsigned int)MAXUINT) -# else -# define PERL_UINT_MAX (~(unsigned int)0) -# endif -# endif -#endif - -#ifndef PERL_UINT_MIN -# define PERL_UINT_MIN ((unsigned int)0) -#endif - -#ifndef PERL_INT_MAX -# ifdef INT_MAX -# define PERL_INT_MAX ((int)INT_MAX) -# else -# ifdef MAXINT /* Often used in */ -# define PERL_INT_MAX ((int)MAXINT) -# else -# define PERL_INT_MAX ((int)(PERL_UINT_MAX >> 1)) -# endif -# endif -#endif - -#ifndef PERL_INT_MIN -# ifdef INT_MIN -# define PERL_INT_MIN ((int)INT_MIN) -# else -# ifdef MININT -# define PERL_INT_MIN ((int)MININT) -# else -# define PERL_INT_MIN (-PERL_INT_MAX - ((3 & -1) == 3)) -# endif -# endif -#endif - -#ifndef PERL_ULONG_MAX -# ifdef ULONG_MAX -# define PERL_ULONG_MAX ((unsigned long)ULONG_MAX) -# else -# ifdef MAXULONG -# define PERL_ULONG_MAX ((unsigned long)MAXULONG) -# else -# define PERL_ULONG_MAX (~(unsigned long)0) -# endif -# endif -#endif - -#ifndef PERL_ULONG_MIN -# define PERL_ULONG_MIN ((unsigned long)0L) -#endif - -#ifndef PERL_LONG_MAX -# ifdef LONG_MAX -# define PERL_LONG_MAX ((long)LONG_MAX) -# else -# ifdef MAXLONG -# define PERL_LONG_MAX ((long)MAXLONG) -# else -# define PERL_LONG_MAX ((long) (PERL_ULONG_MAX >> 1)) -# endif -# endif -#endif - -#ifndef PERL_LONG_MIN -# ifdef LONG_MIN -# define PERL_LONG_MIN ((long)LONG_MIN) -# else -# ifdef MINLONG -# define PERL_LONG_MIN ((long)MINLONG) -# else -# define PERL_LONG_MIN (-PERL_LONG_MAX - ((3 & -1) == 3)) -# endif -# endif -#endif - -#if defined(HAS_QUAD) && (defined(convex) || defined(uts)) -# ifndef PERL_UQUAD_MAX -# ifdef ULONGLONG_MAX -# define PERL_UQUAD_MAX ((unsigned long long)ULONGLONG_MAX) -# else -# ifdef MAXULONGLONG -# define PERL_UQUAD_MAX ((unsigned long long)MAXULONGLONG) -# else -# define PERL_UQUAD_MAX (~(unsigned long long)0) -# endif -# endif -# endif - -# ifndef PERL_UQUAD_MIN -# define PERL_UQUAD_MIN ((unsigned long long)0L) -# endif - -# ifndef PERL_QUAD_MAX -# ifdef LONGLONG_MAX -# define PERL_QUAD_MAX ((long long)LONGLONG_MAX) -# else -# ifdef MAXLONGLONG -# define PERL_QUAD_MAX ((long long)MAXLONGLONG) -# else -# define PERL_QUAD_MAX ((long long) (PERL_UQUAD_MAX >> 1)) -# endif -# endif -# endif - -# ifndef PERL_QUAD_MIN -# ifdef LONGLONG_MIN -# define PERL_QUAD_MIN ((long long)LONGLONG_MIN) -# else -# ifdef MINLONGLONG -# define PERL_QUAD_MIN ((long long)MINLONGLONG) -# else -# define PERL_QUAD_MIN (-PERL_QUAD_MAX - ((3 & -1) == 3)) -# endif -# endif -# endif -#endif - -/* This is based on code from 5.003 perl.h */ -#ifdef HAS_QUAD -# ifdef cray -#ifndef IVTYPE -# define IVTYPE int -#endif - -#ifndef IV_MIN -# define IV_MIN PERL_INT_MIN -#endif - -#ifndef IV_MAX -# define IV_MAX PERL_INT_MAX -#endif - -#ifndef UV_MIN -# define UV_MIN PERL_UINT_MIN -#endif - -#ifndef UV_MAX -# define UV_MAX PERL_UINT_MAX -#endif - -# ifdef INTSIZE -#ifndef IVSIZE -# define IVSIZE INTSIZE -#endif - -# endif -# else -# if defined(convex) || defined(uts) -#ifndef IVTYPE -# define IVTYPE long long -#endif - -#ifndef IV_MIN -# define IV_MIN PERL_QUAD_MIN -#endif - -#ifndef IV_MAX -# define IV_MAX PERL_QUAD_MAX -#endif - -#ifndef UV_MIN -# define UV_MIN PERL_UQUAD_MIN -#endif - -#ifndef UV_MAX -# define UV_MAX PERL_UQUAD_MAX -#endif - -# ifdef LONGLONGSIZE -#ifndef IVSIZE -# define IVSIZE LONGLONGSIZE -#endif - -# endif -# else -#ifndef IVTYPE -# define IVTYPE long -#endif - -#ifndef IV_MIN -# define IV_MIN PERL_LONG_MIN -#endif - -#ifndef IV_MAX -# define IV_MAX PERL_LONG_MAX -#endif - -#ifndef UV_MIN -# define UV_MIN PERL_ULONG_MIN -#endif - -#ifndef UV_MAX -# define UV_MAX PERL_ULONG_MAX -#endif - -# ifdef LONGSIZE -#ifndef IVSIZE -# define IVSIZE LONGSIZE -#endif - -# endif -# endif -# endif -#ifndef IVSIZE -# define IVSIZE 8 -#endif - -#ifndef LONGSIZE -# define LONGSIZE 8 -#endif - -#ifndef PERL_QUAD_MIN -# define PERL_QUAD_MIN IV_MIN -#endif - -#ifndef PERL_QUAD_MAX -# define PERL_QUAD_MAX IV_MAX -#endif - -#ifndef PERL_UQUAD_MIN -# define PERL_UQUAD_MIN UV_MIN -#endif - -#ifndef PERL_UQUAD_MAX -# define PERL_UQUAD_MAX UV_MAX -#endif - -#else -#ifndef IVTYPE -# define IVTYPE long -#endif - -#ifndef LONGSIZE -# define LONGSIZE 4 -#endif - -#ifndef IV_MIN -# define IV_MIN PERL_LONG_MIN -#endif - -#ifndef IV_MAX -# define IV_MAX PERL_LONG_MAX -#endif - -#ifndef UV_MIN -# define UV_MIN PERL_ULONG_MIN -#endif - -#ifndef UV_MAX -# define UV_MAX PERL_ULONG_MAX -#endif - -#endif - -#ifndef IVSIZE -# ifdef LONGSIZE -# define IVSIZE LONGSIZE -# else -# define IVSIZE 4 /* A bold guess, but the best we can make. */ -# endif -#endif -#ifndef UVTYPE -# define UVTYPE unsigned IVTYPE -#endif - -#ifndef UVSIZE -# define UVSIZE IVSIZE -#endif -#ifndef sv_setuv -# define sv_setuv(sv, uv) \ - STMT_START { \ - UV TeMpUv = uv; \ - if (TeMpUv <= IV_MAX) \ - sv_setiv(sv, TeMpUv); \ - else \ - sv_setnv(sv, (double)TeMpUv); \ - } STMT_END -#endif -#ifndef newSVuv -# define newSVuv(uv) ((uv) <= IV_MAX ? newSViv((IV)uv) : newSVnv((NV)uv)) -#endif -#ifndef sv_2uv -# define sv_2uv(sv) ((PL_Sv = (sv)), (UV) (SvNOK(PL_Sv) ? SvNV(PL_Sv) : sv_2nv(PL_Sv))) -#endif - -#ifndef SvUVX -# define SvUVX(sv) ((UV)SvIVX(sv)) -#endif - -#ifndef SvUVXx -# define SvUVXx(sv) SvUVX(sv) -#endif - -#ifndef SvUV -# define SvUV(sv) (SvIOK(sv) ? SvUVX(sv) : sv_2uv(sv)) -#endif - -#ifndef SvUVx -# define SvUVx(sv) ((PL_Sv = (sv)), SvUV(PL_Sv)) -#endif - -/* Hint: sv_uv - * Always use the SvUVx() macro instead of sv_uv(). - */ -#ifndef sv_uv -# define sv_uv(sv) SvUVx(sv) -#endif - -#if !defined(SvUOK) && defined(SvIOK_UV) -# define SvUOK(sv) SvIOK_UV(sv) -#endif -#ifndef XST_mUV -# define XST_mUV(i,v) (ST(i) = sv_2mortal(newSVuv(v)) ) -#endif - -#ifndef XSRETURN_UV -# define XSRETURN_UV(v) STMT_START { XST_mUV(0,v); XSRETURN(1); } STMT_END -#endif -#ifndef PUSHu -# define PUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG; } STMT_END -#endif - -#ifndef XPUSHu -# define XPUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); XPUSHTARG; } STMT_END -#endif - -#ifdef HAS_MEMCMP -#ifndef memNE -# define memNE(s1,s2,l) (memcmp(s1,s2,l)) -#endif - -#ifndef memEQ -# define memEQ(s1,s2,l) (!memcmp(s1,s2,l)) -#endif - -#else -#ifndef memNE -# define memNE(s1,s2,l) (bcmp(s1,s2,l)) -#endif - -#ifndef memEQ -# define memEQ(s1,s2,l) (!bcmp(s1,s2,l)) -#endif - -#endif -#ifndef memEQs -# define memEQs(s1, l, s2) \ - (sizeof(s2)-1 == l && memEQ(s1, (s2 ""), (sizeof(s2)-1))) -#endif - -#ifndef memNEs -# define memNEs(s1, l, s2) !memEQs(s1, l, s2) -#endif -#ifndef MoveD -# define MoveD(s,d,n,t) memmove((char*)(d),(char*)(s), (n) * sizeof(t)) -#endif - -#ifndef CopyD -# define CopyD(s,d,n,t) memcpy((char*)(d),(char*)(s), (n) * sizeof(t)) -#endif - -#ifdef HAS_MEMSET -#ifndef ZeroD -# define ZeroD(d,n,t) memzero((char*)(d), (n) * sizeof(t)) -#endif - -#else -#ifndef ZeroD -# define ZeroD(d,n,t) ((void)memzero((char*)(d), (n) * sizeof(t)), d) -#endif - -#endif -#ifndef PoisonWith -# define PoisonWith(d,n,t,b) (void)memset((char*)(d), (U8)(b), (n) * sizeof(t)) -#endif - -#ifndef PoisonNew -# define PoisonNew(d,n,t) PoisonWith(d,n,t,0xAB) -#endif - -#ifndef PoisonFree -# define PoisonFree(d,n,t) PoisonWith(d,n,t,0xEF) -#endif - -#ifndef Poison -# define Poison(d,n,t) PoisonFree(d,n,t) -#endif -#ifndef Newx -# define Newx(v,n,t) New(0,v,n,t) -#endif - -#ifndef Newxc -# define Newxc(v,n,t,c) Newc(0,v,n,t,c) -#endif - -#ifndef Newxz -# define Newxz(v,n,t) Newz(0,v,n,t) -#endif - -#ifndef PERL_UNUSED_DECL -# ifdef HASATTRIBUTE -# if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER) -# define PERL_UNUSED_DECL -# else -# define PERL_UNUSED_DECL __attribute__((unused)) -# endif -# else -# define PERL_UNUSED_DECL -# endif -#endif - -#ifndef PERL_UNUSED_ARG -# if defined(lint) && defined(S_SPLINT_S) /* www.splint.org */ -# include -# define PERL_UNUSED_ARG(x) NOTE(ARGUNUSED(x)) -# else -# define PERL_UNUSED_ARG(x) ((void)x) -# endif -#endif - -#ifndef PERL_UNUSED_VAR -# define PERL_UNUSED_VAR(x) ((void)x) -#endif - -#ifndef PERL_UNUSED_CONTEXT -# ifdef USE_ITHREADS -# define PERL_UNUSED_CONTEXT PERL_UNUSED_ARG(my_perl) -# else -# define PERL_UNUSED_CONTEXT -# endif -#endif -#ifndef NOOP -# define NOOP /*EMPTY*/(void)0 -#endif - -#ifndef dNOOP -# define dNOOP extern int /*@unused@*/ Perl___notused PERL_UNUSED_DECL -#endif - -#ifndef NVTYPE -# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) -# define NVTYPE long double -# else -# define NVTYPE double -# endif -typedef NVTYPE NV; -#endif - -#ifndef INT2PTR -# if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE) -# define PTRV UV -# define INT2PTR(any,d) (any)(d) -# else -# if PTRSIZE == LONGSIZE -# define PTRV unsigned long -# else -# define PTRV unsigned -# endif -# define INT2PTR(any,d) (any)(PTRV)(d) -# endif -#endif - -#ifndef PTR2ul -# if PTRSIZE == LONGSIZE -# define PTR2ul(p) (unsigned long)(p) -# else -# define PTR2ul(p) INT2PTR(unsigned long,p) -# endif -#endif -#ifndef PTR2nat -# define PTR2nat(p) (PTRV)(p) -#endif - -#ifndef NUM2PTR -# define NUM2PTR(any,d) (any)PTR2nat(d) -#endif - -#ifndef PTR2IV -# define PTR2IV(p) INT2PTR(IV,p) -#endif - -#ifndef PTR2UV -# define PTR2UV(p) INT2PTR(UV,p) -#endif - -#ifndef PTR2NV -# define PTR2NV(p) NUM2PTR(NV,p) -#endif - -#undef START_EXTERN_C -#undef END_EXTERN_C -#undef EXTERN_C -#ifdef __cplusplus -# define START_EXTERN_C extern "C" { -# define END_EXTERN_C } -# define EXTERN_C extern "C" -#else -# define START_EXTERN_C -# define END_EXTERN_C -# define EXTERN_C extern -#endif - -#if defined(PERL_GCC_PEDANTIC) -# ifndef PERL_GCC_BRACE_GROUPS_FORBIDDEN -# define PERL_GCC_BRACE_GROUPS_FORBIDDEN -# endif -#endif - -#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) && !defined(__cplusplus) -# ifndef PERL_USE_GCC_BRACE_GROUPS -# define PERL_USE_GCC_BRACE_GROUPS -# endif -#endif - -#undef STMT_START -#undef STMT_END -#ifdef PERL_USE_GCC_BRACE_GROUPS -# define STMT_START (void)( /* gcc supports ``({ STATEMENTS; })'' */ -# define STMT_END ) -#else -# if defined(VOIDFLAGS) && (VOIDFLAGS) && (defined(sun) || defined(__sun__)) && !defined(__GNUC__) -# define STMT_START if (1) -# define STMT_END else (void)0 -# else -# define STMT_START do -# define STMT_END while (0) -# endif -#endif -#ifndef boolSV -# define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no) -#endif - -/* DEFSV appears first in 5.004_56 */ -#ifndef DEFSV -# define DEFSV GvSV(PL_defgv) -#endif - -#ifndef SAVE_DEFSV -# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv)) -#endif - -#ifndef DEFSV_set -# define DEFSV_set(sv) (DEFSV = (sv)) -#endif - -/* Older perls (<=5.003) lack AvFILLp */ -#ifndef AvFILLp -# define AvFILLp AvFILL -#endif -#ifndef ERRSV -# define ERRSV get_sv("@",FALSE) -#endif - -/* Hint: gv_stashpvn - * This function's backport doesn't support the length parameter, but - * rather ignores it. Portability can only be ensured if the length - * parameter is used for speed reasons, but the length can always be - * correctly computed from the string argument. - */ -#ifndef gv_stashpvn -# define gv_stashpvn(str,len,create) gv_stashpv(str,create) -#endif - -/* Replace: 1 */ -#ifndef get_cv -# define get_cv perl_get_cv -#endif - -#ifndef get_sv -# define get_sv perl_get_sv -#endif - -#ifndef get_av -# define get_av perl_get_av -#endif - -#ifndef get_hv -# define get_hv perl_get_hv -#endif - -/* Replace: 0 */ -#ifndef dUNDERBAR -# define dUNDERBAR dNOOP -#endif - -#ifndef UNDERBAR -# define UNDERBAR DEFSV -#endif -#ifndef dAX -# define dAX I32 ax = MARK - PL_stack_base + 1 -#endif - -#ifndef dITEMS -# define dITEMS I32 items = SP - MARK -#endif -#ifndef dXSTARG -# define dXSTARG SV * targ = sv_newmortal() -#endif -#ifndef dAXMARK -# define dAXMARK I32 ax = POPMARK; \ - register SV ** const mark = PL_stack_base + ax++ -#endif -#ifndef XSprePUSH -# define XSprePUSH (sp = PL_stack_base + ax - 1) -#endif - -#if (PERL_BCDVERSION < 0x5005000) -# undef XSRETURN -# define XSRETURN(off) \ - STMT_START { \ - PL_stack_sp = PL_stack_base + ax + ((off) - 1); \ - return; \ - } STMT_END -#endif -#ifndef XSPROTO -# define XSPROTO(name) void name(pTHX_ CV* cv) -#endif - -#ifndef SVfARG -# define SVfARG(p) ((void*)(p)) -#endif -#ifndef PERL_ABS -# define PERL_ABS(x) ((x) < 0 ? -(x) : (x)) -#endif -#ifndef dVAR -# define dVAR dNOOP -#endif -#ifndef SVf -# define SVf "_" -#endif -#ifndef UTF8_MAXBYTES -# define UTF8_MAXBYTES UTF8_MAXLEN -#endif -#ifndef CPERLscope -# define CPERLscope(x) x -#endif -#ifndef PERL_HASH -# define PERL_HASH(hash,str,len) \ - STMT_START { \ - const char *s_PeRlHaSh = str; \ - I32 i_PeRlHaSh = len; \ - U32 hash_PeRlHaSh = 0; \ - while (i_PeRlHaSh--) \ - hash_PeRlHaSh = hash_PeRlHaSh * 33 + *s_PeRlHaSh++; \ - (hash) = hash_PeRlHaSh; \ - } STMT_END -#endif - -#ifndef PERLIO_FUNCS_DECL -# ifdef PERLIO_FUNCS_CONST -# define PERLIO_FUNCS_DECL(funcs) const PerlIO_funcs funcs -# define PERLIO_FUNCS_CAST(funcs) (PerlIO_funcs*)(funcs) -# else -# define PERLIO_FUNCS_DECL(funcs) PerlIO_funcs funcs -# define PERLIO_FUNCS_CAST(funcs) (funcs) -# endif -#endif - -/* provide these typedefs for older perls */ -#if (PERL_BCDVERSION < 0x5009003) - -# ifdef ARGSproto -typedef OP* (CPERLscope(*Perl_ppaddr_t))(ARGSproto); -# else -typedef OP* (CPERLscope(*Perl_ppaddr_t))(pTHX); -# endif - -typedef OP* (CPERLscope(*Perl_check_t)) (pTHX_ OP*); - -#endif -#ifndef isPSXSPC -# define isPSXSPC(c) (isSPACE(c) || (c) == '\v') -#endif - -#ifndef isBLANK -# define isBLANK(c) ((c) == ' ' || (c) == '\t') -#endif - -#ifdef EBCDIC -#ifndef isALNUMC -# define isALNUMC(c) isalnum(c) -#endif - -#ifndef isASCII -# define isASCII(c) isascii(c) -#endif - -#ifndef isCNTRL -# define isCNTRL(c) iscntrl(c) -#endif - -#ifndef isGRAPH -# define isGRAPH(c) isgraph(c) -#endif - -#ifndef isPRINT -# define isPRINT(c) isprint(c) -#endif - -#ifndef isPUNCT -# define isPUNCT(c) ispunct(c) -#endif - -#ifndef isXDIGIT -# define isXDIGIT(c) isxdigit(c) -#endif - -#else -# if (PERL_BCDVERSION < 0x5010000) -/* Hint: isPRINT - * The implementation in older perl versions includes all of the - * isSPACE() characters, which is wrong. The version provided by - * Devel::PPPort always overrides a present buggy version. - */ -# undef isPRINT -# endif - -#ifdef HAS_QUAD -# ifdef U64TYPE -# define WIDEST_UTYPE U64TYPE -# else -# define WIDEST_UTYPE Quad_t -# endif -#else -# define WIDEST_UTYPE U32 -#endif -#ifndef isALNUMC -# define isALNUMC(c) (isALPHA(c) || isDIGIT(c)) -#endif - -#ifndef isASCII -# define isASCII(c) ((WIDEST_UTYPE) (c) <= 127) -#endif - -#ifndef isCNTRL -# define isCNTRL(c) ((WIDEST_UTYPE) (c) < ' ' || (c) == 127) -#endif - -#ifndef isGRAPH -# define isGRAPH(c) (isALNUM(c) || isPUNCT(c)) -#endif - -#ifndef isPRINT -# define isPRINT(c) (((c) >= 32 && (c) < 127)) -#endif - -#ifndef isPUNCT -# define isPUNCT(c) (((c) >= 33 && (c) <= 47) || ((c) >= 58 && (c) <= 64) || ((c) >= 91 && (c) <= 96) || ((c) >= 123 && (c) <= 126)) -#endif - -#ifndef isXDIGIT -# define isXDIGIT(c) (isDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#endif - -#endif - -/* Until we figure out how to support this in older perls... */ -#if (PERL_BCDVERSION >= 0x5008000) -#ifndef HeUTF8 -# define HeUTF8(he) ((HeKLEN(he) == HEf_SVKEY) ? \ - SvUTF8(HeKEY_sv(he)) : \ - (U32)HeKUTF8(he)) -#endif - -#endif - -#ifndef PERL_SIGNALS_UNSAFE_FLAG - -#define PERL_SIGNALS_UNSAFE_FLAG 0x0001 - -#if (PERL_BCDVERSION < 0x5008000) -# define D_PPP_PERL_SIGNALS_INIT PERL_SIGNALS_UNSAFE_FLAG -#else -# define D_PPP_PERL_SIGNALS_INIT 0 -#endif - -#if defined(NEED_PL_signals) -static U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT; -#elif defined(NEED_PL_signals_GLOBAL) -U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT; -#else -extern U32 DPPP_(my_PL_signals); -#endif -#define PL_signals DPPP_(my_PL_signals) - -#endif - -/* Hint: PL_ppaddr - * Calling an op via PL_ppaddr requires passing a context argument - * for threaded builds. Since the context argument is different for - * 5.005 perls, you can use aTHXR (supplied by ppport.h), which will - * automatically be defined as the correct argument. - */ - -#if (PERL_BCDVERSION <= 0x5005005) -/* Replace: 1 */ -# define PL_ppaddr ppaddr -# define PL_no_modify no_modify -/* Replace: 0 */ -#endif - -#if (PERL_BCDVERSION <= 0x5004005) -/* Replace: 1 */ -# define PL_DBsignal DBsignal -# define PL_DBsingle DBsingle -# define PL_DBsub DBsub -# define PL_DBtrace DBtrace -# define PL_Sv Sv -# define PL_bufend bufend -# define PL_bufptr bufptr -# define PL_compiling compiling -# define PL_copline copline -# define PL_curcop curcop -# define PL_curstash curstash -# define PL_debstash debstash -# define PL_defgv defgv -# define PL_diehook diehook -# define PL_dirty dirty -# define PL_dowarn dowarn -# define PL_errgv errgv -# define PL_error_count error_count -# define PL_expect expect -# define PL_hexdigit hexdigit -# define PL_hints hints -# define PL_in_my in_my -# define PL_laststatval laststatval -# define PL_lex_state lex_state -# define PL_lex_stuff lex_stuff -# define PL_linestr linestr -# define PL_na na -# define PL_perl_destruct_level perl_destruct_level -# define PL_perldb perldb -# define PL_rsfp_filters rsfp_filters -# define PL_rsfp rsfp -# define PL_stack_base stack_base -# define PL_stack_sp stack_sp -# define PL_statcache statcache -# define PL_stdingv stdingv -# define PL_sv_arenaroot sv_arenaroot -# define PL_sv_no sv_no -# define PL_sv_undef sv_undef -# define PL_sv_yes sv_yes -# define PL_tainted tainted -# define PL_tainting tainting -# define PL_tokenbuf tokenbuf -/* Replace: 0 */ -#endif - -/* Warning: PL_parser - * For perl versions earlier than 5.9.5, this is an always - * non-NULL dummy. Also, it cannot be dereferenced. Don't - * use it if you can avoid is and unless you absolutely know - * what you're doing. - * If you always check that PL_parser is non-NULL, you can - * define DPPP_PL_parser_NO_DUMMY to avoid the creation of - * a dummy parser structure. - */ - -#if (PERL_BCDVERSION >= 0x5009005) -# ifdef DPPP_PL_parser_NO_DUMMY -# define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \ - (croak("panic: PL_parser == NULL in %s:%d", \ - __FILE__, __LINE__), (yy_parser *) NULL))->var) -# else -# ifdef DPPP_PL_parser_NO_DUMMY_WARNING -# define D_PPP_parser_dummy_warning(var) -# else -# define D_PPP_parser_dummy_warning(var) \ - warn("warning: dummy PL_" #var " used in %s:%d", __FILE__, __LINE__), -# endif -# define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \ - (D_PPP_parser_dummy_warning(var) &DPPP_(dummy_PL_parser)))->var) -#if defined(NEED_PL_parser) -static yy_parser DPPP_(dummy_PL_parser); -#elif defined(NEED_PL_parser_GLOBAL) -yy_parser DPPP_(dummy_PL_parser); -#else -extern yy_parser DPPP_(dummy_PL_parser); -#endif - -# endif - -/* PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf depends on PL_parser */ -/* Warning: PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf - * Do not use this variable unless you know exactly what you're - * doint. It is internal to the perl parser and may change or even - * be removed in the future. As of perl 5.9.5, you have to check - * for (PL_parser != NULL) for this variable to have any effect. - * An always non-NULL PL_parser dummy is provided for earlier - * perl versions. - * If PL_parser is NULL when you try to access this variable, a - * dummy is being accessed instead and a warning is issued unless - * you define DPPP_PL_parser_NO_DUMMY_WARNING. - * If DPPP_PL_parser_NO_DUMMY is defined, the code trying to access - * this variable will croak with a panic message. - */ - -# define PL_expect D_PPP_my_PL_parser_var(expect) -# define PL_copline D_PPP_my_PL_parser_var(copline) -# define PL_rsfp D_PPP_my_PL_parser_var(rsfp) -# define PL_rsfp_filters D_PPP_my_PL_parser_var(rsfp_filters) -# define PL_linestr D_PPP_my_PL_parser_var(linestr) -# define PL_bufptr D_PPP_my_PL_parser_var(bufptr) -# define PL_bufend D_PPP_my_PL_parser_var(bufend) -# define PL_lex_state D_PPP_my_PL_parser_var(lex_state) -# define PL_lex_stuff D_PPP_my_PL_parser_var(lex_stuff) -# define PL_tokenbuf D_PPP_my_PL_parser_var(tokenbuf) -# define PL_in_my D_PPP_my_PL_parser_var(in_my) -# define PL_in_my_stash D_PPP_my_PL_parser_var(in_my_stash) -# define PL_error_count D_PPP_my_PL_parser_var(error_count) - - -#else - -/* ensure that PL_parser != NULL and cannot be dereferenced */ -# define PL_parser ((void *) 1) - -#endif -#ifndef mPUSHs -# define mPUSHs(s) PUSHs(sv_2mortal(s)) -#endif - -#ifndef PUSHmortal -# define PUSHmortal PUSHs(sv_newmortal()) -#endif - -#ifndef mPUSHp -# define mPUSHp(p,l) sv_setpvn(PUSHmortal, (p), (l)) -#endif - -#ifndef mPUSHn -# define mPUSHn(n) sv_setnv(PUSHmortal, (NV)(n)) -#endif - -#ifndef mPUSHi -# define mPUSHi(i) sv_setiv(PUSHmortal, (IV)(i)) -#endif - -#ifndef mPUSHu -# define mPUSHu(u) sv_setuv(PUSHmortal, (UV)(u)) -#endif -#ifndef mXPUSHs -# define mXPUSHs(s) XPUSHs(sv_2mortal(s)) -#endif - -#ifndef XPUSHmortal -# define XPUSHmortal XPUSHs(sv_newmortal()) -#endif - -#ifndef mXPUSHp -# define mXPUSHp(p,l) STMT_START { EXTEND(sp,1); sv_setpvn(PUSHmortal, (p), (l)); } STMT_END -#endif - -#ifndef mXPUSHn -# define mXPUSHn(n) STMT_START { EXTEND(sp,1); sv_setnv(PUSHmortal, (NV)(n)); } STMT_END -#endif - -#ifndef mXPUSHi -# define mXPUSHi(i) STMT_START { EXTEND(sp,1); sv_setiv(PUSHmortal, (IV)(i)); } STMT_END -#endif - -#ifndef mXPUSHu -# define mXPUSHu(u) STMT_START { EXTEND(sp,1); sv_setuv(PUSHmortal, (UV)(u)); } STMT_END -#endif - -/* Replace: 1 */ -#ifndef call_sv -# define call_sv perl_call_sv -#endif - -#ifndef call_pv -# define call_pv perl_call_pv -#endif - -#ifndef call_argv -# define call_argv perl_call_argv -#endif - -#ifndef call_method -# define call_method perl_call_method -#endif -#ifndef eval_sv -# define eval_sv perl_eval_sv -#endif - -/* Replace: 0 */ -#ifndef PERL_LOADMOD_DENY -# define PERL_LOADMOD_DENY 0x1 -#endif - -#ifndef PERL_LOADMOD_NOIMPORT -# define PERL_LOADMOD_NOIMPORT 0x2 -#endif - -#ifndef PERL_LOADMOD_IMPORT_OPS -# define PERL_LOADMOD_IMPORT_OPS 0x4 -#endif - -#ifndef G_METHOD -# define G_METHOD 64 -# ifdef call_sv -# undef call_sv -# endif -# if (PERL_BCDVERSION < 0x5006000) -# define call_sv(sv, flags) ((flags) & G_METHOD ? perl_call_method((char *) SvPV_nolen_const(sv), \ - (flags) & ~G_METHOD) : perl_call_sv(sv, flags)) -# else -# define call_sv(sv, flags) ((flags) & G_METHOD ? Perl_call_method(aTHX_ (char *) SvPV_nolen_const(sv), \ - (flags) & ~G_METHOD) : Perl_call_sv(aTHX_ sv, flags)) -# endif -#endif - -/* Replace perl_eval_pv with eval_pv */ - -#ifndef eval_pv -#if defined(NEED_eval_pv) -static SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error); -static -#else -extern SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error); -#endif - -#ifdef eval_pv -# undef eval_pv -#endif -#define eval_pv(a,b) DPPP_(my_eval_pv)(aTHX_ a,b) -#define Perl_eval_pv DPPP_(my_eval_pv) - -#if defined(NEED_eval_pv) || defined(NEED_eval_pv_GLOBAL) - -SV* -DPPP_(my_eval_pv)(char *p, I32 croak_on_error) -{ - dSP; - SV* sv = newSVpv(p, 0); - - PUSHMARK(sp); - eval_sv(sv, G_SCALAR); - SvREFCNT_dec(sv); - - SPAGAIN; - sv = POPs; - PUTBACK; - - if (croak_on_error && SvTRUE(GvSV(errgv))) - croak("%s", SvPVx(GvSV(errgv), na)); - - return sv; -} - -#endif -#endif - -#ifndef vload_module -#if defined(NEED_vload_module) -static void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args); -static -#else -extern void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args); -#endif - -#ifdef vload_module -# undef vload_module -#endif -#define vload_module(a,b,c,d) DPPP_(my_vload_module)(aTHX_ a,b,c,d) -#define Perl_vload_module DPPP_(my_vload_module) - -#if defined(NEED_vload_module) || defined(NEED_vload_module_GLOBAL) - -void -DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args) -{ - dTHR; - dVAR; - OP *veop, *imop; - - OP * const modname = newSVOP(OP_CONST, 0, name); - /* 5.005 has a somewhat hacky force_normal that doesn't croak on - SvREADONLY() if PL_compling is true. Current perls take care in - ck_require() to correctly turn off SvREADONLY before calling - force_normal_flags(). This seems a better fix than fudging PL_compling - */ - SvREADONLY_off(((SVOP*)modname)->op_sv); - modname->op_private |= OPpCONST_BARE; - if (ver) { - veop = newSVOP(OP_CONST, 0, ver); - } - else - veop = NULL; - if (flags & PERL_LOADMOD_NOIMPORT) { - imop = sawparens(newNULLLIST()); - } - else if (flags & PERL_LOADMOD_IMPORT_OPS) { - imop = va_arg(*args, OP*); - } - else { - SV *sv; - imop = NULL; - sv = va_arg(*args, SV*); - while (sv) { - imop = append_elem(OP_LIST, imop, newSVOP(OP_CONST, 0, sv)); - sv = va_arg(*args, SV*); - } - } - { - const line_t ocopline = PL_copline; - COP * const ocurcop = PL_curcop; - const int oexpect = PL_expect; - -#if (PERL_BCDVERSION >= 0x5004000) - utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0), - veop, modname, imop); -#elif (PERL_BCDVERSION > 0x5003000) - utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(), - veop, modname, imop); -#else - utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(), - modname, imop); -#endif - PL_expect = oexpect; - PL_copline = ocopline; - PL_curcop = ocurcop; - } -} - -#endif -#endif - -#ifndef load_module -#if defined(NEED_load_module) -static void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...); -static -#else -extern void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...); -#endif - -#ifdef load_module -# undef load_module -#endif -#define load_module DPPP_(my_load_module) -#define Perl_load_module DPPP_(my_load_module) - -#if defined(NEED_load_module) || defined(NEED_load_module_GLOBAL) - -void -DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...) -{ - va_list args; - va_start(args, ver); - vload_module(flags, name, ver, &args); - va_end(args); -} - -#endif -#endif -#ifndef newRV_inc -# define newRV_inc(sv) newRV(sv) /* Replace */ -#endif - -#ifndef newRV_noinc -#if defined(NEED_newRV_noinc) -static SV * DPPP_(my_newRV_noinc)(SV *sv); -static -#else -extern SV * DPPP_(my_newRV_noinc)(SV *sv); -#endif - -#ifdef newRV_noinc -# undef newRV_noinc -#endif -#define newRV_noinc(a) DPPP_(my_newRV_noinc)(aTHX_ a) -#define Perl_newRV_noinc DPPP_(my_newRV_noinc) - -#if defined(NEED_newRV_noinc) || defined(NEED_newRV_noinc_GLOBAL) -SV * -DPPP_(my_newRV_noinc)(SV *sv) -{ - SV *rv = (SV *)newRV(sv); - SvREFCNT_dec(sv); - return rv; -} -#endif -#endif - -/* Hint: newCONSTSUB - * Returns a CV* as of perl-5.7.1. This return value is not supported - * by Devel::PPPort. - */ - -/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */ -#if (PERL_BCDVERSION < 0x5004063) && (PERL_BCDVERSION != 0x5004005) -#if defined(NEED_newCONSTSUB) -static void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv); -static -#else -extern void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv); -#endif - -#ifdef newCONSTSUB -# undef newCONSTSUB -#endif -#define newCONSTSUB(a,b,c) DPPP_(my_newCONSTSUB)(aTHX_ a,b,c) -#define Perl_newCONSTSUB DPPP_(my_newCONSTSUB) - -#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL) - -/* This is just a trick to avoid a dependency of newCONSTSUB on PL_parser */ -/* (There's no PL_parser in perl < 5.005, so this is completely safe) */ -#define D_PPP_PL_copline PL_copline - -void -DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv) -{ - U32 oldhints = PL_hints; - HV *old_cop_stash = PL_curcop->cop_stash; - HV *old_curstash = PL_curstash; - line_t oldline = PL_curcop->cop_line; - PL_curcop->cop_line = D_PPP_PL_copline; - - PL_hints &= ~HINT_BLOCK_SCOPE; - if (stash) - PL_curstash = PL_curcop->cop_stash = stash; - - newSUB( - -#if (PERL_BCDVERSION < 0x5003022) - start_subparse(), -#elif (PERL_BCDVERSION == 0x5003022) - start_subparse(0), -#else /* 5.003_23 onwards */ - start_subparse(FALSE, 0), -#endif - - newSVOP(OP_CONST, 0, newSVpv((char *) name, 0)), - newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */ - newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv)) - ); - - PL_hints = oldhints; - PL_curcop->cop_stash = old_cop_stash; - PL_curstash = old_curstash; - PL_curcop->cop_line = oldline; -} -#endif -#endif - -/* - * Boilerplate macros for initializing and accessing interpreter-local - * data from C. All statics in extensions should be reworked to use - * this, if you want to make the extension thread-safe. See ext/re/re.xs - * for an example of the use of these macros. - * - * Code that uses these macros is responsible for the following: - * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts" - * 2. Declare a typedef named my_cxt_t that is a structure that contains - * all the data that needs to be interpreter-local. - * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t. - * 4. Use the MY_CXT_INIT macro such that it is called exactly once - * (typically put in the BOOT: section). - * 5. Use the members of the my_cxt_t structure everywhere as - * MY_CXT.member. - * 6. Use the dMY_CXT macro (a declaration) in all the functions that - * access MY_CXT. - */ - -#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \ - defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT) - -#ifndef START_MY_CXT - -/* This must appear in all extensions that define a my_cxt_t structure, - * right after the definition (i.e. at file scope). The non-threads - * case below uses it to declare the data as static. */ -#define START_MY_CXT - -#if (PERL_BCDVERSION < 0x5004068) -/* Fetches the SV that keeps the per-interpreter data. */ -#define dMY_CXT_SV \ - SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE) -#else /* >= perl5.004_68 */ -#define dMY_CXT_SV \ - SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \ - sizeof(MY_CXT_KEY)-1, TRUE) -#endif /* < perl5.004_68 */ - -/* This declaration should be used within all functions that use the - * interpreter-local data. */ -#define dMY_CXT \ - dMY_CXT_SV; \ - my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv)) - -/* Creates and zeroes the per-interpreter data. - * (We allocate my_cxtp in a Perl SV so that it will be released when - * the interpreter goes away.) */ -#define MY_CXT_INIT \ - dMY_CXT_SV; \ - /* newSV() allocates one more than needed */ \ - my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ - Zero(my_cxtp, 1, my_cxt_t); \ - sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) - -/* This macro must be used to access members of the my_cxt_t structure. - * e.g. MYCXT.some_data */ -#define MY_CXT (*my_cxtp) - -/* Judicious use of these macros can reduce the number of times dMY_CXT - * is used. Use is similar to pTHX, aTHX etc. */ -#define pMY_CXT my_cxt_t *my_cxtp -#define pMY_CXT_ pMY_CXT, -#define _pMY_CXT ,pMY_CXT -#define aMY_CXT my_cxtp -#define aMY_CXT_ aMY_CXT, -#define _aMY_CXT ,aMY_CXT - -#endif /* START_MY_CXT */ - -#ifndef MY_CXT_CLONE -/* Clones the per-interpreter data. */ -#define MY_CXT_CLONE \ - dMY_CXT_SV; \ - my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ - Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\ - sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) -#endif - -#else /* single interpreter */ - -#ifndef START_MY_CXT - -#define START_MY_CXT static my_cxt_t my_cxt; -#define dMY_CXT_SV dNOOP -#define dMY_CXT dNOOP -#define MY_CXT_INIT NOOP -#define MY_CXT my_cxt - -#define pMY_CXT void -#define pMY_CXT_ -#define _pMY_CXT -#define aMY_CXT -#define aMY_CXT_ -#define _aMY_CXT - -#endif /* START_MY_CXT */ - -#ifndef MY_CXT_CLONE -#define MY_CXT_CLONE NOOP -#endif - -#endif - -#ifndef IVdf -# if IVSIZE == LONGSIZE -# define IVdf "ld" -# define UVuf "lu" -# define UVof "lo" -# define UVxf "lx" -# define UVXf "lX" -# elif IVSIZE == INTSIZE -# define IVdf "d" -# define UVuf "u" -# define UVof "o" -# define UVxf "x" -# define UVXf "X" -# else -# error "cannot define IV/UV formats" -# endif -#endif - -#ifndef NVef -# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \ - defined(PERL_PRIfldbl) && (PERL_BCDVERSION != 0x5006000) - /* Not very likely, but let's try anyway. */ -# define NVef PERL_PRIeldbl -# define NVff PERL_PRIfldbl -# define NVgf PERL_PRIgldbl -# else -# define NVef "e" -# define NVff "f" -# define NVgf "g" -# endif -#endif - -#ifndef SvREFCNT_inc -# ifdef PERL_USE_GCC_BRACE_GROUPS -# define SvREFCNT_inc(sv) \ - ({ \ - SV * const _sv = (SV*)(sv); \ - if (_sv) \ - (SvREFCNT(_sv))++; \ - _sv; \ - }) -# else -# define SvREFCNT_inc(sv) \ - ((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL) -# endif -#endif - -#ifndef SvREFCNT_inc_simple -# ifdef PERL_USE_GCC_BRACE_GROUPS -# define SvREFCNT_inc_simple(sv) \ - ({ \ - if (sv) \ - (SvREFCNT(sv))++; \ - (SV *)(sv); \ - }) -# else -# define SvREFCNT_inc_simple(sv) \ - ((sv) ? (SvREFCNT(sv)++,(SV*)(sv)) : NULL) -# endif -#endif - -#ifndef SvREFCNT_inc_NN -# ifdef PERL_USE_GCC_BRACE_GROUPS -# define SvREFCNT_inc_NN(sv) \ - ({ \ - SV * const _sv = (SV*)(sv); \ - SvREFCNT(_sv)++; \ - _sv; \ - }) -# else -# define SvREFCNT_inc_NN(sv) \ - (PL_Sv=(SV*)(sv),++(SvREFCNT(PL_Sv)),PL_Sv) -# endif -#endif - -#ifndef SvREFCNT_inc_void -# ifdef PERL_USE_GCC_BRACE_GROUPS -# define SvREFCNT_inc_void(sv) \ - ({ \ - SV * const _sv = (SV*)(sv); \ - if (_sv) \ - (void)(SvREFCNT(_sv)++); \ - }) -# else -# define SvREFCNT_inc_void(sv) \ - (void)((PL_Sv=(SV*)(sv)) ? ++(SvREFCNT(PL_Sv)) : 0) -# endif -#endif -#ifndef SvREFCNT_inc_simple_void -# define SvREFCNT_inc_simple_void(sv) STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END -#endif - -#ifndef SvREFCNT_inc_simple_NN -# define SvREFCNT_inc_simple_NN(sv) (++SvREFCNT(sv), (SV*)(sv)) -#endif - -#ifndef SvREFCNT_inc_void_NN -# define SvREFCNT_inc_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) -#endif - -#ifndef SvREFCNT_inc_simple_void_NN -# define SvREFCNT_inc_simple_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) -#endif - -#ifndef newSV_type - -#if defined(NEED_newSV_type) -static SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); -static -#else -extern SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); -#endif - -#ifdef newSV_type -# undef newSV_type -#endif -#define newSV_type(a) DPPP_(my_newSV_type)(aTHX_ a) -#define Perl_newSV_type DPPP_(my_newSV_type) - -#if defined(NEED_newSV_type) || defined(NEED_newSV_type_GLOBAL) - -SV* -DPPP_(my_newSV_type)(pTHX_ svtype const t) -{ - SV* const sv = newSV(0); - sv_upgrade(sv, t); - return sv; -} - -#endif - -#endif - -#if (PERL_BCDVERSION < 0x5006000) -# define D_PPP_CONSTPV_ARG(x) ((char *) (x)) -#else -# define D_PPP_CONSTPV_ARG(x) (x) -#endif -#ifndef newSVpvn -# define newSVpvn(data,len) ((data) \ - ? ((len) ? newSVpv((data), (len)) : newSVpv("", 0)) \ - : newSV(0)) -#endif -#ifndef newSVpvn_utf8 -# define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0) -#endif -#ifndef SVf_UTF8 -# define SVf_UTF8 0 -#endif - -#ifndef newSVpvn_flags - -#if defined(NEED_newSVpvn_flags) -static SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags); -static -#else -extern SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags); -#endif - -#ifdef newSVpvn_flags -# undef newSVpvn_flags -#endif -#define newSVpvn_flags(a,b,c) DPPP_(my_newSVpvn_flags)(aTHX_ a,b,c) -#define Perl_newSVpvn_flags DPPP_(my_newSVpvn_flags) - -#if defined(NEED_newSVpvn_flags) || defined(NEED_newSVpvn_flags_GLOBAL) - -SV * -DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags) -{ - SV *sv = newSVpvn(D_PPP_CONSTPV_ARG(s), len); - SvFLAGS(sv) |= (flags & SVf_UTF8); - return (flags & SVs_TEMP) ? sv_2mortal(sv) : sv; -} - -#endif - -#endif - -/* Backwards compatibility stuff... :-( */ -#if !defined(NEED_sv_2pv_flags) && defined(NEED_sv_2pv_nolen) -# define NEED_sv_2pv_flags -#endif -#if !defined(NEED_sv_2pv_flags_GLOBAL) && defined(NEED_sv_2pv_nolen_GLOBAL) -# define NEED_sv_2pv_flags_GLOBAL -#endif - -/* Hint: sv_2pv_nolen - * Use the SvPV_nolen() or SvPV_nolen_const() macros instead of sv_2pv_nolen(). - */ -#ifndef sv_2pv_nolen -# define sv_2pv_nolen(sv) SvPV_nolen(sv) -#endif - -#ifdef SvPVbyte - -/* Hint: SvPVbyte - * Does not work in perl-5.6.1, ppport.h implements a version - * borrowed from perl-5.7.3. - */ - -#if (PERL_BCDVERSION < 0x5007000) - -#if defined(NEED_sv_2pvbyte) -static char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp); -static -#else -extern char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp); -#endif - -#ifdef sv_2pvbyte -# undef sv_2pvbyte -#endif -#define sv_2pvbyte(a,b) DPPP_(my_sv_2pvbyte)(aTHX_ a,b) -#define Perl_sv_2pvbyte DPPP_(my_sv_2pvbyte) - -#if defined(NEED_sv_2pvbyte) || defined(NEED_sv_2pvbyte_GLOBAL) - -char * -DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp) -{ - sv_utf8_downgrade(sv,0); - return SvPV(sv,*lp); -} - -#endif - -/* Hint: sv_2pvbyte - * Use the SvPVbyte() macro instead of sv_2pvbyte(). - */ - -#undef SvPVbyte - -#define SvPVbyte(sv, lp) \ - ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \ - ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvbyte(sv, &lp)) - -#endif - -#else - -# define SvPVbyte SvPV -# define sv_2pvbyte sv_2pv - -#endif -#ifndef sv_2pvbyte_nolen -# define sv_2pvbyte_nolen(sv) sv_2pv_nolen(sv) -#endif - -/* Hint: sv_pvn - * Always use the SvPV() macro instead of sv_pvn(). - */ - -/* Hint: sv_pvn_force - * Always use the SvPV_force() macro instead of sv_pvn_force(). - */ - -/* If these are undefined, they're not handled by the core anyway */ -#ifndef SV_IMMEDIATE_UNREF -# define SV_IMMEDIATE_UNREF 0 -#endif - -#ifndef SV_GMAGIC -# define SV_GMAGIC 0 -#endif - -#ifndef SV_COW_DROP_PV -# define SV_COW_DROP_PV 0 -#endif - -#ifndef SV_UTF8_NO_ENCODING -# define SV_UTF8_NO_ENCODING 0 -#endif - -#ifndef SV_NOSTEAL -# define SV_NOSTEAL 0 -#endif - -#ifndef SV_CONST_RETURN -# define SV_CONST_RETURN 0 -#endif - -#ifndef SV_MUTABLE_RETURN -# define SV_MUTABLE_RETURN 0 -#endif - -#ifndef SV_SMAGIC -# define SV_SMAGIC 0 -#endif - -#ifndef SV_HAS_TRAILING_NUL -# define SV_HAS_TRAILING_NUL 0 -#endif - -#ifndef SV_COW_SHARED_HASH_KEYS -# define SV_COW_SHARED_HASH_KEYS 0 -#endif - -#if (PERL_BCDVERSION < 0x5007002) - -#if defined(NEED_sv_2pv_flags) -static char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); -static -#else -extern char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); -#endif - -#ifdef sv_2pv_flags -# undef sv_2pv_flags -#endif -#define sv_2pv_flags(a,b,c) DPPP_(my_sv_2pv_flags)(aTHX_ a,b,c) -#define Perl_sv_2pv_flags DPPP_(my_sv_2pv_flags) - -#if defined(NEED_sv_2pv_flags) || defined(NEED_sv_2pv_flags_GLOBAL) - -char * -DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags) -{ - STRLEN n_a = (STRLEN) flags; - return sv_2pv(sv, lp ? lp : &n_a); -} - -#endif - -#if defined(NEED_sv_pvn_force_flags) -static char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); -static -#else -extern char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); -#endif - -#ifdef sv_pvn_force_flags -# undef sv_pvn_force_flags -#endif -#define sv_pvn_force_flags(a,b,c) DPPP_(my_sv_pvn_force_flags)(aTHX_ a,b,c) -#define Perl_sv_pvn_force_flags DPPP_(my_sv_pvn_force_flags) - -#if defined(NEED_sv_pvn_force_flags) || defined(NEED_sv_pvn_force_flags_GLOBAL) - -char * -DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags) -{ - STRLEN n_a = (STRLEN) flags; - return sv_pvn_force(sv, lp ? lp : &n_a); -} - -#endif - -#endif - -#if (PERL_BCDVERSION < 0x5008008) || ( (PERL_BCDVERSION >= 0x5009000) && (PERL_BCDVERSION < 0x5009003) ) -# define DPPP_SVPV_NOLEN_LP_ARG &PL_na -#else -# define DPPP_SVPV_NOLEN_LP_ARG 0 -#endif -#ifndef SvPV_const -# define SvPV_const(sv, lp) SvPV_flags_const(sv, lp, SV_GMAGIC) -#endif - -#ifndef SvPV_mutable -# define SvPV_mutable(sv, lp) SvPV_flags_mutable(sv, lp, SV_GMAGIC) -#endif -#ifndef SvPV_flags -# define SvPV_flags(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pv_flags(sv, &lp, flags)) -#endif -#ifndef SvPV_flags_const -# define SvPV_flags_const(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX_const(sv)) : \ - (const char*) sv_2pv_flags(sv, &lp, flags|SV_CONST_RETURN)) -#endif -#ifndef SvPV_flags_const_nolen -# define SvPV_flags_const_nolen(sv, flags) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? SvPVX_const(sv) : \ - (const char*) sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, flags|SV_CONST_RETURN)) -#endif -#ifndef SvPV_flags_mutable -# define SvPV_flags_mutable(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) : \ - sv_2pv_flags(sv, &lp, flags|SV_MUTABLE_RETURN)) -#endif -#ifndef SvPV_force -# define SvPV_force(sv, lp) SvPV_force_flags(sv, lp, SV_GMAGIC) -#endif - -#ifndef SvPV_force_nolen -# define SvPV_force_nolen(sv) SvPV_force_flags_nolen(sv, SV_GMAGIC) -#endif - -#ifndef SvPV_force_mutable -# define SvPV_force_mutable(sv, lp) SvPV_force_flags_mutable(sv, lp, SV_GMAGIC) -#endif - -#ifndef SvPV_force_nomg -# define SvPV_force_nomg(sv, lp) SvPV_force_flags(sv, lp, 0) -#endif - -#ifndef SvPV_force_nomg_nolen -# define SvPV_force_nomg_nolen(sv) SvPV_force_flags_nolen(sv, 0) -#endif -#ifndef SvPV_force_flags -# define SvPV_force_flags(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvn_force_flags(sv, &lp, flags)) -#endif -#ifndef SvPV_force_flags_nolen -# define SvPV_force_flags_nolen(sv, flags) \ - ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ - ? SvPVX(sv) : sv_pvn_force_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, flags)) -#endif -#ifndef SvPV_force_flags_mutable -# define SvPV_force_flags_mutable(sv, lp, flags) \ - ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ - ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) \ - : sv_pvn_force_flags(sv, &lp, flags|SV_MUTABLE_RETURN)) -#endif -#ifndef SvPV_nolen -# define SvPV_nolen(sv) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? SvPVX(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC)) -#endif -#ifndef SvPV_nolen_const -# define SvPV_nolen_const(sv) \ - ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? SvPVX_const(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC|SV_CONST_RETURN)) -#endif -#ifndef SvPV_nomg -# define SvPV_nomg(sv, lp) SvPV_flags(sv, lp, 0) -#endif - -#ifndef SvPV_nomg_const -# define SvPV_nomg_const(sv, lp) SvPV_flags_const(sv, lp, 0) -#endif - -#ifndef SvPV_nomg_const_nolen -# define SvPV_nomg_const_nolen(sv) SvPV_flags_const_nolen(sv, 0) -#endif - -#ifndef SvPV_nomg_nolen -# define SvPV_nomg_nolen(sv) ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ - ? SvPVX(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, 0)) -#endif -#ifndef SvPV_renew -# define SvPV_renew(sv,n) STMT_START { SvLEN_set(sv, n); \ - SvPV_set((sv), (char *) saferealloc( \ - (Malloc_t)SvPVX(sv), (MEM_SIZE)((n)))); \ - } STMT_END -#endif -#ifndef SvMAGIC_set -# define SvMAGIC_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \ - (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END -#endif - -#if (PERL_BCDVERSION < 0x5009003) -#ifndef SvPVX_const -# define SvPVX_const(sv) ((const char*) (0 + SvPVX(sv))) -#endif - -#ifndef SvPVX_mutable -# define SvPVX_mutable(sv) (0 + SvPVX(sv)) -#endif -#ifndef SvRV_set -# define SvRV_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) >= SVt_RV); \ - (((XRV*) SvANY(sv))->xrv_rv = (val)); } STMT_END -#endif - -#else -#ifndef SvPVX_const -# define SvPVX_const(sv) ((const char*)((sv)->sv_u.svu_pv)) -#endif - -#ifndef SvPVX_mutable -# define SvPVX_mutable(sv) ((sv)->sv_u.svu_pv) -#endif -#ifndef SvRV_set -# define SvRV_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) >= SVt_RV); \ - ((sv)->sv_u.svu_rv = (val)); } STMT_END -#endif - -#endif -#ifndef SvSTASH_set -# define SvSTASH_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \ - (((XPVMG*) SvANY(sv))->xmg_stash = (val)); } STMT_END -#endif - -#if (PERL_BCDVERSION < 0x5004000) -#ifndef SvUV_set -# define SvUV_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \ - (((XPVIV*) SvANY(sv))->xiv_iv = (IV) (val)); } STMT_END -#endif - -#else -#ifndef SvUV_set -# define SvUV_set(sv, val) \ - STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \ - (((XPVUV*) SvANY(sv))->xuv_uv = (val)); } STMT_END -#endif - -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(vnewSVpvf) -#if defined(NEED_vnewSVpvf) -static SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args); -static -#else -extern SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args); -#endif - -#ifdef vnewSVpvf -# undef vnewSVpvf -#endif -#define vnewSVpvf(a,b) DPPP_(my_vnewSVpvf)(aTHX_ a,b) -#define Perl_vnewSVpvf DPPP_(my_vnewSVpvf) - -#if defined(NEED_vnewSVpvf) || defined(NEED_vnewSVpvf_GLOBAL) - -SV * -DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args) -{ - register SV *sv = newSV(0); - sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); - return sv; -} - -#endif -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf) -# define sv_vcatpvf(sv, pat, args) sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)) -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf) -# define sv_vsetpvf(sv, pat, args) sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)) -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg) -#if defined(NEED_sv_catpvf_mg) -static void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...); -static -#else -extern void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...); -#endif - -#define Perl_sv_catpvf_mg DPPP_(my_sv_catpvf_mg) - -#if defined(NEED_sv_catpvf_mg) || defined(NEED_sv_catpvf_mg_GLOBAL) - -void -DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...) -{ - va_list args; - va_start(args, pat); - sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); - va_end(args); -} - -#endif -#endif - -#ifdef PERL_IMPLICIT_CONTEXT -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg_nocontext) -#if defined(NEED_sv_catpvf_mg_nocontext) -static void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...); -static -#else -extern void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...); -#endif - -#define sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext) -#define Perl_sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext) - -#if defined(NEED_sv_catpvf_mg_nocontext) || defined(NEED_sv_catpvf_mg_nocontext_GLOBAL) - -void -DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...) -{ - dTHX; - va_list args; - va_start(args, pat); - sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); - va_end(args); -} - -#endif -#endif -#endif - -/* sv_catpvf_mg depends on sv_catpvf_mg_nocontext */ -#ifndef sv_catpvf_mg -# ifdef PERL_IMPLICIT_CONTEXT -# define sv_catpvf_mg Perl_sv_catpvf_mg_nocontext -# else -# define sv_catpvf_mg Perl_sv_catpvf_mg -# endif -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf_mg) -# define sv_vcatpvf_mg(sv, pat, args) \ - STMT_START { \ - sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \ - SvSETMAGIC(sv); \ - } STMT_END -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg) -#if defined(NEED_sv_setpvf_mg) -static void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...); -static -#else -extern void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...); -#endif - -#define Perl_sv_setpvf_mg DPPP_(my_sv_setpvf_mg) - -#if defined(NEED_sv_setpvf_mg) || defined(NEED_sv_setpvf_mg_GLOBAL) - -void -DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...) -{ - va_list args; - va_start(args, pat); - sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); - va_end(args); -} - -#endif -#endif - -#ifdef PERL_IMPLICIT_CONTEXT -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg_nocontext) -#if defined(NEED_sv_setpvf_mg_nocontext) -static void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...); -static -#else -extern void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...); -#endif - -#define sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext) -#define Perl_sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext) - -#if defined(NEED_sv_setpvf_mg_nocontext) || defined(NEED_sv_setpvf_mg_nocontext_GLOBAL) - -void -DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...) -{ - dTHX; - va_list args; - va_start(args, pat); - sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); - SvSETMAGIC(sv); - va_end(args); -} - -#endif -#endif -#endif - -/* sv_setpvf_mg depends on sv_setpvf_mg_nocontext */ -#ifndef sv_setpvf_mg -# ifdef PERL_IMPLICIT_CONTEXT -# define sv_setpvf_mg Perl_sv_setpvf_mg_nocontext -# else -# define sv_setpvf_mg Perl_sv_setpvf_mg -# endif -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf_mg) -# define sv_vsetpvf_mg(sv, pat, args) \ - STMT_START { \ - sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \ - SvSETMAGIC(sv); \ - } STMT_END -#endif - -/* Hint: newSVpvn_share - * The SVs created by this function only mimic the behaviour of - * shared PVs without really being shared. Only use if you know - * what you're doing. - */ - -#ifndef newSVpvn_share - -#if defined(NEED_newSVpvn_share) -static SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash); -static -#else -extern SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash); -#endif - -#ifdef newSVpvn_share -# undef newSVpvn_share -#endif -#define newSVpvn_share(a,b,c) DPPP_(my_newSVpvn_share)(aTHX_ a,b,c) -#define Perl_newSVpvn_share DPPP_(my_newSVpvn_share) - -#if defined(NEED_newSVpvn_share) || defined(NEED_newSVpvn_share_GLOBAL) - -SV * -DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash) -{ - SV *sv; - if (len < 0) - len = -len; - if (!hash) - PERL_HASH(hash, (char*) src, len); - sv = newSVpvn((char *) src, len); - sv_upgrade(sv, SVt_PVIV); - SvIVX(sv) = hash; - SvREADONLY_on(sv); - SvPOK_on(sv); - return sv; -} - -#endif - -#endif -#ifndef SvSHARED_HASH -# define SvSHARED_HASH(sv) (0 + SvUVX(sv)) -#endif -#ifndef HvNAME_get -# define HvNAME_get(hv) HvNAME(hv) -#endif -#ifndef HvNAMELEN_get -# define HvNAMELEN_get(hv) (HvNAME_get(hv) ? (I32)strlen(HvNAME_get(hv)) : 0) -#endif -#ifndef GvSVn -# define GvSVn(gv) GvSV(gv) -#endif - -#ifndef isGV_with_GP -# define isGV_with_GP(gv) isGV(gv) -#endif - -#ifndef gv_fetchpvn_flags -# define gv_fetchpvn_flags(name, len, flags, svt) gv_fetchpv(name, flags, svt) -#endif - -#ifndef gv_fetchsv -# define gv_fetchsv(name, flags, svt) gv_fetchpv(SvPV_nolen_const(name), flags, svt) -#endif -#ifndef get_cvn_flags -# define get_cvn_flags(name, namelen, flags) get_cv(name, flags) -#endif -#ifndef WARN_ALL -# define WARN_ALL 0 -#endif - -#ifndef WARN_CLOSURE -# define WARN_CLOSURE 1 -#endif - -#ifndef WARN_DEPRECATED -# define WARN_DEPRECATED 2 -#endif - -#ifndef WARN_EXITING -# define WARN_EXITING 3 -#endif - -#ifndef WARN_GLOB -# define WARN_GLOB 4 -#endif - -#ifndef WARN_IO -# define WARN_IO 5 -#endif - -#ifndef WARN_CLOSED -# define WARN_CLOSED 6 -#endif - -#ifndef WARN_EXEC -# define WARN_EXEC 7 -#endif - -#ifndef WARN_LAYER -# define WARN_LAYER 8 -#endif - -#ifndef WARN_NEWLINE -# define WARN_NEWLINE 9 -#endif - -#ifndef WARN_PIPE -# define WARN_PIPE 10 -#endif - -#ifndef WARN_UNOPENED -# define WARN_UNOPENED 11 -#endif - -#ifndef WARN_MISC -# define WARN_MISC 12 -#endif - -#ifndef WARN_NUMERIC -# define WARN_NUMERIC 13 -#endif - -#ifndef WARN_ONCE -# define WARN_ONCE 14 -#endif - -#ifndef WARN_OVERFLOW -# define WARN_OVERFLOW 15 -#endif - -#ifndef WARN_PACK -# define WARN_PACK 16 -#endif - -#ifndef WARN_PORTABLE -# define WARN_PORTABLE 17 -#endif - -#ifndef WARN_RECURSION -# define WARN_RECURSION 18 -#endif - -#ifndef WARN_REDEFINE -# define WARN_REDEFINE 19 -#endif - -#ifndef WARN_REGEXP -# define WARN_REGEXP 20 -#endif - -#ifndef WARN_SEVERE -# define WARN_SEVERE 21 -#endif - -#ifndef WARN_DEBUGGING -# define WARN_DEBUGGING 22 -#endif - -#ifndef WARN_INPLACE -# define WARN_INPLACE 23 -#endif - -#ifndef WARN_INTERNAL -# define WARN_INTERNAL 24 -#endif - -#ifndef WARN_MALLOC -# define WARN_MALLOC 25 -#endif - -#ifndef WARN_SIGNAL -# define WARN_SIGNAL 26 -#endif - -#ifndef WARN_SUBSTR -# define WARN_SUBSTR 27 -#endif - -#ifndef WARN_SYNTAX -# define WARN_SYNTAX 28 -#endif - -#ifndef WARN_AMBIGUOUS -# define WARN_AMBIGUOUS 29 -#endif - -#ifndef WARN_BAREWORD -# define WARN_BAREWORD 30 -#endif - -#ifndef WARN_DIGIT -# define WARN_DIGIT 31 -#endif - -#ifndef WARN_PARENTHESIS -# define WARN_PARENTHESIS 32 -#endif - -#ifndef WARN_PRECEDENCE -# define WARN_PRECEDENCE 33 -#endif - -#ifndef WARN_PRINTF -# define WARN_PRINTF 34 -#endif - -#ifndef WARN_PROTOTYPE -# define WARN_PROTOTYPE 35 -#endif - -#ifndef WARN_QW -# define WARN_QW 36 -#endif - -#ifndef WARN_RESERVED -# define WARN_RESERVED 37 -#endif - -#ifndef WARN_SEMICOLON -# define WARN_SEMICOLON 38 -#endif - -#ifndef WARN_TAINT -# define WARN_TAINT 39 -#endif - -#ifndef WARN_THREADS -# define WARN_THREADS 40 -#endif - -#ifndef WARN_UNINITIALIZED -# define WARN_UNINITIALIZED 41 -#endif - -#ifndef WARN_UNPACK -# define WARN_UNPACK 42 -#endif - -#ifndef WARN_UNTIE -# define WARN_UNTIE 43 -#endif - -#ifndef WARN_UTF8 -# define WARN_UTF8 44 -#endif - -#ifndef WARN_VOID -# define WARN_VOID 45 -#endif - -#ifndef WARN_ASSERTIONS -# define WARN_ASSERTIONS 46 -#endif -#ifndef packWARN -# define packWARN(a) (a) -#endif - -#ifndef ckWARN -# ifdef G_WARN_ON -# define ckWARN(a) (PL_dowarn & G_WARN_ON) -# else -# define ckWARN(a) PL_dowarn -# endif -#endif - -#if (PERL_BCDVERSION >= 0x5004000) && !defined(warner) -#if defined(NEED_warner) -static void DPPP_(my_warner)(U32 err, const char *pat, ...); -static -#else -extern void DPPP_(my_warner)(U32 err, const char *pat, ...); -#endif - -#define Perl_warner DPPP_(my_warner) - -#if defined(NEED_warner) || defined(NEED_warner_GLOBAL) - -void -DPPP_(my_warner)(U32 err, const char *pat, ...) -{ - SV *sv; - va_list args; - - PERL_UNUSED_ARG(err); - - va_start(args, pat); - sv = vnewSVpvf(pat, &args); - va_end(args); - sv_2mortal(sv); - warn("%s", SvPV_nolen(sv)); -} - -#define warner Perl_warner - -#define Perl_warner_nocontext Perl_warner - -#endif -#endif - -/* concatenating with "" ensures that only literal strings are accepted as argument - * note that STR_WITH_LEN() can't be used as argument to macros or functions that - * under some configurations might be macros - */ -#ifndef STR_WITH_LEN -# define STR_WITH_LEN(s) (s ""), (sizeof(s)-1) -#endif -#ifndef newSVpvs -# define newSVpvs(str) newSVpvn(str "", sizeof(str) - 1) -#endif - -#ifndef newSVpvs_flags -# define newSVpvs_flags(str, flags) newSVpvn_flags(str "", sizeof(str) - 1, flags) -#endif - -#ifndef newSVpvs_share -# define newSVpvs_share(str) newSVpvn_share(str "", sizeof(str) - 1, 0) -#endif - -#ifndef sv_catpvs -# define sv_catpvs(sv, str) sv_catpvn(sv, str "", sizeof(str) - 1) -#endif - -#ifndef sv_setpvs -# define sv_setpvs(sv, str) sv_setpvn(sv, str "", sizeof(str) - 1) -#endif - -#ifndef hv_fetchs -# define hv_fetchs(hv, key, lval) hv_fetch(hv, key "", sizeof(key) - 1, lval) -#endif - -#ifndef hv_stores -# define hv_stores(hv, key, val) hv_store(hv, key "", sizeof(key) - 1, val, 0) -#endif -#ifndef gv_fetchpvs -# define gv_fetchpvs(name, flags, svt) gv_fetchpvn_flags(name "", sizeof(name) - 1, flags, svt) -#endif - -#ifndef gv_stashpvs -# define gv_stashpvs(name, flags) gv_stashpvn(name "", sizeof(name) - 1, flags) -#endif -#ifndef get_cvs -# define get_cvs(name, flags) get_cvn_flags(name "", sizeof(name)-1, flags) -#endif -#ifndef SvGETMAGIC -# define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END -#endif - -/* Some random bits for sv_unmagicext. These should probably be pulled in for - real and organized at some point */ -#ifndef HEf_SVKEY -# define HEf_SVKEY -2 -#endif - -#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) -# define MUTABLE_PTR(p) ({ void *_p = (p); _p; }) -#else -# define MUTABLE_PTR(p) ((void *) (p)) -#endif - -#define MUTABLE_SV(p) ((SV *)MUTABLE_PTR(p)) - -/* end of random bits */ -#ifndef PERL_MAGIC_sv -# define PERL_MAGIC_sv '\0' -#endif - -#ifndef PERL_MAGIC_overload -# define PERL_MAGIC_overload 'A' -#endif - -#ifndef PERL_MAGIC_overload_elem -# define PERL_MAGIC_overload_elem 'a' -#endif - -#ifndef PERL_MAGIC_overload_table -# define PERL_MAGIC_overload_table 'c' -#endif - -#ifndef PERL_MAGIC_bm -# define PERL_MAGIC_bm 'B' -#endif - -#ifndef PERL_MAGIC_regdata -# define PERL_MAGIC_regdata 'D' -#endif - -#ifndef PERL_MAGIC_regdatum -# define PERL_MAGIC_regdatum 'd' -#endif - -#ifndef PERL_MAGIC_env -# define PERL_MAGIC_env 'E' -#endif - -#ifndef PERL_MAGIC_envelem -# define PERL_MAGIC_envelem 'e' -#endif - -#ifndef PERL_MAGIC_fm -# define PERL_MAGIC_fm 'f' -#endif - -#ifndef PERL_MAGIC_regex_global -# define PERL_MAGIC_regex_global 'g' -#endif - -#ifndef PERL_MAGIC_isa -# define PERL_MAGIC_isa 'I' -#endif - -#ifndef PERL_MAGIC_isaelem -# define PERL_MAGIC_isaelem 'i' -#endif - -#ifndef PERL_MAGIC_nkeys -# define PERL_MAGIC_nkeys 'k' -#endif - -#ifndef PERL_MAGIC_dbfile -# define PERL_MAGIC_dbfile 'L' -#endif - -#ifndef PERL_MAGIC_dbline -# define PERL_MAGIC_dbline 'l' -#endif - -#ifndef PERL_MAGIC_mutex -# define PERL_MAGIC_mutex 'm' -#endif - -#ifndef PERL_MAGIC_shared -# define PERL_MAGIC_shared 'N' -#endif - -#ifndef PERL_MAGIC_shared_scalar -# define PERL_MAGIC_shared_scalar 'n' -#endif - -#ifndef PERL_MAGIC_collxfrm -# define PERL_MAGIC_collxfrm 'o' -#endif - -#ifndef PERL_MAGIC_tied -# define PERL_MAGIC_tied 'P' -#endif - -#ifndef PERL_MAGIC_tiedelem -# define PERL_MAGIC_tiedelem 'p' -#endif - -#ifndef PERL_MAGIC_tiedscalar -# define PERL_MAGIC_tiedscalar 'q' -#endif - -#ifndef PERL_MAGIC_qr -# define PERL_MAGIC_qr 'r' -#endif - -#ifndef PERL_MAGIC_sig -# define PERL_MAGIC_sig 'S' -#endif - -#ifndef PERL_MAGIC_sigelem -# define PERL_MAGIC_sigelem 's' -#endif - -#ifndef PERL_MAGIC_taint -# define PERL_MAGIC_taint 't' -#endif - -#ifndef PERL_MAGIC_uvar -# define PERL_MAGIC_uvar 'U' -#endif - -#ifndef PERL_MAGIC_uvar_elem -# define PERL_MAGIC_uvar_elem 'u' -#endif - -#ifndef PERL_MAGIC_vstring -# define PERL_MAGIC_vstring 'V' -#endif - -#ifndef PERL_MAGIC_vec -# define PERL_MAGIC_vec 'v' -#endif - -#ifndef PERL_MAGIC_utf8 -# define PERL_MAGIC_utf8 'w' -#endif - -#ifndef PERL_MAGIC_substr -# define PERL_MAGIC_substr 'x' -#endif - -#ifndef PERL_MAGIC_defelem -# define PERL_MAGIC_defelem 'y' -#endif - -#ifndef PERL_MAGIC_glob -# define PERL_MAGIC_glob '*' -#endif - -#ifndef PERL_MAGIC_arylen -# define PERL_MAGIC_arylen '#' -#endif - -#ifndef PERL_MAGIC_pos -# define PERL_MAGIC_pos '.' -#endif - -#ifndef PERL_MAGIC_backref -# define PERL_MAGIC_backref '<' -#endif - -#ifndef PERL_MAGIC_ext -# define PERL_MAGIC_ext '~' -#endif - -/* That's the best we can do... */ -#ifndef sv_catpvn_nomg -# define sv_catpvn_nomg sv_catpvn -#endif - -#ifndef sv_catsv_nomg -# define sv_catsv_nomg sv_catsv -#endif - -#ifndef sv_setsv_nomg -# define sv_setsv_nomg sv_setsv -#endif - -#ifndef sv_pvn_nomg -# define sv_pvn_nomg sv_pvn -#endif - -#ifndef SvIV_nomg -# define SvIV_nomg SvIV -#endif - -#ifndef SvUV_nomg -# define SvUV_nomg SvUV -#endif - -#ifndef sv_catpv_mg -# define sv_catpv_mg(sv, ptr) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_catpv(TeMpSv,ptr); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_catpvn_mg -# define sv_catpvn_mg(sv, ptr, len) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_catpvn(TeMpSv,ptr,len); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_catsv_mg -# define sv_catsv_mg(dsv, ssv) \ - STMT_START { \ - SV *TeMpSv = dsv; \ - sv_catsv(TeMpSv,ssv); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setiv_mg -# define sv_setiv_mg(sv, i) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setiv(TeMpSv,i); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setnv_mg -# define sv_setnv_mg(sv, num) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setnv(TeMpSv,num); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setpv_mg -# define sv_setpv_mg(sv, ptr) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setpv(TeMpSv,ptr); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setpvn_mg -# define sv_setpvn_mg(sv, ptr, len) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setpvn(TeMpSv,ptr,len); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setsv_mg -# define sv_setsv_mg(dsv, ssv) \ - STMT_START { \ - SV *TeMpSv = dsv; \ - sv_setsv(TeMpSv,ssv); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_setuv_mg -# define sv_setuv_mg(sv, i) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_setuv(TeMpSv,i); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif - -#ifndef sv_usepvn_mg -# define sv_usepvn_mg(sv, ptr, len) \ - STMT_START { \ - SV *TeMpSv = sv; \ - sv_usepvn(TeMpSv,ptr,len); \ - SvSETMAGIC(TeMpSv); \ - } STMT_END -#endif -#ifndef SvVSTRING_mg -# define SvVSTRING_mg(sv) (SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_vstring) : NULL) -#endif - -/* Hint: sv_magic_portable - * This is a compatibility function that is only available with - * Devel::PPPort. It is NOT in the perl core. - * Its purpose is to mimic the 5.8.0 behaviour of sv_magic() when - * it is being passed a name pointer with namlen == 0. In that - * case, perl 5.8.0 and later store the pointer, not a copy of it. - * The compatibility can be provided back to perl 5.004. With - * earlier versions, the code will not compile. - */ - -#if (PERL_BCDVERSION < 0x5004000) - - /* code that uses sv_magic_portable will not compile */ - -#elif (PERL_BCDVERSION < 0x5008000) - -# define sv_magic_portable(sv, obj, how, name, namlen) \ - STMT_START { \ - SV *SvMp_sv = (sv); \ - char *SvMp_name = (char *) (name); \ - I32 SvMp_namlen = (namlen); \ - if (SvMp_name && SvMp_namlen == 0) \ - { \ - MAGIC *mg; \ - sv_magic(SvMp_sv, obj, how, 0, 0); \ - mg = SvMAGIC(SvMp_sv); \ - mg->mg_len = -42; /* XXX: this is the tricky part */ \ - mg->mg_ptr = SvMp_name; \ - } \ - else \ - { \ - sv_magic(SvMp_sv, obj, how, SvMp_name, SvMp_namlen); \ - } \ - } STMT_END - -#else - -# define sv_magic_portable(a, b, c, d, e) sv_magic(a, b, c, d, e) - -#endif - -#if !defined(mg_findext) -#if defined(NEED_mg_findext) -static MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl); -static -#else -extern MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl); -#endif - -#define mg_findext DPPP_(my_mg_findext) -#define Perl_mg_findext DPPP_(my_mg_findext) - -#if defined(NEED_mg_findext) || defined(NEED_mg_findext_GLOBAL) - -MAGIC * -DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl) { - if (sv) { - MAGIC *mg; - -#ifdef AvPAD_NAMELIST - assert(!(SvTYPE(sv) == SVt_PVAV && AvPAD_NAMELIST(sv))); -#endif - - for (mg = SvMAGIC (sv); mg; mg = mg->mg_moremagic) { - if (mg->mg_type == type && mg->mg_virtual == vtbl) - return mg; - } - } - - return NULL; -} - -#endif -#endif - -#if !defined(sv_unmagicext) -#if defined(NEED_sv_unmagicext) -static int DPPP_(my_sv_unmagicext)(pTHX_ SV * const sv, const int type, MGVTBL * vtbl); -static -#else -extern int DPPP_(my_sv_unmagicext)(pTHX_ SV * const sv, const int type, MGVTBL * vtbl); -#endif - -#ifdef sv_unmagicext -# undef sv_unmagicext -#endif -#define sv_unmagicext(a,b,c) DPPP_(my_sv_unmagicext)(aTHX_ a,b,c) -#define Perl_sv_unmagicext DPPP_(my_sv_unmagicext) - -#if defined(NEED_sv_unmagicext) || defined(NEED_sv_unmagicext_GLOBAL) - -int -DPPP_(my_sv_unmagicext)(pTHX_ SV *const sv, const int type, MGVTBL *vtbl) -{ - MAGIC* mg; - MAGIC** mgp; - - if (SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv)) - return 0; - mgp = &(SvMAGIC(sv)); - for (mg = *mgp; mg; mg = *mgp) { - const MGVTBL* const virt = mg->mg_virtual; - if (mg->mg_type == type && virt == vtbl) { - *mgp = mg->mg_moremagic; - if (virt && virt->svt_free) - virt->svt_free(aTHX_ sv, mg); - if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) { - if (mg->mg_len > 0) - Safefree(mg->mg_ptr); - else if (mg->mg_len == HEf_SVKEY) /* Questionable on older perls... */ - SvREFCNT_dec(MUTABLE_SV(mg->mg_ptr)); - else if (mg->mg_type == PERL_MAGIC_utf8) - Safefree(mg->mg_ptr); - } - if (mg->mg_flags & MGf_REFCOUNTED) - SvREFCNT_dec(mg->mg_obj); - Safefree(mg); - } - else - mgp = &mg->mg_moremagic; - } - if (SvMAGIC(sv)) { - if (SvMAGICAL(sv)) /* if we're under save_magic, wait for restore_magic; */ - mg_magical(sv); /* else fix the flags now */ - } - else { - SvMAGICAL_off(sv); - SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; - } - return 0; -} - -#endif -#endif - -#ifdef USE_ITHREADS -#ifndef CopFILE -# define CopFILE(c) ((c)->cop_file) -#endif - -#ifndef CopFILEGV -# define CopFILEGV(c) (CopFILE(c) ? gv_fetchfile(CopFILE(c)) : Nullgv) -#endif - -#ifndef CopFILE_set -# define CopFILE_set(c,pv) ((c)->cop_file = savepv(pv)) -#endif - -#ifndef CopFILESV -# define CopFILESV(c) (CopFILE(c) ? GvSV(gv_fetchfile(CopFILE(c))) : Nullsv) -#endif - -#ifndef CopFILEAV -# define CopFILEAV(c) (CopFILE(c) ? GvAV(gv_fetchfile(CopFILE(c))) : Nullav) -#endif - -#ifndef CopSTASHPV -# define CopSTASHPV(c) ((c)->cop_stashpv) -#endif - -#ifndef CopSTASHPV_set -# define CopSTASHPV_set(c,pv) ((c)->cop_stashpv = ((pv) ? savepv(pv) : Nullch)) -#endif - -#ifndef CopSTASH -# define CopSTASH(c) (CopSTASHPV(c) ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv) -#endif - -#ifndef CopSTASH_set -# define CopSTASH_set(c,hv) CopSTASHPV_set(c, (hv) ? HvNAME(hv) : Nullch) -#endif - -#ifndef CopSTASH_eq -# define CopSTASH_eq(c,hv) ((hv) && (CopSTASHPV(c) == HvNAME(hv) \ - || (CopSTASHPV(c) && HvNAME(hv) \ - && strEQ(CopSTASHPV(c), HvNAME(hv))))) -#endif - -#else -#ifndef CopFILEGV -# define CopFILEGV(c) ((c)->cop_filegv) -#endif - -#ifndef CopFILEGV_set -# define CopFILEGV_set(c,gv) ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv)) -#endif - -#ifndef CopFILE_set -# define CopFILE_set(c,pv) CopFILEGV_set((c), gv_fetchfile(pv)) -#endif - -#ifndef CopFILESV -# define CopFILESV(c) (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : Nullsv) -#endif - -#ifndef CopFILEAV -# define CopFILEAV(c) (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : Nullav) -#endif - -#ifndef CopFILE -# define CopFILE(c) (CopFILESV(c) ? SvPVX(CopFILESV(c)) : Nullch) -#endif - -#ifndef CopSTASH -# define CopSTASH(c) ((c)->cop_stash) -#endif - -#ifndef CopSTASH_set -# define CopSTASH_set(c,hv) ((c)->cop_stash = (hv)) -#endif - -#ifndef CopSTASHPV -# define CopSTASHPV(c) (CopSTASH(c) ? HvNAME(CopSTASH(c)) : Nullch) -#endif - -#ifndef CopSTASHPV_set -# define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD)) -#endif - -#ifndef CopSTASH_eq -# define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv)) -#endif - -#endif /* USE_ITHREADS */ - -#if (PERL_BCDVERSION >= 0x5006000) -#ifndef caller_cx - -# if defined(NEED_caller_cx) || defined(NEED_caller_cx_GLOBAL) -static I32 -DPPP_dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock) -{ - I32 i; - - for (i = startingblock; i >= 0; i--) { - register const PERL_CONTEXT * const cx = &cxstk[i]; - switch (CxTYPE(cx)) { - default: - continue; - case CXt_EVAL: - case CXt_SUB: - case CXt_FORMAT: - return i; - } - } - return i; -} -# endif - -# if defined(NEED_caller_cx) -static const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp); -static -#else -extern const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp); -#endif - -#ifdef caller_cx -# undef caller_cx -#endif -#define caller_cx(a,b) DPPP_(my_caller_cx)(aTHX_ a,b) -#define Perl_caller_cx DPPP_(my_caller_cx) - -#if defined(NEED_caller_cx) || defined(NEED_caller_cx_GLOBAL) - -const PERL_CONTEXT * -DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp) -{ - register I32 cxix = DPPP_dopoptosub_at(cxstack, cxstack_ix); - register const PERL_CONTEXT *cx; - register const PERL_CONTEXT *ccstack = cxstack; - const PERL_SI *top_si = PL_curstackinfo; - - for (;;) { - /* we may be in a higher stacklevel, so dig down deeper */ - while (cxix < 0 && top_si->si_type != PERLSI_MAIN) { - top_si = top_si->si_prev; - ccstack = top_si->si_cxstack; - cxix = DPPP_dopoptosub_at(ccstack, top_si->si_cxix); - } - if (cxix < 0) - return NULL; - /* caller() should not report the automatic calls to &DB::sub */ - if (PL_DBsub && GvCV(PL_DBsub) && cxix >= 0 && - ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub)) - count++; - if (!count--) - break; - cxix = DPPP_dopoptosub_at(ccstack, cxix - 1); - } - - cx = &ccstack[cxix]; - if (dbcxp) *dbcxp = cx; - - if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { - const I32 dbcxix = DPPP_dopoptosub_at(ccstack, cxix - 1); - /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the - field below is defined for any cx. */ - /* caller() should not report the automatic calls to &DB::sub */ - if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) - cx = &ccstack[dbcxix]; - } - - return cx; -} - -# endif -#endif /* caller_cx */ -#endif /* 5.6.0 */ -#ifndef IN_PERL_COMPILETIME -# define IN_PERL_COMPILETIME (PL_curcop == &PL_compiling) -#endif - -#ifndef IN_LOCALE_RUNTIME -# define IN_LOCALE_RUNTIME (PL_curcop->op_private & HINT_LOCALE) -#endif - -#ifndef IN_LOCALE_COMPILETIME -# define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE) -#endif - -#ifndef IN_LOCALE -# define IN_LOCALE (IN_PERL_COMPILETIME ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME) -#endif -#ifndef IS_NUMBER_IN_UV -# define IS_NUMBER_IN_UV 0x01 -#endif - -#ifndef IS_NUMBER_GREATER_THAN_UV_MAX -# define IS_NUMBER_GREATER_THAN_UV_MAX 0x02 -#endif - -#ifndef IS_NUMBER_NOT_INT -# define IS_NUMBER_NOT_INT 0x04 -#endif - -#ifndef IS_NUMBER_NEG -# define IS_NUMBER_NEG 0x08 -#endif - -#ifndef IS_NUMBER_INFINITY -# define IS_NUMBER_INFINITY 0x10 -#endif - -#ifndef IS_NUMBER_NAN -# define IS_NUMBER_NAN 0x20 -#endif -#ifndef GROK_NUMERIC_RADIX -# define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(sp, send) -#endif -#ifndef PERL_SCAN_GREATER_THAN_UV_MAX -# define PERL_SCAN_GREATER_THAN_UV_MAX 0x02 -#endif - -#ifndef PERL_SCAN_SILENT_ILLDIGIT -# define PERL_SCAN_SILENT_ILLDIGIT 0x04 -#endif - -#ifndef PERL_SCAN_ALLOW_UNDERSCORES -# define PERL_SCAN_ALLOW_UNDERSCORES 0x01 -#endif - -#ifndef PERL_SCAN_DISALLOW_PREFIX -# define PERL_SCAN_DISALLOW_PREFIX 0x02 -#endif - -#ifndef grok_numeric_radix -#if defined(NEED_grok_numeric_radix) -static bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send); -static -#else -extern bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send); -#endif - -#ifdef grok_numeric_radix -# undef grok_numeric_radix -#endif -#define grok_numeric_radix(a,b) DPPP_(my_grok_numeric_radix)(aTHX_ a,b) -#define Perl_grok_numeric_radix DPPP_(my_grok_numeric_radix) - -#if defined(NEED_grok_numeric_radix) || defined(NEED_grok_numeric_radix_GLOBAL) -bool -DPPP_(my_grok_numeric_radix)(pTHX_ const char **sp, const char *send) -{ -#ifdef USE_LOCALE_NUMERIC -#ifdef PL_numeric_radix_sv - if (PL_numeric_radix_sv && IN_LOCALE) { - STRLEN len; - char* radix = SvPV(PL_numeric_radix_sv, len); - if (*sp + len <= send && memEQ(*sp, radix, len)) { - *sp += len; - return TRUE; - } - } -#else - /* older perls don't have PL_numeric_radix_sv so the radix - * must manually be requested from locale.h - */ -#include - dTHR; /* needed for older threaded perls */ - struct lconv *lc = localeconv(); - char *radix = lc->decimal_point; - if (radix && IN_LOCALE) { - STRLEN len = strlen(radix); - if (*sp + len <= send && memEQ(*sp, radix, len)) { - *sp += len; - return TRUE; - } - } -#endif -#endif /* USE_LOCALE_NUMERIC */ - /* always try "." if numeric radix didn't match because - * we may have data from different locales mixed */ - if (*sp < send && **sp == '.') { - ++*sp; - return TRUE; - } - return FALSE; -} -#endif -#endif - -#ifndef grok_number -#if defined(NEED_grok_number) -static int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep); -static -#else -extern int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep); -#endif - -#ifdef grok_number -# undef grok_number -#endif -#define grok_number(a,b,c) DPPP_(my_grok_number)(aTHX_ a,b,c) -#define Perl_grok_number DPPP_(my_grok_number) - -#if defined(NEED_grok_number) || defined(NEED_grok_number_GLOBAL) -int -DPPP_(my_grok_number)(pTHX_ const char *pv, STRLEN len, UV *valuep) -{ - const char *s = pv; - const char *send = pv + len; - const UV max_div_10 = UV_MAX / 10; - const char max_mod_10 = UV_MAX % 10; - int numtype = 0; - int sawinf = 0; - int sawnan = 0; - - while (s < send && isSPACE(*s)) - s++; - if (s == send) { - return 0; - } else if (*s == '-') { - s++; - numtype = IS_NUMBER_NEG; - } - else if (*s == '+') - s++; - - if (s == send) - return 0; - - /* next must be digit or the radix separator or beginning of infinity */ - if (isDIGIT(*s)) { - /* UVs are at least 32 bits, so the first 9 decimal digits cannot - overflow. */ - UV value = *s - '0'; - /* This construction seems to be more optimiser friendly. - (without it gcc does the isDIGIT test and the *s - '0' separately) - With it gcc on arm is managing 6 instructions (6 cycles) per digit. - In theory the optimiser could deduce how far to unroll the loop - before checking for overflow. */ - if (++s < send) { - int digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - digit = *s - '0'; - if (digit >= 0 && digit <= 9) { - value = value * 10 + digit; - if (++s < send) { - /* Now got 9 digits, so need to check - each time for overflow. */ - digit = *s - '0'; - while (digit >= 0 && digit <= 9 - && (value < max_div_10 - || (value == max_div_10 - && digit <= max_mod_10))) { - value = value * 10 + digit; - if (++s < send) - digit = *s - '0'; - else - break; - } - if (digit >= 0 && digit <= 9 - && (s < send)) { - /* value overflowed. - skip the remaining digits, don't - worry about setting *valuep. */ - do { - s++; - } while (s < send && isDIGIT(*s)); - numtype |= - IS_NUMBER_GREATER_THAN_UV_MAX; - goto skip_value; - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - numtype |= IS_NUMBER_IN_UV; - if (valuep) - *valuep = value; - - skip_value: - if (GROK_NUMERIC_RADIX(&s, send)) { - numtype |= IS_NUMBER_NOT_INT; - while (s < send && isDIGIT(*s)) /* optional digits after the radix */ - s++; - } - } - else if (GROK_NUMERIC_RADIX(&s, send)) { - numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */ - /* no digits before the radix means we need digits after it */ - if (s < send && isDIGIT(*s)) { - do { - s++; - } while (s < send && isDIGIT(*s)); - if (valuep) { - /* integer approximation is valid - it's 0. */ - *valuep = 0; - } - } - else - return 0; - } else if (*s == 'I' || *s == 'i') { - s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; - s++; if (s == send || (*s != 'F' && *s != 'f')) return 0; - s++; if (s < send && (*s == 'I' || *s == 'i')) { - s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; - s++; if (s == send || (*s != 'I' && *s != 'i')) return 0; - s++; if (s == send || (*s != 'T' && *s != 't')) return 0; - s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0; - s++; - } - sawinf = 1; - } else if (*s == 'N' || *s == 'n') { - /* XXX TODO: There are signaling NaNs and quiet NaNs. */ - s++; if (s == send || (*s != 'A' && *s != 'a')) return 0; - s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; - s++; - sawnan = 1; - } else - return 0; - - if (sawinf) { - numtype &= IS_NUMBER_NEG; /* Keep track of sign */ - numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT; - } else if (sawnan) { - numtype &= IS_NUMBER_NEG; /* Keep track of sign */ - numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT; - } else if (s < send) { - /* we can have an optional exponent part */ - if (*s == 'e' || *s == 'E') { - /* The only flag we keep is sign. Blow away any "it's UV" */ - numtype &= IS_NUMBER_NEG; - numtype |= IS_NUMBER_NOT_INT; - s++; - if (s < send && (*s == '-' || *s == '+')) - s++; - if (s < send && isDIGIT(*s)) { - do { - s++; - } while (s < send && isDIGIT(*s)); - } - else - return 0; - } - } - while (s < send && isSPACE(*s)) - s++; - if (s >= send) - return numtype; - if (len == 10 && memEQ(pv, "0 but true", 10)) { - if (valuep) - *valuep = 0; - return IS_NUMBER_IN_UV; - } - return 0; -} -#endif -#endif - -/* - * The grok_* routines have been modified to use warn() instead of - * Perl_warner(). Also, 'hexdigit' was the former name of PL_hexdigit, - * which is why the stack variable has been renamed to 'xdigit'. - */ - -#ifndef grok_bin -#if defined(NEED_grok_bin) -static UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -static -#else -extern UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -#endif - -#ifdef grok_bin -# undef grok_bin -#endif -#define grok_bin(a,b,c,d) DPPP_(my_grok_bin)(aTHX_ a,b,c,d) -#define Perl_grok_bin DPPP_(my_grok_bin) - -#if defined(NEED_grok_bin) || defined(NEED_grok_bin_GLOBAL) -UV -DPPP_(my_grok_bin)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) -{ - const char *s = start; - STRLEN len = *len_p; - UV value = 0; - NV value_nv = 0; - - const UV max_div_2 = UV_MAX / 2; - bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; - bool overflowed = FALSE; - - if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) { - /* strip off leading b or 0b. - for compatibility silently suffer "b" and "0b" as valid binary - numbers. */ - if (len >= 1) { - if (s[0] == 'b') { - s++; - len--; - } - else if (len >= 2 && s[0] == '0' && s[1] == 'b') { - s+=2; - len-=2; - } - } - } - - for (; len-- && *s; s++) { - char bit = *s; - if (bit == '0' || bit == '1') { - /* Write it in this wonky order with a goto to attempt to get the - compiler to make the common case integer-only loop pretty tight. - With gcc seems to be much straighter code than old scan_bin. */ - redo: - if (!overflowed) { - if (value <= max_div_2) { - value = (value << 1) | (bit - '0'); - continue; - } - /* Bah. We're just overflowed. */ - warn("Integer overflow in binary number"); - overflowed = TRUE; - value_nv = (NV) value; - } - value_nv *= 2.0; - /* If an NV has not enough bits in its mantissa to - * represent a UV this summing of small low-order numbers - * is a waste of time (because the NV cannot preserve - * the low-order bits anyway): we could just remember when - * did we overflow and in the end just multiply value_nv by the - * right amount. */ - value_nv += (NV)(bit - '0'); - continue; - } - if (bit == '_' && len && allow_underscores && (bit = s[1]) - && (bit == '0' || bit == '1')) - { - --len; - ++s; - goto redo; - } - if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) - warn("Illegal binary digit '%c' ignored", *s); - break; - } - - if ( ( overflowed && value_nv > 4294967295.0) -#if UVSIZE > 4 - || (!overflowed && value > 0xffffffff ) -#endif - ) { - warn("Binary number > 0b11111111111111111111111111111111 non-portable"); - } - *len_p = s - start; - if (!overflowed) { - *flags = 0; - return value; - } - *flags = PERL_SCAN_GREATER_THAN_UV_MAX; - if (result) - *result = value_nv; - return UV_MAX; -} -#endif -#endif - -#ifndef grok_hex -#if defined(NEED_grok_hex) -static UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -static -#else -extern UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -#endif - -#ifdef grok_hex -# undef grok_hex -#endif -#define grok_hex(a,b,c,d) DPPP_(my_grok_hex)(aTHX_ a,b,c,d) -#define Perl_grok_hex DPPP_(my_grok_hex) - -#if defined(NEED_grok_hex) || defined(NEED_grok_hex_GLOBAL) -UV -DPPP_(my_grok_hex)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) -{ - const char *s = start; - STRLEN len = *len_p; - UV value = 0; - NV value_nv = 0; - - const UV max_div_16 = UV_MAX / 16; - bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; - bool overflowed = FALSE; - const char *xdigit; - - if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) { - /* strip off leading x or 0x. - for compatibility silently suffer "x" and "0x" as valid hex numbers. - */ - if (len >= 1) { - if (s[0] == 'x') { - s++; - len--; - } - else if (len >= 2 && s[0] == '0' && s[1] == 'x') { - s+=2; - len-=2; - } - } - } - - for (; len-- && *s; s++) { - xdigit = strchr((char *) PL_hexdigit, *s); - if (xdigit) { - /* Write it in this wonky order with a goto to attempt to get the - compiler to make the common case integer-only loop pretty tight. - With gcc seems to be much straighter code than old scan_hex. */ - redo: - if (!overflowed) { - if (value <= max_div_16) { - value = (value << 4) | ((xdigit - PL_hexdigit) & 15); - continue; - } - warn("Integer overflow in hexadecimal number"); - overflowed = TRUE; - value_nv = (NV) value; - } - value_nv *= 16.0; - /* If an NV has not enough bits in its mantissa to - * represent a UV this summing of small low-order numbers - * is a waste of time (because the NV cannot preserve - * the low-order bits anyway): we could just remember when - * did we overflow and in the end just multiply value_nv by the - * right amount of 16-tuples. */ - value_nv += (NV)((xdigit - PL_hexdigit) & 15); - continue; - } - if (*s == '_' && len && allow_underscores && s[1] - && (xdigit = strchr((char *) PL_hexdigit, s[1]))) - { - --len; - ++s; - goto redo; - } - if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) - warn("Illegal hexadecimal digit '%c' ignored", *s); - break; - } - - if ( ( overflowed && value_nv > 4294967295.0) -#if UVSIZE > 4 - || (!overflowed && value > 0xffffffff ) -#endif - ) { - warn("Hexadecimal number > 0xffffffff non-portable"); - } - *len_p = s - start; - if (!overflowed) { - *flags = 0; - return value; - } - *flags = PERL_SCAN_GREATER_THAN_UV_MAX; - if (result) - *result = value_nv; - return UV_MAX; -} -#endif -#endif - -#ifndef grok_oct -#if defined(NEED_grok_oct) -static UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -static -#else -extern UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); -#endif - -#ifdef grok_oct -# undef grok_oct -#endif -#define grok_oct(a,b,c,d) DPPP_(my_grok_oct)(aTHX_ a,b,c,d) -#define Perl_grok_oct DPPP_(my_grok_oct) - -#if defined(NEED_grok_oct) || defined(NEED_grok_oct_GLOBAL) -UV -DPPP_(my_grok_oct)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) -{ - const char *s = start; - STRLEN len = *len_p; - UV value = 0; - NV value_nv = 0; - - const UV max_div_8 = UV_MAX / 8; - bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; - bool overflowed = FALSE; - - for (; len-- && *s; s++) { - /* gcc 2.95 optimiser not smart enough to figure that this subtraction - out front allows slicker code. */ - int digit = *s - '0'; - if (digit >= 0 && digit <= 7) { - /* Write it in this wonky order with a goto to attempt to get the - compiler to make the common case integer-only loop pretty tight. - */ - redo: - if (!overflowed) { - if (value <= max_div_8) { - value = (value << 3) | digit; - continue; - } - /* Bah. We're just overflowed. */ - warn("Integer overflow in octal number"); - overflowed = TRUE; - value_nv = (NV) value; - } - value_nv *= 8.0; - /* If an NV has not enough bits in its mantissa to - * represent a UV this summing of small low-order numbers - * is a waste of time (because the NV cannot preserve - * the low-order bits anyway): we could just remember when - * did we overflow and in the end just multiply value_nv by the - * right amount of 8-tuples. */ - value_nv += (NV)digit; - continue; - } - if (digit == ('_' - '0') && len && allow_underscores - && (digit = s[1] - '0') && (digit >= 0 && digit <= 7)) - { - --len; - ++s; - goto redo; - } - /* Allow \octal to work the DWIM way (that is, stop scanning - * as soon as non-octal characters are seen, complain only iff - * someone seems to want to use the digits eight and nine). */ - if (digit == 8 || digit == 9) { - if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) - warn("Illegal octal digit '%c' ignored", *s); - } - break; - } - - if ( ( overflowed && value_nv > 4294967295.0) -#if UVSIZE > 4 - || (!overflowed && value > 0xffffffff ) -#endif - ) { - warn("Octal number > 037777777777 non-portable"); - } - *len_p = s - start; - if (!overflowed) { - *flags = 0; - return value; - } - *flags = PERL_SCAN_GREATER_THAN_UV_MAX; - if (result) - *result = value_nv; - return UV_MAX; -} -#endif -#endif - -#if !defined(my_snprintf) -#if defined(NEED_my_snprintf) -static int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...); -static -#else -extern int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...); -#endif - -#define my_snprintf DPPP_(my_my_snprintf) -#define Perl_my_snprintf DPPP_(my_my_snprintf) - -#if defined(NEED_my_snprintf) || defined(NEED_my_snprintf_GLOBAL) - -int -DPPP_(my_my_snprintf)(char *buffer, const Size_t len, const char *format, ...) -{ - dTHX; - int retval; - va_list ap; - va_start(ap, format); -#ifdef HAS_VSNPRINTF - retval = vsnprintf(buffer, len, format, ap); -#else - retval = vsprintf(buffer, format, ap); -#endif - va_end(ap); - if (retval < 0 || (len > 0 && (Size_t)retval >= len)) - Perl_croak(aTHX_ "panic: my_snprintf buffer overflow"); - return retval; -} - -#endif -#endif - -#if !defined(my_sprintf) -#if defined(NEED_my_sprintf) -static int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...); -static -#else -extern int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...); -#endif - -#define my_sprintf DPPP_(my_my_sprintf) -#define Perl_my_sprintf DPPP_(my_my_sprintf) - -#if defined(NEED_my_sprintf) || defined(NEED_my_sprintf_GLOBAL) - -int -DPPP_(my_my_sprintf)(char *buffer, const char* pat, ...) -{ - va_list args; - va_start(args, pat); - vsprintf(buffer, pat, args); - va_end(args); - return strlen(buffer); -} - -#endif -#endif - -#ifdef NO_XSLOCKS -# ifdef dJMPENV -# define dXCPT dJMPENV; int rEtV = 0 -# define XCPT_TRY_START JMPENV_PUSH(rEtV); if (rEtV == 0) -# define XCPT_TRY_END JMPENV_POP; -# define XCPT_CATCH if (rEtV != 0) -# define XCPT_RETHROW JMPENV_JUMP(rEtV) -# else -# define dXCPT Sigjmp_buf oldTOP; int rEtV = 0 -# define XCPT_TRY_START Copy(top_env, oldTOP, 1, Sigjmp_buf); rEtV = Sigsetjmp(top_env, 1); if (rEtV == 0) -# define XCPT_TRY_END Copy(oldTOP, top_env, 1, Sigjmp_buf); -# define XCPT_CATCH if (rEtV != 0) -# define XCPT_RETHROW Siglongjmp(top_env, rEtV) -# endif -#endif - -#if !defined(my_strlcat) -#if defined(NEED_my_strlcat) -static Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size); -static -#else -extern Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size); -#endif - -#define my_strlcat DPPP_(my_my_strlcat) -#define Perl_my_strlcat DPPP_(my_my_strlcat) - -#if defined(NEED_my_strlcat) || defined(NEED_my_strlcat_GLOBAL) - -Size_t -DPPP_(my_my_strlcat)(char *dst, const char *src, Size_t size) -{ - Size_t used, length, copy; - - used = strlen(dst); - length = strlen(src); - if (size > 0 && used < size - 1) { - copy = (length >= size - used) ? size - used - 1 : length; - memcpy(dst + used, src, copy); - dst[used + copy] = '\0'; - } - return used + length; -} -#endif -#endif - -#if !defined(my_strlcpy) -#if defined(NEED_my_strlcpy) -static Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size); -static -#else -extern Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size); -#endif - -#define my_strlcpy DPPP_(my_my_strlcpy) -#define Perl_my_strlcpy DPPP_(my_my_strlcpy) - -#if defined(NEED_my_strlcpy) || defined(NEED_my_strlcpy_GLOBAL) - -Size_t -DPPP_(my_my_strlcpy)(char *dst, const char *src, Size_t size) -{ - Size_t length, copy; - - length = strlen(src); - if (size > 0) { - copy = (length >= size) ? size - 1 : length; - memcpy(dst, src, copy); - dst[copy] = '\0'; - } - return length; -} - -#endif -#endif -#ifndef PERL_PV_ESCAPE_QUOTE -# define PERL_PV_ESCAPE_QUOTE 0x0001 -#endif - -#ifndef PERL_PV_PRETTY_QUOTE -# define PERL_PV_PRETTY_QUOTE PERL_PV_ESCAPE_QUOTE -#endif - -#ifndef PERL_PV_PRETTY_ELLIPSES -# define PERL_PV_PRETTY_ELLIPSES 0x0002 -#endif - -#ifndef PERL_PV_PRETTY_LTGT -# define PERL_PV_PRETTY_LTGT 0x0004 -#endif - -#ifndef PERL_PV_ESCAPE_FIRSTCHAR -# define PERL_PV_ESCAPE_FIRSTCHAR 0x0008 -#endif - -#ifndef PERL_PV_ESCAPE_UNI -# define PERL_PV_ESCAPE_UNI 0x0100 -#endif - -#ifndef PERL_PV_ESCAPE_UNI_DETECT -# define PERL_PV_ESCAPE_UNI_DETECT 0x0200 -#endif - -#ifndef PERL_PV_ESCAPE_ALL -# define PERL_PV_ESCAPE_ALL 0x1000 -#endif - -#ifndef PERL_PV_ESCAPE_NOBACKSLASH -# define PERL_PV_ESCAPE_NOBACKSLASH 0x2000 -#endif - -#ifndef PERL_PV_ESCAPE_NOCLEAR -# define PERL_PV_ESCAPE_NOCLEAR 0x4000 -#endif - -#ifndef PERL_PV_ESCAPE_RE -# define PERL_PV_ESCAPE_RE 0x8000 -#endif - -#ifndef PERL_PV_PRETTY_NOCLEAR -# define PERL_PV_PRETTY_NOCLEAR PERL_PV_ESCAPE_NOCLEAR -#endif -#ifndef PERL_PV_PRETTY_DUMP -# define PERL_PV_PRETTY_DUMP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_QUOTE -#endif - -#ifndef PERL_PV_PRETTY_REGPROP -# define PERL_PV_PRETTY_REGPROP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_LTGT|PERL_PV_ESCAPE_RE -#endif - -/* Hint: pv_escape - * Note that unicode functionality is only backported to - * those perl versions that support it. For older perl - * versions, the implementation will fall back to bytes. - */ - -#ifndef pv_escape -#if defined(NEED_pv_escape) -static char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags); -static -#else -extern char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags); -#endif - -#ifdef pv_escape -# undef pv_escape -#endif -#define pv_escape(a,b,c,d,e,f) DPPP_(my_pv_escape)(aTHX_ a,b,c,d,e,f) -#define Perl_pv_escape DPPP_(my_pv_escape) - -#if defined(NEED_pv_escape) || defined(NEED_pv_escape_GLOBAL) - -char * -DPPP_(my_pv_escape)(pTHX_ SV *dsv, char const * const str, - const STRLEN count, const STRLEN max, - STRLEN * const escaped, const U32 flags) -{ - const char esc = flags & PERL_PV_ESCAPE_RE ? '%' : '\\'; - const char dq = flags & PERL_PV_ESCAPE_QUOTE ? '"' : esc; - char octbuf[32] = "%123456789ABCDF"; - STRLEN wrote = 0; - STRLEN chsize = 0; - STRLEN readsize = 1; -#if defined(is_utf8_string) && defined(utf8_to_uvchr) - bool isuni = flags & PERL_PV_ESCAPE_UNI ? 1 : 0; -#endif - const char *pv = str; - const char * const end = pv + count; - octbuf[0] = esc; - - if (!(flags & PERL_PV_ESCAPE_NOCLEAR)) - sv_setpvs(dsv, ""); - -#if defined(is_utf8_string) && defined(utf8_to_uvchr) - if ((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count)) - isuni = 1; -#endif - - for (; pv < end && (!max || wrote < max) ; pv += readsize) { - const UV u = -#if defined(is_utf8_string) && defined(utf8_to_uvchr) - isuni ? utf8_to_uvchr((U8*)pv, &readsize) : -#endif - (U8)*pv; - const U8 c = (U8)u & 0xFF; - - if (u > 255 || (flags & PERL_PV_ESCAPE_ALL)) { - if (flags & PERL_PV_ESCAPE_FIRSTCHAR) - chsize = my_snprintf(octbuf, sizeof octbuf, - "%" UVxf, u); - else - chsize = my_snprintf(octbuf, sizeof octbuf, - "%cx{%" UVxf "}", esc, u); - } else if (flags & PERL_PV_ESCAPE_NOBACKSLASH) { - chsize = 1; - } else { - if (c == dq || c == esc || !isPRINT(c)) { - chsize = 2; - switch (c) { - case '\\' : /* fallthrough */ - case '%' : if (c == esc) - octbuf[1] = esc; - else - chsize = 1; - break; - case '\v' : octbuf[1] = 'v'; break; - case '\t' : octbuf[1] = 't'; break; - case '\r' : octbuf[1] = 'r'; break; - case '\n' : octbuf[1] = 'n'; break; - case '\f' : octbuf[1] = 'f'; break; - case '"' : if (dq == '"') - octbuf[1] = '"'; - else - chsize = 1; - break; - default: chsize = my_snprintf(octbuf, sizeof octbuf, - pv < end && isDIGIT((U8)*(pv+readsize)) - ? "%c%03o" : "%c%o", esc, c); - } - } else { - chsize = 1; - } - } - if (max && wrote + chsize > max) { - break; - } else if (chsize > 1) { - sv_catpvn(dsv, octbuf, chsize); - wrote += chsize; - } else { - char tmp[2]; - my_snprintf(tmp, sizeof tmp, "%c", c); - sv_catpvn(dsv, tmp, 1); - wrote++; - } - if (flags & PERL_PV_ESCAPE_FIRSTCHAR) - break; - } - if (escaped != NULL) - *escaped= pv - str; - return SvPVX(dsv); -} - -#endif -#endif - -#ifndef pv_pretty -#if defined(NEED_pv_pretty) -static char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags); -static -#else -extern char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags); -#endif - -#ifdef pv_pretty -# undef pv_pretty -#endif -#define pv_pretty(a,b,c,d,e,f,g) DPPP_(my_pv_pretty)(aTHX_ a,b,c,d,e,f,g) -#define Perl_pv_pretty DPPP_(my_pv_pretty) - -#if defined(NEED_pv_pretty) || defined(NEED_pv_pretty_GLOBAL) - -char * -DPPP_(my_pv_pretty)(pTHX_ SV *dsv, char const * const str, const STRLEN count, - const STRLEN max, char const * const start_color, char const * const end_color, - const U32 flags) -{ - const U8 dq = (flags & PERL_PV_PRETTY_QUOTE) ? '"' : '%'; - STRLEN escaped; - - if (!(flags & PERL_PV_PRETTY_NOCLEAR)) - sv_setpvs(dsv, ""); - - if (dq == '"') - sv_catpvs(dsv, "\""); - else if (flags & PERL_PV_PRETTY_LTGT) - sv_catpvs(dsv, "<"); - - if (start_color != NULL) - sv_catpv(dsv, D_PPP_CONSTPV_ARG(start_color)); - - pv_escape(dsv, str, count, max, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR); - - if (end_color != NULL) - sv_catpv(dsv, D_PPP_CONSTPV_ARG(end_color)); - - if (dq == '"') - sv_catpvs(dsv, "\""); - else if (flags & PERL_PV_PRETTY_LTGT) - sv_catpvs(dsv, ">"); - - if ((flags & PERL_PV_PRETTY_ELLIPSES) && escaped < count) - sv_catpvs(dsv, "..."); - - return SvPVX(dsv); -} - -#endif -#endif - -#ifndef pv_display -#if defined(NEED_pv_display) -static char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim); -static -#else -extern char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim); -#endif - -#ifdef pv_display -# undef pv_display -#endif -#define pv_display(a,b,c,d,e) DPPP_(my_pv_display)(aTHX_ a,b,c,d,e) -#define Perl_pv_display DPPP_(my_pv_display) - -#if defined(NEED_pv_display) || defined(NEED_pv_display_GLOBAL) - -char * -DPPP_(my_pv_display)(pTHX_ SV *dsv, const char *pv, STRLEN cur, STRLEN len, STRLEN pvlim) -{ - pv_pretty(dsv, pv, cur, pvlim, NULL, NULL, PERL_PV_PRETTY_DUMP); - if (len > cur && pv[cur] == '\0') - sv_catpvs(dsv, "\\0"); - return SvPVX(dsv); -} - -#endif -#endif - -#endif /* _P_P_PORTABILITY_H_ */ - -/* End of File ppport.h */ diff --git a/dbLifeLog/DBI-1.641/dbiprof b/dbLifeLog/DBI-1.641/dbiprof deleted file mode 100755 index 0306a99..0000000 --- a/dbLifeLog/DBI-1.641/dbiprof +++ /dev/null @@ -1,263 +0,0 @@ -#!/usr/bin/perl - -use strict; - -my $VERSION = sprintf("1.%06d", q$Revision$ =~ /(\d+)/o); - -use Data::Dumper; -use DBI::ProfileData; -use Getopt::Long; - -# default options -my $number = 10; -my $sort = 'total'; -my $filename = 'dbi.prof'; -my $reverse = 0; -my $case_sensitive = 0; -my (%match, %exclude); - -# get options from command line -GetOptions( - 'version' => sub { die "dbiprof $VERSION\n" }, - 'help' => sub { exit usage() }, - 'number=i' => \$number, - 'sort=s' => \$sort, - 'dumpnodes!' => \my $dumpnodes, - 'reverse' => \$reverse, - 'match=s' => \%match, - 'exclude=s' => \%exclude, - 'case-sensitive' => \$case_sensitive, - 'delete!' => \my $opt_delete, -) or exit usage(); - -sub usage { - print <new( - Files => \@files, - DeleteFiles => $opt_delete, - ); -}; -die "Unable to load profile data: $@\n" if $@; - -if (%match) { # handle matches - while (my ($key, $val) = each %match) { - if ($val =~ m!^/(.+)/$!) { - $val = $case_sensitive ? qr/$1/ : qr/$1/i; - } - $prof->match($key, $val, case_sensitive => $case_sensitive); - } -} - -if (%exclude) { # handle excludes - while (my ($key, $val) = each %exclude) { - if ($val =~ m!^/(.+)/$!) { - $val = $case_sensitive ? qr/$1/ : qr/$1/i; - } - $prof->exclude($key, $val, case_sensitive => $case_sensitive); - } -} - -# sort the data -$prof->sort(field => $sort, reverse => $reverse); - -# all done, print it out -if ($dumpnodes) { - $Data::Dumper::Indent = 1; - $Data::Dumper::Terse = 1; - $Data::Dumper::Useqq = 1; - $Data::Dumper::Deparse = 0; - print Dumper($prof->nodes); -} -else { - print $prof->report(number => $number); -} -exit 0; - -__END__ - -=head1 NAME - -dbiprof - command-line client for DBI::ProfileData - -=head1 SYNOPSIS - -See a report of the ten queries with the longest total runtime in the -profile dump file F: - - dbiprof prof1.out - -See the top 10 most frequently run queries in the profile file -F (the default): - - dbiprof --sort count - -See the same report with 15 entries: - - dbiprof --sort count --number 15 - -=head1 DESCRIPTION - -This tool is a command-line client for the DBI::ProfileData. It -allows you to analyze the profile data file produced by -DBI::ProfileDumper and produce various useful reports. - -=head1 OPTIONS - -This program accepts the following options: - -=over 4 - -=item --number N - -Produce this many items in the report. Defaults to 10. If set to -"all" then all results are shown. - -=item --sort field - -Sort results by the given field. Sorting by multiple fields isn't currently -supported (patches welcome). The available sort fields are: - -=over 4 - -=item total - -Sorts by total time run time across all runs. This is the default -sort. - -=item longest - -Sorts by the longest single run. - -=item count - -Sorts by total number of runs. - -=item first - -Sorts by the time taken in the first run. - -=item shortest - -Sorts by the shortest single run. - -=item key1 - -Sorts by the value of the first element in the Path, which should be numeric. -You can also sort by C and C. - -=back - -=item --reverse - -Reverses the selected sort. For example, to see a report of the -shortest overall time: - - dbiprof --sort total --reverse - -=item --match keyN=value - -Consider only items where the specified key matches the given value. -Keys are numbered from 1. For example, let's say you used a -DBI::Profile Path of: - - [ DBIprofile_Statement, DBIprofile_Methodname ] - -And called dbiprof as in: - - dbiprof --match key2=execute - -Your report would only show execute queries, leaving out prepares, -fetches, etc. - -If the value given starts and ends with slashes (C) then it will be -treated as a regular expression. For example, to only include SELECT -queries where key1 is the statement: - - dbiprof --match key1=/^SELECT/ - -By default the match expression is matched case-insensitively, but -this can be changed with the --case-sensitive option. - -=item --exclude keyN=value - -Remove items for where the specified key matches the given value. For -example, to exclude all prepare entries where key2 is the method name: - - dbiprof --exclude key2=prepare - -Like C<--match>, If the value given starts and ends with slashes -(C) then it will be treated as a regular expression. For example, -to exclude UPDATE queries where key1 is the statement: - - dbiprof --match key1=/^UPDATE/ - -By default the exclude expression is matched case-insensitively, but -this can be changed with the --case-sensitive option. - -=item --case-sensitive - -Using this option causes --match and --exclude to work -case-sensitively. Defaults to off. - -=item --delete - -Sets the C option to L which causes the -files to be deleted after reading. See L for more details. - -=item --dumpnodes - -Print the list of nodes in the form of a perl data structure. -Use the C<-sort> option if you want the list sorted. - -=item --version - -Print the dbiprof version number and exit. - -=back - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=head1 SEE ALSO - -L, -L, L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/dbiprof.PL b/dbLifeLog/DBI-1.641/dbiprof.PL deleted file mode 100644 index c220441..0000000 --- a/dbLifeLog/DBI-1.641/dbiprof.PL +++ /dev/null @@ -1,287 +0,0 @@ -# -*- perl -*- - -my $file = $ARGV[0] || 'dbiprof'; - -my $script = <<'SCRIPT'; -~startperl~ - -use strict; - -my $VERSION = sprintf("1.%06d", q$Revision$ =~ /(\d+)/o); - -use Data::Dumper; -use DBI::ProfileData; -use Getopt::Long; - -# default options -my $number = 10; -my $sort = 'total'; -my $filename = 'dbi.prof'; -my $reverse = 0; -my $case_sensitive = 0; -my (%match, %exclude); - -# get options from command line -GetOptions( - 'version' => sub { die "dbiprof $VERSION\n" }, - 'help' => sub { exit usage() }, - 'number=i' => \$number, - 'sort=s' => \$sort, - 'dumpnodes!' => \my $dumpnodes, - 'reverse' => \$reverse, - 'match=s' => \%match, - 'exclude=s' => \%exclude, - 'case-sensitive' => \$case_sensitive, - 'delete!' => \my $opt_delete, -) or exit usage(); - -sub usage { - print <new( - Files => \@files, - DeleteFiles => $opt_delete, - ); -}; -die "Unable to load profile data: $@\n" if $@; - -if (%match) { # handle matches - while (my ($key, $val) = each %match) { - if ($val =~ m!^/(.+)/$!) { - $val = $case_sensitive ? qr/$1/ : qr/$1/i; - } - $prof->match($key, $val, case_sensitive => $case_sensitive); - } -} - -if (%exclude) { # handle excludes - while (my ($key, $val) = each %exclude) { - if ($val =~ m!^/(.+)/$!) { - $val = $case_sensitive ? qr/$1/ : qr/$1/i; - } - $prof->exclude($key, $val, case_sensitive => $case_sensitive); - } -} - -# sort the data -$prof->sort(field => $sort, reverse => $reverse); - -# all done, print it out -if ($dumpnodes) { - $Data::Dumper::Indent = 1; - $Data::Dumper::Terse = 1; - $Data::Dumper::Useqq = 1; - $Data::Dumper::Deparse = 0; - print Dumper($prof->nodes); -} -else { - print $prof->report(number => $number); -} -exit 0; - -__END__ - -=head1 NAME - -dbiprof - command-line client for DBI::ProfileData - -=head1 SYNOPSIS - -See a report of the ten queries with the longest total runtime in the -profile dump file F: - - dbiprof prof1.out - -See the top 10 most frequently run queries in the profile file -F (the default): - - dbiprof --sort count - -See the same report with 15 entries: - - dbiprof --sort count --number 15 - -=head1 DESCRIPTION - -This tool is a command-line client for the DBI::ProfileData. It -allows you to analyze the profile data file produced by -DBI::ProfileDumper and produce various useful reports. - -=head1 OPTIONS - -This program accepts the following options: - -=over 4 - -=item --number N - -Produce this many items in the report. Defaults to 10. If set to -"all" then all results are shown. - -=item --sort field - -Sort results by the given field. Sorting by multiple fields isn't currently -supported (patches welcome). The available sort fields are: - -=over 4 - -=item total - -Sorts by total time run time across all runs. This is the default -sort. - -=item longest - -Sorts by the longest single run. - -=item count - -Sorts by total number of runs. - -=item first - -Sorts by the time taken in the first run. - -=item shortest - -Sorts by the shortest single run. - -=item key1 - -Sorts by the value of the first element in the Path, which should be numeric. -You can also sort by C and C. - -=back - -=item --reverse - -Reverses the selected sort. For example, to see a report of the -shortest overall time: - - dbiprof --sort total --reverse - -=item --match keyN=value - -Consider only items where the specified key matches the given value. -Keys are numbered from 1. For example, let's say you used a -DBI::Profile Path of: - - [ DBIprofile_Statement, DBIprofile_Methodname ] - -And called dbiprof as in: - - dbiprof --match key2=execute - -Your report would only show execute queries, leaving out prepares, -fetches, etc. - -If the value given starts and ends with slashes (C) then it will be -treated as a regular expression. For example, to only include SELECT -queries where key1 is the statement: - - dbiprof --match key1=/^SELECT/ - -By default the match expression is matched case-insensitively, but -this can be changed with the --case-sensitive option. - -=item --exclude keyN=value - -Remove items for where the specified key matches the given value. For -example, to exclude all prepare entries where key2 is the method name: - - dbiprof --exclude key2=prepare - -Like C<--match>, If the value given starts and ends with slashes -(C) then it will be treated as a regular expression. For example, -to exclude UPDATE queries where key1 is the statement: - - dbiprof --match key1=/^UPDATE/ - -By default the exclude expression is matched case-insensitively, but -this can be changed with the --case-sensitive option. - -=item --case-sensitive - -Using this option causes --match and --exclude to work -case-sensitively. Defaults to off. - -=item --delete - -Sets the C option to L which causes the -files to be deleted after reading. See L for more details. - -=item --dumpnodes - -Print the list of nodes in the form of a perl data structure. -Use the C<-sort> option if you want the list sorted. - -=item --version - -Print the dbiprof version number and exit. - -=back - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=head1 SEE ALSO - -L, -L, L. - -=cut - -SCRIPT - - -require Config; -my $config = {}; -$config->{'startperl'} = $Config::Config{'startperl'}; - -$script =~ s/\~(\w+)\~/$config->{$1}/eg; -if (!(open(FILE, ">$file")) || - !(print FILE $script) || - !(close(FILE))) { - die "Error while writing $file: $!\n"; -} -chmod 0755, $file; -print "Extracted $file from ",__FILE__," with variable substitutions.\n"; - -# syntax check resulting file, but only for developers -exit 1 if -d ".svn"|| -d ".git" and system($^X, '-wc', '-Mblib', $file) != 0; - diff --git a/dbLifeLog/DBI-1.641/dbiproxy b/dbLifeLog/DBI-1.641/dbiproxy deleted file mode 100755 index c705764..0000000 --- a/dbLifeLog/DBI-1.641/dbiproxy +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/perl - -use strict; - -my $VERSION = sprintf("1.%06d", q$Revision$ =~ /(\d+)/o); - -my $arg_test = shift(@ARGV) if $ARGV[0] eq '--test'; -$ENV{DBI_TRACE} = shift(@ARGV) || 2 if $ARGV[0] =~ s/^--dbitrace=?//; - -require DBI::ProxyServer; - -# XXX these should probably be moved into DBI::ProxyServer -delete $ENV{IFS}; -delete $ENV{CDPATH}; -delete $ENV{ENV}; -delete $ENV{BASH_ENV}; - -if ($arg_test) { - require RPC::PlServer::Test; - @DBI::ProxyServer::ISA = qw(RPC::PlServer::Test DBI); -} - -DBI::ProxyServer::main(@ARGV); - -exit(0); - - -__END__ - -=head1 NAME - -dbiproxy - A proxy server for the DBD::Proxy driver - -=head1 SYNOPSIS - - dbiproxy --localport= - - -=head1 DESCRIPTION - -This tool is just a front end for the DBI::ProxyServer package. All it -does is picking options from the command line and calling -DBI::ProxyServer::main(). See L for details. - -Available options include: - -=over 4 - -=item B<--chroot=dir> - -(UNIX only) After doing a bind(), change root directory to the given -directory by doing a chroot(). This is useful for security, but it -restricts the environment a lot. For example, you need to load DBI -drivers in the config file or you have to create hard links to Unix -sockets, if your drivers are using them. For example, with MySQL, a -config file might contain the following lines: - - my $rootdir = '/var/dbiproxy'; - my $unixsockdir = '/tmp'; - my $unixsockfile = 'mysql.sock'; - foreach $dir ($rootdir, "$rootdir$unixsockdir") { - mkdir 0755, $dir; - } - link("$unixsockdir/$unixsockfile", - "$rootdir$unixsockdir/$unixsockfile"); - require DBD::mysql; - - { - 'chroot' => $rootdir, - ... - } - -If you don't know chroot(), think of an FTP server where you can see a -certain directory tree only after logging in. See also the --group and ---user options. - -=item B<--configfile=file> - -Config files are assumed to return a single hash ref that overrides the -arguments of the new method. However, command line arguments in turn take -precedence over the config file. See the "CONFIGURATION FILE" section -in the L documentation for details on the config file. - -=item B<--debug> - -Turn debugging mode on. Mainly this asserts that logging messages of -level "debug" are created. - -=item B<--facility=mode> - -(UNIX only) Facility to use for L. The default is -B. - -=item B<--group=gid> - -After doing a bind(), change the real and effective GID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --user option. - -GID's can be passed as group names or numeric values. - -=item B<--localaddr=ip> - -By default a daemon is listening to any IP number that a machine -has. This attribute allows one to restrict the server to the given -IP number. - -=item B<--localport=port> - -This attribute sets the port on which the daemon is listening. It -must be given somehow, as there's no default. - -=item B<--logfile=file> - -Be default logging messages will be written to the syslog (Unix) or -to the event log (Windows NT). On other operating systems you need to -specify a log file. The special value "STDERR" forces logging to -stderr. See L for details. - -=item B<--mode=modename> - -The server can run in three different modes, depending on the environment. - -If you are running Perl 5.005 and did compile it for threads, then the -server will create a new thread for each connection. The thread will -execute the server's Run() method and then terminate. This mode is the -default, you can force it with "--mode=threads". - -If threads are not available, but you have a working fork(), then the -server will behave similar by creating a new process for each connection. -This mode will be used automatically in the absence of threads or if -you use the "--mode=fork" option. - -Finally there's a single-connection mode: If the server has accepted a -connection, he will enter the Run() method. No other connections are -accepted until the Run() method returns (if the client disconnects). -This operation mode is useful if you have neither threads nor fork(), -for example on the Macintosh. For debugging purposes you can force this -mode with "--mode=single". - -=item B<--pidfile=file> - -(UNIX only) If this option is present, a PID file will be created at the -given location. Default is to not create a pidfile. - -=item B<--user=uid> - -After doing a bind(), change the real and effective UID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --group and the --chroot options. - -UID's can be passed as group names or numeric values. - -=item B<--version> - -Suppresses startup of the server; instead the version string will -be printed and the program exits immediately. - -=back - - -=head1 AUTHOR - - Copyright (c) 1997 Jochen Wiedmann - Am Eisteich 9 - 72555 Metzingen - Germany - - Email: joe@ispsoft.de - Phone: +49 7123 14881 - -The DBI::ProxyServer module is free software; you can redistribute it -and/or modify it under the same terms as Perl itself. In particular -permission is granted to Tim Bunce for distributing this as a part of -the DBI. - - -=head1 SEE ALSO - -L, L, L - -=cut diff --git a/dbLifeLog/DBI-1.641/dbiproxy.PL b/dbLifeLog/DBI-1.641/dbiproxy.PL deleted file mode 100644 index c2d93d0..0000000 --- a/dbLifeLog/DBI-1.641/dbiproxy.PL +++ /dev/null @@ -1,208 +0,0 @@ -# -*- perl -*- - -my $file = $ARGV[0] || 'dbiproxy'; - -my $script = <<'SCRIPT'; -~startperl~ - -use strict; - -my $VERSION = sprintf("1.%06d", q$Revision$ =~ /(\d+)/o); - -my $arg_test = shift(@ARGV) if $ARGV[0] eq '--test'; -$ENV{DBI_TRACE} = shift(@ARGV) || 2 if $ARGV[0] =~ s/^--dbitrace=?//; - -require DBI::ProxyServer; - -# XXX these should probably be moved into DBI::ProxyServer -delete $ENV{IFS}; -delete $ENV{CDPATH}; -delete $ENV{ENV}; -delete $ENV{BASH_ENV}; - -if ($arg_test) { - require RPC::PlServer::Test; - @DBI::ProxyServer::ISA = qw(RPC::PlServer::Test DBI); -} - -DBI::ProxyServer::main(@ARGV); - -exit(0); - - -__END__ - -=head1 NAME - -dbiproxy - A proxy server for the DBD::Proxy driver - -=head1 SYNOPSIS - - dbiproxy --localport= - - -=head1 DESCRIPTION - -This tool is just a front end for the DBI::ProxyServer package. All it -does is picking options from the command line and calling -DBI::ProxyServer::main(). See L for details. - -Available options include: - -=over 4 - -=item B<--chroot=dir> - -(UNIX only) After doing a bind(), change root directory to the given -directory by doing a chroot(). This is useful for security, but it -restricts the environment a lot. For example, you need to load DBI -drivers in the config file or you have to create hard links to Unix -sockets, if your drivers are using them. For example, with MySQL, a -config file might contain the following lines: - - my $rootdir = '/var/dbiproxy'; - my $unixsockdir = '/tmp'; - my $unixsockfile = 'mysql.sock'; - foreach $dir ($rootdir, "$rootdir$unixsockdir") { - mkdir 0755, $dir; - } - link("$unixsockdir/$unixsockfile", - "$rootdir$unixsockdir/$unixsockfile"); - require DBD::mysql; - - { - 'chroot' => $rootdir, - ... - } - -If you don't know chroot(), think of an FTP server where you can see a -certain directory tree only after logging in. See also the --group and ---user options. - -=item B<--configfile=file> - -Config files are assumed to return a single hash ref that overrides the -arguments of the new method. However, command line arguments in turn take -precedence over the config file. See the "CONFIGURATION FILE" section -in the L documentation for details on the config file. - -=item B<--debug> - -Turn debugging mode on. Mainly this asserts that logging messages of -level "debug" are created. - -=item B<--facility=mode> - -(UNIX only) Facility to use for L. The default is -B. - -=item B<--group=gid> - -After doing a bind(), change the real and effective GID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --user option. - -GID's can be passed as group names or numeric values. - -=item B<--localaddr=ip> - -By default a daemon is listening to any IP number that a machine -has. This attribute allows one to restrict the server to the given -IP number. - -=item B<--localport=port> - -This attribute sets the port on which the daemon is listening. It -must be given somehow, as there's no default. - -=item B<--logfile=file> - -Be default logging messages will be written to the syslog (Unix) or -to the event log (Windows NT). On other operating systems you need to -specify a log file. The special value "STDERR" forces logging to -stderr. See L for details. - -=item B<--mode=modename> - -The server can run in three different modes, depending on the environment. - -If you are running Perl 5.005 and did compile it for threads, then the -server will create a new thread for each connection. The thread will -execute the server's Run() method and then terminate. This mode is the -default, you can force it with "--mode=threads". - -If threads are not available, but you have a working fork(), then the -server will behave similar by creating a new process for each connection. -This mode will be used automatically in the absence of threads or if -you use the "--mode=fork" option. - -Finally there's a single-connection mode: If the server has accepted a -connection, he will enter the Run() method. No other connections are -accepted until the Run() method returns (if the client disconnects). -This operation mode is useful if you have neither threads nor fork(), -for example on the Macintosh. For debugging purposes you can force this -mode with "--mode=single". - -=item B<--pidfile=file> - -(UNIX only) If this option is present, a PID file will be created at the -given location. Default is to not create a pidfile. - -=item B<--user=uid> - -After doing a bind(), change the real and effective UID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --group and the --chroot options. - -UID's can be passed as group names or numeric values. - -=item B<--version> - -Suppresses startup of the server; instead the version string will -be printed and the program exits immediately. - -=back - - -=head1 AUTHOR - - Copyright (c) 1997 Jochen Wiedmann - Am Eisteich 9 - 72555 Metzingen - Germany - - Email: joe@ispsoft.de - Phone: +49 7123 14881 - -The DBI::ProxyServer module is free software; you can redistribute it -and/or modify it under the same terms as Perl itself. In particular -permission is granted to Tim Bunce for distributing this as a part of -the DBI. - - -=head1 SEE ALSO - -L, L, L - -=cut -SCRIPT - - -require Config; -my $config = {}; -$config->{'startperl'} = $Config::Config{'startperl'}; - -$script =~ s/\~(\w+)\~/$config->{$1}/eg; -if (!(open(FILE, ">$file")) || - !(print FILE $script) || - !(close(FILE))) { - die "Error while writing $file: $!\n"; -} -chmod 0755, $file; -print "Extracted $file from ",__FILE__," with variable substitutions.\n"; - -# syntax check resulting file, but only for developers -exit 1 if -d ".svn" || -d ".git" and system($^X, '-wc', '-Mblib', $file) != 0; - diff --git a/dbLifeLog/DBI-1.641/dbivport.h b/dbLifeLog/DBI-1.641/dbivport.h deleted file mode 100644 index 77dd96b..0000000 --- a/dbLifeLog/DBI-1.641/dbivport.h +++ /dev/null @@ -1,52 +0,0 @@ -/* dbivport.h - - Provides macros that enable greater portability between DBI versions. - - This file should be *copied* and included in driver distributions - and #included into the source, after #include DBIXS.h - - New driver releases should include an updated copy of dbivport.h - from the most recent DBI release. -*/ - -#ifndef DBI_VPORT_H -#define DBI_VPORT_H - -#ifndef DBIh_SET_ERR_CHAR -/* Emulate DBIh_SET_ERR_CHAR - Only uses the err_i, errstr and state parameters. -*/ -#define DBIh_SET_ERR_CHAR(h, imp_xxh, err_c, err_i, errstr, state, method) \ - sv_setiv(DBIc_ERR(imp_xxh), err_i); \ - (state) ? (void)sv_setpv(DBIc_STATE(imp_xxh), state) : (void)SvOK_off(DBIc_STATE(imp_xxh)); \ - sv_setpv(DBIc_ERRSTR(imp_xxh), errstr) -#endif - -#ifndef DBIcf_Executed -#define DBIcf_Executed 0x080000 -#endif - -#ifndef DBIc_TRACE_LEVEL_MASK -#define DBIc_TRACE_LEVEL_MASK 0x0000000F -#define DBIc_TRACE_FLAGS_MASK 0xFFFFFF00 -#define DBIc_TRACE_SETTINGS(imp) (DBIc_DBISTATE(imp)->debug) -#define DBIc_TRACE_LEVEL(imp) (DBIc_TRACE_SETTINGS(imp) & DBIc_TRACE_LEVEL_MASK) -#define DBIc_TRACE_FLAGS(imp) (DBIc_TRACE_SETTINGS(imp) & DBIc_TRACE_FLAGS_MASK) -/* DBIc_TRACE_MATCHES - true if s1 'matches' s2 (c.f. trace_msg()) - DBIc_TRACE_MATCHES(foo, DBIc_TRACE_SETTINGS(imp)) -*/ -#define DBIc_TRACE_MATCHES(s1, s2) \ - ( ((s1 & DBIc_TRACE_LEVEL_MASK) >= (s2 & DBIc_TRACE_LEVEL_MASK)) \ - || ((s1 & DBIc_TRACE_FLAGS_MASK) & (s2 & DBIc_TRACE_FLAGS_MASK)) ) -/* DBIc_TRACE - true if flags match & DBI level>=flaglevel, or if DBI level>level - DBIc_TRACE(imp, 0, 0, 4) = if level >= 4 - DBIc_TRACE(imp, DBDtf_FOO, 2, 4) = if tracing DBDtf_FOO & level>=2 or level>=4 - DBIc_TRACE(imp, DBDtf_FOO, 2, 0) = as above but never trace just due to level -*/ -#define DBIc_TRACE(imp, flags, flaglevel, level) \ - ( (flags && (DBIc_TRACE_FLAGS(imp) & flags) && (DBIc_TRACE_LEVEL(imp) >= flaglevel)) \ - || (level && DBIc_TRACE_LEVEL(imp) >= level) ) -#endif - - -#endif /* !DBI_VPORT_H */ diff --git a/dbLifeLog/DBI-1.641/dbixs_rev.h b/dbLifeLog/DBI-1.641/dbixs_rev.h deleted file mode 100644 index 83ff5dc..0000000 --- a/dbLifeLog/DBI-1.641/dbixs_rev.h +++ /dev/null @@ -1,3 +0,0 @@ -/* Fri Jul 13 13:32:02 2012 */ -/* Mixed revision working copy (15349:15353) */ -#define DBIXS_REVISION 15349 diff --git a/dbLifeLog/DBI-1.641/dbixs_rev.pl b/dbLifeLog/DBI-1.641/dbixs_rev.pl deleted file mode 100644 index 9e83eb1..0000000 --- a/dbLifeLog/DBI-1.641/dbixs_rev.pl +++ /dev/null @@ -1,51 +0,0 @@ -#!perl -w -use strict; - -my $dbixs_rev_file = "dbixs_rev.h"; - -my $is_make_dist; -my $svnversion; - -if (is_dbi_svn_dir(".")) { - $svnversion = `svnversion -n`; -} -elsif (is_dbi_svn_dir("..")) { - # presumably we're in a subdirectory because the user is doing a 'make dist' - $svnversion = `svnversion -n ..`; - $is_make_dist = 1; -} -else { - # presumably we're being run by an end-user because their file timestamps - # got messed up - print "Skipping regeneration of $dbixs_rev_file\n"; - utime(time(), time(), $dbixs_rev_file); # update modification time - exit 0; -} - -my @warn; -die "Neither current directory nor parent directory are an svn working copy\n" - unless $svnversion and $svnversion =~ m/^\d+/; -push @warn, "Mixed revision working copy ($svnversion:$1)" - if $svnversion =~ s/:(\d+)//; -push @warn, "Code modified since last checkin" - if $svnversion =~ s/[MS]+$//; -warn "$dbixs_rev_file warning: $_\n" for @warn; -die "$0 failed\n" if $is_make_dist && @warn; - -write_header($dbixs_rev_file, DBIXS_REVISION => $svnversion, \@warn); - -sub write_header { - my ($file, $macro, $version, $comments_ref) = @_; - open my $fh, ">$file" or die "Can't open $file: $!\n"; - unshift @$comments_ref, scalar localtime(time); - print $fh "/* $_ */\n" for @$comments_ref; - print $fh "#define $macro $version\n"; - close $fh or die "Error closing $file: $!\n"; - print "Wrote $macro $version to $file\n"; -} - -sub is_dbi_svn_dir { - my ($dir) = @_; - return (-d "$dir/.svn" && -f "$dir/MANIFEST.SKIP"); -} - diff --git a/dbLifeLog/DBI-1.641/ex/corogofer.pl b/dbLifeLog/DBI-1.641/ex/corogofer.pl deleted file mode 100644 index 8baa587..0000000 --- a/dbLifeLog/DBI-1.641/ex/corogofer.pl +++ /dev/null @@ -1,32 +0,0 @@ -#!perl - -use strict; -use warnings; -use Time::HiRes qw(time); - -BEGIN { $ENV{PERL_ANYEVENT_STRICT} = 1; $ENV{PERL_ANYEVENT_VERBOSE} = 1; } - -use AnyEvent; - -BEGIN { $ENV{DBI_TRACE} = 0; $ENV{DBI_PUREPERL} = 0; $ENV{DBI_GOFER_TRACE} = 0; $ENV{DBD_GOFER_TRACE} = 0; }; - -use DBI; - -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=corostream'; - -my $ticker = AnyEvent->timer( after => 0, interval => 0.1, cb => sub { - warn sprintf "-tick- %.2f\n", time -} ); - -warn "connecting...\n"; -my $dbh = DBI->connect("dbi:NullP:"); -warn "...connected\n"; - -for (1..5) { - warn "entering DBI...\n"; - $dbh->do("sleep 0.3"); # pseudo-sql understood by the DBD::NullP driver - warn "...returned\n"; -} - -warn "done."; - diff --git a/dbLifeLog/DBI-1.641/ex/perl_dbi_nulls_test.pl b/dbLifeLog/DBI-1.641/ex/perl_dbi_nulls_test.pl deleted file mode 100644 index fbef238..0000000 --- a/dbLifeLog/DBI-1.641/ex/perl_dbi_nulls_test.pl +++ /dev/null @@ -1,176 +0,0 @@ -#! /usr/bin/perl -w - -# This script checks which style of WHERE clause(s) will support both -# null and non-null values. Refer to the NULL Values sub-section -# of the "Placeholders and Bind Values" section in the DBI -# documention for more information on this issue. The clause styles -# and their numbering (0-6) map directly to the examples in the -# documentation. -# -# To use this script: -# -# 1) If you are not using the DBI_DSN env variable, then update the -# connect method arguments to support your database engine and -# database, and remove the nearby check for DBI_DSN. -# 2) Set PrintError to 1 in the connect method if you want see the -# engine's reason WHY your engine won't support a particular -# style. -# 3) If your database does not support NULL columns by default -# (e.g. Sybase) find and edit the CREATE TABLE statement -# accordingly. -# 4) To properly test style #5, you need the capability to create the -# stored procedure SP_ISNULL that acts as a function: it tests its -# argument and returns 1 if it is null, 0 otherwise. For example, -# using Informix IDS engine, a definition would look like: -# -# CREATE PROCEDURE SP_ISNULL (arg VARCHAR(32)) RETURNING INTEGER; -# IF arg IS NULL THEN RETURN 1; -# ELSE RETURN 0; -# END IF; -# END PROCEDURE; -# -# Warning: This script will attempt to create a table named by the -# $tablename variable (default dbi__null_test_tmp) and WILL DESTROY -# any pre-existing table so named. - -use strict; -use DBI; - -# The array represents the values that will be stored in the char column of our table. -# One array element per row. -# We expect the non-null test to return row 3 (Marge) -# and the null test to return rows 2 and 4 (the undefs). - -my $homer = "Homer"; -my $marge = "Marge"; - -my @char_column_values = ( - $homer, # 1 - undef, # 2 - $marge, # 3 - undef, # 4 -); - -# Define the SQL statements with the various WHERE clause styles we want to test -# and the parameters we'll substitute. - -my @select_clauses = -( - {clause=>qq{WHERE mycol = ?}, nonnull=>[$marge], null=>[undef]}, - {clause=>qq{WHERE NVL(mycol, '-') = NVL(?, '-')}, nonnull=>[$marge], null=>[undef]}, - {clause=>qq{WHERE ISNULL(mycol, '-') = ISNULL(?, '-')}, nonnull=>[$marge], null=>[undef]}, - {clause=>qq{WHERE DECODE(mycol, ?, 1, 0) = 1}, nonnull=>[$marge], null=>[undef]}, - {clause=>qq{WHERE mycol = ? OR (mycol IS NULL AND ? IS NULL)}, nonnull=>[$marge,$marge], null=>[undef,undef]}, - {clause=>qq{WHERE mycol = ? OR (mycol IS NULL AND SP_ISNULL(?) = 1)}, nonnull=>[$marge,$marge], null=>[undef,undef]}, - {clause=>qq{WHERE mycol = ? OR (mycol IS NULL AND ? = 1)}, nonnull=>[$marge,0], null=>[undef,1]}, -); - -# This is the table we'll create and use for these tests. -# If it exists, we'll DESTROY it too. So the name must be obscure. - -my $tablename = "dbi__null_test_tmp"; - -# Remove this if you are not using the DBI_DSN env variable, -# and update the connect statement below. - -die "DBI_DSN environment variable not defined" - unless $ENV{DBI_DSN}; - -my $dbh = DBI->connect(undef, undef, undef, - { - RaiseError => 0, - PrintError => 1 - } -) || die DBI->errstr; - -printf "Using %s, db version: %s\n", $ENV{DBI_DSN} || "connect arguments", $dbh->get_info(18) || "(unknown)"; - -my $sth; -my @ok; - -print "=> Drop table '$tablename', if it already exists...\n"; -do { local $dbh->{PrintError}=0; $dbh->do("DROP TABLE $tablename"); }; - -print "=> Create table '$tablename'...\n"; -$dbh->do("CREATE TABLE $tablename (myid int NOT NULL, mycol char(5))"); -# Use this if your database does not support NULL columns by default: -#$dbh->do("CREATE TABLE $tablename (myid int NOT NULL, mycol char(5) NULL)"); - -print "=> Insert 4 rows into the table...\n"; - -$sth = $dbh->prepare("INSERT INTO $tablename (myid, mycol) VALUES (?,?)"); -for my $i (0..$#char_column_values) -{ - my $val = $char_column_values[$i]; - printf " Inserting values (%d, %s)\n", $i+1, $dbh->quote($val); - $sth->execute($i+1, $val); -} -print "(Driver bug: statement handle should not be Active after an INSERT.)\n" - if $sth->{Active}; - -# Run the tests... - -for my $i (0..$#select_clauses) -{ - my $sel = $select_clauses[$i]; - print "\n=> Testing clause style $i: ".$sel->{clause}."...\n"; - - $sth = $dbh->prepare("SELECT myid,mycol FROM $tablename ".$sel->{clause}) - or next; - - print " Selecting row with $marge\n"; - $sth->execute(@{$sel->{nonnull}}) - or next; - my $r1 = $sth->fetchall_arrayref(); - my $n1_rows = $sth->rows; - my $n1 = @$r1; - - print " Selecting rows with NULL\n"; - $sth->execute(@{$sel->{null}}) - or next; - my $r2 = $sth->fetchall_arrayref(); - my $n2_rows = $sth->rows; - my $n2 = @$r2; - - # Complain a bit... - - print "\n=>Your DBD driver doesn't support the 'rows' method very well.\n\n" - unless ($n1_rows == $n1 && $n2_rows == $n2); - - # Did we get back the expected "n"umber of rows? - # Did we get back the specific "r"ows we expected as identifed by the myid column? - - if ( $n1 == 1 # one row for Marge - && $n2 == 2 # two rows for nulls - && $r1->[0][0] == 3 # Marge is myid 3 - && $r2->[0][0] == 2 # NULL for myid 2 - && $r2->[1][0] == 4 # NULL for myid 4 - ) { - print "=> WHERE clause style $i is supported.\n"; - push @ok, "\tStyle $i: ".$sel->{clause}; - } - else - { - print "=> WHERE clause style $i returned incorrect results.\n"; - if ($n1 > 0 || $n2 > 0) - { - print " Non-NULL test rows returned these row ids: ". - join(", ", map { $r1->[$_][0] } (0..$#{$r1}))."\n"; - print " The NULL test rows returned these row ids: ". - join(", ", map { $r2->[$_][0] } (0..$#{$r2}))."\n"; - } - } -} - -$dbh->disconnect(); -print "\n"; -print "-" x 72, "\n"; -printf "%d styles are supported:\n", scalar @ok; -print "$_\n" for @ok; -print "-" x 72, "\n"; -print "\n"; -print "If these results don't match what's in the 'Placeholders and Bind Values'\n"; -print "section of the DBI documentation, or are for a database that not already\n"; -print "listed, please email the results to dbi-users\@perl.org. Thank you.\n"; - -exit 0; diff --git a/dbLifeLog/DBI-1.641/ex/profile.pl b/dbLifeLog/DBI-1.641/ex/profile.pl deleted file mode 100644 index 96df9ae..0000000 --- a/dbLifeLog/DBI-1.641/ex/profile.pl +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/perl -w - -use DBI; - -$dbh = DBI->connect('dbi:SQLite:dbname=ex_profile.db', '', '', { RaiseError => 1 }); - -$dbh->do("DROP TABLE IF EXISTS ex_profile"); -$dbh->do("CREATE TABLE ex_profile (a int)"); - - $dbh->do("INSERT INTO ex_profile (a) VALUES ($_)", undef) for 1..100; -#$dbh->do("INSERT INTO ex_profile (a) VALUES (?)", undef, $_) for 1..100; - -my $select_sql = "SELECT a FROM ex_profile"; - -$dbh->selectall_arrayref($select_sql); - -$dbh->selectall_hashref($select_sql, 'a'); - -my $sth = $dbh->prepare($select_sql); -$sth->execute; -while ( @row = $sth->fetchrow_array ) { -} - - -__DATA__ diff --git a/dbLifeLog/DBI-1.641/lib/Bundle/DBI.pm b/dbLifeLog/DBI-1.641/lib/Bundle/DBI.pm deleted file mode 100644 index 08bff92..0000000 --- a/dbLifeLog/DBI-1.641/lib/Bundle/DBI.pm +++ /dev/null @@ -1,52 +0,0 @@ -# -*- perl -*- - -package Bundle::DBI; - -use strict; -our $VERSION = "12.008696"; - -1; - -__END__ - -=head1 NAME - -Bundle::DBI - A bundle to install DBI and required modules. - -=head1 SYNOPSIS - - perl -MCPAN -e 'install Bundle::DBI' - -=head1 CONTENTS - -DBI - for to get to know thyself - -DBI::Shell 11.91 - the DBI command line shell - -Storable 2.06 - for DBD::Proxy, DBI::ProxyServer, DBD::Forward - -Net::Daemon 0.37 - for DBD::Proxy and DBI::ProxyServer - -RPC::PlServer 0.2016 - for DBD::Proxy and DBI::ProxyServer - -DBD::Multiplex 1.19 - treat multiple db handles as one - -=head1 DESCRIPTION - -This bundle includes all the modules used by the Perl Database -Interface (DBI) module, created by Tim Bunce. - -A I is a module that simply defines a collection of other -modules. It is used by the L module to automate the fetching, -building and installing of modules from the CPAN ftp archive sites. - -This bundle does not deal with the various database drivers (e.g. -DBD::Informix, DBD::Oracle etc), most of which require software from -sources other than CPAN. You'll need to fetch and build those drivers -yourself. - -=head1 AUTHORS - -Jonathan Leffler, Jochen Wiedmann and Tim Bunce. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/DBM.pm b/dbLifeLog/DBI-1.641/lib/DBD/DBM.pm deleted file mode 100644 index a8fe8b9..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/DBM.pm +++ /dev/null @@ -1,1454 +0,0 @@ -####################################################################### -# -# DBD::DBM - a DBI driver for DBM files -# -# Copyright (c) 2004 by Jeff Zucker < jzucker AT cpan.org > -# Copyright (c) 2010-2013 by Jens Rehsack & H.Merijn Brand -# -# All rights reserved. -# -# You may freely distribute and/or modify this module under the terms -# of either the GNU General Public License (GPL) or the Artistic License, -# as specified in the Perl README file. -# -# USERS - see the pod at the bottom of this file -# -# DBD AUTHORS - see the comments in the code -# -####################################################################### -require 5.008; -use strict; - -################# -package DBD::DBM; -################# -use base qw( DBD::File ); -use vars qw($VERSION $ATTRIBUTION $drh $methods_already_installed); -$VERSION = '0.08'; -$ATTRIBUTION = 'DBD::DBM by Jens Rehsack'; - -# no need to have driver() unless you need private methods -# -sub driver ($;$) -{ - my ( $class, $attr ) = @_; - return $drh if ($drh); - - # do the real work in DBD::File - # - $attr->{Attribution} = 'DBD::DBM by Jens Rehsack'; - $drh = $class->SUPER::driver($attr); - - # install private methods - # - # this requires that dbm_ (or foo_) be a registered prefix - # but you can write private methods before official registration - # by hacking the $dbd_prefix_registry in a private copy of DBI.pm - # - unless ( $methods_already_installed++ ) - { - DBD::DBM::st->install_method('dbm_schema'); - } - - return $drh; -} - -sub CLONE -{ - undef $drh; -} - -##################### -package DBD::DBM::dr; -##################### -$DBD::DBM::dr::imp_data_size = 0; -@DBD::DBM::dr::ISA = qw(DBD::File::dr); - -# you could put some :dr private methods here - -# you may need to over-ride some DBD::File::dr methods here -# but you can probably get away with just letting it do the work -# in most cases - -##################### -package DBD::DBM::db; -##################### -$DBD::DBM::db::imp_data_size = 0; -@DBD::DBM::db::ISA = qw(DBD::File::db); - -use Carp qw/carp/; - -sub validate_STORE_attr -{ - my ( $dbh, $attrib, $value ) = @_; - - if ( $attrib eq "dbm_ext" or $attrib eq "dbm_lockfile" ) - { - ( my $newattrib = $attrib ) =~ s/^dbm_/f_/g; - carp "Attribute '$attrib' is depreciated, use '$newattrib' instead" if ($^W); - $attrib = $newattrib; - } - - return $dbh->SUPER::validate_STORE_attr( $attrib, $value ); -} - -sub validate_FETCH_attr -{ - my ( $dbh, $attrib ) = @_; - - if ( $attrib eq "dbm_ext" or $attrib eq "dbm_lockfile" ) - { - ( my $newattrib = $attrib ) =~ s/^dbm_/f_/g; - carp "Attribute '$attrib' is depreciated, use '$newattrib' instead" if ($^W); - $attrib = $newattrib; - } - - return $dbh->SUPER::validate_FETCH_attr($attrib); -} - -sub set_versions -{ - my $this = $_[0]; - $this->{dbm_version} = $DBD::DBM::VERSION; - return $this->SUPER::set_versions(); -} - -sub init_valid_attributes -{ - my $dbh = shift; - - # define valid private attributes - # - # attempts to set non-valid attrs in connect() or - # with $dbh->{attr} will throw errors - # - # the attrs here *must* start with dbm_ or foo_ - # - # see the STORE methods below for how to check these attrs - # - $dbh->{dbm_valid_attrs} = { - dbm_type => 1, # the global DBM type e.g. SDBM_File - dbm_mldbm => 1, # the global MLDBM serializer - dbm_cols => 1, # the global column names - dbm_version => 1, # verbose DBD::DBM version - dbm_store_metadata => 1, # column names, etc. - dbm_berkeley_flags => 1, # for BerkeleyDB - dbm_valid_attrs => 1, # DBD::DBM::db valid attrs - dbm_readonly_attrs => 1, # DBD::DBM::db r/o attrs - dbm_meta => 1, # DBD::DBM public access for f_meta - dbm_tables => 1, # DBD::DBM public access for f_meta - }; - $dbh->{dbm_readonly_attrs} = { - dbm_version => 1, # verbose DBD::DBM version - dbm_valid_attrs => 1, # DBD::DBM::db valid attrs - dbm_readonly_attrs => 1, # DBD::DBM::db r/o attrs - dbm_meta => 1, # DBD::DBM public access for f_meta - }; - - $dbh->{dbm_meta} = "dbm_tables"; - - return $dbh->SUPER::init_valid_attributes(); -} - -sub init_default_attributes -{ - my ( $dbh, $phase ) = @_; - - $dbh->SUPER::init_default_attributes($phase); - $dbh->{f_lockfile} = '.lck'; - - return $dbh; -} - -sub get_dbm_versions -{ - my ( $dbh, $table ) = @_; - $table ||= ''; - - my $meta; - my $class = $dbh->{ImplementorClass}; - $class =~ s/::db$/::Table/; - $table and ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); - $meta or ( $meta = {} and $class->bootstrap_table_meta( $dbh, $meta, $table ) ); - - my $dver; - my $dtype = $meta->{dbm_type}; - eval { - $dver = $meta->{dbm_type}->VERSION(); - - # *) when we're still alive here, everything went ok - no need to check for $@ - $dtype .= " ($dver)"; - }; - if ( $meta->{dbm_mldbm} ) - { - $dtype .= ' + MLDBM'; - eval { - $dver = MLDBM->VERSION(); - $dtype .= " ($dver)"; # (*) - }; - eval { - my $ser_class = "MLDBM::Serializer::" . $meta->{dbm_mldbm}; - my $ser_mod = $ser_class; - $ser_mod =~ s|::|/|g; - $ser_mod .= ".pm"; - require $ser_mod; - $dver = $ser_class->VERSION(); - $dtype .= ' + ' . $ser_class; # (*) - $dver and $dtype .= " ($dver)"; # (*) - }; - } - return sprintf( "%s using %s", $dbh->{dbm_version}, $dtype ); -} - -# you may need to over-ride some DBD::File::db methods here -# but you can probably get away with just letting it do the work -# in most cases - -##################### -package DBD::DBM::st; -##################### -$DBD::DBM::st::imp_data_size = 0; -@DBD::DBM::st::ISA = qw(DBD::File::st); - -sub FETCH -{ - my ( $sth, $attr ) = @_; - - if ( $attr eq "NULLABLE" ) - { - my @colnames = $sth->sql_get_colnames(); - - # XXX only BerkeleyDB fails having NULL values for non-MLDBM databases, - # none accept it for key - but it requires more knowledge between - # queries and tables storage to return fully correct information - $attr eq "NULLABLE" and return [ map { 0 } @colnames ]; - } - - return $sth->SUPER::FETCH($attr); -} # FETCH - -sub dbm_schema -{ - my ( $sth, $tname ) = @_; - return $sth->set_err( $DBI::stderr, 'No table name supplied!' ) unless $tname; - my $tbl_meta = $sth->{Database}->func( $tname, "f_schema", "get_sql_engine_meta" ) - or return $sth->set_err( $sth->{Database}->err(), $sth->{Database}->errstr() ); - return $tbl_meta->{$tname}->{f_schema}; -} -# you could put some :st private methods here - -# you may need to over-ride some DBD::File::st methods here -# but you can probably get away with just letting it do the work -# in most cases - -############################ -package DBD::DBM::Statement; -############################ - -@DBD::DBM::Statement::ISA = qw(DBD::File::Statement); - -######################## -package DBD::DBM::Table; -######################## -use Carp; -use Fcntl; - -@DBD::DBM::Table::ISA = qw(DBD::File::Table); - -my $dirfext = $^O eq 'VMS' ? '.sdbm_dir' : '.dir'; - -my %reset_on_modify = ( - dbm_type => "dbm_tietype", - dbm_mldbm => "dbm_tietype", - ); -__PACKAGE__->register_reset_on_modify( \%reset_on_modify ); - -my %compat_map = ( - ( map { $_ => "dbm_$_" } qw(type mldbm store_metadata) ), - dbm_ext => 'f_ext', - dbm_file => 'f_file', - dbm_lockfile => ' f_lockfile', - ); -__PACKAGE__->register_compat_map( \%compat_map ); - -sub bootstrap_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_; - - $meta->{dbm_type} ||= $dbh->{dbm_type} || 'SDBM_File'; - $meta->{dbm_mldbm} ||= $dbh->{dbm_mldbm} if ( $dbh->{dbm_mldbm} ); - $meta->{dbm_berkeley_flags} ||= $dbh->{dbm_berkeley_flags}; - - defined $meta->{f_ext} - or $meta->{f_ext} = $dbh->{f_ext}; - unless ( defined( $meta->{f_ext} ) ) - { - my $ext; - if ( $meta->{dbm_type} eq 'SDBM_File' or $meta->{dbm_type} eq 'ODBM_File' ) - { - $ext = '.pag/r'; - } - elsif ( $meta->{dbm_type} eq 'NDBM_File' ) - { - # XXX NDBM_File on FreeBSD (and elsewhere?) may actually be Berkeley - # behind the scenes and so create a single .db file. - if ( $^O =~ /bsd/i or lc($^O) eq 'darwin' ) - { - $ext = '.db/r'; - } - elsif ( $^O eq 'SunOS' or $^O eq 'Solaris' or $^O eq 'AIX' ) - { - $ext = '.pag/r'; # here it's implemented like dbm - just a bit improved - } - # else wrapped GDBM - } - defined($ext) and $meta->{f_ext} = $ext; - } - - $self->SUPER::bootstrap_table_meta( $dbh, $meta, $table ); -} - -sub init_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_; - - $meta->{f_dontopen} = 1; - - unless ( defined( $meta->{dbm_tietype} ) ) - { - my $tie_type = $meta->{dbm_type}; - $INC{"$tie_type.pm"} or require "$tie_type.pm"; - $tie_type eq 'BerkeleyDB' and $tie_type = 'BerkeleyDB::Hash'; - - if ( $meta->{dbm_mldbm} ) - { - $INC{"MLDBM.pm"} or require "MLDBM.pm"; - $meta->{dbm_usedb} = $tie_type; - $tie_type = 'MLDBM'; - } - - $meta->{dbm_tietype} = $tie_type; - } - - unless ( defined( $meta->{dbm_store_metadata} ) ) - { - my $store = $dbh->{dbm_store_metadata}; - defined($store) or $store = 1; - $meta->{dbm_store_metadata} = $store; - } - - unless ( defined( $meta->{col_names} ) ) - { - defined( $dbh->{dbm_cols} ) and $meta->{col_names} = $dbh->{dbm_cols}; - } - - $self->SUPER::init_table_meta( $dbh, $meta, $table ); -} - -sub open_data -{ - my ( $className, $meta, $attrs, $flags ) = @_; - $className->SUPER::open_data( $meta, $attrs, $flags ); - - unless ( $flags->{dropMode} ) - { - # TIEING - # - # XXX allow users to pass in a pre-created tied object - # - my @tie_args; - if ( $meta->{dbm_type} eq 'BerkeleyDB' ) - { - my $DB_CREATE = BerkeleyDB::DB_CREATE(); - my $DB_RDONLY = BerkeleyDB::DB_RDONLY(); - my %tie_flags; - if ( my $f = $meta->{dbm_berkeley_flags} ) - { - defined( $f->{DB_CREATE} ) and $DB_CREATE = delete $f->{DB_CREATE}; - defined( $f->{DB_RDONLY} ) and $DB_RDONLY = delete $f->{DB_RDONLY}; - %tie_flags = %$f; - } - my $open_mode = $flags->{lockMode} || $flags->{createMode} ? $DB_CREATE : $DB_RDONLY; - @tie_args = ( - -Filename => $meta->{f_fqbn}, - -Flags => $open_mode, - %tie_flags - ); - } - else - { - my $open_mode = O_RDONLY; - $flags->{lockMode} and $open_mode = O_RDWR; - $flags->{createMode} and $open_mode = O_RDWR | O_CREAT | O_TRUNC; - - @tie_args = ( $meta->{f_fqbn}, $open_mode, 0666 ); - } - - if ( $meta->{dbm_mldbm} ) - { - $MLDBM::UseDB = $meta->{dbm_usedb}; - $MLDBM::Serializer = $meta->{dbm_mldbm}; - } - - $meta->{hash} = {}; - my $tie_class = $meta->{dbm_tietype}; - eval { tie %{ $meta->{hash} }, $tie_class, @tie_args }; - $@ and croak "Cannot tie(\%h $tie_class @tie_args): $@"; - -f $meta->{f_fqfn} or croak( "No such file: '" . $meta->{f_fqfn} . "'" ); - } - - unless ( $flags->{createMode} ) - { - my ( $meta_data, $schema, $col_names ); - if ( $meta->{dbm_store_metadata} ) - { - $meta_data = $col_names = $meta->{hash}->{"_metadata \0"}; - if ( $meta_data and $meta_data =~ m~(.+)~is ) - { - $schema = $col_names = $1; - $schema =~ s~.*(.+).*~$1~is; - $col_names =~ s~.*(.+).*~$1~is; - } - } - $col_names ||= $meta->{col_names} || [ 'k', 'v' ]; - $col_names = [ split /,/, $col_names ] if ( ref $col_names ne 'ARRAY' ); - if ( $meta->{dbm_store_metadata} and not $meta->{hash}->{"_metadata \0"} ) - { - $schema or $schema = ''; - $meta->{hash}->{"_metadata \0"} = - "" - . "$schema" - . "" - . join( ",", @{$col_names} ) - . "" - . ""; - } - - $meta->{schema} = $schema; - $meta->{col_names} = $col_names; - } -} - -# you must define drop -# it is called from execute of a SQL DROP statement -# -sub drop ($$) -{ - my ( $self, $data ) = @_; - my $meta = $self->{meta}; - $meta->{hash} and untie %{ $meta->{hash} }; - $self->SUPER::drop($data); - # XXX extra_files - -f $meta->{f_fqbn} . $dirfext - and $meta->{f_ext} eq '.pag/r' - and unlink( $meta->{f_fqbn} . $dirfext ); - return 1; -} - -# you must define fetch_row, it is called on all fetches; -# it MUST return undef when no rows are left to fetch; -# checking for $ary[0] is specific to hashes so you'll -# probably need some other kind of check for nothing-left. -# as Janis might say: "undef's just another word for -# nothing left to fetch" :-) -# -sub fetch_row ($$) -{ - my ( $self, $data ) = @_; - my $meta = $self->{meta}; - # fetch with %each - # - my @ary = each %{ $meta->{hash} }; - $meta->{dbm_store_metadata} - and $ary[0] - and $ary[0] eq "_metadata \0" - and @ary = each %{ $meta->{hash} }; - - my ( $key, $val ) = @ary; - unless ($key) - { - delete $self->{row}; - return; - } - my @row = ( ref($val) eq 'ARRAY' ) ? ( $key, @$val ) : ( $key, $val ); - $self->{row} = @row ? \@row : undef; - return wantarray ? @row : \@row; -} - -# you must define push_row except insert_new_row and update_specific_row is defined -# it is called on inserts and updates as primitive -# -sub insert_new_row ($$$) -{ - my ( $self, $data, $row_aryref ) = @_; - my $meta = $self->{meta}; - my $ncols = scalar( @{ $meta->{col_names} } ); - my $nitems = scalar( @{$row_aryref} ); - $ncols == $nitems - or croak "You tried to insert $nitems, but table is created with $ncols columns"; - - my $key = shift @$row_aryref; - my $exists; - eval { $exists = exists( $meta->{hash}->{$key} ); }; - $exists and croak "Row with PK '$key' already exists"; - - $meta->{hash}->{$key} = $meta->{dbm_mldbm} ? $row_aryref : $row_aryref->[0]; - - return 1; -} - -# this is where you grab the column names from a CREATE statement -# if you don't need to do that, it must be defined but can be empty -# -sub push_names ($$$) -{ - my ( $self, $data, $row_aryref ) = @_; - my $meta = $self->{meta}; - - # some sanity checks ... - my $ncols = scalar(@$row_aryref); - $ncols < 2 and croak "At least 2 columns are required for DBD::DBM tables ..."; - !$meta->{dbm_mldbm} - and $ncols > 2 - and croak "Without serializing with MLDBM only 2 columns are supported, you give $ncols"; - $meta->{col_names} = $row_aryref; - return unless $meta->{dbm_store_metadata}; - - my $stmt = $data->{sql_stmt}; - my $col_names = join( ',', @{$row_aryref} ); - my $schema = $data->{Database}->{Statement}; - $schema =~ s/^[^\(]+\((.+)\)$/$1/s; - $schema = $stmt->schema_str() if ( $stmt->can('schema_str') ); - $meta->{hash}->{"_metadata \0"} = - "" - . "$schema" - . "$col_names" - . ""; -} - -# fetch_one_row, delete_one_row, update_one_row -# are optimized for hash-style lookup without looping; -# if you don't need them, omit them, they're optional -# but, in that case you may need to define -# truncate() and seek(), see below -# -sub fetch_one_row ($$;$) -{ - my ( $self, $key_only, $key ) = @_; - my $meta = $self->{meta}; - $key_only and return $meta->{col_names}->[0]; - exists $meta->{hash}->{$key} or return; - my $val = $meta->{hash}->{$key}; - $val = ( ref($val) eq 'ARRAY' ) ? $val : [$val]; - my $row = [ $key, @$val ]; - return wantarray ? @{$row} : $row; -} - -sub delete_one_row ($$$) -{ - my ( $self, $data, $aryref ) = @_; - my $meta = $self->{meta}; - delete $meta->{hash}->{ $aryref->[0] }; -} - -sub update_one_row ($$$) -{ - my ( $self, $data, $aryref ) = @_; - my $meta = $self->{meta}; - my $key = shift @$aryref; - defined $key or return; - my $row = ( ref($aryref) eq 'ARRAY' ) ? $aryref : [$aryref]; - $meta->{hash}->{$key} = $meta->{dbm_mldbm} ? $row : $row->[0]; -} - -sub update_specific_row ($$$$) -{ - my ( $self, $data, $aryref, $origary ) = @_; - my $meta = $self->{meta}; - my $key = shift @$origary; - my $newkey = shift @$aryref; - return unless ( defined $key ); - $key eq $newkey or delete $meta->{hash}->{$key}; - my $row = ( ref($aryref) eq 'ARRAY' ) ? $aryref : [$aryref]; - $meta->{hash}->{$newkey} = $meta->{dbm_mldbm} ? $row : $row->[0]; -} - -# you may not need to explicitly DESTROY the ::Table -# put cleanup code to run when the execute is done -# -sub DESTROY ($) -{ - my $self = shift; - my $meta = $self->{meta}; - $meta->{hash} and untie %{ $meta->{hash} }; - - $self->SUPER::DESTROY(); -} - -# truncate() and seek() must be defined to satisfy DBI::SQL::Nano -# *IF* you define the *_one_row methods above, truncate() and -# seek() can be empty or you can use them without actually -# truncating or seeking anything but if you don't define the -# *_one_row methods, you may need to define these - -# if you need to do something after a series of -# deletes or updates, you can put it in truncate() -# which is called at the end of executing -# -sub truncate ($$) -{ - # my ( $self, $data ) = @_; - return 1; -} - -# seek() is only needed if you use IO::File -# though it could be used for other non-file operations -# that you need to do before "writes" or truncate() -# -sub seek ($$$$) -{ - # my ( $self, $data, $pos, $whence ) = @_; - return 1; -} - -# Th, th, th, that's all folks! See DBD::File and DBD::CSV for other -# examples of creating pure perl DBDs. I hope this helped. -# Now it's time to go forth and create your own DBD! -# Remember to check in with dbi-dev@perl.org before you get too far. -# We may be able to make suggestions or point you to other related -# projects. - -1; -__END__ - -=pod - -=head1 NAME - -DBD::DBM - a DBI driver for DBM & MLDBM files - -=head1 SYNOPSIS - - use DBI; - $dbh = DBI->connect('dbi:DBM:'); # defaults to SDBM_File - $dbh = DBI->connect('DBI:DBM(RaiseError=1):'); # defaults to SDBM_File - $dbh = DBI->connect('dbi:DBM:dbm_type=DB_File'); # defaults to DB_File - $dbh = DBI->connect('dbi:DBM:dbm_mldbm=Storable'); # MLDBM with SDBM_File - - # or - $dbh = DBI->connect('dbi:DBM:', undef, undef); - $dbh = DBI->connect('dbi:DBM:', undef, undef, { - f_ext => '.db/r', - f_dir => '/path/to/dbfiles/', - f_lockfile => '.lck', - dbm_type => 'BerkeleyDB', - dbm_mldbm => 'FreezeThaw', - dbm_store_metadata => 1, - dbm_berkeley_flags => { - '-Cachesize' => 1000, # set a ::Hash flag - }, - }); - -and other variations on connect() as shown in the L docs, -L and L -shown below. - -Use standard DBI prepare, execute, fetch, placeholders, etc., -see L for an example. - -=head1 DESCRIPTION - -DBD::DBM is a database management system that works right out of the -box. If you have a standard installation of Perl and DBI you can -begin creating, accessing, and modifying simple database tables -without any further modules. You can add other modules (e.g., -SQL::Statement, DB_File etc) for improved functionality. - -The module uses a DBM file storage layer. DBM file storage is common on -many platforms and files can be created with it in many programming -languages using different APIs. That means, in addition to creating -files with DBI/SQL, you can also use DBI/SQL to access and modify files -created by other DBM modules and programs and vice versa. B that -in those cases it might be necessary to use a common subset of the -provided features. - -DBM files are stored in binary format optimized for quick retrieval -when using a key field. That optimization can be used advantageously -to make DBD::DBM SQL operations that use key fields very fast. There -are several different "flavors" of DBM which use different storage -formats supported by perl modules such as SDBM_File and MLDBM. This -module supports all of the flavors that perl supports and, when used -with MLDBM, supports tables with any number of columns and insertion -of Perl objects into tables. - -DBD::DBM has been tested with the following DBM types: SDBM_File, -NDBM_File, ODBM_File, GDBM_File, DB_File, BerkeleyDB. Each type was -tested both with and without MLDBM and with the Data::Dumper, -Storable, FreezeThaw, YAML and JSON serializers using the DBI::SQL::Nano -or the SQL::Statement engines. - -=head1 QUICK START - -DBD::DBM operates like all other DBD drivers - it's basic syntax and -operation is specified by DBI. If you're not familiar with DBI, you should -start by reading L and the documents it points to and then come back -and read this file. If you are familiar with DBI, you already know most of -what you need to know to operate this module. Just jump in and create a -test script something like the one shown below. - -You should be aware that there are several options for the SQL engine -underlying DBD::DBM, see L. There are also many -options for DBM support, see especially the section on L. - -But here's a sample to get you started. - - use DBI; - my $dbh = DBI->connect('dbi:DBM:'); - $dbh->{RaiseError} = 1; - for my $sql( split /;\n+/," - CREATE TABLE user ( user_name TEXT, phone TEXT ); - INSERT INTO user VALUES ('Fred Bloggs','233-7777'); - INSERT INTO user VALUES ('Sanjay Patel','777-3333'); - INSERT INTO user VALUES ('Junk','xxx-xxxx'); - DELETE FROM user WHERE user_name = 'Junk'; - UPDATE user SET phone = '999-4444' WHERE user_name = 'Sanjay Patel'; - SELECT * FROM user - "){ - my $sth = $dbh->prepare($sql); - $sth->execute; - $sth->dump_results if $sth->{NUM_OF_FIELDS}; - } - $dbh->disconnect; - -=head1 USAGE - -This section will explain some usage cases in more detail. To get an -overview about the available attributes, see L. - -=head2 Specifying Files and Directories - -DBD::DBM will automatically supply an appropriate file extension for the -type of DBM you are using. For example, if you use SDBM_File, a table -called "fruit" will be stored in two files called "fruit.pag" and -"fruit.dir". You should B specify the file extensions in your SQL -statements. - -DBD::DBM recognizes following default extensions for following types: - -=over 4 - -=item .pag/r - -Chosen for dbm_type C<< SDBM_File >>, C<< ODBM_File >> and C<< NDBM_File >> -when an implementation is detected which wraps C<< -ldbm >> for -C<< NDBM_File >> (e.g. Solaris, AIX, ...). - -For those types, the C<< .dir >> extension is recognized, too (for being -deleted when dropping a table). - -=item .db/r - -Chosen for dbm_type C<< NDBM_File >> when an implementation is detected -which wraps BerkeleyDB 1.x for C<< NDBM_File >> (typically BSD's, Darwin). - -=back - -C<< GDBM_File >>, C<< DB_File >> and C<< BerkeleyDB >> don't usually -use a file extension. - -If your DBM type uses an extension other than one of the recognized -types of extensions, you should set the I attribute to the -extension B file a bug report as described in DBI with the name -of the implementation and extension so we can add it to DBD::DBM. -Thanks in advance for that :-). - - $dbh = DBI->connect('dbi:DBM:f_ext=.db'); # .db extension is used - $dbh = DBI->connect('dbi:DBM:f_ext='); # no extension is used - - # or - $dbh->{f_ext}='.db'; # global setting - $dbh->{f_meta}->{'qux'}->{f_ext}='.db'; # setting for table 'qux' - -By default files are assumed to be in the current working directory. -To use other directories specify the I attribute in either the -connect string or by setting the database handle attribute. - -For example, this will look for the file /foo/bar/fruit (or -/foo/bar/fruit.pag for DBM types that use that extension) - - my $dbh = DBI->connect('dbi:DBM:f_dir=/foo/bar'); - # and this will too: - my $dbh = DBI->connect('dbi:DBM:'); - $dbh->{f_dir} = '/foo/bar'; - # but this is recommended - my $dbh = DBI->connect('dbi:DBM:', undef, undef, { f_dir => '/foo/bar' } ); - - # now you can do - my $ary = $dbh->selectall_arrayref(q{ SELECT x FROM fruit }); - -You can also use delimited identifiers to specify paths directly in SQL -statements. This looks in the same place as the two examples above but -without setting I: - - my $dbh = DBI->connect('dbi:DBM:'); - my $ary = $dbh->selectall_arrayref(q{ - SELECT x FROM "/foo/bar/fruit" - }); - -You can also tell DBD::DBM to use a specified path for a specific table: - - $dbh->{dbm_tables}->{f}->{file} = q(/foo/bar/fruit); - -Please be aware that you cannot specify this during connection. - -If you have SQL::Statement installed, you can use table aliases: - - my $dbh = DBI->connect('dbi:DBM:'); - my $ary = $dbh->selectall_arrayref(q{ - SELECT f.x FROM "/foo/bar/fruit" AS f - }); - -See the L for using DROP on tables. - -=head2 Table locking and flock() - -Table locking is accomplished using a lockfile which has the same -basename as the table's file but with the file extension '.lck' (or a -lockfile extension that you supply, see below). This lock file is -created with the table during a CREATE and removed during a DROP. -Every time the table itself is opened, the lockfile is flocked(). For -SELECT, this is a shared lock. For all other operations, it is an -exclusive lock (except when you specify something different using the -I attribute). - -Since the locking depends on flock(), it only works on operating -systems that support flock(). In cases where flock() is not -implemented, DBD::DBM will simply behave as if the flock() had -occurred although no actual locking will happen. Read the -documentation for flock() for more information. - -Even on those systems that do support flock(), locking is only -advisory - as is always the case with flock(). This means that if -another program tries to access the table file while DBD::DBM has the -table locked, that other program will *succeed* at opening unless -it is also using flock on the '.lck' file. As a result DBD::DBM's -locking only really applies to other programs using DBD::DBM or other -program written to cooperate with DBD::DBM locking. - -=head2 Specifying the DBM type - -Each "flavor" of DBM stores its files in a different format and has -different capabilities and limitations. See L for a -comparison of DBM types. - -By default, DBD::DBM uses the C<< SDBM_File >> type of storage since -C<< SDBM_File >> comes with Perl itself. If you have other types of -DBM storage available, you can use any of them with DBD::DBM. It is -strongly recommended to use at least C<< DB_File >>, because C<< -SDBM_File >> has quirks and limitations and C<< ODBM_file >>, C<< -NDBM_File >> and C<< GDBM_File >> are not always available. - -You can specify the DBM type using the I attribute which can -be set in the connection string or with C<< $dbh->{dbm_type} >> and -C<< $dbh->{f_meta}->{$table_name}->{type} >> for per-table settings in -cases where a single script is accessing more than one kind of DBM -file. - -In the connection string, just set C<< dbm_type=TYPENAME >> where -C<< TYPENAME >> is any DBM type such as GDBM_File, DB_File, etc. Do I -use MLDBM as your I as that is set differently, see below. - - my $dbh=DBI->connect('dbi:DBM:'); # uses the default SDBM_File - my $dbh=DBI->connect('dbi:DBM:dbm_type=GDBM_File'); # uses the GDBM_File - - # You can also use $dbh->{dbm_type} to set the DBM type for the connection: - $dbh->{dbm_type} = 'DB_File'; # set the global DBM type - print $dbh->{dbm_type}; # display the global DBM type - -If you have several tables in your script that use different DBM -types, you can use the $dbh->{dbm_tables} hash to store different -settings for the various tables. You can even use this to perform -joins on files that have completely different storage mechanisms. - - # sets global default of GDBM_File - my $dbh->('dbi:DBM:type=GDBM_File'); - - # overrides the global setting, but only for the tables called - # I and I - my $dbh->{f_meta}->{foo}->{dbm_type} = 'DB_File'; - my $dbh->{f_meta}->{bar}->{dbm_type} = 'BerkeleyDB'; - - # prints the dbm_type for the table "foo" - print $dbh->{f_meta}->{foo}->{dbm_type}; - -B that you must change the I of a table before you access -it for first time. - -=head2 Adding multi-column support with MLDBM - -Most of the DBM types only support two columns and even if it would -support more, DBD::DBM would only use two. However a CPAN module -called MLDBM overcomes this limitation by allowing more than two -columns. MLDBM does this by serializing the data - basically it puts -a reference to an array into the second column. It can also put almost -any kind of Perl object or even B into columns. - -If you want more than two columns, you B install MLDBM. It's available -for many platforms and is easy to install. - -MLDBM is by default distributed with three serializers - Data::Dumper, -Storable, and FreezeThaw. Data::Dumper is the default and Storable is the -fastest. MLDBM can also make use of user-defined serialization methods or -other serialization modules (e.g. L or -L. You select the serializer using the -I attribute. - -Some examples: - - $dbh=DBI->connect('dbi:DBM:dbm_mldbm=Storable'); # use MLDBM with Storable - $dbh=DBI->connect( - 'dbi:DBM:dbm_mldbm=MySerializer' # use MLDBM with a user defined module - ); - $dbh=DBI->connect('dbi::dbm:', undef, - undef, { dbm_mldbm => 'YAML' }); # use 3rd party serializer - $dbh->{dbm_mldbm} = 'YAML'; # same as above - print $dbh->{dbm_mldbm} # show the MLDBM serializer - $dbh->{f_meta}->{foo}->{dbm_mldbm}='Data::Dumper'; # set Data::Dumper for table "foo" - print $dbh->{f_meta}->{foo}->{mldbm}; # show serializer for table "foo" - -MLDBM works on top of other DBM modules so you can also set a DBM type -along with setting dbm_mldbm. The examples above would default to using -SDBM_File with MLDBM. If you wanted GDBM_File instead, here's how: - - # uses DB_File with MLDBM and Storable - $dbh = DBI->connect('dbi:DBM:', undef, undef, { - dbm_type => 'DB_File', - dbm_mldbm => 'Storable', - }); - -SDBM_File, the default I is quite limited, so if you are going to -use MLDBM, you should probably use a different type, see L. - -See below for some L about MLDBM. - -=head2 Support for Berkeley DB - -The Berkeley DB storage type is supported through two different Perl -modules - DB_File (which supports only features in old versions of Berkeley -DB) and BerkeleyDB (which supports all versions). DBD::DBM supports -specifying either "DB_File" or "BerkeleyDB" as a I, with or -without MLDBM support. - -The "BerkeleyDB" dbm_type is experimental and it's interface is likely to -change. It currently defaults to BerkeleyDB::Hash and does not currently -support ::Btree or ::Recno. - -With BerkeleyDB, you can specify initialization flags by setting them in -your script like this: - - use BerkeleyDB; - my $env = new BerkeleyDB::Env -Home => $dir; # and/or other Env flags - $dbh = DBI->connect('dbi:DBM:', undef, undef, { - dbm_type => 'BerkeleyDB', - dbm_mldbm => 'Storable', - dbm_berkeley_flags => { - 'DB_CREATE' => DB_CREATE, # pass in constants - 'DB_RDONLY' => DB_RDONLY, # pass in constants - '-Cachesize' => 1000, # set a ::Hash flag - '-Env' => $env, # pass in an environment - }, - }); - -Do I set the -Flags or -Filename flags as those are determined and -overwritten by the SQL (e.g. -Flags => DB_RDONLY is set automatically -when you issue a SELECT statement). - -Time has not permitted us to provide support in this release of DBD::DBM -for further Berkeley DB features such as transactions, concurrency, -locking, etc. We will be working on these in the future and would value -suggestions, patches, etc. - -See L and L for further details. - -=head2 Optimizing the use of key fields - -Most "flavors" of DBM have only two physical columns (but can contain -multiple logical columns as explained above in -L). They work similarly to a -Perl hash with the first column serving as the key. Like a Perl hash, DBM -files permit you to do quick lookups by specifying the key and thus avoid -looping through all records (supported by DBI::SQL::Nano only). Also like -a Perl hash, the keys must be unique. It is impossible to create two -records with the same key. To put this more simply and in SQL terms, -the key column functions as the I or UNIQUE INDEX. - -In DBD::DBM, you can take advantage of the speed of keyed lookups by using -DBI::SQL::Nano and a WHERE clause with a single equal comparison on the key -field. For example, the following SQL statements are optimized for keyed -lookup: - - CREATE TABLE user ( user_name TEXT, phone TEXT); - INSERT INTO user VALUES ('Fred Bloggs','233-7777'); - # ... many more inserts - SELECT phone FROM user WHERE user_name='Fred Bloggs'; - -The "user_name" column is the key column since it is the first -column. The SELECT statement uses the key column in a single equal -comparison - "user_name='Fred Bloggs'" - so the search will find it -very quickly without having to loop through all the names which were -inserted into the table. - -In contrast, these searches on the same table are not optimized: - - 1. SELECT phone FROM user WHERE user_name < 'Fred'; - 2. SELECT user_name FROM user WHERE phone = '233-7777'; - -In #1, the operation uses a less-than (<) comparison rather than an equals -comparison, so it will not be optimized for key searching. In #2, the key -field "user_name" is not specified in the WHERE clause, and therefore the -search will need to loop through all rows to find the requested row(s). - -B that the underlying DBM storage needs to loop over all I -pairs when the optimized fetch is used. SQL::Statement has a massively -improved where clause evaluation which costs around 15% of the evaluation -in DBI::SQL::Nano - combined with the loop in the DBM storage the speed -improvement isn't so impressive. - -Even if lookups are faster by around 50%, DBI::SQL::Nano and -SQL::Statement can benefit from the key field optimizations on -updating and deleting rows - and here the improved where clause -evaluation of SQL::Statement might beat DBI::SQL::Nano every time the -where clause contains not only the key field (or more than one). - -=head2 Supported SQL syntax - -DBD::DBM uses a subset of SQL. The robustness of that subset depends on -what other modules you have installed. Both options support basic SQL -operations including CREATE TABLE, DROP TABLE, INSERT, DELETE, UPDATE, and -SELECT. - -B
for gotchas and -warnings about the use of flock(). - -=head1 BUGS AND LIMITATIONS - -This module uses hash interfaces of two column file databases. While -none of supported SQL engines have support for indices, the following -statements really do the same (even if they mean something completely -different) for each dbm type which lacks C support: - - $sth->do( "insert into foo values (1, 'hello')" ); - - # this statement does ... - $sth->do( "update foo set v='world' where k=1" ); - # ... the same as this statement - $sth->do( "insert into foo values (1, 'world')" ); - -This is considered to be a bug and might change in a future release. - -Known affected dbm types are C and C. We highly -recommended you use a more modern dbm type such as C. - -=head1 GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS - -If you need help installing or using DBD::DBM, please write to the DBI -users mailing list at dbi-users@perl.org or to the -comp.lang.perl.modules newsgroup on usenet. I cannot always answer -every question quickly but there are many on the mailing list or in -the newsgroup who can. - -DBD developers for DBD's which rely on DBD::File or DBD::DBM or use -one of them as an example are suggested to join the DBI developers -mailing list at dbi-dev@perl.org and strongly encouraged to join our -IRC channel at L. - -If you have suggestions, ideas for improvements, or bugs to report, please -report a bug as described in DBI. Do not mail any of the authors directly, -you might not get an answer. - -When reporting bugs, please send the output of $dbh->dbm_versions($table) -for a table that exhibits the bug and as small a sample as you can make of -the code that produces the bug. And of course, patches are welcome, too -:-). - -If you need enhancements quickly, you can get commercial support as -described at L or you can contact Jens Rehsack -at rehsack@cpan.org for commercial support in Germany. - -Please don't bother Jochen Wiedmann or Jeff Zucker for support - they -handed over further maintenance to H.Merijn Brand and Jens Rehsack. - -=head1 ACKNOWLEDGEMENTS - -Many, many thanks to Tim Bunce for prodding me to write this, and for -copious, wise, and patient suggestions all along the way. (Jeff Zucker) - -I send my thanks and acknowledgements to H.Merijn Brand for his -initial refactoring of DBD::File and his strong and ongoing support of -SQL::Statement. Without him, the current progress would never have -been made. And I have to name Martin J. Evans for each laugh (and -correction) of all those funny word creations I (as non-native -speaker) made to the documentation. And - of course - I have to thank -all those unnamed contributors and testers from the Perl -community. (Jens Rehsack) - -=head1 AUTHOR AND COPYRIGHT - -This module is written by Jeff Zucker < jzucker AT cpan.org >, who also -maintained it till 2007. After that, in 2010, Jens Rehsack & H.Merijn Brand -took over maintenance. - - Copyright (c) 2004 by Jeff Zucker, all rights reserved. - Copyright (c) 2010-2013 by Jens Rehsack & H.Merijn Brand, all rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=head1 SEE ALSO - -L, -L, L, -L, L, L, -L, L, L - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/ExampleP.pm b/dbLifeLog/DBI-1.641/lib/DBD/ExampleP.pm deleted file mode 100644 index ed5414f..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/ExampleP.pm +++ /dev/null @@ -1,435 +0,0 @@ -{ - package DBD::ExampleP; - - use strict; - use Symbol; - - use DBI qw(:sql_types); - - require File::Spec; - - our (@EXPORT,$VERSION,@statnames,%statnames,@stattypes,%stattypes, - @statprec,%statprec,$drh,); - - @EXPORT = qw(); # Do NOT @EXPORT anything. - $VERSION = "12.014311"; - -# $Id: ExampleP.pm 14310 2010-08-02 06:35:25Z Jens $ -# -# Copyright (c) 1994,1997,1998 Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - @statnames = qw(dev ino mode nlink - uid gid rdev size - atime mtime ctime - blksize blocks name); - @statnames{@statnames} = (0 .. @statnames-1); - - @stattypes = (SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, - SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, - SQL_INTEGER, SQL_INTEGER, SQL_INTEGER, - SQL_INTEGER, SQL_INTEGER, SQL_VARCHAR); - @stattypes{@statnames} = @stattypes; - @statprec = ((10) x (@statnames-1), 1024); - @statprec{@statnames} = @statprec; - die unless @statnames == @stattypes; - die unless @statprec == @stattypes; - - $drh = undef; # holds driver handle once initialised - #$gensym = "SYM000"; # used by st::execute() for filehandles - - sub driver{ - return $drh if $drh; - my($class, $attr) = @_; - $class .= "::dr"; - ($drh) = DBI::_new_drh($class, { - 'Name' => 'ExampleP', - 'Version' => $VERSION, - 'Attribution' => 'DBD Example Perl stub by Tim Bunce', - }, ['example implementors private data '.__PACKAGE__]); - $drh; - } - - sub CLONE { - undef $drh; - } -} - - -{ package DBD::ExampleP::dr; # ====== DRIVER ====== - $imp_data_size = 0; - use strict; - - sub connect { # normally overridden, but a handy default - my($drh, $dbname, $user, $auth)= @_; - my ($outer, $dbh) = DBI::_new_dbh($drh, { - Name => $dbname, - examplep_private_dbh_attrib => 42, # an example, for testing - }); - $dbh->{examplep_get_info} = { - 29 => '"', # SQL_IDENTIFIER_QUOTE_CHAR - 41 => '.', # SQL_CATALOG_NAME_SEPARATOR - 114 => 1, # SQL_CATALOG_LOCATION - }; - #$dbh->{Name} = $dbname; - $dbh->STORE('Active', 1); - return $outer; - } - - sub data_sources { - return ("dbi:ExampleP:dir=."); # possibly usefully meaningless - } - -} - - -{ package DBD::ExampleP::db; # ====== DATABASE ====== - $imp_data_size = 0; - use strict; - - sub prepare { - my($dbh, $statement)= @_; - my @fields; - my($fields, $dir) = $statement =~ m/^\s*select\s+(.*?)\s+from\s+(\S*)/i; - - if (defined $fields and defined $dir) { - @fields = ($fields eq '*') - ? keys %DBD::ExampleP::statnames - : split(/\s*,\s*/, $fields); - } - else { - return $dbh->set_err($DBI::stderr, "Syntax error in select statement (\"$statement\")") - unless $statement =~ m/^\s*set\s+/; - # the SET syntax is just a hack so the ExampleP driver can - # be used to test non-select statements. - # Now we have DBI::DBM etc., ExampleP should be deprecated - } - - my ($outer, $sth) = DBI::_new_sth($dbh, { - 'Statement' => $statement, - examplep_private_sth_attrib => 24, # an example, for testing - }, ['example implementors private data '.__PACKAGE__]); - - my @bad = map { - defined $DBD::ExampleP::statnames{$_} ? () : $_ - } @fields; - return $dbh->set_err($DBI::stderr, "Unknown field names: @bad") - if @bad; - - $outer->STORE('NUM_OF_FIELDS' => scalar(@fields)); - - $sth->{examplep_ex_dir} = $dir if defined($dir) && $dir !~ /\?/; - $outer->STORE('NUM_OF_PARAMS' => ($dir) ? $dir =~ tr/?/?/ : 0); - - if (@fields) { - $outer->STORE('NAME' => \@fields); - $outer->STORE('NULLABLE' => [ (0) x @fields ]); - $outer->STORE('SCALE' => [ (0) x @fields ]); - } - - $outer; - } - - - sub table_info { - my $dbh = shift; - my ($catalog, $schema, $table, $type) = @_; - - my @types = split(/["']*,["']/, $type || 'TABLE'); - my %types = map { $_=>$_ } @types; - - # Return a list of all subdirectories - my $dh = Symbol::gensym(); # "DBD::ExampleP::".++$DBD::ExampleP::gensym; - my $dir = $catalog || File::Spec->curdir(); - my @list; - if ($types{VIEW}) { # for use by test harness - push @list, [ undef, "schema", "table", 'VIEW', undef ]; - push @list, [ undef, "sch-ema", "table", 'VIEW', undef ]; - push @list, [ undef, "schema", "ta-ble", 'VIEW', undef ]; - push @list, [ undef, "sch ema", "table", 'VIEW', undef ]; - push @list, [ undef, "schema", "ta ble", 'VIEW', undef ]; - } - if ($types{TABLE}) { - no strict 'refs'; - opendir($dh, $dir) - or return $dbh->set_err(int($!), "Failed to open directory $dir: $!"); - while (defined(my $item = readdir($dh))) { - if ($^O eq 'VMS') { - # if on VMS then avoid warnings from catdir if you use a file - # (not a dir) as the item below - next if $item !~ /\.dir$/oi; - } - my $file = File::Spec->catdir($dir,$item); - next unless -d $file; - my($dev, $ino, $mode, $nlink, $uid) = lstat($file); - my $pwnam = undef; # eval { scalar(getpwnam($uid)) } || $uid; - push @list, [ $dir, $pwnam, $item, 'TABLE', undef ]; - } - close($dh); - } - # We would like to simply do a DBI->connect() here. However, - # this is wrong if we are in a subclass like DBI::ProxyServer. - $dbh->{'dbd_sponge_dbh'} ||= DBI->connect("DBI:Sponge:", '','') - or return $dbh->set_err($DBI::err, - "Failed to connect to DBI::Sponge: $DBI::errstr"); - - my $attr = { - 'rows' => \@list, - 'NUM_OF_FIELDS' => 5, - 'NAME' => ['TABLE_CAT', 'TABLE_SCHEM', 'TABLE_NAME', - 'TABLE_TYPE', 'REMARKS'], - 'TYPE' => [DBI::SQL_VARCHAR(), DBI::SQL_VARCHAR(), - DBI::SQL_VARCHAR(), DBI::SQL_VARCHAR(), DBI::SQL_VARCHAR() ], - 'NULLABLE' => [1, 1, 1, 1, 1] - }; - my $sdbh = $dbh->{'dbd_sponge_dbh'}; - my $sth = $sdbh->prepare("SHOW TABLES FROM $dir", $attr) - or return $dbh->set_err($sdbh->err(), $sdbh->errstr()); - $sth; - } - - - sub type_info_all { - my ($dbh) = @_; - my $ti = [ - { TYPE_NAME => 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE=> 9, - FIXED_PREC_SCALE=> 10, - AUTO_UNIQUE_VALUE => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - }, - [ 'VARCHAR', DBI::SQL_VARCHAR, 1024, "'","'", undef, 0, 1, 1, 0, 0,0,undef,0,0 ], - [ 'INTEGER', DBI::SQL_INTEGER, 10, "","", undef, 0, 0, 1, 0, 0,0,undef,0,0 ], - ]; - return $ti; - } - - - sub ping { - (shift->FETCH('Active')) ? 2 : 0; # the value 2 is checked for by t/80proxy.t - } - - - sub disconnect { - shift->STORE(Active => 0); - return 1; - } - - - sub get_info { - my ($dbh, $info_type) = @_; - return $dbh->{examplep_get_info}->{$info_type}; - } - - - sub FETCH { - my ($dbh, $attrib) = @_; - # In reality this would interrogate the database engine to - # either return dynamic values that cannot be precomputed - # or fetch and cache attribute values too expensive to prefetch. - # else pass up to DBI to handle - return $INC{"DBD/ExampleP.pm"} if $attrib eq 'example_driver_path'; - return $dbh->SUPER::FETCH($attrib); - } - - - sub STORE { - my ($dbh, $attrib, $value) = @_; - # store only known attributes else pass up to DBI to handle - if ($attrib eq 'examplep_set_err') { - # a fake attribute to enable a test case where STORE issues a warning - $dbh->set_err($value, $value); - return; - } - if ($attrib eq 'AutoCommit') { - # convert AutoCommit values to magic ones to let DBI - # know that the driver has 'handled' the AutoCommit attribute - $value = ($value) ? -901 : -900; - } - return $dbh->{$attrib} = $value if $attrib =~ /^examplep_/; - return $dbh->SUPER::STORE($attrib, $value); - } - - sub DESTROY { - my $dbh = shift; - $dbh->disconnect if $dbh->FETCH('Active'); - undef - } - - - # This is an example to demonstrate the use of driver-specific - # methods via $dbh->func(). - # Use it as follows: - # my @tables = $dbh->func($re, 'examplep_tables'); - # - # Returns all the tables that match the regular expression $re. - sub examplep_tables { - my $dbh = shift; my $re = shift; - grep { $_ =~ /$re/ } $dbh->tables(); - } - - sub parse_trace_flag { - my ($h, $name) = @_; - return 0x01000000 if $name eq 'foo'; - return 0x02000000 if $name eq 'bar'; - return 0x04000000 if $name eq 'baz'; - return 0x08000000 if $name eq 'boo'; - return 0x10000000 if $name eq 'bop'; - return $h->SUPER::parse_trace_flag($name); - } - - sub private_attribute_info { - return { example_driver_path => undef }; - } -} - - -{ package DBD::ExampleP::st; # ====== STATEMENT ====== - $imp_data_size = 0; - use strict; no strict 'refs'; # cause problems with filehandles - - sub bind_param { - my($sth, $param, $value, $attribs) = @_; - $sth->{'dbd_param'}->[$param-1] = $value; - return 1; - } - - - sub execute { - my($sth, @dir) = @_; - my $dir; - - if (@dir) { - $sth->bind_param($_, $dir[$_-1]) or return - foreach (1..@dir); - } - - my $dbd_param = $sth->{'dbd_param'} || []; - return $sth->set_err(2, @$dbd_param." values bound when $sth->{NUM_OF_PARAMS} expected") - unless @$dbd_param == $sth->{NUM_OF_PARAMS}; - - return 0 unless $sth->{NUM_OF_FIELDS}; # not a select - - $dir = $dbd_param->[0] || $sth->{examplep_ex_dir}; - return $sth->set_err(2, "No bind parameter supplied") - unless defined $dir; - - $sth->finish; - - # - # If the users asks for directory "long_list_4532", then we fake a - # directory with files "file4351", "file4350", ..., "file0". - # This is a special case used for testing, especially DBD::Proxy. - # - if ($dir =~ /^long_list_(\d+)$/) { - $sth->{dbd_dir} = [ $1 ]; # array ref indicates special mode - $sth->{dbd_datahandle} = undef; - } - else { - $sth->{dbd_dir} = $dir; - my $sym = Symbol::gensym(); # "DBD::ExampleP::".++$DBD::ExampleP::gensym; - opendir($sym, $dir) - or return $sth->set_err(2, "opendir($dir): $!"); - $sth->{dbd_datahandle} = $sym; - } - $sth->STORE(Active => 1); - return 1; - } - - - sub fetch { - my $sth = shift; - my $dir = $sth->{dbd_dir}; - my %s; - - if (ref $dir) { # special fake-data test mode - my $num = $dir->[0]--; - unless ($num > 0) { - $sth->finish(); - return; - } - my $time = time; - @s{@DBD::ExampleP::statnames} = - ( 2051, 1000+$num, 0644, 2, $>, $), 0, 1024, - $time, $time, $time, 512, 2, "file$num") - } - else { # normal mode - my $dh = $sth->{dbd_datahandle} - or return $sth->set_err($DBI::stderr, "fetch without successful execute"); - my $f = readdir($dh); - unless ($f) { - $sth->finish; - return; - } - # untaint $f so that we can use this for DBI taint tests - ($f) = ($f =~ m/^(.*)$/); - my $file = File::Spec->catfile($dir, $f); - # put in all the data fields - @s{ @DBD::ExampleP::statnames } = (lstat($file), $f); - } - - # return just what fields the query asks for - my @new = @s{ @{$sth->{NAME}} }; - - return $sth->_set_fbav(\@new); - } - *fetchrow_arrayref = \&fetch; - - - sub finish { - my $sth = shift; - closedir($sth->{dbd_datahandle}) if $sth->{dbd_datahandle}; - $sth->{dbd_datahandle} = undef; - $sth->{dbd_dir} = undef; - $sth->SUPER::finish(); - return 1; - } - - - sub FETCH { - my ($sth, $attrib) = @_; - # In reality this would interrogate the database engine to - # either return dynamic values that cannot be precomputed - # or fetch and cache attribute values too expensive to prefetch. - if ($attrib eq 'TYPE'){ - return [ @DBD::ExampleP::stattypes{ @{ $sth->FETCH(q{NAME_lc}) } } ]; - } - elsif ($attrib eq 'PRECISION'){ - return [ @DBD::ExampleP::statprec{ @{ $sth->FETCH(q{NAME_lc}) } } ]; - } - elsif ($attrib eq 'ParamValues') { - my $dbd_param = $sth->{dbd_param} || []; - my %pv = map { $_ => $dbd_param->[$_-1] } 1..@$dbd_param; - return \%pv; - } - # else pass up to DBI to handle - return $sth->SUPER::FETCH($attrib); - } - - - sub STORE { - my ($sth, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - return $sth->{$attrib} = $value - if $attrib eq 'NAME' or $attrib eq 'NULLABLE' or $attrib eq 'SCALE' or $attrib eq 'PRECISION'; - return $sth->SUPER::STORE($attrib, $value); - } - - *parse_trace_flag = \&DBD::ExampleP::db::parse_trace_flag; -} - -1; -# vim: sw=4:ts=8 diff --git a/dbLifeLog/DBI-1.641/lib/DBD/File.pm b/dbLifeLog/DBI-1.641/lib/DBD/File.pm deleted file mode 100644 index dd4312b..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/File.pm +++ /dev/null @@ -1,1449 +0,0 @@ -# -*- perl -*- -# -# DBD::File - A base class for implementing DBI drivers that -# act on plain files -# -# This module is currently maintained by -# -# H.Merijn Brand & Jens Rehsack -# -# The original author is Jochen Wiedmann. -# -# Copyright (C) 2009-2013 by H.Merijn Brand & Jens Rehsack -# Copyright (C) 2004 by Jeff Zucker -# Copyright (C) 1998 by Jochen Wiedmann -# -# All rights reserved. -# -# You may distribute this module under the terms of either the GNU -# General Public License or the Artistic License, as specified in -# the Perl README file. - -require 5.008; - -use strict; -use warnings; - -use DBI (); - -package DBD::File; - -use strict; -use warnings; - -use base qw( DBI::DBD::SqlEngine ); -use Carp; -use vars qw( @ISA $VERSION $drh ); - -$VERSION = "0.44"; - -$drh = undef; # holds driver handle(s) once initialized - -sub driver ($;$) -{ - my ($class, $attr) = @_; - - # Drivers typically use a singleton object for the $drh - # We use a hash here to have one singleton per subclass. - # (Otherwise DBD::CSV and DBD::DBM, for example, would - # share the same driver object which would cause problems.) - # An alternative would be to not cache the $drh here at all - # and require that subclasses do that. Subclasses should do - # their own caching, so caching here just provides extra safety. - $drh->{$class} and return $drh->{$class}; - - $attr ||= {}; - { no strict "refs"; - unless ($attr->{Attribution}) { - $class eq "DBD::File" and - $attr->{Attribution} = "$class by Jeff Zucker"; - $attr->{Attribution} ||= ${$class . "::ATTRIBUTION"} || - "oops the author of $class forgot to define this"; - } - $attr->{Version} ||= ${$class . "::VERSION"}; - $attr->{Name} or ($attr->{Name} = $class) =~ s/^DBD\:\://; - } - - $drh->{$class} = $class->SUPER::driver ($attr); - - # XXX inject DBD::XXX::Statement unless exists - - return $drh->{$class}; - } # driver - -sub CLONE -{ - undef $drh; - } # CLONE - -# ====== DRIVER ================================================================ - -package DBD::File::dr; - -use strict; -use warnings; - -use vars qw( @ISA $imp_data_size ); - -use Carp; - -@DBD::File::dr::ISA = qw( DBI::DBD::SqlEngine::dr ); -$DBD::File::dr::imp_data_size = 0; - -sub dsn_quote -{ - my $str = shift; - ref $str and return ""; - defined $str or return ""; - $str =~ s/([;:\\])/\\$1/g; - return $str; - } # dsn_quote - -# XXX rewrite using TableConfig ... -sub default_table_source { "DBD::File::TableSource::FileSystem" } - -sub connect -{ - my ($drh, $dbname, $user, $auth, $attr) = @_; - - # We do not (yet) care about conflicting attributes here - # my $dbh = DBI->connect ("dbi:CSV:f_dir=test", undef, undef, { f_dir => "text" }); - # will test here that both test and text should exist - if (my $attr_hash = (DBI->parse_dsn ($dbname))[3]) { - if (defined $attr_hash->{f_dir} && ! -d $attr_hash->{f_dir}) { - my $msg = "No such directory '$attr_hash->{f_dir}"; - $drh->set_err (2, $msg); - $attr_hash->{RaiseError} and croak $msg; - return; - } - } - if ($attr and defined $attr->{f_dir} && ! -d $attr->{f_dir}) { - my $msg = "No such directory '$attr->{f_dir}"; - $drh->set_err (2, $msg); - $attr->{RaiseError} and croak $msg; - return; - } - - return $drh->SUPER::connect ($dbname, $user, $auth, $attr); - } # connect - -sub disconnect_all -{ - } # disconnect_all - -sub DESTROY -{ - undef; - } # DESTROY - -# ====== DATABASE ============================================================== - -package DBD::File::db; - -use strict; -use warnings; - -use vars qw( @ISA $imp_data_size ); - -use Carp; -require File::Spec; -require Cwd; -use Scalar::Util qw( refaddr ); # in CORE since 5.7.3 - -@DBD::File::db::ISA = qw( DBI::DBD::SqlEngine::db ); -$DBD::File::db::imp_data_size = 0; - -sub data_sources -{ - my ($dbh, $attr, @other) = @_; - ref ($attr) eq "HASH" or $attr = {}; - exists $attr->{f_dir} or $attr->{f_dir} = $dbh->{f_dir}; - exists $attr->{f_dir_search} or $attr->{f_dir_search} = $dbh->{f_dir_search}; - return $dbh->SUPER::data_sources ($attr, @other); - } # data_source - -sub set_versions -{ - my $dbh = shift; - $dbh->{f_version} = $DBD::File::VERSION; - - return $dbh->SUPER::set_versions (); - } # set_versions - -sub init_valid_attributes -{ - my $dbh = shift; - - $dbh->{f_valid_attrs} = { - f_version => 1, # DBD::File version - f_dir => 1, # base directory - f_dir_search => 1, # extended search directories - f_ext => 1, # file extension - f_schema => 1, # schema name - f_lock => 1, # Table locking mode - f_lockfile => 1, # Table lockfile extension - f_encoding => 1, # Encoding of the file - f_valid_attrs => 1, # File valid attributes - f_readonly_attrs => 1, # File readonly attributes - }; - $dbh->{f_readonly_attrs} = { - f_version => 1, # DBD::File version - f_valid_attrs => 1, # File valid attributes - f_readonly_attrs => 1, # File readonly attributes - }; - - return $dbh->SUPER::init_valid_attributes (); - } # init_valid_attributes - -sub init_default_attributes -{ - my ($dbh, $phase) = @_; - - # must be done first, because setting flags implicitly calls $dbdname::db->STORE - $dbh->SUPER::init_default_attributes ($phase); - - # DBI::BD::SqlEngine::dr::connect will detect old-style drivers and - # don't call twice - unless (defined $phase) { - # we have an "old" driver here - $phase = defined $dbh->{sql_init_phase}; - $phase and $phase = $dbh->{sql_init_phase}; - } - - if (0 == $phase) { - # f_ext should not be initialized - # f_map is deprecated (but might return) - $dbh->{f_dir} = Cwd::abs_path (File::Spec->curdir ()); - - push @{$dbh->{sql_init_order}{90}}, "f_meta"; - - # complete derived attributes, if required - (my $drv_class = $dbh->{ImplementorClass}) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix ($drv_class); - if (exists $dbh->{$drv_prefix . "meta"} and !$dbh->{sql_engine_in_gofer}) { - my $attr = $dbh->{$drv_prefix . "meta"}; - defined $dbh->{f_valid_attrs}{f_meta} - and $dbh->{f_valid_attrs}{f_meta} = 1; - - $dbh->{f_meta} = $dbh->{$attr}; - } - } - - return $dbh; - } # init_default_attributes - -sub validate_FETCH_attr -{ - my ($dbh, $attrib) = @_; - - $attrib eq "f_meta" and $dbh->{sql_engine_in_gofer} and $attrib = "sql_meta"; - - return $dbh->SUPER::validate_FETCH_attr ($attrib); - } # validate_FETCH_attr - -sub validate_STORE_attr -{ - my ($dbh, $attrib, $value) = @_; - - if ($attrib eq "f_dir" && defined $value) { - -d $value or - return $dbh->set_err ($DBI::stderr, "No such directory '$value'"); - File::Spec->file_name_is_absolute ($value) or - $value = Cwd::abs_path ($value); - } - - if ($attrib eq "f_ext") { - $value eq "" || $value =~ m{^\.\w+(?:/[rR]*)?$} or - carp "'$value' doesn't look like a valid file extension attribute\n"; - } - - $attrib eq "f_meta" and $dbh->{sql_engine_in_gofer} and $attrib = "sql_meta"; - - return $dbh->SUPER::validate_STORE_attr ($attrib, $value); - } # validate_STORE_attr - -sub get_f_versions -{ - my ($dbh, $table) = @_; - - my $class = $dbh->{ImplementorClass}; - $class =~ s/::db$/::Table/; - my $dver; - my $dtype = "IO::File"; - eval { - $dver = IO::File->VERSION (); - - # when we're still alive here, everything went ok - no need to check for $@ - $dtype .= " ($dver)"; - }; - - my $f_encoding; - if ($table) { - my $meta; - $table and (undef, $meta) = $class->get_table_meta ($dbh, $table, 1); - $meta and $meta->{f_encoding} and $f_encoding = $meta->{f_encoding}; - } # if ($table) - $f_encoding ||= $dbh->{f_encoding}; - - $f_encoding and $dtype .= " + " . $f_encoding . " encoding"; - - return sprintf "%s using %s", $dbh->{f_version}, $dtype; - } # get_f_versions - -# ====== STATEMENT ============================================================= - -package DBD::File::st; - -use strict; -use warnings; - -use vars qw( @ISA $imp_data_size ); - -@DBD::File::st::ISA = qw( DBI::DBD::SqlEngine::st ); -$DBD::File::st::imp_data_size = 0; - -my %supported_attrs = ( - TYPE => 1, - PRECISION => 1, - NULLABLE => 1, - ); - -sub FETCH -{ - my ($sth, $attr) = @_; - - if ($supported_attrs{$attr}) { - my $stmt = $sth->{sql_stmt}; - - if (exists $sth->{ImplementorClass} && - exists $sth->{sql_stmt} && - $sth->{sql_stmt}->isa ("SQL::Statement")) { - - # fill overall_defs unless we know - unless (exists $sth->{f_overall_defs} && ref $sth->{f_overall_defs}) { - my $types = $sth->{Database}{Types}; - unless ($types) { # Fetch types only once per database - if (my $t = $sth->{Database}->type_info_all ()) { - foreach my $i (1 .. $#$t) { - $types->{uc $t->[$i][0]} = $t->[$i][1]; - $types->{$t->[$i][1]} ||= uc $t->[$i][0]; - } - } - # sane defaults - for ([ 0, "" ], - [ 1, "CHAR" ], - [ 4, "INTEGER" ], - [ 12, "VARCHAR" ], - ) { - $types->{$_->[0]} ||= $_->[1]; - $types->{$_->[1]} ||= $_->[0]; - } - $sth->{Database}{Types} = $types; - } - my $all_meta = - $sth->{Database}->func ("*", "table_defs", "get_sql_engine_meta"); - foreach my $tbl (keys %$all_meta) { - my $meta = $all_meta->{$tbl}; - exists $meta->{table_defs} && ref $meta->{table_defs} or next; - foreach (keys %{$meta->{table_defs}{columns}}) { - my $field_info = $meta->{table_defs}{columns}{$_}; - if (defined $field_info->{data_type} && - $field_info->{data_type} !~ m/^[0-9]+$/) { - $field_info->{type_name} = uc $field_info->{data_type}; - $field_info->{data_type} = $types->{$field_info->{type_name}} || 0; - } - $field_info->{type_name} ||= $types->{$field_info->{data_type}} || "CHAR"; - $sth->{f_overall_defs}{$_} = $field_info; - } - } - } - - my @colnames = $sth->sql_get_colnames (); - - $attr eq "TYPE" and - return [ map { $sth->{f_overall_defs}{$_}{data_type} || 12 } - @colnames ]; - - $attr eq "TYPE_NAME" and - return [ map { $sth->{f_overall_defs}{$_}{type_name} || "VARCHAR" } - @colnames ]; - - $attr eq "PRECISION" and - return [ map { $sth->{f_overall_defs}{$_}{data_length} || 0 } - @colnames ]; - - $attr eq "NULLABLE" and - return [ map { ( grep { $_ eq "NOT NULL" } - @{ $sth->{f_overall_defs}{$_}{constraints} || [] }) - ? 0 : 1 } - @colnames ]; - } - } - - return $sth->SUPER::FETCH ($attr); - } # FETCH - -# ====== TableSource =========================================================== - -package DBD::File::TableSource::FileSystem; - -use strict; -use warnings; - -use IO::Dir; - -@DBD::File::TableSource::FileSystem::ISA = "DBI::DBD::SqlEngine::TableSource"; - -sub data_sources -{ - my ($class, $drh, $attr) = @_; - my $dir = $attr && exists $attr->{f_dir} - ? $attr->{f_dir} - : File::Spec->curdir (); - defined $dir or return; # Stream-based databases do not have f_dir - unless (-d $dir && -r $dir && -x $dir) { - $drh->set_err ($DBI::stderr, "Cannot use directory $dir from f_dir"); - return; - } - my %attrs; - $attr and %attrs = %$attr; - delete $attrs{f_dir}; - my $dsn_quote = $drh->{ImplementorClass}->can ("dsn_quote"); - my $dsnextra = join ";", map { $_ . "=" . &{$dsn_quote} ($attrs{$_}) } keys %attrs; - my @dir = ($dir); - $attr->{f_dir_search} && ref $attr->{f_dir_search} eq "ARRAY" and - push @dir, grep { -d $_ } @{$attr->{f_dir_search}}; - my @dsns; - foreach $dir (@dir) { - my $dirh = IO::Dir->new ($dir); - unless (defined $dirh) { - $drh->set_err ($DBI::stderr, "Cannot open directory $dir: $!"); - return; - } - - my ($file, %names, $driver); - $driver = $drh->{ImplementorClass} =~ m/^dbd\:\:([^\:]+)\:\:/i ? $1 : "File"; - - while (defined ($file = $dirh->read ())) { - my $d = File::Spec->catdir ($dir, $file); - # allow current dir ... it can be a data_source too - $file ne File::Spec->updir () && -d $d and - push @dsns, "DBI:$driver:f_dir=" . &{$dsn_quote} ($d) . ($dsnextra ? ";$dsnextra" : ""); - } - } - return @dsns; - } # data_sources - -sub avail_tables -{ - my ($self, $dbh) = @_; - - my $dir = $dbh->{f_dir}; - defined $dir or return; # Stream based db's cannot be queried for tables - - my %seen; - my @tables; - my @dir = ($dir); - $dbh->{f_dir_search} && ref $dbh->{f_dir_search} eq "ARRAY" and - push @dir, grep { -d $_ } @{$dbh->{f_dir_search}}; - foreach $dir (@dir) { - my $dirh = IO::Dir->new ($dir); - - unless (defined $dirh) { - $dbh->set_err ($DBI::stderr, "Cannot open directory $dir: $!"); - return; - } - - my $class = $dbh->FETCH ("ImplementorClass"); - $class =~ s/::db$/::Table/; - my ($file, %names); - my $schema = exists $dbh->{f_schema} - ? defined $dbh->{f_schema} && $dbh->{f_schema} ne "" - ? $dbh->{f_schema} : undef - : eval { getpwuid ((stat $dir)[4]) }; # XXX Win32::pwent - while (defined ($file = $dirh->read ())) { - my ($tbl, $meta) = $class->get_table_meta ($dbh, $file, 0, 0) or next; # XXX - # $tbl && $meta && -f $meta->{f_fqfn} or next; - $seen{defined $schema ? $schema : "\0"}{$dir}{$tbl}++ or - push @tables, [ undef, $schema, $tbl, "TABLE", "FILE" ]; - } - $dirh->close () or - $dbh->set_err ($DBI::stderr, "Cannot close directory $dir: $!"); - } - - return @tables; - } # avail_tables - -# ====== DataSource ============================================================ - -package DBD::File::DataSource::Stream; - -use strict; -use warnings; - -use Carp; - -@DBD::File::DataSource::Stream::ISA = "DBI::DBD::SqlEngine::DataSource"; - -# We may have a working flock () built-in but that doesn't mean that locking -# will work on NFS (flock () may hang hard) -my $locking = eval { - my $fh; - my $nulldevice = File::Spec->devnull (); - open $fh, ">", $nulldevice or croak "Can't open $nulldevice: $!"; - flock $fh, 0; - close $fh; - 1; - }; - -sub complete_table_name -{ - my ($self, $meta, $file, $respect_case) = @_; - - my $tbl = $file; - if (!$respect_case and $meta->{sql_identifier_case} == 1) { # XXX SQL_IC_UPPER - $tbl = uc $tbl; - } - elsif (!$respect_case and $meta->{sql_identifier_case} == 2) { # XXX SQL_IC_LOWER - $tbl = lc $tbl; - } - - $meta->{f_fqfn} = undef; - $meta->{f_fqbn} = undef; - $meta->{f_fqln} = undef; - - $meta->{table_name} = $tbl; - - return $tbl; - } # complete_table_name - -sub apply_encoding -{ - my ($self, $meta, $fn) = @_; - defined $fn or $fn = "file handle " . fileno ($meta->{fh}); - if (my $enc = $meta->{f_encoding}) { - binmode $meta->{fh}, ":encoding($enc)" or - croak "Failed to set encoding layer '$enc' on $fn: $!"; - } - else { - binmode $meta->{fh} or croak "Failed to set binary mode on $fn: $!"; - } - } # apply_encoding - -sub open_data -{ - my ($self, $meta, $attrs, $flags) = @_; - - $flags->{dropMode} and croak "Can't drop a table in stream"; - my $fn = "file handle " . fileno ($meta->{f_file}); - - if ($flags->{createMode} || $flags->{lockMode}) { - $meta->{fh} = IO::Handle->new_from_fd (fileno ($meta->{f_file}), "w+") or - croak "Cannot open $fn for writing: $! (" . ($!+0) . ")"; - } - else { - $meta->{fh} = IO::Handle->new_from_fd (fileno ($meta->{f_file}), "r") or - croak "Cannot open $fn for reading: $! (" . ($!+0) . ")"; - } - - if ($meta->{fh}) { - $self->apply_encoding ($meta, $fn); - } # have $meta->{$fh} - - if ($self->can_flock && $meta->{fh}) { - my $lm = defined $flags->{f_lock} - && $flags->{f_lock} =~ m/^[012]$/ - ? $flags->{f_lock} - : $flags->{lockMode} ? 2 : 1; - if ($lm == 2) { - flock $meta->{fh}, 2 or croak "Cannot obtain exclusive lock on $fn: $!"; - } - elsif ($lm == 1) { - flock $meta->{fh}, 1 or croak "Cannot obtain shared lock on $fn: $!"; - } - # $lm = 0 is forced no locking at all - } - } # open_data - -sub can_flock { $locking } - -package DBD::File::DataSource::File; - -use strict; -use warnings; - -@DBD::File::DataSource::File::ISA = "DBD::File::DataSource::Stream"; - -use Carp; - -my $fn_any_ext_regex = qr/\.[^.]*/; - -sub complete_table_name -{ - my ($self, $meta, $file, $respect_case, $file_is_table) = @_; - - $file eq "." || $file eq ".." and return; # XXX would break a possible DBD::Dir - - # XXX now called without proving f_fqfn first ... - my ($ext, $req) = ("", 0); - if ($meta->{f_ext}) { - ($ext, my $opt) = split m{/}, $meta->{f_ext}; - if ($ext && $opt) { - $opt =~ m/r/i and $req = 1; - } - } - - # (my $tbl = $file) =~ s/\Q$ext\E$//i; - my ($tbl, $basename, $dir, $fn_ext, $user_spec_file, $searchdir); - if ($file_is_table and defined $meta->{f_file}) { - $tbl = $file; - ($basename, $dir, $fn_ext) = File::Basename::fileparse ($meta->{f_file}, $fn_any_ext_regex); - $file = $basename . $fn_ext; - $user_spec_file = 1; - } - else { - ($basename, $dir, undef) = File::Basename::fileparse ($file, qr{\Q$ext\E}); - # $dir is returned with trailing (back)slash. We just need to check - # if it is ".", "./", or ".\" or "[]" (VMS) - if ($dir =~ m{^(?:[.][/\\]?|\[\])$} && ref $meta->{f_dir_search} eq "ARRAY") { - foreach my $d ($meta->{f_dir}, @{$meta->{f_dir_search}}) { - my $f = File::Spec->catdir ($d, $file); - -f $f or next; - $searchdir = Cwd::abs_path ($d); - $dir = ""; - last; - } - } - $file = $tbl = $basename; - $user_spec_file = 0; - } - - if (!$respect_case and $meta->{sql_identifier_case} == 1) { # XXX SQL_IC_UPPER - $basename = uc $basename; - $tbl = uc $tbl; - } - elsif (!$respect_case and $meta->{sql_identifier_case} == 2) { # XXX SQL_IC_LOWER - $basename = lc $basename; - $tbl = lc $tbl; - } - - unless (defined $searchdir) { - $searchdir = File::Spec->file_name_is_absolute ($dir) - ? ($dir =~ s{/$}{}, $dir) - : Cwd::abs_path (File::Spec->catdir ($meta->{f_dir}, $dir)); - } - -d $searchdir or - croak "-d $searchdir: $!"; - - $searchdir eq $meta->{f_dir} and - $dir = ""; - - unless ($user_spec_file) { - $file_is_table and $file = "$basename$ext"; - - # Fully Qualified File Name - my $cmpsub; - if ($respect_case) { - $cmpsub = sub { - my ($fn, undef, $sfx) = File::Basename::fileparse ($_, $fn_any_ext_regex); - $^O eq "VMS" && $sfx eq "." and - $sfx = ""; # no extension turns up as a dot - $fn eq $basename and - return (lc $sfx eq lc $ext or !$req && !$sfx); - return 0; - } - } - else { - $cmpsub = sub { - my ($fn, undef, $sfx) = File::Basename::fileparse ($_, $fn_any_ext_regex); - $^O eq "VMS" && $sfx eq "." and - $sfx = ""; # no extension turns up as a dot - lc $fn eq lc $basename and - return (lc $sfx eq lc $ext or !$req && !$sfx); - return 0; - } - } - - my @f; - { my $dh = IO::Dir->new ($searchdir) or croak "Can't open '$searchdir': $!"; - @f = sort { length $b <=> length $a } - grep { &$cmpsub ($_) } - $dh->read (); - $dh->close () or croak "Can't close '$searchdir': $!"; - } - @f > 0 && @f <= 2 and $file = $f[0]; - !$respect_case && $meta->{sql_identifier_case} == 4 and # XXX SQL_IC_MIXED - ($tbl = $file) =~ s/\Q$ext\E$//i; - - my $tmpfn = $file; - if ($ext && $req) { - # File extension required - $tmpfn =~ s/\Q$ext\E$//i or return; - } - } - - my $fqfn = File::Spec->catfile ($searchdir, $file); - my $fqbn = File::Spec->catfile ($searchdir, $basename); - - $meta->{f_fqfn} = $fqfn; - $meta->{f_fqbn} = $fqbn; - defined $meta->{f_lockfile} && $meta->{f_lockfile} and - $meta->{f_fqln} = $meta->{f_fqbn} . $meta->{f_lockfile}; - - $dir && !$user_spec_file and $tbl = File::Spec->catfile ($dir, $tbl); - $meta->{table_name} = $tbl; - - return $tbl; - } # complete_table_name - -sub open_data -{ - my ($self, $meta, $attrs, $flags) = @_; - - defined $meta->{f_fqfn} && $meta->{f_fqfn} ne "" or croak "No filename given"; - - my ($fh, $fn); - unless ($meta->{f_dontopen}) { - $fn = $meta->{f_fqfn}; - if ($flags->{createMode}) { - -f $meta->{f_fqfn} and - croak "Cannot create table $attrs->{table}: Already exists"; - $fh = IO::File->new ($fn, "a+") or - croak "Cannot open $fn for writing: $! (" . ($!+0) . ")"; - } - else { - unless ($fh = IO::File->new ($fn, ($flags->{lockMode} ? "r+" : "r"))) { - croak "Cannot open $fn: $! (" . ($!+0) . ")"; - } - } - - $meta->{fh} = $fh; - - if ($fh) { - $fh->seek (0, 0) or - croak "Error while seeking back: $!"; - - $self->apply_encoding ($meta); - } - } - if ($meta->{f_fqln}) { - $fn = $meta->{f_fqln}; - if ($flags->{createMode}) { - -f $fn and - croak "Cannot create table lock at '$fn' for $attrs->{table}: Already exists"; - $fh = IO::File->new ($fn, "a+") or - croak "Cannot open $fn for writing: $! (" . ($!+0) . ")"; - } - else { - unless ($fh = IO::File->new ($fn, ($flags->{lockMode} ? "r+" : "r"))) { - croak "Cannot open $fn: $! (" . ($!+0) . ")"; - } - } - - $meta->{lockfh} = $fh; - } - - if ($self->can_flock && $fh) { - my $lm = defined $flags->{f_lock} - && $flags->{f_lock} =~ m/^[012]$/ - ? $flags->{f_lock} - : $flags->{lockMode} ? 2 : 1; - if ($lm == 2) { - flock $fh, 2 or croak "Cannot obtain exclusive lock on $fn: $!"; - } - elsif ($lm == 1) { - flock $fh, 1 or croak "Cannot obtain shared lock on $fn: $!"; - } - # $lm = 0 is forced no locking at all - } - } # open_data - -# ====== SQL::STATEMENT ======================================================== - -package DBD::File::Statement; - -use strict; -use warnings; - -@DBD::File::Statement::ISA = qw( DBI::DBD::SqlEngine::Statement ); - -# ====== SQL::TABLE ============================================================ - -package DBD::File::Table; - -use strict; -use warnings; - -use Carp; -require IO::File; -require File::Basename; -require File::Spec; -require Cwd; -require Scalar::Util; - -@DBD::File::Table::ISA = qw( DBI::DBD::SqlEngine::Table ); - -# ====== UTILITIES ============================================================ - -if (eval { require Params::Util; }) { - Params::Util->import ("_HANDLE"); - } -else { - # taken but modified from Params::Util ... - *_HANDLE = sub { - # It has to be defined, of course - defined $_[0] or return; - - # Normal globs are considered to be file handles - ref $_[0] eq "GLOB" and return $_[0]; - - # Check for a normal tied filehandle - # Side Note: 5.5.4's tied () and can () doesn't like getting undef - tied ($_[0]) and tied ($_[0])->can ("TIEHANDLE") and return $_[0]; - - # There are no other non-object handles that we support - Scalar::Util::blessed ($_[0]) or return; - - # Check for a common base classes for conventional IO::Handle object - $_[0]->isa ("IO::Handle") and return $_[0]; - - # Check for tied file handles using Tie::Handle - $_[0]->isa ("Tie::Handle") and return $_[0]; - - # IO::Scalar is not a proper seekable, but it is valid is a - # regular file handle - $_[0]->isa ("IO::Scalar") and return $_[0]; - - # Yet another special case for IO::String, which refuses (for now - # anyway) to become a subclass of IO::Handle. - $_[0]->isa ("IO::String") and return $_[0]; - - # This is not any sort of object we know about - return; - }; - } - -# ====== FLYWEIGHT SUPPORT ===================================================== - -# Flyweight support for table_info -# The functions file2table, init_table_meta, default_table_meta and -# get_table_meta are using $self arguments for polymorphism only. The -# must not rely on an instantiated DBD::File::Table -sub file2table -{ - my ($self, $meta, $file, $file_is_table, $respect_case) = @_; - - return $meta->{sql_data_source}->complete_table_name ($meta, $file, $respect_case, $file_is_table); - } # file2table - -sub bootstrap_table_meta -{ - my ($self, $dbh, $meta, $table, @other) = @_; - - $self->SUPER::bootstrap_table_meta ($dbh, $meta, $table, @other); - - exists $meta->{f_dir} or $meta->{f_dir} = $dbh->{f_dir}; - exists $meta->{f_dir_search} or $meta->{f_dir_search} = $dbh->{f_dir_search}; - defined $meta->{f_ext} or $meta->{f_ext} = $dbh->{f_ext}; - defined $meta->{f_encoding} or $meta->{f_encoding} = $dbh->{f_encoding}; - exists $meta->{f_lock} or $meta->{f_lock} = $dbh->{f_lock}; - exists $meta->{f_lockfile} or $meta->{f_lockfile} = $dbh->{f_lockfile}; - defined $meta->{f_schema} or $meta->{f_schema} = $dbh->{f_schema}; - - defined $meta->{f_open_file_needed} or - $meta->{f_open_file_needed} = $self->can ("open_file") != DBD::File::Table->can ("open_file"); - - defined ($meta->{sql_data_source}) or - $meta->{sql_data_source} = _HANDLE ($meta->{f_file}) - ? "DBD::File::DataSource::Stream" - : "DBD::File::DataSource::File"; - } # bootstrap_table_meta - -sub get_table_meta ($$$$;$) -{ - my ($self, $dbh, $table, $file_is_table, $respect_case) = @_; - - my $meta = $self->SUPER::get_table_meta ($dbh, $table, $respect_case, $file_is_table); - $table = $meta->{table_name}; - return unless $table; - - return ($table, $meta); - } # get_table_meta - -my %reset_on_modify = ( - f_file => [ "f_fqfn", "sql_data_source" ], - f_dir => "f_fqfn", - f_dir_search => [], - f_ext => "f_fqfn", - f_lockfile => "f_fqfn", # forces new file2table call - ); - -__PACKAGE__->register_reset_on_modify (\%reset_on_modify); - -my %compat_map = map { $_ => "f_$_" } qw( file ext lock lockfile ); - -__PACKAGE__->register_compat_map (\%compat_map); - -# ====== DBD::File <= 0.40 compat stuff ======================================== - -# compat to 0.38 .. 0.40 API -sub open_file -{ - my ($className, $meta, $attrs, $flags) = @_; - - return $className->SUPER::open_data ($meta, $attrs, $flags); - } # open_file - -sub open_data -{ - my ($className, $meta, $attrs, $flags) = @_; - - # compat to 0.38 .. 0.40 API - $meta->{f_open_file_needed} - ? $className->open_file ($meta, $attrs, $flags) - : $className->SUPER::open_data ($meta, $attrs, $flags); - - return; - } # open_data - -# ====== SQL::Eval API ========================================================= - -sub drop ($) -{ - my ($self, $data) = @_; - my $meta = $self->{meta}; - # We have to close the file before unlinking it: Some OS'es will - # refuse the unlink otherwise. - $meta->{fh} and $meta->{fh}->close (); - $meta->{lockfh} and $meta->{lockfh}->close (); - undef $meta->{fh}; - undef $meta->{lockfh}; - $meta->{f_fqfn} and unlink $meta->{f_fqfn}; # XXX ==> sql_data_source - $meta->{f_fqln} and unlink $meta->{f_fqln}; # XXX ==> sql_data_source - delete $data->{Database}{sql_meta}{$self->{table}}; - return 1; - } # drop - -sub seek ($$$$) -{ - my ($self, $data, $pos, $whence) = @_; - my $meta = $self->{meta}; - if ($whence == 0 && $pos == 0) { - $pos = defined $meta->{first_row_pos} ? $meta->{first_row_pos} : 0; - } - elsif ($whence != 2 || $pos != 0) { - croak "Illegal seek position: pos = $pos, whence = $whence"; - } - - $meta->{fh}->seek ($pos, $whence) or - croak "Error while seeking in " . $meta->{f_fqfn} . ": $!"; - } # seek - -sub truncate ($$) -{ - my ($self, $data) = @_; - my $meta = $self->{meta}; - $meta->{fh}->truncate ($meta->{fh}->tell ()) or - croak "Error while truncating " . $meta->{f_fqfn} . ": $!"; - return 1; - } # truncate - -sub DESTROY -{ - my $self = shift; - my $meta = $self->{meta}; - $meta->{fh} and $meta->{fh}->close (); - $meta->{lockfh} and $meta->{lockfh}->close (); - undef $meta->{fh}; - undef $meta->{lockfh}; - - $self->SUPER::DESTROY(); - } # DESTROY - -1; - -__END__ - -=head1 NAME - -DBD::File - Base class for writing file based DBI drivers - -=head1 SYNOPSIS - -This module is a base class for writing other Ls. -It is not intended to function as a DBD itself (though it is possible). -If you want to access flat files, use L, or -L (both of which are subclasses of DBD::File). - -=head1 DESCRIPTION - -The DBD::File module is not a true L driver, but an abstract -base class for deriving concrete DBI drivers from it. The implication -is, that these drivers work with plain files, for example CSV files or -INI files. The module is based on the L -module, a simple SQL engine. - -See L for details on DBI, L for -details on SQL::Statement and L, L -or L for example drivers. - -=head2 Metadata - -The following attributes are handled by DBI itself and not by DBD::File, -thus they all work as expected: - - Active - ActiveKids - CachedKids - CompatMode (Not used) - InactiveDestroy - AutoInactiveDestroy - Kids - PrintError - RaiseError - Warn (Not used) - -=head3 The following DBI attributes are handled by DBD::File: - -=head4 AutoCommit - -Always on. - -=head4 ChopBlanks - -Works. - -=head4 NUM_OF_FIELDS - -Valid after C<< $sth->execute >>. - -=head4 NUM_OF_PARAMS - -Valid after C<< $sth->prepare >>. - -=head4 NAME - -Valid after C<< $sth->execute >>; undef for Non-Select statements. - -=head4 NULLABLE - -Not really working, always returns an array ref of ones, except the -affected table has been created in this session. Valid after -C<< $sth->execute >>; undef for non-select statements. - -=head3 Unsupported DBI attributes and methods - -=head4 bind_param_inout - -=head4 CursorName - -=head4 LongReadLen - -=head4 LongTruncOk - -=head3 DBD::File specific attributes - -In addition to the DBI attributes, you can use the following dbh -attributes: - -=head4 f_dir - -This attribute is used for setting the directory where the files are -opened and it defaults to the current directory (F<.>). Usually you set -it on the dbh but it may be overridden per table (see L). - -When the value for C is a relative path, it is converted into -the appropriate absolute path name (based on the current working -directory) when the dbh attribute is set. - - f_dir => "/data/foo/csv", - -See L. - -=head4 f_dir_search - -This optional attribute can be set to pass a list of folders to also -find existing tables. It will B be used to create new files. - - f_dir_search => [ "/data/bar/csv", "/dump/blargh/data" ], - -=head4 f_ext - -This attribute is used for setting the file extension. The format is: - - extension{/flag} - -where the /flag is optional and the extension is case-insensitive. -C allows you to specify an extension which: - - f_ext => ".csv/r", - -=over - -=item * - -makes DBD::File prefer F over F
. - -=item * - -makes the table name the filename minus the extension. - -=back - - DBI:CSV:f_dir=data;f_ext=.csv - -In the above example and when C contains both F and -F
, DBD::File will open F and the table will be -named "table". If F does not exist but F
does -that file is opened and the table is also called "table". - -If C is not specified and F exists it will be opened -and the table will be called "table.csv" which is probably not what -you want. - -NOTE: even though extensions are case-insensitive, table names are -not. - - DBI:CSV:f_dir=data;f_ext=.csv/r - -The C flag means the file extension is required and any filename -that does not match the extension is ignored. - -Usually you set it on the dbh but it may be overridden per table -(see L). - -=head4 f_schema - -This will set the schema name and defaults to the owner of the -directory in which the table file resides. You can set C to -C. - - my $dbh = DBI->connect ("dbi:CSV:", "", "", { - f_schema => undef, - f_dir => "data", - f_ext => ".csv/r", - }) or die $DBI::errstr; - -By setting the schema you affect the results from the tables call: - - my @tables = $dbh->tables (); - - # no f_schema - "merijn".foo - "merijn".bar - - # f_schema => "dbi" - "dbi".foo - "dbi".bar - - # f_schema => undef - foo - bar - -Defining C to the empty string is equal to setting it to C -so the DSN can be C<"dbi:CSV:f_schema=;f_dir=.">. - -=head4 f_lock - -The C attribute is used to set the locking mode on the opened -table files. Note that not all platforms support locking. By default, -tables are opened with a shared lock for reading, and with an -exclusive lock for writing. The supported modes are: - - 0: No locking at all. - - 1: Shared locks will be used. - - 2: Exclusive locks will be used. - -But see L below. - -=head4 f_lockfile - -If you wish to use a lockfile extension other than C<.lck>, simply specify -the C attribute: - - $dbh = DBI->connect ("dbi:DBM:f_lockfile=.foo"); - $dbh->{f_lockfile} = ".foo"; - $dbh->{dbm_tables}{qux}{f_lockfile} = ".foo"; - -If you wish to disable locking, set the C to C<0>. - - $dbh = DBI->connect ("dbi:DBM:f_lockfile=0"); - $dbh->{f_lockfile} = 0; - $dbh->{dbm_tables}{qux}{f_lockfile} = 0; - -=head4 f_encoding - -With this attribute, you can set the encoding in which the file is opened. -This is implemented using C<< binmode $fh, ":encoding()" >>. - -=head4 f_meta - -Private data area aliasing L which -contains information about the tables this module handles. Table meta -data might not be available until the table has been accessed for the -first time e.g., by issuing a select on it however it is possible to -pre-initialize attributes for each table you use. - -DBD::File recognizes the (public) attributes C, C, -C, C, C, C, C, -in addition to the attributes L already -supports. Be very careful when modifying attributes you do not know, -the consequence might be a destroyed or corrupted table. - -C is an attribute applicable to table meta data only and you -will not find a corresponding attribute in the dbh. Whilst it may be -reasonable to have several tables with the same column names, it is -not for the same file name. If you need access to the same file using -different table names, use C as the SQL engine and the -C keyword: - - SELECT * FROM tbl AS t1, tbl AS t2 WHERE t1.id = t2.id - -C can be an absolute path name or a relative path name but if -it is relative, it is interpreted as being relative to the C -attribute of the table meta data. When C is set DBD::File will -use C as specified and will not attempt to work out an -alternative for C using the C
and C -attribute. - -While C is a private and readonly attribute (which means, you -cannot modify it's values), derived drivers might provide restricted -write access through another attribute. Well known accessors are -C for L, C for L and -C for L. - -=head3 New opportunities for attributes from DBI::DBD::SqlEngine - -=head4 sql_table_source - -C<< $dbh->{sql_table_source} >> can be set to -I (and is the default setting -of DBD::File). This provides usual behaviour of previous DBD::File -releases on - - @ary = DBI->data_sources ($driver); - @ary = DBI->data_sources ($driver, \%attr); - - @ary = $dbh->data_sources (); - @ary = $dbh->data_sources (\%attr); - - @names = $dbh->tables ($catalog, $schema, $table, $type); - - $sth = $dbh->table_info ($catalog, $schema, $table, $type); - $sth = $dbh->table_info ($catalog, $schema, $table, $type, \%attr); - - $dbh->func ("list_tables"); - -=head4 sql_data_source - -C<< $dbh->{sql_data_source} >> can be set to either -I, which is default and provides the -well known behavior of DBD::File releases prior to 0.41, or -I, which reuses already opened -file-handle for operations. - -=head3 Internally private attributes to deal with SQL backends - -Do not modify any of these private attributes unless you understand -the implications of doing so. The behavior of DBD::File and derived -DBDs might be unpredictable when one or more of those attributes are -modified. - -=head4 sql_nano_version - -Contains the version of loaded DBI::SQL::Nano. - -=head4 sql_statement_version - -Contains the version of loaded SQL::Statement. - -=head4 sql_handler - -Contains either the text 'SQL::Statement' or 'DBI::SQL::Nano'. - -=head4 sql_ram_tables - -Contains optionally temporary tables. - -=head4 sql_flags - -Contains optional flags to instantiate the SQL::Parser parsing engine -when SQL::Statement is used as SQL engine. See L for valid -flags. - -=head2 Driver private methods - -=head3 Default DBI methods - -=head4 data_sources - -The C method returns a list of subdirectories of the current -directory in the form "dbi:CSV:f_dir=$dirname". - -If you want to read the subdirectories of another directory, use - - my ($drh) = DBI->install_driver ("CSV"); - my (@list) = $drh->data_sources (f_dir => "/usr/local/csv_data"); - -=head3 Additional methods - -The following methods are only available via their documented name when -DBD::File is used directly. Because this is only reasonable for testing -purposes, the real names must be used instead. Those names can be computed -by replacing the C in the method name with the driver prefix. - -=head4 f_versions - -Signature: - - sub f_versions (;$) - { - my ($table_name) = @_; - $table_name ||= "."; - ... - } - -Returns the versions of the driver, including the DBI version, the Perl -version, DBI::PurePerl version (if DBI::PurePerl is active) and the version -of the SQL engine in use. - - my $dbh = DBI->connect ("dbi:File:"); - my $f_versions = $dbh->func ("f_versions"); - print "$f_versions\n"; - __END__ - # DBD::File 0.41 using IO::File (1.16) - # DBI::DBD::SqlEngine 0.05 using SQL::Statement 1.406 - # DBI 1.623 - # OS darwin (12.2.1) - # Perl 5.017006 (darwin-thread-multi-ld-2level) - -Called in list context, f_versions will return an array containing each -line as single entry. - -Some drivers might use the optional (table name) argument and modify -version information related to the table (e.g. DBD::DBM provides storage -backend information for the requested table, when it has a table name). - -=head1 KNOWN BUGS AND LIMITATIONS - -=over 4 - -=item * - -This module uses flock () internally but flock is not available on all -platforms. On MacOS and Windows 95 there is no locking at all (perhaps -not so important on MacOS and Windows 95, as there is only a single -user). - -=item * - -The module stores details about the handled tables in a private area -of the driver handle (C<$drh>). This data area is not shared between -different driver instances, so several C<< DBI->connect () >> calls will -cause different table instances and private data areas. - -This data area is filled for the first time when a table is accessed, -either via an SQL statement or via C and is not -destroyed until the table is dropped or the driver handle is released. -Manual destruction is possible via L. - -The following attributes are preserved in the data area and will -evaluated instead of driver globals: - -=over 8 - -=item f_ext - -=item f_dir - -=item f_dir_search - -=item f_lock - -=item f_lockfile - -=item f_encoding - -=item f_schema - -=item col_names - -=item sql_identifier_case - -=back - -The following attributes are preserved in the data area only and -cannot be set globally. - -=over 8 - -=item f_file - -=back - -The following attributes are preserved in the data area only and are -computed when initializing the data area: - -=over 8 - -=item f_fqfn - -=item f_fqbn - -=item f_fqln - -=item table_name - -=back - -For DBD::CSV tables this means, once opened "foo.csv" as table named "foo", -another table named "foo" accessing the file "foo.txt" cannot be opened. -Accessing "foo" will always access the file "foo.csv" in memorized -C, locking C via memorized C. - -You can use L or the C attribute for a specific table -to work around this. - -=item * - -When used with SQL::Statement and temporary tables e.g., - - CREATE TEMP TABLE ... - -the table data processing bypasses DBD::File::Table. No file system -calls will be made and there are no clashes with existing (file based) -tables with the same name. Temporary tables are chosen over file -tables, but they will not covered by C. - -=back - -=head1 AUTHOR - -This module is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -The original author is Jochen Wiedmann. - -=head1 COPYRIGHT AND LICENSE - - Copyright (C) 2009-2013 by H.Merijn Brand & Jens Rehsack - Copyright (C) 2004-2009 by Jeff Zucker - Copyright (C) 1998-2004 by Jochen Wiedmann - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=head1 SEE ALSO - -L, L, L, L, -L, L, and -L - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/File/Developers.pod b/dbLifeLog/DBI-1.641/lib/DBD/File/Developers.pod deleted file mode 100644 index 1c1b21b..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/File/Developers.pod +++ /dev/null @@ -1,665 +0,0 @@ -=head1 NAME - -DBD::File::Developers - Developers documentation for DBD::File - -=head1 SYNOPSIS - - package DBD::myDriver; - - use base qw( DBD::File ); - - sub driver - { - ... - my $drh = $proto->SUPER::driver ($attr); - ... - return $drh->{class}; - } - - sub CLONE { ... } - - package DBD::myDriver::dr; - - @ISA = qw( DBD::File::dr ); - - sub data_sources { ... } - ... - - package DBD::myDriver::db; - - @ISA = qw( DBD::File::db ); - - sub init_valid_attributes { ... } - sub init_default_attributes { ... } - sub set_versions { ... } - sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } - sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } - sub get_myd_versions { ... } - - package DBD::myDriver::st; - - @ISA = qw( DBD::File::st ); - - sub FETCH { ... } - sub STORE { ... } - - package DBD::myDriver::Statement; - - @ISA = qw( DBD::File::Statement ); - - package DBD::myDriver::Table; - - @ISA = qw( DBD::File::Table ); - - my %reset_on_modify = ( - myd_abc => "myd_foo", - myd_mno => "myd_bar", - ); - __PACKAGE__->register_reset_on_modify (\%reset_on_modify); - my %compat_map = ( - abc => 'foo_abc', - xyz => 'foo_xyz', - ); - __PACKAGE__->register_compat_map (\%compat_map); - - sub bootstrap_table_meta { ... } - sub init_table_meta { ... } - sub table_meta_attr_changed { ... } - sub open_data { ... } - - sub fetch_row { ... } - sub push_row { ... } - sub push_names { ... } - - # optimize the SQL engine by add one or more of - sub update_current_row { ... } - # or - sub update_specific_row { ... } - # or - sub update_one_row { ... } - # or - sub insert_new_row { ... } - # or - sub delete_current_row { ... } - # or - sub delete_one_row { ... } - -=head1 DESCRIPTION - -This document describes how DBD developers can write DBD::File based DBI -drivers. It supplements L and L, -which you should read first. - -=head1 CLASSES - -Each DBI driver must provide a package global C method and three -DBI related classes: - -=over 4 - -=item DBD::File::dr - -Driver package, contains the methods DBI calls indirectly via DBI -interface: - - DBI->connect ('DBI:DBM:', undef, undef, {}) - - # invokes - package DBD::DBM::dr; - @DBD::DBM::dr::ISA = qw( DBD::File::dr ); - - sub connect ($$;$$$) - { - ... - } - -Similar for C<< data_sources >> and C<< disconnect_all >>. - -Pure Perl DBI drivers derived from DBD::File do not usually need to -override any of the methods provided through the DBD::XXX::dr package -however if you need additional initialization in the connect method -you may need to. - -=item DBD::File::db - -Contains the methods which are called through DBI database handles -(C<< $dbh >>). e.g., - - $sth = $dbh->prepare ("select * from foo"); - # returns the f_encoding setting for table foo - $dbh->csv_get_meta ("foo", "f_encoding"); - -DBD::File provides the typical methods required here. Developers who -write DBI drivers based on DBD::File need to override the methods C<< -set_versions >> and C<< init_valid_attributes >>. - -=item DBD::File::st - -Contains the methods to deal with prepared statement handles. e.g., - - $sth->execute () or die $sth->errstr; - -=back - -=head2 DBD::File - -This is the main package containing the routines to initialize -DBD::File based DBI drivers. Primarily the C<< DBD::File::driver >> -method is invoked, either directly from DBI when the driver is -initialized or from the derived class. - - package DBD::DBM; - - use base qw( DBD::File ); - - sub driver - { - my ($class, $attr) = @_; - ... - my $drh = $class->SUPER::driver ($attr); - ... - return $drh; - } - -It is not necessary to implement your own driver method as long as -additional initialization (e.g. installing more private driver -methods) is not required. You do not need to call C<< setup_driver >> -as DBD::File takes care of it. - -=head2 DBD::File::dr - -The driver package contains the methods DBI calls indirectly via the DBI -interface (see L). - -DBD::File based DBI drivers usually do not need to implement anything here, -it is enough to do the basic initialization: - - package DBD:XXX::dr; - - @DBD::XXX::dr::ISA = qw (DBD::File::dr); - $DBD::XXX::dr::imp_data_size = 0; - $DBD::XXX::dr::data_sources_attr = undef; - $DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann"; - -=head2 DBD::File::db - -This package defines the database methods, which are called via the DBI -database handle C<< $dbh >>. - -Methods provided by DBD::File: - -=over 4 - -=item ping - -Simply returns the content of the C<< Active >> attribute. Override -when your driver needs more complicated actions here. - -=item prepare - -Prepares a new SQL statement to execute. Returns a statement handle, -C<< $sth >> - instance of the DBD:XXX::st. It is neither required nor -recommended to override this method. - -=item FETCH - -Fetches an attribute of a DBI database object. Private handle attributes -must have a prefix (this is mandatory). If a requested attribute is -detected as a private attribute without a valid prefix, the driver prefix -(written as C<$drv_prefix>) is added. - -The driver prefix is extracted from the attribute name and verified against -C<< $dbh->{$drv_prefix . "valid_attrs"} >> (when it exists). If the -requested attribute value is not listed as a valid attribute, this method -croaks. If the attribute is valid and readonly (listed in C<< $dbh->{ -$drv_prefix . "readonly_attrs" } >> when it exists), a real copy of the -attribute value is returned. So it's not possible to modify -C from outside of DBD::File::db or a derived class. - -=item STORE - -Stores a database private attribute. Private handle attributes must have a -prefix (this is mandatory). If a requested attribute is detected as a private -attribute without a valid prefix, the driver prefix (written as -C<$drv_prefix>) is added. If the database handle has an attribute -C<${drv_prefix}_valid_attrs> - for attribute names which are not listed in -that hash, this method croaks. If the database handle has an attribute -C<${drv_prefix}_readonly_attrs>, only attributes which are not listed there -can be stored (once they are initialized). Trying to overwrite such an -immutable attribute forces this method to croak. - -An example of a valid attributes list can be found in -C<< DBD::File::db::init_valid_attributes >>. - -=item set_versions - -This method sets the attribute C with the version of DBD::File. - -This method is called at the begin of the C phase. - -When overriding this method, do not forget to invoke the superior one. - -=item init_valid_attributes - -This method is called after the database handle is instantiated as the -first attribute initialization. - -C<< DBD::File::db::init_valid_attributes >> initializes the attributes -C and C. - -When overriding this method, do not forget to invoke the superior one, -preferably before doing anything else. Compatibility table attribute -access must be initialized here to allow DBD::File to instantiate the -map tie: - - # for DBD::CSV - $dbh->{csv_meta} = "csv_tables"; - # for DBD::DBM - $dbh->{dbm_meta} = "dbm_tables"; - # for DBD::AnyData - $dbh->{ad_meta} = "ad_tables"; - -=item init_default_attributes - -This method is called after the database handle is instantiated to -initialize the default attributes. - -C<< DBD::File::db::init_default_attributes >> initializes the attributes -C, C, C, C. - -When the derived implementor class provides the attribute to validate -attributes (e.g. C<< $dbh->{dbm_valid_attrs} = {...}; >>) or the attribute -containing the immutable attributes (e.g. -C<< $dbh->{dbm_readonly_attrs} = {...}; >>), the attributes -C, C, C and C -are added (when available) to the list of valid and immutable attributes -(where C is interpreted as the driver prefix). - -If C is set, an attribute with the name in C is -initialized providing restricted read/write access to the meta data of the -tables using C in the first (table) level and -C for the meta attribute level. C -uses C to initialize the second level -tied hash on FETCH/STORE. The C class uses -C to FETCH attribute values and -C to STORE attribute values. This -allows it to map meta attributes for compatibility reasons. - -=item get_single_table_meta - -=item get_file_meta - -Retrieve an attribute from a table's meta information. The method -signature is C<< get_file_meta ($dbh, $table, $attr) >>. This method -is called by the injected db handle method C<< ${drv_prefix}get_meta >>. - -While get_file_meta allows C<$table> or C<$attr> to be a list of tables or -attributes to retrieve, get_single_table_meta allows only one table name -and only one attribute name. A table name of C<'.'> (single dot) is -interpreted as the default table and this will retrieve the appropriate -attribute globally from the dbh. This has the same restrictions as -C<< $dbh->{$attrib} >>. - -get_file_meta allows C<'+'> and C<'*'> as wildcards for table names and -C<$table> being a regular expression matching against the table names -(evaluated without the default table). The table name C<'*'> is -I. The table -name C<'+'> is I (/^[_A-Za-z0-9]+$/). - -The table meta information is retrieved using the get_table_meta and -get_table_meta_attr methods of the table class of the implementation. - -=item set_single_table_meta - -=item set_file_meta - -Sets an attribute in a table's meta information. The method signature is -C<< set_file_meta ($dbh, $table, $attr, $value) >>. This method is called -by the injected db handle method C<< ${drv_prefix}set_meta >>. - -While set_file_meta allows C<$table> to be a list of tables and C<$attr> -to be a hash of several attributes to set, set_single_table_meta allows -only one table name and only one attribute name/value pair. - -The wildcard characters for the table name are the same as for -get_file_meta. - -The table meta information is updated using the get_table_meta and -set_table_meta_attr methods of the table class of the implementation. - -=item clear_file_meta - -Clears all meta information cached about a table. The method signature is -C<< clear_file_meta ($dbh, $table) >>. This method is called -by the injected db handle method C<< ${drv_prefix}clear_meta >>. - -=back - -=head2 DBD::File::st - -Contains the methods to deal with prepared statement handles: - -=over 4 - -=item FETCH - -Fetches statement handle attributes. Supported attributes (for full overview -see L) are C, C, C -and C in case that SQL::Statement is used as SQL execution engine -and a statement is successful prepared. When SQL::Statement has additional -information about a table, those information are returned. Otherwise, the -same defaults as in L are used. - -This method usually requires extending in a derived implementation. -See L or L for some example. - -=back - -=head2 DBD::File::TableSource::FileSystem - -Provides data sources and table information on database driver and database -handle level. - - package DBD::File::TableSource::FileSystem; - - sub data_sources ($;$) - { - my ($class, $drh, $attrs) = @_; - ... - } - - sub avail_tables - { - my ($class, $drh) = @_; - ... - } - -The C method is called when the user invokes any of the -following: - - @ary = DBI->data_sources ($driver); - @ary = DBI->data_sources ($driver, \%attr); - - @ary = $dbh->data_sources (); - @ary = $dbh->data_sources (\%attr); - -The C method is called when the user invokes any of the -following: - - @names = $dbh->tables ($catalog, $schema, $table, $type); - - $sth = $dbh->table_info ($catalog, $schema, $table, $type); - $sth = $dbh->table_info ($catalog, $schema, $table, $type, \%attr); - - $dbh->func ("list_tables"); - -Every time where an C<\%attr> argument can be specified, this C<\%attr> -object's C attribute is preferred over the C<$dbh> -attribute or the driver default. - -=head2 DBD::File::DataSource::Stream - - package DBD::File::DataSource::Stream; - - @DBD::File::DataSource::Stream::ISA = 'DBI::DBD::SqlEngine::DataSource'; - - sub complete_table_name - { - my ($self, $meta, $file, $respect_case) = @_; - ... - } - -Clears all meta attributes identifying a file: C, C and -C. The table name is set according to C<$respect_case> and -C<< $meta->{sql_identifier_case} >> (SQL_IC_LOWER, SQL_IC_UPPER). - - package DBD::File::DataSource::Stream; - - sub apply_encoding - { - my ($self, $meta, $fn) = @_; - ... - } - -Applies the encoding from I (C<< $meta->{f_encoding} >>) -to the file handled opened in C. - - package DBD::File::DataSource::Stream; - - sub open_data - { - my ($self, $meta, $attrs, $flags) = @_; - ... - } - -Opens (C) the file handle provided in C<< $meta->{f_file} >>. - - package DBD::File::DataSource::Stream; - - sub can_flock { ... } - -Returns whether C is available or not (avoids retesting in -subclasses). - -=head2 DBD::File::DataSource::File - - package DBD::File::DataSource::File; - - sub complete_table_name ($$;$) - { - my ($self, $meta, $table, $respect_case) = @_; - ... - } - -The method C tries to map a filename to the associated -table name. It is called with a partially filled meta structure for the -resulting table containing at least the following attributes: -C<< f_ext >>, C<< f_dir >>, C<< f_lockfile >> and C<< sql_identifier_case >>. - -If a file/table map can be found then this method sets the C<< f_fqfn ->>, C<< f_fqbn >>, C<< f_fqln >> and C<< table_name >> attributes in -the meta structure. If a map cannot be found the table name will be -undef. - - package DBD::File::DataSource::File; - - sub open_data ($) - { - my ($self, $meta, $attrs, $flags) = @_; - ... - } - -Depending on the attributes set in the table's meta data, the -following steps are performed. Unless C<< f_dontopen >> is set to a -true value, C<< f_fqfn >> must contain the full qualified file name -for the table to work on (file2table ensures this). The encoding in -C<< f_encoding >> is applied if set and the file is opened. If -C<> (full qualified lock name) is set, this file is opened, -too. Depending on the value in C<< f_lock >>, the appropriate lock is -set on the opened data file or lock file. - -=head2 DBD::File::Statement - -Derives from DBI::SQL::Nano::Statement to provide following method: - -=over 4 - -=item open_table - -Implements the open_table method required by L and -L. All the work for opening the file(s) belonging to the -table is handled and parametrized in DBD::File::Table. Unless you intend -to add anything to the following implementation, an empty DBD::XXX::Statement -package satisfies DBD::File. - - sub open_table ($$$$$) - { - my ($self, $data, $table, $createMode, $lockMode) = @_; - - my $class = ref $self; - $class =~ s/::Statement/::Table/; - - my $flags = { - createMode => $createMode, - lockMode => $lockMode, - }; - $self->{command} eq "DROP" and $flags->{dropMode} = 1; - - return $class->new ($data, { table => $table }, $flags); - } # open_table - -=back - -=head2 DBD::File::Table - -Derives from DBI::SQL::Nano::Table and provides physical file access for -the table data which are stored in the files. - -=over 4 - -=item bootstrap_table_meta - -Initializes a table meta structure. Can be safely overridden in a -derived class, as long as the C<< SUPER >> method is called at the end -of the overridden method. - -It copies the following attributes from the database into the table meta data -C<< f_dir >>, C<< f_ext >>, C<< f_encoding >>, C<< f_lock >>, C<< f_schema >> -and C<< f_lockfile >> and makes them sticky to the table. - -This method should be called before you attempt to map between file -name and table name to ensure the correct directory, extension etc. are -used. - -=item init_table_meta - -Initializes more attributes of the table meta data - usually more -expensive ones (e.g. those which require class instantiations) - when -the file name and the table name could mapped. - -=item get_table_meta - -Returns the table meta data. If there are none for the required -table, a new one is initialized. When it fails, nothing is -returned. On success, the name of the table and the meta data -structure is returned. - -=item get_table_meta_attr - -Returns a single attribute from the table meta data. If the attribute -name appears in C<%compat_map>, the attribute name is updated from -there. - -=item set_table_meta_attr - -Sets a single attribute in the table meta data. If the attribute -name appears in C<%compat_map>, the attribute name is updated from -there. - -=item table_meta_attr_changed - -Called when an attribute of the meta data is modified. - -If the modified attribute requires to reset a calculated attribute, the -calculated attribute is reset (deleted from meta data structure) and -the I flag is removed, too. The decision is made based on -C<%register_reset_on_modify>. - -=item register_reset_on_modify - -Allows C to reset meta attributes when special -attributes are modified. For DBD::File, modifying one of C, C, -C or C will reset C. DBD::DBM extends the -list for C and C to reset the value of C. - -If your DBD has calculated values in the meta data area, then call -C: - - my %reset_on_modify = (xxx_foo => "xxx_bar"); - __PACKAGE__->register_reset_on_modify (\%reset_on_modify); - -=item register_compat_map - -Allows C and C to update the -attribute name to the current favored one: - - # from DBD::DBM - my %compat_map = (dbm_ext => "f_ext"); - __PACKAGE__->register_compat_map (\%compat_map); - -=item open_file - -Called to open the table's data file. - -Depending on the attributes set in the table's meta data, the -following steps are performed. Unless C<< f_dontopen >> is set to a -true value, C<< f_fqfn >> must contain the full qualified file name -for the table to work on (file2table ensures this). The encoding in -C<< f_encoding >> is applied if set and the file is opened. If -C<> (full qualified lock name) is set, this file is opened, -too. Depending on the value in C<< f_lock >>, the appropriate lock is -set on the opened data file or lock file. - -After this is done, a derived class might add more steps in an overridden -C<< open_file >> method. - -=item new - -Instantiates the table. This is done in 3 steps: - - 1. get the table meta data - 2. open the data file - 3. bless the table data structure using inherited constructor new - -It is not recommended to override the constructor of the table class. -Find a reasonable place to add you extensions in one of the above four -methods. - -=item drop - -Implements the abstract table method for the C<< DROP >> -command. Discards table meta data after all files belonging to the -table are closed and unlinked. - -Overriding this method might be reasonable in very rare cases. - -=item seek - -Implements the abstract table method used when accessing the table from the -engine. C<< seek >> is called every time the engine uses dumb algorithms -for iterating over the table content. - -=item truncate - -Implements the abstract table method used when dumb table algorithms -for C<< UPDATE >> or C<< DELETE >> need to truncate the table storage -after the last written row. - -=back - -You should consult the documentation of C<< SQL::Eval::Table >> (see -L) to get more information about the abstract methods of the -table's base class you have to override and a description of the table -meta information expected by the SQL engines. - -=head1 AUTHOR - -The module DBD::File is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -The original author is Jochen Wiedmann. - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2010-2013 by H.Merijn Brand & Jens Rehsack - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/File/HowTo.pod b/dbLifeLog/DBI-1.641/lib/DBD/File/HowTo.pod deleted file mode 100644 index 9531b22..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/File/HowTo.pod +++ /dev/null @@ -1,191 +0,0 @@ -=head1 NAME - -DBD::File::HowTo - Guide to create DBD::File based driver - -=head1 SYNOPSIS - - perldoc DBD::File::HowTo - perldoc DBI - perldoc DBI::DBD - perldoc DBD::File::Developers - perldoc DBI::DBD::SqlEngine::Developers - perldoc DBI::DBD::SqlEngine - perldoc SQL::Eval - perldoc DBI::DBD::SqlEngine::HowTo - perldoc SQL::Statement::Embed - perldoc DBD::File - perldoc DBD::File::HowTo - perldoc DBD::File::Developers - -=head1 DESCRIPTION - -This document provides a step-by-step guide, how to create a new -C based DBD. It expects that you carefully read the L -documentation and that you're familiar with L and had read and -understood L. - -This document addresses experienced developers who are really sure that -they need to invest time when writing a new DBI Driver. Writing a DBI -Driver is neither a weekend project nor an easy job for hobby coders -after work. Expect one or two man-month of time for the first start. - -Those who are still reading, should be able to sing the rules of -L. - -Of course, DBD::File is a DBI::DBD::SqlEngine and you surely read -L before continuing here. - -=head1 CREATING DRIVER CLASSES - -Do you have an entry in DBI's DBD registry? For this guide, a prefix of -C is assumed. - -=head2 Sample Skeleton - - package DBD::Foo; - - use strict; - use warnings; - use vars qw(@ISA $VERSION); - use base qw(DBD::File); - - use DBI (); - - $VERSION = "0.001"; - - package DBD::Foo::dr; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBD::File::dr); - $imp_data_size = 0; - - package DBD::Foo::db; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBD::File::db); - $imp_data_size = 0; - - package DBD::Foo::st; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBD::File::st); - $imp_data_size = 0; - - package DBD::Foo::Statement; - - use vars qw(@ISA); - - @ISA = qw(DBD::File::Statement); - - package DBD::Foo::Table; - - use vars qw(@ISA); - - @ISA = qw(DBD::File::Table); - - 1; - -Tiny, eh? And all you have now is a DBD named foo which will is able to -deal with temporary tables, as long as you use L. In -L environments, this DBD can do nothing. - -=head2 Start over - -Based on L, we're now having a driver which -could do basic things. Of course, it should now derive from DBD::File -instead of DBI::DBD::SqlEngine, shouldn't it? - -DBD::File extends DBI::DBD::SqlEngine to deal with any kind of files. -In principle, the only extensions required are to the table class: - - package DBD::Foo::Table; - - sub bootstrap_table_meta - { - my ( $self, $dbh, $meta, $table ) = @_; - - # initialize all $meta attributes which might be relevant for - # file2table - - return $self->SUPER::bootstrap_table_meta($dbh, $meta, $table); - } - - sub init_table_meta - { - my ( $self, $dbh, $meta, $table ) = @_; - - # called after $meta contains the results from file2table - # initialize all missing $meta attributes - - $self->SUPER::init_table_meta( $dbh, $meta, $table ); - } - -In case C doesn't open the files as the driver -needs that, override it! - - sub open_file - { - my ( $self, $meta, $attrs, $flags ) = @_; - # ensure that $meta->{f_dontopen} is set - $self->SUPER::open_file( $meta, $attrs, $flags ); - # now do what ever needs to be done - } - -Combined with the methods implemented using the L -guide, the table is full working and you could try a start over. - -=head2 User comfort - -C since C<0.39> consolidates all persistent meta data of a table -into a single structure stored in C<< $dbh->{f_meta} >>. With C -version C<0.41> and C version C<0.05>, this -consolidation moves to L. It's still the -C<< $dbh->{$drv_prefix . "_meta"} >> attribute which cares, so what you -learned at this place before, is still valid. - - sub init_valid_attributes - { - my $dbh = $_[0]; - - $dbh->SUPER::init_valid_attributes (); - - $dbh->{foo_valid_attrs} = { ... }; - $dbh->{foo_readonly_attrs} = { ... }; - - $dbh->{foo_meta} = "foo_tables"; - - return $dbh; - } - -See updates at L. - -=head2 Testing - -Now you should have your own DBD::File based driver. Was easy, wasn't it? -But does it work well? Prove it by writing tests and remember to use -dbd_edit_mm_attribs from L to ensure testing even rare cases. - -=head1 AUTHOR - -This guide is written by Jens Rehsack. DBD::File is written by Jochen -Wiedmann and Jeff Zucker. - -The module DBD::File is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/File/Roadmap.pod b/dbLifeLog/DBI-1.641/lib/DBD/File/Roadmap.pod deleted file mode 100644 index ec91712..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/File/Roadmap.pod +++ /dev/null @@ -1,176 +0,0 @@ -=head1 NAME - -DBD::File::Roadmap - Planned Enhancements for DBD::File and pure Perl DBD's - -Jens Rehsack - May 2010 - -=head1 SYNOPSIS - -This document gives a high level overview of the future of the DBD::File DBI -driver and groundwork for pure Perl DBI drivers. - -The planned enhancements cover features, testing, performance, reliability, -extensibility and more. - -=head1 CHANGES AND ENHANCEMENTS - -=head2 Features - -There are some features missing we would like to add, but there is -no time plan: - -=over 4 - -=item LOCK TABLE - -The newly implemented internal common table meta storage area would allow -us to implement LOCK TABLE support based on file system C -support. - -=item Transaction support - -While DBD::AnyData recommends explicitly committing by importing and -exporting tables, DBD::File might be enhanced in a future version to allow -transparent transactions using the temporary tables of SQL::Statement as -shadow (dirty) tables. - -Transaction support will heavily rely on lock table support. - -=item Data Dictionary Persistence - -SQL::Statement provides dictionary information when a "CREATE TABLE ..." -statement is executed. This dictionary is preserved for some statement -handle attribute fetches (as C or C). - -It is planned to extend DBD::File to support data dictionaries to work -on the tables in it. It is not planned to support one table in different -dictionaries, but you can have several dictionaries in one directory. - -=item SQL Engine selecting on connect - -Currently the SQL engine selected is chosen during the loading of the module -L. Ideally end users should be able to select the engine -used in C<< DBI->connect () >> with a special DBD::File attribute. - -=back - -Other points of view to the planned features (and more features for the -SQL::Statement engine) are shown in L. - -=head2 Testing - -DBD::File and the dependent DBD::DBM requires a lot more automated tests -covering API stability and compatibility with optional modules -like SQL::Statement. - -=head2 Performance - -Several arguments for support of features like indexes on columns -and cursors are made for DBD::CSV (which is a DBD::File based driver, -too). Similar arguments could be made for DBD::DBM, DBD::AnyData, -DBD::RAM or DBD::PO etc. - -To improve the performance of the underlying SQL engines, a clean -re-implementation seems to be required. Currently both engines are -prematurely optimized and therefore it is not trivial to provide -further optimization without the risk of breaking existing features. - -Join the DBI developers IRC channel at L to -participate or post to the DBI Developers Mailing List. - -=head2 Reliability - -DBD::File currently lacks the following points: - -=over 4 - -=item duplicate table names - -It is currently possible to access a table quoted with a relative path -(a) and additionally using an absolute path (b). If (a) and (b) are -the same file that is not recognized (except for -flock protection handled by the Operating System) and two independent -tables are handled. - -=item invalid table names - -The current implementation does not prevent someone choosing a -directory name as a physical file name for the table to open. - -=back - -=head2 Extensibility - -I (Jens Rehsack) have some (partially for example only) DBD's in mind: - -=over 4 - -=item DBD::Sys - -Derive DBD::Sys from a common code base shared with DBD::File which handles -all the emulation DBI needs (as getinfo, SQL engine handling, ...) - -=item DBD::Dir - -Provide a DBD::File derived to work with fixed table definitions through the -file system to demonstrate how DBI / Pure Perl DBDs could handle databases -with hierarchical structures. - -=item DBD::Join - -Provide a DBI driver which is able to manage multiple connections to other -Databases (as DBD::Multiplex), but allow them to point to different data -sources and allow joins between the tables of them: - - # Example - # Let table 'lsof' being a table in DBD::Sys giving a list of open files using lsof utility - # Let table 'dir' being a atable from DBD::Dir - $sth = $dbh->prepare( "select * from dir,lsof where path='/documents' and dir.entry = lsof.filename" ) - $sth->execute(); # gives all open files in '/documents' - ... - - # Let table 'filesys' a DBD::Sys table of known file systems on current host - # Let table 'applications' a table of your Configuration Management Database - # where current applications (relocatable, with mountpoints for filesystems) - # are stored - $sth = dbh->prepare( "select * from applications,filesys where " . - "application.mountpoint = filesys.mountpoint and ". - "filesys.mounted is true" ); - $sth->execute(); # gives all currently mounted applications on this host - -=back - -=head1 PRIORITIES - -Our priorities are focused on current issues. Initially many new test -cases for DBD::File and DBD::DBM should be added to the DBI test -suite. After that some additional documentation on how to use the -DBD::File API will be provided. - -Any additional priorities will come later and can be modified by (paying) -users. - -=head1 RESOURCES AND CONTRIBUTIONS - -See L for I. - -If your company has benefited from DBI, please consider if -it could make a donation to The Perl Foundation "DBI Development" -fund at L to secure future development. - -Alternatively, if your company would benefit from a specific new -DBI feature, please consider sponsoring it's development through -the options listed in the section "Commercial Support from the Author" -on L. - -Using such targeted financing allows you to contribute to DBI -development and rapidly get something specific and directly valuable -to you in return. - -My company also offers annual support contracts for the DBI, which -provide another way to support the DBI and get something specific -in return. Contact me for details. - -Thank you. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer.pm deleted file mode 100644 index 681ed02..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer.pm +++ /dev/null @@ -1,1292 +0,0 @@ -{ - package DBD::Gofer; - - use strict; - - require DBI; - require DBI::Gofer::Request; - require DBI::Gofer::Response; - require Carp; - - our $VERSION = "0.015327"; - -# $Id: Gofer.pm 15326 2012-06-06 16:32:38Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - - - # attributes we'll allow local STORE - our %xxh_local_store_attrib = map { $_=>1 } qw( - Active - CachedKids - Callbacks - DbTypeSubclass - ErrCount Executed - FetchHashKeyName - HandleError HandleSetErr - InactiveDestroy - AutoInactiveDestroy - PrintError PrintWarn - Profile - RaiseError - RootClass - ShowErrorStatement - Taint TaintIn TaintOut - TraceLevel - Warn - dbi_quote_identifier_cache - dbi_connect_closure - dbi_go_execute_unique - ); - our %xxh_local_store_attrib_if_same_value = map { $_=>1 } qw( - Username - dbi_connect_method - ); - - our $drh = undef; # holds driver handle once initialized - our $methods_already_installed; - - sub driver{ - return $drh if $drh; - - DBI->setup_driver('DBD::Gofer'); - - unless ($methods_already_installed++) { - my $opts = { O=> 0x0004 }; # IMA_KEEP_ERR - DBD::Gofer::db->install_method('go_dbh_method', $opts); - DBD::Gofer::st->install_method('go_sth_method', $opts); - DBD::Gofer::st->install_method('go_clone_sth', $opts); - DBD::Gofer::db->install_method('go_cache', $opts); - DBD::Gofer::st->install_method('go_cache', $opts); - } - - my($class, $attr) = @_; - $class .= "::dr"; - ($drh) = DBI::_new_drh($class, { - 'Name' => 'Gofer', - 'Version' => $VERSION, - 'Attribution' => 'DBD Gofer by Tim Bunce', - }); - - $drh; - } - - - sub CLONE { - undef $drh; - } - - - sub go_cache { - my $h = shift; - $h->{go_cache} = shift if @_; - # return handle's override go_cache, if it has one - return $h->{go_cache} if defined $h->{go_cache}; - # or else the transports default go_cache - return $h->{go_transport}->{go_cache}; - } - - - sub set_err_from_response { # set error/warn/info and propagate warnings - my $h = shift; - my $response = shift; - if (my $warnings = $response->warnings) { - warn $_ for @$warnings; - } - my ($err, $errstr, $state) = $response->err_errstr_state; - # Only set_err() if there's an error else leave the current values - # (The current values will normally be set undef by the DBI dispatcher - # except for methods marked KEEPERR such as ping.) - $h->set_err($err, $errstr, $state) if defined $err; - return undef; - } - - - sub install_methods_proxy { - my ($installed_methods) = @_; - while ( my ($full_method, $attr) = each %$installed_methods ) { - # need to install both a DBI dispatch stub and a proxy stub - # (the dispatch stub may be already here due to local driver use) - - DBI->_install_method($full_method, "", $attr||{}) - unless defined &{$full_method}; - - # now install proxy stubs on the driver side - $full_method =~ m/^DBI::(\w\w)::(\w+)$/ - or die "Invalid method name '$full_method' for install_method"; - my ($type, $method) = ($1, $2); - my $driver_method = "DBD::Gofer::${type}::${method}"; - next if defined &{$driver_method}; - my $sub; - if ($type eq 'db') { - $sub = sub { return shift->go_dbh_method(undef, $method, @_) }; - } - else { - $sub = sub { shift->set_err($DBI::stderr, "Can't call \$${type}h->$method when using DBD::Gofer"); return; }; - } - no strict 'refs'; - *$driver_method = $sub; - } - } -} - - -{ package DBD::Gofer::dr; # ====== DRIVER ====== - - $imp_data_size = 0; - use strict; - - sub connect_cached { - my ($drh, $dsn, $user, $auth, $attr)= @_; - $attr ||= {}; - return $drh->SUPER::connect_cached($dsn, $user, $auth, { - (%$attr), - go_connect_method => $attr->{go_connect_method} || 'connect_cached', - }); - } - - - sub connect { - my($drh, $dsn, $user, $auth, $attr)= @_; - my $orig_dsn = $dsn; - - # first remove dsn= and everything after it - my $remote_dsn = ($dsn =~ s/;?\bdsn=(.*)$// && $1) - or return $drh->set_err($DBI::stderr, "No dsn= argument in '$orig_dsn'"); - - if ($attr->{go_bypass}) { # don't use DBD::Gofer for this connection - # useful for testing with DBI_AUTOPROXY, e.g., t/03handle.t - return DBI->connect($remote_dsn, $user, $auth, $attr); - } - - my %go_attr; - # extract any go_ attributes from the connect() attr arg - for my $k (grep { /^go_/ } keys %$attr) { - $go_attr{$k} = delete $attr->{$k}; - } - # then override those with any attributes embedded in our dsn (not remote_dsn) - for my $kv (grep /=/, split /;/, $dsn, -1) { - my ($k, $v) = split /=/, $kv, 2; - $go_attr{ "go_$k" } = $v; - } - - if (not ref $go_attr{go_policy}) { # if not a policy object already - my $policy_class = $go_attr{go_policy} || 'classic'; - $policy_class = "DBD::Gofer::Policy::$policy_class" - unless $policy_class =~ /::/; - _load_class($policy_class) - or return $drh->set_err($DBI::stderr, "Can't load $policy_class: $@"); - # replace policy name in %go_attr with policy object - $go_attr{go_policy} = eval { $policy_class->new(\%go_attr) } - or return $drh->set_err($DBI::stderr, "Can't instanciate $policy_class: $@"); - } - # policy object is left in $go_attr{go_policy} so transport can see it - my $go_policy = $go_attr{go_policy}; - - if ($go_attr{go_cache} and not ref $go_attr{go_cache}) { # if not a cache object already - my $cache_class = $go_attr{go_cache}; - $cache_class = "DBI::Util::CacheMemory" if $cache_class eq '1'; - _load_class($cache_class) - or return $drh->set_err($DBI::stderr, "Can't load $cache_class $@"); - $go_attr{go_cache} = eval { $cache_class->new() } - or $drh->set_err(0, "Can't instanciate $cache_class: $@"); # warning - } - - # delete any other attributes that don't apply to transport - my $go_connect_method = delete $go_attr{go_connect_method}; - - my $transport_class = delete $go_attr{go_transport} - or return $drh->set_err($DBI::stderr, "No transport= argument in '$orig_dsn'"); - $transport_class = "DBD::Gofer::Transport::$transport_class" - unless $transport_class =~ /::/; - _load_class($transport_class) - or return $drh->set_err($DBI::stderr, "Can't load $transport_class: $@"); - my $go_transport = eval { $transport_class->new(\%go_attr) } - or return $drh->set_err($DBI::stderr, "Can't instanciate $transport_class: $@"); - - my $request_class = "DBI::Gofer::Request"; - my $go_request = eval { - my $go_attr = { %$attr }; - # XXX user/pass of fwd server vs db server ? also impact of autoproxy - if ($user) { - $go_attr->{Username} = $user; - $go_attr->{Password} = $auth; - } - # delete any attributes we can't serialize (or don't want to) - delete @{$go_attr}{qw(Profile HandleError HandleSetErr Callbacks)}; - # delete any attributes that should only apply to the client-side - delete @{$go_attr}{qw(RootClass DbTypeSubclass)}; - - $go_connect_method ||= $go_policy->connect_method($remote_dsn, $go_attr) || 'connect'; - $request_class->new({ - dbh_connect_call => [ $go_connect_method, $remote_dsn, $user, $auth, $go_attr ], - }) - } or return $drh->set_err($DBI::stderr, "Can't instanciate $request_class: $@"); - - my ($dbh, $dbh_inner) = DBI::_new_dbh($drh, { - 'Name' => $dsn, - 'USER' => $user, - go_transport => $go_transport, - go_request => $go_request, - go_policy => $go_policy, - }); - - # mark as inactive temporarily for STORE. Active not set until connected() called. - $dbh->STORE(Active => 0); - - # should we ping to check the connection - # and fetch dbh attributes - my $skip_connect_check = $go_policy->skip_connect_check($attr, $dbh); - if (not $skip_connect_check) { - if (not $dbh->go_dbh_method(undef, 'ping')) { - return undef if $dbh->err; # error already recorded, typically - return $dbh->set_err($DBI::stderr, "ping failed"); - } - } - - return $dbh; - } - - sub _load_class { # return true or false+$@ - my $class = shift; - (my $pm = $class) =~ s{::}{/}g; - $pm .= ".pm"; - return 1 if eval { require $pm }; - delete $INC{$pm}; # shouldn't be needed (perl bug?) and assigning undef isn't enough - undef; # error in $@ - } - -} - - -{ package DBD::Gofer::db; # ====== DATABASE ====== - $imp_data_size = 0; - use strict; - use Carp qw(carp croak); - - my %dbh_local_store_attrib = %DBD::Gofer::xxh_local_store_attrib; - - sub connected { - shift->STORE(Active => 1); - } - - sub go_dbh_method { - my $dbh = shift; - my $meta = shift; - # @_ now contains ($method_name, @args) - - my $request = $dbh->{go_request}; - $request->init_request([ wantarray, @_ ], $dbh); - ++$dbh->{go_request_count}; - - my $go_policy = $dbh->{go_policy}; - my $dbh_attribute_update = $go_policy->dbh_attribute_update(); - $request->dbh_attributes( $go_policy->dbh_attribute_list() ) - if $dbh_attribute_update eq 'every' - or $dbh->{go_request_count}==1; - - $request->dbh_last_insert_id_args($meta->{go_last_insert_id_args}) - if $meta->{go_last_insert_id_args}; - - my $transport = $dbh->{go_transport} - or return $dbh->set_err($DBI::stderr, "Not connected (no transport)"); - - local $transport->{go_cache} = $dbh->{go_cache} - if defined $dbh->{go_cache}; - - my ($response, $retransmit_sub) = $transport->transmit_request($request); - $response ||= $transport->receive_response($request, $retransmit_sub); - $dbh->{go_response} = $response - or die "No response object returned by $transport"; - - die "response '$response' returned by $transport is not a response object" - unless UNIVERSAL::isa($response,"DBI::Gofer::Response"); - - if (my $dbh_attributes = $response->dbh_attributes) { - - # XXX installed_methods piggybacks on dbh_attributes for now - if (my $installed_methods = delete $dbh_attributes->{dbi_installed_methods}) { - DBD::Gofer::install_methods_proxy($installed_methods) - if $dbh->{go_request_count}==1; - } - - # XXX we don't STORE here, we just stuff the value into the attribute cache - $dbh->{$_} = $dbh_attributes->{$_} - for keys %$dbh_attributes; - } - - my $rv = $response->rv; - if (my $resultset_list = $response->sth_resultsets) { - # dbh method call returned one or more resultsets - # (was probably a metadata method like table_info) - # - # setup an sth but don't execute/forward it - my $sth = $dbh->prepare(undef, { go_skip_prepare_check => 1 }); - # set the sth response to our dbh response - (tied %$sth)->{go_response} = $response; - # setup the sth with the results in our response - $sth->more_results; - # and return that new sth as if it came from original request - $rv = [ $sth ]; - } - elsif (!$rv) { # should only occur for major transport-level error - #carp("no rv in response { @{[ %$response ]} }"); - $rv = [ ]; - } - - DBD::Gofer::set_err_from_response($dbh, $response); - - return (wantarray) ? @$rv : $rv->[0]; - } - - - # Methods that should be forwarded but can be cached - for my $method (qw( - tables table_info column_info primary_key_info foreign_key_info statistics_info - data_sources type_info_all get_info - parse_trace_flags parse_trace_flag - func - )) { - my $policy_name = "cache_$method"; - my $super_name = "SUPER::$method"; - my $sub = sub { - my $dbh = shift; - my $rv; - - # if we know the remote side doesn't override the DBI's default method - # then we might as well just call the DBI's default method on the client - # (which may, in turn, call other methods that are forwarded, like get_info) - if ($dbh->{dbi_default_methods}{$method} && $dbh->{go_policy}->skip_default_methods()) { - $dbh->trace_msg(" !! $method: using local default as remote method is also default\n"); - return $dbh->$super_name(@_); - } - - my $cache; - my $cache_key; - if (my $cache_it = $dbh->{go_policy}->$policy_name(undef, $dbh, @_)) { - $cache = $dbh->{go_meta_cache} ||= {}; # keep separate from go_cache - $cache_key = sprintf "%s_wa%d(%s)", $policy_name, wantarray||0, - join(",\t", map { # XXX basic but sufficient for now - !ref($_) ? DBI::neat($_,1e6) - : ref($_) eq 'ARRAY' ? DBI::neat_list($_,1e6,",\001") - : ref($_) eq 'HASH' ? do { my @k = sort keys %$_; DBI::neat_list([@k,@{$_}{@k}],1e6,",\002") } - : do { warn "unhandled argument type ($_)"; $_ } - } @_); - if ($rv = $cache->{$cache_key}) { - $dbh->trace_msg("$method(@_) returning previously cached value ($cache_key)\n",4); - my @cache_rv = @$rv; - # if it's an sth we have to clone it - $cache_rv[0] = $cache_rv[0]->go_clone_sth if UNIVERSAL::isa($cache_rv[0],'DBI::st'); - return (wantarray) ? @cache_rv : $cache_rv[0]; - } - } - - $rv = [ (wantarray) - ? ($dbh->go_dbh_method(undef, $method, @_)) - : scalar $dbh->go_dbh_method(undef, $method, @_) - ]; - - if ($cache) { - $dbh->trace_msg("$method(@_) caching return value ($cache_key)\n",4); - my @cache_rv = @$rv; - # if it's an sth we have to clone it - #$cache_rv[0] = $cache_rv[0]->go_clone_sth - # if UNIVERSAL::isa($cache_rv[0],'DBI::st'); - $cache->{$cache_key} = \@cache_rv - unless UNIVERSAL::isa($cache_rv[0],'DBI::st'); # XXX cloning sth not yet done - } - - return (wantarray) ? @$rv : $rv->[0]; - }; - no strict 'refs'; - *$method = $sub; - } - - - # Methods that can use the DBI defaults for some situations/drivers - for my $method (qw( - quote quote_identifier - )) { # XXX keep DBD::Gofer::Policy::Base in sync - my $policy_name = "locally_$method"; - my $super_name = "SUPER::$method"; - my $sub = sub { - my $dbh = shift; - - # if we know the remote side doesn't override the DBI's default method - # then we might as well just call the DBI's default method on the client - # (which may, in turn, call other methods that are forwarded, like get_info) - if ($dbh->{dbi_default_methods}{$method} && $dbh->{go_policy}->skip_default_methods()) { - $dbh->trace_msg(" !! $method: using local default as remote method is also default\n"); - return $dbh->$super_name(@_); - } - - # false: use remote gofer - # 1: use local DBI default method - # code ref: use the code ref - my $locally = $dbh->{go_policy}->$policy_name($dbh, @_); - if ($locally) { - return $locally->($dbh, @_) if ref $locally eq 'CODE'; - return $dbh->$super_name(@_); - } - return $dbh->go_dbh_method(undef, $method, @_); # propagate context - }; - no strict 'refs'; - *$method = $sub; - } - - - # Methods that should always fail - for my $method (qw( - begin_work commit rollback - )) { - no strict 'refs'; - *$method = sub { return shift->set_err($DBI::stderr, "$method not available with DBD::Gofer") } - } - - - sub do { - my ($dbh, $sql, $attr, @args) = @_; - delete $dbh->{Statement}; # avoid "Modification of non-creatable hash value attempted" - $dbh->{Statement} = $sql; # for profiling and ShowErrorStatement - my $meta = { go_last_insert_id_args => $attr->{go_last_insert_id_args} }; - return $dbh->go_dbh_method($meta, 'do', $sql, $attr, @args); - } - - sub ping { - my $dbh = shift; - return $dbh->set_err('', "can't ping while not connected") # info - unless $dbh->SUPER::FETCH('Active'); - my $skip_ping = $dbh->{go_policy}->skip_ping(); - return ($skip_ping) ? 1 : $dbh->go_dbh_method(undef, 'ping', @_); - } - - sub last_insert_id { - my $dbh = shift; - my $response = $dbh->{go_response} or return undef; - return $response->last_insert_id; - } - - sub FETCH { - my ($dbh, $attrib) = @_; - - # FETCH is effectively already cached because the DBI checks the - # attribute cache in the handle before calling FETCH - # and this FETCH copies the value into the attribute cache - - # forward driver-private attributes (except ours) - if ($attrib =~ m/^[a-z]/ && $attrib !~ /^go_/) { - my $value = $dbh->go_dbh_method(undef, 'FETCH', $attrib); - $dbh->{$attrib} = $value; # XXX forces caching by DBI - return $dbh->{$attrib} = $value; - } - - # else pass up to DBI to handle - return $dbh->SUPER::FETCH($attrib); - } - - sub STORE { - my ($dbh, $attrib, $value) = @_; - if ($attrib eq 'AutoCommit') { - croak "Can't enable transactions when using DBD::Gofer" if !$value; - return $dbh->SUPER::STORE($attrib => ($value) ? -901 : -900); - } - return $dbh->SUPER::STORE($attrib => $value) - # we handle this attribute locally - if $dbh_local_store_attrib{$attrib} - # or it's a private_ (application) attribute - or $attrib =~ /^private_/ - # or not yet connected (ie being called by DBI->connect) - or not $dbh->FETCH('Active'); - - return $dbh->SUPER::STORE($attrib => $value) - if $DBD::Gofer::xxh_local_store_attrib_if_same_value{$attrib} - && do { # values are the same - my $crnt = $dbh->FETCH($attrib); - local $^W; - (defined($value) ^ defined($crnt)) - ? 0 # definedness differs - : $value eq $crnt; - }; - - # dbh attributes are set at connect-time - see connect() - carp("Can't alter \$dbh->{$attrib} after handle created with DBD::Gofer") if $dbh->FETCH('Warn'); - return $dbh->set_err($DBI::stderr, "Can't alter \$dbh->{$attrib} after handle created with DBD::Gofer"); - } - - sub disconnect { - my $dbh = shift; - $dbh->{go_transport} = undef; - $dbh->STORE(Active => 0); - } - - sub prepare { - my ($dbh, $statement, $attr)= @_; - - return $dbh->set_err($DBI::stderr, "Can't prepare when disconnected") - unless $dbh->FETCH('Active'); - - $attr = { %$attr } if $attr; # copy so we can edit - - my $policy = delete($attr->{go_policy}) || $dbh->{go_policy}; - my $lii_args = delete $attr->{go_last_insert_id_args}; - my $go_prepare = delete($attr->{go_prepare_method}) - || $dbh->{go_prepare_method} - || $policy->prepare_method($dbh, $statement, $attr) - || 'prepare'; # e.g. for code not using placeholders - my $go_cache = delete $attr->{go_cache}; - # set to undef if there are no attributes left for the actual prepare call - $attr = undef if $attr and not %$attr; - - my ($sth, $sth_inner) = DBI::_new_sth($dbh, { - Statement => $statement, - go_prepare_call => [ 0, $go_prepare, $statement, $attr ], - # go_method_calls => [], # autovivs if needed - go_request => $dbh->{go_request}, - go_transport => $dbh->{go_transport}, - go_policy => $policy, - go_last_insert_id_args => $lii_args, - go_cache => $go_cache, - }); - $sth->STORE(Active => 0); # XXX needed? It should be the default - - my $skip_prepare_check = $policy->skip_prepare_check($attr, $dbh, $statement, $attr, $sth); - if (not $skip_prepare_check) { - $sth->go_sth_method() or return undef; - } - - return $sth; - } - - sub prepare_cached { - my ($dbh, $sql, $attr, $if_active)= @_; - $attr ||= {}; - return $dbh->SUPER::prepare_cached($sql, { - %$attr, - go_prepare_method => $attr->{go_prepare_method} || 'prepare_cached', - }, $if_active); - } - - *go_cache = \&DBD::Gofer::go_cache; -} - - -{ package DBD::Gofer::st; # ====== STATEMENT ====== - $imp_data_size = 0; - use strict; - - my %sth_local_store_attrib = (%DBD::Gofer::xxh_local_store_attrib, NUM_OF_FIELDS => 1); - - sub go_sth_method { - my ($sth, $meta) = @_; - - if (my $ParamValues = $sth->{ParamValues}) { - my $ParamAttr = $sth->{ParamAttr}; - # XXX the sort here is a hack to work around a DBD::Sybase bug - # but only works properly for params 1..9 - # (reverse because of the unshift) - my @params = reverse sort keys %$ParamValues; - if (@params > 9 && ($sth->{Database}{go_dsn}||'') =~ /dbi:Sybase/) { - # if more than 9 then we need to do a proper numeric sort - # also warn to alert user of this issue - warn "Sybase param binding order hack in use"; - @params = sort { $b <=> $a } @params; - } - for my $p (@params) { - # unshift to put binds before execute call - unshift @{ $sth->{go_method_calls} }, - [ 'bind_param', $p, $ParamValues->{$p}, $ParamAttr->{$p} ]; - } - } - - my $dbh = $sth->{Database} or die "panic"; - ++$dbh->{go_request_count}; - - my $request = $sth->{go_request}; - $request->init_request($sth->{go_prepare_call}, $sth); - $request->sth_method_calls(delete $sth->{go_method_calls}) - if $sth->{go_method_calls}; - $request->sth_result_attr({}); # (currently) also indicates this is an sth request - - $request->dbh_last_insert_id_args($meta->{go_last_insert_id_args}) - if $meta->{go_last_insert_id_args}; - - my $go_policy = $sth->{go_policy}; - my $dbh_attribute_update = $go_policy->dbh_attribute_update(); - $request->dbh_attributes( $go_policy->dbh_attribute_list() ) - if $dbh_attribute_update eq 'every' - or $dbh->{go_request_count}==1; - - my $transport = $sth->{go_transport} - or return $sth->set_err($DBI::stderr, "Not connected (no transport)"); - - local $transport->{go_cache} = $sth->{go_cache} - if defined $sth->{go_cache}; - - my ($response, $retransmit_sub) = $transport->transmit_request($request); - $response ||= $transport->receive_response($request, $retransmit_sub); - $sth->{go_response} = $response - or die "No response object returned by $transport"; - $dbh->{go_response} = $response; # mainly for last_insert_id - - if (my $dbh_attributes = $response->dbh_attributes) { - # XXX we don't STORE here, we just stuff the value into the attribute cache - $dbh->{$_} = $dbh_attributes->{$_} - for keys %$dbh_attributes; - # record the values returned, so we know that we have fetched - # values are which we have fetched (see dbh->FETCH method) - $dbh->{go_dbh_attributes_fetched} = $dbh_attributes; - } - - my $rv = $response->rv; # may be undef on error - if ($response->sth_resultsets) { - # setup first resultset - including sth attributes - $sth->more_results; - } - else { - $sth->STORE(Active => 0); - $sth->{go_rows} = $rv; - } - # set error/warn/info (after more_results as that'll clear err) - DBD::Gofer::set_err_from_response($sth, $response); - - return $rv; - } - - - sub bind_param { - my ($sth, $param, $value, $attr) = @_; - $sth->{ParamValues}{$param} = $value; - $sth->{ParamAttr}{$param} = $attr - if defined $attr; # attr is sticky if not explicitly set - return 1; - } - - - sub execute { - my $sth = shift; - $sth->bind_param($_, $_[$_-1]) for (1..@_); - push @{ $sth->{go_method_calls} }, [ 'execute' ]; - my $meta = { go_last_insert_id_args => $sth->{go_last_insert_id_args} }; - return $sth->go_sth_method($meta); - } - - - sub more_results { - my $sth = shift; - - $sth->finish; - - my $response = $sth->{go_response} or do { - # e.g., we haven't sent a request yet (ie prepare then more_results) - $sth->trace_msg(" No response object present", 3); - return; - }; - - my $resultset_list = $response->sth_resultsets - or return $sth->set_err($DBI::stderr, "No sth_resultsets"); - - my $meta = shift @$resultset_list - or return undef; # no more result sets - #warn "more_results: ".Data::Dumper::Dumper($meta); - - # pull out the special non-attributes first - my ($rowset, $err, $errstr, $state) - = delete @{$meta}{qw(rowset err errstr state)}; - - # copy meta attributes into attribute cache - my $NUM_OF_FIELDS = delete $meta->{NUM_OF_FIELDS}; - $sth->STORE('NUM_OF_FIELDS', $NUM_OF_FIELDS); - # XXX need to use STORE for some? - $sth->{$_} = $meta->{$_} for keys %$meta; - - if (($NUM_OF_FIELDS||0) > 0) { - $sth->{go_rows} = ($rowset) ? @$rowset : -1; - $sth->{go_current_rowset} = $rowset; - $sth->{go_current_rowset_err} = [ $err, $errstr, $state ] - if defined $err; - $sth->STORE(Active => 1) if $rowset; - } - - return $sth; - } - - - sub go_clone_sth { - my ($sth1) = @_; - # clone an (un-fetched-from) sth - effectively undoes the initial more_results - # not 100% so just for use in caching returned sth e.g. table_info - my $sth2 = $sth1->{Database}->prepare($sth1->{Statement}, { go_skip_prepare_check => 1 }); - $sth2->STORE($_, $sth1->{$_}) for qw(NUM_OF_FIELDS Active); - my $sth2_inner = tied %$sth2; - $sth2_inner->{$_} = $sth1->{$_} for qw(NUM_OF_PARAMS FetchHashKeyName); - die "not fully implemented yet"; - return $sth2; - } - - - sub fetchrow_arrayref { - my ($sth) = @_; - my $resultset = $sth->{go_current_rowset} || do { - # should only happen if fetch called after execute failed - my $rowset_err = $sth->{go_current_rowset_err} - || [ 1, 'no result set (did execute fail)' ]; - return $sth->set_err( @$rowset_err ); - }; - return $sth->_set_fbav(shift @$resultset) if @$resultset; - $sth->finish; # no more data so finish - return undef; - } - *fetch = \&fetchrow_arrayref; # alias - - - sub fetchall_arrayref { - my ($sth, $slice, $max_rows) = @_; - my $resultset = $sth->{go_current_rowset} || do { - # should only happen if fetch called after execute failed - my $rowset_err = $sth->{go_current_rowset_err} - || [ 1, 'no result set (did execute fail)' ]; - return $sth->set_err( @$rowset_err ); - }; - my $mode = ref($slice) || 'ARRAY'; - return $sth->SUPER::fetchall_arrayref($slice, $max_rows) - if ref($slice) or defined $max_rows; - $sth->finish; # no more data after this so finish - return $resultset; - } - - - sub rows { - return shift->{go_rows}; - } - - - sub STORE { - my ($sth, $attrib, $value) = @_; - - return $sth->SUPER::STORE($attrib => $value) - if $sth_local_store_attrib{$attrib} # handle locally - # or it's a private_ (application) attribute - or $attrib =~ /^private_/; - - # otherwise warn but do it anyway - # this will probably need refining later - my $msg = "Altering \$sth->{$attrib} won't affect proxied handle"; - Carp::carp($msg) if $sth->FETCH('Warn'); - - # XXX could perhaps do - # push @{ $sth->{go_method_calls} }, [ 'STORE', $attrib, $value ] - # if not $sth->FETCH('Executed'); - # but how to handle repeat executions? How to we know when an - # attribute is being set to affect the current resultset or the - # next execution? - # Could just always use go_method_calls I guess. - - # do the store locally anyway, just in case - $sth->SUPER::STORE($attrib => $value); - - return $sth->set_err($DBI::stderr, $msg); - } - - # sub bind_param_array - # we use DBI's default, which sets $sth->{ParamArrays}{$param} = $value - # and calls bind_param($param, undef, $attr) if $attr. - - sub execute_array { - my $sth = shift; - my $attr = shift; - $sth->bind_param_array($_, $_[$_-1]) for (1..@_); - push @{ $sth->{go_method_calls} }, [ 'execute_array', $attr ]; - return $sth->go_sth_method($attr); - } - - *go_cache = \&DBD::Gofer::go_cache; -} - -1; - -__END__ - -=head1 NAME - -DBD::Gofer - A stateless-proxy driver for communicating with a remote DBI - -=head1 SYNOPSIS - - use DBI; - - $original_dsn = "dbi:..."; # your original DBI Data Source Name - - $dbh = DBI->connect("dbi:Gofer:transport=$transport;...;dsn=$original_dsn", - $user, $passwd, \%attributes); - - ... use $dbh as if it was connected to $original_dsn ... - - -The C part specifies the name of the module to use to -transport the requests to the remote DBI. If $transport doesn't contain any -double colons then it's prefixed with C. - -The C part I of the DSN because -everything after C is assumed to be the DSN that the remote DBI should -use. - -The C<...> represents attributes that influence the operation of the Gofer -driver or transport. These are described below or in the documentation of the -transport module being used. - -=encoding ISO8859-1 - -=head1 DESCRIPTION - -DBD::Gofer is a DBI database driver that forwards requests to another DBI -driver, usually in a separate process, often on a separate machine. It tries to -be as transparent as possible so it appears that you are using the remote -driver directly. - -DBD::Gofer is very similar to DBD::Proxy. The major difference is that with -DBD::Gofer no state is maintained on the remote end. That means every -request contains all the information needed to create the required state. (So, -for example, every request includes the DSN to connect to.) Each request can be -sent to any available server. The server executes the request and returns a -single response that includes all the data. - -This is very similar to the way http works as a stateless protocol for the web. -Each request from your web browser can be handled by a different web server process. - -=head2 Use Cases - -This may seem like pointless overhead but there are situations where this is a -very good thing. Let's consider a specific case. - -Imagine using DBD::Gofer with an http transport. Your application calls -connect(), prepare("select * from table where foo=?"), bind_param(), and execute(). -At this point DBD::Gofer builds a request containing all the information -about the method calls. It then uses the httpd transport to send that request -to an apache web server. - -This 'dbi execute' web server executes the request (using DBI::Gofer::Execute -and related modules) and builds a response that contains all the rows of data, -if the statement returned any, along with all the attributes that describe the -results, such as $sth->{NAME}. This response is sent back to DBD::Gofer which -unpacks it and presents it to the application as if it had executed the -statement itself. - -=head2 Advantages - -Okay, but you still don't see the point? Well let's consider what we've gained: - -=head3 Connection Pooling and Throttling - -The 'dbi execute' web server leverages all the functionality of web -infrastructure in terms of load balancing, high-availability, firewalls, access -management, proxying, caching. - -At its most basic level you get a configurable pool of persistent database connections. - -=head3 Simple Scaling - -Got thousands of processes all trying to connect to the database? You can use -DBD::Gofer to connect them to your smaller pool of 'dbi execute' web servers instead. - -=head3 Caching - -Client-side caching is as simple as adding "C" to the DSN. -This feature alone can be worth using DBD::Gofer for. - -=head3 Fewer Network Round-trips - -DBD::Gofer sends as few requests as possible (dependent on the policy being used). - -=head3 Thin Clients / Unsupported Platforms - -You no longer need drivers for your database on every system. DBD::Gofer is pure perl. - -=head1 CONSTRAINTS - -There are some natural constraints imposed by the DBD::Gofer 'stateless' approach. -But not many: - -=head2 You can't change database handle attributes after connect() - -You can't change database handle attributes after you've connected. -Use the connect() call to specify all the attribute settings you want. - -This is because it's critical that when a request is complete the database -handle is left in the same state it was when first connected. - -An exception is made for attributes with names starting "C": -They can be set after connect() but the change is only applied locally. - -=head2 You can't change statement handle attributes after prepare() - -You can't change statement handle attributes after prepare. - -An exception is made for attributes with names starting "C": -They can be set after prepare() but the change is only applied locally. - -=head2 You can't use transactions - -AutoCommit only. Transactions aren't supported. - -(In theory transactions could be supported when using a transport that -maintains a connection, like C does. If you're interested in this -please get in touch via dbi-dev@perl.org) - -=head2 You can't call driver-private sth methods - -But that's rarely needed anyway. - -=head1 GENERAL CAVEATS - -A few important things to keep in mind when using DBD::Gofer: - -=head2 Temporary tables, locks, and other per-connection persistent state - -You shouldn't expect any per-session state to persist between requests. -This includes locks and temporary tables. - -Because the server-side may execute your requests via a different -database connections, you can't rely on any per-connection persistent state, -such as temporary tables, being available from one request to the next. - -This is an easy trap to fall into. A good way to check for this is to test your -code with a Gofer policy package that sets the C policy to -'connect' to force a new connection for each request. The C policy does this. - -=head2 Driver-private Database Handle Attributes - -Some driver-private dbh attributes may not be available if the driver has not -implemented the private_attribute_info() method (added in DBI 1.54). - -=head2 Driver-private Statement Handle Attributes - -Driver-private sth attributes can be set in the prepare() call. TODO - -Some driver-private sth attributes may not be available if the driver has not -implemented the private_attribute_info() method (added in DBI 1.54). - -=head2 Multiple Resultsets - -Multiple resultsets are supported only if the driver supports the more_results() method -(an exception is made for DBD::Sybase). - -=head2 Statement activity that also updates dbh attributes - -Some drivers may update one or more dbh attributes after performing activity on -a child sth. For example, DBD::mysql provides $dbh->{mysql_insertid} in addition to -$sth->{mysql_insertid}. Currently mysql_insertid is supported via a hack but a -more general mechanism is needed for other drivers to use. - -=head2 Methods that report an error always return undef - -With DBD::Gofer, a method that sets an error always return an undef or empty list. -That shouldn't be a problem in practice because the DBI doesn't define any -methods that return meaningful values while also reporting an error. - -=head2 Subclassing only applies to client-side - -The RootClass and DbTypeSubclass attributes are not passed to the Gofer server. - -=head1 CAVEATS FOR SPECIFIC METHODS - -=head2 last_insert_id - -To enable use of last_insert_id you need to indicate to DBD::Gofer that you'd -like to use it. You do that my adding a C attribute to -the do() or prepare() method calls. For example: - - $dbh->do($sql, { go_last_insert_id_args => [...] }); - -or - - $sth = $dbh->prepare($sql, { go_last_insert_id_args => [...] }); - -The array reference should contains the args that you want passed to the -last_insert_id() method. - -=head2 execute_for_fetch - -The array methods bind_param_array() and execute_array() are supported. -When execute_array() is called the data is serialized and executed in a single -round-trip to the Gofer server. This makes it very fast, but requires enough -memory to store all the serialized data. - -The execute_for_fetch() method currently isn't optimised, it uses the DBI -fallback behaviour of executing each tuple individually. -(It could be implemented as a wrapper for execute_array() - patches welcome.) - -=head1 TRANSPORTS - -DBD::Gofer doesn't concern itself with transporting requests and responses to and fro. -For that it uses special Gofer transport modules. - -Gofer transport modules usually come in pairs: one for the 'client' DBD::Gofer -driver to use and one for the remote 'server' end. They have very similar names: - - DBD::Gofer::Transport:: - DBI::Gofer::Transport:: - -Sometimes the transports on the DBD and DBI sides may have different names. For -example DBD::Gofer::Transport::http is typically used with DBI::Gofer::Transport::mod_perl -(DBD::Gofer::Transport::http and DBI::Gofer::Transport::mod_perl modules are -part of the GoferTransport-http distribution). - -=head2 Bundled Transports - -Several transport modules are provided with DBD::Gofer: - -=head3 null - -The null transport is the simplest of them all. It doesn't actually transport the request anywhere. -It just serializes (freezes) the request into a string, then thaws it back into -a data structure before passing it to DBI::Gofer::Execute to execute. The same -freeze and thaw is applied to the results. - -The null transport is the best way to test if your application will work with Gofer. -Just set the DBI_AUTOPROXY environment variable to "C" -(see L below) and run your application, or ideally its test suite, as usual. - -It doesn't take any parameters. - -=head3 pipeone - -The pipeone transport launches a subprocess for each request. It passes in the -request and reads the response. - -The fact that a new subprocess is started for each request ensures that the -server side is truly stateless. While this does make the transport I slow, -it is useful as a way to test that your application doesn't depend on -per-connection state, such as temporary tables, persisting between requests. - -It's also useful both as a proof of concept and as a base class for the stream -driver. - -=head3 stream - -The stream driver also launches a subprocess and writes requests and reads -responses, like the pipeone transport. In this case, however, the subprocess -is expected to handle more that one request. (Though it will be automatically -restarted if it exits.) - -This is the first transport that is truly useful because it can launch the -subprocess on a remote machine using C. This means you can now use DBD::Gofer -to easily access any databases that's accessible from any system you can login to. -You also get all the benefits of ssh, including encryption and optional compression. - -See L below for an example. - -=head2 Other Transports - -Implementing a Gofer transport is I simple, and more transports are very welcome. -Just take a look at any existing transports that are similar to your needs. - -=head3 http - -See the GoferTransport-http distribution on CPAN: http://search.cpan.org/dist/GoferTransport-http/ - -=head3 Gearman - -I know Ask Bjørn Hansen has implemented a transport for the C distributed -job system, though it's not on CPAN at the time of writing this. - -=head1 CONNECTING - -Simply prefix your existing DSN with "C" -where $transport is the name of the Gofer transport you want to use (see L). -The C and C attributes must be specified and the C attributes must be last. - -Other attributes can be specified in the DSN to configure DBD::Gofer and/or the -Gofer transport module being used. The main attributes after C, are -C and C. These and other attributes are described below. - -=head2 Using DBI_AUTOPROXY - -The simplest way to try out DBD::Gofer is to set the DBI_AUTOPROXY environment variable. -In this case you don't include the C part. For example: - - export DBI_AUTOPROXY="dbi:Gofer:transport=null" - -or, for a more useful example, try: - - export DBI_AUTOPROXY="dbi:Gofer:transport=stream;url=ssh:user@example.com" - -=head2 Connection Attributes - -These attributes can be specified in the DSN. They can also be passed in the -\%attr parameter of the DBI connect method by adding a "C" prefix to the name. - -=head3 transport - -Specifies the Gofer transport class to use. Required. See L above. - -If the value does not include C<::> then "C" is prefixed. - -The transport object can be accessed via $h->{go_transport}. - -=head3 dsn - -Specifies the DSN for the remote side to connect to. Required, and must be last. - -=head3 url - -Used to tell the transport where to connect to. The exact form of the value depends on the transport used. - -=head3 policy - -Specifies the policy to use. See L. - -If the value does not include C<::> then "C" is prefixed. - -The policy object can be accessed via $h->{go_policy}. - -=head3 timeout - -Specifies a timeout, in seconds, to use when waiting for responses from the server side. - -=head3 retry_limit - -Specifies the number of times a failed request will be retried. Default is 0. - -=head3 retry_hook - -Specifies a code reference to be called to decide if a failed request should be retried. -The code reference is called like this: - - $transport = $h->{go_transport}; - $retry = $transport->go_retry_hook->($request, $response, $transport); - -If it returns true then the request will be retried, up to the C. -If it returns a false but defined value then the request will not be retried. -If it returns undef then the default behaviour will be used, as if C -had not been specified. - -The default behaviour is to retry requests where $request->is_idempotent is true, -or the error message matches C. - -=head3 cache - -Specifies that client-side caching should be performed. The value is the name -of a cache class to use. - -Any class implementing get($key) and set($key, $value) methods can be used. -That includes a great many powerful caching classes on CPAN, including the -Cache and Cache::Cache distributions. - -You can use "C" is a shortcut for "C". -See L for a description of this simple fast default cache. - -The cache object can be accessed via $h->go_cache. For example: - - $dbh->go_cache->clear; # free up memory being used by the cache - -The cache keys are the frozen (serialized) requests, and the values are the -frozen responses. - -The default behaviour is to only use the cache for requests where -$request->is_idempotent is true (i.e., the dbh has the ReadOnly attribute set -or the SQL statement is obviously a SELECT without a FOR UPDATE clause.) - -For even more control you can use the C attribute to pass in an -instantiated cache object. Individual methods, including prepare(), can also -specify alternative caches via the C attribute. For example, to -specify no caching for a particular query, you could use - - $sth = $dbh->prepare( $sql, { go_cache => 0 } ); - -This can be used to implement different caching policies for different statements. - -It's interesting to note that DBD::Gofer can be used to add client-side caching -to any (gofer compatible) application, with no code changes and no need for a -gofer server. Just set the DBI_AUTOPROXY environment variable like this: - - DBI_AUTOPROXY='dbi:Gofer:transport=null;cache=1' - -=head1 CONFIGURING BEHAVIOUR POLICY - -DBD::Gofer supports a 'policy' mechanism that allows you to fine-tune the number of round-trips to the Gofer server. -The policies are grouped into classes (which may be subclassed) and referenced by the name of the class. - -The L class is the base class for all the policy -packages and describes all the available policies. - -Three policy packages are supplied with DBD::Gofer: - -L is most 'transparent' but slowest because it -makes more round-trips to the Gofer server. - -L is a reasonable compromise - it's the default policy. - -L is fastest, but may require code changes in your applications. - -Generally the default C policy is fine. When first testing an existing -application with Gofer it is a good idea to start with the C policy -first and then switch to C or a custom policy, for final testing. - - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 ACKNOWLEDGEMENTS - -The development of DBD::Gofer and related modules was sponsored by -Shopzilla.com (L), where I currently work. - -=head1 SEE ALSO - -L, L, L. - -L, L. - -L - -=head1 Caveats for specific drivers - -This section aims to record issues to be aware of when using Gofer with specific drivers. -It usually only documents issues that are not natural consequences of the limitations -of the Gofer approach - as documented above. - -=head1 TODO - -This is just a random brain dump... (There's more in the source of the Changes file, not the pod) - -Document policy mechanism - -Add mechanism for transports to list config params and for Gofer to apply any that match (and warn if any left over?) - -Driver-private sth attributes - set via prepare() - change DBI spec - -add hooks into transport base class for checking & updating a result set cache - ie via a standard cache interface such as: - http://search.cpan.org/~robm/Cache-FastMmap/FastMmap.pm - http://search.cpan.org/~bradfitz/Cache-Memcached/lib/Cache/Memcached.pm - http://search.cpan.org/~dclinton/Cache-Cache/ - http://search.cpan.org/~cleishman/Cache/ -Also caching instructions could be passed through the httpd transport layer -in such a way that appropriate http cache headers are added to the results -so that web caches (squid etc) could be used to implement the caching. -(MUST require the use of GET rather than POST requests.) - -Rework handling of installed_methods to not piggyback on dbh_attributes? - -Perhaps support transactions for transports where it's possible (ie null and stream)? -Would make stream transport (ie ssh) more useful to more people. - -Make sth_result_attr more like dbh_attributes (using '*' etc) - -Add @val = FETCH_many(@names) to DBI in C and use in Gofer/Execute? - -Implement _new_sth in C. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/Base.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/Base.pm deleted file mode 100644 index 0121c88..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/Base.pm +++ /dev/null @@ -1,162 +0,0 @@ -package DBD::Gofer::Policy::Base; - -# $Id: Base.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; -use Carp; - -our $VERSION = "0.010088"; -our $AUTOLOAD; - -my %policy_defaults = ( - # force connect method (unless overridden by go_connect_method=>'...' attribute) - # if false: call same method on client as on server - connect_method => 'connect', - # force prepare method (unless overridden by go_prepare_method=>'...' attribute) - # if false: call same method on client as on server - prepare_method => 'prepare', - skip_connect_check => 0, - skip_default_methods => 0, - skip_prepare_check => 0, - skip_ping => 0, - dbh_attribute_update => 'every', - dbh_attribute_list => ['*'], - locally_quote => 0, - locally_quote_identifier => 0, - cache_parse_trace_flags => 1, - cache_parse_trace_flag => 1, - cache_data_sources => 1, - cache_type_info_all => 1, - cache_tables => 0, - cache_table_info => 0, - cache_column_info => 0, - cache_primary_key_info => 0, - cache_foreign_key_info => 0, - cache_statistics_info => 0, - cache_get_info => 0, - cache_func => 0, -); - -my $base_policy_file = $INC{"DBD/Gofer/Policy/Base.pm"}; - -__PACKAGE__->create_policy_subs(\%policy_defaults); - -sub create_policy_subs { - my ($class, $policy_defaults) = @_; - - while ( my ($policy_name, $policy_default) = each %$policy_defaults) { - my $policy_attr_name = "go_$policy_name"; - my $sub = sub { - # $policy->foo($attr, ...) - #carp "$policy_name($_[1],...)"; - # return the policy default value unless an attribute overrides it - return (ref $_[1] && exists $_[1]->{$policy_attr_name}) - ? $_[1]->{$policy_attr_name} - : $policy_default; - }; - no strict 'refs'; - *{$class . '::' . $policy_name} = $sub; - } -} - -sub AUTOLOAD { - carp "Unknown policy name $AUTOLOAD used"; - # only warn once - no strict 'refs'; - *$AUTOLOAD = sub { undef }; - return undef; -} - -sub new { - my ($class, $args) = @_; - my $policy = {}; - bless $policy, $class; -} - -sub DESTROY { }; - -1; - -=head1 NAME - -DBD::Gofer::Policy::Base - Base class for DBD::Gofer policies - -=head1 SYNOPSIS - - $dbh = DBI->connect("dbi:Gofer:transport=...;policy=...", ...) - -=head1 DESCRIPTION - -DBD::Gofer can be configured via a 'policy' mechanism that allows you to -fine-tune the number of round-trips to the Gofer server. The policies are -grouped into classes (which may be subclassed) and referenced by the name of -the class. - -The L class is the base class for all the policy -classes and describes all the individual policy items. - -The Base policy is not used directly. You should use a policy class derived from it. - -=head1 POLICY CLASSES - -Three policy classes are supplied with DBD::Gofer: - -L is most 'transparent' but slowest because it -makes more round-trips to the Gofer server. - -L is a reasonable compromise - it's the default policy. - -L is fastest, but may require code changes in your applications. - -Generally the default C policy is fine. When first testing an existing -application with Gofer it is a good idea to start with the C policy -first and then switch to C or a custom policy, for final testing. - -=head1 POLICY ITEMS - -These are temporary docs: See the source code for list of policies and their defaults. - -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. - -See the source code to this module for more details. - -=head1 POLICY CUSTOMIZATION - -XXX This area of DBD::Gofer is subject to change. - -There are three ways to customize policies: - -Policy classes are designed to influence the overall behaviour of DBD::Gofer -with existing, unaltered programs, so they work in a reasonably optimal way -without requiring code changes. You can implement new policy classes as -subclasses of existing policies. - -In many cases individual policy items can be overridden on a case-by-case basis -within your application code. You do this by passing a corresponding -C<>> attribute into DBI methods by your application code. -This let's you fine-tune the behaviour for special cases. - -The policy items are implemented as methods. In many cases the methods are -passed parameters relating to the DBD::Gofer code being executed. This means -the policy can implement dynamic behaviour that varies depending on the -particular circumstances, such as the particular statement being executed. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/classic.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/classic.pm deleted file mode 100644 index 7316f13..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/classic.pm +++ /dev/null @@ -1,79 +0,0 @@ -package DBD::Gofer::Policy::classic; - -# $Id: classic.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -our $VERSION = "0.010088"; - -use base qw(DBD::Gofer::Policy::Base); - -__PACKAGE__->create_policy_subs({ - - # always use connect_cached on server - connect_method => 'connect_cached', - - # use same methods on server as is called on client - prepare_method => '', - - # don't skip the connect check since that also sets dbh attributes - # although this makes connect more expensive, that's partly offset - # by skip_ping=>1 below, which makes connect_cached very fast. - skip_connect_check => 0, - - # most code doesn't rely on sth attributes being set after prepare - skip_prepare_check => 1, - - # we're happy to use local method if that's the same as the remote - skip_default_methods => 1, - - # ping is not important for DBD::Gofer and most transports - skip_ping => 1, - - # only update dbh attributes on first contact with server - dbh_attribute_update => 'first', - - # we'd like to set locally_* but can't because drivers differ - - # get_info results usually don't change - cache_get_info => 1, -}); - - -1; - -=head1 NAME - -DBD::Gofer::Policy::classic - The 'classic' policy for DBD::Gofer - -=head1 SYNOPSIS - - $dbh = DBI->connect("dbi:Gofer:transport=...;policy=classic", ...) - -The C policy is the default DBD::Gofer policy, so need not be included in the DSN. - -=head1 DESCRIPTION - -Temporary docs: See the source code for list of policies and their defaults. - -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/pedantic.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/pedantic.pm deleted file mode 100644 index af3e451..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/pedantic.pm +++ /dev/null @@ -1,53 +0,0 @@ -package DBD::Gofer::Policy::pedantic; - -# $Id: pedantic.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -our $VERSION = "0.010088"; - -use base qw(DBD::Gofer::Policy::Base); - -# the 'pedantic' policy is the same as the Base policy - -1; - -=head1 NAME - -DBD::Gofer::Policy::pedantic - The 'pedantic' policy for DBD::Gofer - -=head1 SYNOPSIS - - $dbh = DBI->connect("dbi:Gofer:transport=...;policy=pedantic", ...) - -=head1 DESCRIPTION - -The C policy tries to be as transparent as possible. To do this it -makes round-trips to the server for almost every DBI method call. - -This is the best policy to use when first testing existing code with Gofer. -Once it's working well you should consider moving to the C policy or defining your own policy class. - -Temporary docs: See the source code for list of policies and their defaults. - -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/rush.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/rush.pm deleted file mode 100644 index f8d5743..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Policy/rush.pm +++ /dev/null @@ -1,90 +0,0 @@ -package DBD::Gofer::Policy::rush; - -# $Id: rush.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -our $VERSION = "0.010088"; - -use base qw(DBD::Gofer::Policy::Base); - -__PACKAGE__->create_policy_subs({ - - # always use connect_cached on server - connect_method => 'connect_cached', - - # use same methods on server as is called on client - # (because code not using placeholders would bloat the sth cache) - prepare_method => '', - - # Skipping the connect check is fast, but it also skips - # fetching the remote dbh attributes! - # Make sure that your application doesn't need access to dbh attributes. - skip_connect_check => 1, - - # most code doesn't rely on sth attributes being set after prepare - skip_prepare_check => 1, - - # we're happy to use local method if that's the same as the remote - skip_default_methods => 1, - - # ping is almost meaningless for DBD::Gofer and most transports anyway - skip_ping => 1, - - # don't update dbh attributes at all - # XXX actually we currently need dbh_attribute_update for skip_default_methods to work - # and skip_default_methods is more valuable to us than the cost of dbh_attribute_update - dbh_attribute_update => 'none', # actually means 'first' currently - #dbh_attribute_list => undef, - - # we'd like to set locally_* but can't because drivers differ - - # in a rush assume metadata doesn't change - cache_tables => 1, - cache_table_info => 1, - cache_column_info => 1, - cache_primary_key_info => 1, - cache_foreign_key_info => 1, - cache_statistics_info => 1, - cache_get_info => 1, -}); - - -1; - -=head1 NAME - -DBD::Gofer::Policy::rush - The 'rush' policy for DBD::Gofer - -=head1 SYNOPSIS - - $dbh = DBI->connect("dbi:Gofer:transport=...;policy=rush", ...) - -=head1 DESCRIPTION - -The C policy tries to make as few round-trips as possible. -It's the opposite end of the policy spectrum to the C policy. - -Temporary docs: See the source code for list of policies and their defaults. - -In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/Base.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/Base.pm deleted file mode 100644 index afe96cc..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/Base.pm +++ /dev/null @@ -1,410 +0,0 @@ -package DBD::Gofer::Transport::Base; - -# $Id: Base.pm 14120 2010-06-07 19:52:19Z H.Merijn $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use base qw(DBI::Gofer::Transport::Base); - -our $VERSION = "0.014121"; - -__PACKAGE__->mk_accessors(qw( - trace - go_dsn - go_url - go_policy - go_timeout - go_retry_hook - go_retry_limit - go_cache - cache_hit - cache_miss - cache_store -)); -__PACKAGE__->mk_accessors_using(make_accessor_autoviv_hashref => qw( - meta -)); - - -sub new { - my ($class, $args) = @_; - $args->{$_} = 0 for (qw(cache_hit cache_miss cache_store)); - $args->{keep_meta_frozen} ||= 1 if $args->{go_cache}; - #warn "args @{[ %$args ]}\n"; - return $class->SUPER::new($args); -} - - -sub _init_trace { $ENV{DBD_GOFER_TRACE} || 0 } - - -sub new_response { - my $self = shift; - return DBI::Gofer::Response->new(@_); -} - - -sub transmit_request { - my ($self, $request) = @_; - my $trace = $self->trace; - my $response; - - my ($go_cache, $request_cache_key); - if ($go_cache = $self->{go_cache}) { - $request_cache_key - = $request->{meta}{request_cache_key} - = $self->get_cache_key_for_request($request); - if ($request_cache_key) { - my $frozen_response = eval { $go_cache->get($request_cache_key) }; - if ($frozen_response) { - $self->_dump("cached response found for ".ref($request), $request) - if $trace; - $response = $self->thaw_response($frozen_response); - $self->trace_msg("transmit_request is returning a response from cache $go_cache\n") - if $trace; - ++$self->{cache_hit}; - return $response; - } - warn $@ if $@; - ++$self->{cache_miss}; - $self->trace_msg("transmit_request cache miss\n") - if $trace; - } - } - - my $to = $self->go_timeout; - my $transmit_sub = sub { - $self->trace_msg("transmit_request\n") if $trace; - local $SIG{ALRM} = sub { die "TIMEOUT\n" } if $to; - - my $response = eval { - local $SIG{PIPE} = sub { - my $extra = ($! eq "Broken pipe") ? "" : " ($!)"; - die "Unable to send request: Broken pipe$extra\n"; - }; - alarm($to) if $to; - $self->transmit_request_by_transport($request); - }; - alarm(0) if $to; - - if ($@) { - return $self->transport_timedout("transmit_request", $to) - if $@ eq "TIMEOUT\n"; - return $self->new_response({ err => 1, errstr => $@ }); - } - - return $response; - }; - - $response = $self->_transmit_request_with_retries($request, $transmit_sub); - - if ($response) { - my $frozen_response = delete $response->{meta}{frozen}; - $self->_store_response_in_cache($frozen_response, $request_cache_key) - if $request_cache_key; - } - - $self->trace_msg("transmit_request is returning a response itself\n") - if $trace && $response; - - return $response unless wantarray; - return ($response, $transmit_sub); -} - - -sub _transmit_request_with_retries { - my ($self, $request, $transmit_sub) = @_; - my $response; - do { - $response = $transmit_sub->(); - } while ( $response && $self->response_needs_retransmit($request, $response) ); - return $response; -} - - -sub receive_response { - my ($self, $request, $retransmit_sub) = @_; - my $to = $self->go_timeout; - - my $receive_sub = sub { - $self->trace_msg("receive_response\n"); - local $SIG{ALRM} = sub { die "TIMEOUT\n" } if $to; - - my $response = eval { - alarm($to) if $to; - $self->receive_response_by_transport($request); - }; - alarm(0) if $to; - - if ($@) { - return $self->transport_timedout("receive_response", $to) - if $@ eq "TIMEOUT\n"; - return $self->new_response({ err => 1, errstr => $@ }); - } - return $response; - }; - - my $response; - do { - $response = $receive_sub->(); - if ($self->response_needs_retransmit($request, $response)) { - $response = $self->_transmit_request_with_retries($request, $retransmit_sub); - $response ||= $receive_sub->(); - } - } while ( $self->response_needs_retransmit($request, $response) ); - - if ($response) { - my $frozen_response = delete $response->{meta}{frozen}; - my $request_cache_key = $request->{meta}{request_cache_key}; - $self->_store_response_in_cache($frozen_response, $request_cache_key) - if $request_cache_key && $self->{go_cache}; - } - - return $response; -} - - -sub response_retry_preference { - my ($self, $request, $response) = @_; - - # give the user a chance to express a preference (or undef for default) - if (my $go_retry_hook = $self->go_retry_hook) { - my $retry = $go_retry_hook->($request, $response, $self); - $self->trace_msg(sprintf "go_retry_hook returned %s\n", - (defined $retry) ? $retry : 'undef'); - return $retry if defined $retry; - } - - # This is the main decision point. We don't retry requests that got - # as far as executing because the error is probably from the database - # (not transport) so retrying is unlikely to help. But note that any - # severe transport error occurring after execute is likely to return - # a new response object that doesn't have the execute flag set. Beware! - return 0 if $response->executed_flag_set; - - return 1 if ($response->errstr || '') =~ m/induced by DBI_GOFER_RANDOM/; - - return 1 if $request->is_idempotent; # i.e. is SELECT or ReadOnly was set - - return undef; # we couldn't make up our mind -} - - -sub response_needs_retransmit { - my ($self, $request, $response) = @_; - - my $err = $response->err - or return 0; # nothing went wrong - - my $retry = $self->response_retry_preference($request, $response); - - if (!$retry) { # false or undef - $self->trace_msg("response_needs_retransmit: response not suitable for retry\n"); - return 0; - } - - # we'd like to retry but have we retried too much already? - - my $retry_limit = $self->go_retry_limit; - if (!$retry_limit) { - $self->trace_msg("response_needs_retransmit: retries disabled (retry_limit not set)\n"); - return 0; - } - - my $request_meta = $request->meta; - my $retry_count = $request_meta->{retry_count} || 0; - if ($retry_count >= $retry_limit) { - $self->trace_msg("response_needs_retransmit: $retry_count is too many retries\n"); - # XXX should be possible to disable altering the err - $response->errstr(sprintf "%s (after %d retries by gofer)", $response->errstr, $retry_count); - return 0; - } - - # will retry now, do the admin - ++$retry_count; - $self->trace_msg("response_needs_retransmit: retry $retry_count\n"); - - # hook so response_retry_preference can defer some code execution - # until we've checked retry_count and retry_limit. - if (ref $retry eq 'CODE') { - $retry->($retry_count, $retry_limit) - and warn "should return false"; # protect future use - } - - ++$request_meta->{retry_count}; # update count for this request object - ++$self->meta->{request_retry_count}; # update cumulative transport stats - - return 1; -} - - -sub transport_timedout { - my ($self, $method, $timeout) = @_; - $timeout ||= $self->go_timeout; - return $self->new_response({ err => 1, errstr => "DBD::Gofer $method timed-out after $timeout seconds" }); -} - - -# return undef if we don't want to cache this request -# subclasses may use more specialized rules -sub get_cache_key_for_request { - my ($self, $request) = @_; - - # we only want to cache idempotent requests - # is_idempotent() is true if GOf_REQUEST_IDEMPOTENT or GOf_REQUEST_READONLY set - return undef if not $request->is_idempotent; - - # XXX would be nice to avoid the extra freeze here - my $key = $self->freeze_request($request, undef, 1); - - #use Digest::MD5; warn "get_cache_key_for_request: ".Digest::MD5::md5_base64($key)."\n"; - - return $key; -} - - -sub _store_response_in_cache { - my ($self, $frozen_response, $request_cache_key) = @_; - my $go_cache = $self->{go_cache} - or return; - - # new() ensures that enabling go_cache also enables keep_meta_frozen - warn "No meta frozen in response" if !$frozen_response; - warn "No request_cache_key" if !$request_cache_key; - - if ($frozen_response && $request_cache_key) { - $self->trace_msg("receive_response added response to cache $go_cache\n"); - eval { $go_cache->set($request_cache_key, $frozen_response) }; - warn $@ if $@; - ++$self->{cache_store}; - } -} - -1; - -__END__ - -=head1 NAME - -DBD::Gofer::Transport::Base - base class for DBD::Gofer client transports - -=head1 SYNOPSIS - - my $remote_dsn = "..." - DBI->connect("dbi:Gofer:transport=...;url=...;timeout=...;retry_limit=...;dsn=$remote_dsn",...) - -or, enable by setting the DBI_AUTOPROXY environment variable: - - export DBI_AUTOPROXY='dbi:Gofer:transport=...;url=...' - -which will force I DBI connections to be made via that Gofer server. - -=head1 DESCRIPTION - -This is the base class for all DBD::Gofer client transports. - -=head1 ATTRIBUTES - -Gofer transport attributes can be specified either in the attributes parameter -of the connect() method call, or in the DSN string. When used in the DSN -string, attribute names don't have the C prefix. - -=head2 go_dsn - -The full DBI DSN that the Gofer server should connect to on your behalf. - -When used in the DSN it must be the last element in the DSN string. - -=head2 go_timeout - -A time limit for sending a request and receiving a response. Some drivers may -implement sending and receiving as separate steps, in which case (currently) -the timeout applies to each separately. - -If a request needs to be resent then the timeout is restarted for each sending -of a request and receiving of a response. - -=head2 go_retry_limit - -The maximum number of times an request may be retried. The default is 2. - -=head2 go_retry_hook - -This subroutine reference is called, if defined, for each response received where $response->err is true. - -The subroutine is pass three parameters: the request object, the response object, and the transport object. - -If it returns an undefined value then the default retry behaviour is used. See L below. - -If it returns a defined but false value then the request is not resent. - -If it returns true value then the request is resent, so long as the number of retries does not exceed C. - -=head1 RETRY ON ERROR - -The default retry on error behaviour is: - - - Retry if the error was due to DBI_GOFER_RANDOM. See L. - - - Retry if $request->is_idempotent returns true. See L. - -A retry won't be allowed if the number of previous retries has reached C. - -=head1 TRACING - -Tracing of gofer requests and responses can be enabled by setting the -C environment variable. A value of 1 gives a reasonably -compact summary of each request and response. A value of 2 or more gives a -detailed, and voluminous, dump. - -The trace is written using DBI->trace_msg() and so is written to the default -DBI trace output, which is usually STDERR. - -=head1 METHODS - -I - -=head2 response_retry_preference - - $retry = $transport->response_retry_preference($request, $response); - -The response_retry_preference is called by DBD::Gofer when considering if a -request should be retried after an error. - -Returns true (would like to retry), false (must not retry), undef (no preference). - -If a true value is returned in the form of a CODE ref then, if DBD::Gofer does -decide to retry the request, it calls the code ref passing $retry_count, $retry_limit. -Can be used for logging and/or to implement exponential backoff behaviour. -Currently the called code must return using C to allow for future extensions. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007-2008, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L, L, L, L. - -and some example transports: - -L - -L - -L - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/corostream.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/corostream.pm deleted file mode 100644 index 6e79278..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/corostream.pm +++ /dev/null @@ -1,144 +0,0 @@ -package DBD::Gofer::Transport::corostream; - -use strict; -use warnings; - -use Carp; - -use Coro::Select; # a slow but coro-aware replacement for CORE::select (global effect!) - -use Coro; -use Coro::Handle; - -use base qw(DBD::Gofer::Transport::stream); - -# XXX ensure DBI_PUREPERL for parent doesn't pass to child -sub start_pipe_command { - local $ENV{DBI_PUREPERL} = $ENV{DBI_PUREPERL_COROCHILD}; # typically undef - my $connection = shift->SUPER::start_pipe_command(@_); - return $connection; -} - - - -1; - -__END__ - -=head1 NAME - -DBD::Gofer::Transport::corostream - Async DBD::Gofer stream transport using Coro and AnyEvent - -=head1 SYNOPSIS - - DBI_AUTOPROXY="dbi:Gofer:transport=corostream" perl some-perl-script-using-dbi.pl - -or - - $dsn = ...; # the DSN for the driver and database you want to use - $dbh = DBI->connect("dbi:Gofer:transport=corostream;dsn=$dsn", ...); - -=head1 DESCRIPTION - -The I from using L is that it enables the use of existing -DBI frameworks like L. - -=head1 KNOWN ISSUES AND LIMITATIONS - - - Uses Coro::Select so alters CORE::select globally - Parent class probably needs refactoring to enable a more encapsulated approach. - - - Doesn't prevent multiple concurrent requests - Probably just needs a per-connection semaphore - - - Coro has many caveats. Caveat emptor. - -=head1 STATUS - -THIS IS CURRENTLY JUST A PROOF-OF-CONCEPT IMPLEMENTATION FOR EXPERIMENTATION. - -Please note that I have no plans to develop this code further myself. -I'd very much welcome contributions. Interested? Let me know! - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2010, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L - -L - -=head1 APPENDIX - -Example code: - - #!perl - - use strict; - use warnings; - use Time::HiRes qw(time); - - BEGIN { $ENV{PERL_ANYEVENT_STRICT} = 1; $ENV{PERL_ANYEVENT_VERBOSE} = 1; } - - use AnyEvent; - - BEGIN { $ENV{DBI_TRACE} = 0; $ENV{DBI_GOFER_TRACE} = 0; $ENV{DBD_GOFER_TRACE} = 0; }; - - use DBI; - - $ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=corostream'; - - my $ticker = AnyEvent->timer( after => 0, interval => 0.1, cb => sub { - warn sprintf "-tick- %.2f\n", time - } ); - - warn "connecting...\n"; - my $dbh = DBI->connect("dbi:NullP:"); - warn "...connected\n"; - - for (1..3) { - warn "entering DBI...\n"; - $dbh->do("sleep 0.3"); # pseudo-sql understood by the DBD::NullP driver - warn "...returned\n"; - } - - warn "done."; - -Example output: - - $ perl corogofer.pl - connecting... - -tick- 1293631437.14 - -tick- 1293631437.14 - ...connected - entering DBI... - -tick- 1293631437.25 - -tick- 1293631437.35 - -tick- 1293631437.45 - -tick- 1293631437.55 - ...returned - entering DBI... - -tick- 1293631437.66 - -tick- 1293631437.76 - -tick- 1293631437.86 - ...returned - entering DBI... - -tick- 1293631437.96 - -tick- 1293631438.06 - -tick- 1293631438.16 - ...returned - done. at corogofer.pl line 39. - -You can see that the timer callback is firing while the code 'waits' inside the -do() method for the response from the database. Normally that would block. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/null.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/null.pm deleted file mode 100644 index 22dcc04..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/null.pm +++ /dev/null @@ -1,111 +0,0 @@ -package DBD::Gofer::Transport::null; - -# $Id: null.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use base qw(DBD::Gofer::Transport::Base); - -use DBI::Gofer::Execute; - -our $VERSION = "0.010088"; - -__PACKAGE__->mk_accessors(qw( - pending_response - transmit_count -)); - -my $executor = DBI::Gofer::Execute->new(); - - -sub transmit_request_by_transport { - my ($self, $request) = @_; - $self->transmit_count( ($self->transmit_count()||0) + 1 ); # just for tests - - my $frozen_request = $self->freeze_request($request); - - # ... - # the request is magically transported over to ... ourselves - # ... - - my $response = $executor->execute_request( $self->thaw_request($frozen_request, undef, 1) ); - - # put response 'on the shelf' ready for receive_response() - $self->pending_response( $response ); - - return undef; -} - - -sub receive_response_by_transport { - my $self = shift; - - my $response = $self->pending_response; - - my $frozen_response = $self->freeze_response($response, undef, 1); - - # ... - # the response is magically transported back to ... ourselves - # ... - - return $self->thaw_response($frozen_response); -} - - -1; -__END__ - -=head1 NAME - -DBD::Gofer::Transport::null - DBD::Gofer client transport for testing - -=head1 SYNOPSIS - - my $original_dsn = "..." - DBI->connect("dbi:Gofer:transport=null;dsn=$original_dsn",...) - -or, enable by setting the DBI_AUTOPROXY environment variable: - - export DBI_AUTOPROXY="dbi:Gofer:transport=null" - -=head1 DESCRIPTION - -Connect via DBD::Gofer but execute the requests within the same process. - -This is a quick and simple way to test applications for compatibility with the -(few) restrictions that DBD::Gofer imposes. - -It also provides a simple, portable way for the DBI test suite to be used to -test DBD::Gofer on all platforms with no setup. - -Also, by measuring the difference in performance between normal connections and -connections via C the basic cost of using DBD::Gofer -can be measured. Furthermore, the additional cost of more advanced transports can be -isolated by comparing their performance with the null transport. - -The C script in the DBI distribution includes a comparative benchmark. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L - -L - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/pipeone.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/pipeone.pm deleted file mode 100644 index 3d792b9..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/pipeone.pm +++ /dev/null @@ -1,253 +0,0 @@ -package DBD::Gofer::Transport::pipeone; - -# $Id: pipeone.pm 10087 2007-10-16 12:42:37Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use Carp; -use Fcntl; -use IO::Select; -use IPC::Open3 qw(open3); -use Symbol qw(gensym); - -use base qw(DBD::Gofer::Transport::Base); - -our $VERSION = "0.010088"; - -__PACKAGE__->mk_accessors(qw( - connection_info - go_perl -)); - - -sub new { - my ($self, $args) = @_; - $args->{go_perl} ||= do { - ($INC{"blib.pm"}) ? [ $^X, '-Mblib' ] : [ $^X ]; - }; - if (not ref $args->{go_perl}) { - # user can override the perl to be used, either with an array ref - # containing the command name and args to use, or with a string - # (ie via the DSN) in which case, to enable args to be passed, - # we split on two or more consecutive spaces (otherwise the path - # to perl couldn't contain a space itself). - $args->{go_perl} = [ split /\s{2,}/, $args->{go_perl} ]; - } - return $self->SUPER::new($args); -} - - -# nonblock($fh) puts filehandle into nonblocking mode -sub nonblock { - my $fh = shift; - my $flags = fcntl($fh, F_GETFL, 0) - or croak "Can't get flags for filehandle $fh: $!"; - fcntl($fh, F_SETFL, $flags | O_NONBLOCK) - or croak "Can't make filehandle $fh nonblocking: $!"; -} - - -sub start_pipe_command { - my ($self, $cmd) = @_; - $cmd = [ $cmd ] unless ref $cmd eq 'ARRAY'; - - # if it's important that the subprocess uses the same - # (versions of) modules as us then the caller should - # set PERL5LIB itself. - - # limit various forms of insanity, for now - local $ENV{DBI_TRACE}; # use DBI_GOFER_TRACE instead - local $ENV{DBI_AUTOPROXY}; - local $ENV{DBI_PROFILE}; - - my ($wfh, $rfh, $efh) = (gensym, gensym, gensym); - my $pid = open3($wfh, $rfh, $efh, @$cmd) - or die "error starting @$cmd: $!\n"; - if ($self->trace) { - $self->trace_msg(sprintf("Started pid $pid: @$cmd {fd: w%d r%d e%d, ppid=$$}\n", fileno $wfh, fileno $rfh, fileno $efh),0); - } - nonblock($rfh); - nonblock($efh); - my $ios = IO::Select->new($rfh, $efh); - - return { - cmd=>$cmd, - pid=>$pid, - wfh=>$wfh, rfh=>$rfh, efh=>$efh, - ios=>$ios, - }; -} - - -sub cmd_as_string { - my $self = shift; - # XXX meant to return a properly shell-escaped string suitable for system - # but its only for debugging so that can wait - my $connection_info = $self->connection_info; - return join " ", map { (m/^[-:\w]*$/) ? $_ : "'$_'" } @{$connection_info->{cmd}}; -} - - -sub transmit_request_by_transport { - my ($self, $request) = @_; - - my $frozen_request = $self->freeze_request($request); - - my $cmd = [ @{$self->go_perl}, qw(-MDBI::Gofer::Transport::pipeone -e run_one_stdio)]; - my $info = $self->start_pipe_command($cmd); - - my $wfh = delete $info->{wfh}; - # send frozen request - local $\; - print $wfh $frozen_request - or warn "error writing to @$cmd: $!\n"; - # indicate that there's no more - close $wfh - or die "error closing pipe to @$cmd: $!\n"; - - $self->connection_info( $info ); - return; -} - - -sub read_response_from_fh { - my ($self, $fh_actions) = @_; - my $trace = $self->trace; - - my $info = $self->connection_info || die; - my ($ios) = @{$info}{qw(ios)}; - my $errors = 0; - my $complete; - - die "No handles to read response from" unless $ios->count; - - while ($ios->count) { - my @readable = $ios->can_read(); - for my $fh (@readable) { - local $_; - my $actions = $fh_actions->{$fh} || die "panic: no action for $fh"; - my $rv = sysread($fh, $_='', 1024*31); # to fit in 32KB slab - unless ($rv) { # error (undef) or end of file (0) - my $action; - unless (defined $rv) { # was an error - $self->trace_msg("error on handle $fh: $!\n") if $trace >= 4; - $action = $actions->{error} || $actions->{eof}; - ++$errors; - # XXX an error may be a permenent condition of the handle - # if so we'll loop here - not good - } - else { - $action = $actions->{eof}; - $self->trace_msg("eof on handle $fh\n") if $trace >= 4; - } - if ($action->($fh)) { - $self->trace_msg("removing $fh from handle set\n") if $trace >= 4; - $ios->remove($fh); - } - next; - } - # action returns true if the response is now complete - # (we finish all handles - $actions->{read}->($fh) && ++$complete; - } - last if $complete; - } - return $errors; -} - - -sub receive_response_by_transport { - my $self = shift; - - my $info = $self->connection_info || die; - my ($pid, $rfh, $efh, $ios, $cmd) = @{$info}{qw(pid rfh efh ios cmd)}; - - my $frozen_response; - my $stderr_msg; - - $self->read_response_from_fh( { - $efh => { - error => sub { warn "error reading response stderr: $!"; 1 }, - eof => sub { warn "eof on stderr" if 0; 1 }, - read => sub { $stderr_msg .= $_; 0 }, - }, - $rfh => { - error => sub { warn "error reading response: $!"; 1 }, - eof => sub { warn "eof on stdout" if 0; 1 }, - read => sub { $frozen_response .= $_; 0 }, - }, - }); - - waitpid $info->{pid}, 0 - or warn "waitpid: $!"; # XXX do something more useful? - - die ref($self)." command (@$cmd) failed: $stderr_msg" - if not $frozen_response; # no output on stdout at all - - # XXX need to be able to detect and deal with corruption - my $response = $self->thaw_response($frozen_response); - - if ($stderr_msg) { - # add stderr messages as warnings (for PrintWarn) - $response->add_err(0, $stderr_msg, undef, $self->trace) - # but ignore warning from old version of blib - unless $stderr_msg =~ /^Using .*blib/ && "@$cmd" =~ /-Mblib/; - } - - return $response; -} - - -1; - -__END__ - -=head1 NAME - -DBD::Gofer::Transport::pipeone - DBD::Gofer client transport for testing - -=head1 SYNOPSIS - - $original_dsn = "..."; - DBI->connect("dbi:Gofer:transport=pipeone;dsn=$original_dsn",...) - -or, enable by setting the DBI_AUTOPROXY environment variable: - - export DBI_AUTOPROXY="dbi:Gofer:transport=pipeone" - -=head1 DESCRIPTION - -Connect via DBD::Gofer and execute each request by starting executing a subprocess. - -This is, as you might imagine, spectacularly inefficient! - -It's only intended for testing. Specifically it demonstrates that the server -side is completely stateless. - -It also provides a base class for the much more useful L -transport. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L - -L - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/stream.pm b/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/stream.pm deleted file mode 100644 index af954f8..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Gofer/Transport/stream.pm +++ /dev/null @@ -1,292 +0,0 @@ -package DBD::Gofer::Transport::stream; - -# $Id: stream.pm 14598 2010-12-21 22:53:25Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use Carp; - -use base qw(DBD::Gofer::Transport::pipeone); - -our $VERSION = "0.014599"; - -__PACKAGE__->mk_accessors(qw( - go_persist -)); - -my $persist_all = 5; -my %persist; - - -sub _connection_key { - my ($self) = @_; - return join "~", $self->go_url||"", @{ $self->go_perl || [] }; -} - - -sub _connection_get { - my ($self) = @_; - - my $persist = $self->go_persist; # = 0 can force non-caching - $persist = $persist_all if not defined $persist; - my $key = ($persist) ? $self->_connection_key : ''; - if ($persist{$key} && $self->_connection_check($persist{$key})) { - $self->trace_msg("reusing persistent connection $key\n",0) if $self->trace >= 1; - return $persist{$key}; - } - - my $connection = $self->_make_connection; - - if ($key) { - %persist = () if keys %persist > $persist_all; # XXX quick hack to limit subprocesses - $persist{$key} = $connection; - } - - return $connection; -} - - -sub _connection_check { - my ($self, $connection) = @_; - $connection ||= $self->connection_info; - my $pid = $connection->{pid}; - my $ok = (kill 0, $pid); - $self->trace_msg("_connection_check: $ok (pid $$)\n",0) if $self->trace; - return $ok; -} - - -sub _connection_kill { - my ($self) = @_; - my $connection = $self->connection_info; - my ($pid, $wfh, $rfh, $efh) = @{$connection}{qw(pid wfh rfh efh)}; - $self->trace_msg("_connection_kill: closing write handle\n",0) if $self->trace; - # closing the write file handle should be enough, generally - close $wfh; - # in future we may want to be more aggressive - #close $rfh; close $efh; kill 15, $pid - # but deleting from the persist cache... - delete $persist{ $self->_connection_key }; - # ... and removing the connection_info should suffice - $self->connection_info( undef ); - return; -} - - -sub _make_connection { - my ($self) = @_; - - my $go_perl = $self->go_perl; - my $cmd = [ @$go_perl, qw(-MDBI::Gofer::Transport::stream -e run_stdio_hex)]; - - #push @$cmd, "DBI_TRACE=2=/tmp/goferstream.log", "sh", "-c"; - if (my $url = $self->go_url) { - die "Only 'ssh:user\@host' style url supported by this transport" - unless $url =~ s/^ssh://; - my $ssh = $url; - my $setup_env = join "||", map { "source $_ 2>/dev/null" } qw(.bash_profile .bash_login .profile); - my $setup = $setup_env.q{; exec "$@"}; - # don't use $^X on remote system by default as it's possibly wrong - $cmd->[0] = 'perl' if "@$go_perl" eq $^X; - # -x not only 'Disables X11 forwarding' but also makes connections *much* faster - unshift @$cmd, qw(ssh -xq), split(' ', $ssh), qw(bash -c), $setup; - } - - $self->trace_msg("new connection: @$cmd\n",0) if $self->trace; - - # XXX add a handshake - some message from DBI::Gofer::Transport::stream that's - # sent as soon as it starts that we can wait for to report success - and soak up - # and report useful warnings etc from ssh before we get it? Increases latency though. - my $connection = $self->start_pipe_command($cmd); - return $connection; -} - - -sub transmit_request_by_transport { - my ($self, $request) = @_; - my $trace = $self->trace; - - my $connection = $self->connection_info || do { - my $con = $self->_connection_get; - $self->connection_info( $con ); - $con; - }; - - my $encoded_request = unpack("H*", $self->freeze_request($request)); - $encoded_request .= "\015\012"; - - my $wfh = $connection->{wfh}; - $self->trace_msg(sprintf("transmit_request_by_transport: to fh %s fd%d\n", $wfh, fileno($wfh)),0) - if $trace >= 4; - - # send frozen request - local $\; - $wfh->print($encoded_request) # autoflush enabled - or do { - my $err = $!; - # XXX could/should make new connection and retry - $self->_connection_kill; - die "Error sending request: $err"; - }; - $self->trace_msg("Request sent: $encoded_request\n",0) if $trace >= 4; - - return undef; # indicate no response yet (so caller calls receive_response_by_transport) -} - - -sub receive_response_by_transport { - my $self = shift; - my $trace = $self->trace; - - $self->trace_msg("receive_response_by_transport: awaiting response\n",0) if $trace >= 4; - my $connection = $self->connection_info || die; - my ($pid, $rfh, $efh, $cmd) = @{$connection}{qw(pid rfh efh cmd)}; - - my $errno = 0; - my $encoded_response; - my $stderr_msg; - - $self->read_response_from_fh( { - $efh => { - error => sub { warn "error reading response stderr: $!"; $errno||=$!; 1 }, - eof => sub { warn "eof reading efh" if $trace >= 4; 1 }, - read => sub { $stderr_msg .= $_; 0 }, - }, - $rfh => { - error => sub { warn "error reading response: $!"; $errno||=$!; 1 }, - eof => sub { warn "eof reading rfh" if $trace >= 4; 1 }, - read => sub { $encoded_response .= $_; ($encoded_response=~s/\015\012$//) ? 1 : 0 }, - }, - }); - - # if we got no output on stdout at all then the command has - # probably exited, possibly with an error to stderr. - # Turn this situation into a reasonably useful DBI error. - if (not $encoded_response) { - my @msg; - push @msg, "error while reading response: $errno" if $errno; - if ($stderr_msg) { - chomp $stderr_msg; - push @msg, sprintf "error reported by \"%s\" (pid %d%s): %s", - $self->cmd_as_string, - $pid, ((kill 0, $pid) ? "" : ", exited"), - $stderr_msg; - } - die join(", ", "No response received", @msg)."\n"; - } - - $self->trace_msg("Response received: $encoded_response\n",0) - if $trace >= 4; - - $self->trace_msg("Gofer stream stderr message: $stderr_msg\n",0) - if $stderr_msg && $trace; - - my $frozen_response = pack("H*", $encoded_response); - - # XXX need to be able to detect and deal with corruption - my $response = $self->thaw_response($frozen_response); - - if ($stderr_msg) { - # add stderr messages as warnings (for PrintWarn) - $response->add_err(0, $stderr_msg, undef, $trace) - # but ignore warning from old version of blib - unless $stderr_msg =~ /^Using .*blib/ && "@$cmd" =~ /-Mblib/; - } - - return $response; -} - -sub transport_timedout { - my $self = shift; - $self->_connection_kill; - return $self->SUPER::transport_timedout(@_); -} - -1; - -__END__ - -=head1 NAME - -DBD::Gofer::Transport::stream - DBD::Gofer transport for stdio streaming - -=head1 SYNOPSIS - - DBI->connect('dbi:Gofer:transport=stream;url=ssh:username@host.example.com;dsn=dbi:...',...) - -or, enable by setting the DBI_AUTOPROXY environment variable: - - export DBI_AUTOPROXY='dbi:Gofer:transport=stream;url=ssh:username@host.example.com' - -=head1 DESCRIPTION - -Without the C parameter it launches a subprocess as - - perl -MDBI::Gofer::Transport::stream -e run_stdio_hex - -and feeds requests into it and reads responses from it. But that's not very useful. - -With a C parameter it uses ssh to launch the subprocess -on a remote system. That's much more useful! - -It gives you secure remote access to DBI databases on any system you can login to. -Using ssh also gives you optional compression and many other features (see the -ssh manual for how to configure that and many other options via ~/.ssh/config file). - -The actual command invoked is something like: - - ssh -xq ssh:username@host.example.com bash -c $setup $run - -where $run is the command shown above, and $command is - - . .bash_profile 2>/dev/null || . .bash_login 2>/dev/null || . .profile 2>/dev/null; exec "$@" - -which is trying (in a limited and fairly unportable way) to setup the environment -(PATH, PERL5LIB etc) as it would be if you had logged in to that system. - -The "C" used in the command will default to the value of $^X when not using ssh. -On most systems that's the full path to the perl that's currently executing. - - -=head1 PERSISTENCE - -Currently gofer stream connections persist (remain connected) after all -database handles have been disconnected. This makes later connections in the -same process very fast. - -Currently up to 5 different gofer stream connections (based on url) can -persist. If more than 5 are in the cache when a new connection is made then -the cache is cleared before adding the new connection. Simple but effective. - -=head1 TO DO - -Document go_perl attribute - -Automatically reconnect (within reason) if there's a transport error. - -Decide on default for persistent connection - on or off? limits? ttl? - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=head1 SEE ALSO - -L - -L - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Mem.pm b/dbLifeLog/DBI-1.641/lib/DBD/Mem.pm deleted file mode 100644 index 86af196..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Mem.pm +++ /dev/null @@ -1,376 +0,0 @@ -# -*- perl -*- -# -# DBD::Mem - A DBI driver for in-memory tables -# -# This module is currently maintained by -# -# Jens Rehsack -# -# Copyright (C) 2016,2017 by Jens Rehsack -# -# All rights reserved. -# -# You may distribute this module under the terms of either the GNU -# General Public License or the Artistic License, as specified in -# the Perl README file. - -require 5.008; -use strict; - -################# -package DBD::Mem; -################# -use base qw( DBI::DBD::SqlEngine ); -use vars qw($VERSION $ATTRIBUTION $drh); -$VERSION = '0.001'; -$ATTRIBUTION = 'DBD::Mem by Jens Rehsack'; - -# no need to have driver() unless you need private methods -# -sub driver ($;$) -{ - my ( $class, $attr ) = @_; - return $drh if ($drh); - - # do the real work in DBI::DBD::SqlEngine - # - $attr->{Attribution} = 'DBD::Mem by Jens Rehsack'; - $drh = $class->SUPER::driver($attr); - - return $drh; -} - -sub CLONE -{ - undef $drh; -} - -##################### -package DBD::Mem::dr; -##################### -$DBD::Mem::dr::imp_data_size = 0; -@DBD::Mem::dr::ISA = qw(DBI::DBD::SqlEngine::dr); - -# you could put some :dr private methods here - -# you may need to over-ride some DBI::DBD::SqlEngine::dr methods here -# but you can probably get away with just letting it do the work -# in most cases - -##################### -package DBD::Mem::db; -##################### -$DBD::Mem::db::imp_data_size = 0; -@DBD::Mem::db::ISA = qw(DBI::DBD::SqlEngine::db); - -use Carp qw/carp/; - -sub set_versions -{ - my $this = $_[0]; - $this->{mem_version} = $DBD::Mem::VERSION; - return $this->SUPER::set_versions(); -} - -sub init_valid_attributes -{ - my $dbh = shift; - - # define valid private attributes - # - # attempts to set non-valid attrs in connect() or - # with $dbh->{attr} will throw errors - # - # the attrs here *must* start with mem_ or foo_ - # - # see the STORE methods below for how to check these attrs - # - $dbh->{mem_valid_attrs} = { - mem_version => 1, # verbose DBD::Mem version - mem_valid_attrs => 1, # DBD::Mem::db valid attrs - mem_readonly_attrs => 1, # DBD::Mem::db r/o attrs - mem_meta => 1, # DBD::Mem public access for f_meta - mem_tables => 1, # DBD::Mem public access for f_meta - }; - $dbh->{mem_readonly_attrs} = { - mem_version => 1, # verbose DBD::Mem version - mem_valid_attrs => 1, # DBD::Mem::db valid attrs - mem_readonly_attrs => 1, # DBD::Mem::db r/o attrs - mem_meta => 1, # DBD::Mem public access for f_meta - }; - - $dbh->{mem_meta} = "mem_tables"; - - return $dbh->SUPER::init_valid_attributes(); -} - -sub get_mem_versions -{ - my ( $dbh, $table ) = @_; - $table ||= ''; - - my $meta; - my $class = $dbh->{ImplementorClass}; - $class =~ s/::db$/::Table/; - $table and ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); - $meta or ( $meta = {} and $class->bootstrap_table_meta( $dbh, $meta, $table ) ); - - return sprintf( "%s using %s", $dbh->{mem_version}, $AnyData2::VERSION ); -} - -package DBD::Mem::st; - -use strict; -use warnings; - -our $imp_data_size = 0; -our @ISA = qw(DBI::DBD::SqlEngine::st); - -############################ -package DBD::Mem::Statement; -############################ - -@DBD::Mem::Statement::ISA = qw(DBI::DBD::SqlEngine::Statement); - - -sub open_table ($$$$$) -{ - my ( $self, $data, $table, $createMode, $lockMode ) = @_; - - my $class = ref $self; - $class =~ s/::Statement/::Table/; - - my $flags = { - createMode => $createMode, - lockMode => $lockMode, - }; - if( defined( $data->{Database}->{mem_table_data}->{$table} ) && $data->{Database}->{mem_table_data}->{$table}) - { - my $t = $data->{Database}->{mem_tables}->{$table}; - $t->seek( $data, 0, 0 ); - return $t; - } - - return $self->SUPER::open_table($data, $table, $createMode, $lockMode); -} - -# ====== DataSource ============================================================ - -package DBD::Mem::DataSource; - -use strict; -use warnings; - -use Carp; - -@DBD::Mem::DataSource::ISA = "DBI::DBD::SqlEngine::DataSource"; - -sub complete_table_name ($$;$) -{ - my ( $self, $meta, $table, $respect_case ) = @_; - $table; -} - -sub open_data ($) -{ - my ( $self, $meta, $attrs, $flags ) = @_; - defined $meta->{data_tbl} or $meta->{data_tbl} = []; -} - -######################## -package DBD::Mem::Table; -######################## - -# shamelessly stolen from SQL::Statement::RAM - -use Carp qw/croak/; - -@DBD::Mem::Table::ISA = qw(DBI::DBD::SqlEngine::Table); - -use Carp qw(croak); - -sub new -{ - #my ( $class, $tname, $col_names, $data_tbl ) = @_; - my ( $class, $data, $attrs, $flags ) = @_; - my $self = $class->SUPER::new($data, $attrs, $flags); - - my $meta = $self->{meta}; - $self->{records} = $meta->{data_tbl}; - $self->{index} = 0; - - $self; -} - -sub bootstrap_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_; - - defined $meta->{sql_data_source} or $meta->{sql_data_source} = "DBD::Mem::DataSource"; - - $meta; -} - -sub fetch_row -{ - my ( $self, $data ) = @_; - - return $self->{row} = - ( $self->{records} and ( $self->{index} < scalar( @{ $self->{records} } ) ) ) - ? [ @{ $self->{records}->[ $self->{index}++ ] } ] - : undef; -} - -sub push_row -{ - my ( $self, $data, $fields ) = @_; - my $currentRow = $self->{index}; - $self->{index} = $currentRow + 1; - $self->{records}->[$currentRow] = $fields; - return 1; -} - -sub truncate -{ - my $self = shift; - return splice @{ $self->{records} }, $self->{index}, 1; -} - -sub push_names -{ - my ( $self, $data, $names ) = @_; - my $meta = $self->{meta}; - $meta->{col_names} = $self->{col_names} = $names; - $self->{org_col_names} = [ @{$names} ]; - $self->{col_nums} = {}; - $self->{col_nums}{ $names->[$_] } = $_ for ( 0 .. scalar @$names - 1 ); -} - -sub drop ($) -{ - my ($self, $data) = @_; - delete $data->{Database}{sql_meta}{$self->{table}}; - return 1; -} # drop - -sub seek -{ - my ( $self, $data, $pos, $whence ) = @_; - return unless defined $self->{records}; - - my ($currentRow) = $self->{index}; - if ( $whence == 0 ) - { - $currentRow = $pos; - } - elsif ( $whence == 1 ) - { - $currentRow += $pos; - } - elsif ( $whence == 2 ) - { - $currentRow = @{ $self->{records} } + $pos; - } - else - { - croak $self . "->seek: Illegal whence argument ($whence)"; - } - - $currentRow < 0 and - croak "Illegal row number: $currentRow"; - $self->{index} = $currentRow; -} - -1; - -=head1 NAME - -DBD::Mem - a DBI driver for Mem & MLMem files - -=head1 SYNOPSIS - - use DBI; - $dbh = DBI->connect('dbi:Mem:', undef, undef, {}); - $dbh = DBI->connect('dbi:Mem:', undef, undef, {RaiseError => 1}); - - # or - $dbh = DBI->connect('dbi:Mem:'); - $dbh = DBI->connect('DBI:Mem(RaiseError=1):'); - -and other variations on connect() as shown in the L docs and -. - -Use standard DBI prepare, execute, fetch, placeholders, etc., -see L for an example. - -=head1 DESCRIPTION - -DBD::Mem is a database management system that works right out of the box. -If you have a standard installation of Perl and DBI you can begin creating, -accessing, and modifying simple database tables without any further modules. -You can add other modules (e.g., SQL::Statement) for improved functionality. - -DBD::Mem doesn't store any data persistently - all data has the lifetime of -the instantiated C<$dbh>. The main reason to use DBD::Mem is to use extended -features of L where temporary tables are required. One can -use DBD::Mem to simulate C or sub-queries. - -Bundling C with L will allow us further compatibility checks -of L beyond the capabilities of L and -L. This will ensure DBI provided basis for drivers like -L or L are better prepared and tested for -not-file based backends. - -=head2 Metadata - -There're no new meta data introduced by C. See -L for full description. - -=head1 GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS - -If you need help installing or using DBD::Mem, please write to the DBI -users mailing list at L or to the -comp.lang.perl.modules newsgroup on usenet. I cannot always answer -every question quickly but there are many on the mailing list or in -the newsgroup who can. - -DBD developers for DBD's which rely on DBI::DBD::SqlEngine or DBD::Mem or -use one of them as an example are suggested to join the DBI developers -mailing list at L and strongly encouraged to join our -IRC channel at L. - -If you have suggestions, ideas for improvements, or bugs to report, please -report a bug as described in DBI. Do not mail any of the authors directly, -you might not get an answer. - -When reporting bugs, please send the output of C<< $dbh->mem_versions($table) >> -for a table that exhibits the bug and as small a sample as you can make of -the code that produces the bug. And of course, patches are welcome, too -:-). - -If you need enhancements quickly, you can get commercial support as -described at L or you can contact Jens Rehsack -at rehsack@cpan.org for commercial support. - -=head1 AUTHOR AND COPYRIGHT - -This module is written by Jens Rehsack < rehsack AT cpan.org >. - - Copyright (c) 2016- by Jens Rehsack, all rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=head1 SEE ALSO - -L for the Database interface of the Perl Programming Language. - -L and L for the available SQL engines. - -L where the implementation is shamelessly stolen from -to allow DBI bundled Pure-Perl drivers increase the test coverage. - -L using C for an incredible fast in-memory database engine. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/NullP.pm b/dbLifeLog/DBI-1.641/lib/DBD/NullP.pm deleted file mode 100644 index f70c67c..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/NullP.pm +++ /dev/null @@ -1,206 +0,0 @@ -use strict; -{ - package DBD::NullP; - - require DBI; - require Carp; - - our @EXPORT = qw(); # Do NOT @EXPORT anything. - our $VERSION = "12.014715"; - -# $Id: NullP.pm 14714 2011-02-22 17:27:07Z Tim $ -# -# Copyright (c) 1994-2007 Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - our $drh = undef; # holds driver handle once initialised - - sub driver{ - return $drh if $drh; - my($class, $attr) = @_; - $class .= "::dr"; - ($drh) = DBI::_new_drh($class, { - 'Name' => 'NullP', - 'Version' => $VERSION, - 'Attribution' => 'DBD Example Null Perl stub by Tim Bunce', - }, [ qw'example implementors private data']); - $drh; - } - - sub CLONE { - undef $drh; - } -} - - -{ package DBD::NullP::dr; # ====== DRIVER ====== - our $imp_data_size = 0; - use strict; - - sub connect { # normally overridden, but a handy default - my $dbh = shift->SUPER::connect(@_) - or return; - $dbh->STORE(Active => 1); - $dbh; - } - - - sub DESTROY { undef } -} - - -{ package DBD::NullP::db; # ====== DATABASE ====== - our $imp_data_size = 0; - use strict; - use Carp qw(croak); - - # Added get_info to support tests in 10examp.t - sub get_info { - my ($dbh, $type) = @_; - - if ($type == 29) { # identifier quote - return '"'; - } - return; - } - - # Added table_info to support tests in 10examp.t - sub table_info { - my ($dbh, $catalog, $schema, $table, $type) = @_; - - my ($outer, $sth) = DBI::_new_sth($dbh, { - 'Statement' => 'tables', - }); - if (defined($type) && $type eq '%' && # special case for tables('','','','%') - grep {defined($_) && $_ eq ''} ($catalog, $schema, $table)) { - $outer->{dbd_nullp_data} = [[undef, undef, undef, 'TABLE', undef], - [undef, undef, undef, 'VIEW', undef], - [undef, undef, undef, 'ALIAS', undef]]; - } elsif (defined($catalog) && $catalog eq '%' && # special case for tables('%','','') - grep {defined($_) && $_ eq ''} ($schema, $table)) { - $outer->{dbd_nullp_data} = [['catalog1', undef, undef, undef, undef], - ['catalog2', undef, undef, undef, undef]]; - } else { - $outer->{dbd_nullp_data} = [['catalog', 'schema', 'table1', 'TABLE']]; - $outer->{dbd_nullp_data} = [['catalog', 'schema', 'table2', 'TABLE']]; - $outer->{dbd_nullp_data} = [['catalog', 'schema', 'table3', 'TABLE']]; - } - $outer->STORE(NUM_OF_FIELDS => 5); - $sth->STORE(Active => 1); - return $outer; - } - - sub prepare { - my ($dbh, $statement)= @_; - - my ($outer, $sth) = DBI::_new_sth($dbh, { - 'Statement' => $statement, - }); - - return $outer; - } - - sub FETCH { - my ($dbh, $attrib) = @_; - # In reality this would interrogate the database engine to - # either return dynamic values that cannot be precomputed - # or fetch and cache attribute values too expensive to prefetch. - return $dbh->SUPER::FETCH($attrib); - } - - sub STORE { - my ($dbh, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - if ($attrib eq 'AutoCommit') { - Carp::croak("Can't disable AutoCommit") unless $value; - # convert AutoCommit values to magic ones to let DBI - # know that the driver has 'handled' the AutoCommit attribute - $value = ($value) ? -901 : -900; - } elsif ($attrib eq 'nullp_set_err') { - # a fake attribute to produce a test case where STORE issues a warning - $dbh->set_err($value, $value); - } - return $dbh->SUPER::STORE($attrib, $value); - } - - sub ping { 1 } - - sub disconnect { - shift->STORE(Active => 0); - } - -} - - -{ package DBD::NullP::st; # ====== STATEMENT ====== - our $imp_data_size = 0; - use strict; - - sub bind_param { - my ($sth, $param, $value, $attr) = @_; - $sth->{ParamValues}{$param} = $value; - $sth->{ParamAttr}{$param} = $attr - if defined $attr; # attr is sticky if not explicitly set - return 1; - } - - sub execute { - my $sth = shift; - $sth->bind_param($_, $_[$_-1]) for (1..@_); - if ($sth->{Statement} =~ m/^ \s* SELECT \s+/xmsi) { - $sth->STORE(NUM_OF_FIELDS => 1); - $sth->{NAME} = [ "fieldname" ]; - # just for the sake of returning something, we return the params - my $params = $sth->{ParamValues} || {}; - $sth->{dbd_nullp_data} = [ @{$params}{ sort keys %$params } ]; - $sth->STORE(Active => 1); - } - # force a sleep - handy for testing - elsif ($sth->{Statement} =~ m/^ \s* SLEEP \s+ (\S+) /xmsi) { - my $secs = $1; - if (eval { require Time::HiRes; defined &Time::HiRes::sleep }) { - Time::HiRes::sleep($secs); - } - else { - sleep $secs; - } - } - # force an error - handy for testing - elsif ($sth->{Statement} =~ m/^ \s* ERROR \s+ (\d+) \s* (.*) /xmsi) { - return $sth->set_err($1, $2); - } - # anything else is silently ignored, successfully - 1; - } - - sub fetchrow_arrayref { - my $sth = shift; - my $data = shift @{$sth->{dbd_nullp_data}}; - if (!$data || !@$data) { - $sth->finish; # no more data so finish - return undef; - } - return $sth->_set_fbav($data); - } - *fetch = \&fetchrow_arrayref; # alias - - sub FETCH { - my ($sth, $attrib) = @_; - # would normally validate and only fetch known attributes - # else pass up to DBI to handle - return $sth->SUPER::FETCH($attrib); - } - - sub STORE { - my ($sth, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - return $sth->SUPER::STORE($attrib, $value); - } - -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Proxy.pm b/dbLifeLog/DBI-1.641/lib/DBD/Proxy.pm deleted file mode 100644 index 4240dab..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Proxy.pm +++ /dev/null @@ -1,1004 +0,0 @@ -# -*- perl -*- -# -# -# DBD::Proxy - DBI Proxy driver -# -# -# Copyright (c) 1997,1998 Jochen Wiedmann -# -# The DBD::Proxy module is free software; you can redistribute it and/or -# modify it under the same terms as Perl itself. In particular permission -# is granted to Tim Bunce for distributing this as a part of the DBI. -# -# -# Author: Jochen Wiedmann -# Am Eisteich 9 -# 72555 Metzingen -# Germany -# -# Email: joe@ispsoft.de -# Phone: +49 7123 14881 -# - -use strict; -use Carp; - -require DBI; -DBI->require_version(1.0201); - -use RPC::PlClient 0.2000; # XXX change to 0.2017 once it's released - -{ package DBD::Proxy::RPC::PlClient; - @DBD::Proxy::RPC::PlClient::ISA = qw(RPC::PlClient); - sub Call { - my $self = shift; - if ($self->{debug}) { - my ($rpcmeth, $obj, $method, @args) = @_; - local $^W; # silence undefs - Carp::carp("Server $rpcmeth $method(@args)"); - } - return $self->SUPER::Call(@_); - } -} - - -package DBD::Proxy; - -use vars qw($VERSION $drh %ATTR); - -$VERSION = "0.2004"; - -$drh = undef; # holds driver handle once initialised - -%ATTR = ( # common to db & st, see also %ATTR in DBD::Proxy::db & ::st - 'Warn' => 'local', - 'Active' => 'local', - 'Kids' => 'local', - 'CachedKids' => 'local', - 'PrintError' => 'local', - 'RaiseError' => 'local', - 'HandleError' => 'local', - 'TraceLevel' => 'cached', - 'CompatMode' => 'local', -); - -sub driver ($$) { - if (!$drh) { - my($class, $attr) = @_; - - $class .= "::dr"; - - $drh = DBI::_new_drh($class, { - 'Name' => 'Proxy', - 'Version' => $VERSION, - 'Attribution' => 'DBD::Proxy by Jochen Wiedmann', - }); - $drh->STORE(CompatMode => 1); # disable DBI dispatcher attribute cache (for FETCH) - } - $drh; -} - -sub CLONE { - undef $drh; -} - -sub proxy_set_err { - my ($h,$errmsg) = @_; - my ($err, $state) = ($errmsg =~ s/ \[err=(.*?),state=(.*?)\]//) - ? ($1, $2) : (1, ' ' x 5); - return $h->set_err($err, $errmsg, $state); -} - -package DBD::Proxy::dr; # ====== DRIVER ====== - -$DBD::Proxy::dr::imp_data_size = 0; - -sub connect ($$;$$) { - my($drh, $dsn, $user, $auth, $attr)= @_; - my($dsnOrig) = $dsn; - - my %attr = %$attr; - my ($var, $val); - while (length($dsn)) { - if ($dsn =~ /^dsn=(.*)/) { - $attr{'dsn'} = $1; - last; - } - if ($dsn =~ /^(.*?);(.*)/) { - $var = $1; - $dsn = $2; - } else { - $var = $dsn; - $dsn = ''; - } - if ($var =~ /^(.*?)=(.*)/) { - $var = $1; - $val = $2; - $attr{$var} = $val; - } - } - - my $err = ''; - if (!defined($attr{'hostname'})) { $err .= " Missing hostname."; } - if (!defined($attr{'port'})) { $err .= " Missing port."; } - if (!defined($attr{'dsn'})) { $err .= " Missing remote dsn."; } - - # Create a cipher object, if requested - my $cipherRef = undef; - if ($attr{'cipher'}) { - $cipherRef = eval { $attr{'cipher'}->new(pack('H*', - $attr{'key'})) }; - if ($@) { $err .= " Cannot create cipher object: $@."; } - } - my $userCipherRef = undef; - if ($attr{'userkey'}) { - my $cipher = $attr{'usercipher'} || $attr{'cipher'}; - $userCipherRef = eval { $cipher->new(pack('H*', $attr{'userkey'})) }; - if ($@) { $err .= " Cannot create usercipher object: $@."; } - } - - return DBD::Proxy::proxy_set_err($drh, $err) if $err; # Returns undef - - my %client_opts = ( - 'peeraddr' => $attr{'hostname'}, - 'peerport' => $attr{'port'}, - 'socket_proto' => 'tcp', - 'application' => $attr{dsn}, - 'user' => $user || '', - 'password' => $auth || '', - 'version' => $DBD::Proxy::VERSION, - 'cipher' => $cipherRef, - 'debug' => $attr{debug} || 0, - 'timeout' => $attr{timeout} || undef, - 'logfile' => $attr{logfile} || undef - ); - # Options starting with 'proxy_rpc_' are forwarded to the RPC layer after - # stripping the prefix. - while (my($var,$val) = each %attr) { - if ($var =~ s/^proxy_rpc_//) { - $client_opts{$var} = $val; - } - } - # Create an RPC::PlClient object. - my($client, $msg) = eval { DBD::Proxy::RPC::PlClient->new(%client_opts) }; - - return DBD::Proxy::proxy_set_err($drh, "Cannot log in to DBI::ProxyServer: $@") - if $@; # Returns undef - return DBD::Proxy::proxy_set_err($drh, "Constructor didn't return a handle: $msg") - unless ($msg =~ /^((?:\w+|\:\:)+)=(\w+)/); # Returns undef - - $msg = RPC::PlClient::Object->new($1, $client, $msg); - - my $max_proto_ver; - my ($server_ver_str) = eval { $client->Call('Version') }; - if ( $@ ) { - # Server denies call, assume legacy protocol. - $max_proto_ver = 1; - } else { - # Parse proxy server version. - my ($server_ver_num) = $server_ver_str =~ /^DBI::ProxyServer\s+([\d\.]+)/; - $max_proto_ver = $server_ver_num >= 0.3 ? 2 : 1; - } - my $req_proto_ver; - if ( exists $attr{proxy_lazy_prepare} ) { - $req_proto_ver = ($attr{proxy_lazy_prepare} == 0) ? 2 : 1; - return DBD::Proxy::proxy_set_err($drh, - "DBI::ProxyServer does not support synchronous statement preparation.") - if $max_proto_ver < $req_proto_ver; - } - - # Switch to user specific encryption mode, if desired - if ($userCipherRef) { - $client->{'cipher'} = $userCipherRef; - } - - # create a 'blank' dbh - my $this = DBI::_new_dbh($drh, { - 'Name' => $dsnOrig, - 'proxy_dbh' => $msg, - 'proxy_client' => $client, - 'RowCacheSize' => $attr{'RowCacheSize'} || 20, - 'proxy_proto_ver' => $req_proto_ver || 1 - }); - - foreach $var (keys %attr) { - if ($var =~ /proxy_/) { - $this->{$var} = $attr{$var}; - } - } - $this->SUPER::STORE('Active' => 1); - - $this; -} - - -sub DESTROY { undef } - - -package DBD::Proxy::db; # ====== DATABASE ====== - -$DBD::Proxy::db::imp_data_size = 0; - -# XXX probably many more methods need to be added here -# in order to trigger our AUTOLOAD to redirect them to the server. -# (Unless the sub is declared it's bypassed by perl method lookup.) -# See notes in ToDo about method metadata -# The question is whether to add all the methods in %DBI::DBI_methods -# to the corresponding classes (::db, ::st etc) -# Also need to consider methods that, if proxied, would change the server state -# in a way that might not be visible on the client, ie begin_work -> AutoCommit. - -sub commit; -sub rollback; -sub ping; - -use vars qw(%ATTR $AUTOLOAD); - -# inherited: STORE / FETCH against this class. -# local: STORE / FETCH against parent class. -# cached: STORE to remote and local objects, FETCH from local. -# remote: STORE / FETCH against remote object only (default). -# -# Note: Attribute names starting with 'proxy_' always treated as 'inherited'. -# -%ATTR = ( # see also %ATTR in DBD::Proxy::st - %DBD::Proxy::ATTR, - RowCacheSize => 'inherited', - #AutoCommit => 'cached', - 'FetchHashKeyName' => 'cached', - Statement => 'local', - Driver => 'local', - dbi_connect_closure => 'local', - Username => 'local', -); - -sub AUTOLOAD { - my $method = $AUTOLOAD; - $method =~ s/(.*::(.*)):://; - my $class = $1; - my $type = $2; - #warn "AUTOLOAD of $method (class=$class, type=$type)"; - my %expand = ( - 'method' => $method, - 'class' => $class, - 'type' => $type, - 'call' => "$method(\@_)", - # XXX was trying to be smart but was tripping up over the DBI's own - # smartness. Disabled, but left here in case there are issues. - # 'call' => (UNIVERSAL::can("DBI::_::$type", $method)) ? "$method(\@_)" : "func(\@_, '$method')", - ); - - my $method_code = q{ - package ~class~; - sub ~method~ { - my $h = shift; - local $@; - my @result = wantarray - ? eval { $h->{'proxy_~type~h'}->~call~ } - : eval { scalar $h->{'proxy_~type~h'}->~call~ }; - return DBD::Proxy::proxy_set_err($h, $@) if $@; - return wantarray ? @result : $result[0]; - } - }; - $method_code =~ s/\~(\w+)\~/$expand{$1}/eg; - local $SIG{__DIE__} = 'DEFAULT'; - my $err = do { local $@; eval $method_code.2; $@ }; - die $err if $err; - goto &$AUTOLOAD; -} - -sub DESTROY { - my $dbh = shift; - local $@ if $@; # protect $@ - $dbh->disconnect if $dbh->SUPER::FETCH('Active'); -} - - -sub connected { } # client-side not server-side, RT#75868 - -sub disconnect ($) { - my ($dbh) = @_; - - # Sadly the Proxy too-often disagrees with the backend database - # on the subject of 'Active'. In the short term, I'd like the - # Proxy to ease up and let me decide when it's proper to go over - # the wire. This ultimately applies to finish() as well. - #return unless $dbh->SUPER::FETCH('Active'); - - # Drop database connection at remote end - my $rdbh = $dbh->{'proxy_dbh'}; - if ( $rdbh ) { - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - eval { $rdbh->disconnect() } ; - DBD::Proxy::proxy_set_err($dbh, $@) if $@; - } - - # Close TCP connect to remote - # XXX possibly best left till DESTROY? Add a config attribute to choose? - #$dbh->{proxy_client}->Disconnect(); # Disconnect method requires newer PlRPC module - $dbh->{proxy_client}->{socket} = undef; # hack - - $dbh->SUPER::STORE('Active' => 0); - 1; -} - - -sub STORE ($$$) { - my($dbh, $attr, $val) = @_; - my $type = $ATTR{$attr} || 'remote'; - - if ($attr eq 'TraceLevel') { - warn("TraceLevel $val"); - my $pc = $dbh->{proxy_client} || die; - $pc->{logfile} ||= 1; # XXX hack - $pc->{debug} = ($val && $val >= 4); - $pc->Debug("$pc debug enabled") if $pc->{debug}; - } - - if ($attr =~ /^proxy_/ || $type eq 'inherited') { - $dbh->{$attr} = $val; - return 1; - } - - if ($type eq 'remote' || $type eq 'cached') { - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $dbh->{'proxy_dbh'}->STORE($attr => $val) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; # returns undef - $dbh->SUPER::STORE($attr => $val) if $type eq 'cached'; - return $result; - } - return $dbh->SUPER::STORE($attr => $val); -} - -sub FETCH ($$) { - my($dbh, $attr) = @_; - # we only get here for cached attribute values if the handle is in CompatMode - # otherwise the DBI dispatcher handles the FETCH itself from the attribute cache. - my $type = $ATTR{$attr} || 'remote'; - - if ($attr =~ /^proxy_/ || $type eq 'inherited' || $type eq 'cached') { - return $dbh->{$attr}; - } - - return $dbh->SUPER::FETCH($attr) unless $type eq 'remote'; - - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $dbh->{'proxy_dbh'}->FETCH($attr) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; - return $result; -} - -sub prepare ($$;$) { - my($dbh, $stmt, $attr) = @_; - my $sth = DBI::_new_sth($dbh, { - 'Statement' => $stmt, - 'proxy_attr' => $attr, - 'proxy_cache_only' => 0, - 'proxy_params' => [], - } - ); - my $proto_ver = $dbh->{'proxy_proto_ver'}; - if ( $proto_ver > 1 ) { - $sth->{'proxy_attr_cache'} = {cache_filled => 0}; - my $rdbh = $dbh->{'proxy_dbh'}; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $rsth = eval { $rdbh->prepare($sth->{'Statement'}, $sth->{'proxy_attr'}, undef, $proto_ver) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - return DBD::Proxy::proxy_set_err($sth, "Constructor didn't return a handle: $rsth") - unless ($rsth =~ /^((?:\w+|\:\:)+)=(\w+)/); - - my $client = $dbh->{'proxy_client'}; - $rsth = RPC::PlClient::Object->new($1, $client, $rsth); - - $sth->{'proxy_sth'} = $rsth; - # If statement is a positioned update we do not want any readahead. - $sth->{'RowCacheSize'} = 1 if $stmt =~ /\bfor\s+update\b/i; - # Since resources are used by prepared remote handle, mark us active. - $sth->SUPER::STORE(Active => 1); - } - $sth; -} - -sub quote { - my $dbh = shift; - my $proxy_quote = $dbh->{proxy_quote} || 'remote'; - - return $dbh->SUPER::quote(@_) - if $proxy_quote eq 'local' && @_ == 1; - - # For the common case of only a single argument - # (no $data_type) we could learn and cache the behaviour. - # Or we could probe the driver with a few test cases. - # Or we could add a way to ask the DBI::ProxyServer - # if $dbh->can('quote') == \&DBI::_::db::quote. - # Tim - # - # Sounds all *very* smart to me. I'd rather suggest to - # implement some of the typical quote possibilities - # and let the user set - # $dbh->{'proxy_quote'} = 'backslash_escaped'; - # for example. - # Jochen - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $dbh->{'proxy_dbh'}->quote(@_) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; - return $result; -} - -sub table_info { - my $dbh = shift; - my $rdbh = $dbh->{'proxy_dbh'}; - #warn "table_info(@_)"; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my($numFields, $names, $types, @rows) = eval { $rdbh->table_info(@_) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; - my ($sth, $inner) = DBI::_new_sth($dbh, { - 'Statement' => "SHOW TABLES", - 'proxy_params' => [], - 'proxy_data' => \@rows, - 'proxy_attr_cache' => { - 'NUM_OF_PARAMS' => 0, - 'NUM_OF_FIELDS' => $numFields, - 'NAME' => $names, - 'TYPE' => $types, - 'cache_filled' => 1 - }, - 'proxy_cache_only' => 1, - }); - $sth->SUPER::STORE('NUM_OF_FIELDS' => $numFields); - $inner->{NAME} = $names; - $inner->{TYPE} = $types; - $sth->SUPER::STORE('Active' => 1); # already execute()'d - $sth->{'proxy_rows'} = @rows; - return $sth; -} - -sub tables { - my $dbh = shift; - #warn "tables(@_)"; - return $dbh->SUPER::tables(@_); -} - - -sub type_info_all { - my $dbh = shift; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $dbh->{'proxy_dbh'}->type_info_all(@_) }; - return DBD::Proxy::proxy_set_err($dbh, $@) if $@; - return $result; -} - - -package DBD::Proxy::st; # ====== STATEMENT ====== - -$DBD::Proxy::st::imp_data_size = 0; - -use vars qw(%ATTR); - -# inherited: STORE to current object. FETCH from current if exists, else call up -# to the (proxy) database object. -# local: STORE / FETCH against parent class. -# cache_only: STORE noop (read-only). FETCH from private_* if exists, else call -# remote and cache the result. -# remote: STORE / FETCH against remote object only (default). -# -# Note: Attribute names starting with 'proxy_' always treated as 'inherited'. -# -%ATTR = ( # see also %ATTR in DBD::Proxy::db - %DBD::Proxy::ATTR, - 'Database' => 'local', - 'RowsInCache' => 'local', - 'RowCacheSize' => 'inherited', - 'NULLABLE' => 'cache_only', - 'NAME' => 'cache_only', - 'TYPE' => 'cache_only', - 'PRECISION' => 'cache_only', - 'SCALE' => 'cache_only', - 'NUM_OF_FIELDS' => 'cache_only', - 'NUM_OF_PARAMS' => 'cache_only' -); - -*AUTOLOAD = \&DBD::Proxy::db::AUTOLOAD; - -sub execute ($@) { - my $sth = shift; - my $params = @_ ? \@_ : $sth->{'proxy_params'}; - - # new execute, so delete any cached rows from previous execute - undef $sth->{'proxy_data'}; - undef $sth->{'proxy_rows'}; - - my $rsth = $sth->{proxy_sth}; - my $dbh = $sth->FETCH('Database'); - my $proto_ver = $dbh->{proxy_proto_ver}; - - my ($numRows, @outData); - - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - if ( $proto_ver > 1 ) { - ($numRows, @outData) = eval { $rsth->execute($params, $proto_ver) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - - # Attributes passed back only on the first execute() of a statement. - unless ($sth->{proxy_attr_cache}->{cache_filled}) { - my ($numFields, $numParams, $names, $types) = splice(@outData, 0, 4); - $sth->{'proxy_attr_cache'} = { - 'NUM_OF_FIELDS' => $numFields, - 'NUM_OF_PARAMS' => $numParams, - 'NAME' => $names, - 'cache_filled' => 1 - }; - $sth->SUPER::STORE('NUM_OF_FIELDS' => $numFields); - $sth->SUPER::STORE('NUM_OF_PARAMS' => $numParams); - } - - } - else { - if ($rsth) { - ($numRows, @outData) = eval { $rsth->execute($params, $proto_ver) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - - } - else { - my $rdbh = $dbh->{'proxy_dbh'}; - - # Legacy prepare is actually prepare + first execute on the server. - ($rsth, @outData) = - eval { $rdbh->prepare($sth->{'Statement'}, - $sth->{'proxy_attr'}, $params, $proto_ver) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - return DBD::Proxy::proxy_set_err($sth, "Constructor didn't return a handle: $rsth") - unless ($rsth =~ /^((?:\w+|\:\:)+)=(\w+)/); - - my $client = $dbh->{'proxy_client'}; - $rsth = RPC::PlClient::Object->new($1, $client, $rsth); - - my ($numFields, $numParams, $names, $types) = splice(@outData, 0, 4); - $sth->{'proxy_sth'} = $rsth; - $sth->{'proxy_attr_cache'} = { - 'NUM_OF_FIELDS' => $numFields, - 'NUM_OF_PARAMS' => $numParams, - 'NAME' => $names - }; - $sth->SUPER::STORE('NUM_OF_FIELDS' => $numFields); - $sth->SUPER::STORE('NUM_OF_PARAMS' => $numParams); - $numRows = shift @outData; - } - } - # Always condition active flag. - $sth->SUPER::STORE('Active' => 1) if $sth->FETCH('NUM_OF_FIELDS'); # is SELECT - $sth->{'proxy_rows'} = $numRows; - # Any remaining items are output params. - if (@outData) { - foreach my $p (@$params) { - if (ref($p->[0])) { - my $ref = shift @outData; - ${$p->[0]} = $$ref; - } - } - } - - $sth->{'proxy_rows'} || '0E0'; -} - -sub fetch ($) { - my $sth = shift; - - my $data = $sth->{'proxy_data'}; - - $sth->{'proxy_rows'} = 0 unless defined $sth->{'proxy_rows'}; - - if(!$data || !@$data) { - return undef unless $sth->SUPER::FETCH('Active'); - - my $rsth = $sth->{'proxy_sth'}; - if (!$rsth) { - die "Attempt to fetch row without execute"; - } - my $num_rows = $sth->FETCH('RowCacheSize') || 20; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my @rows = eval { $rsth->fetch($num_rows) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - unless (@rows == $num_rows) { - undef $sth->{'proxy_data'}; - # server side has already called finish - $sth->SUPER::STORE(Active => 0); - } - return undef unless @rows; - $sth->{'proxy_data'} = $data = [@rows]; - } - my $row = shift @$data; - - $sth->SUPER::STORE(Active => 0) if ( $sth->{proxy_cache_only} and !@$data ); - $sth->{'proxy_rows'}++; - return $sth->_set_fbav($row); -} -*fetchrow_arrayref = \&fetch; - -sub rows ($) { - my $rows = shift->{'proxy_rows'}; - return (defined $rows) ? $rows : -1; -} - -sub finish ($) { - my($sth) = @_; - return 1 unless $sth->SUPER::FETCH('Active'); - my $rsth = $sth->{'proxy_sth'}; - $sth->SUPER::STORE('Active' => 0); - return 0 unless $rsth; # Something's out of sync - my $no_finish = exists($sth->{'proxy_no_finish'}) - ? $sth->{'proxy_no_finish'} - : $sth->FETCH('Database')->{'proxy_no_finish'}; - unless ($no_finish) { - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $rsth->finish() }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - return $result; - } - 1; -} - -sub STORE ($$$) { - my($sth, $attr, $val) = @_; - my $type = $ATTR{$attr} || 'remote'; - - if ($attr =~ /^proxy_/ || $type eq 'inherited') { - $sth->{$attr} = $val; - return 1; - } - - if ($type eq 'cache_only') { - return 0; - } - - if ($type eq 'remote' || $type eq 'cached') { - my $rsth = $sth->{'proxy_sth'} or return undef; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $rsth->STORE($attr => $val) }; - return DBD::Proxy::proxy_set_err($sth, $@) if ($@); - return $result if $type eq 'remote'; # else fall through to cache locally - } - return $sth->SUPER::STORE($attr => $val); -} - -sub FETCH ($$) { - my($sth, $attr) = @_; - - if ($attr =~ /^proxy_/) { - return $sth->{$attr}; - } - - my $type = $ATTR{$attr} || 'remote'; - if ($type eq 'inherited') { - if (exists($sth->{$attr})) { - return $sth->{$attr}; - } - return $sth->FETCH('Database')->{$attr}; - } - - if ($type eq 'cache_only' && - exists($sth->{'proxy_attr_cache'}->{$attr})) { - return $sth->{'proxy_attr_cache'}->{$attr}; - } - - if ($type ne 'local') { - my $rsth = $sth->{'proxy_sth'} or return undef; - local $SIG{__DIE__} = 'DEFAULT'; - local $@; - my $result = eval { $rsth->FETCH($attr) }; - return DBD::Proxy::proxy_set_err($sth, $@) if $@; - return $result; - } - elsif ($attr eq 'RowsInCache') { - my $data = $sth->{'proxy_data'}; - $data ? @$data : 0; - } - else { - $sth->SUPER::FETCH($attr); - } -} - -sub bind_param ($$$@) { - my $sth = shift; my $param = shift; - $sth->{'proxy_params'}->[$param-1] = [@_]; -} -*bind_param_inout = \&bind_param; - -sub DESTROY { - my $sth = shift; - $sth->finish if $sth->SUPER::FETCH('Active'); -} - - -1; - - -__END__ - -=head1 NAME - -DBD::Proxy - A proxy driver for the DBI - -=head1 SYNOPSIS - - use DBI; - - $dbh = DBI->connect("dbi:Proxy:hostname=$host;port=$port;dsn=$db", - $user, $passwd); - - # See the DBI module documentation for full details - -=head1 DESCRIPTION - -DBD::Proxy is a Perl module for connecting to a database via a remote -DBI driver. See L for an alternative with different trade-offs. - -This is of course not needed for DBI drivers which already -support connecting to a remote database, but there are engines which -don't offer network connectivity. - -Another application is offering database access through a firewall, as -the driver offers query based restrictions. For example you can -restrict queries to exactly those that are used in a given CGI -application. - -Speaking of CGI, another application is (or rather, will be) to reduce -the database connect/disconnect overhead from CGI scripts by using -proxying the connect_cached method. The proxy server will hold the -database connections open in a cache. The CGI script then trades the -database connect/disconnect overhead for the DBD::Proxy -connect/disconnect overhead which is typically much less. - - -=head1 CONNECTING TO THE DATABASE - -Before connecting to a remote database, you must ensure, that a Proxy -server is running on the remote machine. There's no default port, so -you have to ask your system administrator for the port number. See -L for details. - -Say, your Proxy server is running on machine "alpha", port 3334, and -you'd like to connect to an ODBC database called "mydb" as user "joe" -with password "hello". When using DBD::ODBC directly, you'd do a - - $dbh = DBI->connect("DBI:ODBC:mydb", "joe", "hello"); - -With DBD::Proxy this becomes - - $dsn = "DBI:Proxy:hostname=alpha;port=3334;dsn=DBI:ODBC:mydb"; - $dbh = DBI->connect($dsn, "joe", "hello"); - -You see, this is mainly the same. The DBD::Proxy module will create a -connection to the Proxy server on "alpha" which in turn will connect -to the ODBC database. - -Refer to the L documentation on the C method for a way -to automatically use DBD::Proxy without having to change your code. - -DBD::Proxy's DSN string has the format - - $dsn = "DBI:Proxy:key1=val1; ... ;keyN=valN;dsn=valDSN"; - -In other words, it is a collection of key/value pairs. The following -keys are recognized: - -=over 4 - -=item hostname - -=item port - -Hostname and port of the Proxy server; these keys must be present, -no defaults. Example: - - hostname=alpha;port=3334 - -=item dsn - -The value of this attribute will be used as a dsn name by the Proxy -server. Thus it must have the format C, in particular -it will contain colons. The I value may contain semicolons, hence -this key *must* be the last and it's value will be the complete -remaining part of the dsn. Example: - - dsn=DBI:ODBC:mydb - -=item cipher - -=item key - -=item usercipher - -=item userkey - -By using these fields you can enable encryption. If you set, -for example, - - cipher=$class;key=$key - -(note the semicolon) then DBD::Proxy will create a new cipher object -by executing - - $cipherRef = $class->new(pack("H*", $key)); - -and pass this object to the RPC::PlClient module when creating a -client. See L. Example: - - cipher=IDEA;key=97cd2375efa329aceef2098babdc9721 - -The usercipher/userkey attributes allow you to use two phase encryption: -The cipher/key encryption will be used in the login and authorisation -phase. Once the client is authorised, he will change to usercipher/userkey -encryption. Thus the cipher/key pair is a B based secret, typically -less secure than the usercipher/userkey secret and readable by anyone. -The usercipher/userkey secret is B private secret. - -Of course encryption requires an appropriately configured server. See -L. - -=item debug - -Turn on debugging mode - -=item stderr - -This attribute will set the corresponding attribute of the RPC::PlClient -object, thus logging will not use syslog(), but redirected to stderr. -This is the default under Windows. - - stderr=1 - -=item logfile - -Similar to the stderr attribute, but output will be redirected to the -given file. - - logfile=/dev/null - -=item RowCacheSize - -The DBD::Proxy driver supports this attribute (which is DBI standard, -as of DBI 1.02). It's used to reduce network round-trips by fetching -multiple rows in one go. The current default value is 20, but this may -change. - - -=item proxy_no_finish - -This attribute can be used to reduce network traffic: If the -application is calling $sth->finish() then the proxy tells the server -to finish the remote statement handle. Of course this slows down things -quite a lot, but is perfectly good for reducing memory usage with -persistent connections. - -However, if you set the I attribute to a TRUE value, -either in the database handle or in the statement handle, then finish() -calls will be suppressed. This is what you want, for example, in small -and fast CGI applications. - -=item proxy_quote - -This attribute can be used to reduce network traffic: By default calls -to $dbh->quote() are passed to the remote driver. Of course this slows -down things quite a lot, but is the safest default behaviour. - -However, if you set the I attribute to the value 'C' -either in the database handle or in the statement handle, and the call -to quote has only one parameter, then the local default DBI quote -method will be used (which will be faster but may be wrong). - -=back - -=head1 KNOWN ISSUES - -=head2 Unproxied method calls - -If a method isn't being proxied, try declaring a stub sub in the appropriate -package (DBD::Proxy::db for a dbh method, and DBD::Proxy::st for an sth method). -For example: - - sub DBD::Proxy::db::selectall_arrayref; - -That will enable selectall_arrayref to be proxied. - -Currently many methods aren't explicitly proxied and so you get the DBI's -default methods executed on the client. - -Some of those methods, like selectall_arrayref, may then call other methods -that are proxied (selectall_arrayref calls fetchall_arrayref which calls fetch -which is proxied). So things may appear to work but operate more slowly than -the could. - -This may all change in a later version. - -=head2 Complex handle attributes - -Sometimes handles are having complex attributes like hash refs or -array refs and not simple strings or integers. For example, with -DBD::CSV, you would like to write something like - - $dbh->{"csv_tables"}->{"passwd"} = - { "sep_char" => ":", "eol" => "\n"; - -The above example would advice the CSV driver to assume the file -"passwd" to be in the format of the /etc/passwd file: Colons as -separators and a line feed without carriage return as line -terminator. - -Surprisingly this example doesn't work with the proxy driver. To understand -the reasons, you should consider the following: The Perl compiler is -executing the above example in two steps: - -=over - -=item 1 - -The first step is fetching the value of the key "csv_tables" in the -handle $dbh. The value returned is complex, a hash ref. - -=item 2 - -The second step is storing some value (the right hand side of the -assignment) as the key "passwd" in the hash ref from step 1. - -=back - -This becomes a little bit clearer, if we rewrite the above code: - - $tables = $dbh->{"csv_tables"}; - $tables->{"passwd"} = { "sep_char" => ":", "eol" => "\n"; - -While the examples work fine without the proxy, the fail due to a -subtle difference in step 1: By DBI magic, the hash ref -$dbh->{'csv_tables'} is returned from the server to the client. -The client creates a local copy. This local copy is the result of -step 1. In other words, step 2 modifies a local copy of the hash ref, -but not the server's hash ref. - -The workaround is storing the modified local copy back to the server: - - $tables = $dbh->{"csv_tables"}; - $tables->{"passwd"} = { "sep_char" => ":", "eol" => "\n"; - $dbh->{"csv_tables"} = $tables; - - -=head1 SECURITY WARNING - -L used underneath is not secure due to serializing and -deserializing data with L module. Use the proxy driver only in -trusted environment. - - -=head1 AUTHOR AND COPYRIGHT - -This module is Copyright (c) 1997, 1998 - - Jochen Wiedmann - Am Eisteich 9 - 72555 Metzingen - Germany - - Email: joe@ispsoft.de - Phone: +49 7123 14887 - -The DBD::Proxy module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. In particular permission -is granted to Tim Bunce for distributing this as a part of the DBI. - - -=head1 SEE ALSO - -L, L, L - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBD/Sponge.pm b/dbLifeLog/DBI-1.641/lib/DBD/Sponge.pm deleted file mode 100644 index 4bd1bbc..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBD/Sponge.pm +++ /dev/null @@ -1,305 +0,0 @@ -use strict; -{ - package DBD::Sponge; - - require DBI; - require Carp; - - our @EXPORT = qw(); # Do NOT @EXPORT anything. - our $VERSION = "12.010003"; - -# $Id: Sponge.pm 10002 2007-09-26 21:03:25Z Tim $ -# -# Copyright (c) 1994-2003 Tim Bunce Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - - our $drh = undef; # holds driver handle once initialised - my $methods_already_installed; - - sub driver{ - return $drh if $drh; - - DBD::Sponge::db->install_method("sponge_test_installed_method") - unless $methods_already_installed++; - - my($class, $attr) = @_; - $class .= "::dr"; - ($drh) = DBI::_new_drh($class, { - 'Name' => 'Sponge', - 'Version' => $VERSION, - 'Attribution' => "DBD::Sponge $VERSION (fake cursor driver) by Tim Bunce", - }); - $drh; - } - - sub CLONE { - undef $drh; - } -} - - -{ package DBD::Sponge::dr; # ====== DRIVER ====== - our $imp_data_size = 0; - # we use default (dummy) connect method -} - - -{ package DBD::Sponge::db; # ====== DATABASE ====== - our $imp_data_size = 0; - use strict; - - sub prepare { - my($dbh, $statement, $attribs) = @_; - my $rows = delete $attribs->{'rows'} - or return $dbh->set_err($DBI::stderr,"No rows attribute supplied to prepare"); - my ($outer, $sth) = DBI::_new_sth($dbh, { - 'Statement' => $statement, - 'rows' => $rows, - (map { exists $attribs->{$_} ? ($_=>$attribs->{$_}) : () } - qw(execute_hook) - ), - }); - if (my $behave_like = $attribs->{behave_like}) { - $outer->{$_} = $behave_like->{$_} - foreach (qw(RaiseError PrintError HandleError ShowErrorStatement)); - } - - if ($statement =~ /^\s*insert\b/) { # very basic, just for testing execute_array() - $sth->{is_insert} = 1; - my $NUM_OF_PARAMS = $attribs->{NUM_OF_PARAMS} - or return $dbh->set_err($DBI::stderr,"NUM_OF_PARAMS not specified for INSERT statement"); - $sth->STORE('NUM_OF_PARAMS' => $attribs->{NUM_OF_PARAMS} ); - } - else { #assume select - - # we need to set NUM_OF_FIELDS - my $numFields; - if ($attribs->{'NUM_OF_FIELDS'}) { - $numFields = $attribs->{'NUM_OF_FIELDS'}; - } elsif ($attribs->{'NAME'}) { - $numFields = @{$attribs->{NAME}}; - } elsif ($attribs->{'TYPE'}) { - $numFields = @{$attribs->{TYPE}}; - } elsif (my $firstrow = $rows->[0]) { - $numFields = scalar @$firstrow; - } else { - return $dbh->set_err($DBI::stderr, 'Cannot determine NUM_OF_FIELDS'); - } - $sth->STORE('NUM_OF_FIELDS' => $numFields); - $sth->{NAME} = $attribs->{NAME} - || [ map { "col$_" } 1..$numFields ]; - $sth->{TYPE} = $attribs->{TYPE} - || [ (DBI::SQL_VARCHAR()) x $numFields ]; - $sth->{PRECISION} = $attribs->{PRECISION} - || [ map { length($sth->{NAME}->[$_]) } 0..$numFields -1 ]; - $sth->{SCALE} = $attribs->{SCALE} - || [ (0) x $numFields ]; - $sth->{NULLABLE} = $attribs->{NULLABLE} - || [ (2) x $numFields ]; - } - - $outer; - } - - sub type_info_all { - my ($dbh) = @_; - my $ti = [ - { TYPE_NAME => 0, - DATA_TYPE => 1, - PRECISION => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE=> 9, - MONEY => 10, - AUTO_INCREMENT => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - }, - [ 'VARCHAR', DBI::SQL_VARCHAR(), undef, "'","'", undef, 0, 1, 1, 0, 0,0,undef,0,0 ], - ]; - return $ti; - } - - sub FETCH { - my ($dbh, $attrib) = @_; - # In reality this would interrogate the database engine to - # either return dynamic values that cannot be precomputed - # or fetch and cache attribute values too expensive to prefetch. - return 1 if $attrib eq 'AutoCommit'; - # else pass up to DBI to handle - return $dbh->SUPER::FETCH($attrib); - } - - sub STORE { - my ($dbh, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - if ($attrib eq 'AutoCommit') { - return 1 if $value; # is already set - Carp::croak("Can't disable AutoCommit"); - } - return $dbh->SUPER::STORE($attrib, $value); - } - - sub sponge_test_installed_method { - my ($dbh, @args) = @_; - return $dbh->set_err(42, "not enough parameters") unless @args >= 2; - return \@args; - } -} - - -{ package DBD::Sponge::st; # ====== STATEMENT ====== - our $imp_data_size = 0; - use strict; - - sub execute { - my $sth = shift; - - # hack to support ParamValues (when not using bind_param) - $sth->{ParamValues} = (@_) ? { map { $_ => $_[$_-1] } 1..@_ } : undef; - - if (my $hook = $sth->{execute_hook}) { - &$hook($sth, @_) or return; - } - - if ($sth->{is_insert}) { - my $row; - $row = (@_) ? [ @_ ] : die "bind_param not supported yet" ; - my $NUM_OF_PARAMS = $sth->{NUM_OF_PARAMS}; - return $sth->set_err($DBI::stderr, @$row." values bound (@$row) but $NUM_OF_PARAMS expected") - if @$row != $NUM_OF_PARAMS; - { local $^W; $sth->trace_msg("inserting (@$row)\n"); } - push @{ $sth->{rows} }, $row; - } - else { # mark select sth as Active - $sth->STORE(Active => 1); - } - # else do nothing for select as data is already in $sth->{rows} - return 1; - } - - sub fetch { - my ($sth) = @_; - my $row = shift @{$sth->{'rows'}}; - unless ($row) { - $sth->STORE(Active => 0); - return undef; - } - return $sth->_set_fbav($row); - } - *fetchrow_arrayref = \&fetch; - - sub FETCH { - my ($sth, $attrib) = @_; - # would normally validate and only fetch known attributes - # else pass up to DBI to handle - return $sth->SUPER::FETCH($attrib); - } - - sub STORE { - my ($sth, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - return $sth->SUPER::STORE($attrib, $value); - } -} - -1; - -__END__ - -=pod - -=head1 NAME - -DBD::Sponge - Create a DBI statement handle from Perl data - -=head1 SYNOPSIS - - my $sponge = DBI->connect("dbi:Sponge:","","",{ RaiseError => 1 }); - my $sth = $sponge->prepare($statement, { - rows => $data, - NAME => $names, - %attr - } - ); - -=head1 DESCRIPTION - -DBD::Sponge is useful for making a Perl data structure accessible through a -standard DBI statement handle. This may be useful to DBD module authors who -need to transform data in this way. - -=head1 METHODS - -=head2 connect() - - my $sponge = DBI->connect("dbi:Sponge:","","",{ RaiseError => 1 }); - -Here's a sample syntax for creating a database handle for the Sponge driver. -No username and password are needed. - -=head2 prepare() - - my $sth = $sponge->prepare($statement, { - rows => $data, - NAME => $names, - %attr - } - ); - -=over 4 - -=item * - -The C<$statement> here is an arbitrary statement or name you want -to provide as identity of your data. If you're using DBI::Profile -it will appear in the profile data. - -Generally it's expected that you are preparing a statement handle -as if a C -statements (or any other statements that can return many -values from the database using a cursor-like mechanism). See -C above for more explanations. - -There plans for a preparse function to be provided by B, but this has -not reached fruition yet. -Meantime, if you want to know how ugly it can get, try looking at the -C in B F and the related -functions in F and F. - -=head3 The dbd_st_fetch method - -This function fetches a row of data. The row is stored in in an array, -of C's that B prepares for you. This has two advantages: it is fast -(you even reuse the C's, so they don't have to be created after the -first C), and it guarantees that B handles C for -you. - -What you do is the following: - - AV* av; - int numFields = DBIc_NUM_FIELDS(imp_sth); /* Correct, if NUM_FIELDS - is constant for this statement. There are drivers where this is - not the case! */ - int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks); - int i; - - if (!fetch_new_row_of_data(...)) { - ... /* check for error or end-of-data */ - DBIc_ACTIVE_off(imp_sth); /* turn off Active flag automatically */ - return Nullav; - } - /* get the fbav (field buffer array value) for this row */ - /* it is very important to only call this after you know */ - /* that you have a row of data to return. */ - av = DBIc_DBISTATE(imp_sth)->get_fbav(imp_sth); - for (i = 0; i < numFields; i++) { - SV* sv = fetch_a_field(..., i); - if (chopBlanks && SvOK(sv) && type_is_blank_padded(field_type[i])) { - /* Remove white space from end (only) of sv */ - } - sv_setsv(AvARRAY(av)[i], sv); /* Note: (re)use! */ - } - return av; - -There's no need to use a C function returning an C. -It's more common to use your database API functions to fetch the -data as character strings and use code like this: - - sv_setpvn(AvARRAY(av)[i], char_ptr, char_count); - -C values must be returned as C. You can use code like this: - - SvOK_off(AvARRAY(av)[i]); - -The function returns the C prepared by B for success or C -otherwise. - - *FIX ME* Discuss what happens when there's no more data to fetch. - Are errors permitted if another fetch occurs after the first fetch - that reports no more data. (Permitted, not required.) - -If an error occurs which leaves the I<$sth> in a state where remaining -rows can't be fetched then I should be turned off before the -method returns. - -=head3 The dbd_st_finish3 method - -The C<$sth-Efinish()> method can be called if the user wishes to -indicate that no more rows will be fetched even if the database has more -rows to offer, and the B code can call the function when handles are -being destroyed. See the B specification for more background details. - -In both circumstances, the B code ends up calling the -C method (if you provide a mapping for -C in F), or C otherwise. -The difference is that C takes a third argument which -is an C with the value 1 if it is being called from a C -method and 0 otherwise. - -Note that B v1.32 and earlier test on C to call -C; if you provide C, either define -C too, or insist on B v1.33 or later. - -All it I to do is turn off the I flag for the I. -It will only be called by F code, if the driver has set I -to on for the I. - -Outline example: - - int dbd_st_finish3(SV* sth, imp_sth_t* imp_sth, int from_destroy) { - if (DBIc_ACTIVE(imp_sth)) - { - /* close cursor or equivalent action */ - DBIc_ACTIVE_off(imp_sth); - } - return 1; - } - -The from_destroy parameter is true if C is being called -from C - and so the statement is about to be destroyed. -For many drivers there is no point in doing anything more than turning off -the I flag in this case. - -The function returns I for success, I otherwise, but there isn't -a lot anyone can do to recover if there is an error. - -=head3 The dbd_st_destroy method - -This function is the private part of the statement handle destructor. - - void dbd_st_destroy(SV* sth, imp_sth_t* imp_sth) { - ... /* any clean-up that's needed */ - DBIc_IMPSET_off(imp_sth); /* let DBI know we've done it */ - } - -The B F code will call C for you, if the -I has the I flag set, before calling C. - -=head3 The dbd_st_STORE_attrib and dbd_st_FETCH_attrib methods - -These functions correspond to C and C attrib -above, except that they are for statement handles. -See above. - - int dbd_st_STORE_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv, - SV* valuesv); - SV* dbd_st_FETCH_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv); - -=head3 The dbd_bind_ph method - -This function is internally used by the C method, the -C method and by the B F code if -C is called with any bind parameters. - - int dbd_bind_ph (SV *sth, imp_sth_t *imp_sth, SV *param, - SV *value, IV sql_type, SV *attribs, - int is_inout, IV maxlen); - -The I argument holds an C with the parameter number (1, 2, ...). -The I argument is the parameter value and I is its type. - -If your driver does not support C then you should -ignore I and croak if I is I. - -If your driver I support C then you should -note that I is the C I dereferencing the reference -passed to C. - -In drivers of simple databases the function will, for example, store -the value in a parameter array and use it later in C. -See the B driver for an example. - -=head3 Implementing bind_param_inout support - -To provide support for parameters bound by reference rather than by -value, the driver must do a number of things. First, and most -importantly, it must note the references and stash them in its own -driver structure. Secondly, when a value is bound to a column, the -driver must discard any previous reference bound to the column. On -each execute, the driver must evaluate the references and internally -bind the values resulting from the references. This is only applicable -if the user writes: - - $sth->execute; - -If the user writes: - - $sth->execute(@values); - -then B automatically calls the binding code for each element of -I<@values>. These calls are indistinguishable from explicit user calls to -C. - -=head2 C/XS version of Makefile.PL - -The F file for a C/XS driver is similar to the code needed -for a pure Perl driver, but there are a number of extra bits of -information needed by the build system. - -For example, the attributes list passed to C needs -to specify the object files that need to be compiled and built into -the shared object (DLL). This is often, but not necessarily, just -F (unless that should be F because you're building -on MS Windows). - -Note that you can reliably determine the extension of the object files -from the I<$Config{obj_ext}> values, and there are many other useful pieces -of configuration information lurking in that hash. -You get access to it with: - - use Config; - -=head2 Methods which do not need to be written - -The B code implements the majority of the methods which are accessed -using the notation Cfunction()>, the only exceptions being -Cconnect()> and Cdata_sources()> which require -support from the driver. - -The B code implements the following documented driver, database and -statement functions which do not need to be written by the B driver -writer. - -=over 4 - -=item $dbh->do() - -The default implementation of this function prepares, executes and -destroys the statement. This can be replaced if there is a better -way to implement this, such as C which can -sometimes be used if there are no parameters. - -=item $h->errstr() - -=item $h->err() - -=item $h->state() - -=item $h->trace() - -The B driver does not need to worry about these routines at all. - -=item $h->{ChopBlanks} - -This attribute needs to be honored during C operations, but does -not need to be handled by the attribute handling code. - -=item $h->{RaiseError} - -The B driver does not need to worry about this attribute at all. - -=item $h->{PrintError} - -The B driver does not need to worry about this attribute at all. - -=item $sth->bind_col() - -Assuming the driver uses the Cget_fbav()> -function (C drivers, see below), or the C<$sth-E_set_fbav($data)> -method (Perl drivers) the driver does not need to do anything about this -routine. - -=item $sth->bind_columns() - -Regardless of whether the driver uses -Cget_fbav()>, the driver does not need -to do anything about this routine as it simply iteratively calls -C<$sth-Ebind_col()>. - -=back - -The B code implements a default implementation of the following -functions which do not need to be written by the B driver writer -unless the default implementation is incorrect for the Driver. - -=over 4 - -=item $dbh->quote() - -This should only be written if the database does not accept the ANSI -SQL standard for quoting strings, with the string enclosed in single -quotes and any embedded single quotes replaced by two consecutive -single quotes. - -For the two argument form of quote, you need to implement the -C method to provide the information that quote needs. - -=item $dbh->ping() - -This should be implemented as a simple efficient way to determine -whether the connection to the database is still alive. Typically -code like this: - - sub ping { - my $dbh = shift; - $sth = $dbh->prepare_cached(q{ - select * from A_TABLE_NAME where 1=0 - }) or return 0; - $sth->execute or return 0; - $sth->finish; - return 1; - } - -where I is the name of a table that always exists (such as a -database system catalogue). - -=item $drh->default_user - -The default implementation of default_user will get the database -username and password fields from C<$ENV{DBI_USER}> and -C<$ENV{DBI_PASS}>. You can override this method. It is called as -follows: - - ($user, $pass) = $drh->default_user($user, $pass, $attr) - -=back - -=head1 METADATA METHODS - -The exposition above ignores the B MetaData methods. -The metadata methods are all associated with a database handle. - -=head2 Using DBI::DBD::Metadata - -The B module is a good semi-automatic way for the -developer of a B module to write the C and C -functions quickly and accurately. - -=head3 Generating the get_info method - -Prior to B v1.33, this existed as the method C -in the B module. From B v1.33, it exists as the method -C in the B module. This -discussion assumes you have B v1.33 or later. - -You examine the documentation for C using: - - perldoc DBI::DBD::Metadata - -To use it, you need a Perl B driver for your database which implements -the C method. In practice, this means you need to install -B, an ODBC driver manager, and an ODBC driver for your -database. - -With the pre-requisites in place, you might type: - - perl -MDBI::DBD::Metadata -we \ - "write_getinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })" - -The procedure writes to standard output the code that should be added to -your F file and the code that should be written to -F. - -You should review the output to ensure that it is sensible. - -=head3 Generating the type_info method - -Given the idea of the C method, it was not hard -to devise a parallel method, C, which does the -analogous job for the B C metadata method. The -C method was added to B v1.33. - -You examine the documentation for C using: - - perldoc DBI::DBD::Metadata - -The setup is exactly analogous to the mechanism described in -L. - -With the pre-requisites in place, you might type: - - perl -MDBI::DBD::Metadata -we \ - "write_typeinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })" - -The procedure writes to standard output the code that should be added to -your F file and the code that should be written to -F. - -You should review the output to ensure that it is sensible. - -=head2 Writing DBD::Driver::db::get_info - -If you use the B module, then the code you need is -generated for you. - -If you decide not to use the B module, you -should probably borrow the code from a driver that has done so (eg -B from version 1.05 onwards) and crib the code from -there, or look at the code that generates that module and follow -that. The method in F will be very simple; the method in -F is not very much more complex unless your -DBMS itself is much more complex. - -Note that some of the B utility methods rely on information from the -C method to perform their operations correctly. See, for -example, the C and quote methods, discussed below. - -=head2 Writing DBD::Driver::db::type_info_all - -If you use the C module, then the code you need is -generated for you. - -If you decide not to use the C module, you -should probably borrow the code from a driver that has done so (eg -C from version 1.05 onwards) and crib the code from -there, or look at the code that generates that module and follow -that. The method in F will be very simple; the method in -F is not very much more complex unless your -DBMS itself is much more complex. - -=head2 Writing DBD::Driver::db::type_info - -The guidelines on writing this method are still not really clear. -No sample implementation is available. - -=head2 Writing DBD::Driver::db::table_info - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::column_info - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::primary_key_info - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::primary_key - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::foreign_key_info - - *FIX ME* The guidelines on writing this method have not been written yet. - No sample implementation is available. - -=head2 Writing DBD::Driver::db::tables - -This method generates an array of names in a format suitable for being -embedded in SQL statements in places where a table name is expected. - -If your database hews close enough to the SQL standard or if you have -implemented an appropriate C function and and the appropriate -C function, then the B default version of this method -will work for your driver too. - -Otherwise, you have to write a function yourself, such as: - - sub tables - { - my($dbh, $cat, $sch, $tab, $typ) = @_; - my(@res); - my($sth) = $dbh->table_info($cat, $sch, $tab, $typ); - my(@arr); - while (@arr = $sth->fetchrow_array) - { - push @res, $dbh->quote_identifier($arr[0], $arr[1], $arr[2]); - } - return @res; - } - -See also the default implementation in F. - -=head2 Writing DBD::Driver::db::quote - -This method takes a value and converts it into a string suitable for -embedding in an SQL statement as a string literal. - -If your DBMS accepts the SQL standard notation for strings (single -quotes around the string as a whole with any embedded single quotes -doubled up), then you do not need to write this method as B provides a -default method that does it for you. - -If your DBMS uses an alternative notation or escape mechanism, then you -need to provide an equivalent function. For example, suppose your DBMS -used C notation with double quotes around the string and backslashes -escaping both double quotes and backslashes themselves. Then you might -write the function as: - - sub quote - { - my($dbh, $str) = @_; - $str =~ s/["\\]/\\$&/gmo; - return qq{"$str"}; - } - -Handling newlines and other control characters is left as an exercise -for the reader. - -This sample method ignores the I<$data_type> indicator which is the -optional second argument to the method. - -=head2 Writing DBD::Driver::db::quote_identifier - -This method is called to ensure that the name of the given table (or -other database object) can be embedded into an SQL statement without -danger of misinterpretation. The result string should be usable in the -text of an SQL statement as the identifier for a table. - -If your DBMS accepts the SQL standard notation for quoted identifiers -(which uses double quotes around the identifier as a whole, with any -embedded double quotes doubled up) and accepts I<"schema"."identifier"> -(and I<"catalog"."schema"."identifier"> when a catalog is specified), then -you do not need to write this method as B provides a default method -that does it for you. - -In fact, even if your DBMS does not handle exactly that notation but -you have implemented the C method and it gives the correct -responses, then it will work for you. If your database is fussier, then -you need to implement your own version of the function. - -For example, B has to deal with an environment variable -I. If it is not set, then the DBMS treats names enclosed in -double quotes as strings rather than names, which is usually a syntax -error. Additionally, the catalog portion of the name is separated from -the schema and table by a different delimiter (colon instead of dot), -and the catalog portion is never enclosed in quotes. (Fortunately, -valid strings for the catalog will never contain weird characters that -might need to be escaped, unless you count dots, dashes, slashes and -at-signs as weird.) Finally, an Informix database can contain objects -that cannot be accessed because they were created by a user with the -I environment variable set, but the current user does not -have it set. By design choice, the C method encloses -those identifiers in double quotes anyway, which generally triggers a -syntax error, and the metadata methods which generate lists of tables -etc omit those identifiers from the result sets. - - sub quote_identifier - { - my($dbh, $cat, $sch, $obj) = @_; - my($rv) = ""; - my($qq) = (defined $ENV{DELIMIDENT}) ? '"' : ''; - $rv .= qq{$cat:} if (defined $cat); - if (defined $sch) - { - if ($sch !~ m/^\w+$/o) - { - $qq = '"'; - $sch =~ s/$qq/$qq$qq/gm; - } - $rv .= qq{$qq$sch$qq.}; - } - if (defined $obj) - { - if ($obj !~ m/^\w+$/o) - { - $qq = '"'; - $obj =~ s/$qq/$qq$qq/gm; - } - $rv .= qq{$qq$obj$qq}; - } - return $rv; - } - -Handling newlines and other control characters is left as an exercise -for the reader. - -Note that there is an optional fourth parameter to this function which -is a reference to a hash of attributes; this sample implementation -ignores that. - -This sample implementation also ignores the single-argument variant of -the method. - -=head1 TRACING - -Tracing in DBI is controlled with a combination of a trace level and a -set of flags which together are known as the trace settings. The trace -settings are stored in a single integer and divided into levels and -flags by a set of masks (C and -C). - -Each handle has it's own trace settings and so does the DBI. When you -call a method the DBI merges the handles settings into its own for the -duration of the call: the trace flags of the handle are OR'd into the -trace flags of the DBI, and if the handle has a higher trace level -then the DBI trace level is raised to match it. The previous DBI trace -settings are restored when the called method returns. - -=head2 Trace Level - -The trace level is the first 4 bits of the trace settings (masked by -C) and represents trace levels of 1 to 15. Do -not output anything at trace levels less than 3 as they are reserved -for DBI. - -For advice on what to output at each level see "Trace Levels" in -L. - -To test for a trace level you can use the C macro -like this: - - if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) { - PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar"); - } - -Also B the use of PerlIO_printf which you should always use for -tracing and never the C C I/O functions. - -=head2 Trace Flags - -Trace flags are used to enable tracing of specific activities within -the DBI and drivers. The DBI defines some trace flags and drivers can -define others. DBI trace flag names begin with a capital letter and -driver specific names begin with a lowercase letter. For a list of DBI -defined trace flags see "Trace Flags" in L. - -If you want to use private trace flags you'll probably want to be able -to set them by name. Drivers are expected to override the -parse_trace_flag (note the singular) and check if $trace_flag_name is -a driver specific trace flags and, if not, then call the DBIs default -parse_trace_flag(). To do that you'll need to define a -parse_trace_flag() method like this: - - sub parse_trace_flag { - my ($h, $name) = @_; - return 0x01000000 if $name eq 'foo'; - return 0x02000000 if $name eq 'bar'; - return 0x04000000 if $name eq 'baz'; - return 0x08000000 if $name eq 'boo'; - return 0x10000000 if $name eq 'bop'; - return $h->SUPER::parse_trace_flag($name); - } - -All private flag names must be lowercase, and all private flags must -be in the top 8 of the 32 bits of C i.e., -0xFF000000. - -If you've defined a parse_trace_flag() method in ::db you'll also want -it in ::st, so just alias it in: - - *parse_trace_flag = \&DBD::foo:db::parse_trace_flag; - -You may want to act on the current 'SQL' trace flag that DBI defines -to output SQL prepared/executed as DBI currently does not do SQL -tracing. - -=head2 Trace Macros - -Access to the trace level and trace flags is via a set of macros. - - DBIc_TRACE_SETTINGS(imp) returns the trace settings - DBIc_TRACE_LEVEL(imp) returns the trace level - DBIc_TRACE_FLAGS(imp) returns the trace flags - DBIc_TRACE(imp, flags, flaglevel, level) - - e.g., - - DBIc_TRACE(imp, 0, 0, 4) - if level >= 4 - - DBIc_TRACE(imp, DBDtf_FOO, 2, 4) - if tracing DBDtf_FOO & level>=2 or level>=4 - - DBIc_TRACE(imp, DBDtf_FOO, 2, 0) - as above but never trace just due to level - -=head1 WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE - -Study F (supplied with B) and F (supplied -with B) and the corresponding I files for ideas. - -Note that the emulation code sets C<$dbh-E{CompatMode} = 1;> for each -connection so that the internals of the driver can implement behaviour -compatible with the old interface when dealing with those handles. - -=head2 Setting emulation perl variables - -For example, ingperl has a I<$sql_rowcount> variable. Rather than try -to manually update this in F it can be done faster in C code. -In C: - - sql_rowcount = perl_get_sv("Ingperl::sql_rowcount", GV_ADDMULTI); - -In the relevant places do: - - if (DBIc_COMPAT(imp_sth)) /* only do this for compatibility mode handles */ - sv_setiv(sql_rowcount, the_row_count); - -=head1 OTHER MISCELLANEOUS INFORMATION - -=head2 The imp_xyz_t types - -Any handle has a corresponding C structure filled with private data. -Some of this data is reserved for use by B (except for using the -DBIc macros below), some is for you. See the description of the -F file above for examples. Most functions in F -are passed both the handle C and a pointer to C. In -rare cases, however, you may use the following macros: - -=over 4 - -=item D_imp_dbh(dbh) - -Given a function argument I, declare a variable I and -initialize it with a pointer to the handles private data. Note: This -must be a part of the function header, because it declares a variable. - -=item D_imp_sth(sth) - -Likewise for statement handles. - -=item D_imp_xxx(h) - -Given any handle, declare a variable I and initialize it -with a pointer to the handles private data. It is safe, for example, -to cast I to C, if C. -(You can also call C, but that's much -slower.) - -=item D_imp_dbh_from_sth - -Given a I, declare a variable I and initialize it with a -pointer to the parent database handle's implementors structure. - -=back - -=head2 Using DBIc_IMPSET_on - -The driver code which initializes a handle should use C -as soon as its state is such that the cleanup code must be called. -When this happens is determined by your driver code. - -B - -For example, B maintains a linked list of database -handles in the driver, and within each handle, a linked list of -statements. Once a statement is added to the linked list, it is crucial -that it is cleaned up (removed from the list). When I -was being called too late, it was able to cause all sorts of problems. - -=head2 Using DBIc_is(), DBIc_has(), DBIc_on() and DBIc_off() - -Once upon a long time ago, the only way of handling the internal B -boolean flags/attributes was through macros such as: - - DBIc_WARN DBIc_WARN_on DBIc_WARN_off - DBIc_COMPAT DBIc_COMPAT_on DBIc_COMPAT_off - -Each of these took an I pointer as an argument. - -Since then, new attributes have been added such as I, -I and I, and these do not have the full set of -macros. The approved method for handling these is now the four macros: - - DBIc_is(imp, flag) - DBIc_has(imp, flag) an alias for DBIc_is - DBIc_on(imp, flag) - DBIc_off(imp, flag) - DBIc_set(imp, flag, on) set if on is true, else clear - -Consequently, the C family of macros is now mostly deprecated -and new drivers should avoid using them, even though the older drivers -will probably continue to do so for quite a while yet. However... - -There is an I to that. The I and I -flags should be set via the C and C macros, -and unset via the C and C macros. - -=head2 Using the get_fbav() method - -B. - -The C<$sth-Ebind_col()> and C<$sth-Ebind_columns()> documented -in the B specification do not have to be implemented by the driver -writer because B takes care of the details for you. - -However, the key to ensuring that bound columns work is to call the -function Cget_fbav()> in the code which -fetches a row of data. - -This returns an C, and each element of the C contains the C which -should be set to contain the returned data. - -The pure Perl equivalent is the C<$sth-E_set_fbav($data)> method, as -described in the part on pure Perl drivers. - -=head2 Casting strings to Perl types based on a SQL type - -DBI from 1.611 (and DBIXS_REVISION 13606) defines the -sql_type_cast_svpv method which may be used to cast a string -representation of a value to a more specific Perl type based on a SQL -type. You should consider using this method when processing bound -column data as it provides some support for the TYPE bind_col -attribute which is rarely used in drivers. - - int sql_type_cast_svpv(pTHX_ SV *sv, int sql_type, U32 flags, void *v) - -C is what you would like cast, C is one of the DBI defined -SQL types (e.g., C) and C is a bitmask as follows: - -=over - -=item DBIstcf_STRICT - -If set this indicates you want an error state returned if the cast -cannot be performed. - -=item DBIstcf_DISCARD_STRING - -If set and the pv portion of the C is cast then this will cause -sv's pv to be freed up. - -=back - -sql_type_cast_svpv returns the following states: - - -2 sql_type is not handled - sv not changed - -1 sv is undef, sv not changed - 0 sv could not be cast cleanly and DBIstcf_STRICT was specified - 1 sv could not be case cleanly and DBIstcf_STRICT was not specified - 2 sv was cast ok - -The current implementation of sql_type_cast_svpv supports -C, C and C. C uses -sv_2iv and hence may set IV, UV or NV depending on the -number. C uses sv_2nv so may set NV and C -will set IV or UV or NV. - -DBIstcf_STRICT should be implemented as the StrictlyTyped attribute -and DBIstcf_DISCARD_STRING implemented as the DiscardString attribute -to the bind_col method and both default to off. - -See DBD::Oracle for an example of how this is used. - -=head1 SUBCLASSING DBI DRIVERS - -This is definitely an open subject. It can be done, as demonstrated by -the B driver, but it is not as simple as one might think. - -(Note that this topic is different from subclassing the B. For an -example of that, see the F file supplied with the B.) - -The main problem is that the I's and I's that your C and -C methods return are not instances of your B -or B packages, they are not even derived from it. -Instead they are instances of the B or B classes or -a derived subclass. Thus, if you write a method C and do a - - $dbh->mymethod() - -then the autoloader will search for that method in the package B. -Of course you can instead to a - - $dbh->func('mymethod') - -and that will indeed work, even if C is inherited, but not -without additional work. Setting I<@ISA> is not sufficient. - -=head2 Overwriting methods - -The first problem is, that the C method has no idea of -subclasses. For example, you cannot implement base class and subclass -in the same file: The C method wants to do a - - require DBD::Driver; - -In particular, your subclass B to be a separate driver, from -the view of B, and you cannot share driver handles. - -Of course that's not much of a problem. You should even be able -to inherit the base classes C method. But you cannot -simply overwrite the method, unless you do something like this, -quoted from B: - - sub connect ($$;$$$) { - my ($drh, $dbname, $user, $auth, $attr) = @_; - - my $this = $drh->DBD::File::dr::connect($dbname, $user, $auth, $attr); - if (!exists($this->{csv_tables})) { - $this->{csv_tables} = {}; - } - - $this; - } - -Note that we cannot do a - - $drh->SUPER::connect($dbname, $user, $auth, $attr); - -as we would usually do in a an OO environment, because I<$drh> is an instance -of B. And note, that the C method of B is -able to handle subclass attributes. See the description of Pure Perl -drivers above. - -It is essential that you always call superclass method in the above -manner. However, that should do. - -=head2 Attribute handling - -Fortunately the B specifications allow a simple, but still -performant way of handling attributes. The idea is based on the -convention that any driver uses a prefix I for its private -methods. Thus it's always clear whether to pass attributes to the super -class or not. For example, consider this C method from the -B class: - - sub STORE { - my ($dbh, $attr, $val) = @_; - if ($attr !~ /^driver_/) { - return $dbh->DBD::File::db::STORE($attr, $val); - } - if ($attr eq 'driver_foo') { - ... - } - -=cut - -use Exporter (); -use Config qw(%Config); -use Carp; -use Cwd; -use File::Spec; -use strict; -use vars qw( - @ISA @EXPORT - $is_dbi -); - -BEGIN { - if ($^O eq 'VMS') { - require vmsish; - import vmsish; - require VMS::Filespec; - import VMS::Filespec; - } - else { - *vmsify = sub { return $_[0] }; - *unixify = sub { return $_[0] }; - } -} - -@ISA = qw(Exporter); - -@EXPORT = qw( - dbd_dbi_dir - dbd_dbi_arch_dir - dbd_edit_mm_attribs - dbd_postamble -); - -BEGIN { - $is_dbi = (-r 'DBI.pm' && -r 'DBI.xs' && -r 'DBIXS.h'); - require DBI unless $is_dbi; -} - -my $done_inst_checks; - -sub _inst_checks { - return if $done_inst_checks++; - my $cwd = cwd(); - if ($cwd =~ /\Q$Config{path_sep}/) { - warn "*** Warning: Path separator characters (`$Config{path_sep}') ", - "in the current directory path ($cwd) may cause problems\a\n\n"; - sleep 2; - } - if ($cwd =~ /\s/) { - warn "*** Warning: whitespace characters ", - "in the current directory path ($cwd) may cause problems\a\n\n"; - sleep 2; - } - if ( $^O eq 'MSWin32' - && $Config{cc} eq 'cl' - && !(exists $ENV{'LIB'} && exists $ENV{'INCLUDE'})) - { - die < { name => "DBI::PurePerl", - match => qr/^\d/, - add => [ '$ENV{DBI_PUREPERL} = 2', - 'END { delete $ENV{DBI_PUREPERL}; }' ], - }, - g => { name => "DBD::Gofer", - match => qr/^\d/, - add => [ q{$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'}, - q|END { delete $ENV{DBI_AUTOPROXY}; }| ], - }, - n => { name => "DBI::SQL::Nano", - match => qr/^(?:48dbi_dbd_sqlengine|49dbd_file|5\ddbm_\w+|85gofer)\.t$/, - add => [ q{$ENV{DBI_SQL_NANO} = 1}, - q|END { delete $ENV{DBI_SQL_NANO}; }| ], - }, - # mx => { name => "DBD::Multiplex", - # add => [ q{local $ENV{DBI_AUTOPROXY} = 'dbi:Multiplex:';} ], - # } - # px => { name => "DBD::Proxy", - # need mechanism for starting/stopping the proxy server - # add => [ q{local $ENV{DBI_AUTOPROXY} = 'dbi:Proxy:XXX';} ], - # } - ); - - # decide what needs doing - $dbd_attr->{create_pp_tests} or delete $test_variants{p}; - $dbd_attr->{create_nano_tests} or delete $test_variants{n}; - $dbd_attr->{create_gap_tests} or delete $test_variants{g}; - - # expand for all combinations - my @all_keys = my @tv_keys = sort keys %test_variants; - while( @tv_keys ) { - my $cur_key = shift @tv_keys; - last if( 1 < length $cur_key ); - my @new_keys; - foreach my $remain (@tv_keys) { - push @new_keys, $cur_key . $remain unless $remain =~ /$cur_key/; - } - push @tv_keys, @new_keys; - push @all_keys, @new_keys; - } - - my %uniq_keys; - foreach my $key (@all_keys) { - @tv_keys = sort split //, $key; - my $ordered = join( '', @tv_keys ); - $uniq_keys{$ordered} = 1; - } - @all_keys = sort { length $a <=> length $b or $a cmp $b } keys %uniq_keys; - - # do whatever needs doing - if( keys %test_variants ) { - # XXX need to convert this to work within the generated Makefile - # so 'make' creates them and 'make clean' deletes them - opendir DIR, 't' or die "Can't read 't' directory: $!"; - my @tests = grep { /\.t$/ } readdir DIR; - closedir DIR; - - foreach my $test_combo (@all_keys) { - @tv_keys = split //, $test_combo; - my @test_names = map { $test_variants{$_}->{name} } @tv_keys; - printf "Creating test wrappers for " . join( " + ", @test_names ) . ":\n"; - my @test_matches = map { $test_variants{$_}->{match} } @tv_keys; - my @test_adds; - foreach my $test_add ( map { $test_variants{$_}->{add} } @tv_keys) { - push @test_adds, @$test_add; - } - my $v_type = $test_combo; - $v_type = 'x' . $v_type if length( $v_type ) > 1; - - TEST: - foreach my $test (sort @tests) { - foreach my $match (@test_matches) { - next TEST if $test !~ $match; - } - my $usethr = ($test =~ /(\d+|\b)thr/ && $] >= 5.008 && $Config{useithreads}); - my $v_test = "t/zv${v_type}_$test"; - my $v_perl = ($test =~ /taint/) ? "perl -wT" : "perl -w"; - printf "%s %s\n", $v_test, ($usethr) ? "(use threads)" : ""; - open PPT, ">$v_test" or warn "Can't create $v_test: $!"; - print PPT "#!$v_perl\n"; - print PPT "use threads;\n" if $usethr; - print PPT "$_;\n" foreach @test_adds; - print PPT "require './t/$test'; # or warn \$!;\n"; - close PPT or warn "Error writing $v_test: $!"; - } - } - } - return %$mm_attr; -} - -sub dbd_dbi_dir { - _inst_checks(); - return '.' if $is_dbi; - my $dbidir = $INC{'DBI.pm'} || die "DBI.pm not in %INC!"; - $dbidir =~ s:/DBI\.pm$::; - return $dbidir; -} - -sub dbd_dbi_arch_dir { - _inst_checks(); - return '$(INST_ARCHAUTODIR)' if $is_dbi; - my $dbidir = dbd_dbi_dir(); - my %seen; - my @try = grep { not $seen{$_}++ } map { vmsify( unixify($_) . "/auto/DBI/" ) } @INC; - my @xst = grep { -f vmsify( unixify($_) . "/Driver.xst" ) } @try; - Carp::croak("Unable to locate Driver.xst in @try") unless @xst; - Carp::carp( "Multiple copies of Driver.xst found in: @xst") if @xst > 1; - print "Using DBI $DBI::VERSION (for perl $] on $Config{archname}) installed in $xst[0]\n"; - return File::Spec->canonpath($xst[0]); -} - -sub dbd_postamble { - my $self = shift; - _inst_checks(); - my $dbi_instarch_dir = ($is_dbi) ? "." : dbd_dbi_arch_dir(); - my $dbi_driver_xst= File::Spec->catfile($dbi_instarch_dir, 'Driver.xst'); - my $xstf_h = File::Spec->catfile($dbi_instarch_dir, 'Driver_xst.h'); - - # we must be careful of quotes, especially for Win32 here. - return ' -# --- This section was generated by DBI::DBD::dbd_postamble() -DBI_INSTARCH_DIR='.$dbi_instarch_dir.' -DBI_DRIVER_XST='.$dbi_driver_xst.' - -# The main dependency (technically correct but probably not used) -$(BASEEXT).c: $(BASEEXT).xsi - -# This dependency is needed since MakeMaker uses the .xs.o rule -$(BASEEXT)$(OBJ_EXT): $(BASEEXT).xsi - -$(BASEEXT).xsi: $(DBI_DRIVER_XST) '.$xstf_h.' - $(PERL) -p -e "s/~DRIVER~/$(BASEEXT)/g" $(DBI_DRIVER_XST) > $(BASEEXT).xsi - -# --- -'; -} - -package DBDI; # just to reserve it via PAUSE for the future - -1; - -__END__ - -=head1 AUTHORS - -Jonathan Leffler (previously ), -Jochen Wiedmann , -Steffen Goeldner , -and Tim Bunce . - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/DBD/Metadata.pm b/dbLifeLog/DBI-1.641/lib/DBI/DBD/Metadata.pm deleted file mode 100644 index eec95f0..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/DBD/Metadata.pm +++ /dev/null @@ -1,492 +0,0 @@ -package DBI::DBD::Metadata; - -# $Id: Metadata.pm 14213 2010-06-30 19:29:18Z Martin $ -# -# Copyright (c) 1997-2003 Jonathan Leffler, Jochen Wiedmann, -# Steffen Goeldner and Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; - -use Exporter (); -use Carp; - -use DBI; -use DBI::Const::GetInfoType qw(%GetInfoType); - -our @ISA = qw(Exporter); -our @EXPORT = qw(write_getinfo_pm write_typeinfo_pm); - -our $VERSION = "2.014214"; - - -=head1 NAME - -DBI::DBD::Metadata - Generate the code and data for some DBI metadata methods - -=head1 SYNOPSIS - -The idea is to extract metadata information from a good quality -ODBC driver and use it to generate code and data to use in your own -DBI driver for the same database. - -To generate code to support the get_info method: - - perl -MDBI::DBD::Metadata -e "write_getinfo_pm('dbi:ODBC:dsn-name','user','pass','Driver')" - - perl -MDBI::DBD::Metadata -e write_getinfo_pm dbi:ODBC:foo_db username password Driver - -To generate code to support the type_info method: - - perl -MDBI::DBD::Metadata -e "write_typeinfo_pm('dbi:ODBC:dsn-name','user','pass','Driver')" - - perl -MDBI::DBD::Metadata -e write_typeinfo_pm dbi:ODBC:dsn-name user pass Driver - -Where C is the connection to use to extract the -data, and C is the name of the driver you want the code -generated for (the driver name gets embedded into the output in -numerous places). - -=head1 Generating a GetInfo package for a driver - -The C in the DBI::DBD::Metadata module generates a -DBD::Driver::GetInfo package on standard output. - -This method generates a DBD::Driver::GetInfo package from the data -source you specified in the parameter list or in the environment -variable DBI_DSN. -DBD::Driver::GetInfo should help a DBD author implement the DBI -get_info() method. -Because you are just creating this package, it is very unlikely that -DBD::Driver already provides a good implementation for get_info(). -Thus you will probably connect via DBD::ODBC. - -Once you are sure that it is producing reasonably sane data, you should -typically redirect the standard output to lib/DBD/Driver/GetInfo.pm, and -then hand edit the result. -Do not forget to update your Makefile.PL and MANIFEST to include this as -an extra PM file that should be installed. - -If you connect via DBD::ODBC, you should use version 0.38 or greater; - -Please take a critical look at the data returned! -ODBC drivers vary dramatically in their quality. - -The generator assumes that most values are static and places these -values directly in the %info hash. -A few examples show the use of CODE references and the implementation -via subroutines. -It is very likely that you will have to write additional subroutines for -values depending on the session state or server version, e.g. -SQL_DBMS_VER. - -A possible implementation of DBD::Driver::db::get_info() may look like: - - sub get_info { - my($dbh, $info_type) = @_; - require DBD::Driver::GetInfo; - my $v = $DBD::Driver::GetInfo::info{int($info_type)}; - $v = $v->($dbh) if ref $v eq 'CODE'; - return $v; - } - -Please replace Driver (or "") with the name of your driver. -Note that this stub function is generated for you by write_getinfo_pm -function, but you must manually transfer the code to Driver.pm. - -=cut - -sub write_getinfo_pm -{ - my ($dsn, $user, $pass, $driver) = @_ ? @_ : @ARGV; - my $dbh = DBI->connect($dsn, $user, $pass, {RaiseError=>1}); - $driver = "" unless defined $driver; - - print <(\$dbh) if ref \$v eq 'CODE'; - return \$v; - } - -# Transfer this to lib/DBD/${driver}/GetInfo.pm - -# The \%info hash was automatically generated by -# DBI::DBD::Metadata::write_getinfo_pm v$DBI::DBD::Metadata::VERSION. - -package DBD::${driver}::GetInfo; - -use strict; -use DBD::${driver}; - -# Beware: not officially documented interfaces... -# use DBI::Const::GetInfoType qw(\%GetInfoType); -# use DBI::Const::GetInfoReturn qw(\%GetInfoReturnTypes \%GetInfoReturnValues); - -my \$sql_driver = '${driver}'; -my \$sql_ver_fmt = '%02d.%02d.%04d'; # ODBC version string: ##.##.##### -my \$sql_driver_ver = sprintf \$sql_ver_fmt, split (/\\./, \$DBD::${driver}::VERSION); -PERL - -my $kw_map = 0; -{ -# Informix CLI (ODBC) v3.81.0000 does not return a list of keywords. - local $\ = "\n"; - local $, = "\n"; - my ($kw) = $dbh->get_info($GetInfoType{SQL_KEYWORDS}); - if ($kw) - { - print "\nmy \@Keywords = qw(\n"; - print sort split /,/, $kw; - print ");\n\n"; - print "sub sql_keywords {\n"; - print q% return join ',', @Keywords;%; - print "\n}\n\n"; - $kw_map = 1; - } -} - - print <<'PERL'; - -sub sql_data_source_name { - my $dbh = shift; - return "dbi:$sql_driver:" . $dbh->{Name}; -} - -sub sql_user_name { - my $dbh = shift; - # CURRENT_USER is a non-standard attribute, probably undef - # Username is a standard DBI attribute - return $dbh->{CURRENT_USER} || $dbh->{Username}; -} - -PERL - - print "\nour \%info = (\n"; - foreach my $key (sort keys %GetInfoType) - { - my $num = $GetInfoType{$key}; - my $val = eval { $dbh->get_info($num); }; - if ($key eq 'SQL_DATA_SOURCE_NAME') { - $val = '\&sql_data_source_name'; - } - elsif ($key eq 'SQL_KEYWORDS') { - $val = ($kw_map) ? '\&sql_keywords' : 'undef'; - } - elsif ($key eq 'SQL_DRIVER_NAME') { - $val = "\$INC{'DBD/$driver.pm'}"; - } - elsif ($key eq 'SQL_DRIVER_VER') { - $val = '$sql_driver_ver'; - } - elsif ($key eq 'SQL_USER_NAME') { - $val = '\&sql_user_name'; - } - elsif (not defined $val) { - $val = 'undef'; - } - elsif ($val eq '') { - $val = "''"; - } - elsif ($val =~ /\D/) { - $val =~ s/\\/\\\\/g; - $val =~ s/'/\\'/g; - $val = "'$val'"; - } - printf "%s %5d => %-30s # %s\n", (($val eq 'undef') ? '#' : ' '), $num, "$val,", $key; - } - print ");\n\n1;\n\n__END__\n"; -} - - - -=head1 Generating a TypeInfo package for a driver - -The C function in the DBI::DBD::Metadata module generates -on standard output the data needed for a driver's type_info_all method. -It also provides default implementations of the type_info_all -method for inclusion in the driver's main implementation file. - -The driver parameter is the name of the driver for which the methods -will be generated; for the sake of examples, this will be "Driver". -Typically, the dsn parameter will be of the form "dbi:ODBC:odbc_dsn", -where the odbc_dsn is a DSN for one of the driver's databases. -The user and pass parameters are the other optional connection -parameters that will be provided to the DBI connect method. - -Once you are sure that it is producing reasonably sane data, you should -typically redirect the standard output to lib/DBD/Driver/TypeInfo.pm, -and then hand edit the result if necessary. -Do not forget to update your Makefile.PL and MANIFEST to include this as -an extra PM file that should be installed. - -Please take a critical look at the data returned! -ODBC drivers vary dramatically in their quality. - -The generator assumes that all the values are static and places these -values directly in the %info hash. - -A possible implementation of DBD::Driver::type_info_all() may look like: - - sub type_info_all { - my ($dbh) = @_; - require DBD::Driver::TypeInfo; - return [ @$DBD::Driver::TypeInfo::type_info_all ]; - } - -Please replace Driver (or "") with the name of your driver. -Note that this stub function is generated for you by the write_typeinfo_pm -function, but you must manually transfer the code to Driver.pm. - -=cut - - -# These two are used by fmt_value... -my %dbi_inv; -my %sql_type_inv; - -#-DEBUGGING-# -#sub print_hash -#{ -# my ($name, %hash) = @_; -# print "Hash: $name\n"; -# foreach my $key (keys %hash) -# { -# print "$key => $hash{$key}\n"; -# } -#} -#-DEBUGGING-# - -sub inverse_hash -{ - my (%hash) = @_; - my (%inv); - foreach my $key (keys %hash) - { - my $val = $hash{$key}; - die "Double mapping for key value $val ($inv{$val}, $key)!" - if (defined $inv{$val}); - $inv{$val} = $key; - } - return %inv; -} - -sub fmt_value -{ - my ($num, $val) = @_; - if (!defined $val) - { - $val = "undef"; - } - elsif ($val !~ m/^[-+]?\d+$/) - { - # All the numbers in type_info_all are integers! - # Anything that isn't an integer is a string. - # Ensure that no double quotes screw things up. - $val =~ s/"/\\"/g if ($val =~ m/"/o); - $val = qq{"$val"}; - } - elsif ($dbi_inv{$num} =~ m/^(SQL_)?DATA_TYPE$/) - { - # All numeric... - $val = $sql_type_inv{$val} - if (defined $sql_type_inv{$val}); - } - return $val; -} - -sub write_typeinfo_pm -{ - my ($dsn, $user, $pass, $driver) = @_ ? @_ : @ARGV; - my $dbh = DBI->connect($dsn, $user, $pass, {AutoCommit=>1, RaiseError=>1}); - $driver = "" unless defined $driver; - - print < 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - FIXED_PREC_SCALE => 10, - AUTO_UNIQUE_VALUE => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - SQL_DATA_TYPE => 15, - SQL_DATETIME_SUB => 16, - NUM_PREC_RADIX => 17, - INTERVAL_PRECISION => 18, - ); - - #-DEBUG-# print_hash("dbi_map", %dbi_map); - - %dbi_inv = inverse_hash(%dbi_map); - - #-DEBUG-# print_hash("dbi_inv", %dbi_inv); - - my $maxlen = 0; - foreach my $key (keys %dbi_map) - { - $maxlen = length($key) if length($key) > $maxlen; - } - - # Print the name/value mapping entry in the type_info_all array; - my $fmt = " \%-${maxlen}s => \%2d,\n"; - my $numkey = 0; - my $maxkey = 0; - print " \$type_info_all = [\n {\n"; - foreach my $i (sort { $a <=> $b } keys %dbi_inv) - { - printf($fmt, $dbi_inv{$i}, $i); - $numkey++; - $maxkey = $i; - } - print " },\n"; - - print STDERR "### WARNING - Non-dense set of keys ($numkey keys, $maxkey max key)\n" - unless $numkey = $maxkey + 1; - - my $h = $dbh->type_info_all; - my @tia = @$h; - my %odbc_map = map { uc $_ => $tia[0]->{$_} } keys %{$tia[0]}; - shift @tia; # Remove the mapping reference. - my $numtyp = $#tia; - - #-DEBUG-# print_hash("odbc_map", %odbc_map); - - # In theory, the key/number mapping sequence for %dbi_map - # should be the same as the one from the ODBC driver. However, to - # prevent the possibility of mismatches, and to deal with older - # missing attributes or unexpected new ones, we chase back through - # the %dbi_inv and %odbc_map hashes, generating @dbi_to_odbc - # to map our new key number to the old one. - # Report if @dbi_to_odbc is not an identity mapping. - my @dbi_to_odbc; - foreach my $num (sort { $a <=> $b } keys %dbi_inv) - { - # Find the name in %dbi_inv that matches this index number. - my $dbi_key = $dbi_inv{$num}; - #-DEBUG-# print "dbi_key = $dbi_key\n"; - #-DEBUG-# print "odbc_key = $odbc_map{$dbi_key}\n"; - # Find the index in %odbc_map that has this key. - $dbi_to_odbc[$num] = (defined $odbc_map{$dbi_key}) ? $odbc_map{$dbi_key} : undef; - } - - # Determine the length of the longest formatted value in each field - my @len; - for (my $i = 0; $i <= $numtyp; $i++) - { - my @odbc_val = @{$tia[$i]}; - for (my $num = 0; $num <= $maxkey; $num++) - { - # Find the value of the entry in the @odbc_val array. - my $val = (defined $dbi_to_odbc[$num]) ? $odbc_val[$dbi_to_odbc[$num]] : undef; - $val = fmt_value($num, $val); - #-DEBUG-# print "val = $val\n"; - $val = "$val,"; - $len[$num] = length($val) if !defined $len[$num] || length($val) > $len[$num]; - } - } - - # Generate format strings to left justify each string in maximum field width. - my @fmt; - for (my $i = 0; $i <= $maxkey; $i++) - { - $fmt[$i] = "%-$len[$i]s"; - #-DEBUG-# print "fmt[$i] = $fmt[$i]\n"; - } - - # Format the data from type_info_all - for (my $i = 0; $i <= $numtyp; $i++) - { - my @odbc_val = @{$tia[$i]}; - print " [ "; - for (my $num = 0; $num <= $maxkey; $num++) - { - # Find the value of the entry in the @odbc_val array. - my $val = (defined $dbi_to_odbc[$num]) ? $odbc_val[$dbi_to_odbc[$num]] : undef; - $val = fmt_value($num, $val); - printf $fmt[$num], "$val,"; - } - print " ],\n"; - } - - print " ];\n\n 1;\n}\n\n__END__\n"; - -} - -1; - -__END__ - -=head1 AUTHORS - -Jonathan Leffler (previously ), -Jochen Wiedmann , -Steffen Goeldner , -and Tim Bunce . - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine.pm b/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine.pm deleted file mode 100644 index fb755ab..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine.pm +++ /dev/null @@ -1,2233 +0,0 @@ -# -*- perl -*- -# -# DBI::DBD::SqlEngine - A base class for implementing DBI drivers that -# have not an own SQL engine -# -# This module is currently maintained by -# -# H.Merijn Brand & Jens Rehsack -# -# The original author is Jochen Wiedmann. -# -# Copyright (C) 2009-2013 by H.Merijn Brand & Jens Rehsack -# Copyright (C) 2004 by Jeff Zucker -# Copyright (C) 1998 by Jochen Wiedmann -# -# All rights reserved. -# -# You may distribute this module under the terms of either the GNU -# General Public License or the Artistic License, as specified in -# the Perl README file. - -require 5.008; - -use strict; - -use DBI (); -require DBI::SQL::Nano; - -package DBI::DBD::SqlEngine; - -use strict; - -use Carp; -use vars qw( @ISA $VERSION $drh %methods_installed); - -$VERSION = "0.06"; - -$drh = undef; # holds driver handle(s) once initialized - -DBI->setup_driver("DBI::DBD::SqlEngine"); # only needed once but harmless to repeat - -my %accessors = ( - versions => "get_driver_versions", - new_meta => "new_sql_engine_meta", - get_meta => "get_sql_engine_meta", - set_meta => "set_sql_engine_meta", - clear_meta => "clear_sql_engine_meta", - ); - -sub driver ($;$) -{ - my ( $class, $attr ) = @_; - - # Drivers typically use a singleton object for the $drh - # We use a hash here to have one singleton per subclass. - # (Otherwise DBD::CSV and DBD::DBM, for example, would - # share the same driver object which would cause problems.) - # An alternative would be to not cache the $drh here at all - # and require that subclasses do that. Subclasses should do - # their own caching, so caching here just provides extra safety. - $drh->{$class} and return $drh->{$class}; - - $attr ||= {}; - { - no strict "refs"; - unless ( $attr->{Attribution} ) - { - $class eq "DBI::DBD::SqlEngine" - and $attr->{Attribution} = "$class by Jens Rehsack"; - $attr->{Attribution} ||= ${ $class . "::ATTRIBUTION" } - || "oops the author of $class forgot to define this"; - } - $attr->{Version} ||= ${ $class . "::VERSION" }; - $attr->{Name} or ( $attr->{Name} = $class ) =~ s/^DBD\:\://; - } - - $drh->{$class} = DBI::_new_drh( $class . "::dr", $attr ); - $drh->{$class}->STORE( ShowErrorStatement => 1 ); - - my $prefix = DBI->driver_prefix($class); - if ($prefix) - { - my $dbclass = $class . "::db"; - while ( my ( $accessor, $funcname ) = each %accessors ) - { - my $method = $prefix . $accessor; - $dbclass->can($method) and next; - my $inject = sprintf <<'EOI', $dbclass, $method, $dbclass, $funcname; -sub %s::%s -{ - my $func = %s->can (q{%s}); - goto &$func; - } -EOI - eval $inject; - $dbclass->install_method($method); - } - } - else - { - warn "Using DBI::DBD::SqlEngine with unregistered driver $class.\n" - . "Reading documentation how to prevent is strongly recommended.\n"; - - } - - # XXX inject DBD::XXX::Statement unless exists - - my $stclass = $class . "::st"; - $stclass->install_method("sql_get_colnames") unless ( $methods_installed{__PACKAGE__}++ ); - - return $drh->{$class}; -} # driver - -sub CLONE -{ - undef $drh; -} # CLONE - -# ====== DRIVER ================================================================ - -package DBI::DBD::SqlEngine::dr; - -use strict; -use warnings; - -use vars qw(@ISA $imp_data_size); - -use Carp qw/carp/; - -$imp_data_size = 0; - -sub connect ($$;$$$) -{ - my ( $drh, $dbname, $user, $auth, $attr ) = @_; - - # create a 'blank' dbh - my $dbh = DBI::_new_dbh( - $drh, - { - Name => $dbname, - USER => $user, - CURRENT_USER => $user, - } - ); - - if ($dbh) - { - # must be done first, because setting flags implicitly calls $dbdname::db->STORE - $dbh->func( 0, "init_default_attributes" ); - my $two_phased_init; - defined $dbh->{sql_init_phase} and $two_phased_init = ++$dbh->{sql_init_phase}; - my %second_phase_attrs; - my @func_inits; - - # this must be done to allow DBI.pm reblessing got handle after successful connecting - exists $attr->{RootClass} and $second_phase_attrs{RootClass} = delete $attr->{RootClass}; - - my ( $var, $val ); - while ( length $dbname ) - { - if ( $dbname =~ s/^((?:[^\\;]|\\.)*?);//s ) - { - $var = $1; - } - else - { - $var = $dbname; - $dbname = ""; - } - - if ( $var =~ m/^(.+?)=(.*)/s ) - { - $var = $1; - ( $val = $2 ) =~ s/\\(.)/$1/g; - exists $attr->{$var} - and carp("$var is given in DSN *and* \$attr during DBI->connect()") - if ($^W); - exists $attr->{$var} or $attr->{$var} = $val; - } - elsif ( $var =~ m/^(.+?)=>(.*)/s ) - { - $var = $1; - ( $val = $2 ) =~ s/\\(.)/$1/g; - my $ref = eval $val; - # $dbh->$var($ref); - push( @func_inits, $var, $ref ); - } - } - - # The attributes need to be sorted in a specific way as the - # assignment is through tied hashes and calls STORE on each - # attribute. Some attributes require to be called prior to - # others - # e.g. f_dir *must* be done before xx_tables in DBD::File - # The dbh attribute sql_init_order is a hash with the order - # as key (low is first, 0 .. 100) and the attributes that - # are set to that oreder as anon-list as value: - # { 0 => [qw( AutoCommit PrintError RaiseError Profile ... )], - # 10 => [ list of attr to be dealt with immediately after first ], - # 50 => [ all fields that are unspecified or default sort order ], - # 90 => [ all fields that are needed after other initialisation ], - # } - - my %order = map { - my $order = $_; - map { ( $_ => $order ) } @{ $dbh->{sql_init_order}{$order} }; - } sort { $a <=> $b } keys %{ $dbh->{sql_init_order} || {} }; - my @ordered_attr = - map { $_->[0] } - sort { $a->[1] <=> $b->[1] } - map { [ $_, defined $order{$_} ? $order{$_} : 50 ] } - keys %$attr; - - # initialize given attributes ... lower weighted before higher weighted - foreach my $a (@ordered_attr) - { - exists $attr->{$a} or next; - $two_phased_init and eval { - $dbh->{$a} = $attr->{$a}; - delete $attr->{$a}; - }; - $@ and $second_phase_attrs{$a} = delete $attr->{$a}; - $two_phased_init or $dbh->STORE( $a, delete $attr->{$a} ); - } - - $two_phased_init and $dbh->func( 1, "init_default_attributes" ); - %$attr = %second_phase_attrs; - - for ( my $i = 0; $i < scalar(@func_inits); $i += 2 ) - { - my $func = $func_inits[$i]; - my $arg = $func_inits[ $i + 1 ]; - $dbh->$func($arg); - } - - $dbh->func("init_done"); - - $dbh->STORE( Active => 1 ); - } - - return $dbh; -} # connect - -sub data_sources ($;$) -{ - my ( $drh, $attr ) = @_; - - my $tbl_src; - $attr - and defined $attr->{sql_table_source} - and $attr->{sql_table_source}->isa('DBI::DBD::SqlEngine::TableSource') - and $tbl_src = $attr->{sql_table_source}; - - !defined($tbl_src) - and $drh->{ImplementorClass}->can('default_table_source') - and $tbl_src = $drh->{ImplementorClass}->default_table_source(); - defined($tbl_src) or return; - - $tbl_src->data_sources( $drh, $attr ); -} # data_sources - -sub disconnect_all -{ -} # disconnect_all - -sub DESTROY -{ - undef; -} # DESTROY - -# ====== DATABASE ============================================================== - -package DBI::DBD::SqlEngine::db; - -use strict; -use warnings; - -use vars qw(@ISA $imp_data_size); - -use Carp; - -if ( eval { require Clone; } ) -{ - Clone->import("clone"); -} -else -{ - require Storable; # in CORE since 5.7.3 - *clone = \&Storable::dclone; -} - -$imp_data_size = 0; - -sub ping -{ - ( $_[0]->FETCH("Active") ) ? 1 : 0; -} # ping - -sub data_sources -{ - my ( $dbh, $attr, @other ) = @_; - my $drh = $dbh->{Driver}; # XXX proxy issues? - ref($attr) eq 'HASH' or $attr = {}; - defined( $attr->{sql_table_source} ) or $attr->{sql_table_source} = $dbh->{sql_table_source}; - return $drh->data_sources( $attr, @other ); -} - -sub prepare ($$;@) -{ - my ( $dbh, $statement, @attribs ) = @_; - - # create a 'blank' sth - my $sth = DBI::_new_sth( $dbh, { Statement => $statement } ); - - if ($sth) - { - my $class = $sth->FETCH("ImplementorClass"); - $class =~ s/::st$/::Statement/; - my $stmt; - - # if using SQL::Statement version > 1 - # cache the parser object if the DBD supports parser caching - # SQL::Nano and older SQL::Statements don't support this - - if ( $class->isa("SQL::Statement") ) - { - my $parser = $dbh->{sql_parser_object}; - $parser ||= eval { $dbh->func("sql_parser_object") }; - if ($@) - { - $stmt = eval { $class->new($statement) }; - } - else - { - $stmt = eval { $class->new( $statement, $parser ) }; - } - } - else - { - $stmt = eval { $class->new($statement) }; - } - if ( $@ || $stmt->{errstr} ) - { - $dbh->set_err( $DBI::stderr, $@ || $stmt->{errstr} ); - undef $sth; - } - else - { - $sth->STORE( "sql_stmt", $stmt ); - $sth->STORE( "sql_params", [] ); - $sth->STORE( "NUM_OF_PARAMS", scalar( $stmt->params() ) ); - my @colnames = $sth->sql_get_colnames(); - $sth->STORE( "NUM_OF_FIELDS", scalar @colnames ); - } - } - return $sth; -} # prepare - -sub set_versions -{ - my $dbh = $_[0]; - $dbh->{sql_engine_version} = $DBI::DBD::SqlEngine::VERSION; - for (qw( nano_version statement_version )) - { - defined $DBI::SQL::Nano::versions->{$_} or next; - $dbh->{"sql_$_"} = $DBI::SQL::Nano::versions->{$_}; - } - $dbh->{sql_handler} = - $dbh->{sql_statement_version} - ? "SQL::Statement" - : "DBI::SQL::Nano"; - - return $dbh; -} # set_versions - -sub init_valid_attributes -{ - my $dbh = $_[0]; - - $dbh->{sql_valid_attrs} = { - sql_engine_version => 1, # DBI::DBD::SqlEngine version - sql_handler => 1, # Nano or S:S - sql_nano_version => 1, # Nano version - sql_statement_version => 1, # S:S version - sql_flags => 1, # flags for SQL::Parser - sql_dialect => 1, # dialect for SQL::Parser - sql_quoted_identifier_case => 1, # case for quoted identifiers - sql_identifier_case => 1, # case for non-quoted identifiers - sql_parser_object => 1, # SQL::Parser instance - sql_sponge_driver => 1, # Sponge driver for table_info () - sql_valid_attrs => 1, # SQL valid attributes - sql_readonly_attrs => 1, # SQL readonly attributes - sql_init_phase => 1, # Only during initialization - sql_meta => 1, # meta data for tables - sql_meta_map => 1, # mapping table for identifier case - sql_data_source => 1, # reasonable datasource class - }; - $dbh->{sql_readonly_attrs} = { - sql_engine_version => 1, # DBI::DBD::SqlEngine version - sql_handler => 1, # Nano or S:S - sql_nano_version => 1, # Nano version - sql_statement_version => 1, # S:S version - sql_quoted_identifier_case => 1, # case for quoted identifiers - sql_parser_object => 1, # SQL::Parser instance - sql_sponge_driver => 1, # Sponge driver for table_info () - sql_valid_attrs => 1, # SQL valid attributes - sql_readonly_attrs => 1, # SQL readonly attributes - }; - - return $dbh; -} # init_valid_attributes - -sub init_default_attributes -{ - my ( $dbh, $phase ) = @_; - my $given_phase = $phase; - - unless ( defined($phase) ) - { - # we have an "old" driver here - $phase = defined $dbh->{sql_init_phase}; - $phase and $phase = $dbh->{sql_init_phase}; - } - - if ( 0 == $phase ) - { - # must be done first, because setting flags implicitly calls $dbdname::db->STORE - $dbh->func("init_valid_attributes"); - - $dbh->func("set_versions"); - - $dbh->{sql_identifier_case} = 2; # SQL_IC_LOWER - $dbh->{sql_quoted_identifier_case} = 3; # SQL_IC_SENSITIVE - - $dbh->{sql_dialect} = "CSV"; - - $dbh->{sql_init_phase} = $given_phase; - - # complete derived attributes, if required - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix($drv_class); - my $valid_attrs = $drv_prefix . "valid_attrs"; - my $ro_attrs = $drv_prefix . "readonly_attrs"; - - # check whether we're running in a Gofer server or not (see - # validate_FETCH_attr for details) - $dbh->{sql_engine_in_gofer} = - ( defined $INC{"DBD/Gofer.pm"} && ( caller(5) )[0] eq "DBI::Gofer::Execute" ); - $dbh->{sql_meta} = {}; - $dbh->{sql_meta_map} = {}; # choose new name because it contains other keys - - # init_default_attributes calls inherited routine before derived DBD's - # init their default attributes, so we don't override something here - # - # defining an order of attribute initialization from connect time - # specified ones with a magic baarier (see next statement) - my $drv_pfx_meta = $drv_prefix . "meta"; - $dbh->{sql_init_order} = { - 0 => [qw( Profile RaiseError PrintError AutoCommit )], - 90 => [ "sql_meta", $dbh->{$drv_pfx_meta} ? $dbh->{$drv_pfx_meta} : () ], - }; - # ensuring Profile, RaiseError, PrintError, AutoCommit are initialized - # first when initializing attributes from connect time specified - # attributes - # further, initializations to predefined tables are happens after any - # unspecified attribute initialization (that default to order 50) - - my @comp_attrs = qw(valid_attrs version readonly_attrs); - - if ( exists $dbh->{$drv_pfx_meta} and !$dbh->{sql_engine_in_gofer} ) - { - my $attr = $dbh->{$drv_pfx_meta}; - defined $attr - and defined $dbh->{$valid_attrs} - and !defined $dbh->{$valid_attrs}{$attr} - and $dbh->{$valid_attrs}{$attr} = 1; - - my %h; - tie %h, "DBI::DBD::SqlEngine::TieTables", $dbh; - $dbh->{$attr} = \%h; - - push @comp_attrs, "meta"; - } - - foreach my $comp_attr (@comp_attrs) - { - my $attr = $drv_prefix . $comp_attr; - defined $dbh->{$valid_attrs} - and !defined $dbh->{$valid_attrs}{$attr} - and $dbh->{$valid_attrs}{$attr} = 1; - defined $dbh->{$ro_attrs} - and !defined $dbh->{$ro_attrs}{$attr} - and $dbh->{$ro_attrs}{$attr} = 1; - } - } - - return $dbh; -} # init_default_attributes - -sub init_done -{ - defined $_[0]->{sql_init_phase} and delete $_[0]->{sql_init_phase}; - delete $_[0]->{sql_valid_attrs}->{sql_init_phase}; - return; -} - -sub sql_parser_object -{ - my $dbh = $_[0]; - my $dialect = $dbh->{sql_dialect} || "CSV"; - my $parser = { - RaiseError => $dbh->FETCH("RaiseError"), - PrintError => $dbh->FETCH("PrintError"), - }; - my $sql_flags = $dbh->FETCH("sql_flags") || {}; - %$parser = ( %$parser, %$sql_flags ); - $parser = SQL::Parser->new( $dialect, $parser ); - $dbh->{sql_parser_object} = $parser; - return $parser; -} # sql_parser_object - -sub sql_sponge_driver -{ - my $dbh = $_[0]; - my $dbh2 = $dbh->{sql_sponge_driver}; - unless ($dbh2) - { - $dbh2 = $dbh->{sql_sponge_driver} = DBI->connect("DBI:Sponge:"); - unless ($dbh2) - { - $dbh->set_err( $DBI::stderr, $DBI::errstr ); - return; - } - } -} - -sub disconnect ($) -{ - %{ $_[0]->{sql_meta} } = (); - %{ $_[0]->{sql_meta_map} } = (); - $_[0]->STORE( Active => 0 ); - return 1; -} # disconnect - -sub validate_FETCH_attr -{ - my ( $dbh, $attrib ) = @_; - - # If running in a Gofer server, access to our tied compatibility hash - # would force Gofer to serialize the tieing object including it's - # private $dbh reference used to do the driver function calls. - # This will result in nasty exceptions. So return a copy of the - # sql_meta structure instead, which is the source of for the compatibility - # tie-hash. It's not as good as liked, but the best we can do in this - # situation. - if ( $dbh->{sql_engine_in_gofer} ) - { - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix($drv_class); - exists $dbh->{ $drv_prefix . "meta" } && $attrib eq $dbh->{ $drv_prefix . "meta" } - and $attrib = "sql_meta"; - } - - return $attrib; -} - -sub FETCH ($$) -{ - my ( $dbh, $attrib ) = @_; - $attrib eq "AutoCommit" - and return 1; - - # Driver private attributes are lower cased - if ( $attrib eq ( lc $attrib ) ) - { - # first let the implementation deliver an alias for the attribute to fetch - # after it validates the legitimation of the fetch request - $attrib = $dbh->func( $attrib, "validate_FETCH_attr" ) or return; - - my $attr_prefix; - $attrib =~ m/^([a-z]+_)/ and $attr_prefix = $1; - unless ($attr_prefix) - { - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - $attr_prefix = DBI->driver_prefix($drv_class); - $attrib = $attr_prefix . $attrib; - } - my $valid_attrs = $attr_prefix . "valid_attrs"; - my $ro_attrs = $attr_prefix . "readonly_attrs"; - - exists $dbh->{$valid_attrs} - and ( $dbh->{$valid_attrs}{$attrib} - or return $dbh->set_err( $DBI::stderr, "Invalid attribute '$attrib'" ) ); - exists $dbh->{$ro_attrs} - and $dbh->{$ro_attrs}{$attrib} - and defined $dbh->{$attrib} - and refaddr( $dbh->{$attrib} ) - and return clone( $dbh->{$attrib} ); - - return $dbh->{$attrib}; - } - # else pass up to DBI to handle - return $dbh->SUPER::FETCH($attrib); -} # FETCH - -sub validate_STORE_attr -{ - my ( $dbh, $attrib, $value ) = @_; - - if ( $attrib eq "sql_identifier_case" || $attrib eq "sql_quoted_identifier_case" - and $value < 1 || $value > 4 ) - { - croak "attribute '$attrib' must have a value from 1 .. 4 (SQL_IC_UPPER .. SQL_IC_MIXED)"; - # XXX correctly a remap of all entries in sql_meta/sql_meta_map is required here - } - - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix($drv_class); - - exists $dbh->{ $drv_prefix . "meta" } - and $attrib eq $dbh->{ $drv_prefix . "meta" } - and $attrib = "sql_meta"; - - return ( $attrib, $value ); -} - -# the ::db::STORE method is what gets called when you set -# a lower-cased database handle attribute such as $dbh->{somekey}=$someval; -# -# STORE should check to make sure that "somekey" is a valid attribute name -# but only if it is really one of our attributes (starts with dbm_ or foo_) -# You can also check for valid values for the attributes if needed -# and/or perform other operations -# -sub STORE ($$$) -{ - my ( $dbh, $attrib, $value ) = @_; - - if ( $attrib eq "AutoCommit" ) - { - $value and return 1; # is already set - croak "Can't disable AutoCommit"; - } - - if ( $attrib eq lc $attrib ) - { - # Driver private attributes are lower cased - - ( $attrib, $value ) = $dbh->func( $attrib, $value, "validate_STORE_attr" ); - $attrib or return; - - my $attr_prefix; - $attrib =~ m/^([a-z]+_)/ and $attr_prefix = $1; - unless ($attr_prefix) - { - ( my $drv_class = $dbh->{ImplementorClass} ) =~ s/::db$//; - $attr_prefix = DBI->driver_prefix($drv_class); - $attrib = $attr_prefix . $attrib; - } - my $valid_attrs = $attr_prefix . "valid_attrs"; - my $ro_attrs = $attr_prefix . "readonly_attrs"; - - exists $dbh->{$valid_attrs} - and ( $dbh->{$valid_attrs}{$attrib} - or return $dbh->set_err( $DBI::stderr, "Invalid attribute '$attrib'" ) ); - exists $dbh->{$ro_attrs} - and $dbh->{$ro_attrs}{$attrib} - and defined $dbh->{$attrib} - and return $dbh->set_err( $DBI::stderr, - "attribute '$attrib' is readonly and must not be modified" ); - - if ( $attrib eq "sql_meta" ) - { - while ( my ( $k, $v ) = each %$value ) - { - $dbh->{$attrib}{$k} = $v; - } - } - else - { - $dbh->{$attrib} = $value; - } - - return 1; - } - - return $dbh->SUPER::STORE( $attrib, $value ); -} # STORE - -sub get_driver_versions -{ - my ( $dbh, $table ) = @_; - my %vsn = ( - OS => "$^O ($Config::Config{osvers})", - Perl => "$] ($Config::Config{archname})", - DBI => $DBI::VERSION, - ); - my %vmp; - - my $sql_engine_verinfo = - join " ", - $dbh->{sql_engine_version}, "using", $dbh->{sql_handler}, - $dbh->{sql_handler} eq "SQL::Statement" - ? $dbh->{sql_statement_version} - : $dbh->{sql_nano_version}; - - my $indent = 0; - my @deriveds = ( $dbh->{ImplementorClass} ); - while (@deriveds) - { - my $derived = shift @deriveds; - $derived eq "DBI::DBD::SqlEngine::db" and last; - $derived->isa("DBI::DBD::SqlEngine::db") or next; - #no strict 'refs'; - eval "push \@deriveds, \@${derived}::ISA"; - #use strict; - ( my $drv_class = $derived ) =~ s/::db$//; - my $drv_prefix = DBI->driver_prefix($drv_class); - my $ddgv = $dbh->{ImplementorClass}->can("get_${drv_prefix}versions"); - my $drv_version = $ddgv ? &$ddgv( $dbh, $table ) : $dbh->{ $drv_prefix . "version" }; - $drv_version ||= - eval { $derived->VERSION() }; # XXX access $drv_class::VERSION via symbol table - $vsn{$drv_class} = $drv_version; - $indent and $vmp{$drv_class} = " " x $indent . $drv_class; - $indent += 2; - } - - $vsn{"DBI::DBD::SqlEngine"} = $sql_engine_verinfo; - $indent and $vmp{"DBI::DBD::SqlEngine"} = " " x $indent . "DBI::DBD::SqlEngine"; - - $DBI::PurePerl and $vsn{"DBI::PurePerl"} = $DBI::PurePerl::VERSION; - - $indent += 20; - my @versions = map { sprintf "%-${indent}s %s", $vmp{$_} || $_, $vsn{$_} } - sort { - $a->isa($b) and return -1; - $b->isa($a) and return 1; - $a->isa("DBI::DBD::SqlEngine") and return -1; - $b->isa("DBI::DBD::SqlEngine") and return 1; - return $a cmp $b; - } keys %vsn; - - return wantarray ? @versions : join "\n", @versions; -} # get_versions - -sub get_single_table_meta -{ - my ( $dbh, $table, $attr ) = @_; - my $meta; - - $table eq "." - and return $dbh->FETCH($attr); - - ( my $class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); - $meta or croak "No such table '$table'"; - - # prevent creation of undef attributes - return $class->get_table_meta_attr( $meta, $attr ); -} # get_single_table_meta - -sub get_sql_engine_meta -{ - my ( $dbh, $table, $attr ) = @_; - - my $gstm = $dbh->{ImplementorClass}->can("get_single_table_meta"); - - $table eq "*" - and $table = [ ".", keys %{ $dbh->{sql_meta} } ]; - $table eq "+" - and $table = [ grep { m/^[_A-Za-z0-9]+$/ } keys %{ $dbh->{sql_meta} } ]; - ref $table eq "Regexp" - and $table = [ grep { $_ =~ $table } keys %{ $dbh->{sql_meta} } ]; - - ref $table || ref $attr - or return $gstm->( $dbh, $table, $attr ); - - ref $table or $table = [$table]; - ref $attr or $attr = [$attr]; - "ARRAY" eq ref $table - or return - $dbh->set_err( $DBI::stderr, - "Invalid argument for \$table - SCALAR, Regexp or ARRAY expected but got " . ref $table ); - "ARRAY" eq ref $attr - or return $dbh->set_err( - "Invalid argument for \$attr - SCALAR or ARRAY expected but got " . ref $attr ); - - my %results; - foreach my $tname ( @{$table} ) - { - my %tattrs; - foreach my $aname ( @{$attr} ) - { - $tattrs{$aname} = $gstm->( $dbh, $tname, $aname ); - } - $results{$tname} = \%tattrs; - } - - return \%results; -} # get_sql_engine_meta - -sub new_sql_engine_meta -{ - my ( $dbh, $table, $values ) = @_; - my $respect_case = 0; - - "HASH" eq ref $values - or croak "Invalid argument for \$values - SCALAR or HASH expected but got " . ref $values; - - $table =~ s/^\"// and $respect_case = 1; # handle quoted identifiers - $table =~ s/\"$//; - - unless ($respect_case) - { - defined $dbh->{sql_meta_map}{$table} and $table = $dbh->{sql_meta_map}{$table}; - } - - $dbh->{sql_meta}{$table} = { %{$values} }; - my $class; - defined $values->{sql_table_class} and $class = $values->{sql_table_class}; - defined $class or ( $class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - # XXX we should never hit DBD::File::Table::get_table_meta here ... - my ( undef, $meta ) = $class->get_table_meta( $dbh, $table, $respect_case ); - 1; -} # new_sql_engine_meta - -sub set_single_table_meta -{ - my ( $dbh, $table, $attr, $value ) = @_; - my $meta; - - $table eq "." - and return $dbh->STORE( $attr, $value ); - - ( my $class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); # 1 means: respect case - $meta or croak "No such table '$table'"; - $class->set_table_meta_attr( $meta, $attr, $value ); - - return $dbh; -} # set_single_table_meta - -sub set_sql_engine_meta -{ - my ( $dbh, $table, $attr, $value ) = @_; - - my $sstm = $dbh->{ImplementorClass}->can("set_single_table_meta"); - - $table eq "*" - and $table = [ ".", keys %{ $dbh->{sql_meta} } ]; - $table eq "+" - and $table = [ grep { m/^[_A-Za-z0-9]+$/ } keys %{ $dbh->{sql_meta} } ]; - ref($table) eq "Regexp" - and $table = [ grep { $_ =~ $table } keys %{ $dbh->{sql_meta} } ]; - - ref $table || ref $attr - or return $sstm->( $dbh, $table, $attr, $value ); - - ref $table or $table = [$table]; - ref $attr or $attr = { $attr => $value }; - "ARRAY" eq ref $table - or croak "Invalid argument for \$table - SCALAR, Regexp or ARRAY expected but got " - . ref $table; - "HASH" eq ref $attr - or croak "Invalid argument for \$attr - SCALAR or HASH expected but got " . ref $attr; - - foreach my $tname ( @{$table} ) - { - while ( my ( $aname, $aval ) = each %$attr ) - { - $sstm->( $dbh, $tname, $aname, $aval ); - } - } - - return $dbh; -} # set_file_meta - -sub clear_sql_engine_meta -{ - my ( $dbh, $table ) = @_; - - ( my $class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - my ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 ); - $meta and %{$meta} = (); - - return; -} # clear_file_meta - -sub DESTROY ($) -{ - my $dbh = shift; - $dbh->SUPER::FETCH("Active") and $dbh->disconnect; - undef $dbh->{sql_parser_object}; -} # DESTROY - -sub type_info_all ($) -{ - [ - { - TYPE_NAME => 0, - DATA_TYPE => 1, - PRECISION => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - MONEY => 10, - AUTO_INCREMENT => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - }, - [ - "VARCHAR", DBI::SQL_VARCHAR(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, 999999, - ], - [ "CHAR", DBI::SQL_CHAR(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, 999999, ], - [ "INTEGER", DBI::SQL_INTEGER(), undef, "", "", undef, 0, 0, 1, 0, 0, 0, undef, 0, 0, ], - [ "REAL", DBI::SQL_REAL(), undef, "", "", undef, 0, 0, 1, 0, 0, 0, undef, 0, 0, ], - [ - "BLOB", DBI::SQL_LONGVARBINARY(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, - 999999, - ], - [ - "BLOB", DBI::SQL_LONGVARBINARY(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, - 999999, - ], - [ - "TEXT", DBI::SQL_LONGVARCHAR(), undef, "'", "'", undef, 0, 1, 1, 0, 0, 0, undef, 1, - 999999, - ], - ]; -} # type_info_all - -sub get_avail_tables -{ - my $dbh = $_[0]; - my @tables = (); - - if ( $dbh->{sql_handler} eq "SQL::Statement" and $dbh->{sql_ram_tables} ) - { - # XXX map +[ undef, undef, $_, "TABLE", "TEMP" ], keys %{...} - foreach my $table ( keys %{ $dbh->{sql_ram_tables} } ) - { - push @tables, [ undef, undef, $table, "TABLE", "TEMP" ]; - } - } - - my $tbl_src; - defined $dbh->{sql_table_source} - and $dbh->{sql_table_source}->isa('DBI::DBD::SqlEngine::TableSource') - and $tbl_src = $dbh->{sql_table_source}; - - !defined($tbl_src) - and $dbh->{Driver}->{ImplementorClass}->can('default_table_source') - and $tbl_src = $dbh->{Driver}->{ImplementorClass}->default_table_source(); - defined($tbl_src) and push( @tables, $tbl_src->avail_tables($dbh) ); - - return @tables; -} # get_avail_tables - -{ - my $names = [qw( TABLE_QUALIFIER TABLE_OWNER TABLE_NAME TABLE_TYPE REMARKS )]; - - sub table_info ($) - { - my $dbh = shift; - - my @tables = $dbh->func("get_avail_tables"); - - # Temporary kludge: DBD::Sponge dies if @tables is empty. :-( - # this no longer seems to be true @tables or return; - - my $dbh2 = $dbh->func("sql_sponge_driver"); - my $sth = $dbh2->prepare( - "TABLE_INFO", - { - rows => \@tables, - NAME => $names, - } - ); - $sth or return $dbh->set_err( $DBI::stderr, $dbh2->errstr ); - $sth->execute or return; - return $sth; - } # table_info -} - -sub list_tables ($) -{ - my $dbh = shift; - my @table_list; - - my @tables = $dbh->func("get_avail_tables") or return; - foreach my $ref (@tables) - { - # rt69260 and rt67223 - the same issue in 2 different queues - push @table_list, $ref->[2]; - } - - return @table_list; -} # list_tables - -sub quote ($$;$) -{ - my ( $self, $str, $type ) = @_; - defined $str or return "NULL"; - defined $type && ( $type == DBI::SQL_NUMERIC() - || $type == DBI::SQL_DECIMAL() - || $type == DBI::SQL_INTEGER() - || $type == DBI::SQL_SMALLINT() - || $type == DBI::SQL_FLOAT() - || $type == DBI::SQL_REAL() - || $type == DBI::SQL_DOUBLE() - || $type == DBI::SQL_TINYINT() ) - and return $str; - - $str =~ s/\\/\\\\/sg; - $str =~ s/\0/\\0/sg; - $str =~ s/\'/\\\'/sg; - $str =~ s/\n/\\n/sg; - $str =~ s/\r/\\r/sg; - return "'$str'"; -} # quote - -sub commit ($) -{ - my $dbh = shift; - $dbh->FETCH("Warn") - and carp "Commit ineffective while AutoCommit is on", -1; - return 1; -} # commit - -sub rollback ($) -{ - my $dbh = shift; - $dbh->FETCH("Warn") - and carp "Rollback ineffective while AutoCommit is on", -1; - return 0; -} # rollback - -# ====== Tie-Meta ============================================================== - -package DBI::DBD::SqlEngine::TieMeta; - -use Carp qw(croak); -require Tie::Hash; -@DBI::DBD::SqlEngine::TieMeta::ISA = qw(Tie::Hash); - -sub TIEHASH -{ - my ( $class, $tblClass, $tblMeta ) = @_; - - my $self = bless( - { - tblClass => $tblClass, - tblMeta => $tblMeta, - }, - $class - ); - return $self; -} # new - -sub STORE -{ - my ( $self, $meta_attr, $meta_val ) = @_; - - $self->{tblClass}->set_table_meta_attr( $self->{tblMeta}, $meta_attr, $meta_val ); - - return; -} # STORE - -sub FETCH -{ - my ( $self, $meta_attr ) = @_; - - return $self->{tblClass}->get_table_meta_attr( $self->{tblMeta}, $meta_attr ); -} # FETCH - -sub FIRSTKEY -{ - my $a = scalar keys %{ $_[0]->{tblMeta} }; - each %{ $_[0]->{tblMeta} }; -} # FIRSTKEY - -sub NEXTKEY -{ - each %{ $_[0]->{tblMeta} }; -} # NEXTKEY - -sub EXISTS -{ - exists $_[0]->{tblMeta}{ $_[1] }; -} # EXISTS - -sub DELETE -{ - croak "Can't delete single attributes from table meta structure"; -} # DELETE - -sub CLEAR -{ - %{ $_[0]->{tblMeta} } = (); -} # CLEAR - -sub SCALAR -{ - scalar %{ $_[0]->{tblMeta} }; -} # SCALAR - -# ====== Tie-Tables ============================================================ - -package DBI::DBD::SqlEngine::TieTables; - -use Carp qw(croak); -require Tie::Hash; -@DBI::DBD::SqlEngine::TieTables::ISA = qw(Tie::Hash); - -sub TIEHASH -{ - my ( $class, $dbh ) = @_; - - ( my $tbl_class = $dbh->{ImplementorClass} ) =~ s/::db$/::Table/; - my $self = bless( - { - dbh => $dbh, - tblClass => $tbl_class, - }, - $class - ); - return $self; -} # new - -sub STORE -{ - my ( $self, $table, $tbl_meta ) = @_; - - "HASH" eq ref $tbl_meta - or croak "Invalid data for storing as table meta data (must be hash)"; - - ( undef, my $meta ) = $self->{tblClass}->get_table_meta( $self->{dbh}, $table, 1 ); - $meta or croak "Invalid table name '$table'"; - - while ( my ( $meta_attr, $meta_val ) = each %$tbl_meta ) - { - $self->{tblClass}->set_table_meta_attr( $meta, $meta_attr, $meta_val ); - } - - return; -} # STORE - -sub FETCH -{ - my ( $self, $table ) = @_; - - ( undef, my $meta ) = $self->{tblClass}->get_table_meta( $self->{dbh}, $table, 1 ); - $meta or croak "Invalid table name '$table'"; - - my %h; - tie %h, "DBI::DBD::SqlEngine::TieMeta", $self->{tblClass}, $meta; - - return \%h; -} # FETCH - -sub FIRSTKEY -{ - my $a = scalar keys %{ $_[0]->{dbh}->{sql_meta} }; - each %{ $_[0]->{dbh}->{sql_meta} }; -} # FIRSTKEY - -sub NEXTKEY -{ - each %{ $_[0]->{dbh}->{sql_meta} }; -} # NEXTKEY - -sub EXISTS -{ - exists $_[0]->{dbh}->{sql_meta}->{ $_[1] } - or exists $_[0]->{dbh}->{sql_meta_map}->{ $_[1] }; -} # EXISTS - -sub DELETE -{ - my ( $self, $table ) = @_; - - ( undef, my $meta ) = $self->{tblClass}->get_table_meta( $self->{dbh}, $table, 1 ); - $meta or croak "Invalid table name '$table'"; - - delete $_[0]->{dbh}->{sql_meta}->{ $meta->{table_name} }; -} # DELETE - -sub CLEAR -{ - %{ $_[0]->{dbh}->{sql_meta} } = (); - %{ $_[0]->{dbh}->{sql_meta_map} } = (); -} # CLEAR - -sub SCALAR -{ - scalar %{ $_[0]->{dbh}->{sql_meta} }; -} # SCALAR - -# ====== STATEMENT ============================================================= - -package DBI::DBD::SqlEngine::st; - -use strict; -use warnings; - -use vars qw(@ISA $imp_data_size); - -$imp_data_size = 0; - -sub bind_param ($$$;$) -{ - my ( $sth, $pNum, $val, $attr ) = @_; - if ( $attr && defined $val ) - { - my $type = ref $attr eq "HASH" ? $attr->{TYPE} : $attr; - if ( $type == DBI::SQL_BIGINT() - || $type == DBI::SQL_INTEGER() - || $type == DBI::SQL_SMALLINT() - || $type == DBI::SQL_TINYINT() ) - { - $val += 0; - } - elsif ( $type == DBI::SQL_DECIMAL() - || $type == DBI::SQL_DOUBLE() - || $type == DBI::SQL_FLOAT() - || $type == DBI::SQL_NUMERIC() - || $type == DBI::SQL_REAL() ) - { - $val += 0.; - } - else - { - $val = "$val"; - } - } - $sth->{sql_params}[ $pNum - 1 ] = $val; - return 1; -} # bind_param - -sub execute -{ - my $sth = shift; - my $params = @_ ? ( $sth->{sql_params} = [@_] ) : $sth->{sql_params}; - - $sth->finish; - my $stmt = $sth->{sql_stmt}; - - # must not proved when already executed - SQL::Statement modifies - # received params - unless ( $sth->{sql_params_checked}++ ) - { - # SQL::Statement and DBI::SQL::Nano will return the list of required params - # when called in list context. Do not look into the several items, they're - # implementation specific and may change without warning - unless ( ( my $req_prm = $stmt->params() ) == ( my $nparm = @$params ) ) - { - my $msg = "You passed $nparm parameters where $req_prm required"; - return $sth->set_err( $DBI::stderr, $msg ); - } - } - - my @err; - my $result; - eval { - local $SIG{__WARN__} = sub { push @err, @_ }; - $result = $stmt->execute( $sth, $params ); - }; - unless ( defined $result ) - { - $sth->set_err( $DBI::stderr, $@ || $stmt->{errstr} || $err[0] ); - return; - } - - if ( $stmt->{NUM_OF_FIELDS} ) - { # is a SELECT statement - $sth->STORE( Active => 1 ); - $sth->FETCH("NUM_OF_FIELDS") - or $sth->STORE( "NUM_OF_FIELDS", $stmt->{NUM_OF_FIELDS} ); - } - return $result; -} # execute - -sub finish -{ - my $sth = $_[0]; - $sth->SUPER::STORE( Active => 0 ); - delete $sth->{sql_stmt}{data}; - return 1; -} # finish - -sub fetch ($) -{ - my $sth = $_[0]; - my $data = $sth->{sql_stmt}{data}; - if ( !$data || ref $data ne "ARRAY" ) - { - $sth->set_err( - $DBI::stderr, - "Attempt to fetch row without a preceding execute () call or from a non-SELECT statement" - ); - return; - } - my $dav = shift @$data; - unless ($dav) - { - $sth->finish; - return; - } - if ( $sth->FETCH("ChopBlanks") ) # XXX: (TODO) Only chop on CHAR fields, - { # not on VARCHAR or NUMERIC (see DBI docs) - $_ && $_ =~ s/ +$// for @$dav; - } - return $sth->_set_fbav($dav); -} # fetch - -no warnings 'once'; -*fetchrow_arrayref = \&fetch; - -use warnings; - -sub sql_get_colnames -{ - my $sth = $_[0]; - # Being a bit dirty here, as neither SQL::Statement::Structure nor - # DBI::SQL::Nano::Statement_ does not offer an interface to the - # required data - my @colnames; - if ( $sth->{sql_stmt}->{NAME} and "ARRAY" eq ref( $sth->{sql_stmt}->{NAME} ) ) - { - @colnames = @{ $sth->{sql_stmt}->{NAME} }; - } - elsif ( $sth->{sql_stmt}->isa('SQL::Statement') ) - { - my $stmt = $sth->{sql_stmt} || {}; - my @coldefs = @{ $stmt->{column_defs} || [] }; - @colnames = map { $_->{name} || $_->{value} } @coldefs; - } - @colnames = $sth->{sql_stmt}->column_names() unless (@colnames); - - @colnames = () if ( grep { m/\*/ } @colnames ); - - return @colnames; -} - -sub FETCH ($$) -{ - my ( $sth, $attrib ) = @_; - - $attrib eq "NAME" and return [ $sth->sql_get_colnames() ]; - - $attrib eq "TYPE" and return [ ( DBI::SQL_VARCHAR() ) x scalar $sth->sql_get_colnames() ]; - $attrib eq "TYPE_NAME" and return [ ("VARCHAR") x scalar $sth->sql_get_colnames() ]; - $attrib eq "PRECISION" and return [ (0) x scalar $sth->sql_get_colnames() ]; - $attrib eq "NULLABLE" and return [ (1) x scalar $sth->sql_get_colnames() ]; - - if ( $attrib eq lc $attrib ) - { - # Private driver attributes are lower cased - return $sth->{$attrib}; - } - - # else pass up to DBI to handle - return $sth->SUPER::FETCH($attrib); -} # FETCH - -sub STORE ($$$) -{ - my ( $sth, $attrib, $value ) = @_; - if ( $attrib eq lc $attrib ) # Private driver attributes are lower cased - { - $sth->{$attrib} = $value; - return 1; - } - return $sth->SUPER::STORE( $attrib, $value ); -} # STORE - -sub DESTROY ($) -{ - my $sth = shift; - $sth->SUPER::FETCH("Active") and $sth->finish; - undef $sth->{sql_stmt}; - undef $sth->{sql_params}; -} # DESTROY - -sub rows ($) -{ - return $_[0]->{sql_stmt}{NUM_OF_ROWS}; -} # rows - -# ====== TableSource =========================================================== - -package DBI::DBD::SqlEngine::TableSource; - -use strict; -use warnings; - -use Carp; - -sub data_sources ($;$) -{ - my ( $class, $drh, $attrs ) = @_; - croak( ( ref( $_[0] ) ? ref( $_[0] ) : $_[0] ) . " must implement data_sources" ); -} - -sub avail_tables -{ - my ( $self, $dbh ) = @_; - croak( ( ref( $_[0] ) ? ref( $_[0] ) : $_[0] ) . " must implement avail_tables" ); -} - -# ====== DataSource ============================================================ - -package DBI::DBD::SqlEngine::DataSource; - -use strict; -use warnings; - -use Carp; - -sub complete_table_name ($$;$) -{ - my ( $self, $meta, $table, $respect_case ) = @_; - croak( ( ref( $_[0] ) ? ref( $_[0] ) : $_[0] ) . " must implement complete_table_name" ); -} - -sub open_data ($) -{ - my ( $self, $meta, $attrs, $flags ) = @_; - croak( ( ref( $_[0] ) ? ref( $_[0] ) : $_[0] ) . " must implement open_data" ); -} - -# ====== SQL::STATEMENT ======================================================== - -package DBI::DBD::SqlEngine::Statement; - -use strict; -use warnings; - -use Carp; - -@DBI::DBD::SqlEngine::Statement::ISA = qw(DBI::SQL::Nano::Statement); - -sub open_table ($$$$$) -{ - my ( $self, $data, $table, $createMode, $lockMode ) = @_; - - my $class = ref $self; - $class =~ s/::Statement/::Table/; - - my $flags = { - createMode => $createMode, - lockMode => $lockMode, - }; - $self->{command} eq "DROP" and $flags->{dropMode} = 1; - - my ( $tblnm, $table_meta ) = $class->get_table_meta( $data->{Database}, $table, 1 ) - or croak "Cannot find appropriate meta for table '$table'"; - - defined $table_meta->{sql_table_class} and $class = $table_meta->{sql_table_class}; - - # because column name mapping is initialized in constructor ... - # and therefore specific opening operations might be done before - # reaching DBI::DBD::SqlEngine::Table->new(), we need to intercept - # ReadOnly here - my $write_op = $createMode || $lockMode || $flags->{dropMode}; - if ($write_op) - { - $table_meta->{readonly} - and croak "Table '$table' is marked readonly - " - . $self->{command} - . ( $lockMode ? " with locking" : "" ) - . " command forbidden"; - } - - return $class->new( $data, { table => $table }, $flags ); -} # open_table - -# ====== SQL::TABLE ============================================================ - -package DBI::DBD::SqlEngine::Table; - -use strict; -use warnings; - -use Carp; - -@DBI::DBD::SqlEngine::Table::ISA = qw(DBI::SQL::Nano::Table); - -sub bootstrap_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_; - - defined $dbh->{ReadOnly} - and !defined( $meta->{readonly} ) - and $meta->{readonly} = $dbh->{ReadOnly}; - defined $meta->{sql_identifier_case} - or $meta->{sql_identifier_case} = $dbh->{sql_identifier_case}; - - exists $meta->{sql_data_source} or $meta->{sql_data_source} = $dbh->{sql_data_source}; - - $meta; -} - -sub init_table_meta -{ - my ( $self, $dbh, $meta, $table ) = @_ if (0); - - return; -} # init_table_meta - -sub get_table_meta ($$$;$) -{ - my ( $self, $dbh, $table, $respect_case, @other ) = @_; - unless ( defined $respect_case ) - { - $respect_case = 0; - $table =~ s/^\"// and $respect_case = 1; # handle quoted identifiers - $table =~ s/\"$//; - } - - unless ($respect_case) - { - defined $dbh->{sql_meta_map}{$table} and $table = $dbh->{sql_meta_map}{$table}; - } - - my $meta = {}; - defined $dbh->{sql_meta}{$table} and $meta = $dbh->{sql_meta}{$table}; - - do_initialize: - unless ( $meta->{initialized} ) - { - $self->bootstrap_table_meta( $dbh, $meta, $table, @other ); - $meta->{sql_data_source}->complete_table_name( $meta, $table, $respect_case, @other ) - or return; - - if ( defined $meta->{table_name} and $table ne $meta->{table_name} ) - { - $dbh->{sql_meta_map}{$table} = $meta->{table_name}; - $table = $meta->{table_name}; - } - - # now we know a bit more - let's check if user can't use consequent spelling - # XXX add know issue about reset sql_identifier_case here ... - if ( defined $dbh->{sql_meta}{$table} ) - { - $meta = delete $dbh->{sql_meta}{$table}; # avoid endless loop - $meta->{initialized} - or goto do_initialize; - #or $meta->{sql_data_source}->complete_table_name( $meta, $table, $respect_case, @other ) - #or return; - } - - unless ( $dbh->{sql_meta}{$table}{initialized} ) - { - $self->init_table_meta( $dbh, $meta, $table ); - $meta->{initialized} = 1; - $dbh->{sql_meta}{$table} = $meta; - } - } - - return ( $table, $meta ); -} # get_table_meta - -my %reset_on_modify = (); -my %compat_map = (); - -sub register_reset_on_modify -{ - my ( $proto, $extra_resets ) = @_; - foreach my $cv ( keys %$extra_resets ) - { - #%reset_on_modify = ( %reset_on_modify, %$extra_resets ); - push @{ $reset_on_modify{$cv} }, - ref $extra_resets->{$cv} ? @{ $extra_resets->{$cv} } : ( $extra_resets->{$cv} ); - } - return; -} # register_reset_on_modify - -sub register_compat_map -{ - my ( $proto, $extra_compat_map ) = @_; - %compat_map = ( %compat_map, %$extra_compat_map ); - return; -} # register_compat_map - -sub get_table_meta_attr -{ - my ( $class, $meta, $attrib ) = @_; - exists $compat_map{$attrib} - and $attrib = $compat_map{$attrib}; - exists $meta->{$attrib} - and return $meta->{$attrib}; - return; -} # get_table_meta_attr - -sub set_table_meta_attr -{ - my ( $class, $meta, $attrib, $value ) = @_; - exists $compat_map{$attrib} - and $attrib = $compat_map{$attrib}; - $class->table_meta_attr_changed( $meta, $attrib, $value ); - $meta->{$attrib} = $value; -} # set_table_meta_attr - -sub table_meta_attr_changed -{ - my ( $class, $meta, $attrib, $value ) = @_; - defined $reset_on_modify{$attrib} - and delete @$meta{ @{ $reset_on_modify{$attrib} } } - and $meta->{initialized} = 0; -} # table_meta_attr_changed - -sub open_data -{ - my ( $self, $meta, $attrs, $flags ) = @_; - - $meta->{sql_data_source} - or croak "Table " . $meta->{table_name} . " not completely initialized"; - $meta->{sql_data_source}->open_data( $meta, $attrs, $flags ); - - return; -} # open_data - -# ====== SQL::Eval API ========================================================= - -sub new -{ - my ( $className, $data, $attrs, $flags ) = @_; - my $dbh = $data->{Database}; - - my ( $tblnm, $meta ) = $className->get_table_meta( $dbh, $attrs->{table}, 1 ) - or croak "Cannot find appropriate table '$attrs->{table}'"; - $attrs->{table} = $tblnm; - - # Being a bit dirty here, as SQL::Statement::Structure does not offer - # me an interface to the data I want - $flags->{createMode} && $data->{sql_stmt}{table_defs} - and $meta->{table_defs} = $data->{sql_stmt}{table_defs}; - - # open_file must be called before inherited new is invoked - # because column name mapping is initialized in constructor ... - $className->open_data( $meta, $attrs, $flags ); - - my $tbl = { - %{$attrs}, - meta => $meta, - col_names => $meta->{col_names} || [], - }; - return $className->SUPER::new($tbl); -} # new - -sub DESTROY -{ - my $self = shift; - my $meta = $self->{meta}; - $self->{row} and undef $self->{row}; - () -} - -1; - -=pod - -=head1 NAME - -DBI::DBD::SqlEngine - Base class for DBI drivers without their own SQL engine - -=head1 SYNOPSIS - - package DBD::myDriver; - - use base qw(DBI::DBD::SqlEngine); - - sub driver - { - ... - my $drh = $proto->SUPER::driver($attr); - ... - return $drh->{class}; - } - - package DBD::myDriver::dr; - - @ISA = qw(DBI::DBD::SqlEngine::dr); - - sub data_sources { ... } - ... - - package DBD::myDriver::db; - - @ISA = qw(DBI::DBD::SqlEngine::db); - - sub init_valid_attributes { ... } - sub init_default_attributes { ... } - sub set_versions { ... } - sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } - sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } - sub get_myd_versions { ... } - sub get_avail_tables { ... } - - package DBD::myDriver::st; - - @ISA = qw(DBI::DBD::SqlEngine::st); - - sub FETCH { ... } - sub STORE { ... } - - package DBD::myDriver::Statement; - - @ISA = qw(DBI::DBD::SqlEngine::Statement); - - sub open_table { ... } - - package DBD::myDriver::Table; - - @ISA = qw(DBI::DBD::SqlEngine::Table); - - sub new { ... } - -=head1 DESCRIPTION - -DBI::DBD::SqlEngine abstracts the usage of SQL engines from the -DBD. DBD authors can concentrate on the data retrieval they want to -provide. - -It is strongly recommended that you read L and -L, because many of the DBD::File API is provided -by DBI::DBD::SqlEngine. - -Currently the API of DBI::DBD::SqlEngine is experimental and will -likely change in the near future to provide the table meta data basics -like DBD::File. - -DBI::DBD::SqlEngine expects that any driver in inheritance chain has -a L. - -=head2 Metadata - -The following attributes are handled by DBI itself and not by -DBI::DBD::SqlEngine, thus they all work as expected: - - Active - ActiveKids - CachedKids - CompatMode (Not used) - InactiveDestroy - AutoInactiveDestroy - Kids - PrintError - RaiseError - Warn (Not used) - -=head3 The following DBI attributes are handled by DBI::DBD::SqlEngine: - -=head4 AutoCommit - -Always on. - -=head4 ChopBlanks - -Works. - -=head4 NUM_OF_FIELDS - -Valid after C<< $sth->execute >>. - -=head4 NUM_OF_PARAMS - -Valid after C<< $sth->prepare >>. - -=head4 NAME - -Valid after C<< $sth->execute >>; probably undef for Non-Select statements. - -=head4 NULLABLE - -Not really working, always returns an array ref of ones, as DBD::CSV -does not verify input data. Valid after C<< $sth->execute >>; undef for -non-select statements. - -=head3 The following DBI attributes and methods are not supported: - -=over 4 - -=item bind_param_inout - -=item CursorName - -=item LongReadLen - -=item LongTruncOk - -=back - -=head3 DBI::DBD::SqlEngine specific attributes - -In addition to the DBI attributes, you can use the following dbh -attributes: - -=head4 sql_engine_version - -Contains the module version of this driver (B) - -=head4 sql_nano_version - -Contains the module version of DBI::SQL::Nano (B) - -=head4 sql_statement_version - -Contains the module version of SQL::Statement, if available (B) - -=head4 sql_handler - -Contains the SQL Statement engine, either DBI::SQL::Nano or SQL::Statement -(B). - -=head4 sql_parser_object - -Contains an instantiated instance of SQL::Parser (B). -This is filled when used first time (only when used with SQL::Statement). - -=head4 sql_sponge_driver - -Contains an internally used DBD::Sponge handle (B). - -=head4 sql_valid_attrs - -Contains the list of valid attributes for each DBI::DBD::SqlEngine based -driver (B). - -=head4 sql_readonly_attrs - -Contains the list of those attributes which are readonly (B). - -=head4 sql_identifier_case - -Contains how DBI::DBD::SqlEngine deals with non-quoted SQL identifiers: - - * SQL_IC_UPPER (1) means all identifiers are internally converted - into upper-cased pendants - * SQL_IC_LOWER (2) means all identifiers are internally converted - into lower-cased pendants - * SQL_IC_MIXED (4) means all identifiers are taken as they are - -These conversions happen if (and only if) no existing identifier matches. -Once existing identifier is used as known. - -The SQL statement execution classes doesn't have to care, so don't expect -C affects column names in statements like - - SELECT * FROM foo - -=head4 sql_quoted_identifier_case - -Contains how DBI::DBD::SqlEngine deals with quoted SQL identifiers -(B). It's fixated to SQL_IC_SENSITIVE (3), which is interpreted -as SQL_IC_MIXED. - -=head4 sql_flags - -Contains additional flags to instantiate an SQL::Parser. Because an -SQL::Parser is instantiated only once, it's recommended to set this flag -before any statement is executed. - -=head4 sql_dialect - -Controls the dialect understood by SQL::Parser. Possible values (delivery -state of SQL::Statement): - - * ANSI - * CSV - * AnyData - -Defaults to "CSV". Because an SQL::Parser is instantiated only once and -SQL::Parser doesn't allow one to modify the dialect once instantiated, -it's strongly recommended to set this flag before any statement is -executed (best place is connect attribute hash). - -=head4 sql_engine_in_gofer - -This value has a true value in case of this driver is operated via -L. The impact of being operated via Gofer is a read-only -driver (not read-only databases!), so you cannot modify any attributes -later - neither any table settings. B you won't get an error in -cases you modify table attributes, so please carefully watch -C. - -=head4 sql_meta - -Private data area which contains information about the tables this -module handles. Table meta data might not be available until the -table has been accessed for the first time e.g., by issuing a select -on it however it is possible to pre-initialize attributes for each table -you use. - -DBI::DBD::SqlEngine recognizes the (public) attributes C, -C, C, C and C. -Be very careful when modifying attributes you do not know, the consequence -might be a destroyed or corrupted table. - -While C is a private and readonly attribute (which means, you -cannot modify it's values), derived drivers might provide restricted -write access through another attribute. Well known accessors are -C for L, C for L and -C for L. - -=head4 sql_table_source - -Controls the class which will be used for fetching available tables. - -See L for details. - -=head4 sql_data_source - -Contains the class name to be used for opening tables. - -See L for details. - -=head2 Driver private methods - -=head3 Default DBI methods - -=head4 data_sources - -The C method returns a list of subdirectories of the current -directory in the form "dbi:CSV:f_dir=$dirname". - -If you want to read the subdirectories of another directory, use - - my ($drh) = DBI->install_driver ("CSV"); - my (@list) = $drh->data_sources (f_dir => "/usr/local/csv_data"); - -=head4 list_tables - -This method returns a list of file names inside $dbh->{f_dir}. -Example: - - my ($dbh) = DBI->connect ("dbi:CSV:f_dir=/usr/local/csv_data"); - my (@list) = $dbh->func ("list_tables"); - -Note that the list includes all files contained in the directory, even -those that have non-valid table names, from the view of SQL. - -=head3 Additional methods - -The following methods are only available via their documented name when -DBI::DBD::SQlEngine is used directly. Because this is only reasonable for -testing purposes, the real names must be used instead. Those names can be -computed by replacing the C in the method name with the driver prefix. - -=head4 sql_versions - -Signature: - - sub sql_versions (;$) { - my ($table_name) = @_; - $table_name ||= "."; - ... - } - -Returns the versions of the driver, including the DBI version, the Perl -version, DBI::PurePerl version (if DBI::PurePerl is active) and the version -of the SQL engine in use. - - my $dbh = DBI->connect ("dbi:File:"); - my $sql_versions = $dbh->func( "sql_versions" ); - print "$sql_versions\n"; - __END__ - # DBI::DBD::SqlEngine 0.05 using SQL::Statement 1.402 - # DBI 1.623 - # OS netbsd (6.99.12) - # Perl 5.016002 (x86_64-netbsd-thread-multi) - -Called in list context, sql_versions will return an array containing each -line as single entry. - -Some drivers might use the optional (table name) argument and modify -version information related to the table (e.g. DBD::DBM provides storage -backend information for the requested table, when it has a table name). - -=head4 sql_get_meta - -Signature: - - sub sql_get_meta ($$) - { - my ($table_name, $attrib) = @_; - ... - } - -Returns the value of a meta attribute set for a specific table, if any. -See L for the possible attributes. - -A table name of C<"."> (single dot) is interpreted as the default table. -This will retrieve the appropriate attribute globally from the dbh. -This has the same restrictions as C<< $dbh->{$attrib} >>. - -=head4 sql_set_meta - -Signature: - - sub sql_set_meta ($$$) - { - my ($table_name, $attrib, $value) = @_; - ... - } - -Sets the value of a meta attribute set for a specific table. -See L for the possible attributes. - -A table name of C<"."> (single dot) is interpreted as the default table -which will set the specified attribute globally for the dbh. -This has the same restrictions as C<< $dbh->{$attrib} = $value >>. - -=head4 sql_clear_meta - -Signature: - - sub sql_clear_meta ($) - { - my ($table_name) = @_; - ... - } - -Clears the table specific meta information in the private storage of the -dbh. - -=head2 Extensibility - -=head3 DBI::DBD::SqlEngine::TableSource - -Provides data sources and table information on database driver and database -handle level. - - package DBI::DBD::SqlEngine::TableSource; - - sub data_sources ($;$) - { - my ( $class, $drh, $attrs ) = @_; - ... - } - - sub avail_tables - { - my ( $class, $drh ) = @_; - ... - } - -The C method is called when the user invokes any of the -following: - - @ary = DBI->data_sources($driver); - @ary = DBI->data_sources($driver, \%attr); - - @ary = $dbh->data_sources(); - @ary = $dbh->data_sources(\%attr); - -The C method is called when the user invokes any of the -following: - - @names = $dbh->tables( $catalog, $schema, $table, $type ); - - $sth = $dbh->table_info( $catalog, $schema, $table, $type ); - $sth = $dbh->table_info( $catalog, $schema, $table, $type, \%attr ); - - $dbh->func( "list_tables" ); - -Every time where an C<\%attr> argument can be specified, this C<\%attr> -object's C attribute is preferred over the C<$dbh> -attribute or the driver default, eg. - - @ary = DBI->data_sources("dbi:CSV:", { - f_dir => "/your/csv/tables", - # note: this class doesn't comes with DBI - sql_table_source => "DBD::File::Archive::Tar::TableSource", - # scan tarballs instead of directories - }); - -When you're going to implement such a DBD::File::Archive::Tar::TableSource -class, remember to add correct attributes (including C -and C) to the returned DSN's. - -=head3 DBI::DBD::SqlEngine::DataSource - -Provides base functionality for dealing with tables. It is primarily -designed for allowing transparent access to files on disk or already -opened (file-)streams (eg. for DBD::CSV). - -Derived classes shall be restricted to similar functionality, too (eg. -opening streams from an archive, transparently compress/uncompress -log files before parsing them, - - package DBI::DBD::SqlEngine::DataSource; - - sub complete_table_name ($$;$) - { - my ( $self, $meta, $table, $respect_case ) = @_; - ... - } - -The method C is called when first setting up the -I for a table: - - "SELECT user.id, user.name, user.shell FROM user WHERE ..." - -results in opening the table C. First step of the table open -process is completing the name. Let's imagine you're having a L -handle with following settings: - - $dbh->{sql_identifier_case} = SQL_IC_LOWER; - $dbh->{f_ext} = '.lst'; - $dbh->{f_dir} = '/data/web/adrmgr'; - -Those settings will result in looking for files matching -C<[Uu][Ss][Ee][Rr](\.lst)?$> in C. The scanning of the -directory C and the pattern match check will be done -in C by the C method. - -If you intend to provide other sources of data streams than files, in -addition to provide an appropriate C method, a method -to open the resource is required: - - package DBI::DBD::SqlEngine::DataSource; - - sub open_data ($) - { - my ( $self, $meta, $attrs, $flags ) = @_; - ... - } - -After the method C has been run successfully, the table's meta -information are in a state which allowes the table's data accessor methods -will be able to fetch/store row information. Implementation details heavily -depends on the table implementation, whereby the most famous is surely -L. - -=head1 SQL ENGINES - -DBI::DBD::SqlEngine currently supports two SQL engines: -L and -L. DBI::SQL::Nano supports a -I limited subset of SQL statements, but it might be faster for some -very simple tasks. SQL::Statement in contrast supports a much larger subset -of ANSI SQL. - -To use SQL::Statement, you need at least version 1.401 of -SQL::Statement and the environment variable C must not -be set to a true value. - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command. - - perldoc DBI::DBD::SqlEngine - -You can also look for information at: - -=over 4 - -=item * RT: CPAN's request tracker - -L -L - -=item * AnnoCPAN: Annotated CPAN documentation - -L -L - -=item * CPAN Ratings - -L - -=item * Search CPAN - -L - -=back - -=head2 Where can I go for more help? - -For questions about installation or usage, please ask on the -dbi-dev@perl.org mailing list. - -If you have a bug report, patch or suggestion, please open -a new report ticket on CPAN, if there is not already one for -the issue you want to report. Of course, you can mail any of the -module maintainers, but it is less likely to be missed if -it is reported on RT. - -Report tickets should contain a detailed description of the bug or -enhancement request you want to report and at least an easy way to -verify/reproduce the issue and any supplied fix. Patches are always -welcome, too. - -=head1 ACKNOWLEDGEMENTS - -Thanks to Tim Bunce, Martin Evans and H.Merijn Brand for their continued -support while developing DBD::File, DBD::DBM and DBD::AnyData. -Their support, hints and feedback helped to design and implement this -module. - -=head1 AUTHOR - -This module is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -The original authors are Jochen Wiedmann and Jeff Zucker. - -=head1 COPYRIGHT AND LICENSE - - Copyright (C) 2009-2013 by H.Merijn Brand & Jens Rehsack - Copyright (C) 2004-2009 by Jeff Zucker - Copyright (C) 1998-2004 by Jochen Wiedmann - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=head1 SEE ALSO - -L, L, L and L. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine/Developers.pod b/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine/Developers.pod deleted file mode 100644 index ff272ab..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine/Developers.pod +++ /dev/null @@ -1,851 +0,0 @@ -=head1 NAME - -DBI::DBD::SqlEngine::Developers - Developers documentation for DBI::DBD::SqlEngine - -=head1 SYNOPSIS - - package DBD::myDriver; - - use base qw(DBI::DBD::SqlEngine); - - sub driver - { - ... - my $drh = $proto->SUPER::driver($attr); - ... - return $drh->{class}; - } - - sub CLONE { ... } - - package DBD::myDriver::dr; - - @ISA = qw(DBI::DBD::SqlEngine::dr); - - sub data_sources { ... } - ... - - package DBD::myDriver::db; - - @ISA = qw(DBI::DBD::SqlEngine::db); - - sub init_valid_attributes { ... } - sub init_default_attributes { ... } - sub set_versions { ... } - sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } - sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } - sub get_myd_versions { ... } - sub get_avail_tables { ... } - - package DBD::myDriver::st; - - @ISA = qw(DBI::DBD::SqlEngine::st); - - sub FETCH { ... } - sub STORE { ... } - - package DBD::myDriver::Statement; - - @ISA = qw(DBI::DBD::SqlEngine::Statement); - - sub open_table { ... } - - package DBD::myDriver::Table; - - @ISA = qw(DBI::DBD::SqlEngine::Table); - - my %reset_on_modify = ( - myd_abc => "myd_foo", - myd_mno => "myd_bar", - ); - __PACKAGE__->register_reset_on_modify( \%reset_on_modify ); - my %compat_map = ( - abc => 'foo_abc', - xyz => 'foo_xyz', - ); - __PACKAGE__->register_compat_map( \%compat_map ); - - sub bootstrap_table_meta { ... } - sub init_table_meta { ... } - sub table_meta_attr_changed { ... } - sub open_data { ... } - - sub new { ... } - - sub fetch_row { ... } - sub push_row { ... } - sub push_names { ... } - sub seek { ... } - sub truncate { ... } - sub drop { ... } - - # optimize the SQL engine by add one or more of - sub update_current_row { ... } - # or - sub update_specific_row { ... } - # or - sub update_one_row { ... } - # or - sub insert_new_row { ... } - # or - sub delete_current_row { ... } - # or - sub delete_one_row { ... } - -=head1 DESCRIPTION - -This document describes the interface of DBI::DBD::SqlEngine for DBD -developers who write DBI::DBD::SqlEngine based DBI drivers. It supplements -L and L, which you should read first. - -=head1 CLASSES - -Each DBI driver must provide a package global C<< driver >> method and -three DBI related classes: - -=over 4 - -=item DBI::DBD::SqlEngine::dr - -Driver package, contains the methods DBI calls indirectly via DBI -interface: - - DBI->connect ('DBI:DBM:', undef, undef, {}) - - # invokes - package DBD::DBM::dr; - @DBD::DBM::dr::ISA = qw(DBI::DBD::SqlEngine::dr); - - sub connect ($$;$$$) - { - ... - } - -Similar for C and C. - -Pure Perl DBI drivers derived from DBI::DBD::SqlEngine usually don't need to -override any of the methods provided through the DBD::XXX::dr package. -However if you need additional initialization not fitting in -C and C of you're ::db -class, the connect method might be the final place to be modified. - -=item DBI::DBD::SqlEngine::db - -Contains the methods which are called through DBI database handles -(C<< $dbh >>). e.g., - - $sth = $dbh->prepare ("select * from foo"); - # returns the f_encoding setting for table foo - $dbh->csv_get_meta ("foo", "f_encoding"); - -DBI::DBD::SqlEngine provides the typical methods required here. Developers who -write DBI drivers based on DBI::DBD::SqlEngine need to override the methods -C<< set_versions >> and C<< init_valid_attributes >>. - -=item DBI::DBD::SqlEngine::TieMeta; - -Provides the tie-magic for C<< $dbh->{$drv_pfx . "_meta"} >>. Routes -C through C<< $drv->set_sql_engine_meta() >> and C through -C<< $drv->get_sql_engine_meta() >>. C is not supported, you have -to execute a C statement, where applicable. - -=item DBI::DBD::SqlEngine::TieTables; - -Provides the tie-magic for tables in C<< $dbh->{$drv_pfx . "_meta"} >>. -Routes C though C<< $tblClass->set_table_meta_attr() >> and C -though C<< $tblClass->get_table_meta_attr() >>. C removes an -attribute from the I retrieved by -C<< $tblClass->get_table_meta() >>. - -=item DBI::DBD::SqlEngine::st - -Contains the methods to deal with prepared statement handles. e.g., - - $sth->execute () or die $sth->errstr; - -=item DBI::DBD::SqlEngine::TableSource; - -Base class for 3rd party table sources: - - $dbh->{sql_table_source} = "DBD::Foo::TableSource"; - -=item DBI::DBD::SqlEngine::DataSource; - -Base class for 3rd party data sources: - - $dbh->{sql_data_source} = "DBD::Foo::DataSource"; - -=item DBI::DBD::SqlEngine::Statement; - -Base class for derived drivers statement engine. Implements C. - -=item DBI::DBD::SqlEngine::Table; - -Contains tailoring between SQL engine's requirements and -C magic for finding the right tables and storage. -Builds bridges between C handling of C, -table initialization for SQL engines and I's attribute -management for derived drivers. - -=back - -=head2 DBI::DBD::SqlEngine - -This is the main package containing the routines to initialize -DBI::DBD::SqlEngine based DBI drivers. Primarily the -C<< DBI::DBD::SqlEngine::driver >> method is invoked, either directly -from DBI when the driver is initialized or from the derived class. - - package DBD::DBM; - - use base qw( DBI::DBD::SqlEngine ); - - sub driver - { - my ( $class, $attr ) = @_; - ... - my $drh = $class->SUPER::driver( $attr ); - ... - return $drh; - } - -It is not necessary to implement your own driver method as long as -additional initialization (e.g. installing more private driver -methods) is not required. You do not need to call C<< setup_driver >> -as DBI::DBD::SqlEngine takes care of it. - -=head2 DBI::DBD::SqlEngine::dr - -The driver package contains the methods DBI calls indirectly via the DBI -interface (see L). - -DBI::DBD::SqlEngine based DBI drivers usually do not need to implement anything here, -it is enough to do the basic initialization: - - package DBD:XXX::dr; - - @DBD::XXX::dr::ISA = qw (DBI::DBD::SqlEngine::dr); - $DBD::XXX::dr::imp_data_size = 0; - $DBD::XXX::dr::data_sources_attr = undef; - $DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann"; - -=head3 Methods provided by C<< DBI::DBD::SqlEngine::dr >>: - -=over 4 - -=item connect - -Supervises the driver bootstrap when calling - - DBI->connect( "dbi:Foo", , , { ... } ); - -First it instantiates a new driver using C. After that, -initial bootstrap of the newly instantiated driver is done by - - $dbh->func( 0, "init_default_attributes" ); - -The first argument (C<0>) signals that this is the very first call to -C. Modern drivers understand that and do early -stage setup here after calling - - package DBD::Foo::db; - our @DBD::Foo::db::ISA = qw(DBI::DBD::SqlEngine::db); - - sub init_default_attributes - { - my ($dbh, $phase) = @_; - $dbh->SUPER::init_default_attributes($phase); - ...; # own setup code, maybe separated by phases - } - -When the C<$phase> argument is passed down until -C, C recognizes -a I driver and initializes the attributes from I and I<$attr> -arguments passed via C<< DBI->connect( $dsn, $user, $pass, \%attr ) >>. - -At the end of the attribute initialization after I, C -invoked C again for I: - - $dbh->func( 1, "init_default_attributes" ); - -=item data_sources - -Returns a list of I's using the C method of the -class specified in C<< $dbh->{sql_table_source} >> or via C<\%attr>: - - @ary = DBI->data_sources($driver); - @ary = DBI->data_sources($driver, \%attr); - -=item disconnect_all - -C doesn't have an overall driver cache, so nothing -happens here at all. - -=back - -=head2 DBI::DBD::SqlEngine::db - -This package defines the database methods, which are called via the DBI -database handle C<< $dbh >>. - -=head3 Methods provided by C<< DBI::DBD::SqlEngine::db >>: - -=over 4 - -=item ping - -Simply returns the content of the C<< Active >> attribute. Override -when your driver needs more complicated actions here. - -=item prepare - -Prepares a new SQL statement to execute. Returns a statement handle, -C<< $sth >> - instance of the DBD:XXX::st. It is neither required nor -recommended to override this method. - -=item validate_FETCH_attr - -Called by C to allow inherited drivers do their own attribute -name validation. Calling convention is similar to C and the -return value is the approved attribute name. - - return $validated_attribute_name; - -In case of validation fails (e.g. accessing private attribute or similar), -C is permitted to throw an exception. - -=item FETCH - -Fetches an attribute of a DBI database object. Private handle attributes -must have a prefix (this is mandatory). If a requested attribute is -detected as a private attribute without a valid prefix, the driver prefix -(written as C<$drv_prefix>) is added. - -The driver prefix is extracted from the attribute name and verified against -C<< $dbh->{ $drv_prefix . "valid_attrs" } >> (when it exists). If the -requested attribute value is not listed as a valid attribute, this method -croaks. If the attribute is valid and readonly (listed in C<< $dbh->{ -$drv_prefix . "readonly_attrs" } >> when it exists), a real copy of the -attribute value is returned. So it's not possible to modify -C from outside of DBI::DBD::SqlEngine::db or a derived class. - -=item validate_STORE_attr - -Called by C to allow inherited drivers do their own attribute -name validation. Calling convention is similar to C and the -return value is the approved attribute name followed by the approved -new value. - - return ($validated_attribute_name, $validated_attribute_value); - -In case of validation fails (e.g. accessing private attribute or similar), -C is permitted to throw an exception -(C throws an exception when -someone tries to assign value other than C -to C<< $dbh->{sql_identifier_case} >> or -C<< $dbh->{sql_quoted_identifier_case} >>). - -=item STORE - -Stores a database private attribute. Private handle attributes must have a -prefix (this is mandatory). If a requested attribute is detected as a private -attribute without a valid prefix, the driver prefix (written as -C<$drv_prefix>) is added. If the database handle has an attribute -C<${drv_prefix}_valid_attrs> - for attribute names which are not listed in -that hash, this method croaks. If the database handle has an attribute -C<${drv_prefix}_readonly_attrs>, only attributes which are not listed there -can be stored (once they are initialized). Trying to overwrite such an -immutable attribute forces this method to croak. - -An example of a valid attributes list can be found in -C<< DBI::DBD::SqlEngine::db::init_valid_attributes >>. - -=item set_versions - -This method sets the attributes C<< f_version >>, C<< sql_nano_version >>, -C<< sql_statement_version >> and (if not prohibited by a restrictive -C<< ${prefix}_valid_attrs >>) C<< ${prefix}_version >>. - -This method is called at the end of the C<< connect () >> phase. - -When overriding this method, do not forget to invoke the superior one. - -=item init_valid_attributes - -This method is called after the database handle is instantiated as the -first attribute initialization. - -C<< DBI::DBD::SqlEngine::db::init_valid_attributes >> initializes the -attributes C and C. - -When overriding this method, do not forget to invoke the superior one, -preferably before doing anything else. - -=item init_default_attributes - -This method is called after the database handle is instantiated to -initialize the default attributes. It expects one argument: C<$phase>. -If C<$phase> is not given, C of C -expects this is an old-fashioned driver which isn't capable of multi-phased -initialization. - -C<< DBI::DBD::SqlEngine::db::init_default_attributes >> initializes the -attributes C, C, -C, C, C, C, -C and C when L -is available. - -It sets C to the given C<$phase>. - -When the derived implementor class provides the attribute to validate -attributes (e.g. C<< $dbh->{dbm_valid_attrs} = {...}; >>) or the attribute -containing the immutable attributes (e.g. C<< $dbh->{dbm_readonly_attrs} -= {...}; >>), the attributes C, C and -C are added (when available) to the list of valid and -immutable attributes (where C is interpreted as the driver prefix). - -=item get_versions - -This method is called by the code injected into the instantiated driver to -provide the user callable driver method C<< ${prefix}versions >> (e.g. -C<< dbm_versions >>, C<< csv_versions >>, ...). - -The DBI::DBD::SqlEngine implementation returns all version information known by -DBI::DBD::SqlEngine (e.g. DBI version, Perl version, DBI::DBD::SqlEngine version and -the SQL handler version). - -C takes the C<$dbh> as the first argument and optionally a -second argument containing a table name. The second argument is not -evaluated in C<< DBI::DBD::SqlEngine::db::get_versions >> itself - but -might be in the future. - -If the derived implementor class provides a method named -C, this is invoked and the return value of -it is associated to the derived driver name: - - if (my $dgv = $dbh->{ImplementorClass}->can ("get_" . $drv_prefix . "versions") { - (my $derived_driver = $dbh->{ImplementorClass}) =~ s/::db$//; - $versions{$derived_driver} = &$dgv ($dbh, $table); - } - -Override it to add more version information about your module, (e.g. -some kind of parser version in case of DBD::CSV, ...), if one line is not -enough room to provide all relevant information. - -=item sql_parser_object - -Returns a L instance, when C<< sql_handler >> is set to -"SQL::Statement". The parser instance is stored in C<< sql_parser_object >>. - -It is not recommended to override this method. - -=item disconnect - -Disconnects from a database. All local table information is discarded and -the C<< Active >> attribute is set to 0. - -=item type_info_all - -Returns information about all the types supported by DBI::DBD::SqlEngine. - -=item table_info - -Returns a statement handle which is prepared to deliver information about -all known tables. - -=item list_tables - -Returns a list of all known table names. - -=item quote - -Quotes a string for use in SQL statements. - -=item commit - -Warns about a useless call (if warnings enabled) and returns. -DBI::DBD::SqlEngine is typically a driver which commits every action -instantly when executed. - -=item rollback - -Warns about a useless call (if warnings enabled) and returns. -DBI::DBD::SqlEngine is typically a driver which commits every action -instantly when executed. - -=back - -=head3 Attributes used by C<< DBI::DBD::SqlEngine::db >>: - -This section describes attributes which are important to developers of DBI -Database Drivers derived from C. - -=over 4 - -=item sql_init_order - -This attribute contains a hash with priorities as key and an array -containing the C<$dbh> attributes to be initialized during before/after -other attributes. - -C initializes following attributes: - - $dbh->{sql_init_order} = { - 0 => [qw( Profile RaiseError PrintError AutoCommit )], - 90 => [ "sql_meta", $dbh->{$drv_pfx_meta} ? $dbh->{$drv_pfx_meta} : () ] - } - -The default priority of not listed attribute keys is C<50>. It is well -known that a lot of attributes needed to be set before some table settings -are initialized. For example, for L, when using - - my $dbh = DBI->connect( "dbi:DBM:", undef, undef, { - f_dir => "/path/to/dbm/databases", - dbm_type => "BerkeleyDB", - dbm_mldbm => "JSON", # use MLDBM::Serializer::JSON - dbm_tables => { - quick => { - dbm_type => "GDBM_File", - dbm_MLDBM => "FreezeThaw" - } - } - }); - -This defines a known table C which uses the L backend and -L as serializer instead of the overall default L and -L. B all files containing the table data have to be searched in -C<< $dbh->{f_dir} >>, which requires C<< $dbh->{f_dir} >> must be initialized -before C<< $dbh->{sql_meta}->{quick} >> is initialized by -C method of L to get -C<< $dbh->{sql_meta}->{quick}->{f_dir} >> being initialized properly. - -=item sql_init_phase - -This attribute is only set during the initialization steps of the DBI -Database Driver. It contains the value of the currently run initialization -phase. Currently supported phases are I and I. This -attribute is set in C and removed in C. - -=item sql_engine_in_gofer - -This value has a true value in case of this driver is operated via -L. The impact of being operated via Gofer is a read-only -driver (not read-only databases!), so you cannot modify any attributes -later - neither any table settings. B you won't get an error in -cases you modify table attributes, so please carefully watch -C. - -=item sql_table_source - -Names a class which is responsible for delivering I and -I (Database Driver related). I here -refers to L, not C. - -See L for details. - -=item sql_data_source - -Name a class which is responsible for handling table resources open -and completing table names requested via SQL statements. - -See L for details. - -=item sql_dialect - -Controls the dialect understood by SQL::Parser. Possible values (delivery -state of SQL::Statement): - - * ANSI - * CSV - * AnyData - -Defaults to "CSV". Because an SQL::Parser is instantiated only once and -SQL::Parser doesn't allow one to modify the dialect once instantiated, -it's strongly recommended to set this flag before any statement is -executed (best place is connect attribute hash). - -=back - -=head2 DBI::DBD::SqlEngine::st - -Contains the methods to deal with prepared statement handles: - -=over 4 - -=item bind_param - -Common routine to bind placeholders to a statement for execution. It -is dangerous to override this method without detailed knowledge about -the DBI::DBD::SqlEngine internal storage structure. - -=item execute - -Executes a previously prepared statement (with placeholders, if any). - -=item finish - -Finishes a statement handle, discards all buffered results. The prepared -statement is not discarded so the statement can be executed again. - -=item fetch - -Fetches the next row from the result-set. This method may be rewritten -in a later version and if it's overridden in a derived class, the -derived implementation should not rely on the storage details. - -=item fetchrow_arrayref - -Alias for C<< fetch >>. - -=item FETCH - -Fetches statement handle attributes. Supported attributes (for full overview -see L) are C, C, C -and C. Each column is returned as C which might be wrong -depending on the derived backend storage. If the statement handle has -private attributes, they can be fetched using this method, too. B that -statement attributes are not associated with any table used in this statement. - -This method usually requires extending in a derived implementation. -See L or L for some example. - -=item STORE - -Allows storing of statement private attributes. No special handling is -currently implemented here. - -=item rows - -Returns the number of rows affected by the last execute. This method might -return C. - -=back - -=head2 DBI::DBD::SqlEngine::TableSource - -Provides data sources and table information on database driver and database -handle level. - - package DBI::DBD::SqlEngine::TableSource; - - sub data_sources ($;$) - { - my ( $class, $drh, $attrs ) = @_; - ... - } - - sub avail_tables - { - my ( $class, $drh ) = @_; - ... - } - -The C method is called when the user invokes any of the -following: - - @ary = DBI->data_sources($driver); - @ary = DBI->data_sources($driver, \%attr); - - @ary = $dbh->data_sources(); - @ary = $dbh->data_sources(\%attr); - -The C method is called when the user invokes any of the -following: - - @names = $dbh->tables( $catalog, $schema, $table, $type ); - - $sth = $dbh->table_info( $catalog, $schema, $table, $type ); - $sth = $dbh->table_info( $catalog, $schema, $table, $type, \%attr ); - - $dbh->func( "list_tables" ); - -Every time where an C<\%attr> argument can be specified, this C<\%attr> -object's C attribute is preferred over the C<$dbh> -attribute or the driver default. - -=head2 DBI::DBD::SqlEngine::DataSource - -Provides base functionality for dealing with tables. It is primarily -designed for allowing transparent access to files on disk or already -opened (file-)streams (e.g. for DBD::CSV). - -Derived classes shall be restricted to similar functionality, too (e.g. -opening streams from an archive, transparently compress/uncompress -log files before parsing them, - - package DBI::DBD::SqlEngine::DataSource; - - sub complete_table_name ($$;$) - { - my ( $self, $meta, $table, $respect_case ) = @_; - ... - } - -The method C is called when first setting up the -I for a table: - - "SELECT user.id, user.name, user.shell FROM user WHERE ..." - -results in opening the table C. First step of the table open -process is completing the name. Let's imagine you're having a L -handle with following settings: - - $dbh->{sql_identifier_case} = SQL_IC_LOWER; - $dbh->{f_ext} = '.lst'; - $dbh->{f_dir} = '/data/web/adrmgr'; - -Those settings will result in looking for files matching -C<[Uu][Ss][Ee][Rr](\.lst)?$> in C. The scanning of the -directory C and the pattern match check will be done -in C by the C method. - -If you intend to provide other sources of data streams than files, in -addition to provide an appropriate C method, a method -to open the resource is required: - - package DBI::DBD::SqlEngine::DataSource; - - sub open_data ($) - { - my ( $self, $meta, $attrs, $flags ) = @_; - ... - } - -After the method C has been run successfully, the table's meta -information are in a state which allows the table's data accessor methods -will be able to fetch/store row information. Implementation details heavily -depends on the table implementation, whereby the most famous is surely -L. - -=head2 DBI::DBD::SqlEngine::Statement - -Derives from DBI::SQL::Nano::Statement for unified naming when deriving -new drivers. No additional feature is provided from here. - -=head2 DBI::DBD::SqlEngine::Table - -Derives from DBI::SQL::Nano::Table for unified naming when deriving -new drivers. - -You should consult the documentation of C<< SQL::Eval::Table >> (see -L) to get more information about the abstract methods of the -table's base class you have to override and a description of the table -meta information expected by the SQL engines. - -=over 4 - -=item bootstrap_table_meta - -Initializes a table meta structure. Can be safely overridden in a -derived class, as long as the C<< SUPER >> method is called at the end -of the overridden method. - -It copies the following attributes from the database into the table meta data -C<< $dbh->{ReadOnly} >> into C<< $meta->{readonly} >>, C -and C and makes them sticky to the table. - -This method should be called before you attempt to map between file -name and table name to ensure the correct directory, extension etc. are -used. - -=item init_table_meta - -Initializes more attributes of the table meta data - usually more -expensive ones (e.g. those which require class instantiations) - when -the file name and the table name could mapped. - -=item get_table_meta - -Returns the table meta data. If there are none for the required table, -a new one is initialized. When after bootstrapping a new I -and L a -mapping can be established between an existing I and the -new bootstrapped one, the already existing is used and a mapping -shortcut between the recent used table name and the already known -table name is hold in C<< $dbh->{sql_meta_map} >>. When it fails, -nothing is returned. On success, the name of the table and the meta data -structure is returned. - -=item get_table_meta_attr - -Returns a single attribute from the table meta data. If the attribute -name appears in C<%compat_map>, the attribute name is updated from -there. - -=item set_table_meta_attr - -Sets a single attribute in the table meta data. If the attribute -name appears in C<%compat_map>, the attribute name is updated from -there. - -=item table_meta_attr_changed - -Called when an attribute of the meta data is modified. - -If the modified attribute requires to reset a calculated attribute, the -calculated attribute is reset (deleted from meta data structure) and -the I flag is removed, too. The decision is made based on -C<%register_reset_on_modify>. - -=item register_reset_on_modify - -Allows C to reset meta attributes when special -attributes are modified. For DBD::File, modifying one of C, C, -C or C will reset C. DBD::DBM extends the -list for C and C to reset the value of C. - -If your DBD has calculated values in the meta data area, then call -C: - - my %reset_on_modify = ( "xxx_foo" => "xxx_bar" ); - __PACKAGE__->register_reset_on_modify( \%reset_on_modify ); - -=item register_compat_map - -Allows C and C to update the -attribute name to the current favored one: - - # from DBD::DBM - my %compat_map = ( "dbm_ext" => "f_ext" ); - __PACKAGE__->register_compat_map( \%compat_map ); - -=item open_data - -Called to open the table's data storage. This is silently forwarded -to C<< $meta->{sql_data_source}->open_data() >>. - -After this is done, a derived class might add more steps in an overridden -C<< open_file >> method. - -=item new - -Instantiates the table. This is done in 3 steps: - - 1. get the table meta data - 2. open the data file - 3. bless the table data structure using inherited constructor new - -It is not recommended to override the constructor of the table class. -Find a reasonable place to add you extensions in one of the above four -methods. - -=back - -=head1 AUTHOR - -The module DBI::DBD::SqlEngine is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine/HowTo.pod b/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine/HowTo.pod deleted file mode 100644 index b6c8caa..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/DBD/SqlEngine/HowTo.pod +++ /dev/null @@ -1,333 +0,0 @@ -=head1 NAME - -DBI::DBD::SqlEngine::HowTo - Guide to create DBI::DBD::SqlEngine based driver - -=head1 SYNOPSIS - - perldoc DBI::DBD::SqlEngine::HowTo - perldoc DBI - perldoc DBI::DBD - perldoc DBI::DBD::SqlEngine::Developers - perldoc SQL::Eval - perldoc DBI::DBD::SqlEngine - perldoc DBI::DBD::SqlEngine::HowTo - perldoc SQL::Statement::Embed - -=head1 DESCRIPTION - -This document provides a step-by-step guide, how to create a new -C based DBD. It expects that you carefully read the -L documentation and that you're familiar with L and had -read and understood L. - -This document addresses experienced developers who are really sure that -they need to invest time when writing a new DBI Driver. Writing a DBI -Driver is neither a weekend project nor an easy job for hobby coders -after work. Expect one or two man-month of time for the first start. - -Those who are still reading, should be able to sing the rules of -L. - -=head1 CREATING DRIVER CLASSES - -Do you have an entry in DBI's DBD registry? DBI::DBD::SqlEngine expect -having a unique prefix for every driver class in inheritance chain. - -It's easy to get a prefix - just drop the DBI team a note -(L). If you want for some reason hide your work, take -a look at L how to wrap a private prefix method -around existing C. - -For this guide, a prefix of C is assumed. - -=head2 Sample Skeleton - - package DBD::Foo; - - use strict; - use warnings; - use vars qw($VERSION); - use base qw(DBI::DBD::SqlEngine); - - use DBI (); - - $VERSION = "0.001"; - - package DBD::Foo::dr; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBI::DBD::SqlEngine::dr); - $imp_data_size = 0; - - package DBD::Foo::db; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBI::DBD::SqlEngine::db); - $imp_data_size = 0; - - package DBD::Foo::st; - - use vars qw(@ISA $imp_data_size); - - @ISA = qw(DBI::DBD::SqlEngine::st); - $imp_data_size = 0; - - package DBD::Foo::Statement; - - use vars qw(@ISA); - - @ISA = qw(DBI::DBD::SqlEngine::Statement); - - package DBD::Foo::Table; - - use vars qw(@ISA); - - @ISA = qw(DBI::DBD::SqlEngine::Table); - - 1; - -Tiny, eh? And all you have now is a DBD named foo which will is able to -deal with temporary tables, as long as you use L. In -L environments, this DBD can do nothing. - -=head2 Deal with own attributes - -Before we start doing usable stuff with our DBI driver, we need to think -about what we want to do and how we want to do it. - -Do we need tunable knobs accessible by users? Do we need status -information? All this is handled in attributes of the database handles (be -careful when your DBD is running "behind" a L proxy). - -How come the attributes into the DBD and how are they fetchable by the -user? Good question, but you should know because you've read the L -documentation. - -C and C -taking care for you - all they need to know is which attribute names -are valid and mutable or immutable. Tell them by adding -C to your db class: - - sub init_valid_attributes - { - my $dbh = $_[0]; - - $dbh->SUPER::init_valid_attributes (); - - $dbh->{foo_valid_attrs} = { - foo_version => 1, # contains version of this driver - foo_valid_attrs => 1, # contains the valid attributes of foo drivers - foo_readonly_attrs => 1, # contains immutable attributes of foo drivers - foo_bar => 1, # contains the bar attribute - foo_baz => 1, # contains the baz attribute - foo_manager => 1, # contains the manager of the driver instance - foo_manager_type => 1, # contains the manager class of the driver instance - }; - $dbh->{foo_readonly_attrs} = { - foo_version => 1, # ensure no-one modifies the driver version - foo_valid_attrs => 1, # do not permit one to add more valid attributes ... - foo_readonly_attrs => 1, # ... or make the immutable mutable - foo_manager => 1, # manager is set internally only - }; - - return $dbh; - } - -Woooho - but now the user cannot assign new managers? This is intended, -overwrite C to handle it! - - sub STORE ($$$) - { - my ( $dbh, $attrib, $value ) = @_; - - $dbh->SUPER::STORE( $attrib, $value ); - - # we're still alive, so no exception is thrown ... - # by DBI::DBD::SqlEngine::db::STORE - if ( $attrib eq "foo_manager_type" ) - { - $dbh->{foo_manager} = $dbh->{foo_manager_type}->new(); - # ... probably correct some states based on the new - # foo_manager_type - see DBD::Sys for an example - } - } - -But ... my driver runs without a manager until someone first assignes -a C. Well, no - there're two places where you can -initialize defaults: - - sub init_default_attributes - { - my ($dbh, $phase) = @_; - - $dbh->SUPER::init_default_attributes($phase); - - if( 0 == $phase ) - { - # init all attributes which have no knowledge about - # user settings from DSN or the attribute hash - $dbh->{foo_manager_type} = "DBD::Foo::Manager"; - } - elsif( 1 == $phase ) - { - # init phase with more knowledge from DSN or attribute - # hash - $dbh->{foo_manager} = $dbh->{foo_manager_type}->new(); - } - - return $dbh; - } - -So far we can prevent the users to use our database driver as data -storage for anything and everything. We care only about the real important -stuff for peace on earth and alike attributes. But in fact, the driver -still can't do anything. It can do less than nothing - meanwhile it's -not a stupid storage area anymore. - -=head2 User comfort - -C since C<0.05> consolidates all persistent meta data -of a table into a single structure stored in C<< $dbh->{sql_meta} >>. While -DBI::DBD::SqlEngine provides only readonly access to this structure, -modifications are still allowed. - -Primarily DBI::DBD::SqlEngine provides access via the setters -C, C, C, -C, C and C. -Those methods are easily accessible by the users via the C<< $dbh->func () >> -interface provided by DBI. Well, many users don't feel comfortize when calling - - # don't require extension for tables cars - $dbh->func ("cars", "f_ext", ".csv", "set_sql_engine_meta"); - -DBI::DBD::SqlEngine will inject a method into your driver to increase the -user comfort to allow: - - # don't require extension for tables cars - $dbh->foo_set_meta ("cars", "f_ext", ".csv"); - -Better, but here and there users likes to do: - - # don't require extension for tables cars - $dbh->{foo_tables}->{cars}->{f_ext} = ".csv"; - -This interface is provided when derived DBD's define following in -C (re-capture L): - - sub init_valid_attributes - { - my $dbh = $_[0]; - - $dbh->SUPER::init_valid_attributes (); - - $dbh->{foo_valid_attrs} = { - foo_version => 1, # contains version of this driver - foo_valid_attrs => 1, # contains the valid attributes of foo drivers - foo_readonly_attrs => 1, # contains immutable attributes of foo drivers - foo_bar => 1, # contains the bar attribute - foo_baz => 1, # contains the baz attribute - foo_manager => 1, # contains the manager of the driver instance - foo_manager_type => 1, # contains the manager class of the driver instance - foo_meta => 1, # contains the public interface to modify table meta attributes - }; - $dbh->{foo_readonly_attrs} = { - foo_version => 1, # ensure no-one modifies the driver version - foo_valid_attrs => 1, # do not permit one to add more valid attributes ... - foo_readonly_attrs => 1, # ... or make the immutable mutable - foo_manager => 1, # manager is set internally only - foo_meta => 1, # ensure public interface to modify table meta attributes are immutable - }; - - $dbh->{foo_meta} = "foo_tables"; - - return $dbh; - } - -This provides a tied hash in C<< $dbh->{foo_tables} >> and a tied hash for -each table's meta data in C<< $dbh->{foo_tables}->{$table_name} >>. -Modifications on the table meta attributes are done using the table -methods: - - sub get_table_meta_attr { ... } - sub set_table_meta_attr { ... } - -Both methods can adjust the attribute name for compatibility reasons, e.g. -when former versions of the DBD allowed different names to be used for the -same flag: - - my %compat_map = ( - abc => 'foo_abc', - xyz => 'foo_xyz', - ); - __PACKAGE__->register_compat_map( \%compat_map ); - -If any user modification on a meta attribute needs reinitialization of -the meta structure (in case of C these are the attributes -C, C, C and C), inform DBI::DBD::SqlEngine by -doing - - my %reset_on_modify = ( - foo_xyz => "foo_bar", - foo_abc => "foo_bar", - ); - __PACKAGE__->register_reset_on_modify( \%reset_on_modify ); - -The next access to the table meta data will force DBI::DBD::SqlEngine to re-do the -entire meta initialization process. - -Any further action which needs to be taken can handled in -C: - - sub table_meta_attr_changed - { - my ($class, $meta, $attrib, $value) = @_; - ... - $class->SUPER::table_meta_attr_changed ($meta, $attrib, $value); - } - -This is done before the new value is set in C<$meta>, so the attribute -changed handler can act depending on the old value. - -=head2 Dealing with Tables - -Let's put some life into it - it's going to be time for it. - -This is a good point where a quick side step to L -will help to shorten the next paragraph. The documentation in -SQL::Statement::Embed regarding embedding in own DBD's works pretty -fine with SQL::Statement and DBI::SQL::Nano. - -Second look should go to L to get a -picture over the driver part of the table API. Usually there isn't much -to do for an easy driver. - -=head2 Testing - -Now you should have your first own DBD. Was easy, wasn't it? But does -it work well? Prove it by writing tests and remember to use -dbd_edit_mm_attribs from L to ensure testing even rare cases. - -=head1 AUTHOR - -This guide is written by Jens Rehsack. DBI::DBD::SqlEngine is written by -Jens Rehsack using code from DBD::File originally written by Jochen -Wiedmann and Jeff Zucker. - -The module DBI::DBD::SqlEngine is currently maintained by - -H.Merijn Brand < h.m.brand at xs4all.nl > and -Jens Rehsack < rehsack at googlemail.com > - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack - -All rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, as -specified in the Perl README file. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Execute.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Execute.pm deleted file mode 100644 index 5fdf9b3..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Execute.pm +++ /dev/null @@ -1,900 +0,0 @@ -package DBI::Gofer::Execute; - -# $Id: Execute.pm 14282 2010-07-26 00:12:54Z David $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use Carp; - -use DBI qw(dbi_time); -use DBI::Gofer::Request; -use DBI::Gofer::Response; - -use base qw(DBI::Util::_accessor); - -our $VERSION = "0.014283"; - -our @all_dbh_methods = sort map { keys %$_ } $DBI::DBI_methods{db}, $DBI::DBI_methods{common}; -our %all_dbh_methods = map { $_ => (DBD::_::db->can($_)||undef) } @all_dbh_methods; - -our $local_log = $ENV{DBI_GOFER_LOCAL_LOG}; # do extra logging to stderr - -our $current_dbh; # the dbh we're using for this request - - -# set trace for server-side gofer -# Could use DBI_TRACE env var when it's an unrelated separate process -# but using DBI_GOFER_TRACE makes testing easier for subprocesses (eg stream) -DBI->trace(split /=/, $ENV{DBI_GOFER_TRACE}, 2) if $ENV{DBI_GOFER_TRACE}; - - -# define valid configuration attributes (args to new()) -# the values here indicate the basic type of values allowed -my %configuration_attributes = ( - gofer_execute_class => 1, - default_connect_dsn => 1, - forced_connect_dsn => 1, - default_connect_attributes => {}, - forced_connect_attributes => {}, - track_recent => 1, - check_request_sub => sub {}, - check_response_sub => sub {}, - forced_single_resultset => 1, - max_cached_dbh_per_drh => 1, - max_cached_sth_per_dbh => 1, - forced_response_attributes => {}, - forced_gofer_random => 1, - stats => {}, -); - -__PACKAGE__->mk_accessors( - keys %configuration_attributes -); - - - -sub new { - my ($self, $args) = @_; - $args->{default_connect_attributes} ||= {}; - $args->{forced_connect_attributes} ||= {}; - $args->{max_cached_sth_per_dbh} ||= 1000; - $args->{stats} ||= {}; - return $self->SUPER::new($args); -} - - -sub valid_configuration_attributes { - my $self = shift; - return { %configuration_attributes }; -} - - -my %extra_attr = ( - # Only referenced if the driver doesn't support private_attribute_info method. - # What driver-specific attributes should be returned for the driver being used? - # keyed by $dbh->{Driver}{Name} - # XXX for sth should split into attr specific to resultsets (where NUM_OF_FIELDS > 0) and others - # which would reduce processing/traffic for non-select statements - mysql => { - dbh => [qw( - mysql_errno mysql_error mysql_hostinfo mysql_info mysql_insertid - mysql_protoinfo mysql_serverinfo mysql_stat mysql_thread_id - )], - sth => [qw( - mysql_is_blob mysql_is_key mysql_is_num mysql_is_pri_key mysql_is_auto_increment - mysql_length mysql_max_length mysql_table mysql_type mysql_type_name mysql_insertid - )], - # XXX this dbh_after_sth stuff is a temporary, but important, hack. - # should be done via hash instead of arrays where the hash value contains - # flags that can indicate which attributes need to be handled in this way - dbh_after_sth => [qw( - mysql_insertid - )], - }, - Pg => { - dbh => [qw( - pg_protocol pg_lib_version pg_server_version - pg_db pg_host pg_port pg_default_port - pg_options pg_pid - )], - sth => [qw( - pg_size pg_type pg_oid_status pg_cmd_status - )], - }, - Sybase => { - dbh => [qw( - syb_dynamic_supported syb_oc_version syb_server_version syb_server_version_string - )], - sth => [qw( - syb_types syb_proc_status syb_result_type - )], - }, - SQLite => { - dbh => [qw( - sqlite_version - )], - sth => [qw( - )], - }, - ExampleP => { - dbh => [qw( - examplep_private_dbh_attrib - )], - sth => [qw( - examplep_private_sth_attrib - )], - dbh_after_sth => [qw( - examplep_insertid - )], - }, -); - - -sub _connect { - my ($self, $request) = @_; - - my $stats = $self->{stats}; - - # discard CachedKids from time to time - if (++$stats->{_requests_served} % 1000 == 0 # XXX config? - and my $max_cached_dbh_per_drh = $self->{max_cached_dbh_per_drh} - ) { - my %drivers = DBI->installed_drivers(); - while ( my ($driver, $drh) = each %drivers ) { - next unless my $CK = $drh->{CachedKids}; - next unless keys %$CK > $max_cached_dbh_per_drh; - next if $driver eq 'Gofer'; # ie transport=null when testing - DBI->trace_msg(sprintf "Clearing %d cached dbh from $driver", - scalar keys %$CK, $self->{max_cached_dbh_per_drh}); - $_->{Active} && $_->disconnect for values %$CK; - %$CK = (); - } - } - - # local $ENV{...} can leak, so only do it if required - local $ENV{DBI_AUTOPROXY} if $ENV{DBI_AUTOPROXY}; - - my ($connect_method, $dsn, $username, $password, $attr) = @{ $request->dbh_connect_call }; - $connect_method ||= 'connect_cached'; - $stats->{method_calls_dbh}->{$connect_method}++; - - # delete attributes we don't want to affect the server-side - # (Could just do this on client-side and trust the client. DoS?) - delete @{$attr}{qw(Profile InactiveDestroy AutoInactiveDestroy HandleError HandleSetErr TraceLevel Taint TaintIn TaintOut)}; - - $dsn = $self->forced_connect_dsn || $dsn || $self->default_connect_dsn - or die "No forced_connect_dsn, requested dsn, or default_connect_dsn for request"; - - my $random = $self->{forced_gofer_random} || $ENV{DBI_GOFER_RANDOM} || ''; - - my $connect_attr = { - - # the configured default attributes, if any - %{ $self->default_connect_attributes }, - - # pass username and password as attributes - # then they can be overridden by forced_connect_attributes - Username => $username, - Password => $password, - - # the requested attributes - %$attr, - - # force some attributes the way we'd like them - PrintWarn => $local_log, - PrintError => $local_log, - - # the configured default attributes, if any - %{ $self->forced_connect_attributes }, - - # RaiseError must be enabled - RaiseError => 1, - - # reset Executed flag (of the cached handle) so we can use it to tell - # if errors happened before the main part of the request was executed - Executed => 0, - - # ensure this connect_cached doesn't have the same args as the client - # because that causes subtle issues if in the same process (ie transport=null) - # include pid to avoid problems with forking (ie null transport in mod_perl) - # include gofer-random to avoid random behaviour leaking to other handles - dbi_go_execute_unique => join("|", __PACKAGE__, $$, $random), - }; - - # XXX implement our own private connect_cached method? (with rate-limited ping) - my $dbh = DBI->$connect_method($dsn, undef, undef, $connect_attr); - - $dbh->{ShowErrorStatement} = 1 if $local_log; - - # XXX should probably just be a Callbacks => arg to connect_cached - # with a cache of pre-built callback hooks (memoized, without $self) - if (my $random = $self->{forced_gofer_random} || $ENV{DBI_GOFER_RANDOM}) { - $self->_install_rand_callbacks($dbh, $random); - } - - my $CK = $dbh->{CachedKids}; - if ($CK && keys %$CK > $self->{max_cached_sth_per_dbh}) { - %$CK = (); # clear all statement handles - } - - #$dbh->trace(0); - $current_dbh = $dbh; - return $dbh; -} - - -sub reset_dbh { - my ($self, $dbh) = @_; - $dbh->set_err(undef, undef); # clear any error state -} - - -sub new_response_with_err { - my ($self, $rv, $eval_error, $dbh) = @_; - # this is the usual way to create a response for both success and failure - # capture err+errstr etc and merge in $eval_error ($@) - - my ($err, $errstr, $state) = ($DBI::err, $DBI::errstr, $DBI::state); - - if ($eval_error) { - $err ||= $DBI::stderr || 1; # ensure err is true - if ($errstr) { - $eval_error =~ s/(?: : \s)? \Q$errstr//x if $errstr; - chomp $errstr; - $errstr .= "; $eval_error"; - } - else { - $errstr = $eval_error; - } - } - chomp $errstr if $errstr; - - my $flags; - # (XXX if we ever add transaction support then we'll need to take extra - # steps because the commit/rollback would reset Executed before we get here) - $flags |= GOf_RESPONSE_EXECUTED if $dbh && $dbh->{Executed}; - - my $response = DBI::Gofer::Response->new({ - rv => $rv, - err => $err, - errstr => $errstr, - state => $state, - flags => $flags, - }); - - return $response; -} - - -sub execute_request { - my ($self, $request) = @_; - # should never throw an exception - - DBI->trace_msg("-----> execute_request\n"); - - my @warnings; - local $SIG{__WARN__} = sub { - push @warnings, @_; - warn @_ if $local_log; - }; - - my $response = eval { - - if (my $check_request_sub = $self->check_request_sub) { - $request = $check_request_sub->($request, $self) - or die "check_request_sub failed"; - } - - my $version = $request->version || 0; - die ref($request)." version $version is not supported" - if $version < 0.009116 or $version >= 1; - - ($request->is_sth_request) - ? $self->execute_sth_request($request) - : $self->execute_dbh_request($request); - }; - $response ||= $self->new_response_with_err(undef, $@, $current_dbh); - - if (my $check_response_sub = $self->check_response_sub) { - # not protected with an eval so it can choose to throw an exception - my $new = $check_response_sub->($response, $self, $request); - $response = $new if ref $new; - } - - undef $current_dbh; - - $response->warnings(\@warnings) if @warnings; - DBI->trace_msg("<----- execute_request\n"); - return $response; -} - - -sub execute_dbh_request { - my ($self, $request) = @_; - my $stats = $self->{stats}; - - my $dbh; - my $rv_ref = eval { - $dbh = $self->_connect($request); - my $args = $request->dbh_method_call; # [ wantarray, 'method_name', @args ] - my $wantarray = shift @$args; - my $meth = shift @$args; - $stats->{method_calls_dbh}->{$meth}++; - my @rv = ($wantarray) - ? $dbh->$meth(@$args) - : scalar $dbh->$meth(@$args); - \@rv; - } || []; - my $response = $self->new_response_with_err($rv_ref, $@, $dbh); - - return $response if not $dbh; - - # does this request also want any dbh attributes returned? - if (my $dbh_attributes = $request->dbh_attributes) { - $response->dbh_attributes( $self->gather_dbh_attributes($dbh, $dbh_attributes) ); - } - - if ($rv_ref and my $lid_args = $request->dbh_last_insert_id_args) { - $stats->{method_calls_dbh}->{last_insert_id}++; - my $id = $dbh->last_insert_id( @$lid_args ); - $response->last_insert_id( $id ); - } - - if ($rv_ref and UNIVERSAL::isa($rv_ref->[0],'DBI::st')) { - # dbh_method_call was probably a metadata method like table_info - # that returns a statement handle, so turn the $sth into resultset - my $sth = $rv_ref->[0]; - $response->sth_resultsets( $self->gather_sth_resultsets($sth, $request, $response) ); - $response->rv("(sth)"); # don't try to return actual sth - } - - # we're finished with this dbh for this request - $self->reset_dbh($dbh); - - return $response; -} - - -sub gather_dbh_attributes { - my ($self, $dbh, $dbh_attributes) = @_; - my @req_attr_names = @$dbh_attributes; - if ($req_attr_names[0] eq '*') { # auto include std + private - shift @req_attr_names; - push @req_attr_names, @{ $self->_std_response_attribute_names($dbh) }; - } - my %dbh_attr_values; - @dbh_attr_values{@req_attr_names} = $dbh->FETCH_many(@req_attr_names); - - # XXX piggyback installed_methods onto dbh_attributes for now - $dbh_attr_values{dbi_installed_methods} = { DBI->installed_methods }; - - # XXX piggyback default_methods onto dbh_attributes for now - $dbh_attr_values{dbi_default_methods} = _get_default_methods($dbh); - - return \%dbh_attr_values; -} - - -sub _std_response_attribute_names { - my ($self, $h) = @_; - $h = tied(%$h) || $h; # switch to inner handle - - # cache the private_attribute_info data for each handle - # XXX might be better to cache it in the executor - # as it's unlikely to change - # or perhaps at least cache it in the dbh even for sth - # as the sth are typically very short lived - - my ($dbh, $h_type, $driver_name, @attr_names); - - if ($dbh = $h->{Database}) { # is an sth - - # does the dbh already have the answer cached? - return $dbh->{private_gofer_std_attr_names_sth} if $dbh->{private_gofer_std_attr_names_sth}; - - ($h_type, $driver_name) = ('sth', $dbh->{Driver}{Name}); - push @attr_names, qw(NUM_OF_PARAMS NUM_OF_FIELDS NAME TYPE NULLABLE PRECISION SCALE); - } - else { # is a dbh - return $h->{private_gofer_std_attr_names_dbh} if $h->{private_gofer_std_attr_names_dbh}; - - ($h_type, $driver_name, $dbh) = ('dbh', $h->{Driver}{Name}, $h); - # explicitly add these because drivers may have different defaults - # add Name so the client gets the real Name of the connection - push @attr_names, qw(ChopBlanks LongReadLen LongTruncOk ReadOnly Name); - } - - if (my $pai = $h->private_attribute_info) { - push @attr_names, keys %$pai; - } - else { - push @attr_names, @{ $extra_attr{ $driver_name }{$h_type} || []}; - } - if (my $fra = $self->{forced_response_attributes}) { - push @attr_names, @{ $fra->{ $driver_name }{$h_type} || []} - } - $dbh->trace_msg("_std_response_attribute_names for $driver_name $h_type: @attr_names\n"); - - # cache into the dbh even for sth, as the dbh is usually longer lived - return $dbh->{"private_gofer_std_attr_names_$h_type"} = \@attr_names; -} - - -sub execute_sth_request { - my ($self, $request) = @_; - my $dbh; - my $sth; - my $last_insert_id; - my $stats = $self->{stats}; - - my $rv = eval { - $dbh = $self->_connect($request); - - my $args = $request->dbh_method_call; # [ wantarray, 'method_name', @args ] - shift @$args; # discard wantarray - my $meth = shift @$args; - $stats->{method_calls_sth}->{$meth}++; - $sth = $dbh->$meth(@$args); - my $last = '(sth)'; # a true value (don't try to return actual sth) - - # execute methods on the sth, e.g., bind_param & execute - if (my $calls = $request->sth_method_calls) { - for my $meth_call (@$calls) { - my $method = shift @$meth_call; - $stats->{method_calls_sth}->{$method}++; - $last = $sth->$method(@$meth_call); - } - } - - if (my $lid_args = $request->dbh_last_insert_id_args) { - $stats->{method_calls_sth}->{last_insert_id}++; - $last_insert_id = $dbh->last_insert_id( @$lid_args ); - } - - $last; - }; - my $response = $self->new_response_with_err($rv, $@, $dbh); - - return $response if not $dbh; - - $response->last_insert_id( $last_insert_id ) - if defined $last_insert_id; - - # even if the eval failed we still want to try to gather attribute values - # (XXX would be nice to be able to support streaming of results. - # which would reduce memory usage and latency for large results) - if ($sth) { - $response->sth_resultsets( $self->gather_sth_resultsets($sth, $request, $response) ); - $sth->finish; - } - - # does this request also want any dbh attributes returned? - my $dbh_attr_set; - if (my $dbh_attributes = $request->dbh_attributes) { - $dbh_attr_set = $self->gather_dbh_attributes($dbh, $dbh_attributes); - } - # XXX needs to be integrated with private_attribute_info() etc - if (my $dbh_attr = $extra_attr{$dbh->{Driver}{Name}}{dbh_after_sth}) { - @{$dbh_attr_set}{@$dbh_attr} = $dbh->FETCH_many(@$dbh_attr); - } - $response->dbh_attributes($dbh_attr_set) if $dbh_attr_set && %$dbh_attr_set; - - $self->reset_dbh($dbh); - - return $response; -} - - -sub gather_sth_resultsets { - my ($self, $sth, $request, $response) = @_; - my $resultsets = eval { - - my $attr_names = $self->_std_response_attribute_names($sth); - my $sth_attr = {}; - $sth_attr->{$_} = 1 for @$attr_names; - - # let the client add/remove sth attributes - if (my $sth_result_attr = $request->sth_result_attr) { - $sth_attr->{$_} = $sth_result_attr->{$_} - for keys %$sth_result_attr; - } - my @sth_attr = grep { $sth_attr->{$_} } keys %$sth_attr; - - my $row_count = 0; - my $rs_list = []; - while (1) { - my $rs = $self->fetch_result_set($sth, \@sth_attr); - push @$rs_list, $rs; - if (my $rows = $rs->{rowset}) { - $row_count += @$rows; - } - last if $self->{forced_single_resultset}; - last if !($sth->more_results || $sth->{syb_more_results}); - } - - my $stats = $self->{stats}; - $stats->{rows_returned_total} += $row_count; - $stats->{rows_returned_max} = $row_count - if $row_count > ($stats->{rows_returned_max}||0); - - $rs_list; - }; - $response->add_err(1, $@) if $@; - return $resultsets; -} - - -sub fetch_result_set { - my ($self, $sth, $sth_attr) = @_; - my %meta; - eval { - @meta{ @$sth_attr } = $sth->FETCH_many(@$sth_attr); - # we assume @$sth_attr contains NUM_OF_FIELDS - $meta{rowset} = $sth->fetchall_arrayref() - if (($meta{NUM_OF_FIELDS}||0) > 0); # is SELECT - # the fetchall_arrayref may fail with a 'not executed' kind of error - # because gather_sth_resultsets/fetch_result_set are called even if - # execute() failed, or even if there was no execute() call at all. - # The corresponding error goes into the resultset err, not the top-level - # response err, so in most cases this resultset err is never noticed. - }; - if ($@) { - chomp $@; - $meta{err} = $DBI::err || 1; - $meta{errstr} = $DBI::errstr || $@; - $meta{state} = $DBI::state; - } - return \%meta; -} - - -sub _get_default_methods { - my ($dbh) = @_; - # returns a ref to a hash of dbh method names for methods which the driver - # hasn't overridden i.e., quote(). These don't need to be forwarded via gofer. - my $ImplementorClass = $dbh->{ImplementorClass} or die; - my %default_methods; - for my $method (@all_dbh_methods) { - my $dbi_sub = $all_dbh_methods{$method} || 42; - my $imp_sub = $ImplementorClass->can($method) || 42; - next if $imp_sub != $dbi_sub; - #warn("default $method\n"); - $default_methods{$method} = 1; - } - return \%default_methods; -} - - -# XXX would be nice to make this a generic DBI module -sub _install_rand_callbacks { - my ($self, $dbh, $dbi_gofer_random) = @_; - - my $callbacks = $dbh->{Callbacks} || {}; - my $prev = $dbh->{private_gofer_rand_fail_callbacks} || {}; - - # return if we've already setup this handle with callbacks for these specs - return if (($callbacks->{_dbi_gofer_random_spec}||'') eq $dbi_gofer_random); - #warn "$dbh # $callbacks->{_dbi_gofer_random_spec}"; - $callbacks->{_dbi_gofer_random_spec} = $dbi_gofer_random; - - my ($fail_percent, $fail_err, $delay_percent, $delay_duration, %spec_part, @spec_note); - my @specs = split /,/, $dbi_gofer_random; - for my $spec (@specs) { - if ($spec =~ m/^fail=(-?[.\d]+)%?$/) { - $fail_percent = $1; - $spec_part{fail} = $spec; - next; - } - if ($spec =~ m/^err=(-?\d+)$/) { - $fail_err = $1; - $spec_part{err} = $spec; - next; - } - if ($spec =~ m/^delay([.\d]+)=(-?[.\d]+)%?$/) { - $delay_duration = $1; - $delay_percent = $2; - $spec_part{delay} = $spec; - next; - } - elsif ($spec !~ m/^(\w+|\*)$/) { - warn "Ignored DBI_GOFER_RANDOM item '$spec' which isn't a config or a dbh method name"; - next; - } - - my $method = $spec; - if ($callbacks->{$method} && $prev->{$method} && $callbacks->{$method} != $prev->{$method}) { - warn "Callback for $method method already installed so DBI_GOFER_RANDOM callback not installed\n"; - next; - } - unless (defined $fail_percent or defined $delay_percent) { - warn "Ignored DBI_GOFER_RANDOM item '$spec' because not preceded by 'fail=N' and/or 'delayN=N'"; - next; - } - - push @spec_note, join(",", values(%spec_part), $method); - $callbacks->{$method} = $self->_mk_rand_callback($method, $fail_percent, $delay_percent, $delay_duration, $fail_err); - } - warn "DBI_GOFER_RANDOM failures/delays enabled: @spec_note\n" - if @spec_note; - $dbh->{Callbacks} = $callbacks; - $dbh->{private_gofer_rand_fail_callbacks} = $callbacks; -} - -my %_mk_rand_callback_seqn; - -sub _mk_rand_callback { - my ($self, $method, $fail_percent, $delay_percent, $delay_duration, $fail_err) = @_; - my ($fail_modrate, $delay_modrate); - $fail_percent ||= 0; $fail_modrate = int(1/(-$fail_percent )*100) if $fail_percent; - $delay_percent ||= 0; $delay_modrate = int(1/(-$delay_percent)*100) if $delay_percent; - # note that $method may be "*" but that's not recommended or documented or wise - return sub { - my ($h) = @_; - my $seqn = ++$_mk_rand_callback_seqn{$method}; - my $delay = ($delay_percent > 0) ? rand(100) < $delay_percent : - ($delay_percent < 0) ? !($seqn % $delay_modrate): 0; - my $fail = ($fail_percent > 0) ? rand(100) < $fail_percent : - ($fail_percent < 0) ? !($seqn % $fail_modrate) : 0; - #no warnings 'uninitialized'; - #warn "_mk_rand_callback($fail_percent:$fail_modrate, $delay_percent:$delay_modrate): seqn=$seqn fail=$fail delay=$delay"; - if ($delay) { - my $msg = "DBI_GOFER_RANDOM delaying execution of $method() by $delay_duration seconds\n"; - # Note what's happening in a trace message. If the delay percent is an even - # number then use warn() instead so it's sent back to the client. - ($delay_percent % 2 == 1) ? warn($msg) : $h->trace_msg($msg); - select undef, undef, undef, $delay_duration; # allows floating point value - } - if ($fail) { - undef $_; # tell DBI to not call the method - # the "induced by DBI_GOFER_RANDOM" is special and must be included in errstr - # as it's checked for in a few places, such as the gofer retry logic - return $h->set_err($fail_err || $DBI::stderr, - "fake error from $method method induced by DBI_GOFER_RANDOM env var ($fail_percent%)"); - } - return; - } -} - - -sub update_stats { - my ($self, - $request, $response, - $frozen_request, $frozen_response, - $time_received, - $store_meta, $other_meta, - ) = @_; - - # should always have a response object here - carp("No response object provided") unless $request; - - my $stats = $self->{stats}; - $stats->{frozen_request_max_bytes} = length($frozen_request) - if $frozen_request - && length($frozen_request) > ($stats->{frozen_request_max_bytes}||0); - $stats->{frozen_response_max_bytes} = length($frozen_response) - if $frozen_response - && length($frozen_response) > ($stats->{frozen_response_max_bytes}||0); - - my $recent; - if (my $track_recent = $self->{track_recent}) { - $recent = { - request => $frozen_request, - response => $frozen_response, - time_received => $time_received, - duration => dbi_time()-$time_received, - # for any other info - ($store_meta) ? (meta => $store_meta) : (), - }; - $recent->{request_object} = $request - if !$frozen_request && $request; - $recent->{response_object} = $response - if !$frozen_response; - my @queues = ($stats->{recent_requests} ||= []); - push @queues, ($stats->{recent_errors} ||= []) - if !$response or $response->err; - for my $queue (@queues) { - push @$queue, $recent; - shift @$queue if @$queue > $track_recent; - } - } - return $recent; -} - - -1; -__END__ - -=head1 NAME - -DBI::Gofer::Execute - Executes Gofer requests and returns Gofer responses - -=head1 SYNOPSIS - - $executor = DBI::Gofer::Execute->new( { ...config... }); - - $response = $executor->execute_request( $request ); - -=head1 DESCRIPTION - -Accepts a DBI::Gofer::Request object, executes the requested DBI method calls, -and returns a DBI::Gofer::Response object. - -Any error, including any internal 'fatal' errors are caught and converted into -a DBI::Gofer::Response object. - -This module is usually invoked by a 'server-side' Gofer transport module. -They usually have names in the "C" namespace. -Examples include: L and L. - -=head1 CONFIGURATION - -=head2 check_request_sub - -If defined, it must be a reference to a subroutine that will 'check' the request. -It is passed the request object and the executor as its only arguments. - -The subroutine can either return the original request object or die with a -suitable error message (which will be turned into a Gofer response). - -It can also construct and return a new request that should be executed instead -of the original request. - -=head2 check_response_sub - -If defined, it must be a reference to a subroutine that will 'check' the response. -It is passed the response object, the executor, and the request object. -The sub may alter the response object and return undef, or return a new response object. - -This mechanism can be used to, for example, terminate the service if specific -database errors are seen. - -=head2 forced_connect_dsn - -If set, this DSN is always used instead of the one in the request. - -=head2 default_connect_dsn - -If set, this DSN is used if C is not set and the request does not contain a DSN itself. - -=head2 forced_connect_attributes - -A reference to a hash of connect() attributes. Individual attributes in -C will take precedence over corresponding attributes -in the request. - -=head2 default_connect_attributes - -A reference to a hash of connect() attributes. Individual attributes in the -request take precedence over corresponding attributes in C. - -=head2 max_cached_dbh_per_drh - -If set, the loaded drivers will be checked to ensure they don't have more than -this number of cached connections. There is no default value. This limit is not -enforced for every request. - -=head2 max_cached_sth_per_dbh - -If set, all the cached statement handles will be cleared once the number of -cached statement handles rises above this limit. The default is 1000. - -=head2 forced_single_resultset - -If true, then only the first result set will be fetched and returned in the response. - -=head2 forced_response_attributes - -A reference to a data structure that can specify extra attributes to be returned in responses. - - forced_response_attributes => { - DriverName => { - dbh => [ qw(dbh_attrib_name) ], - sth => [ qw(sth_attrib_name) ], - }, - }, - -This can be useful in cases where the driver has not implemented the -private_attribute_info() method and DBI::Gofer::Execute's own fallback list of -private attributes doesn't include the driver or attributes you need. - -=head2 track_recent - -If set, specifies the number of recent requests and responses that should be -kept by the update_stats() method for diagnostics. See L. - -Note that this setting can significantly increase memory use. Use with caution. - -=head2 forced_gofer_random - -Enable forced random failures and/or delays for testing. See L below. - -=head1 DRIVER-SPECIFIC ISSUES - -Gofer needs to know about any driver-private attributes that should have their -values sent back to the client. - -If the driver doesn't support private_attribute_info() method, and very few do, -then the module fallsback to using some hard-coded details, if available, for -the driver being used. Currently hard-coded details are available for the -mysql, Pg, Sybase, and SQLite drivers. - -=head1 TESTING - -DBD::Gofer, DBD::Execute and related packages are well tested by executing the -DBI test suite with DBI_AUTOPROXY configured to route all DBI calls via DBD::Gofer. - -Because Gofer includes timeout and 'retry on error' mechanisms there is a need -for some way to trigger delays and/or errors. This can be done via the -C configuration item, or else the DBI_GOFER_RANDOM environment -variable. - -=head2 DBI_GOFER_RANDOM - -The value of the C configuration item (or else the -DBI_GOFER_RANDOM environment variable) is treated as a series of tokens -separated by commas. - -The tokens can be one of three types: - -=over 4 - -=item fail=R% - -Set the current failure rate to R where R is a percentage. -The value R can be floating point, e.g., C. -Negative values for R have special meaning, see below. - -=item err=N - -Sets the current failure err value to N (instead of the DBI's default 'standard -err value' of 2000000000). This is useful when you want to simulate a -specific error. - -=item delayN=R% - -Set the current random delay rate to R where R is a percentage, and set the -current delay duration to N seconds. The values of R and N can be floating point, -e.g., C. Negative values for R have special meaning, see below. - -If R is an odd number (R % 2 == 1) then a message is logged via warn() which -will be returned to, and echoed at, the client. - -=item methodname - -Applies the current fail, err, and delay values to the named method. -If neither a fail nor delay have been set yet then a warning is generated. - -=back - -For example: - - $executor = DBI::Gofer::Execute->new( { - forced_gofer_random => "fail=0.01%,do,delay60=1%,execute", - }); - -will cause the do() method to fail for 0.01% of calls, and the execute() method to -fail 0.01% of calls and be delayed by 60 seconds on 1% of calls. - -If the percentage value (C) is negative then instead of the failures being -triggered randomly (via the rand() function) they are triggered via a sequence -number. In other words "C" will mean every fifth call will fail. -Each method has a distinct sequence number. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Request.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Request.pm deleted file mode 100644 index 1b64748..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Request.pm +++ /dev/null @@ -1,200 +0,0 @@ -package DBI::Gofer::Request; - -# $Id: Request.pm 12536 2009-02-24 22:37:09Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; - -use DBI qw(neat neat_list); - -use base qw(DBI::Util::_accessor); - -our $VERSION = "0.012537"; - -use constant GOf_REQUEST_IDEMPOTENT => 0x0001; -use constant GOf_REQUEST_READONLY => 0x0002; - -our @EXPORT = qw(GOf_REQUEST_IDEMPOTENT GOf_REQUEST_READONLY); - - -__PACKAGE__->mk_accessors(qw( - version - flags - dbh_connect_call - dbh_method_call - dbh_attributes - dbh_last_insert_id_args - sth_method_calls - sth_result_attr -)); -__PACKAGE__->mk_accessors_using(make_accessor_autoviv_hashref => qw( - meta -)); - - -sub new { - my ($self, $args) = @_; - $args->{version} ||= $VERSION; - return $self->SUPER::new($args); -} - - -sub reset { - my ($self, $flags) = @_; - # remove everything except connect and version - %$self = ( - version => $self->{version}, - dbh_connect_call => $self->{dbh_connect_call}, - ); - $self->{flags} = $flags if $flags; -} - - -sub init_request { - my ($self, $method_and_args, $dbh) = @_; - $self->reset( $dbh->{ReadOnly} ? GOf_REQUEST_READONLY : 0 ); - $self->dbh_method_call($method_and_args); -} - - -sub is_sth_request { - return shift->{sth_result_attr}; -} - - -sub statements { - my $self = shift; - my @statements; - if (my $dbh_method_call = $self->dbh_method_call) { - my $statement_method_regex = qr/^(?:do|prepare)$/; - my (undef, $method, $arg1) = @$dbh_method_call; - push @statements, $arg1 if $method && $method =~ $statement_method_regex; - } - return @statements; -} - - -sub is_idempotent { - my $self = shift; - - if (my $flags = $self->flags) { - return 1 if $flags & (GOf_REQUEST_IDEMPOTENT|GOf_REQUEST_READONLY); - } - - # else check if all statements are SELECT statement that don't include FOR UPDATE - my @statements = $self->statements; - # XXX this is very minimal for now, doesn't even allow comments before the select - # (and can't ever work for "exec stored_procedure_name" kinds of statements) - # XXX it also doesn't deal with multiple statements: prepare("select foo; update bar") - return 1 if @statements == grep { - m/^ \s* SELECT \b /xmsi && !m/ \b FOR \s+ UPDATE \b /xmsi - } @statements; - - return 0; -} - - -sub summary_as_text { - my $self = shift; - my ($context) = @_; - my @s = ''; - - if ($context && %$context) { - my @keys = sort keys %$context; - push @s, join(", ", map { "$_=>".$context->{$_} } @keys); - } - - my ($method, $dsn, $user, $pass, $attr) = @{ $self->dbh_connect_call }; - $method ||= 'connect_cached'; - $pass = '***' if defined $pass; - my $tmp = ''; - if ($attr) { - $tmp = { %{$attr||{}} }; # copy so we can edit - $tmp->{Password} = '***' if exists $tmp->{Password}; - $tmp = "{ ".neat_list([ %$tmp ])." }"; - } - push @s, sprintf "dbh= $method(%s, %s)", neat_list([$dsn, $user, $pass]), $tmp; - - if (my $flags = $self->flags) { - push @s, sprintf "flags: 0x%x", $flags; - } - - if (my $dbh_attr = $self->dbh_attributes) { - push @s, sprintf "dbh->FETCH: %s", @$dbh_attr - if @$dbh_attr; - } - - my ($wantarray, $meth, @args) = @{ $self->dbh_method_call }; - my $args = neat_list(\@args); - $args =~ s/\n+/ /g; - push @s, sprintf "dbh->%s(%s)", $meth, $args; - - if (my $lii_args = $self->dbh_last_insert_id_args) { - push @s, sprintf "dbh->last_insert_id(%s)", neat_list($lii_args); - } - - for my $call (@{ $self->sth_method_calls || [] }) { - my ($meth, @args) = @$call; - ($args = neat_list(\@args)) =~ s/\n+/ /g; - push @s, sprintf "sth->%s(%s)", $meth, $args; - } - - if (my $sth_attr = $self->sth_result_attr) { - push @s, sprintf "sth->FETCH: %s", %$sth_attr - if %$sth_attr; - } - - return join("\n\t", @s) . "\n"; -} - - -sub outline_as_text { # one-line version of summary_as_text - my $self = shift; - my @s = ''; - my $neatlen = 80; - - if (my $flags = $self->flags) { - push @s, sprintf "flags=0x%x", $flags; - } - - my (undef, $meth, @args) = @{ $self->dbh_method_call }; - push @s, sprintf "%s(%s)", $meth, neat_list(\@args, $neatlen); - - for my $call (@{ $self->sth_method_calls || [] }) { - my ($meth, @args) = @$call; - push @s, sprintf "%s(%s)", $meth, neat_list(\@args, $neatlen); - } - - my ($method, $dsn) = @{ $self->dbh_connect_call }; - push @s, "$method($dsn,...)"; # dsn last as it's usually less interesting - - (my $outline = join("; ", @s)) =~ s/\s+/ /g; # squish whitespace, incl newlines - return $outline; -} - -1; - -=head1 NAME - -DBI::Gofer::Request - Encapsulate a request from DBD::Gofer to DBI::Gofer::Execute - -=head1 DESCRIPTION - -This is an internal class. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Response.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Response.pm deleted file mode 100644 index 24915b6..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Response.pm +++ /dev/null @@ -1,218 +0,0 @@ -package DBI::Gofer::Response; - -# $Id: Response.pm 11565 2008-07-22 20:17:33Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; - -use Carp; -use DBI qw(neat neat_list); - -use base qw(DBI::Util::_accessor Exporter); - -our $VERSION = "0.011566"; - -use constant GOf_RESPONSE_EXECUTED => 0x0001; - -our @EXPORT = qw(GOf_RESPONSE_EXECUTED); - - -__PACKAGE__->mk_accessors(qw( - version - rv - err - errstr - state - flags - last_insert_id - dbh_attributes - sth_resultsets - warnings -)); -__PACKAGE__->mk_accessors_using(make_accessor_autoviv_hashref => qw( - meta -)); - - -sub new { - my ($self, $args) = @_; - $args->{version} ||= $VERSION; - chomp $args->{errstr} if $args->{errstr}; - return $self->SUPER::new($args); -} - - -sub err_errstr_state { - my $self = shift; - return @{$self}{qw(err errstr state)}; -} - -sub executed_flag_set { - my $flags = shift->flags - or return 0; - return $flags & GOf_RESPONSE_EXECUTED; -} - - -sub add_err { - my ($self, $err, $errstr, $state, $trace) = @_; - - # acts like the DBI's set_err method. - # this code copied from DBI::PurePerl's set_err method. - - chomp $errstr if $errstr; - $state ||= ''; - carp ref($self)."->add_err($err, $errstr, $state)" - if $trace and defined($err) || $errstr; - - my ($r_err, $r_errstr, $r_state) = ($self->{err}, $self->{errstr}, $self->{state}); - - if ($r_errstr) { - $r_errstr .= sprintf " [err was %s now %s]", $r_err, $err - if $r_err && $err && $r_err ne $err; - $r_errstr .= sprintf " [state was %s now %s]", $r_state, $state - if $r_state and $r_state ne "S1000" && $state && $r_state ne $state; - $r_errstr .= "\n$errstr" if $r_errstr ne $errstr; - } - else { - $r_errstr = $errstr; - } - - # assign if higher priority: err > "0" > "" > undef - my $err_changed; - if ($err # new error: so assign - or !defined $r_err # no existing warn/info: so assign - # new warn ("0" len 1) > info ("" len 0): so assign - or defined $err && length($err) > length($r_err) - ) { - $r_err = $err; - ++$err_changed; - } - - $r_state = ($state eq "00000") ? "" : $state - if $state && $err_changed; - - ($self->{err}, $self->{errstr}, $self->{state}) = ($r_err, $r_errstr, $r_state); - - return undef; -} - - -sub summary_as_text { - my $self = shift; - my ($context) = @_; - - my ($rv, $err, $errstr, $state) = ($self->{rv}, $self->{err}, $self->{errstr}, $self->{state}); - - my @s = sprintf("\trv=%s", (ref $rv) ? "[".neat_list($rv)."]" : neat($rv)); - $s[-1] .= sprintf(", err=%s, errstr=%s", $err, neat($errstr)) - if defined $err; - $s[-1] .= sprintf(", flags=0x%x", $self->{flags}) - if defined $self->{flags}; - - push @s, "last_insert_id=%s", $self->last_insert_id - if defined $self->last_insert_id; - - if (my $dbh_attr = $self->dbh_attributes) { - my @keys = sort keys %$dbh_attr; - push @s, sprintf "dbh= { %s }", join(", ", map { "$_=>".neat($dbh_attr->{$_},100) } @keys) - if @keys; - } - - for my $rs (@{$self->sth_resultsets || []}) { - my ($rowset, $err, $errstr, $state) - = @{$rs}{qw(rowset err errstr state)}; - my $summary = "rowset: "; - my $NUM_OF_FIELDS = $rs->{NUM_OF_FIELDS} || 0; - my $rows = $rowset ? @$rowset : 0; - if ($rowset || $NUM_OF_FIELDS > 0) { - $summary .= sprintf "%d rows, %d columns", $rows, $NUM_OF_FIELDS; - } - $summary .= sprintf ", err=%s, errstr=%s", $err, neat($errstr) if defined $err; - if ($rows) { - my $NAME = $rs->{NAME}; - # generate - my @colinfo = map { "$NAME->[$_]=".neat($rowset->[0][$_], 30) } 0..@{$NAME}-1; - $summary .= sprintf " [%s]", join ", ", @colinfo; - $summary .= ",..." if $rows > 1; - # we can be a little more helpful for Sybase/MSSQL user - $summary .= " syb_result_type=$rs->{syb_result_type}" - if $rs->{syb_result_type} and $rs->{syb_result_type} != 4040; - } - push @s, $summary; - } - for my $w (@{$self->warnings || []}) { - chomp $w; - push @s, "warning: $w"; - } - if ($context && %$context) { - my @keys = sort keys %$context; - push @s, join(", ", map { "$_=>".$context->{$_} } @keys); - } - return join("\n\t", @s). "\n"; -} - - -sub outline_as_text { # one-line version of summary_as_text - my $self = shift; - my ($context) = @_; - - my ($rv, $err, $errstr, $state) = ($self->{rv}, $self->{err}, $self->{errstr}, $self->{state}); - - my $s = sprintf("rv=%s", (ref $rv) ? "[".neat_list($rv)."]" : neat($rv)); - $s .= sprintf(", err=%s %s", $err, neat($errstr)) - if defined $err; - $s .= sprintf(", flags=0x%x", $self->{flags}) - if $self->{flags}; - - if (my $sth_resultsets = $self->sth_resultsets) { - $s .= sprintf(", %d resultsets ", scalar @$sth_resultsets); - - my @rs; - for my $rs (@{$self->sth_resultsets || []}) { - my $summary = ""; - my ($rowset, $err, $errstr) - = @{$rs}{qw(rowset err errstr)}; - my $NUM_OF_FIELDS = $rs->{NUM_OF_FIELDS} || 0; - my $rows = $rowset ? @$rowset : 0; - if ($rowset || $NUM_OF_FIELDS > 0) { - $summary .= sprintf "%dr x %dc", $rows, $NUM_OF_FIELDS; - } - $summary .= sprintf "%serr %s %s", ($summary?", ":""), $err, neat($errstr) - if defined $err; - push @rs, $summary; - } - $s .= join "; ", map { "[$_]" } @rs; - } - - return $s; -} - - -1; - -=head1 NAME - -DBI::Gofer::Response - Encapsulate a response from DBI::Gofer::Execute to DBD::Gofer - -=head1 DESCRIPTION - -This is an internal class. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/Base.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/Base.pm deleted file mode 100644 index 84f4fdc..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/Base.pm +++ /dev/null @@ -1,64 +0,0 @@ -package DBI::Gofer::Serializer::Base; - -# $Id: Base.pm 9949 2007-09-18 09:38:15Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -=head1 NAME - -DBI::Gofer::Serializer::Base - base class for Gofer serialization - -=head1 SYNOPSIS - - $serializer = $serializer_class->new(); - - $string = $serializer->serialize( $data ); - ($string, $deserializer_class) = $serializer->serialize( $data ); - - $data = $serializer->deserialize( $string ); - -=head1 DESCRIPTION - -DBI::Gofer::Serializer::* classes implement a very minimal subset of the L API. - -Gofer serializers are expected to be very fast and are not required to deal -with anything other than non-blessed references to arrays and hashes, and plain scalars. - -=cut - - -use strict; -use warnings; - -use Carp qw(croak); - -our $VERSION = "0.009950"; - - -sub new { - my $class = shift; - my $deserializer_class = $class->deserializer_class; - return bless { deserializer_class => $deserializer_class } => $class; -} - -sub deserializer_class { - my $self = shift; - my $class = ref($self) || $self; - $class =~ s/^DBI::Gofer::Serializer:://; - return $class; -} - -sub serialize { - my $self = shift; - croak ref($self)." has not implemented the serialize method"; -} - -sub deserialize { - my $self = shift; - croak ref($self)." has not implemented the deserialize method"; -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/DataDumper.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/DataDumper.pm deleted file mode 100644 index f374196..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/DataDumper.pm +++ /dev/null @@ -1,53 +0,0 @@ -package DBI::Gofer::Serializer::DataDumper; - -use strict; -use warnings; - -our $VERSION = "0.009950"; - -# $Id: DataDumper.pm 9949 2007-09-18 09:38:15Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -=head1 NAME - -DBI::Gofer::Serializer::DataDumper - Gofer serialization using DataDumper - -=head1 SYNOPSIS - - $serializer = DBI::Gofer::Serializer::DataDumper->new(); - - $string = $serializer->serialize( $data ); - -=head1 DESCRIPTION - -Uses DataDumper to serialize. Deserialization is not supported. -The output of this class is only meant for human consumption. - -See also L. - -=cut - -use Data::Dumper; - -use base qw(DBI::Gofer::Serializer::Base); - - -sub serialize { - my $self = shift; - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Terse = 1; - local $Data::Dumper::Useqq = 0; # enabling this disables xs - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - local $Data::Dumper::Deparse = 0; - local $Data::Dumper::Purity = 0; - my $frozen = Data::Dumper::Dumper(shift); - return $frozen unless wantarray; - return ($frozen, $self->{deserializer_class}); -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/Storable.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/Storable.pm deleted file mode 100644 index 9d03de0..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Serializer/Storable.pm +++ /dev/null @@ -1,60 +0,0 @@ -package DBI::Gofer::Serializer::Storable; - -use strict; -use warnings; - -use base qw(DBI::Gofer::Serializer::Base); - -# $Id: Storable.pm 15585 2013-03-22 20:31:22Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -=head1 NAME - -DBI::Gofer::Serializer::Storable - Gofer serialization using Storable - -=head1 SYNOPSIS - - $serializer = DBI::Gofer::Serializer::Storable->new(); - - $string = $serializer->serialize( $data ); - ($string, $deserializer_class) = $serializer->serialize( $data ); - - $data = $serializer->deserialize( $string ); - -=head1 DESCRIPTION - -Uses Storable::nfreeze() to serialize and Storable::thaw() to deserialize. - -The serialize() method sets local $Storable::forgive_me = 1; so it doesn't -croak if it encounters any data types that can't be serialized, such as code refs. - -See also L. - -=cut - -use Storable qw(nfreeze thaw); - -our $VERSION = "0.015586"; - -use base qw(DBI::Gofer::Serializer::Base); - - -sub serialize { - my $self = shift; - local $Storable::forgive_me = 1; # for CODE refs etc - local $Storable::canonical = 1; # for go_cache - my $frozen = nfreeze(shift); - return $frozen unless wantarray; - return ($frozen, $self->{deserializer_class}); -} - -sub deserialize { - my $self = shift; - return thaw(shift); -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/Base.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/Base.pm deleted file mode 100644 index 08a5f3b..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/Base.pm +++ /dev/null @@ -1,174 +0,0 @@ -package DBI::Gofer::Transport::Base; - -# $Id: Base.pm 12536 2009-02-24 22:37:09Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use DBI; - -use base qw(DBI::Util::_accessor); - -use DBI::Gofer::Serializer::Storable; -use DBI::Gofer::Serializer::DataDumper; - -our $VERSION = "0.012537"; - -__PACKAGE__->mk_accessors(qw( - trace - keep_meta_frozen - serializer_obj -)); - - -# see also $ENV{DBI_GOFER_TRACE} in DBI::Gofer::Execute -sub _init_trace { (split(/=/,$ENV{DBI_GOFER_TRACE}||0))[0] } - - -sub new { - my ($class, $args) = @_; - $args->{trace} ||= $class->_init_trace; - $args->{serializer_obj} ||= DBI::Gofer::Serializer::Storable->new(); - my $self = bless {}, $class; - $self->$_( $args->{$_} ) for keys %$args; - $self->trace_msg("$class->new({ @{[ %$args ]} })\n") if $self->trace; - return $self; -} - -my $packet_header_text = "GoFER1:"; -my $packet_header_regex = qr/^GoFER(\d+):/; - - -sub _freeze_data { - my ($self, $data, $serializer, $skip_trace) = @_; - my $frozen = eval { - $self->_dump("freezing $self->{trace} ".ref($data), $data) - if !$skip_trace and $self->trace; - - local $data->{meta}; # don't include meta in serialization - $serializer ||= $self->{serializer_obj}; - my ($data, $deserializer_class) = $serializer->serialize($data); - - $packet_header_text . $data; - }; - if ($@) { - chomp $@; - die "Error freezing ".ref($data)." object: $@"; - } - - # stash the frozen data into the data structure itself - # to make life easy for the client caching code in DBD::Gofer::Transport::Base - $data->{meta}{frozen} = $frozen if $self->keep_meta_frozen; - - return $frozen; -} -# public aliases used by subclasses -*freeze_request = \&_freeze_data; -*freeze_response = \&_freeze_data; - - -sub _thaw_data { - my ($self, $frozen_data, $serializer, $skip_trace) = @_; - my $data; - eval { - # check for and extract our gofer header and the info it contains - (my $frozen = $frozen_data) =~ s/$packet_header_regex//o - or die "does not have gofer header\n"; - my ($t_version) = $1; - $serializer ||= $self->{serializer_obj}; - $data = $serializer->deserialize($frozen); - die ref($serializer)."->deserialize didn't return a reference" - unless ref $data; - $data->{_transport}{version} = $t_version; - - $data->{meta}{frozen} = $frozen_data if $self->keep_meta_frozen; - }; - if ($@) { - chomp(my $err = $@); - # remove extra noise from Storable - $err =~ s{ at \S+?/Storable.pm \(autosplit into \S+?/Storable/thaw.al\) line \d+(, \S+ line \d+)?}{}; - my $msg = sprintf "Error thawing: %s (data=%s)", $err, DBI::neat($frozen_data,50); - Carp::cluck("$msg, pid $$ stack trace follows:"); # XXX if $self->trace; - die $msg; - } - $self->_dump("thawing $self->{trace} ".ref($data), $data) - if !$skip_trace and $self->trace; - - return $data; -} -# public aliases used by subclasses -*thaw_request = \&_thaw_data; -*thaw_response = \&_thaw_data; - - -# this should probably live in the request and response classes -# and the tace level passed in -sub _dump { - my ($self, $label, $data) = @_; - - # don't dump the binary - local $data->{meta}{frozen} if $data->{meta} && $data->{meta}{frozen}; - - my $trace_level = $self->trace; - my $summary; - if ($trace_level >= 4) { - require Data::Dumper; - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Terse = 1; - local $Data::Dumper::Useqq = 0; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - local $Data::Dumper::Deparse = 0; - local $Data::Dumper::Purity = 0; - $summary = Data::Dumper::Dumper($data); - } - elsif ($trace_level >= 2) { - $summary = eval { $data->summary_as_text } || $@ || "no summary available\n"; - } - else { - $summary = eval { $data->outline_as_text."\n" } || $@ || "no summary available\n"; - } - $self->trace_msg("$label: $summary"); -} - - -sub trace_msg { - my ($self, $msg, $min_level) = @_; - $min_level = 1 unless defined $min_level; - # transport trace level can override DBI's trace level - $min_level = 0 if $self->trace >= $min_level; - return DBI->trace_msg("gofer ".$msg, $min_level); -} - -1; - -=head1 NAME - -DBI::Gofer::Transport::Base - Base class for Gofer transports - -=head1 DESCRIPTION - -This is the base class for server-side Gofer transports. - -It's also the base class for the client-side base class L. - -This is an internal class. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/pipeone.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/pipeone.pm deleted file mode 100644 index 0d6985e..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/pipeone.pm +++ /dev/null @@ -1,64 +0,0 @@ -package DBI::Gofer::Transport::pipeone; - -# $Id: pipeone.pm 12536 2009-02-24 22:37:09Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use DBI::Gofer::Execute; - -use base qw(DBI::Gofer::Transport::Base Exporter); - -our $VERSION = "0.012537"; - -our @EXPORT = qw(run_one_stdio); - -my $executor = DBI::Gofer::Execute->new(); - -sub run_one_stdio { - - binmode STDIN; - binmode STDOUT; - - my $transport = DBI::Gofer::Transport::pipeone->new(); - - my $frozen_request = do { local $/; }; - - my $response = $executor->execute_request( $transport->thaw_request($frozen_request) ); - - my $frozen_response = $transport->freeze_response($response); - - print $frozen_response; - - # no point calling $executor->update_stats(...) for pipeONE -} - -1; -__END__ - -=head1 NAME - -DBI::Gofer::Transport::pipeone - DBD::Gofer server-side transport for pipeone - -=head1 SYNOPSIS - -See L. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut - diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/stream.pm b/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/stream.pm deleted file mode 100644 index 24b0ba6..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Gofer/Transport/stream.pm +++ /dev/null @@ -1,76 +0,0 @@ -package DBI::Gofer::Transport::stream; - -# $Id: stream.pm 12536 2009-02-24 22:37:09Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -use DBI qw(dbi_time); -use DBI::Gofer::Execute; - -use base qw(DBI::Gofer::Transport::pipeone Exporter); - -our $VERSION = "0.012537"; - -our @EXPORT = qw(run_stdio_hex); - -my $executor = DBI::Gofer::Execute->new(); - -sub run_stdio_hex { - - my $transport = DBI::Gofer::Transport::stream->new(); - local $| = 1; - - DBI->trace_msg("$0 started (pid $$)\n"); - - local $\; # OUTPUT_RECORD_SEPARATOR - local $/ = "\012"; # INPUT_RECORD_SEPARATOR - while ( defined( my $encoded_request = ) ) { - my $time_received = dbi_time(); - $encoded_request =~ s/\015?\012$//; - - my $frozen_request = pack "H*", $encoded_request; - my $request = $transport->thaw_request( $frozen_request ); - - my $response = $executor->execute_request( $request ); - - my $frozen_response = $transport->freeze_response($response); - my $encoded_response = unpack "H*", $frozen_response; - - print $encoded_response, "\015\012"; # autoflushed due to $|=1 - - # there's no way to access the stats currently - # so this just serves as a basic test and illustration of update_stats() - $executor->update_stats($request, $response, $frozen_request, $frozen_response, $time_received, 1); - } - DBI->trace_msg("$0 ending (pid $$)\n"); -} - -1; -__END__ - -=head1 NAME - -DBI::Gofer::Transport::stream - DBD::Gofer server-side transport for stream - -=head1 SYNOPSIS - -See L. - -=head1 AUTHOR - -Tim Bunce, L - -=head1 LICENCE AND COPYRIGHT - -Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. - -This module is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. See L. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Profile.pm b/dbLifeLog/DBI-1.641/lib/DBI/Profile.pm deleted file mode 100644 index f2cc886..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Profile.pm +++ /dev/null @@ -1,954 +0,0 @@ -package DBI::Profile; - -=head1 NAME - -DBI::Profile - Performance profiling and benchmarking for the DBI - -=head1 SYNOPSIS - -The easiest way to enable DBI profiling is to set the DBI_PROFILE -environment variable to 2 and then run your code as usual: - - DBI_PROFILE=2 prog.pl - -This will profile your program and then output a textual summary -grouped by query when the program exits. You can also enable profiling by -setting the Profile attribute of any DBI handle: - - $dbh->{Profile} = 2; - -Then the summary will be printed when the handle is destroyed. - -Many other values apart from are possible - see L<"ENABLING A PROFILE"> below. - -=head1 DESCRIPTION - -The DBI::Profile module provides a simple interface to collect and -report performance and benchmarking data from the DBI. - -For a more elaborate interface, suitable for larger programs, see -L and L. -For Apache/mod_perl applications see -L. - -=head1 OVERVIEW - -Performance data collection for the DBI is built around several -concepts which are important to understand clearly. - -=over 4 - -=item Method Dispatch - -Every method call on a DBI handle passes through a single 'dispatch' -function which manages all the common aspects of DBI method calls, -such as handling the RaiseError attribute. - -=item Data Collection - -If profiling is enabled for a handle then the dispatch code takes -a high-resolution timestamp soon after it is entered. Then, after -calling the appropriate method and just before returning, it takes -another high-resolution timestamp and calls a function to record -the information. That function is passed the two timestamps -plus the DBI handle and the name of the method that was called. -That data about a single DBI method call is called a I. - -=item Data Filtering - -If the method call was invoked by the DBI or by a driver then the call is -ignored for profiling because the time spent will be accounted for by the -original 'outermost' call for your code. - -For example, the calls that the selectrow_arrayref() method makes -to prepare() and execute() etc. are not counted individually -because the time spent in those methods is going to be allocated -to the selectrow_arrayref() method when it returns. If this was not -done then it would be very easy to double count time spent inside -the DBI. - -=item Data Storage Tree - -The profile data is accumulated as 'leaves on a tree'. The 'path' through the -branches of the tree to a particular leaf is determined dynamically for each sample. -This is a key feature of DBI profiling. - -For each profiled method call the DBI walks along the Path and uses each value -in the Path to step into and grow the Data tree. - -For example, if the Path is - - [ 'foo', 'bar', 'baz' ] - -then the new profile sample data will be I into the tree at - - $h->{Profile}->{Data}->{foo}->{bar}->{baz} - -But it's not very useful to merge all the call data into one leaf node (except -to get an overall 'time spent inside the DBI' total). It's more common to want -the Path to include dynamic values such as the current statement text and/or -the name of the method called to show what the time spent inside the DBI was for. - -The Path can contain some 'magic cookie' values that are automatically replaced -by corresponding dynamic values when they're used. These magic cookies always -start with a punctuation character. - -For example a value of 'C' in the Path causes the corresponding -entry in the Data to be the name of the method that was called. -For example, if the Path was: - - [ 'foo', '!MethodName', 'bar' ] - -and the selectall_arrayref() method was called, then the profile sample data -for that call will be merged into the tree at: - - $h->{Profile}->{Data}->{foo}->{selectall_arrayref}->{bar} - -=item Profile Data - -Profile data is stored at the 'leaves' of the tree as references -to an array of numeric values. For example: - - [ - 106, # 0: count of samples at this node - 0.0312958955764771, # 1: total duration - 0.000490069389343262, # 2: first duration - 0.000176072120666504, # 3: shortest duration - 0.00140702724456787, # 4: longest duration - 1023115819.83019, # 5: time of first sample - 1023115819.86576, # 6: time of last sample - ] - -After the first sample, later samples always update elements 0, 1, and 6, and -may update 3 or 4 depending on the duration of the sampled call. - -=back - -=head1 ENABLING A PROFILE - -Profiling is enabled for a handle by assigning to the Profile -attribute. For example: - - $h->{Profile} = DBI::Profile->new(); - -The Profile attribute holds a blessed reference to a hash object -that contains the profile data and attributes relating to it. - -The class the Profile object is blessed into is expected to -provide at least a DESTROY method which will dump the profile data -to the DBI trace file handle (STDERR by default). - -All these examples have the same effect as each other: - - $h->{Profile} = 0; - $h->{Profile} = "/DBI::Profile"; - $h->{Profile} = DBI::Profile->new(); - $h->{Profile} = {}; - $h->{Profile} = { Path => [] }; - -Similarly, these examples have the same effect as each other: - - $h->{Profile} = 6; - $h->{Profile} = "6/DBI::Profile"; - $h->{Profile} = "!Statement:!MethodName/DBI::Profile"; - $h->{Profile} = { Path => [ '!Statement', '!MethodName' ] }; - -If a non-blessed hash reference is given then the DBI::Profile -module is automatically C'd and the reference is blessed -into that class. - -If a string is given then it is processed like this: - - ($path, $module, $args) = split /\//, $string, 3 - - @path = split /:/, $path - @args = split /:/, $args - - eval "require $module" if $module - $module ||= "DBI::Profile" - - $module->new( Path => \@Path, @args ) - -So the first value is used to select the Path to be used (see below). -The second value, if present, is used as the name of a module which -will be loaded and it's C method called. If not present it -defaults to DBI::Profile. Any other values are passed as arguments -to the C method. For example: "C<2/DBIx::OtherProfile/Foo:42>". - -Numbers can be used as a shorthand way to enable common Path values. -The simplest way to explain how the values are interpreted is to show the code: - - push @Path, "DBI" if $path_elem & 0x01; - push @Path, "!Statement" if $path_elem & 0x02; - push @Path, "!MethodName" if $path_elem & 0x04; - push @Path, "!MethodClass" if $path_elem & 0x08; - push @Path, "!Caller2" if $path_elem & 0x10; - -So "2" is the same as "!Statement" and "6" (2+4) is the same as -"!Statement:!Method". Those are the two most commonly used values. Using a -negative number will reverse the path. Thus "-6" will group by method name then -statement. - -The splitting and parsing of string values assigned to the Profile -attribute may seem a little odd, but there's a good reason for it. -Remember that attributes can be embedded in the Data Source Name -string which can be passed in to a script as a parameter. For -example: - - dbi:DriverName(Profile=>2):dbname - dbi:DriverName(Profile=>{Username}:!Statement/MyProfiler/Foo:42):dbname - -And also, if the C environment variable is set then -The DBI arranges for every driver handle to share the same profile -object. When perl exits a single profile summary will be generated -that reflects (as nearly as practical) the total use of the DBI by -the application. - - -=head1 THE PROFILE OBJECT - -The DBI core expects the Profile attribute value to be a hash -reference and if the following values don't exist it will create -them as needed: - -=head2 Data - -A reference to a hash containing the collected profile data. - -=head2 Path - -The Path value is a reference to an array. Each element controls the -value to use at the corresponding level of the profile Data tree. - -If the value of Path is anything other than an array reference, -it is treated as if it was: - - [ '!Statement' ] - -The elements of Path array can be one of the following types: - -=head3 Special Constant - -B - -Use the current Statement text. Typically that's the value of the Statement -attribute for the handle the method was called with. Some methods, like -commit() and rollback(), are unrelated to a particular statement. For those -methods !Statement records an empty string. - -For statement handles this is always simply the string that was -given to prepare() when the handle was created. For database handles -this is the statement that was last prepared or executed on that -database handle. That can lead to a little 'fuzzyness' because, for -example, calls to the quote() method to build a new statement will -typically be associated with the previous statement. In practice -this isn't a significant issue and the dynamic Path mechanism can -be used to setup your own rules. - -B - -Use the name of the DBI method that the profile sample relates to. - -B - -Use the fully qualified name of the DBI method, including -the package, that the profile sample relates to. This shows you -where the method was implemented. For example: - - 'DBD::_::db::selectrow_arrayref' => - 0.022902s - 'DBD::mysql::db::selectrow_arrayref' => - 2.244521s / 99 = 0.022445s avg (first 0.022813s, min 0.022051s, max 0.028932s) - -The "DBD::_::db::selectrow_arrayref" shows that the driver has -inherited the selectrow_arrayref method provided by the DBI. - -But you'll note that there is only one call to -DBD::_::db::selectrow_arrayref but another 99 to -DBD::mysql::db::selectrow_arrayref. Currently the first -call doesn't record the true location. That may change. - -B - -Use a string showing the filename and line number of the code calling the method. - -B - -Use a string showing the filename and line number of the code calling the -method, as for !Caller, but also include filename and line number of the code -that called that. Calls from DBI:: and DBD:: packages are skipped. - -B - -Same as !Caller above except that only the filename is included, not the line number. - -B - -Same as !Caller2 above except that only the filenames are included, not the line number. - -B - -Use the current value of time(). Rarely used. See the more useful C below. - -B - -Where C is an integer. Use the current value of time() but with reduced precision. -The value used is determined in this way: - - int( time() / N ) * N - -This is a useful way to segregate a profile into time slots. For example: - - [ '!Time~60', '!Statement' ] - -=head3 Code Reference - -The subroutine is passed the handle it was called on and the DBI method name. -The current Statement is in $_. The statement string should not be modified, -so most subs start with C. - -The list of values it returns is used at that point in the Profile Path. -Any undefined values are treated as the string "C". - -The sub can 'veto' (reject) a profile sample by including a reference to undef -(C<\undef>) in the returned list. That can be useful when you want to only profile -statements that match a certain pattern, or only profile certain methods. - -=head3 Subroutine Specifier - -A Path element that begins with 'C<&>' is treated as the name of a subroutine -in the DBI::ProfileSubs namespace and replaced with the corresponding code reference. - -Currently this only works when the Path is specified by the C -environment variable. - -Also, currently, the only subroutine in the DBI::ProfileSubs namespace is -C<'&norm_std_n3'>. That's a very handy subroutine when profiling code that -doesn't use placeholders. See L for more information. - -=head3 Attribute Specifier - -A string enclosed in braces, such as 'C<{Username}>', specifies that the current -value of the corresponding database handle attribute should be used at that -point in the Path. - -=head3 Reference to a Scalar - -Specifies that the current value of the referenced scalar be used at that point -in the Path. This provides an efficient way to get 'contextual' values into -your profile. - -=head3 Other Values - -Any other values are stringified and used literally. - -(References, and values that begin with punctuation characters are reserved.) - - -=head1 REPORTING - -=head2 Report Format - -The current accumulated profile data can be formatted and output using - - print $h->{Profile}->format; - -To discard the profile data and start collecting fresh data -you can do: - - $h->{Profile}->{Data} = undef; - - -The default results format looks like this: - - DBI::Profile: 0.001015s 42.7% (5 calls) programname @ YYYY-MM-DD HH:MM:SS - '' => - 0.000024s / 2 = 0.000012s avg (first 0.000015s, min 0.000009s, max 0.000015s) - 'SELECT mode,size,name FROM table' => - 0.000991s / 3 = 0.000330s avg (first 0.000678s, min 0.000009s, max 0.000678s) - -Which shows the total time spent inside the DBI, with a count of -the total number of method calls and the name of the script being -run, then a formatted version of the profile data tree. - -If the results are being formatted when the perl process is exiting -(which is usually the case when the DBI_PROFILE environment variable -is used) then the percentage of time the process spent inside the -DBI is also shown. If the process is not exiting then the percentage is -calculated using the time between the first and last call to the DBI. - -In the example above the paths in the tree are only one level deep and -use the Statement text as the value (that's the default behaviour). - -The merged profile data at the 'leaves' of the tree are presented -as total time spent, count, average time spent (which is simply total -time divided by the count), then the time spent on the first call, -the time spent on the fastest call, and finally the time spent on -the slowest call. - -The 'avg', 'first', 'min' and 'max' times are not particularly -useful when the profile data path only contains the statement text. -Here's an extract of a more detailed example using both statement -text and method name in the path: - - 'SELECT mode,size,name FROM table' => - 'FETCH' => - 0.000076s - 'fetchrow_hashref' => - 0.036203s / 108 = 0.000335s avg (first 0.000490s, min 0.000152s, max 0.002786s) - -Here you can see the 'avg', 'first', 'min' and 'max' for the -108 calls to fetchrow_hashref() become rather more interesting. -Also the data for FETCH just shows a time value because it was only -called once. - -Currently the profile data is output sorted by branch names. That -may change in a later version so the leaf nodes are sorted by total -time per leaf node. - - -=head2 Report Destination - -The default method of reporting is for the DESTROY method of the -Profile object to format the results and write them using: - - DBI->trace_msg($results, 0); # see $ON_DESTROY_DUMP below - -to write them to the DBI trace() filehandle (which defaults to -STDERR). To direct the DBI trace filehandle to write to a file -without enabling tracing the trace() method can be called with a -trace level of 0. For example: - - DBI->trace(0, $filename); - -The same effect can be achieved without changing the code by -setting the C environment variable to C<0=filename>. - -The $DBI::Profile::ON_DESTROY_DUMP variable holds a code ref -that's called to perform the output of the formatted results. -The default value is: - - $ON_DESTROY_DUMP = sub { DBI->trace_msg($results, 0) }; - -Apart from making it easy to send the dump elsewhere, it can also -be useful as a simple way to disable dumping results. - -=head1 CHILD HANDLES - -Child handles inherit a reference to the Profile attribute value -of their parent. So if profiling is enabled for a database handle -then by default the statement handles created from it all contribute -to the same merged profile data tree. - - -=head1 PROFILE OBJECT METHODS - -=head2 format - -See L. - -=head2 as_node_path_list - - @ary = $dbh->{Profile}->as_node_path_list(); - @ary = $dbh->{Profile}->as_node_path_list($node, $path); - -Returns the collected data ($dbh->{Profile}{Data}) restructured into a list of -array refs, one for each leaf node in the Data tree. This 'flat' structure is -often much simpler for applications to work with. - -The first element of each array ref is a reference to the leaf node. -The remaining elements are the 'path' through the data tree to that node. - -For example, given a data tree like this: - - {key1a}{key2a}[node1] - {key1a}{key2b}[node2] - {key1b}{key2a}{key3a}[node3] - -The as_node_path_list() method will return this list: - - [ [node1], 'key1a', 'key2a' ] - [ [node2], 'key1a', 'key2b' ] - [ [node3], 'key1b', 'key2a', 'key3a' ] - -The nodes are ordered by key, depth-first. - -The $node argument can be used to focus on a sub-tree. -If not specified it defaults to $dbh->{Profile}{Data}. - -The $path argument can be used to specify a list of path elements that will be -added to each element of the returned list. If not specified it defaults to a -ref to an empty array. - -=head2 as_text - - @txt = $dbh->{Profile}->as_text(); - $txt = $dbh->{Profile}->as_text({ - node => undef, - path => [], - separator => " > ", - format => '%1$s: %11$fs / %10$d = %2$fs avg (first %12$fs, min %13$fs, max %14$fs)'."\n"; - sortsub => sub { ... }, - ); - -Returns the collected data ($dbh->{Profile}{Data}) reformatted into a list of formatted strings. -In scalar context the list is returned as a single concatenated string. - -A hashref can be used to pass in arguments, the default values are shown in the example above. - -The C and arguments are passed to as_node_path_list(). - -The C argument is used to join the elements of the path for each leaf node. - -The C argument is used to pass in a ref to a sub that will order the list. -The subroutine will be passed a reference to the array returned by -as_node_path_list() and should sort the contents of the array in place. -The return value from the sub is ignored. For example, to sort the nodes by the -second level key you could use: - - sortsub => sub { my $ary=shift; @$ary = sort { $a->[2] cmp $b->[2] } @$ary } - -The C argument is a C format string that specifies the format -to use for each leaf node. It uses the explicit format parameter index -mechanism to specify which of the arguments should appear where in the string. -The arguments to sprintf are: - - 1: path to node, joined with the separator - 2: average duration (total duration/count) - (3 thru 9 are currently unused) - 10: count - 11: total duration - 12: first duration - 13: smallest duration - 14: largest duration - 15: time of first call - 16: time of first call - -=head1 CUSTOM DATA MANIPULATION - -Recall that C<< $h->{Profile}->{Data} >> is a reference to the collected data. -Either to a 'leaf' array (when the Path is empty, i.e., DBI_PROFILE env var is 1), -or a reference to hash containing values that are either further hash -references or leaf array references. - -Sometimes it's useful to be able to summarise some or all of the collected data. -The dbi_profile_merge_nodes() function can be used to merge leaf node values. - -=head2 dbi_profile_merge_nodes - - use DBI qw(dbi_profile_merge_nodes); - - $time_in_dbi = dbi_profile_merge_nodes(my $totals=[], @$leaves); - -Merges profile data node. Given a reference to a destination array, and zero or -more references to profile data, merges the profile data into the destination array. -For example: - - $time_in_dbi = dbi_profile_merge_nodes( - my $totals=[], - [ 10, 0.51, 0.11, 0.01, 0.22, 1023110000, 1023110010 ], - [ 15, 0.42, 0.12, 0.02, 0.23, 1023110005, 1023110009 ], - ); - -$totals will then contain - - [ 25, 0.93, 0.11, 0.01, 0.23, 1023110000, 1023110010 ] - -and $time_in_dbi will be 0.93; - -The second argument need not be just leaf nodes. If given a reference to a hash -then the hash is recursively searched for leaf nodes and all those found -are merged. - -For example, to get the time spent 'inside' the DBI during an http request, -your logging code run at the end of the request (i.e. mod_perl LogHandler) -could use: - - my $time_in_dbi = 0; - if (my $Profile = $dbh->{Profile}) { # if DBI profiling is enabled - $time_in_dbi = dbi_profile_merge_nodes(my $total=[], $Profile->{Data}); - $Profile->{Data} = {}; # reset the profile data - } - -If profiling has been enabled then $time_in_dbi will hold the time spent inside -the DBI for that handle (and any other handles that share the same profile data) -since the last request. - -Prior to DBI 1.56 the dbi_profile_merge_nodes() function was called dbi_profile_merge(). -That name still exists as an alias. - -=head1 CUSTOM DATA COLLECTION - -=head2 Using The Path Attribute - - XXX example to be added later using a selectall_arrayref call - XXX nested inside a fetch loop where the first column of the - XXX outer loop is bound to the profile Path using - XXX bind_column(1, \${ $dbh->{Profile}->{Path}->[0] }) - XXX so you end up with separate profiles for each loop - XXX (patches welcome to add this to the docs :) - -=head2 Adding Your Own Samples - -The dbi_profile() function can be used to add extra sample data -into the profile data tree. For example: - - use DBI; - use DBI::Profile (dbi_profile dbi_time); - - my $t1 = dbi_time(); # floating point high-resolution time - - ... execute code you want to profile here ... - - my $t2 = dbi_time(); - dbi_profile($h, $statement, $method, $t1, $t2); - -The $h parameter is the handle the extra profile sample should be -associated with. The $statement parameter is the string to use where -the Path specifies !Statement. If $statement is undef -then $h->{Statement} will be used. Similarly $method is the string -to use if the Path specifies !MethodName. There is no -default value for $method. - -The $h->{Profile}{Path} attribute is processed by dbi_profile() in -the usual way. - -The $h parameter is usually a DBI handle but it can also be a reference to a -hash, in which case the dbi_profile() acts on each defined value in the hash. -This is an efficient way to update multiple profiles with a single sample, -and is used by the L module. - -=head1 SUBCLASSING - -Alternate profile modules must subclass DBI::Profile to help ensure -they work with future versions of the DBI. - - -=head1 CAVEATS - -Applications which generate many different statement strings -(typically because they don't use placeholders) and profile with -!Statement in the Path (the default) will consume memory -in the Profile Data structure for each statement. Use a code ref -in the Path to return an edited (simplified) form of the statement. - -If a method throws an exception itself (not via RaiseError) then -it won't be counted in the profile. - -If a HandleError subroutine throws an exception (rather than returning -0 and letting RaiseError do it) then the method call won't be counted -in the profile. - -Time spent in DESTROY is added to the profile of the parent handle. - -Time spent in DBI->*() methods is not counted. The time spent in -the driver connect method, $drh->connect(), when it's called by -DBI->connect is counted if the DBI_PROFILE environment variable is set. - -Time spent fetching tied variables, $DBI::errstr, is counted. - -Time spent in FETCH for $h->{Profile} is not counted, so getting the profile -data doesn't alter it. - -DBI::PurePerl does not support profiling (though it could in theory). - -For asynchronous queries, time spent while the query is running on the -backend is not counted. - -A few platforms don't support the gettimeofday() high resolution -time function used by the DBI (and available via the dbi_time() function). -In which case you'll get integer resolution time which is mostly useless. - -On Windows platforms the dbi_time() function is limited to millisecond -resolution. Which isn't sufficiently fine for our needs, but still -much better than integer resolution. This limited resolution means -that fast method calls will often register as taking 0 time. And -timings in general will have much more 'jitter' depending on where -within the 'current millisecond' the start and end timing was taken. - -This documentation could be more clear. Probably needs to be reordered -to start with several examples and build from there. Trying to -explain the concepts first seems painful and to lead to just as -many forward references. (Patches welcome!) - -=cut - - -use strict; -use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); -use Exporter (); -use UNIVERSAL (); -use Carp; - -use DBI qw(dbi_time dbi_profile dbi_profile_merge_nodes dbi_profile_merge); - -$VERSION = "2.015065"; - -@ISA = qw(Exporter); -@EXPORT = qw( - DBIprofile_Statement - DBIprofile_MethodName - DBIprofile_MethodClass - dbi_profile - dbi_profile_merge_nodes - dbi_profile_merge - dbi_time -); -@EXPORT_OK = qw( - format_profile_thingy -); - -use constant DBIprofile_Statement => '!Statement'; -use constant DBIprofile_MethodName => '!MethodName'; -use constant DBIprofile_MethodClass => '!MethodClass'; - -our $ON_DESTROY_DUMP = sub { DBI->trace_msg(shift, 0) }; -our $ON_FLUSH_DUMP = sub { DBI->trace_msg(shift, 0) }; - -sub new { - my $class = shift; - my $profile = { @_ }; - return bless $profile => $class; -} - - -sub _auto_new { - my $class = shift; - my ($arg) = @_; - - # This sub is called by DBI internals when a non-hash-ref is - # assigned to the Profile attribute. For example - # dbi:mysql(RaiseError=>1,Profile=>!Statement:!MethodName/DBIx::MyProfile/arg1:arg2):dbname - # This sub works out what to do and returns a suitable hash ref. - - $arg =~ s/^DBI::/2\/DBI::/ - and carp "Automatically changed old-style DBI::Profile specification to $arg"; - - # it's a path/module/k1:v1:k2:v2:... list - my ($path, $package, $args) = split /\//, $arg, 3; - my @args = (defined $args) ? split(/:/, $args, -1) : (); - my @Path; - - for my $element (split /:/, $path) { - if (DBI::looks_like_number($element)) { - my $reverse = ($element < 0) ? ($element=-$element, 1) : 0; - my @p; - # a single "DBI" is special-cased in format() - push @p, "DBI" if $element & 0x01; - push @p, DBIprofile_Statement if $element & 0x02; - push @p, DBIprofile_MethodName if $element & 0x04; - push @p, DBIprofile_MethodClass if $element & 0x08; - push @p, '!Caller2' if $element & 0x10; - push @Path, ($reverse ? reverse @p : @p); - } - elsif ($element =~ m/^&(\w.*)/) { - my $name = "DBI::ProfileSubs::$1"; # capture $1 early - require DBI::ProfileSubs; - my $code = do { no strict; *{$name}{CODE} }; - if (defined $code) { - push @Path, $code; - } - else { - warn "$name: subroutine not found\n"; - push @Path, $element; - } - } - else { - push @Path, $element; - } - } - - eval "require $package" if $package; # silently ignores errors - $package ||= $class; - - return $package->new(Path => \@Path, @args); -} - - -sub empty { # empty out profile data - my $self = shift; - DBI->trace_msg("profile data discarded\n",0) if $self->{Trace}; - $self->{Data} = undef; -} - -sub filename { # baseclass method, see DBI::ProfileDumper - return undef; -} - -sub flush_to_disk { # baseclass method, see DBI::ProfileDumper & DashProfiler::Core - my $self = shift; - return unless $ON_FLUSH_DUMP; - return unless $self->{Data}; - my $detail = $self->format(); - $ON_FLUSH_DUMP->($detail) if $detail; -} - - -sub as_node_path_list { - my ($self, $node, $path) = @_; - # convert the tree into an array of arrays - # from - # {key1a}{key2a}[node1] - # {key1a}{key2b}[node2] - # {key1b}{key2a}{key3a}[node3] - # to - # [ [node1], 'key1a', 'key2a' ] - # [ [node2], 'key1a', 'key2b' ] - # [ [node3], 'key1b', 'key2a', 'key3a' ] - - $node ||= $self->{Data} or return; - $path ||= []; - if (ref $node eq 'HASH') { # recurse - $path = [ @$path, undef ]; - return map { - $path->[-1] = $_; - ($node->{$_}) ? $self->as_node_path_list($node->{$_}, $path) : () - } sort keys %$node; - } - return [ $node, @$path ]; -} - - -sub as_text { - my ($self, $args_ref) = @_; - my $separator = $args_ref->{separator} || " > "; - my $format_path_element = $args_ref->{format_path_element} - || "%s"; # or e.g., " key%2$d='%s'" - my $format = $args_ref->{format} - || '%1$s: %11$fs / %10$d = %2$fs avg (first %12$fs, min %13$fs, max %14$fs)'."\n"; - - my @node_path_list = $self->as_node_path_list(undef, $args_ref->{path}); - - $args_ref->{sortsub}->(\@node_path_list) if $args_ref->{sortsub}; - - my $eval = "qr/".quotemeta($separator)."/"; - my $separator_re = eval($eval) || quotemeta($separator); - #warn "[$eval] = [$separator_re]"; - my @text; - my @spare_slots = (undef) x 7; - for my $node_path (@node_path_list) { - my ($node, @path) = @$node_path; - my $idx = 0; - for (@path) { - s/[\r\n]+/ /g; - s/$separator_re/ /g; - ++$idx; - if ($format_path_element eq "%s") { - $_ = sprintf $format_path_element, $_; - } else { - $_ = sprintf $format_path_element, $_, $idx; - } - } - push @text, sprintf $format, - join($separator, @path), # 1=path - ($node->[0] ? $node->[1]/$node->[0] : 0), # 2=avg - @spare_slots, - @$node; # 10=count, 11=dur, 12=first_dur, 13=min, 14=max, 15=first_called, 16=last_called - } - return @text if wantarray; - return join "", @text; -} - - -sub format { - my $self = shift; - my $class = ref($self) || $self; - - my $prologue = "$class: "; - my $detail = $self->format_profile_thingy( - $self->{Data}, 0, " ", - my $path = [], - my $leaves = [], - )."\n"; - - if (@$leaves) { - dbi_profile_merge_nodes(my $totals=[], @$leaves); - my ($count, $time_in_dbi, undef, undef, undef, $t1, $t2) = @$totals; - (my $progname = $0) =~ s:.*/::; - if ($count) { - $prologue .= sprintf "%fs ", $time_in_dbi; - my $perl_time = ($DBI::PERL_ENDING) ? time() - $^T : $t2-$t1; - $prologue .= sprintf "%.2f%% ", $time_in_dbi/$perl_time*100 if $perl_time; - my @lt = localtime(time); - my $ts = sprintf "%d-%02d-%02d %02d:%02d:%02d", - 1900+$lt[5], $lt[4]+1, @lt[3,2,1,0]; - $prologue .= sprintf "(%d calls) $progname \@ $ts\n", $count; - } - if (@$leaves == 1 && ref($self->{Data}) eq 'HASH' && $self->{Data}->{DBI}) { - $detail = ""; # hide the "DBI" from DBI_PROFILE=1 - } - } - return ($prologue, $detail) if wantarray; - return $prologue.$detail; -} - - -sub format_profile_leaf { - my ($self, $thingy, $depth, $pad, $path, $leaves) = @_; - croak "format_profile_leaf called on non-leaf ($thingy)" - unless UNIVERSAL::isa($thingy,'ARRAY'); - - push @$leaves, $thingy if $leaves; - my ($count, $total_time, $first_time, $min, $max, $first_called, $last_called) = @$thingy; - return sprintf "%s%fs\n", ($pad x $depth), $total_time - if $count <= 1; - return sprintf "%s%fs / %d = %fs avg (first %fs, min %fs, max %fs)\n", - ($pad x $depth), $total_time, $count, $count ? $total_time/$count : 0, - $first_time, $min, $max; -} - - -sub format_profile_branch { - my ($self, $thingy, $depth, $pad, $path, $leaves) = @_; - croak "format_profile_branch called on non-branch ($thingy)" - unless UNIVERSAL::isa($thingy,'HASH'); - my @chunk; - my @keys = sort keys %$thingy; - while ( @keys ) { - my $k = shift @keys; - my $v = $thingy->{$k}; - push @$path, $k; - push @chunk, sprintf "%s'%s' =>\n%s", - ($pad x $depth), $k, - $self->format_profile_thingy($v, $depth+1, $pad, $path, $leaves); - pop @$path; - } - return join "", @chunk; -} - - -sub format_profile_thingy { - my ($self, $thingy, $depth, $pad, $path, $leaves) = @_; - return "undef" if not defined $thingy; - return $self->format_profile_leaf( $thingy, $depth, $pad, $path, $leaves) - if UNIVERSAL::isa($thingy,'ARRAY'); - return $self->format_profile_branch($thingy, $depth, $pad, $path, $leaves) - if UNIVERSAL::isa($thingy,'HASH'); - return "$thingy\n"; -} - - -sub on_destroy { - my $self = shift; - return unless $ON_DESTROY_DUMP; - return unless $self->{Data}; - my $detail = $self->format(); - $ON_DESTROY_DUMP->($detail) if $detail; - $self->{Data} = undef; -} - -sub DESTROY { - my $self = shift; - local $@; - DBI->trace_msg("profile data DESTROY\n",0) - if (($self->{Trace}||0) >= 2); - eval { $self->on_destroy }; - if ($@) { - chomp $@; - my $class = ref($self) || $self; - DBI->trace_msg("$class on_destroy failed: $@", 0); - } -} - -1; - diff --git a/dbLifeLog/DBI-1.641/lib/DBI/ProfileData.pm b/dbLifeLog/DBI-1.641/lib/DBI/ProfileData.pm deleted file mode 100644 index e6bb994..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/ProfileData.pm +++ /dev/null @@ -1,736 +0,0 @@ -package DBI::ProfileData; -use strict; - -=head1 NAME - -DBI::ProfileData - manipulate DBI::ProfileDumper data dumps - -=head1 SYNOPSIS - -The easiest way to use this module is through the dbiprof frontend -(see L for details): - - dbiprof --number 15 --sort count - -This module can also be used to roll your own profile analysis: - - # load data from dbi.prof - $prof = DBI::ProfileData->new(File => "dbi.prof"); - - # get a count of the records (unique paths) in the data set - $count = $prof->count(); - - # sort by longest overall time - $prof->sort(field => "longest"); - - # sort by longest overall time, least to greatest - $prof->sort(field => "longest", reverse => 1); - - # exclude records with key2 eq 'disconnect' - $prof->exclude(key2 => 'disconnect'); - - # exclude records with key1 matching /^UPDATE/i - $prof->exclude(key1 => qr/^UPDATE/i); - - # remove all records except those where key1 matches /^SELECT/i - $prof->match(key1 => qr/^SELECT/i); - - # produce a formatted report with the given number of items - $report = $prof->report(number => 10); - - # clone the profile data set - $clone = $prof->clone(); - - # get access to hash of header values - $header = $prof->header(); - - # get access to sorted array of nodes - $nodes = $prof->nodes(); - - # format a single node in the same style as report() - $text = $prof->format($nodes->[0]); - - # get access to Data hash in DBI::Profile format - $Data = $prof->Data(); - -=head1 DESCRIPTION - -This module offers the ability to read, manipulate and format -L profile data. - -Conceptually, a profile consists of a series of records, or nodes, -each of each has a set of statistics and set of keys. Each record -must have a unique set of keys, but there is no requirement that every -record have the same number of keys. - -=head1 METHODS - -The following methods are supported by DBI::ProfileData objects. - -=cut - -our $VERSION = "2.010008"; - -use Carp qw(croak); -use Symbol; -use Fcntl qw(:flock); - -use DBI::Profile qw(dbi_profile_merge); - -# some constants for use with node data arrays -sub COUNT () { 0 }; -sub TOTAL () { 1 }; -sub FIRST () { 2 }; -sub SHORTEST () { 3 }; -sub LONGEST () { 4 }; -sub FIRST_AT () { 5 }; -sub LAST_AT () { 6 }; -sub PATH () { 7 }; - - -my $HAS_FLOCK = (defined $ENV{DBI_PROFILE_FLOCK}) - ? $ENV{DBI_PROFILE_FLOCK} - : do { local $@; eval { flock STDOUT, 0; 1 } }; - - -=head2 $prof = DBI::ProfileData->new(File => "dbi.prof") - -=head2 $prof = DBI::ProfileData->new(File => "dbi.prof", Filter => sub { ... }) - -=head2 $prof = DBI::ProfileData->new(Files => [ "dbi.prof.1", "dbi.prof.2" ]) - -Creates a new DBI::ProfileData object. Takes either a single file -through the File option or a list of Files in an array ref. If -multiple files are specified then the header data from the first file -is used. - -=head3 Files - -Reference to an array of file names to read. - -=head3 File - -Name of file to read. Takes precedence over C. - -=head3 DeleteFiles - -If true, the files are deleted after being read. - -Actually the files are renamed with a C suffix before being read, -and then, after reading all the files, they're all deleted together. - -The files are locked while being read which, combined with the rename, makes it -safe to 'consume' files that are still being generated by L. - -=head3 Filter - -The C parameter can be used to supply a code reference that can -manipulate the profile data as it is being read. This is most useful for -editing SQL statements so that slightly different statements in the raw data -will be merged and aggregated in the loaded data. For example: - - Filter => sub { - my ($path_ref, $data_ref) = @_; - s/foo = '.*?'/foo = '...'/ for @$path_ref; - } - -Here's an example that performs some normalization on the SQL. It converts all -numbers to C and all quoted strings to C. It can also convert digits to -N within names. Finally, it summarizes long "IN (...)" clauses. - -It's aggressive and simplistic, but it's often sufficient, and serves as an -example that you can tailor to suit your own needs: - - Filter => sub { - my ($path_ref, $data_ref) = @_; - local $_ = $path_ref->[0]; # whichever element contains the SQL Statement - s/\b\d+\b/N/g; # 42 -> N - s/\b0x[0-9A-Fa-f]+\b/N/g; # 0xFE -> N - s/'.*?'/'S'/g; # single quoted strings (doesn't handle escapes) - s/".*?"/"S"/g; # double quoted strings (doesn't handle escapes) - # convert names like log_20001231 into log_NNNNNNNN, controlled by $opt{n} - s/([a-z_]+)(\d{$opt{n},})/$1.('N' x length($2))/ieg if $opt{n}; - # abbreviate massive "in (...)" statements and similar - s!(([NS],){100,})!sprintf("$2,{repeated %d times}",length($1)/2)!eg; - } - -It's often better to perform this kinds of normalization in the DBI while the -data is being collected, to avoid too much memory being used by storing profile -data for many different SQL statement. See L. - -=cut - -sub new { - my $pkg = shift; - my $self = { - Files => [ "dbi.prof" ], - Filter => undef, - DeleteFiles => 0, - LockFile => $HAS_FLOCK, - _header => {}, - _nodes => [], - _node_lookup => {}, - _sort => 'none', - @_ - }; - bless $self, $pkg; - - # File (singular) overrides Files (plural) - $self->{Files} = [ $self->{File} ] if exists $self->{File}; - - $self->_read_files(); - return $self; -} - -# read files into _header and _nodes -sub _read_files { - my $self = shift; - my $files = $self->{Files}; - my $read_header = 0; - my @files_to_delete; - - my $fh = gensym; - foreach (@$files) { - my $filename = $_; - - if ($self->{DeleteFiles}) { - my $newfilename = $filename . ".deleteme"; - if ($^O eq 'VMS') { - # VMS default filesystem can only have one period - $newfilename = $filename . 'deleteme'; - } - # will clobber an existing $newfilename - rename($filename, $newfilename) - or croak "Can't rename($filename, $newfilename): $!"; - # On a versioned filesystem we want old versions to be removed - 1 while (unlink $filename); - $filename = $newfilename; - } - - open($fh, "<", $filename) - or croak("Unable to read profile file '$filename': $!"); - - # lock the file in case it's still being written to - # (we'll be forced to wait till the write is complete) - flock($fh, LOCK_SH) if $self->{LockFile}; - - if (-s $fh) { # not empty - $self->_read_header($fh, $filename, $read_header ? 0 : 1); - $read_header = 1; - $self->_read_body($fh, $filename); - } - close($fh); # and release lock - - push @files_to_delete, $filename - if $self->{DeleteFiles}; - } - for (@files_to_delete){ - # for versioned file systems - 1 while (unlink $_); - if(-e $_){ - warn "Can't delete '$_': $!"; - } - } - - # discard node_lookup now that all files are read - delete $self->{_node_lookup}; -} - -# read the header from the given $fh named $filename. Discards the -# data unless $keep. -sub _read_header { - my ($self, $fh, $filename, $keep) = @_; - - # get profiler module id - my $first = <$fh>; - chomp $first; - $self->{_profiler} = $first if $keep; - - # collect variables from the header - local $_; - while (<$fh>) { - chomp; - last unless length $_; - /^(\S+)\s*=\s*(.*)/ - or croak("Syntax error in header in $filename line $.: $_"); - # XXX should compare new with existing (from previous file) - # and warn if they differ (different program or path) - $self->{_header}{$1} = unescape_key($2) if $keep; - } -} - - -sub unescape_key { # inverse of escape_key() in DBI::ProfileDumper - local $_ = shift; - s/(?{_nodes}; - my $lookup = $self->{_node_lookup}; - my $filter = $self->{Filter}; - - # build up node array - my @path = (""); - my (@data, $path_key); - local $_; - while (<$fh>) { - chomp; - if (/^\+\s+(\d+)\s?(.*)/) { - # it's a key - my ($key, $index) = ($2, $1 - 1); - - $#path = $index; # truncate path to new length - $path[$index] = unescape_key($key); # place new key at end - - } - elsif (s/^=\s+//) { - # it's data - file in the node array with the path in index 0 - # (the optional minus is to make it more robust against systems - # with unstable high-res clocks - typically due to poor NTP config - # of kernel SMP behaviour, i.e. min time may be -0.000008)) - - @data = split / /, $_; - - # corrupt data? - croak("Invalid number of fields in $filename line $.: $_") - unless @data == 7; - croak("Invalid leaf node characters $filename line $.: $_") - unless m/^[-+ 0-9eE\.]+$/; - - # hook to enable pre-processing of the data - such as mangling SQL - # so that slightly different statements get treated as the same - # and so merged in the results - $filter->(\@path, \@data) if $filter; - - # elements of @path can't have NULLs in them, so this - # forms a unique string per @path. If there's some way I - # can get this without arbitrarily stripping out a - # character I'd be happy to hear it! - $path_key = join("\0",@path); - - # look for previous entry - if (exists $lookup->{$path_key}) { - # merge in the new data - dbi_profile_merge($nodes->[$lookup->{$path_key}], \@data); - } else { - # insert a new node - nodes are arrays with data in 0-6 - # and path data after that - push(@$nodes, [ @data, @path ]); - - # record node in %seen - $lookup->{$path_key} = $#$nodes; - } - } - else { - croak("Invalid line type syntax error in $filename line $.: $_"); - } - } -} - - - -=head2 $copy = $prof->clone(); - -Clone a profile data set creating a new object. - -=cut - -sub clone { - my $self = shift; - - # start with a simple copy - my $clone = bless { %$self }, ref($self); - - # deep copy nodes - $clone->{_nodes} = [ map { [ @$_ ] } @{$self->{_nodes}} ]; - - # deep copy header - $clone->{_header} = { %{$self->{_header}} }; - - return $clone; -} - -=head2 $header = $prof->header(); - -Returns a reference to a hash of header values. These are the key -value pairs included in the header section of the L -data format. For example: - - $header = { - Path => [ '!Statement', '!MethodName' ], - Program => 't/42profile_data.t', - }; - -Note that modifying this hash will modify the header data stored -inside the profile object. - -=cut - -sub header { shift->{_header} } - - -=head2 $nodes = $prof->nodes() - -Returns a reference the sorted nodes array. Each element in the array -is a single record in the data set. The first seven elements are the -same as the elements provided by L. After that each key is -in a separate element. For example: - - $nodes = [ - [ - 2, # 0, count - 0.0312958955764771, # 1, total duration - 0.000490069389343262, # 2, first duration - 0.000176072120666504, # 3, shortest duration - 0.00140702724456787, # 4, longest duration - 1023115819.83019, # 5, time of first event - 1023115819.86576, # 6, time of last event - 'SELECT foo FROM bar' # 7, key1 - 'execute' # 8, key2 - # 6+N, keyN - ], - # ... - ]; - -Note that modifying this array will modify the node data stored inside -the profile object. - -=cut - -sub nodes { shift->{_nodes} } - - -=head2 $count = $prof->count() - -Returns the number of items in the profile data set. - -=cut - -sub count { scalar @{shift->{_nodes}} } - - -=head2 $prof->sort(field => "field") - -=head2 $prof->sort(field => "field", reverse => 1) - -Sorts data by the given field. Available fields are: - - longest - total - count - shortest - -The default sort is greatest to smallest, which is the opposite of the -normal Perl meaning. This, however, matches the expected behavior of -the dbiprof frontend. - -=cut - - -# sorts data by one of the available fields -{ - my %FIELDS = ( - longest => LONGEST, - total => TOTAL, - count => COUNT, - shortest => SHORTEST, - key1 => PATH+0, - key2 => PATH+1, - key3 => PATH+2, - ); - sub sort { - my $self = shift; - my $nodes = $self->{_nodes}; - my %opt = @_; - - croak("Missing required field option.") unless $opt{field}; - - my $index = $FIELDS{$opt{field}}; - - croak("Unrecognized sort field '$opt{field}'.") - unless defined $index; - - # sort over index - if ($opt{reverse}) { - @$nodes = sort { - $a->[$index] <=> $b->[$index] - } @$nodes; - } else { - @$nodes = sort { - $b->[$index] <=> $a->[$index] - } @$nodes; - } - - # remember how we're sorted - $self->{_sort} = $opt{field}; - - return $self; - } -} - - -=head2 $count = $prof->exclude(key2 => "disconnect") - -=head2 $count = $prof->exclude(key2 => "disconnect", case_sensitive => 1) - -=head2 $count = $prof->exclude(key1 => qr/^SELECT/i) - -Removes records from the data set that match the given string or -regular expression. This method modifies the data in a permanent -fashion - use clone() first to maintain the original data after -exclude(). Returns the number of nodes left in the profile data set. - -=cut - -sub exclude { - my $self = shift; - my $nodes = $self->{_nodes}; - my %opt = @_; - - # find key index number - my ($index, $val); - foreach (keys %opt) { - if (/^key(\d+)$/) { - $index = PATH + $1 - 1; - $val = $opt{$_}; - last; - } - } - croak("Missing required keyN option.") unless $index; - - if (UNIVERSAL::isa($val,"Regexp")) { - # regex match - @$nodes = grep { - $#$_ < $index or $_->[$index] !~ /$val/ - } @$nodes; - } else { - if ($opt{case_sensitive}) { - @$nodes = grep { - $#$_ < $index or $_->[$index] ne $val; - } @$nodes; - } else { - $val = lc $val; - @$nodes = grep { - $#$_ < $index or lc($_->[$index]) ne $val; - } @$nodes; - } - } - - return scalar @$nodes; -} - - -=head2 $count = $prof->match(key2 => "disconnect") - -=head2 $count = $prof->match(key2 => "disconnect", case_sensitive => 1) - -=head2 $count = $prof->match(key1 => qr/^SELECT/i) - -Removes records from the data set that do not match the given string -or regular expression. This method modifies the data in a permanent -fashion - use clone() first to maintain the original data after -match(). Returns the number of nodes left in the profile data set. - -=cut - -sub match { - my $self = shift; - my $nodes = $self->{_nodes}; - my %opt = @_; - - # find key index number - my ($index, $val); - foreach (keys %opt) { - if (/^key(\d+)$/) { - $index = PATH + $1 - 1; - $val = $opt{$_}; - last; - } - } - croak("Missing required keyN option.") unless $index; - - if (UNIVERSAL::isa($val,"Regexp")) { - # regex match - @$nodes = grep { - $#$_ >= $index and $_->[$index] =~ /$val/ - } @$nodes; - } else { - if ($opt{case_sensitive}) { - @$nodes = grep { - $#$_ >= $index and $_->[$index] eq $val; - } @$nodes; - } else { - $val = lc $val; - @$nodes = grep { - $#$_ >= $index and lc($_->[$index]) eq $val; - } @$nodes; - } - } - - return scalar @$nodes; -} - - -=head2 $Data = $prof->Data() - -Returns the same Data hash structure as seen in L. This -structure is not sorted. The nodes() structure probably makes more -sense for most analysis. - -=cut - -sub Data { - my $self = shift; - my (%Data, @data, $ptr); - - foreach my $node (@{$self->{_nodes}}) { - # traverse to key location - $ptr = \%Data; - foreach my $key (@{$node}[PATH .. $#$node - 1]) { - $ptr->{$key} = {} unless exists $ptr->{$key}; - $ptr = $ptr->{$key}; - } - - # slice out node data - $ptr->{$node->[-1]} = [ @{$node}[0 .. 6] ]; - } - - return \%Data; -} - - -=head2 $text = $prof->format($nodes->[0]) - -Formats a single node into a human-readable block of text. - -=cut - -sub format { - my ($self, $node) = @_; - my $format; - - # setup keys - my $keys = ""; - for (my $i = PATH; $i <= $#$node; $i++) { - my $key = $node->[$i]; - - # remove leading and trailing space - $key =~ s/^\s+//; - $key =~ s/\s+$//; - - # if key has newlines or is long take special precautions - if (length($key) > 72 or $key =~ /\n/) { - $keys .= " Key " . ($i - PATH + 1) . " :\n\n$key\n\n"; - } else { - $keys .= " Key " . ($i - PATH + 1) . " : $key\n"; - } - } - - # nodes with multiple runs get the long entry format, nodes with - # just one run get a single count. - if ($node->[COUNT] > 1) { - $format = <[TOTAL] / $node->[COUNT]) . $keys; - } else { - $format = <report(number => 10) - -Produces a report with the given number of items. - -=cut - -sub report { - my $self = shift; - my $nodes = $self->{_nodes}; - my %opt = @_; - - croak("Missing required number option") unless exists $opt{number}; - - $opt{number} = @$nodes if @$nodes < $opt{number}; - - my $report = $self->_report_header($opt{number}); - for (0 .. $opt{number} - 1) { - $report .= sprintf("#" x 5 . "[ %d ]". "#" x 59 . "\n", - $_ + 1); - $report .= $self->format($nodes->[$_]); - $report .= "\n"; - } - return $report; -} - -# format the header for report() -sub _report_header { - my ($self, $number) = @_; - my $nodes = $self->{_nodes}; - my $node_count = @$nodes; - - # find total runtime and method count - my ($time, $count) = (0,0); - foreach my $node (@$nodes) { - $time += $node->[TOTAL]; - $count += $node->[COUNT]; - } - - my $header = <{_profiler}) - -END - - # output header fields - while (my ($key, $value) = each %{$self->{_header}}) { - $header .= sprintf(" %-13s : %s\n", $key, $value); - } - - # output summary data fields - $header .= sprintf(<{_sort}, $count, $time); - Total Records : %d (showing %d, sorted by %s) - Total Count : %d - Total Runtime : %3.6f seconds - -END - - return $header; -} - - -1; - -__END__ - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper.pm b/dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper.pm deleted file mode 100644 index 440b5c9..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper.pm +++ /dev/null @@ -1,351 +0,0 @@ -package DBI::ProfileDumper; -use strict; - -=head1 NAME - -DBI::ProfileDumper - profile DBI usage and output data to a file - -=head1 SYNOPSIS - -To profile an existing program using DBI::ProfileDumper, set the -DBI_PROFILE environment variable and run your program as usual. For -example, using bash: - - DBI_PROFILE=2/DBI::ProfileDumper program.pl - -Then analyze the generated file (F) with L: - - dbiprof - -You can also activate DBI::ProfileDumper from within your code: - - use DBI; - - # profile with default path (2) and output file (dbi.prof) - $dbh->{Profile} = "!Statement/DBI::ProfileDumper"; - - # same thing, spelled out - $dbh->{Profile} = "!Statement/DBI::ProfileDumper/File:dbi.prof"; - - # another way to say it - use DBI::ProfileDumper; - $dbh->{Profile} = DBI::ProfileDumper->new( - Path => [ '!Statement' ], - File => 'dbi.prof' ); - - # using a custom path - $dbh->{Profile} = DBI::ProfileDumper->new( - Path => [ "foo", "bar" ], - File => 'dbi.prof', - ); - - -=head1 DESCRIPTION - -DBI::ProfileDumper is a subclass of L which -dumps profile data to disk instead of printing a summary to your -screen. You can then use L to analyze the data in -a number of interesting ways, or you can roll your own analysis using -L. - -B For Apache/mod_perl applications, use -L. - -=head1 USAGE - -One way to use this module is just to enable it in your C<$dbh>: - - $dbh->{Profile} = "1/DBI::ProfileDumper"; - -This will write out profile data by statement into a file called -F. If you want to modify either of these properties, you -can construct the DBI::ProfileDumper object yourself: - - use DBI::ProfileDumper; - $dbh->{Profile} = DBI::ProfileDumper->new( - Path => [ '!Statement' ], - File => 'dbi.prof' - ); - -The C option takes the same values as in -L. The C option gives the name of the -file where results will be collected. If it already exists it will be -overwritten. - -You can also activate this module by setting the DBI_PROFILE -environment variable: - - $ENV{DBI_PROFILE} = "!Statement/DBI::ProfileDumper"; - -This will cause all DBI handles to share the same profiling object. - -=head1 METHODS - -The following methods are available to be called using the profile -object. You can get access to the profile object from the Profile key -in any DBI handle: - - my $profile = $dbh->{Profile}; - -=head2 flush_to_disk - - $profile->flush_to_disk() - -Flushes all collected profile data to disk and empties the Data hash. Returns -the filename written to. If no profile data has been collected then the file is -not written and flush_to_disk() returns undef. - -The file is locked while it's being written. A process 'consuming' the files -while they're being written to, should rename the file first, then lock it, -then read it, then close and delete it. The C option to -L does the right thing. - -This method may be called multiple times during a program run. - -=head2 empty - - $profile->empty() - -Clears the Data hash without writing to disk. - -=head2 filename - - $filename = $profile->filename(); - -Get or set the filename. - -The filename can be specified as a CODE reference, in which case the referenced -code should return the filename to be used. The code will be called with the -profile object as its first argument. - -=head1 DATA FORMAT - -The data format written by DBI::ProfileDumper starts with a header -containing the version number of the module used to generate it. Then -a block of variable declarations describes the profile. After two -newlines, the profile data forms the body of the file. For example: - - DBI::ProfileDumper 2.003762 - Path = [ '!Statement', '!MethodName' ] - Program = t/42profile_data.t - - + 1 SELECT name FROM users WHERE id = ? - + 2 prepare - = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - + 2 execute - 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - + 2 fetchrow_hashref - = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - + 1 UPDATE users SET name = ? WHERE id = ? - + 2 prepare - = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - + 2 execute - = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 - -The lines beginning with C<+> signs signify keys. The number after -the C<+> sign shows the nesting level of the key. Lines beginning -with C<=> are the actual profile data, in the same order as -in DBI::Profile. - -Note that the same path may be present multiple times in the data file -since C may be called more than once. When read by -DBI::ProfileData the data points will be merged to produce a single -data set for each distinct path. - -The key strings are transformed in three ways. First, all backslashes -are doubled. Then all newlines and carriage-returns are transformed -into C<\n> and C<\r> respectively. Finally, any NULL bytes (C<\0>) -are entirely removed. When DBI::ProfileData reads the file the first -two transformations will be reversed, but NULL bytes will not be -restored. - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=cut - -# inherit from DBI::Profile -use DBI::Profile; - -our @ISA = ("DBI::Profile"); - -our $VERSION = "2.015325"; - -use Carp qw(croak); -use Fcntl qw(:flock); -use Symbol; - -my $HAS_FLOCK = (defined $ENV{DBI_PROFILE_FLOCK}) - ? $ENV{DBI_PROFILE_FLOCK} - : do { local $@; eval { flock STDOUT, 0; 1 } }; - -my $program_header; - - -# validate params and setup default -sub new { - my $pkg = shift; - my $self = $pkg->SUPER::new( - LockFile => $HAS_FLOCK, - @_, - ); - - # provide a default filename - $self->filename("dbi.prof") unless $self->filename; - - DBI->trace_msg("$self: @{[ %$self ]}\n",0) - if $self->{Trace} && $self->{Trace} >= 2; - - return $self; -} - - -# get/set filename to use -sub filename { - my $self = shift; - $self->{File} = shift if @_; - my $filename = $self->{File}; - $filename = $filename->($self) if ref($filename) eq 'CODE'; - return $filename; -} - - -# flush available data to disk -sub flush_to_disk { - my $self = shift; - my $class = ref $self; - my $filename = $self->filename; - my $data = $self->{Data}; - - if (1) { # make an option - if (not $data or ref $data eq 'HASH' && !%$data) { - DBI->trace_msg("flush_to_disk skipped for empty profile\n",0) if $self->{Trace}; - return undef; - } - } - - my $fh = gensym; - if (($self->{_wrote_header}||'') eq $filename) { - # append more data to the file - # XXX assumes that Path hasn't changed - open($fh, ">>", $filename) - or croak("Unable to open '$filename' for $class output: $!"); - } else { - # create new file (or overwrite existing) - if (-f $filename) { - my $bak = $filename.'.prev'; - unlink($bak); - rename($filename, $bak) - or warn "Error renaming $filename to $bak: $!\n"; - } - open($fh, ">", $filename) - or croak("Unable to open '$filename' for $class output: $!"); - } - # lock the file (before checking size and writing the header) - flock($fh, LOCK_EX) if $self->{LockFile}; - # write header if file is empty - typically because we just opened it - # in '>' mode, or perhaps we used '>>' but the file had been truncated externally. - if (-s $fh == 0) { - DBI->trace_msg("flush_to_disk wrote header to $filename\n",0) if $self->{Trace}; - $self->write_header($fh); - $self->{_wrote_header} = $filename; - } - - my $lines = $self->write_data($fh, $self->{Data}, 1); - DBI->trace_msg("flush_to_disk wrote $lines lines to $filename\n",0) if $self->{Trace}; - - close($fh) # unlocks the file - or croak("Error closing '$filename': $!"); - - $self->empty(); - - - return $filename; -} - - -# write header to a filehandle -sub write_header { - my ($self, $fh) = @_; - - # isolate us against globals which effect print - local($\, $,); - - # $self->VERSION can return undef during global destruction - my $version = $self->VERSION || $VERSION; - - # module name and version number - print $fh ref($self)." $version\n"; - - # print out Path (may contain CODE refs etc) - my @path_words = map { escape_key($_) } @{ $self->{Path} || [] }; - print $fh "Path = [ ", join(', ', @path_words), " ]\n"; - - # print out $0 and @ARGV - if (!$program_header) { - # XXX should really quote as well as escape - $program_header = "Program = " - . join(" ", map { escape_key($_) } $0, @ARGV) - . "\n"; - } - print $fh $program_header; - - # all done - print $fh "\n"; -} - - -# write data in the proscribed format -sub write_data { - my ($self, $fh, $data, $level) = @_; - - # XXX it's valid for $data to be an ARRAY ref, i.e., Path is empty. - # produce an empty profile for invalid $data - return 0 unless $data and UNIVERSAL::isa($data,'HASH'); - - # isolate us against globals which affect print - local ($\, $,); - - my $lines = 0; - while (my ($key, $value) = each(%$data)) { - # output a key - print $fh "+ $level ". escape_key($key). "\n"; - if (UNIVERSAL::isa($value,'ARRAY')) { - # output a data set for a leaf node - print $fh "= ".join(' ', @$value)."\n"; - $lines += 1; - } else { - # recurse through keys - this could be rewritten to use a - # stack for some small performance gain - $lines += $self->write_data($fh, $value, $level + 1); - } - } - return $lines; -} - - -# escape a key for output -sub escape_key { - my $key = shift; - $key =~ s!\\!\\\\!g; - $key =~ s!\n!\\n!g; - $key =~ s!\r!\\r!g; - $key =~ s!\0!!g; - return $key; -} - - -# flush data to disk when profile object goes out of scope -sub on_destroy { - shift->flush_to_disk(); -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper/Apache.pm b/dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper/Apache.pm deleted file mode 100644 index df0d35c..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/ProfileDumper/Apache.pm +++ /dev/null @@ -1,219 +0,0 @@ -package DBI::ProfileDumper::Apache; - -use strict; - -=head1 NAME - -DBI::ProfileDumper::Apache - capture DBI profiling data from Apache/mod_perl - -=head1 SYNOPSIS - -Add this line to your F: - - PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache - -(If you're using mod_perl2, see L for some additional notes.) - -Then restart your server. Access the code you wish to test using a -web browser, then shutdown your server. This will create a set of -F files in your Apache log directory. - -Get a profiling report with L: - - dbiprof /path/to/your/apache/logs/dbi.prof.* - -When you're ready to perform another profiling run, delete the old files and start again. - -=head1 DESCRIPTION - -This module interfaces DBI::ProfileDumper to Apache/mod_perl. Using -this module you can collect profiling data from mod_perl applications. -It works by creating a DBI::ProfileDumper data file for each Apache -process. These files are created in your Apache log directory. You -can then use the dbiprof utility to analyze the profile files. - -=head1 USAGE - -=head2 LOADING THE MODULE - -The easiest way to use this module is just to set the DBI_PROFILE -environment variable in your F: - - PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache - -The DBI will look after loading and using the module when the first DBI handle -is created. - -It's also possible to use this module by setting the Profile attribute -of any DBI handle: - - $dbh->{Profile} = "2/DBI::ProfileDumper::Apache"; - -See L for more possibilities, and L for full -details of the DBI's profiling mechanism. - -=head2 WRITING PROFILE DATA - -The profile data files will be written to your Apache log directory by default. - -The user that the httpd processes run as will need write access to the -directory. So, for example, if you're running the child httpds as user 'nobody' -and using chronolog to write to the logs directory, then you'll need to change -the default. - -You can change the destination directory either by specifying a C value -when creating the profile (like C in the L docs), -or you can use the C env var to change that. For example: - - PerlSetEnv DBI_PROFILE_APACHE_LOG_DIR /server_root/logs - -=head3 When using mod_perl2 - -Under mod_perl2 you'll need to either set the C env var, -or enable the mod_perl2 C option, like this: - - PerlOptions +GlobalRequest - -to the global config section you're about test with DBI::ProfileDumper::Apache. -If you don't do one of those then you'll see messages in your error_log similar to: - - DBI::ProfileDumper::Apache on_destroy failed: Global $r object is not available. Set: - PerlOptions +GlobalRequest in httpd.conf at ..../DBI/ProfileDumper/Apache.pm line 144 - -=head3 Naming the files - -The default file name is inherited from L via the -filename() method, but DBI::ProfileDumper::Apache appends the parent pid and -the current pid, separated by dots, to that name. - -=head3 Silencing the log - -By default a message is written to STDERR (i.e., the apache error_log file) -when flush_to_disk() is called (either explicitly, or implicitly via DESTROY). - -That's usually very useful. If you don't want the log message you can silence -it by setting the C attribute true. - - PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache/Quiet:1 - - $dbh->{Profile} = "!Statement/DBI::ProfileDumper/Quiet:1"; - - $dbh->{Profile} = DBI::ProfileDumper->new( - Path => [ '!Statement' ] - Quiet => 1 - ); - - -=head2 GATHERING PROFILE DATA - -Once you have the module loaded, use your application as you normally -would. Stop the webserver when your tests are complete. Profile data -files will be produced when Apache exits and you'll see something like -this in your error_log: - - DBI::ProfileDumper::Apache writing to /usr/local/apache/logs/dbi.prof.2604.2619 - -Now you can use dbiprof to examine the data: - - dbiprof /usr/local/apache/logs/dbi.prof.2604.* - -By passing dbiprof a list of all generated files, dbiprof will -automatically merge them into one result set. You can also pass -dbiprof sorting and querying options, see L for details. - -=head2 CLEANING UP - -Once you've made some code changes, you're ready to start again. -First, delete the old profile data files: - - rm /usr/local/apache/logs/dbi.prof.* - -Then restart your server and get back to work. - -=head1 OTHER ISSUES - -=head2 Memory usage - -DBI::Profile can use a lot of memory for very active applications because it -collects profiling data in memory for each distinct query run. -Calling C will write the current data to disk and free the -memory it's using. For example: - - $dbh->{Profile}->flush_to_disk() if $dbh->{Profile}; - -or, rather than flush every time, you could flush less often: - - $dbh->{Profile}->flush_to_disk() - if $dbh->{Profile} and ++$i % 100; - -=head1 AUTHOR - -Sam Tregar - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2002 Sam Tregar - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl 5 itself. - -=cut - -our $VERSION = "2.014121"; - -our @ISA = qw(DBI::ProfileDumper); - -use DBI::ProfileDumper; -use File::Spec; - -my $initial_pid = $$; - -use constant MP2 => ($ENV{MOD_PERL_API_VERSION} and $ENV{MOD_PERL_API_VERSION} == 2) ? 1 : 0; - -my $server_root_dir; - -if (MP2) { - require Apache2::ServerUtil; - $server_root_dir = Apache2::ServerUtil::server_root(); -} -else { - require Apache; - $server_root_dir = eval { Apache->server_root_relative('') } || "/tmp"; -} - - -sub _dirname { - my $self = shift; - return $self->{Dir} ||= $ENV{DBI_PROFILE_APACHE_LOG_DIR} - || File::Spec->catdir($server_root_dir, "logs"); -} - - -sub filename { - my $self = shift; - my $filename = $self->SUPER::filename(@_); - return $filename if not $filename; # not set yet - - # to be able to identify groups of profile files from the same set of - # apache processes, we include the parent pid in the file name - # as well as the pid. - my $group_pid = ($$ eq $initial_pid) ? $$ : getppid(); - $filename .= ".$group_pid.$$"; - - return $filename if File::Spec->file_name_is_absolute($filename); - return File::Spec->catfile($self->_dirname, $filename); -} - - -sub flush_to_disk { - my $self = shift; - - my $filename = $self->SUPER::flush_to_disk(@_); - - print STDERR ref($self)." pid$$ written to $filename\n" - if $filename && not $self->{Quiet}; - - return $filename; -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBI/ProfileSubs.pm b/dbLifeLog/DBI-1.641/lib/DBI/ProfileSubs.pm deleted file mode 100644 index 015462b..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/ProfileSubs.pm +++ /dev/null @@ -1,50 +0,0 @@ -package DBI::ProfileSubs; - -our $VERSION = "0.009396"; - -=head1 NAME - -DBI::ProfileSubs - Subroutines for dynamic profile Path - -=head1 SYNOPSIS - - DBI_PROFILE='&norm_std_n3' prog.pl - -This is new and still experimental. - -=head1 TO DO - -Define come kind of naming convention for the subs. - -=cut - -use strict; -use warnings; - - -# would be good to refactor these regex into separate subs and find some -# way to compose them in various combinations into multiple subs. -# Perhaps via AUTOLOAD where \&auto_X_Y_Z creates a sub that does X, Y, and Z. -# The final subs always need to be very fast. -# - -sub norm_std_n3 { - # my ($h, $method_name) = @_; - local $_ = $_; - - s/\b\d+\b//g; # 42 -> - s/\b0x[0-9A-Fa-f]+\b//g; # 0xFE -> - - s/'.*?'/''/g; # single quoted strings (doesn't handle escapes) - s/".*?"/""/g; # double quoted strings (doesn't handle escapes) - - # convert names like log20001231 into log - s/([a-z_]+)(\d{3,})\b/${1}/ig; - - # abbreviate massive "in (...)" statements and similar - s!((\s*<[NS]>\s*,\s*){100,})!sprintf("$2,",length($1)/2)!eg; - - return $_; -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBI/ProxyServer.pm b/dbLifeLog/DBI-1.641/lib/DBI/ProxyServer.pm deleted file mode 100644 index ef21849..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/ProxyServer.pm +++ /dev/null @@ -1,897 +0,0 @@ -# $Header: /home/timbo/dbi/lib/DBI/RCS/ProxyServer.pm,v 11.9 2003/05/14 11:08:17 timbo Exp $ -# -*- perl -*- -# -# DBI::ProxyServer - a proxy server for DBI drivers -# -# Copyright (c) 1997 Jochen Wiedmann -# -# The DBD::Proxy module is free software; you can redistribute it and/or -# modify it under the same terms as Perl itself. In particular permission -# is granted to Tim Bunce for distributing this as a part of the DBI. -# -# -# Author: Jochen Wiedmann -# Am Eisteich 9 -# 72555 Metzingen -# Germany -# -# Email: joe@ispsoft.de -# Phone: +49 7123 14881 -# -# -############################################################################## - - -require 5.004; -use strict; - -use RPC::PlServer 0.2001; -require DBI; -require Config; - - -package DBI::ProxyServer; - - - -############################################################################ -# -# Constants -# -############################################################################ - -use vars qw($VERSION @ISA); - -$VERSION = "0.3005"; -@ISA = qw(RPC::PlServer DBI); - - -# Most of the options below are set to default values, we note them here -# just for the sake of documentation. -my %DEFAULT_SERVER_OPTIONS; -{ - my $o = \%DEFAULT_SERVER_OPTIONS; - $o->{'chroot'} = undef, # To be used in the initfile, - # after loading the required - # DBI drivers. - $o->{'clients'} = - [ { 'mask' => '.*', - 'accept' => 1, - 'cipher' => undef - } - ]; - $o->{'configfile'} = '/etc/dbiproxy.conf' if -f '/etc/dbiproxy.conf'; - $o->{'debug'} = 0; - $o->{'facility'} = 'daemon'; - $o->{'group'} = undef; - $o->{'localaddr'} = undef; # Bind to any local IP number - $o->{'localport'} = undef; # Must set port number on the - # command line. - $o->{'logfile'} = undef; # Use syslog or EventLog. - - # XXX don't restrict methods that can be called (trust users once connected) - $o->{'XXX_methods'} = { - 'DBI::ProxyServer' => { - 'Version' => 1, - 'NewHandle' => 1, - 'CallMethod' => 1, - 'DestroyHandle' => 1 - }, - 'DBI::ProxyServer::db' => { - 'prepare' => 1, - 'commit' => 1, - 'rollback' => 1, - 'STORE' => 1, - 'FETCH' => 1, - 'func' => 1, - 'quote' => 1, - 'type_info_all' => 1, - 'table_info' => 1, - 'disconnect' => 1, - }, - 'DBI::ProxyServer::st' => { - 'execute' => 1, - 'STORE' => 1, - 'FETCH' => 1, - 'func' => 1, - 'fetch' => 1, - 'finish' => 1 - } - }; - if ($Config::Config{'usethreads'} eq 'define') { - $o->{'mode'} = 'threads'; - } elsif ($Config::Config{'d_fork'} eq 'define') { - $o->{'mode'} = 'fork'; - } else { - $o->{'mode'} = 'single'; - } - # No pidfile by default, configuration must provide one if needed - $o->{'pidfile'} = 'none'; - $o->{'user'} = undef; -}; - - -############################################################################ -# -# Name: Version -# -# Purpose: Return version string -# -# Inputs: $class - This class -# -# Result: Version string; suitable for printing by "--version" -# -############################################################################ - -sub Version { - my $version = $DBI::ProxyServer::VERSION; - "DBI::ProxyServer $version, Copyright (C) 1998, Jochen Wiedmann"; -} - - -############################################################################ -# -# Name: AcceptApplication -# -# Purpose: Verify DBI DSN -# -# Inputs: $self - This instance -# $dsn - DBI dsn -# -# Returns: TRUE for a valid DSN, FALSE otherwise -# -############################################################################ - -sub AcceptApplication { - my $self = shift; my $dsn = shift; - $dsn =~ /^dbi:\w+:/i; -} - - -############################################################################ -# -# Name: AcceptVersion -# -# Purpose: Verify requested DBI version -# -# Inputs: $self - Instance -# $version - DBI version being requested -# -# Returns: TRUE for ok, FALSE otherwise -# -############################################################################ - -sub AcceptVersion { - my $self = shift; my $version = shift; - require DBI; - DBI::ProxyServer->init_rootclass(); - $DBI::VERSION >= $version; -} - - -############################################################################ -# -# Name: AcceptUser -# -# Purpose: Verify user and password by connecting to the client and -# creating a database connection -# -# Inputs: $self - Instance -# $user - User name -# $password - Password -# -############################################################################ - -sub AcceptUser { - my $self = shift; my $user = shift; my $password = shift; - return 0 if (!$self->SUPER::AcceptUser($user, $password)); - my $dsn = $self->{'application'}; - $self->Debug("Connecting to $dsn as $user"); - local $ENV{DBI_AUTOPROXY} = ''; # :-) - $self->{'dbh'} = eval { - DBI::ProxyServer->connect($dsn, $user, $password, - { 'PrintError' => 0, - 'Warn' => 0, - 'RaiseError' => 1, - 'HandleError' => sub { - my $err = $_[1]->err; - my $state = $_[1]->state || ''; - $_[0] .= " [err=$err,state=$state]"; - return 0; - } }) - }; - if ($@) { - $self->Error("Error while connecting to $dsn as $user: $@"); - return 0; - } - [1, $self->StoreHandle($self->{'dbh'}) ]; -} - - -sub CallMethod { - my $server = shift; - my $dbh = $server->{'dbh'}; - # We could store the private_server attribute permanently in - # $dbh. However, we'd have a reference loop in that case and - # I would be concerned about garbage collection. :-( - $dbh->{'private_server'} = $server; - $server->Debug("CallMethod: => " . do { local $^W; join(",", @_)}); - my @result = eval { $server->SUPER::CallMethod(@_) }; - my $msg = $@; - undef $dbh->{'private_server'}; - if ($msg) { - $server->Debug("CallMethod died with: $@"); - die $msg; - } else { - $server->Debug("CallMethod: <= " . do { local $^W; join(",", @result) }); - } - @result; -} - - -sub main { - my $server = DBI::ProxyServer->new(\%DEFAULT_SERVER_OPTIONS, \@_); - $server->Bind(); -} - - -############################################################################ -# -# The DBI part of the proxyserver is implemented as a DBI subclass. -# Thus we can reuse some of the DBI methods and overwrite only -# those that need additional handling. -# -############################################################################ - -package DBI::ProxyServer::dr; - -@DBI::ProxyServer::dr::ISA = qw(DBI::dr); - - -package DBI::ProxyServer::db; - -@DBI::ProxyServer::db::ISA = qw(DBI::db); - -sub prepare { - my($dbh, $statement, $attr, $params, $proto_ver) = @_; - my $server = $dbh->{'private_server'}; - if (my $client = $server->{'client'}) { - if ($client->{'sql'}) { - if ($statement =~ /^\s*(\S+)/) { - my $st = $1; - if (!($statement = $client->{'sql'}->{$st})) { - die "Unknown SQL query: $st"; - } - } else { - die "Cannot parse restricted SQL statement: $statement"; - } - } - } - my $sth = $dbh->SUPER::prepare($statement, $attr); - my $handle = $server->StoreHandle($sth); - - if ( $proto_ver and $proto_ver > 1 ) { - $sth->{private_proxyserver_described} = 0; - return $handle; - - } else { - # The difference between the usual prepare and ours is that we implement - # a combined prepare/execute. The DBD::Proxy driver doesn't call us for - # prepare. Only if an execute happens, then we are called with method - # "prepare". Further execute's are called as "execute". - my @result = $sth->execute($params); - my ($NAME, $TYPE); - my $NUM_OF_FIELDS = $sth->{NUM_OF_FIELDS}; - if ($NUM_OF_FIELDS) { # is a SELECT - $NAME = $sth->{NAME}; - $TYPE = $sth->{TYPE}; - } - ($handle, $NUM_OF_FIELDS, $sth->{'NUM_OF_PARAMS'}, - $NAME, $TYPE, @result); - } -} - -sub table_info { - my $dbh = shift; - my $sth = $dbh->SUPER::table_info(); - my $numFields = $sth->{'NUM_OF_FIELDS'}; - my $names = $sth->{'NAME'}; - my $types = $sth->{'TYPE'}; - - # We wouldn't need to send all the rows at this point, instead we could - # make use of $rsth->fetch() on the client as usual. - # The problem is that some drivers (namely DBD::ExampleP, DBD::mysql and - # DBD::mSQL) are returning foreign sth's here, thus an instance of - # DBI::st and not DBI::ProxyServer::st. We could fix this by permitting - # the client to execute method DBI::st, but I don't like this. - my @rows; - while (my ($row) = $sth->fetch()) { - last unless defined $row; - push(@rows, [@$row]); - } - ($numFields, $names, $types, @rows); -} - - -package DBI::ProxyServer::st; - -@DBI::ProxyServer::st::ISA = qw(DBI::st); - -sub execute { - my $sth = shift; my $params = shift; my $proto_ver = shift; - my @outParams; - if ($params) { - for (my $i = 0; $i < @$params;) { - my $param = $params->[$i++]; - if (!ref($param)) { - $sth->bind_param($i, $param); - } - else { - if (!ref(@$param[0])) {#It's not a reference - $sth->bind_param($i, @$param); - } - else { - $sth->bind_param_inout($i, @$param); - my $ref = shift @$param; - push(@outParams, $ref); - } - } - } - } - my $rows = $sth->SUPER::execute(); - if ( $proto_ver and $proto_ver > 1 and not $sth->{private_proxyserver_described} ) { - my ($NAME, $TYPE); - my $NUM_OF_FIELDS = $sth->{NUM_OF_FIELDS}; - if ($NUM_OF_FIELDS) { # is a SELECT - $NAME = $sth->{NAME}; - $TYPE = $sth->{TYPE}; - } - $sth->{private_proxyserver_described} = 1; - # First execution, we ship back description. - return ($rows, $NUM_OF_FIELDS, $sth->{'NUM_OF_PARAMS'}, $NAME, $TYPE, @outParams); - } - ($rows, @outParams); -} - -sub fetch { - my $sth = shift; my $numRows = shift || 1; - my($ref, @rows); - while ($numRows-- && ($ref = $sth->SUPER::fetch())) { - push(@rows, [@$ref]); - } - @rows; -} - - -1; - - -__END__ - -=head1 NAME - -DBI::ProxyServer - a server for the DBD::Proxy driver - -=head1 SYNOPSIS - - use DBI::ProxyServer; - DBI::ProxyServer::main(@ARGV); - -=head1 DESCRIPTION - -DBI::Proxy Server is a module for implementing a proxy for the DBI proxy -driver, DBD::Proxy. It allows access to databases over the network if the -DBMS does not offer networked operations. But the proxy server might be -useful for you, even if you have a DBMS with integrated network -functionality: It can be used as a DBI proxy in a firewalled environment. - -DBI::ProxyServer runs as a daemon on the machine with the DBMS or on the -firewall. The client connects to the agent using the DBI driver DBD::Proxy, -thus in the exactly same way than using DBD::mysql, DBD::mSQL or any other -DBI driver. - -The agent is implemented as a RPC::PlServer application. Thus you have -access to all the possibilities of this module, in particular encryption -and a similar configuration file. DBI::ProxyServer adds the possibility of -query restrictions: You can define a set of queries that a client may -execute and restrict access to those. (Requires a DBI driver that supports -parameter binding.) See L. - -The provided driver script, L, may either be used as it is or -used as the basis for a local version modified to meet your needs. - -=head1 OPTIONS - -When calling the DBI::ProxyServer::main() function, you supply an -array of options. These options are parsed by the Getopt::Long module. -The ProxyServer inherits all of RPC::PlServer's and hence Net::Daemon's -options and option handling, in particular the ability to read -options from either the command line or a config file. See -L. See L. Available options include - -=over 4 - -=item I (B<--chroot=dir>) - -(UNIX only) After doing a bind(), change root directory to the given -directory by doing a chroot(). This is useful for security, but it -restricts the environment a lot. For example, you need to load DBI -drivers in the config file or you have to create hard links to Unix -sockets, if your drivers are using them. For example, with MySQL, a -config file might contain the following lines: - - my $rootdir = '/var/dbiproxy'; - my $unixsockdir = '/tmp'; - my $unixsockfile = 'mysql.sock'; - foreach $dir ($rootdir, "$rootdir$unixsockdir") { - mkdir 0755, $dir; - } - link("$unixsockdir/$unixsockfile", - "$rootdir$unixsockdir/$unixsockfile"); - require DBD::mysql; - - { - 'chroot' => $rootdir, - ... - } - -If you don't know chroot(), think of an FTP server where you can see a -certain directory tree only after logging in. See also the --group and ---user options. - -=item I - -An array ref with a list of clients. Clients are hash refs, the attributes -I (0 for denying access and 1 for permitting) and I, a Perl -regular expression for the clients IP number or its host name. - -=item I (B<--configfile=file>) - -Config files are assumed to return a single hash ref that overrides the -arguments of the new method. However, command line arguments in turn take -precedence over the config file. See the L<"CONFIGURATION FILE"> section -below for details on the config file. - -=item I (B<--debug>) - -Turn debugging mode on. Mainly this asserts that logging messages of -level "debug" are created. - -=item I (B<--facility=mode>) - -(UNIX only) Facility to use for L. The default is -B. - -=item I (B<--group=gid>) - -After doing a bind(), change the real and effective GID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --user option. - -GID's can be passed as group names or numeric values. - -=item I (B<--localaddr=ip>) - -By default a daemon is listening to any IP number that a machine -has. This attribute allows one to restrict the server to the given -IP number. - -=item I (B<--localport=port>) - -This attribute sets the port on which the daemon is listening. It -must be given somehow, as there's no default. - -=item I (B<--logfile=file>) - -Be default logging messages will be written to the syslog (Unix) or -to the event log (Windows NT). On other operating systems you need to -specify a log file. The special value "STDERR" forces logging to -stderr. See L for details. - -=item I (B<--mode=modename>) - -The server can run in three different modes, depending on the environment. - -If you are running Perl 5.005 and did compile it for threads, then the -server will create a new thread for each connection. The thread will -execute the server's Run() method and then terminate. This mode is the -default, you can force it with "--mode=threads". - -If threads are not available, but you have a working fork(), then the -server will behave similar by creating a new process for each connection. -This mode will be used automatically in the absence of threads or if -you use the "--mode=fork" option. - -Finally there's a single-connection mode: If the server has accepted a -connection, he will enter the Run() method. No other connections are -accepted until the Run() method returns (if the client disconnects). -This operation mode is useful if you have neither threads nor fork(), -for example on the Macintosh. For debugging purposes you can force this -mode with "--mode=single". - -=item I (B<--pidfile=file>) - -(UNIX only) If this option is present, a PID file will be created at the -given location. Default is to not create a pidfile. - -=item I (B<--user=uid>) - -After doing a bind(), change the real and effective UID to the given. -This is useful, if you want your server to bind to a privileged port -(<1024), but don't want the server to execute as root. See also -the --group and the --chroot options. - -UID's can be passed as group names or numeric values. - -=item I (B<--version>) - -Suppresses startup of the server; instead the version string will -be printed and the program exits immediately. - -=back - -=head1 SHUTDOWN - -DBI::ProxyServer is built on L which is, in turn, built on L. - -You should refer to L for how to shutdown the server, except that -you can't because it's not currently documented there (as of v0.43). -The bottom-line is that it seems that there's no support for graceful shutdown. - -=head1 CONFIGURATION FILE - -The configuration file is just that of I or I -with some additional attributes in the client list. - -The config file is a Perl script. At the top of the file you may include -arbitrary Perl source, for example load drivers at the start (useful -to enhance performance), prepare a chroot environment and so on. - -The important thing is that you finally return a hash ref of option -name/value pairs. The possible options are listed above. - -All possibilities of Net::Daemon and RPC::PlServer apply, in particular - -=over 4 - -=item Host and/or User dependent access control - -=item Host and/or User dependent encryption - -=item Changing UID and/or GID after binding to the port - -=item Running in a chroot() environment - -=back - -Additionally the server offers you query restrictions. Suggest the -following client list: - - 'clients' => [ - { 'mask' => '^admin\.company\.com$', - 'accept' => 1, - 'users' => [ 'root', 'wwwrun' ], - }, - { - 'mask' => '^admin\.company\.com$', - 'accept' => 1, - 'users' => [ 'root', 'wwwrun' ], - 'sql' => { - 'select' => 'SELECT * FROM foo', - 'insert' => 'INSERT INTO foo VALUES (?, ?, ?)' - } - } - -then only the users root and wwwrun may connect from admin.company.com, -executing arbitrary queries, but only wwwrun may connect from other -hosts and is restricted to - - $sth->prepare("select"); - -or - - $sth->prepare("insert"); - -which in fact are "SELECT * FROM foo" or "INSERT INTO foo VALUES (?, ?, ?)". - - -=head1 Proxyserver Configuration file (bigger example) - -This section tells you how to restrict a DBI-Proxy: Not every user from -every workstation shall be able to execute every query. - -There is a perl program "dbiproxy" which runs on a machine which is able -to connect to all the databases we wish to reach. All Perl-DBD-drivers must -be installed on this machine. You can also reach databases for which drivers -are not available on the machine where you run the program querying the -database, e.g. ask MS-Access-database from Linux. - -Create a configuration file "proxy_oracle.cfg" at the dbproxy-server: - - { - # This shall run in a shell or a DOS-window - # facility => 'daemon', - pidfile => 'your_dbiproxy.pid', - logfile => 1, - debug => 0, - mode => 'single', - localport => '12400', - - # Access control, the first match in this list wins! - # So the order is important - clients => [ - # hint to organize: - # the most specialized rules for single machines/users are 1st - # then the denying rules - # then the rules about whole networks - - # rule: internal_webserver - # desc: to get statistical information - { - # this IP-address only is meant - mask => '^10\.95\.81\.243$', - # accept (not defer) connections like this - accept => 1, - # only users from this list - # are allowed to log on - users => [ 'informationdesk' ], - # only this statistical query is allowed - # to get results for a web-query - sql => { - alive => 'select count(*) from dual', - statistic_area => 'select count(*) from e01admin.e01e203 where geb_bezei like ?', - } - }, - - # rule: internal_bad_guy_1 - { - mask => '^10\.95\.81\.1$', - accept => 0, - }, - - # rule: employee_workplace - # desc: get detailed information - { - # any IP-address is meant here - mask => '^10\.95\.81\.(\d+)$', - # accept (not defer) connections like this - accept => 1, - # only users from this list - # are allowed to log on - users => [ 'informationdesk', 'lippmann' ], - # all these queries are allowed: - sql => { - search_city => 'select ort_nr, plz, ort from e01admin.e01e200 where plz like ?', - search_area => 'select gebiettyp, geb_bezei from e01admin.e01e203 where geb_bezei like ? or geb_bezei like ?', - } - }, - - # rule: internal_bad_guy_2 - # This does NOT work, because rule "employee_workplace" hits - # with its ip-address-mask of the whole network - { - # don't accept connection from this ip-address - mask => '^10\.95\.81\.5$', - accept => 0, - } - ] - } - -Start the proxyserver like this: - - rem well-set Oracle_home needed for Oracle - set ORACLE_HOME=d:\oracle\ora81 - dbiproxy --configfile proxy_oracle.cfg - - -=head2 Testing the connection from a remote machine - -Call a program "dbish" from your commandline. I take the machine from rule "internal_webserver" - - dbish "dbi:Proxy:hostname=oracle.zdf;port=12400;dsn=dbi:Oracle:e01" informationdesk xxx - -There will be a shell-prompt: - - informationdesk@dbi...> alive - - Current statement buffer (enter '/'...): - alive - - informationdesk@dbi...> / - COUNT(*) - '1' - [1 rows of 1 fields returned] - - -=head2 Testing the connection with a perl-script - -Create a perl-script like this: - - # file: oratest.pl - # call me like this: perl oratest.pl user password - - use strict; - use DBI; - - my $user = shift || die "Usage: $0 user password"; - my $pass = shift || die "Usage: $0 user password"; - my $config = { - dsn_at_proxy => "dbi:Oracle:e01", - proxy => "hostname=oechsle.zdf;port=12400", - }; - my $dsn = sprintf "dbi:Proxy:%s;dsn=%s", - $config->{proxy}, - $config->{dsn_at_proxy}; - - my $dbh = DBI->connect( $dsn, $user, $pass ) - || die "connect did not work: $DBI::errstr"; - - my $sql = "search_city"; - printf "%s\n%s\n%s\n", "="x40, $sql, "="x40; - my $cur = $dbh->prepare($sql); - $cur->bind_param(1,'905%'); - &show_result ($cur); - - my $sql = "search_area"; - printf "%s\n%s\n%s\n", "="x40, $sql, "="x40; - my $cur = $dbh->prepare($sql); - $cur->bind_param(1,'Pfarr%'); - $cur->bind_param(2,'Bronnamberg%'); - &show_result ($cur); - - my $sql = "statistic_area"; - printf "%s\n%s\n%s\n", "="x40, $sql, "="x40; - my $cur = $dbh->prepare($sql); - $cur->bind_param(1,'Pfarr%'); - &show_result ($cur); - - $dbh->disconnect; - exit; - - - sub show_result { - my $cur = shift; - unless ($cur->execute()) { - print "Could not execute\n"; - return; - } - - my $rownum = 0; - while (my @row = $cur->fetchrow_array()) { - printf "Row is: %s\n", join(", ",@row); - if ($rownum++ > 5) { - print "... and so on\n"; - last; - } - } - $cur->finish; - } - -The result - - C:\>perl oratest.pl informationdesk xxx - ======================================== - search_city - ======================================== - Row is: 3322, 9050, Chemnitz - Row is: 3678, 9051, Chemnitz - Row is: 10447, 9051, Chemnitz - Row is: 12128, 9051, Chemnitz - Row is: 10954, 90513, Zirndorf - Row is: 5808, 90513, Zirndorf - Row is: 5715, 90513, Zirndorf - ... and so on - ======================================== - search_area - ======================================== - Row is: 101, Bronnamberg - Row is: 400, Pfarramt Zirndorf - Row is: 400, Pfarramt Rosstal - Row is: 400, Pfarramt Oberasbach - Row is: 401, Pfarramt Zirndorf - Row is: 401, Pfarramt Rosstal - ======================================== - statistic_area - ======================================== - DBD::Proxy::st execute failed: Server returned error: Failed to execute method CallMethod: Unknown SQL query: statistic_area at E:/Perl/site/lib/DBI/ProxyServer.pm line 258. - Could not execute - - -=head2 How the configuration works - -The most important section to control access to your dbi-proxy is "client=>" -in the file "proxy_oracle.cfg": - -Controlling which person at which machine is allowed to access - -=over 4 - -=item * "mask" is a perl regular expression against the plain ip-address of the machine which wishes to connect _or_ the reverse-lookup from a nameserver. - -=item * "accept" tells the dbiproxy-server whether ip-adresse like in "mask" are allowed to connect or not (0/1) - -=item * "users" is a reference to a list of usernames which must be matched, this is NOT a regular expression. - -=back - -Controlling which SQL-statements are allowed - -You can put every SQL-statement you like in simply omitting "sql => ...", but the more important thing is to restrict the connection so that only allowed queries are possible. - -If you include an sql-section in your config-file like this: - - sql => { - alive => 'select count(*) from dual', - statistic_area => 'select count(*) from e01admin.e01e203 where geb_bezei like ?', - } - -The user is allowed to put two queries against the dbi-proxy. The queries are _not_ "select count(*)...", the queries are "alive" and "statistic_area"! These keywords are replaced by the real query. So you can run a query for "alive": - - my $sql = "alive"; - my $cur = $dbh->prepare($sql); - ... - -The flexibility is that you can put parameters in the where-part of the query so the query are not static. Simply replace a value in the where-part of the query through a question mark and bind it as a parameter to the query. - - my $sql = "statistic_area"; - my $cur = $dbh->prepare($sql); - $cur->bind_param(1,'905%'); - # A second parameter would be called like this: - # $cur->bind_param(2,'98%'); - -The result is this query: - - select count(*) from e01admin.e01e203 - where geb_bezei like '905%' - -Don't try to put parameters into the sql-query like this: - - # Does not work like you think. - # Only the first word of the query is parsed, - # so it's changed to "statistic_area", the rest is omitted. - # You _have_ to work with $cur->bind_param. - my $sql = "statistic_area 905%"; - my $cur = $dbh->prepare($sql); - ... - - -=head2 Problems - -=over 4 - -=item * I don't know how to restrict users to special databases. - -=item * I don't know how to pass query-parameters via dbish - -=back - - -=head1 SECURITY WARNING - -L used underneath is not secure due to serializing and -deserializing data with L module. Use the proxy driver only in -trusted environment. - - -=head1 AUTHOR - - Copyright (c) 1997 Jochen Wiedmann - Am Eisteich 9 - 72555 Metzingen - Germany - - Email: joe@ispsoft.de - Phone: +49 7123 14881 - -The DBI::ProxyServer module is free software; you can redistribute it -and/or modify it under the same terms as Perl itself. In particular -permission is granted to Tim Bunce for distributing this as a part of -the DBI. - - -=head1 SEE ALSO - -L, L, L, L, -L, L, L, -L, L, L diff --git a/dbLifeLog/DBI-1.641/lib/DBI/PurePerl.pm b/dbLifeLog/DBI-1.641/lib/DBI/PurePerl.pm deleted file mode 100644 index 32a8f1f..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/PurePerl.pm +++ /dev/null @@ -1,1279 +0,0 @@ -######################################################################## -package # hide from PAUSE - DBI; -# vim: ts=8:sw=4 -######################################################################## -# -# Copyright (c) 2002,2003 Tim Bunce Ireland. -# -# See COPYRIGHT section in DBI.pm for usage and distribution rights. -# -######################################################################## -# -# Please send patches and bug reports to -# -# Jeff Zucker with cc to -# -######################################################################## - -use strict; -use Carp; -require Symbol; - -require utf8; -*utf8::is_utf8 = sub { # hack for perl 5.6 - require bytes; - return unless defined $_[0]; - return !(length($_[0]) == bytes::length($_[0])) -} unless defined &utf8::is_utf8; - -$DBI::PurePerl = $ENV{DBI_PUREPERL} || 1; -$DBI::PurePerl::VERSION = "2.014286"; - -$DBI::neat_maxlen ||= 400; - -$DBI::tfh = Symbol::gensym(); -open $DBI::tfh, ">&STDERR" or warn "Can't dup STDERR: $!"; -select( (select($DBI::tfh), $| = 1)[0] ); # autoflush - -# check for weaken support, used by ChildHandles -my $HAS_WEAKEN = eval { - require Scalar::Util; - # this will croak() if this Scalar::Util doesn't have a working weaken(). - Scalar::Util::weaken( my $test = [] ); - 1; -}; - -%DBI::last_method_except = map { $_=>1 } qw(DESTROY _set_fbav set_err); - -use constant SQL_ALL_TYPES => 0; -use constant SQL_ARRAY => 50; -use constant SQL_ARRAY_LOCATOR => 51; -use constant SQL_BIGINT => (-5); -use constant SQL_BINARY => (-2); -use constant SQL_BIT => (-7); -use constant SQL_BLOB => 30; -use constant SQL_BLOB_LOCATOR => 31; -use constant SQL_BOOLEAN => 16; -use constant SQL_CHAR => 1; -use constant SQL_CLOB => 40; -use constant SQL_CLOB_LOCATOR => 41; -use constant SQL_DATE => 9; -use constant SQL_DATETIME => 9; -use constant SQL_DECIMAL => 3; -use constant SQL_DOUBLE => 8; -use constant SQL_FLOAT => 6; -use constant SQL_GUID => (-11); -use constant SQL_INTEGER => 4; -use constant SQL_INTERVAL => 10; -use constant SQL_INTERVAL_DAY => 103; -use constant SQL_INTERVAL_DAY_TO_HOUR => 108; -use constant SQL_INTERVAL_DAY_TO_MINUTE => 109; -use constant SQL_INTERVAL_DAY_TO_SECOND => 110; -use constant SQL_INTERVAL_HOUR => 104; -use constant SQL_INTERVAL_HOUR_TO_MINUTE => 111; -use constant SQL_INTERVAL_HOUR_TO_SECOND => 112; -use constant SQL_INTERVAL_MINUTE => 105; -use constant SQL_INTERVAL_MINUTE_TO_SECOND => 113; -use constant SQL_INTERVAL_MONTH => 102; -use constant SQL_INTERVAL_SECOND => 106; -use constant SQL_INTERVAL_YEAR => 101; -use constant SQL_INTERVAL_YEAR_TO_MONTH => 107; -use constant SQL_LONGVARBINARY => (-4); -use constant SQL_LONGVARCHAR => (-1); -use constant SQL_MULTISET => 55; -use constant SQL_MULTISET_LOCATOR => 56; -use constant SQL_NUMERIC => 2; -use constant SQL_REAL => 7; -use constant SQL_REF => 20; -use constant SQL_ROW => 19; -use constant SQL_SMALLINT => 5; -use constant SQL_TIME => 10; -use constant SQL_TIMESTAMP => 11; -use constant SQL_TINYINT => (-6); -use constant SQL_TYPE_DATE => 91; -use constant SQL_TYPE_TIME => 92; -use constant SQL_TYPE_TIMESTAMP => 93; -use constant SQL_TYPE_TIMESTAMP_WITH_TIMEZONE => 95; -use constant SQL_TYPE_TIME_WITH_TIMEZONE => 94; -use constant SQL_UDT => 17; -use constant SQL_UDT_LOCATOR => 18; -use constant SQL_UNKNOWN_TYPE => 0; -use constant SQL_VARBINARY => (-3); -use constant SQL_VARCHAR => 12; -use constant SQL_WCHAR => (-8); -use constant SQL_WLONGVARCHAR => (-10); -use constant SQL_WVARCHAR => (-9); - -# for Cursor types -use constant SQL_CURSOR_FORWARD_ONLY => 0; -use constant SQL_CURSOR_KEYSET_DRIVEN => 1; -use constant SQL_CURSOR_DYNAMIC => 2; -use constant SQL_CURSOR_STATIC => 3; -use constant SQL_CURSOR_TYPE_DEFAULT => SQL_CURSOR_FORWARD_ONLY; - -use constant IMA_HAS_USAGE => 0x0001; #/* check parameter usage */ -use constant IMA_FUNC_REDIRECT => 0x0002; #/* is $h->func(..., "method")*/ -use constant IMA_KEEP_ERR => 0x0004; #/* don't reset err & errstr */ -use constant IMA_KEEP_ERR_SUB => 0x0008; #/* '' if in nested call */ -use constant IMA_NO_TAINT_IN => 0x0010; #/* don't check for tainted args*/ -use constant IMA_NO_TAINT_OUT => 0x0020; #/* don't taint results */ -use constant IMA_COPY_UP_STMT => 0x0040; #/* copy sth Statement to dbh */ -use constant IMA_END_WORK => 0x0080; #/* set on commit & rollback */ -use constant IMA_STUB => 0x0100; #/* do nothing eg $dbh->connected */ -use constant IMA_CLEAR_STMT => 0x0200; #/* clear Statement before call */ -use constant IMA_UNRELATED_TO_STMT=> 0x0400; #/* profile as empty Statement */ -use constant IMA_NOT_FOUND_OKAY => 0x0800; #/* not error if not found */ -use constant IMA_EXECUTE => 0x1000; #/* do/execute: DBIcf_Executed */ -use constant IMA_SHOW_ERR_STMT => 0x2000; #/* dbh meth relates to Statement*/ -use constant IMA_HIDE_ERR_PARAMVALUES => 0x4000; #/* ParamValues are not relevant */ -use constant IMA_IS_FACTORY => 0x8000; #/* new h ie connect & prepare */ -use constant IMA_CLEAR_CACHED_KIDS => 0x10000; #/* clear CachedKids before call */ - -use constant DBIstcf_STRICT => 0x0001; -use constant DBIstcf_DISCARD_STRING => 0x0002; - -my %is_flag_attribute = map {$_ =>1 } qw( - Active - AutoCommit - ChopBlanks - CompatMode - Executed - Taint - TaintIn - TaintOut - InactiveDestroy - AutoInactiveDestroy - LongTruncOk - MultiThread - PrintError - PrintWarn - RaiseError - ShowErrorStatement - Warn -); -my %is_valid_attribute = map {$_ =>1 } (keys %is_flag_attribute, qw( - ActiveKids - Attribution - BegunWork - CachedKids - Callbacks - ChildHandles - CursorName - Database - DebugDispatch - Driver - Err - Errstr - ErrCount - FetchHashKeyName - HandleError - HandleSetErr - ImplementorClass - Kids - LongReadLen - NAME NAME_uc NAME_lc NAME_uc_hash NAME_lc_hash - NULLABLE - NUM_OF_FIELDS - NUM_OF_PARAMS - Name - PRECISION - ParamValues - Profile - Provider - ReadOnly - RootClass - RowCacheSize - RowsInCache - SCALE - State - Statement - TYPE - Type - TraceLevel - Username - Version -)); - -sub valid_attribute { - my $attr = shift; - return 1 if $is_valid_attribute{$attr}; - return 1 if $attr =~ m/^[a-z]/; # starts with lowercase letter - return 0 -} - -my $initial_setup; -sub initial_setup { - $initial_setup = 1; - print $DBI::tfh __FILE__ . " version " . $DBI::PurePerl::VERSION . "\n" - if $DBI::dbi_debug & 0xF; - untie $DBI::err; - untie $DBI::errstr; - untie $DBI::state; - untie $DBI::rows; - #tie $DBI::lasth, 'DBI::var', '!lasth'; # special case: return boolean -} - -sub _install_method { - my ( $caller, $method, $from, $param_hash ) = @_; - initial_setup() unless $initial_setup; - - my ($class, $method_name) = $method =~ /^[^:]+::(.+)::(.+)$/; - my $bitmask = $param_hash->{'O'} || 0; - my @pre_call_frag; - - return if $method_name eq 'can'; - - push @pre_call_frag, q{ - delete $h->{CachedKids}; - # ignore DESTROY for outer handle (DESTROY for inner likely to follow soon) - return if $h_inner; - # handle AutoInactiveDestroy and InactiveDestroy - $h->{InactiveDestroy} = 1 - if $h->{AutoInactiveDestroy} and $$ != $h->{dbi_pp_pid}; - $h->{Active} = 0 - if $h->{InactiveDestroy}; - # copy err/errstr/state up to driver so $DBI::err etc still work - if ($h->{err} and my $drh = $h->{Driver}) { - $drh->{$_} = $h->{$_} for ('err','errstr','state'); - } - } if $method_name eq 'DESTROY'; - - push @pre_call_frag, q{ - return $h->{$_[0]} if exists $h->{$_[0]}; - } if $method_name eq 'FETCH' && !exists $ENV{DBI_TRACE}; # XXX ? - - push @pre_call_frag, "return;" - if IMA_STUB & $bitmask; - - push @pre_call_frag, q{ - $method_name = pop @_; - } if IMA_FUNC_REDIRECT & $bitmask; - - push @pre_call_frag, q{ - my $parent_dbh = $h->{Database}; - } if (IMA_COPY_UP_STMT|IMA_EXECUTE) & $bitmask; - - push @pre_call_frag, q{ - warn "No Database set for $h on $method_name!" unless $parent_dbh; # eg proxy problems - $parent_dbh->{Statement} = $h->{Statement} if $parent_dbh; - } if IMA_COPY_UP_STMT & $bitmask; - - push @pre_call_frag, q{ - $h->{Executed} = 1; - $parent_dbh->{Executed} = 1 if $parent_dbh; - } if IMA_EXECUTE & $bitmask; - - push @pre_call_frag, q{ - %{ $h->{CachedKids} } = () if $h->{CachedKids}; - } if IMA_CLEAR_CACHED_KIDS & $bitmask; - - if (IMA_KEEP_ERR & $bitmask) { - push @pre_call_frag, q{ - my $keep_error = DBI::_err_hash($h); - }; - } - else { - my $ke_init = (IMA_KEEP_ERR_SUB & $bitmask) - ? q{= ($h->{dbi_pp_parent}->{dbi_pp_call_depth} && DBI::_err_hash($h)) } - : ""; - push @pre_call_frag, qq{ - my \$keep_error $ke_init; - }; - my $clear_error_code = q{ - #warn "$method_name cleared err"; - $h->{err} = $DBI::err = undef; - $h->{errstr} = $DBI::errstr = undef; - $h->{state} = $DBI::state = ''; - }; - $clear_error_code = q{ - printf $DBI::tfh " !! %s: %s CLEARED by call to }.$method_name.q{ method\n". - $h->{err}, $h->{err} - if defined $h->{err} && $DBI::dbi_debug & 0xF; - }. $clear_error_code - if exists $ENV{DBI_TRACE}; - push @pre_call_frag, ($ke_init) - ? qq{ unless (\$keep_error) { $clear_error_code }} - : $clear_error_code - unless $method_name eq 'set_err'; - } - - push @pre_call_frag, q{ - my $ErrCount = $h->{ErrCount}; - }; - - push @pre_call_frag, q{ - if (($DBI::dbi_debug & 0xF) >= 2) { - local $^W; - my $args = join " ", map { DBI::neat($_) } ($h, @_); - printf $DBI::tfh " > $method_name in $imp ($args) [$@]\n"; - } - } if exists $ENV{DBI_TRACE}; # note use of 'exists' - - push @pre_call_frag, q{ - $h->{'dbi_pp_last_method'} = $method_name; - } unless exists $DBI::last_method_except{$method_name}; - - # --- post method call code fragments --- - my @post_call_frag; - - push @post_call_frag, q{ - if (my $trace_level = ($DBI::dbi_debug & 0xF)) { - if ($h->{err}) { - printf $DBI::tfh " !! ERROR: %s %s\n", $h->{err}, $h->{errstr}; - } - my $ret = join " ", map { DBI::neat($_) } @ret; - my $msg = " < $method_name= $ret"; - $msg = ($trace_level >= 2) ? Carp::shortmess($msg) : "$msg\n"; - print $DBI::tfh $msg; - } - } if exists $ENV{DBI_TRACE}; # note use of exists - - push @post_call_frag, q{ - $h->{Executed} = 0; - if ($h->{BegunWork}) { - $h->{BegunWork} = 0; - $h->{AutoCommit} = 1; - } - } if IMA_END_WORK & $bitmask; - - push @post_call_frag, q{ - if ( ref $ret[0] and - UNIVERSAL::isa($ret[0], 'DBI::_::common') and - defined( (my $h_new = tied(%{$ret[0]})||$ret[0])->{err} ) - ) { - # copy up info/warn to drh so PrintWarn on connect is triggered - $h->set_err($h_new->{err}, $h_new->{errstr}, $h_new->{state}) - } - } if IMA_IS_FACTORY & $bitmask; - - push @post_call_frag, q{ - if ($keep_error) { - $keep_error = 0 - if $h->{ErrCount} > $ErrCount - or DBI::_err_hash($h) ne $keep_error; - } - - $DBI::err = $h->{err}; - $DBI::errstr = $h->{errstr}; - $DBI::state = $h->{state}; - - if ( !$keep_error - && defined(my $err = $h->{err}) - && ($call_depth <= 1 && !$h->{dbi_pp_parent}{dbi_pp_call_depth}) - ) { - - my($pe,$pw,$re,$he) = @{$h}{qw(PrintError PrintWarn RaiseError HandleError)}; - my $msg; - - if ($err && ($pe || $re || $he) # error - or (!$err && length($err) && $pw) # warning - ) { - my $last = ($DBI::last_method_except{$method_name}) - ? ($h->{'dbi_pp_last_method'}||$method_name) : $method_name; - my $errstr = $h->{errstr} || $DBI::errstr || $err || ''; - my $msg = sprintf "%s %s %s: %s", $imp, $last, - ($err eq "0") ? "warning" : "failed", $errstr; - - if ($h->{'ShowErrorStatement'} and my $Statement = $h->{Statement}) { - $msg .= ' [for Statement "' . $Statement; - if (my $ParamValues = $h->FETCH('ParamValues')) { - $msg .= '" with ParamValues: '; - $msg .= DBI::_concat_hash_sorted($ParamValues, "=", ", ", 1, undef); - $msg .= "]"; - } - else { - $msg .= '"]'; - } - } - if ($err eq "0") { # is 'warning' (not info) - carp $msg if $pw; - } - else { - my $do_croak = 1; - if (my $subsub = $h->{'HandleError'}) { - $do_croak = 0 if &$subsub($msg,$h,$ret[0]); - } - if ($do_croak) { - printf $DBI::tfh " $method_name has failed ($h->{PrintError},$h->{RaiseError})\n" - if ($DBI::dbi_debug & 0xF) >= 4; - carp $msg if $pe; - die $msg if $h->{RaiseError}; - } - } - } - } - }; - - - my $method_code = q[ - sub { - my $h = shift; - my $h_inner = tied(%$h); - $h = $h_inner if $h_inner; - - my $imp; - if ($method_name eq 'DESTROY') { - # during global destruction, $h->{...} can trigger "Can't call FETCH on an undef value" - # implying that tied() above lied to us, so we need to use eval - local $@; # protect $@ - $imp = eval { $h->{"ImplementorClass"} } or return; # probably global destruction - } - else { - $imp = $h->{"ImplementorClass"} or do { - warn "Can't call $method_name method on handle $h after take_imp_data()\n" - if not exists $h->{Active}; - return; # or, more likely, global destruction - }; - } - - ] . join("\n", '', @pre_call_frag, '') . q[ - - my $call_depth = $h->{'dbi_pp_call_depth'} + 1; - local ($h->{'dbi_pp_call_depth'}) = $call_depth; - - my @ret; - my $sub = $imp->can($method_name); - if (!$sub and IMA_FUNC_REDIRECT & $bitmask and $sub = $imp->can('func')) { - push @_, $method_name; - } - if ($sub) { - (wantarray) ? (@ret = &$sub($h,@_)) : (@ret = scalar &$sub($h,@_)); - } - else { - # XXX could try explicit fallback to $imp->can('AUTOLOAD') etc - # which would then let Multiplex pass PurePerl tests, but some - # hook into install_method may be better. - croak "Can't locate DBI object method \"$method_name\" via package \"$imp\"" - if ] . ((IMA_NOT_FOUND_OKAY & $bitmask) ? 0 : 1) . q[; - } - - ] . join("\n", '', @post_call_frag, '') . q[ - - return (wantarray) ? @ret : $ret[0]; - } - ]; - no strict qw(refs); - my $code_ref = eval qq{#line 1 "DBI::PurePerl $method"\n$method_code}; - warn "$@\n$method_code\n" if $@; - die "$@\n$method_code\n" if $@; - *$method = $code_ref; - if (0 && $method =~ /\b(connect|FETCH)\b/) { # debuging tool - my $l=0; # show line-numbered code for method - warn "*$method code:\n".join("\n", map { ++$l.": $_" } split/\n/,$method_code); - } -} - - -sub _new_handle { - my ($class, $parent, $attr, $imp_data, $imp_class) = @_; - - DBI->trace_msg(" New $class (for $imp_class, parent=$parent, id=".($imp_data||'').")\n") - if $DBI::dbi_debug >= 3; - - $attr->{ImplementorClass} = $imp_class - or Carp::croak("_new_handle($class): 'ImplementorClass' attribute not given"); - - # This is how we create a DBI style Object: - # %outer gets tied to %$attr (which becomes the 'inner' handle) - my (%outer, $i, $h); - $i = tie %outer, $class, $attr; # ref to inner hash (for driver) - $h = bless \%outer, $class; # ref to outer hash (for application) - # The above tie and bless may migrate down into _setup_handle()... - # Now add magic so DBI method dispatch works - DBI::_setup_handle($h, $imp_class, $parent, $imp_data); - return $h unless wantarray; - return ($h, $i); -} - -sub _setup_handle { - my($h, $imp_class, $parent, $imp_data) = @_; - my $h_inner = tied(%$h) || $h; - if (($DBI::dbi_debug & 0xF) >= 4) { - local $^W; - print $DBI::tfh " _setup_handle(@_)\n"; - } - $h_inner->{"imp_data"} = $imp_data; - $h_inner->{"ImplementorClass"} = $imp_class; - $h_inner->{"Kids"} = $h_inner->{"ActiveKids"} = 0; # XXX not maintained - if ($parent) { - foreach (qw( - RaiseError PrintError PrintWarn HandleError HandleSetErr - Warn LongTruncOk ChopBlanks AutoCommit ReadOnly - ShowErrorStatement FetchHashKeyName LongReadLen CompatMode - )) { - $h_inner->{$_} = $parent->{$_} - if exists $parent->{$_} && !exists $h_inner->{$_}; - } - if (ref($parent) =~ /::db$/) { # is sth - $h_inner->{Database} = $parent; - $parent->{Statement} = $h_inner->{Statement}; - $h_inner->{NUM_OF_PARAMS} = 0; - $h_inner->{Active} = 0; # driver sets true when there's data to fetch - } - elsif (ref($parent) =~ /::dr$/){ # is dbh - $h_inner->{Driver} = $parent; - $h_inner->{Active} = 0; - } - else { - warn "panic: ".ref($parent); # should never happen - } - $h_inner->{dbi_pp_parent} = $parent; - - # add to the parent's ChildHandles - if ($HAS_WEAKEN) { - my $handles = $parent->{ChildHandles} ||= []; - push @$handles, $h; - Scalar::Util::weaken($handles->[-1]); - # purge destroyed handles occasionally - if (@$handles % 120 == 0) { - @$handles = grep { defined } @$handles; - Scalar::Util::weaken($_) for @$handles; # re-weaken after grep - } - } - } - else { # setting up a driver handle - $h_inner->{Warn} = 1; - $h_inner->{PrintWarn} = 1; - $h_inner->{AutoCommit} = 1; - $h_inner->{TraceLevel} = 0; - $h_inner->{CompatMode} = (1==0); - $h_inner->{FetchHashKeyName} ||= 'NAME'; - $h_inner->{LongReadLen} ||= 80; - $h_inner->{ChildHandles} ||= [] if $HAS_WEAKEN; - $h_inner->{Type} ||= 'dr'; - $h_inner->{Active} = 1; - } - $h_inner->{"dbi_pp_call_depth"} = 0; - $h_inner->{"dbi_pp_pid"} = $$; - $h_inner->{ErrCount} = 0; -} - -sub constant { - warn "constant(@_) called unexpectedly"; return undef; -} - -sub trace { - my ($h, $level, $file) = @_; - $level = $h->parse_trace_flags($level) - if defined $level and !DBI::looks_like_number($level); - my $old_level = $DBI::dbi_debug; - _set_trace_file($file) if $level; - if (defined $level) { - $DBI::dbi_debug = $level; - print $DBI::tfh " DBI $DBI::VERSION (PurePerl) " - . "dispatch trace level set to $DBI::dbi_debug\n" - if $DBI::dbi_debug & 0xF; - } - _set_trace_file($file) if !$level; - return $old_level; -} - -sub _set_trace_file { - my ($file) = @_; - # - # DAA add support for filehandle inputs - # - # DAA required to avoid closing a prior fh trace() - $DBI::tfh = undef unless $DBI::tfh_needs_close; - - if (ref $file eq 'GLOB') { - $DBI::tfh = $file; - select((select($DBI::tfh), $| = 1)[0]); - $DBI::tfh_needs_close = 0; - return 1; - } - if ($file && ref \$file eq 'GLOB') { - $DBI::tfh = *{$file}{IO}; - select((select($DBI::tfh), $| = 1)[0]); - $DBI::tfh_needs_close = 0; - return 1; - } - $DBI::tfh_needs_close = 1; - if (!$file || $file eq 'STDERR') { - open $DBI::tfh, ">&STDERR" or carp "Can't dup STDERR: $!"; - } - elsif ($file eq 'STDOUT') { - open $DBI::tfh, ">&STDOUT" or carp "Can't dup STDOUT: $!"; - } - else { - open $DBI::tfh, ">>$file" or carp "Can't open $file: $!"; - } - select((select($DBI::tfh), $| = 1)[0]); - return 1; -} -sub _get_imp_data { shift->{"imp_data"}; } -sub _svdump { } -sub dump_handle { - my ($h,$msg,$level) = @_; - $msg||="dump_handle $h"; - print $DBI::tfh "$msg:\n"; - for my $attrib (sort keys %$h) { - print $DBI::tfh "\t$attrib => ".DBI::neat($h->{$attrib})."\n"; - } -} - -sub _handles { - my $h = shift; - my $h_inner = tied %$h; - if ($h_inner) { # this is okay - return $h unless wantarray; - return ($h, $h_inner); - } - # XXX this isn't okay... we have an inner handle but - # currently have no way to get at its outer handle, - # so we just warn and return the inner one for both... - Carp::carp("Can't return outer handle from inner handle using DBI::PurePerl"); - return $h unless wantarray; - return ($h,$h); -} - -sub hash { - my ($key, $type) = @_; - my ($hash); - if (!$type) { - $hash = 0; - # XXX The C version uses the "char" type, which could be either - # signed or unsigned. I use signed because so do the two - # compilers on my system. - for my $char (unpack ("c*", $key)) { - $hash = $hash * 33 + $char; - } - $hash &= 0x7FFFFFFF; # limit to 31 bits - $hash |= 0x40000000; # set bit 31 - return -$hash; # return negative int - } - elsif ($type == 1) { # Fowler/Noll/Vo hash - # see http://www.isthe.com/chongo/tech/comp/fnv/ - require Math::BigInt; # feel free to reimplement w/o BigInt! - (my $version = $Math::BigInt::VERSION || 0) =~ s/_.*//; # eg "1.70_01" - if ($version >= 1.56) { - $hash = Math::BigInt->new(0x811c9dc5); - for my $uchar (unpack ("C*", $key)) { - # multiply by the 32 bit FNV magic prime mod 2^64 - $hash = ($hash * 0x01000193) & 0xffffffff; - # xor the bottom with the current octet - $hash ^= $uchar; - } - # cast to int - return unpack "i", pack "i", $hash; - } - croak("DBI::PurePerl doesn't support hash type 1 without Math::BigInt >= 1.56 (available on CPAN)"); - } - else { - croak("bad hash type $type"); - } -} - -sub looks_like_number { - my @new = (); - for my $thing(@_) { - if (!defined $thing or $thing eq '') { - push @new, undef; - } - else { - push @new, ($thing =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) ? 1 : 0; - } - } - return (@_ >1) ? @new : $new[0]; -} - -sub neat { - my $v = shift; - return "undef" unless defined $v; - my $quote = q{"}; - if (not utf8::is_utf8($v)) { - return $v if (($v & ~ $v) eq "0"); # is SvNIOK - $quote = q{'}; - } - my $maxlen = shift || $DBI::neat_maxlen; - if ($maxlen && $maxlen < length($v) + 2) { - $v = substr($v,0,$maxlen-5); - $v .= '...'; - } - $v =~ s/[^[:print:]]/./g; - return "$quote$v$quote"; -} - -sub sql_type_cast { - my (undef, $sql_type, $flags) = @_; - - return -1 unless defined $_[0]; - - my $cast_ok = 1; - - my $evalret = eval { - use warnings FATAL => qw(numeric); - if ($sql_type == SQL_INTEGER) { - my $dummy = $_[0] + 0; - return 1; - } - elsif ($sql_type == SQL_DOUBLE) { - my $dummy = $_[0] + 0.0; - return 1; - } - elsif ($sql_type == SQL_NUMERIC) { - my $dummy = $_[0] + 0.0; - return 1; - } - else { - return -2; - } - } or $^W && warn $@; # XXX warnings::warnif("numeric", $@) ? - - return $evalret if defined($evalret) && ($evalret == -2); - $cast_ok = 0 unless $evalret; - - # DBIstcf_DISCARD_STRING not supported for PurePerl currently - - return 2 if $cast_ok; - return 0 if $flags & DBIstcf_STRICT; - return 1; -} - -sub dbi_time { - return time(); -} - -sub DBI::st::TIEHASH { bless $_[1] => $_[0] }; - -sub _concat_hash_sorted { - my ( $hash_ref, $kv_separator, $pair_separator, $use_neat, $num_sort ) = @_; - # $num_sort: 0=lexical, 1=numeric, undef=try to guess - - return undef unless defined $hash_ref; - die "hash is not a hash reference" unless ref $hash_ref eq 'HASH'; - my $keys = _get_sorted_hash_keys($hash_ref, $num_sort); - my $string = ''; - for my $key (@$keys) { - $string .= $pair_separator if length $string > 0; - my $value = $hash_ref->{$key}; - if ($use_neat) { - $value = DBI::neat($value, 0); - } - else { - $value = (defined $value) ? "'$value'" : 'undef'; - } - $string .= $key . $kv_separator . $value; - } - return $string; -} - -sub _get_sorted_hash_keys { - my ($hash_ref, $num_sort) = @_; - if (not defined $num_sort) { - my $sort_guess = 1; - $sort_guess = (not looks_like_number($_)) ? 0 : $sort_guess - for keys %$hash_ref; - $num_sort = $sort_guess; - } - - my @keys = keys %$hash_ref; - no warnings 'numeric'; - my @sorted = ($num_sort) - ? sort { $a <=> $b or $a cmp $b } @keys - : sort @keys; - return \@sorted; -} - -sub _err_hash { - return 1 unless defined $_[0]->{err}; - return "$_[0]->{err} $_[0]->{errstr}" -} - - -package - DBI::var; - -sub FETCH { - my($key)=shift; - return $DBI::err if $$key eq '*err'; - return $DBI::errstr if $$key eq '&errstr'; - Carp::confess("FETCH $key not supported when using DBI::PurePerl"); -} - -package - DBD::_::common; - -sub swap_inner_handle { - my ($h1, $h2) = @_; - # can't make this work till we can get the outer handle from the inner one - # probably via a WeakRef - return $h1->set_err($DBI::stderr, "swap_inner_handle not currently supported by DBI::PurePerl"); -} - -sub trace { # XXX should set per-handle level, not global - my ($h, $level, $file) = @_; - $level = $h->parse_trace_flags($level) - if defined $level and !DBI::looks_like_number($level); - my $old_level = $DBI::dbi_debug; - DBI::_set_trace_file($file) if defined $file; - if (defined $level) { - $DBI::dbi_debug = $level; - if ($DBI::dbi_debug) { - printf $DBI::tfh - " %s trace level set to %d in DBI $DBI::VERSION (PurePerl)\n", - $h, $DBI::dbi_debug; - print $DBI::tfh " Full trace not available because DBI_TRACE is not in environment\n" - unless exists $ENV{DBI_TRACE}; - } - } - return $old_level; -} -*debug = \&trace; *debug = \&trace; # twice to avoid typo warning - -sub FETCH { - my($h,$key)= @_; - my $v = $h->{$key}; - #warn ((exists $h->{$key}) ? "$key=$v\n" : "$key NONEXISTANT\n"); - return $v if defined $v; - if ($key =~ /^NAME_.c$/) { - my $cols = $h->FETCH('NAME'); - return undef unless $cols; - my @lcols = map { lc $_ } @$cols; - $h->{NAME_lc} = \@lcols; - my @ucols = map { uc $_ } @$cols; - $h->{NAME_uc} = \@ucols; - return $h->FETCH($key); - } - if ($key =~ /^NAME.*_hash$/) { - my $i=0; - for my $c(@{$h->FETCH('NAME')||[]}) { - $h->{'NAME_hash'}->{$c} = $i; - $h->{'NAME_lc_hash'}->{"\L$c"} = $i; - $h->{'NAME_uc_hash'}->{"\U$c"} = $i; - $i++; - } - return $h->{$key}; - } - if (!defined $v && !exists $h->{$key}) { - return ($h->FETCH('TaintIn') && $h->FETCH('TaintOut')) if $key eq'Taint'; - return (1==0) if $is_flag_attribute{$key}; # return perl-style sv_no, not undef - return $DBI::dbi_debug if $key eq 'TraceLevel'; - return [] if $key eq 'ChildHandles' && $HAS_WEAKEN; - if ($key eq 'Type') { - return "dr" if $h->isa('DBI::dr'); - return "db" if $h->isa('DBI::db'); - return "st" if $h->isa('DBI::st'); - Carp::carp( sprintf "Can't determine Type for %s",$h ); - } - if (!$is_valid_attribute{$key} and $key =~ m/^[A-Z]/) { - local $^W; # hide undef warnings - Carp::carp( sprintf "Can't get %s->{%s}: unrecognised attribute (@{[ %$h ]})",$h,$key ) - } - } - return $v; -} -sub STORE { - my ($h,$key,$value) = @_; - if ($key eq 'AutoCommit') { - Carp::croak("DBD driver has not implemented the AutoCommit attribute") - unless $value == -900 || $value == -901; - $value = ($value == -901); - } - elsif ($key =~ /^Taint/ ) { - Carp::croak(sprintf "Can't set %s->{%s}: Taint mode not supported by DBI::PurePerl",$h,$key) - if $value; - } - elsif ($key eq 'TraceLevel') { - $h->trace($value); - return 1; - } - elsif ($key eq 'NUM_OF_FIELDS') { - $h->{$key} = $value; - if ($value) { - my $fbav = DBD::_::st::dbih_setup_fbav($h); - @$fbav = (undef) x $value if @$fbav != $value; - } - return 1; - } - elsif (!$is_valid_attribute{$key} && $key =~ /^[A-Z]/ && !exists $h->{$key}) { - Carp::carp(sprintf "Can't set %s->{%s}: unrecognised attribute or invalid value %s", - $h,$key,$value); - } - $h->{$key} = $is_flag_attribute{$key} ? !!$value : $value; - Scalar::Util::weaken($h->{$key}) if $key eq 'CachedKids'; - return 1; -} -sub DELETE { - my ($h, $key) = @_; - return $h->FETCH($key) unless $key =~ /^private_/; - return delete $h->{$key}; -} -sub err { return shift->{err} } -sub errstr { return shift->{errstr} } -sub state { return shift->{state} } -sub set_err { - my ($h, $errnum,$msg,$state, $method, $rv) = @_; - $h = tied(%$h) || $h; - - if (my $hss = $h->{HandleSetErr}) { - return if $hss->($h, $errnum, $msg, $state, $method); - } - - if (!defined $errnum) { - $h->{err} = $DBI::err = undef; - $h->{errstr} = $DBI::errstr = undef; - $h->{state} = $DBI::state = ''; - return; - } - - if ($h->{errstr}) { - $h->{errstr} .= sprintf " [err was %s now %s]", $h->{err}, $errnum - if $h->{err} && $errnum && $h->{err} ne $errnum; - $h->{errstr} .= sprintf " [state was %s now %s]", $h->{state}, $state - if $h->{state} and $h->{state} ne "S1000" && $state && $h->{state} ne $state; - $h->{errstr} .= "\n$msg" if $h->{errstr} ne $msg; - $DBI::errstr = $h->{errstr}; - } - else { - $h->{errstr} = $DBI::errstr = $msg; - } - - # assign if higher priority: err > "0" > "" > undef - my $err_changed; - if ($errnum # new error: so assign - or !defined $h->{err} # no existing warn/info: so assign - # new warn ("0" len 1) > info ("" len 0): so assign - or defined $errnum && length($errnum) > length($h->{err}) - ) { - $h->{err} = $DBI::err = $errnum; - ++$h->{ErrCount} if $errnum; - ++$err_changed; - } - - if ($err_changed) { - $state ||= "S1000" if $DBI::err; - $h->{state} = $DBI::state = ($state eq "00000") ? "" : $state - if $state; - } - - if (my $p = $h->{Database}) { # just sth->dbh, not dbh->drh (see ::db::DESTROY) - $p->{err} = $DBI::err; - $p->{errstr} = $DBI::errstr; - $p->{state} = $DBI::state; - } - - $h->{'dbi_pp_last_method'} = $method; - return $rv; # usually undef -} -sub trace_msg { - my ($h, $msg, $minlevel)=@_; - $minlevel = 1 unless defined $minlevel; - return unless $minlevel <= ($DBI::dbi_debug & 0xF); - print $DBI::tfh $msg; - return 1; -} -sub private_data { - warn "private_data @_"; -} -sub take_imp_data { - my $dbh = shift; - # A reasonable default implementation based on the one in DBI.xs. - # Typically a pure-perl driver would have their own take_imp_data method - # that would delete all but the essential items in the hash before ending with: - # return $dbh->SUPER::take_imp_data(); - # Of course it's useless if the driver doesn't also implement support for - # the dbi_imp_data attribute to the connect() method. - require Storable; - croak("Can't take_imp_data from handle that's not Active") - unless $dbh->{Active}; - for my $sth (@{ $dbh->{ChildHandles} || [] }) { - next unless $sth; - $sth->finish if $sth->{Active}; - bless $sth, 'DBI::zombie'; - } - delete $dbh->{$_} for (keys %is_valid_attribute); - delete $dbh->{$_} for grep { m/^dbi_/ } keys %$dbh; - # warn "@{[ %$dbh ]}"; - local $Storable::forgive_me = 1; # in case there are some CODE refs - my $imp_data = Storable::freeze($dbh); - # XXX um, should probably untie here - need to check dispatch behaviour - return $imp_data; -} -sub rows { - return -1; # always returns -1 here, see DBD::_::st::rows below -} -sub DESTROY { -} - -package - DBD::_::dr; - -sub dbixs_revision { - return 0; -} - -package - DBD::_::db; - -sub connected { -} - - -package - DBD::_::st; - -sub fetchrow_arrayref { - my $h = shift; - # if we're here then driver hasn't implemented fetch/fetchrow_arrayref - # so we assume they've implemented fetchrow_array and call that instead - my @row = $h->fetchrow_array or return; - return $h->_set_fbav(\@row); -} -# twice to avoid typo warning -*fetch = \&fetchrow_arrayref; *fetch = \&fetchrow_arrayref; - -sub fetchrow_array { - my $h = shift; - # if we're here then driver hasn't implemented fetchrow_array - # so we assume they've implemented fetch/fetchrow_arrayref - my $row = $h->fetch or return; - return @$row; -} -*fetchrow = \&fetchrow_array; *fetchrow = \&fetchrow_array; - -sub fetchrow_hashref { - my $h = shift; - my $row = $h->fetch or return; - my $FetchCase = shift; - my $FetchHashKeyName = $FetchCase || $h->{'FetchHashKeyName'} || 'NAME'; - my $FetchHashKeys = $h->FETCH($FetchHashKeyName); - my %rowhash; - @rowhash{ @$FetchHashKeys } = @$row; - return \%rowhash; -} -sub dbih_setup_fbav { - my $h = shift; - return $h->{'_fbav'} || do { - $DBI::rows = $h->{'_rows'} = 0; - my $fields = $h->{'NUM_OF_FIELDS'} - or DBI::croak("NUM_OF_FIELDS not set"); - my @row = (undef) x $fields; - \@row; - }; -} -sub _get_fbav { - my $h = shift; - my $av = $h->{'_fbav'} ||= dbih_setup_fbav($h); - $DBI::rows = ++$h->{'_rows'}; - return $av; -} -sub _set_fbav { - my $h = shift; - my $fbav = $h->{'_fbav'}; - if ($fbav) { - $DBI::rows = ++$h->{'_rows'}; - } - else { - $fbav = $h->_get_fbav; - } - my $row = shift; - if (my $bc = $h->{'_bound_cols'}) { - for my $i (0..@$row-1) { - my $bound = $bc->[$i]; - $fbav->[$i] = ($bound) ? ($$bound = $row->[$i]) : $row->[$i]; - } - } - else { - @$fbav = @$row; - } - return $fbav; -} -sub bind_col { - my ($h, $col, $value_ref,$from_bind_columns) = @_; - my $fbav = $h->{'_fbav'} ||= dbih_setup_fbav($h); # from _get_fbav() - my $num_of_fields = @$fbav; - DBI::croak("bind_col: column $col is not a valid column (1..$num_of_fields)") - if $col < 1 or $col > $num_of_fields; - return 1 if not defined $value_ref; # ie caller is just trying to set TYPE - DBI::croak("bind_col($col,$value_ref) needs a reference to a scalar") - unless ref $value_ref eq 'SCALAR'; - $h->{'_bound_cols'}->[$col-1] = $value_ref; - return 1; -} -sub finish { - my $h = shift; - $h->{'_fbav'} = undef; - $h->{'Active'} = 0; - return 1; -} -sub rows { - my $h = shift; - my $rows = $h->{'_rows'}; - return -1 unless defined $rows; - return $rows; -} - -1; -__END__ - -=pod - -=head1 NAME - -DBI::PurePerl -- a DBI emulation using pure perl (no C/XS compilation required) - -=head1 SYNOPSIS - - BEGIN { $ENV{DBI_PUREPERL} = 2 } - use DBI; - -=head1 DESCRIPTION - -This is a pure perl emulation of the DBI internals. In almost all -cases you will be better off using standard DBI since the portions -of the standard version written in C make it *much* faster. - -However, if you are in a situation where it isn't possible to install -a compiled version of standard DBI, and you're using pure-perl DBD -drivers, then this module allows you to use most common features -of DBI without needing any changes in your scripts. - -=head1 EXPERIMENTAL STATUS - -DBI::PurePerl is new so please treat it as experimental pending -more extensive testing. So far it has passed all tests with DBD::CSV, -DBD::AnyData, DBD::XBase, DBD::Sprite, DBD::mysqlPP. Please send -bug reports to Jeff Zucker at with a cc to -. - -=head1 USAGE - -The usage is the same as for standard DBI with the exception -that you need to set the environment variable DBI_PUREPERL if -you want to use the PurePerl version. - - DBI_PUREPERL == 0 (the default) Always use compiled DBI, die - if it isn't properly compiled & installed - - DBI_PUREPERL == 1 Use compiled DBI if it is properly compiled - & installed, otherwise use PurePerl - - DBI_PUREPERL == 2 Always use PurePerl - -You may set the environment variable in your shell (e.g. with -set or setenv or export, etc) or else set it in your script like -this: - - BEGIN { $ENV{DBI_PUREPERL}=2 } - -before you C. - -=head1 INSTALLATION - -In most situations simply install DBI (see the DBI pod for details). - -In the situation in which you can not install DBI itself, you -may manually copy DBI.pm and PurePerl.pm into the appropriate -directories. - -For example: - - cp DBI.pm /usr/jdoe/mylibs/. - cp PurePerl.pm /usr/jdoe/mylibs/DBI/. - -Then add this to the top of scripts: - - BEGIN { - $ENV{DBI_PUREPERL} = 1; # or =2 - unshift @INC, '/usr/jdoe/mylibs'; - } - -(Or should we perhaps patch Makefile.PL so that if DBI_PUREPERL -is set to 2 prior to make, the normal compile process is skipped -and the files are installed automatically?) - -=head1 DIFFERENCES BETWEEN DBI AND DBI::PurePerl - -=head2 Attributes - -Boolean attributes still return boolean values but the actual values -used may be different, i.e., 0 or undef instead of an empty string. - -Some handle attributes are either not supported or have very limited -functionality: - - ActiveKids - InactiveDestroy - AutoInactiveDestroy - Kids - Taint - TaintIn - TaintOut - -(and probably others) - -=head2 Tracing - -Trace functionality is more limited and the code to handle tracing is -only embedded into DBI:PurePerl if the DBI_TRACE environment variable -is defined. To enable total tracing you can set the DBI_TRACE -environment variable as usual. But to enable individual handle -tracing using the trace() method you also need to set the DBI_TRACE -environment variable, but set it to 0. - -=head2 Parameter Usage Checking - -The DBI does some basic parameter count checking on method calls. -DBI::PurePerl doesn't. - -=head2 Speed - -DBI::PurePerl is slower. Although, with some drivers in some -contexts this may not be very significant for you. - -By way of example... the test.pl script in the DBI source -distribution has a simple benchmark that just does: - - my $null_dbh = DBI->connect('dbi:NullP:','',''); - my $i = 10_000; - $null_dbh->prepare('') while $i--; - -In other words just prepares a statement, creating and destroying -a statement handle, over and over again. Using the real DBI this -runs at ~4550 handles per second whereas DBI::PurePerl manages -~2800 per second on the same machine (not too bad really). - -=head2 May not fully support hash() - -If you want to use type 1 hash, i.e., C with -DBI::PurePerl, you'll need version 1.56 or higher of Math::BigInt -(available on CPAN). - -=head2 Doesn't support preparse() - -The DBI->preparse() method isn't supported in DBI::PurePerl. - -=head2 Doesn't support DBD::Proxy - -There's a subtle problem somewhere I've not been able to identify. -DBI::ProxyServer seem to work fine with DBI::PurePerl but DBD::Proxy -does not work 100% (which is sad because that would be far more useful :) -Try re-enabling t/80proxy.t for DBI::PurePerl to see if the problem -that remains will affect you're usage. - -=head2 Others - - can() - doesn't have any special behaviour - -Please let us know if you find any other differences between DBI -and DBI::PurePerl. - -=head1 AUTHORS - -Tim Bunce and Jeff Zucker. - -Tim provided the direction and basis for the code. The original -idea for the module and most of the brute force porting from C to -Perl was by Jeff. Tim then reworked some core parts to boost the -performance and accuracy of the emulation. Thanks also to Randal -Schwartz and John Tobey for patches. - -=head1 COPYRIGHT - -Copyright (c) 2002 Tim Bunce Ireland. - -See COPYRIGHT section in DBI.pm for usage and distribution rights. - -=cut diff --git a/dbLifeLog/DBI-1.641/lib/DBI/SQL/Nano.pm b/dbLifeLog/DBI-1.641/lib/DBI/SQL/Nano.pm deleted file mode 100644 index 2988c10..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/SQL/Nano.pm +++ /dev/null @@ -1,1014 +0,0 @@ -####################################################################### -# -# DBI::SQL::Nano - a very tiny SQL engine -# -# Copyright (c) 2010 by Jens Rehsack < rehsack AT cpan.org > -# Copyright (c) 2004 by Jeff Zucker < jzucker AT cpan.org > -# -# All rights reserved. -# -# You may freely distribute and/or modify this module under the terms -# of either the GNU General Public License (GPL) or the Artistic License, -# as specified in the Perl README file. -# -# See the pod at the bottom of this file for help information -# -####################################################################### - -####################### -package DBI::SQL::Nano; -####################### -use strict; -use warnings; -use vars qw( $VERSION $versions ); - -use Carp qw(croak); - -require DBI; # for looks_like_number() - -BEGIN -{ - $VERSION = "1.015544"; - - $versions->{nano_version} = $VERSION; - if ( $ENV{DBI_SQL_NANO} || !eval { require SQL::Statement; $SQL::Statement::VERSION ge '1.400' } ) - { - @DBI::SQL::Nano::Statement::ISA = qw(DBI::SQL::Nano::Statement_); - @DBI::SQL::Nano::Table::ISA = qw(DBI::SQL::Nano::Table_); - } - else - { - @DBI::SQL::Nano::Statement::ISA = qw( SQL::Statement ); - @DBI::SQL::Nano::Table::ISA = qw( SQL::Eval::Table); - $versions->{statement_version} = $SQL::Statement::VERSION; - } -} - -################################### -package DBI::SQL::Nano::Statement_; -################################### - -use Carp qw(croak); -use Errno; - -if ( eval { require Clone; } ) -{ - Clone->import("clone"); -} -else -{ - require Storable; # in CORE since 5.7.3 - *clone = \&Storable::dclone; -} - -sub new -{ - my ( $class, $sql ) = @_; - my $self = {}; - bless $self, $class; - return $self->prepare($sql); -} - -##################################################################### -# PREPARE -##################################################################### -sub prepare -{ - my ( $self, $sql ) = @_; - $sql =~ s/\s+$//; - $sql =~ s/\s*;$//; - for ($sql) - { - /^\s*CREATE\s+TABLE\s+(.*?)\s*\((.+)\)\s*$/is - && do - { - $self->{command} = 'CREATE'; - $self->{table_name} = $1; - defined $2 and $2 ne "" and - $self->{column_names} = parse_coldef_list($2); - $self->{column_names} or croak "Can't find columns"; - }; - /^\s*DROP\s+TABLE\s+(IF\s+EXISTS\s+)?(.*?)\s*$/is - && do - { - $self->{command} = 'DROP'; - $self->{table_name} = $2; - defined $1 and $1 ne "" and - $self->{ignore_missing_table} = 1; - }; - /^\s*SELECT\s+(.*?)\s+FROM\s+(\S+)((.*))?/is - && do - { - $self->{command} = 'SELECT'; - defined $1 and $1 ne "" and - $self->{column_names} = parse_comma_list($1); - $self->{column_names} or croak "Can't find columns"; - $self->{table_name} = $2; - if ( my $clauses = $4 ) - { - if ( $clauses =~ /^(.*)\s+ORDER\s+BY\s+(.*)$/is ) - { - $clauses = $1; - $self->{order_clause} = $self->parse_order_clause($2); - } - $self->{where_clause} = $self->parse_where_clause($clauses) if ($clauses); - } - }; - /^\s*INSERT\s+(?:INTO\s+)?(\S+)\s*(\((.*?)\))?\s*VALUES\s*\((.+)\)/is - && do - { - $self->{command} = 'INSERT'; - $self->{table_name} = $1; - defined $2 and $2 ne "" and - $self->{column_names} = parse_comma_list($2); - defined $4 and $4 ne "" and - $self->{values} = $self->parse_values_list($4); - $self->{values} or croak "Can't parse values"; - }; - /^\s*DELETE\s+FROM\s+(\S+)((.*))?/is - && do - { - $self->{command} = 'DELETE'; - $self->{table_name} = $1; - defined $3 and $3 ne "" and - $self->{where_clause} = $self->parse_where_clause($3); - }; - /^\s*UPDATE\s+(\S+)\s+SET\s+(.+)(\s+WHERE\s+.+)/is - && do - { - $self->{command} = 'UPDATE'; - $self->{table_name} = $1; - defined $2 and $2 ne "" and - $self->parse_set_clause($2); - defined $3 and $3 ne "" and - $self->{where_clause} = $self->parse_where_clause($3); - }; - } - croak "Couldn't parse" unless ( $self->{command} and $self->{table_name} ); - return $self; -} - -sub parse_order_clause -{ - my ( $self, $str ) = @_; - my @clause = split /\s+/, $str; - return { $clause[0] => 'ASC' } if ( @clause == 1 ); - croak "Bad ORDER BY clause '$str'" if ( @clause > 2 ); - $clause[1] ||= ''; - return { $clause[0] => uc $clause[1] } - if $clause[1] =~ /^ASC$/i - or $clause[1] =~ /^DESC$/i; - croak "Bad ORDER BY clause '$clause[1]'"; -} - -sub parse_coldef_list -{ # check column definitions - my @col_defs; - for ( split ',', shift ) - { - my $col = clean_parse_str($_); - if ( $col =~ /^(\S+?)\s+.+/ ) - { # doesn't check what it is - $col = $1; # just checks if it exists - } - else - { - croak "No column definition for '$_'"; - } - push @col_defs, $col; - } - return \@col_defs; -} - -sub parse_comma_list -{ - [ map { clean_parse_str($_) } split( ',', shift ) ]; -} -sub clean_parse_str { local $_ = shift; s/\(//; s/\)//; s/^\s+//; s/\s+$//; $_; } - -sub parse_values_list -{ - my ( $self, $str ) = @_; - [ map { $self->parse_value( clean_parse_str($_) ) } split( ',', $str ) ]; -} - -sub parse_set_clause -{ - my $self = shift; - my @cols = split /,/, shift; - my $set_clause; - for my $col (@cols) - { - my ( $col_name, $value ) = $col =~ /^\s*(.+?)\s*=\s*(.+?)\s*$/s; - push @{ $self->{column_names} }, $col_name; - push @{ $self->{values} }, $self->parse_value($value); - } - croak "Can't parse set clause" unless ( $self->{column_names} and $self->{values} ); -} - -sub parse_value -{ - my ( $self, $str ) = @_; - return unless ( defined $str ); - $str =~ s/\s+$//; - $str =~ s/^\s+//; - if ( $str =~ /^\?$/ ) - { - push @{ $self->{params} }, '?'; - return { - value => '?', - type => 'placeholder' - }; - } - return { - value => undef, - type => 'NULL' - } if ( $str =~ /^NULL$/i ); - return { - value => $1, - type => 'string' - } if ( $str =~ /^'(.+)'$/s ); - return { - value => $str, - type => 'number' - } if ( DBI::looks_like_number($str) ); - return { - value => $str, - type => 'column' - }; -} - -sub parse_where_clause -{ - my ( $self, $str ) = @_; - $str =~ s/\s+$//; - if ( $str =~ /^\s*WHERE\s+(.*)/i ) - { - $str = $1; - } - else - { - croak "Couldn't find WHERE clause in '$str'"; - } - my ($neg) = $str =~ s/^\s*(NOT)\s+//is; - my $opexp = '=|<>|<=|>=|<|>|LIKE|CLIKE|IS'; - my ( $val1, $op, $val2 ) = $str =~ /^(.+?)\s*($opexp)\s*(.+)\s*$/iso; - croak "Couldn't parse WHERE expression '$str'" unless ( defined $val1 and defined $op and defined $val2 ); - return { - arg1 => $self->parse_value($val1), - arg2 => $self->parse_value($val2), - op => $op, - neg => $neg, - }; -} - -##################################################################### -# EXECUTE -##################################################################### -sub execute -{ - my ( $self, $data, $params ) = @_; - my $num_placeholders = $self->params; - my $num_params = scalar @$params || 0; - croak "Number of params '$num_params' does not match number of placeholders '$num_placeholders'" - unless ( $num_placeholders == $num_params ); - if ( scalar @$params ) - { - for my $i ( 0 .. $#{ $self->{values} } ) - { - if ( $self->{values}->[$i]->{type} eq 'placeholder' ) - { - $self->{values}->[$i]->{value} = shift @$params; - } - } - if ( $self->{where_clause} ) - { - if ( $self->{where_clause}->{arg1}->{type} eq 'placeholder' ) - { - $self->{where_clause}->{arg1}->{value} = shift @$params; - } - if ( $self->{where_clause}->{arg2}->{type} eq 'placeholder' ) - { - $self->{where_clause}->{arg2}->{value} = shift @$params; - } - } - } - my $command = $self->{command}; - ( $self->{'NUM_OF_ROWS'}, $self->{'NUM_OF_FIELDS'}, $self->{'data'}, ) = $self->$command( $data, $params ); - $self->{NAME} ||= $self->{column_names}; - return $self->{'NUM_OF_ROWS'} || '0E0'; -} - -my $enoentstr = "Cannot open .*\(" . Errno::ENOENT . "\)"; -my $enoentrx = qr/$enoentstr/; - -sub DROP ($$$) -{ - my ( $self, $data, $params ) = @_; - - my $table; - my @err; - eval { - local $SIG{__WARN__} = sub { push @err, @_ }; - ($table) = $self->open_tables( $data, 0, 1 ); - }; - if ( $self->{ignore_missing_table} and ( $@ or @err ) and grep { $_ =~ $enoentrx } ( @err, $@ ) ) - { - $@ = ''; - return ( -1, 0 ); - } - - croak( $@ || $err[0] ) if ( $@ || @err ); - return ( -1, 0 ) unless $table; - - $table->drop($data); - ( -1, 0 ); -} - -sub CREATE ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 1, 1 ); - $table->push_names( $data, $self->{column_names} ); - ( 0, 0 ); -} - -sub INSERT ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 0, 1 ); - $self->verify_columns($table); - my $all_columns = $table->{col_names}; - $table->seek( $data, 0, 2 ) unless ( $table->can('insert_one_row') ); - my ($array) = []; - my ( $val, $col, $i ); - $self->{column_names} = $table->col_names() unless ( $self->{column_names} ); - my $cNum = scalar( @{ $self->{column_names} } ) if ( $self->{column_names} ); - my $param_num = 0; - - $cNum or - croak "Bad col names in INSERT"; - - my $maxCol = $#$all_columns; - - for ( $i = 0; $i < $cNum; $i++ ) - { - $col = $self->{column_names}->[$i]; - $array->[ $self->column_nums( $table, $col ) ] = $self->row_values($i); - } - - # Extend row to put values in ALL fields - $#$array < $maxCol and $array->[$maxCol] = undef; - - $table->can('insert_new_row') ? $table->insert_new_row( $data, $array ) : $table->push_row( $data, $array ); - - return ( 1, 0 ); -} - -sub DELETE ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 0, 1 ); - $self->verify_columns($table); - my ($affected) = 0; - my ( @rows, $array ); - my $can_dor = $table->can('delete_one_row'); - while ( $array = $table->fetch_row($data) ) - { - if ( $self->eval_where( $table, $array ) ) - { - ++$affected; - if ( $self->{fetched_from_key} ) - { - $array = $self->{fetched_value}; - $table->delete_one_row( $data, $array ); - return ( $affected, 0 ); - } - push( @rows, $array ) if ($can_dor); - } - else - { - push( @rows, $array ) unless ($can_dor); - } - } - if ($can_dor) - { - foreach $array (@rows) - { - $table->delete_one_row( $data, $array ); - } - } - else - { - $table->seek( $data, 0, 0 ); - foreach $array (@rows) - { - $table->push_row( $data, $array ); - } - $table->truncate($data); - } - return ( $affected, 0 ); -} - -sub _anycmp($$;$) -{ - my ( $a, $b, $case_fold ) = @_; - - if ( !defined($a) || !defined($b) ) - { - return defined($a) - defined($b); - } - elsif ( DBI::looks_like_number($a) && DBI::looks_like_number($b) ) - { - return $a <=> $b; - } - else - { - return $case_fold ? lc($a) cmp lc($b) || $a cmp $b : $a cmp $b; - } -} - -sub SELECT ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 0, 0 ); - $self->verify_columns($table); - my $tname = $self->{table_name}; - my ($affected) = 0; - my ( @rows, %cols, $array, $val, $col, $i ); - while ( $array = $table->fetch_row($data) ) - { - if ( $self->eval_where( $table, $array ) ) - { - $array = $self->{fetched_value} if ( $self->{fetched_from_key} ); - unless ( keys %cols ) - { - my $col_nums = $self->column_nums($table); - %cols = reverse %{$col_nums}; - } - - my $rowhash; - for ( sort keys %cols ) - { - $rowhash->{ $cols{$_} } = $array->[$_]; - } - my @newarray; - for ( $i = 0; $i < @{ $self->{column_names} }; $i++ ) - { - $col = $self->{column_names}->[$i]; - push @newarray, $rowhash->{$col}; - } - push( @rows, \@newarray ); - return ( scalar(@rows), scalar @{ $self->{column_names} }, \@rows ) - if ( $self->{fetched_from_key} ); - } - } - if ( $self->{order_clause} ) - { - my ( $sort_col, $desc ) = each %{ $self->{order_clause} }; - my @sortCols = ( $self->column_nums( $table, $sort_col, 1 ) ); - $sortCols[1] = uc $desc eq 'DESC' ? 1 : 0; - - @rows = sort { - my ( $result, $colNum, $desc ); - my $i = 0; - do - { - $colNum = $sortCols[ $i++ ]; - $desc = $sortCols[ $i++ ]; - $result = _anycmp( $a->[$colNum], $b->[$colNum] ); - $result = -$result if ($desc); - } while ( !$result && $i < @sortCols ); - $result; - } @rows; - } - ( scalar(@rows), scalar @{ $self->{column_names} }, \@rows ); -} - -sub UPDATE ($$$) -{ - my ( $self, $data, $params ) = @_; - my $table = $self->open_tables( $data, 0, 1 ); - $self->verify_columns($table); - return undef unless $table; - my $affected = 0; - my $can_usr = $table->can('update_specific_row'); - my $can_uor = $table->can('update_one_row'); - my $can_rwu = $can_usr || $can_uor; - my ( @rows, $array, $f_array, $val, $col, $i ); - - while ( $array = $table->fetch_row($data) ) - { - if ( $self->eval_where( $table, $array ) ) - { - $array = $self->{fetched_value} if ( $self->{fetched_from_key} and $can_rwu ); - my $orig_ary = clone($array) if ($can_usr); - for ( $i = 0; $i < @{ $self->{column_names} }; $i++ ) - { - $col = $self->{column_names}->[$i]; - $array->[ $self->column_nums( $table, $col ) ] = $self->row_values($i); - } - $affected++; - if ( $self->{fetched_value} ) - { - if ($can_usr) - { - $table->update_specific_row( $data, $array, $orig_ary ); - } - elsif ($can_uor) - { - $table->update_one_row( $data, $array ); - } - return ( $affected, 0 ); - } - push( @rows, $can_usr ? [ $array, $orig_ary ] : $array ); - } - else - { - push( @rows, $array ) unless ($can_rwu); - } - } - if ($can_rwu) - { - foreach my $array (@rows) - { - if ($can_usr) - { - $table->update_specific_row( $data, @$array ); - } - elsif ($can_uor) - { - $table->update_one_row( $data, $array ); - } - } - } - else - { - $table->seek( $data, 0, 0 ); - foreach my $array (@rows) - { - $table->push_row( $data, $array ); - } - $table->truncate($data); - } - - return ( $affected, 0 ); -} - -sub verify_columns -{ - my ( $self, $table ) = @_; - my @cols = @{ $self->{column_names} }; - if ( $self->{where_clause} ) - { - if ( my $col = $self->{where_clause}->{arg1} ) - { - push @cols, $col->{value} if $col->{type} eq 'column'; - } - if ( my $col = $self->{where_clause}->{arg2} ) - { - push @cols, $col->{value} if $col->{type} eq 'column'; - } - } - for (@cols) - { - $self->column_nums( $table, $_ ); - } -} - -sub column_nums -{ - my ( $self, $table, $stmt_col_name, $find_in_stmt ) = @_; - my %dbd_nums = %{ $table->col_nums() }; - my @dbd_cols = @{ $table->col_names() }; - my %stmt_nums; - if ( $stmt_col_name and !$find_in_stmt ) - { - while ( my ( $k, $v ) = each %dbd_nums ) - { - return $v if uc $k eq uc $stmt_col_name; - } - croak "No such column '$stmt_col_name'"; - } - if ( $stmt_col_name and $find_in_stmt ) - { - for my $i ( 0 .. @{ $self->{column_names} } ) - { - return $i if uc $stmt_col_name eq uc $self->{column_names}->[$i]; - } - croak "No such column '$stmt_col_name'"; - } - for my $i ( 0 .. $#dbd_cols ) - { - for my $stmt_col ( @{ $self->{column_names} } ) - { - $stmt_nums{$stmt_col} = $i if uc $dbd_cols[$i] eq uc $stmt_col; - } - } - return \%stmt_nums; -} - -sub eval_where -{ - my ( $self, $table, $rowary ) = @_; - my $where = $self->{"where_clause"} || return 1; - my $col_nums = $table->col_nums(); - my %cols = reverse %{$col_nums}; - my $rowhash; - for ( sort keys %cols ) - { - $rowhash->{ uc $cols{$_} } = $rowary->[$_]; - } - return $self->process_predicate( $where, $table, $rowhash ); -} - -sub process_predicate -{ - my ( $self, $pred, $table, $rowhash ) = @_; - my $val1 = $pred->{arg1}; - if ( $val1->{type} eq 'column' ) - { - $val1 = $rowhash->{ uc $val1->{value} }; - } - else - { - $val1 = $val1->{value}; - } - my $val2 = $pred->{arg2}; - if ( $val2->{type} eq 'column' ) - { - $val2 = $rowhash->{ uc $val2->{value} }; - } - else - { - $val2 = $val2->{value}; - } - my $op = $pred->{op}; - my $neg = $pred->{neg}; - if ( $op eq '=' and !$neg and $table->can('fetch_one_row') ) - { - my $key_col = $table->fetch_one_row( 1, 1 ); - if ( $pred->{arg1}->{value} =~ /^$key_col$/i ) - { - $self->{fetched_from_key} = 1; - $self->{fetched_value} = $table->fetch_one_row( 0, $pred->{arg2}->{value} ); - return 1; - } - } - my $match = $self->is_matched( $val1, $op, $val2 ) || 0; - if ($neg) { $match = $match ? 0 : 1; } - return $match; -} - -sub is_matched -{ - my ( $self, $val1, $op, $val2 ) = @_; - if ( $op eq 'IS' ) - { - return 1 if ( !defined $val1 or $val1 eq '' ); - return 0; - } - $val1 = '' unless ( defined $val1 ); - $val2 = '' unless ( defined $val2 ); - if ( $op =~ /LIKE|CLIKE/i ) - { - $val2 = quotemeta($val2); - $val2 =~ s/\\%/.*/g; - $val2 =~ s/_/./g; - } - if ( $op eq 'LIKE' ) { return $val1 =~ /^$val2$/s; } - if ( $op eq 'CLIKE' ) { return $val1 =~ /^$val2$/si; } - if ( DBI::looks_like_number($val1) && DBI::looks_like_number($val2) ) - { - if ( $op eq '<' ) { return $val1 < $val2; } - if ( $op eq '>' ) { return $val1 > $val2; } - if ( $op eq '=' ) { return $val1 == $val2; } - if ( $op eq '<>' ) { return $val1 != $val2; } - if ( $op eq '<=' ) { return $val1 <= $val2; } - if ( $op eq '>=' ) { return $val1 >= $val2; } - } - else - { - if ( $op eq '<' ) { return $val1 lt $val2; } - if ( $op eq '>' ) { return $val1 gt $val2; } - if ( $op eq '=' ) { return $val1 eq $val2; } - if ( $op eq '<>' ) { return $val1 ne $val2; } - if ( $op eq '<=' ) { return $val1 ge $val2; } - if ( $op eq '>=' ) { return $val1 le $val2; } - } -} - -sub params -{ - my ( $self, $val_num ) = @_; - if ( !$self->{"params"} ) { return 0; } - if ( defined $val_num ) - { - return $self->{"params"}->[$val_num]; - } - - return wantarray ? @{ $self->{"params"} } : scalar @{ $self->{"params"} }; -} - -sub open_tables -{ - my ( $self, $data, $createMode, $lockMode ) = @_; - my $table_name = $self->{table_name}; - my $table; - eval { $table = $self->open_table( $data, $table_name, $createMode, $lockMode ) }; - if ($@) - { - chomp $@; - croak $@; - } - croak "Couldn't open table '$table_name'" unless $table; - if ( !$self->{column_names} or $self->{column_names}->[0] eq '*' ) - { - $self->{column_names} = $table->col_names(); - } - return $table; -} - -sub row_values -{ - my ( $self, $val_num ) = @_; - if ( !$self->{"values"} ) { return 0; } - if ( defined $val_num ) - { - return $self->{"values"}->[$val_num]->{value}; - } - if (wantarray) - { - return map { $_->{"value"} } @{ $self->{"values"} }; - } - else - { - return scalar @{ $self->{"values"} }; - } -} - -sub column_names -{ - my ($self) = @_; - my @col_names; - if ( $self->{column_names} and $self->{column_names}->[0] ne '*' ) - { - @col_names = @{ $self->{column_names} }; - } - return @col_names; -} - -############################### -package DBI::SQL::Nano::Table_; -############################### - -use Carp qw(croak); - -sub new ($$) -{ - my ( $proto, $attr ) = @_; - my ($self) = {%$attr}; - - defined( $self->{col_names} ) and "ARRAY" eq ref( $self->{col_names} ) - or croak("attribute 'col_names' must be defined as an array"); - exists( $self->{col_nums} ) or $self->{col_nums} = _map_colnums( $self->{col_names} ); - defined( $self->{col_nums} ) and "HASH" eq ref( $self->{col_nums} ) - or croak("attribute 'col_nums' must be defined as a hash"); - - bless( $self, ( ref($proto) || $proto ) ); - return $self; -} - -sub _map_colnums -{ - my $col_names = $_[0]; - my %col_nums; - for my $i ( 0 .. $#$col_names ) - { - next unless $col_names->[$i]; - $col_nums{ $col_names->[$i] } = $i; - } - return \%col_nums; -} - -sub row() { return $_[0]->{row}; } -sub column($) { return $_[0]->{row}->[ $_[0]->column_num( $_[1] ) ]; } -sub column_num($) { $_[0]->{col_nums}->{ $_[1] }; } -sub col_nums() { $_[0]->{col_nums} } -sub col_names() { $_[0]->{col_names}; } - -sub drop ($$) { croak "Abstract method " . ref( $_[0] ) . "::drop called" } -sub fetch_row ($$$) { croak "Abstract method " . ref( $_[0] ) . "::fetch_row called" } -sub push_row ($$$) { croak "Abstract method " . ref( $_[0] ) . "::push_row called" } -sub push_names ($$$) { croak "Abstract method " . ref( $_[0] ) . "::push_names called" } -sub truncate ($$) { croak "Abstract method " . ref( $_[0] ) . "::truncate called" } -sub seek ($$$$) { croak "Abstract method " . ref( $_[0] ) . "::seek called" } - -1; -__END__ - -=pod - -=head1 NAME - -DBI::SQL::Nano - a very tiny SQL engine - -=head1 SYNOPSIS - - BEGIN { $ENV{DBI_SQL_NANO}=1 } # forces use of Nano rather than SQL::Statement - use DBI::SQL::Nano; - use Data::Dumper; - my $stmt = DBI::SQL::Nano::Statement->new( - "SELECT bar,baz FROM foo WHERE qux = 1" - ) or die "Couldn't parse"; - print Dumper $stmt; - -=head1 DESCRIPTION - -C<< DBI::SQL::Nano >> is meant as a I minimal SQL engine for use in -situations where SQL::Statement is not available. In most situations you are -better off installing L although DBI::SQL::Nano may be faster -for some B simple tasks. - -DBI::SQL::Nano, like SQL::Statement is primarily intended to provide a SQL -engine for use with some pure perl DBDs including L, L, -L, and L. It is not of much use in and of itself. -You can dump out the structure of a parsed SQL statement, but that is about -it. - -=head1 USAGE - -=head2 Setting the DBI_SQL_NANO flag - -By default, when a C<< DBD >> uses C<< DBI::SQL::Nano >>, the module will -look to see if C<< SQL::Statement >> is installed. If it is, SQL::Statement -objects are used. If SQL::Statement is not available, DBI::SQL::Nano -objects are used. - -In some cases, you may wish to use DBI::SQL::Nano objects even if -SQL::Statement is available. To force usage of DBI::SQL::Nano objects -regardless of the availability of SQL::Statement, set the environment -variable DBI_SQL_NANO to 1. - -You can set the environment variable in your shell prior to running your -script (with SET or EXPORT or whatever), or else you can set it in your -script by putting this at the top of the script: - - BEGIN { $ENV{DBI_SQL_NANO} = 1 } - -=head2 Supported SQL syntax - - Here's a pseudo-BNF. Square brackets [] indicate optional items; - Angle brackets <> indicate items defined elsewhere in the BNF. - - statement ::= - DROP TABLE [IF EXISTS] - | CREATE TABLE - | INSERT INTO [] VALUES - | DELETE FROM [] - | UPDATE SET - | SELECT FROM [] - [] - - the optional IF EXISTS clause ::= - * similar to MySQL - prevents errors when trying to drop - a table that doesn't exist - - identifiers ::= - * table and column names should be valid SQL identifiers - * especially avoid using spaces and commas in identifiers - * note: there is no error checking for invalid names, some - will be accepted, others will cause parse failures - - table_name ::= - * only one table (no multiple table operations) - * see identifier for valid table names - - col_def_list ::= - * a parens delimited, comma-separated list of column names - * see identifier for valid column names - * column types and column constraints may be included but are ignored - e.g. these are all the same: - (id,phrase) - (id INT, phrase VARCHAR(40)) - (id INT PRIMARY KEY, phrase VARCHAR(40) NOT NULL) - * you are *strongly* advised to put in column types even though - they are ignored ... it increases portability - - insert_col_list ::= - * a parens delimited, comma-separated list of column names - * as in standard SQL, this is optional - - select_col_list ::= - * a comma-separated list of column names - * or an asterisk denoting all columns - - val_list ::= - * a parens delimited, comma-separated list of values which can be: - * placeholders (an unquoted question mark) - * numbers (unquoted numbers) - * column names (unquoted strings) - * nulls (unquoted word NULL) - * strings (delimited with single quote marks); - * note: leading and trailing percent mark (%) and underscore (_) - can be used as wildcards in quoted strings for use with - the LIKE and CLIKE operators - * note: escaped single quotation marks within strings are not - supported, neither are embedded commas, use placeholders instead - - set_clause ::= - * a comma-separated list of column = value pairs - * see val_list for acceptable value formats - - where_clause ::= - * a single "column/value column/value" predicate, optionally - preceded by "NOT" - * note: multiple predicates combined with ORs or ANDs are not supported - * see val_list for acceptable value formats - * op may be one of: - < > >= <= = <> LIKE CLIKE IS - * CLIKE is a case insensitive LIKE - - order_clause ::= column_name [ASC|DESC] - * a single column optional ORDER BY clause is supported - * as in standard SQL, if neither ASC (ascending) nor - DESC (descending) is specified, ASC becomes the default - -=head1 TABLES - -DBI::SQL::Nano::Statement operates on exactly one table. This table will be -opened by inherit from DBI::SQL::Nano::Statement and implements the -C<< open_table >> method. - - sub open_table ($$$$$) - { - ... - return Your::Table->new( \%attributes ); - } - -DBI::SQL::Nano::Statement_ expects a rudimentary interface is implemented by -the table object, as well as SQL::Statement expects. - - package Your::Table; - - use vars qw(@ISA); - @ISA = qw(DBI::SQL::Nano::Table); - - sub drop ($$) { ... } - sub fetch_row ($$$) { ... } - sub push_row ($$$) { ... } - sub push_names ($$$) { ... } - sub truncate ($$) { ... } - sub seek ($$$$) { ... } - -The base class interfaces are provided by DBI::SQL::Nano::Table_ in case of -relying on DBI::SQL::Nano or SQL::Eval::Table (see L for details) -otherwise. - -=head1 BUGS AND LIMITATIONS - -There are no known bugs in DBI::SQL::Nano::Statement. If you find a one -and want to report, please see L for how to report bugs. - -DBI::SQL::Nano::Statement is designed to provide a minimal subset for -executing SQL statements. - -The most important limitation might be the restriction on one table per -statement. This implies, that no JOINs are supported and there cannot be -any foreign key relation between tables. - -The where clause evaluation of DBI::SQL::Nano::Statement is very slow -(SQL::Statement uses a precompiled evaluation). - -INSERT can handle only one row per statement. To insert multiple rows, -use placeholders as explained in DBI. - -The DBI::SQL::Nano parser is very limited and does not support any -additional syntax such as brackets, comments, functions, aggregations -etc. - -In contrast to SQL::Statement, temporary tables are not supported. - -=head1 ACKNOWLEDGEMENTS - -Tim Bunce provided the original idea for this module, helped me out of the -tangled trap of namespaces, and provided help and advice all along the way. -Although I wrote it from the ground up, it is based on Jochen Wiedmann's -original design of SQL::Statement, so much of the credit for the API goes -to him. - -=head1 AUTHOR AND COPYRIGHT - -This module is originally written by Jeff Zucker < jzucker AT cpan.org > - -This module is currently maintained by Jens Rehsack < jrehsack AT cpan.org > - -Copyright (C) 2010 by Jens Rehsack, all rights reserved. -Copyright (C) 2004 by Jeff Zucker, all rights reserved. - -You may freely distribute and/or modify this module under the terms of -either the GNU General Public License (GPL) or the Artistic License, -as specified in the Perl README file. - -=cut - diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Util/CacheMemory.pm b/dbLifeLog/DBI-1.641/lib/DBI/Util/CacheMemory.pm deleted file mode 100644 index ee61690..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Util/CacheMemory.pm +++ /dev/null @@ -1,117 +0,0 @@ -package DBI::Util::CacheMemory; - -# $Id: CacheMemory.pm 10314 2007-11-26 22:25:33Z Tim $ -# -# Copyright (c) 2007, Tim Bunce, Ireland -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -use strict; -use warnings; - -=head1 NAME - -DBI::Util::CacheMemory - a very fast but very minimal subset of Cache::Memory - -=head1 DESCRIPTION - -Like Cache::Memory (part of the Cache distribution) but doesn't support any fancy features. - -This module aims to be a very fast compatible strict sub-set for simple cases, -such as basic client-side caching for DBD::Gofer. - -Like Cache::Memory, and other caches in the Cache and Cache::Cache -distributions, the data will remain in the cache until cleared, it expires, -or the process dies. The cache object simply going out of scope will I -destroy the data. - -=head1 METHODS WITH CHANGES - -=head2 new - -All options except C are ignored. - -=head2 set - -Doesn't support expiry. - -=head2 purge - -Same as clear() - deletes everything in the namespace. - -=head1 METHODS WITHOUT CHANGES - -=over - -=item clear - -=item count - -=item exists - -=item remove - -=back - -=head1 UNSUPPORTED METHODS - -If it's not listed above, it's not supported. - -=cut - -our $VERSION = "0.010315"; - -my %cache; - -sub new { - my ($class, %options ) = @_; - my $namespace = $options{namespace} ||= 'Default'; - #$options{_cache} = \%cache; # can be handy for debugging/dumping - my $self = bless \%options => $class; - $cache{ $namespace } ||= {}; # init - ensure it exists - return $self; -} - -sub set { - my ($self, $key, $value) = @_; - $cache{ $self->{namespace} }->{$key} = $value; -} - -sub get { - my ($self, $key) = @_; - return $cache{ $self->{namespace} }->{$key}; -} - -sub exists { - my ($self, $key) = @_; - return exists $cache{ $self->{namespace} }->{$key}; -} - -sub remove { - my ($self, $key) = @_; - return delete $cache{ $self->{namespace} }->{$key}; -} - -sub purge { - return shift->clear; -} - -sub clear { - $cache{ shift->{namespace} } = {}; -} - -sub count { - return scalar keys %{ $cache{ shift->{namespace} } }; -} - -sub size { - my $c = $cache{ shift->{namespace} }; - my $size = 0; - while ( my ($k,$v) = each %$c ) { - $size += length($k) + length($v); - } - return $size; -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBI/Util/_accessor.pm b/dbLifeLog/DBI-1.641/lib/DBI/Util/_accessor.pm deleted file mode 100644 index 6bb0936..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/Util/_accessor.pm +++ /dev/null @@ -1,65 +0,0 @@ -package DBI::Util::_accessor; -use strict; -use Carp; -our $VERSION = "0.009479"; - -# inspired by Class::Accessor::Fast - -sub new { - my($proto, $fields) = @_; - my($class) = ref $proto || $proto; - $fields ||= {}; - - my @dubious = grep { !m/^_/ && !$proto->can($_) } keys %$fields; - carp "$class doesn't have accessors for fields: @dubious" if @dubious; - - # make a (shallow) copy of $fields. - bless {%$fields}, $class; -} - -sub mk_accessors { - my($self, @fields) = @_; - $self->mk_accessors_using('make_accessor', @fields); -} - -sub mk_accessors_using { - my($self, $maker, @fields) = @_; - my $class = ref $self || $self; - - # So we don't have to do lots of lookups inside the loop. - $maker = $self->can($maker) unless ref $maker; - - no strict 'refs'; - foreach my $field (@fields) { - my $accessor = $self->$maker($field); - *{$class."\:\:$field"} = $accessor - unless defined &{$class."\:\:$field"}; - } - #my $hash_ref = \%{$class."\:\:_accessors_hash}; - #$hash_ref->{$_}++ for @fields; - # XXX also copy down _accessors_hash of base class(es) - # so one in this class is complete - return; -} - -sub make_accessor { - my($class, $field) = @_; - return sub { - my $self = shift; - return $self->{$field} unless @_; - croak "Too many arguments to $field" if @_ > 1; - return $self->{$field} = shift; - }; -} - -sub make_accessor_autoviv_hashref { - my($class, $field) = @_; - return sub { - my $self = shift; - return $self->{$field} ||= {} unless @_; - croak "Too many arguments to $field" if @_ > 1; - return $self->{$field} = shift; - }; -} - -1; diff --git a/dbLifeLog/DBI-1.641/lib/DBI/W32ODBC.pm b/dbLifeLog/DBI-1.641/lib/DBI/W32ODBC.pm deleted file mode 100644 index 2689968..0000000 --- a/dbLifeLog/DBI-1.641/lib/DBI/W32ODBC.pm +++ /dev/null @@ -1,181 +0,0 @@ -package - DBI; # hide this non-DBI package from simple indexers - -# $Id: W32ODBC.pm 8696 2007-01-24 23:12:38Z Tim $ -# -# Copyright (c) 1997,1999 Tim Bunce -# With many thanks to Patrick Hollins for polishing. -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -=head1 NAME - -DBI::W32ODBC - An experimental DBI emulation layer for Win32::ODBC - -=head1 SYNOPSIS - - use DBI::W32ODBC; - - # apart from the line above everything is just the same as with - # the real DBI when using a basic driver with few features. - -=head1 DESCRIPTION - -This is an experimental pure perl DBI emulation layer for Win32::ODBC - -If you can improve this code I'd be interested in hearing about it. If -you are having trouble using it please respect the fact that it's very -experimental. Ideally fix it yourself and send me the details. - -=head2 Some Things Not Yet Implemented - - Most attributes including PrintError & RaiseError. - type_info and table_info - -Volunteers welcome! - -=cut - -${'DBI::VERSION'} # hide version from PAUSE indexer - = "0.01"; - -my $Revision = sprintf("12.%06d", q$Revision: 8696 $ =~ /(\d+)/o); - - -sub DBI::W32ODBC::import { } # must trick here since we're called DBI/W32ODBC.pm - - -use Carp; - -use Win32::ODBC; - -@ISA = qw(Win32::ODBC); - -use strict; - -$DBI::dbi_debug = $ENV{PERL_DBI_DEBUG} || 0; -carp "Loaded (W32ODBC) DBI.pm ${'DBI::VERSION'} (debug $DBI::dbi_debug)" - if $DBI::dbi_debug; - - - -sub connect { - my ($class, $dbname, $dbuser, $dbpasswd, $module, $attr) = @_; - $dbname .= ";UID=$dbuser" if $dbuser; - $dbname .= ";PWD=$dbpasswd" if $dbpasswd; - my $h = new Win32::ODBC $dbname; - warn "Error connecting to $dbname: ".Win32::ODBC::Error()."\n" unless $h; - bless $h, $class if $h; # rebless into our class - $h; -} - - -sub quote { - my ($h, $string) = @_; - return "NULL" if !defined $string; - $string =~ s/'/''/g; # standard - # This hack seems to be required for Access but probably breaks for - # other databases when using \r and \n. It would be better if we could - # use ODBC options to detect that we're actually using Access. - $string =~ s/\r/' & chr\$(13) & '/g; - $string =~ s/\n/' & chr\$(10) & '/g; - "'$string'"; -} - -sub do { - my($h, $statement, $attribs, @params) = @_; - Carp::carp "\$h->do() attribs unused" if $attribs; - my $new_h = $h->prepare($statement) or return undef; ## - pop @{ $h->{'___sths'} }; ## certain death assured - $new_h->execute(@params) or return undef; ## - my $rows = $new_h->rows; ## - $new_h->finish; ## bang bang - ($rows == 0) ? "0E0" : $rows; -} - -# --- - -sub prepare { - my ($h, $sql) = @_; - ## opens a new connection with every prepare to allow - ## multiple, concurrent queries - my $new_h = new Win32::ODBC $h->{DSN}; ## - return undef if not $new_h; ## bail if no connection - bless $new_h; ## shouldn't be sub-classed... - $new_h->{'__prepare'} = $sql; ## - $new_h->{NAME} = []; ## - $new_h->{NUM_OF_FIELDS} = -1; ## - push @{ $h->{'___sths'} } ,$new_h; ## save sth in parent for mass destruction - return $new_h; ## -} - -sub execute { - my ($h) = @_; - my $rc = $h->Sql($h->{'__prepare'}); - return undef if $rc; - my @fields = $h->FieldNames; - $h->{NAME} = \@fields; - $h->{NUM_OF_FIELDS} = scalar @fields; - $h; # return dbh as pseudo sth -} - - -sub fetchrow_hashref { ## provide DBI compatibility - my $h = shift; - my $NAME = shift || "NAME"; - my $row = $h->fetchrow_arrayref or return undef; - my %hash; - @hash{ @{ $h->{$NAME} } } = @$row; - return \%hash; -} - -sub fetchrow { - my $h = shift; - return unless $h->FetchRow(); - my $fields_r = $h->{NAME}; - return $h->Data(@$fields_r); -} -sub fetch { - my @row = shift->fetchrow; - return undef unless @row; - return \@row; -} -*fetchrow_arrayref = \&fetch; ## provide DBI compatibility -*fetchrow_array = \&fetchrow; ## provide DBI compatibility - -sub rows { - shift->RowCount; -} - -sub finish { - shift->Close; ## uncommented this line -} - -# --- - -sub commit { - shift->Transact(ODBC::SQL_COMMIT); -} -sub rollback { - shift->Transact(ODBC::SQL_ROLLBACK); -} - -sub disconnect { - my ($h) = shift; ## this will kill all the statement handles - foreach (@{$h->{'___sths'}}) { ## created for a specific connection - $_->Close if $_->{DSN}; ## - } ## - $h->Close; ## -} - -sub err { - (shift->Error)[0]; -} -sub errstr { - scalar( shift->Error ); -} - -# --- - -1; diff --git a/dbLifeLog/DBI-1.641/lib/Win32/DBIODBC.pm b/dbLifeLog/DBI-1.641/lib/Win32/DBIODBC.pm deleted file mode 100644 index f033444..0000000 --- a/dbLifeLog/DBI-1.641/lib/Win32/DBIODBC.pm +++ /dev/null @@ -1,248 +0,0 @@ -package # hide this package from CPAN indexer - Win32::ODBC; - -use strict; - -use DBI; - -# once we've been loaded we don't want perl to load the real Win32::ODBC -$INC{'Win32/ODBC.pm'} = $INC{'Win32/DBIODBC.pm'} || 1; - -#my $db = new Win32::ODBC("DSN=$self->{'DSN'};UID=$self->{'UID'};PWD=$self->{'PWD'};"); - -#EMU --- my $db = new Win32::ODBC("DSN=$DSN;UID=$login;PWD=$password;"); -sub new -{ - shift; - my $connect_line= shift; - -# [R] self-hack to allow empty UID and PWD - my $temp_connect_line; - $connect_line=~/DSN=\w+/; - $temp_connect_line="$&;"; - if ($connect_line=~/UID=\w?/) - {$temp_connect_line.="$&;";} - else {$temp_connect_line.="UID=;";}; - if ($connect_line=~/PWD=\w?/) - {$temp_connect_line.="$&;";} - else {$temp_connect_line.="PWD=;";}; - $connect_line=$temp_connect_line; -# -[R]- - - my $self= {}; - - - $_=$connect_line; - /^(DSN=)(.*)(;UID=)(.*)(;PWD=)(.*)(;)$/; - - #---- DBI CONNECTION VARIABLES - - $self->{ODBC_DSN}=$2; - $self->{ODBC_UID}=$4; - $self->{ODBC_PWD}=$6; - - - #---- DBI CONNECTION VARIABLES - $self->{DBI_DBNAME}=$self->{ODBC_DSN}; - $self->{DBI_USER}=$self->{ODBC_UID}; - $self->{DBI_PASSWORD}=$self->{ODBC_PWD}; - $self->{DBI_DBD}='ODBC'; - - #---- DBI CONNECTION - $self->{'DBI_DBH'}=DBI->connect($self->{'DBI_DBNAME'}, - $self->{'DBI_USER'},$self->{'DBI_PASSWORD'},$self->{'DBI_DBD'}); - - warn "Error($DBI::err) : $DBI::errstr\n" if ! $self->{'DBI_DBH'}; - - - #---- RETURN - - bless $self; -} - - -#EMU --- $db->Sql('SELECT * FROM DUAL'); -sub Sql -{ - my $self= shift; - my $SQL_statment=shift; - - # print " SQL : $SQL_statment \n"; - - $self->{'DBI_SQL_STATMENT'}=$SQL_statment; - - my $dbh=$self->{'DBI_DBH'}; - - # print " DBH : $dbh \n"; - - my $sth=$dbh->prepare("$SQL_statment"); - - # print " STH : $sth \n"; - - $self->{'DBI_STH'}=$sth; - - if ($sth) - { - $sth->execute(); - } - - #--- GET ERROR MESSAGES - $self->{DBI_ERR}=$DBI::err; - $self->{DBI_ERRSTR}=$DBI::errstr; - - if ($sth) - { - #--- GET COLUMNS NAMES - $self->{'DBI_NAME'} = $sth->{NAME}; - } - -# [R] provide compatibility with Win32::ODBC's way of identifying erroneous SQL statements - return ($self->{'DBI_ERR'})?1:undef; -# -[R]- -} - - -#EMU --- $db->FetchRow()) -sub FetchRow -{ - my $self= shift; - - my $sth=$self->{'DBI_STH'}; - if ($sth) - { - my @row=$sth->fetchrow_array; - $self->{'DBI_ROW'}=\@row; - - if (scalar(@row)>0) - { - #-- the row of result is not nul - #-- return something nothing will be return else - return 1; - } - } - return undef; -} - -# [R] provide compatibility with Win32::ODBC's Data() method. -sub Data -{ - my $self=shift; - my @array=@{$self->{'DBI_ROW'}}; - foreach my $element (@array) - { - # remove padding of spaces by DBI - $element=~s/(\s*$)//; - }; - return (wantarray())?@array:join('', @array); -}; -# -[R]- - -#EMU --- %record = $db->DataHash; -sub DataHash -{ - my $self= shift; - - my $p_name=$self->{'DBI_NAME'}; - my $p_row=$self->{'DBI_ROW'}; - - my @name=@$p_name; - my @row=@$p_row; - - my %DataHash; -#print @name; print "\n"; print @row; -# [R] new code that seems to work consistent with Win32::ODBC - while (@name) - { - my $name=shift(@name); - my $value=shift(@row); - - # remove padding of spaces by DBI - $name=~s/(\s*$)//; - $value=~s/(\s*$)//; - - $DataHash{$name}=$value; - }; -# -[R]- - -# [R] old code that didn't appear to work -# foreach my $name (@name) -# { -# $name=~s/(^\s*)|(\s*$)//; -# my @arr=@$name; -# foreach (@arr) -# { -# print "lot $name name col $_ or ROW= 0 $row[0] 1 $row[1] 2 $row[2] \n "; -# $DataHash{$name}=shift(@row); -# } -# } -# -[R]- - - #--- Return Hash - return %DataHash; -} - - -#EMU --- $db->Error() -sub Error -{ - my $self= shift; - - if ($self->{'DBI_ERR'} ne '') - { - #--- Return error message - $self->{'DBI_ERRSTR'}; - } - - #-- else good no error message - -} - -# [R] provide compatibility with Win32::ODBC's Close() method. -sub Close -{ - my $self=shift; - - my $dbh=$self->{'DBI_DBH'}; - $dbh->disconnect; -} -# -[R]- - -1; - -__END__ - -# [R] to -[R]- indicate sections edited by me, Roy Lee - -=head1 NAME - -Win32::DBIODBC - Win32::ODBC emulation layer for the DBI - -=head1 SYNOPSIS - - use Win32::DBIODBC; # instead of use Win32::ODBC - -=head1 DESCRIPTION - -This is a I basic I alpha quality Win32::ODBC emulation -for the DBI. To use it just replace - - use Win32::ODBC; - -in your scripts with - - use Win32::DBIODBC; - -or, while experimenting, you can pre-load this module without changing your -scripts by doing - - perl -MWin32::DBIODBC your_script_name - -=head1 TO DO - -Error handling is virtually non-existent. - -=head1 AUTHOR - -Tom Horen - -=cut diff --git a/dbLifeLog/DBI-1.641/pm_to_blib b/dbLifeLog/DBI-1.641/pm_to_blib deleted file mode 100644 index e69de29..0000000 diff --git a/dbLifeLog/DBI-1.641/t/01basics.t b/dbLifeLog/DBI-1.641/t/01basics.t deleted file mode 100755 index 36f153b..0000000 --- a/dbLifeLog/DBI-1.641/t/01basics.t +++ /dev/null @@ -1,340 +0,0 @@ -#!perl -w - -use strict; - -use Test::More tests => 130; -use File::Spec; -use Config; - -$|=1; - -## ---------------------------------------------------------------------------- -## 01basic.t - test of some basic DBI functions -## ---------------------------------------------------------------------------- -# Mostly this script takes care of testing the items exported by the 3 -# tags below (in this order): -# - :sql_types -# - :squl_cursor_types -# - :util -# It also then handles some other class methods and functions of DBI, such -# as the following: -# - $DBI::dbi_debug & its relation to DBI->trace -# - DBI->internal -# and then tests on that return value: -# - $i->debug -# - $i->{DebugDispatch} -# - $i->{Warn} -# - $i->{Attribution} -# - $i->{Version} -# - $i->{private_test1} -# - $i->{cachedKids} -# - $i->{Kids} -# - $i->{ActiveKids} -# - $i->{Active} -# - and finally that it will not autovivify -# - DBI->available_drivers -# - DBI->installed_versions (only for developers) -## ---------------------------------------------------------------------------- - -## load DBI and export some symbols -BEGIN { - diag "--- Perl $] on $Config{archname}"; - - use_ok('DBI', qw( - :sql_types - :sql_cursor_types - :utils - )); -} - - -## ---------------------------------------------------------------------------- -## testing the :sql_types exports - -cmp_ok(SQL_GUID , '==', -11, '... testing sql_type'); -cmp_ok(SQL_WLONGVARCHAR , '==', -10, '... testing sql_type'); -cmp_ok(SQL_WVARCHAR , '==', -9, '... testing sql_type'); -cmp_ok(SQL_WCHAR , '==', -8, '... testing sql_type'); -cmp_ok(SQL_BIT , '==', -7, '... testing sql_type'); -cmp_ok(SQL_TINYINT , '==', -6, '... testing sql_type'); -cmp_ok(SQL_BIGINT , '==', -5, '... testing sql_type'); -cmp_ok(SQL_LONGVARBINARY , '==', -4, '... testing sql_type'); -cmp_ok(SQL_VARBINARY , '==', -3, '... testing sql_type'); -cmp_ok(SQL_BINARY , '==', -2, '... testing sql_type'); -cmp_ok(SQL_LONGVARCHAR , '==', -1, '... testing sql_type'); -cmp_ok(SQL_UNKNOWN_TYPE , '==', 0, '... testing sql_type'); -cmp_ok(SQL_ALL_TYPES , '==', 0, '... testing sql_type'); -cmp_ok(SQL_CHAR , '==', 1, '... testing sql_type'); -cmp_ok(SQL_NUMERIC , '==', 2, '... testing sql_type'); -cmp_ok(SQL_DECIMAL , '==', 3, '... testing sql_type'); -cmp_ok(SQL_INTEGER , '==', 4, '... testing sql_type'); -cmp_ok(SQL_SMALLINT , '==', 5, '... testing sql_type'); -cmp_ok(SQL_FLOAT , '==', 6, '... testing sql_type'); -cmp_ok(SQL_REAL , '==', 7, '... testing sql_type'); -cmp_ok(SQL_DOUBLE , '==', 8, '... testing sql_type'); -cmp_ok(SQL_DATETIME , '==', 9, '... testing sql_type'); -cmp_ok(SQL_DATE , '==', 9, '... testing sql_type'); -cmp_ok(SQL_INTERVAL , '==', 10, '... testing sql_type'); -cmp_ok(SQL_TIME , '==', 10, '... testing sql_type'); -cmp_ok(SQL_TIMESTAMP , '==', 11, '... testing sql_type'); -cmp_ok(SQL_VARCHAR , '==', 12, '... testing sql_type'); -cmp_ok(SQL_BOOLEAN , '==', 16, '... testing sql_type'); -cmp_ok(SQL_UDT , '==', 17, '... testing sql_type'); -cmp_ok(SQL_UDT_LOCATOR , '==', 18, '... testing sql_type'); -cmp_ok(SQL_ROW , '==', 19, '... testing sql_type'); -cmp_ok(SQL_REF , '==', 20, '... testing sql_type'); -cmp_ok(SQL_BLOB , '==', 30, '... testing sql_type'); -cmp_ok(SQL_BLOB_LOCATOR , '==', 31, '... testing sql_type'); -cmp_ok(SQL_CLOB , '==', 40, '... testing sql_type'); -cmp_ok(SQL_CLOB_LOCATOR , '==', 41, '... testing sql_type'); -cmp_ok(SQL_ARRAY , '==', 50, '... testing sql_type'); -cmp_ok(SQL_ARRAY_LOCATOR , '==', 51, '... testing sql_type'); -cmp_ok(SQL_MULTISET , '==', 55, '... testing sql_type'); -cmp_ok(SQL_MULTISET_LOCATOR , '==', 56, '... testing sql_type'); -cmp_ok(SQL_TYPE_DATE , '==', 91, '... testing sql_type'); -cmp_ok(SQL_TYPE_TIME , '==', 92, '... testing sql_type'); -cmp_ok(SQL_TYPE_TIMESTAMP , '==', 93, '... testing sql_type'); -cmp_ok(SQL_TYPE_TIME_WITH_TIMEZONE , '==', 94, '... testing sql_type'); -cmp_ok(SQL_TYPE_TIMESTAMP_WITH_TIMEZONE , '==', 95, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_YEAR , '==', 101, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_MONTH , '==', 102, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_DAY , '==', 103, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_HOUR , '==', 104, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_MINUTE , '==', 105, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_SECOND , '==', 106, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_YEAR_TO_MONTH , '==', 107, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_DAY_TO_HOUR , '==', 108, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_DAY_TO_MINUTE , '==', 109, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_DAY_TO_SECOND , '==', 110, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_HOUR_TO_MINUTE , '==', 111, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_HOUR_TO_SECOND , '==', 112, '... testing sql_type'); -cmp_ok(SQL_INTERVAL_MINUTE_TO_SECOND , '==', 113, '... testing sql_type'); - -## ---------------------------------------------------------------------------- -## testing the :sql_cursor_types exports - -cmp_ok(SQL_CURSOR_FORWARD_ONLY, '==', 0, '... testing sql_cursor_types'); -cmp_ok(SQL_CURSOR_KEYSET_DRIVEN, '==', 1, '... testing sql_cursor_types'); -cmp_ok(SQL_CURSOR_DYNAMIC, '==', 2, '... testing sql_cursor_types'); -cmp_ok(SQL_CURSOR_STATIC, '==', 3, '... testing sql_cursor_types'); -cmp_ok(SQL_CURSOR_TYPE_DEFAULT, '==', 0, '... testing sql_cursor_types'); - -## ---------------------------------------------------------------------------- -## test the :util exports - -## testing looks_like_number - -my @is_num = looks_like_number(undef, "", "foo", 1, ".", 2, "2"); - -ok(!defined $is_num[0], '... looks_like_number : undef -> undef'); -ok(!defined $is_num[1], '... looks_like_number : "" -> undef (eg "don\'t know")'); -ok( defined $is_num[2], '... looks_like_number : "foo" -> defined false'); -ok( !$is_num[2], '... looks_like_number : "foo" -> defined false'); -ok( $is_num[3], '... looks_like_number : 1 -> true'); -ok( !$is_num[4], '... looks_like_number : "." -> false'); -ok( $is_num[5], '... looks_like_number : 1 -> true'); -ok( $is_num[6], '... looks_like_number : 1 -> true'); - -## testing neat - -cmp_ok($DBI::neat_maxlen, '==', 1000, "... $DBI::neat_maxlen initial state is 400"); - -is(neat(1 + 1), "2", '... neat : 1 + 1 -> "2"'); -is(neat("2"), "'2'", '... neat : 2 -> "\'2\'"'); -is(neat(undef), "undef", '... neat : undef -> "undef"'); - -## testing neat_list - -is(neat_list([ 1 + 1, "2", undef, "foobarbaz"], 8, "|"), "2|'2'|undef|'foo...'", '... test array argument w/separator and maxlen'); -is(neat_list([ 1 + 1, "2", undef, "foobarbaz"]), "2, '2', undef, 'foobarbaz'", '... test array argument w/out separator or maxlen'); - - -## ---------------------------------------------------------------------------- -## testing DBI functions - -## test DBI->internal - -my $switch = DBI->internal; - -isa_ok($switch, 'DBI::dr'); - -## checking attributes of $switch - -# NOTE: -# check too see if this covers all the attributes or not - -# TO DO: -# these three can be improved -$switch->debug(0); -pass('... test debug'); -$switch->{DebugDispatch} = 0; # handled by Switch -pass('... test DebugDispatch'); -$switch->{Warn} = 1; # handled by DBI core -pass('... test Warn'); - -like($switch->{'Attribution'}, qr/DBI.*? by Tim Bunce/, '... this should say Tim Bunce'); - -# is this being presumptious? -is($switch->{'Version'}, $DBI::VERSION, '... the version should match DBI version'); - -cmp_ok(($switch->{private_test1} = 1), '==', 1, '... this should work and return 1'); -cmp_ok($switch->{private_test1}, '==', 1, '... this should equal 1'); - -is($switch->{CachedKids}, undef, '... CachedKids should be undef initially'); -my $cache = {}; -$switch->{CachedKids} = $cache; -is($switch->{CachedKids}, $cache, '... CachedKids should be our ref'); - -cmp_ok($switch->{Kids}, '==', 0, '... this should be zero'); -cmp_ok($switch->{ActiveKids}, '==', 0, '... this should be zero'); - -ok($switch->{Active}, '... Active flag is true'); - -# test attribute warnings -{ - my $warn = ""; - local $SIG{__WARN__} = sub { $warn .= "@_" }; - $switch->{FooBarUnknown} = 1; - like($warn, qr/Can't set.*FooBarUnknown/, '... we should get a warning here'); - - $warn = ""; - $_ = $switch->{BarFooUnknown}; - like($warn, qr/Can't get.*BarFooUnknown/, '... we should get a warning here'); - - $warn = ""; - my $dummy = $switch->{$_} for qw(private_foo dbd_foo dbi_foo); # special cases - cmp_ok($warn, 'eq', "", '... we should get no warnings here'); -} - -# is this here for a reason? Are we testing anything? - -$switch->trace_msg("Test \$h->trace_msg text.\n", 1); -DBI->trace_msg("Test DBI->trace_msg text.\n", 1); - -## testing DBI->available_drivers - -my @drivers = DBI->available_drivers(); -cmp_ok(scalar(@drivers), '>', 0, '... we at least have one driver installed'); - -# NOTE: -# we lowercase the interpolated @drivers array -# so that our reg-exp will match on VMS & Win32 - -like(lc("@drivers"), qr/examplep/, '... we should at least have ExampleP installed'); - -# call available_drivers in scalar context - -my $num_drivers = DBI->available_drivers; -cmp_ok($num_drivers, '>', 0, '... we should at least have one driver'); - -## testing DBI::hash - -cmp_ok(DBI::hash("foo1" ), '==', -1077531989, '... should be -1077531989'); -cmp_ok(DBI::hash("foo1",0), '==', -1077531989, '... should be -1077531989'); -cmp_ok(DBI::hash("foo2",0), '==', -1077531990, '... should be -1077531990'); -SKIP: { - skip("Math::BigInt < 1.56",2) - if $DBI::PurePerl && !eval { require Math::BigInt; require_version Math::BigInt 1.56 }; - skip("Math::BigInt $Math::BigInt::VERSION broken",2) - if $DBI::PurePerl && $Math::BigInt::VERSION =~ /^1\.8[45]/; - my $bigint_vers = $Math::BigInt::VERSION || ""; - if (!$DBI::PurePerl) { - cmp_ok(DBI::hash("foo1",1), '==', -1263462440); - cmp_ok(DBI::hash("foo2",1), '==', -1263462437); - } - else { - # for PurePerl we use Math::BigInt but that's often caused test failures that - # aren't DBI's fault. So we just warn (via a skip) if it's not working right. - skip("Seems like your Math::BigInt $Math::BigInt::VERSION has a bug",2) - unless (DBI::hash("foo1X",1) == -1263462440) && (DBI::hash("foo2",1) == -1263462437); - ok(1, "Math::BigInt $Math::BigInt::VERSION worked okay"); - ok(1); - } -} - -is(data_string_desc(""), "UTF8 off, ASCII, 0 characters 0 bytes"); -is(data_string_desc(42), "UTF8 off, ASCII, 2 characters 2 bytes"); -is(data_string_desc("foo"), "UTF8 off, ASCII, 3 characters 3 bytes"); -is(data_string_desc(undef), "UTF8 off, undef"); -is(data_string_desc("bar\x{263a}"), "UTF8 on, non-ASCII, 4 characters 6 bytes"); -is(data_string_desc("\xEA"), "UTF8 off, non-ASCII, 1 characters 1 bytes"); - -is(data_string_diff( "", ""), ""); -is(data_string_diff( "",undef), "String b is undef, string a has 0 characters"); -is(data_string_diff(undef,undef), ""); -is(data_string_diff("aaa","aaa"), ""); - -is(data_string_diff("aaa","aba"), "Strings differ at index 1: a[1]=a, b[1]=b"); -is(data_string_diff("aba","aaa"), "Strings differ at index 1: a[1]=b, b[1]=a"); -is(data_string_diff("aa" ,"aaa"), "String a truncated after 2 characters"); -is(data_string_diff("aaa","aa" ), "String b truncated after 2 characters"); - -is(data_diff( "", ""), ""); -is(data_diff(undef,undef), ""); -is(data_diff("aaa","aaa"), ""); - -is(data_diff( "",undef), - join "","a: UTF8 off, ASCII, 0 characters 0 bytes\n", - "b: UTF8 off, undef\n", - "String b is undef, string a has 0 characters\n"); -is(data_diff("aaa","aba"), - join "","a: UTF8 off, ASCII, 3 characters 3 bytes\n", - "b: UTF8 off, ASCII, 3 characters 3 bytes\n", - "Strings differ at index 1: a[1]=a, b[1]=b\n"); -is(data_diff(pack("C",0xEA), pack("U",0xEA)), - join "", "a: UTF8 off, non-ASCII, 1 characters 1 bytes\n", - "b: UTF8 on, non-ASCII, 1 characters 2 bytes\n", - "Strings contain the same sequence of characters\n"); -is(data_diff(pack("C",0xEA), pack("U",0xEA), 1), ""); # no logical difference - - -## ---------------------------------------------------------------------------- -# restrict this test to just developers - -SKIP: { - skip 'developer tests', 4 unless -d ".svn" || -d ".git"; - - if ($^O eq "MSWin32" && eval { require Win32API::File }) { - Win32API::File::SetErrorMode(Win32API::File::SEM_FAILCRITICALERRORS()); - } - - print "Test DBI->installed_versions (for @drivers)\n"; - print "(If one of those drivers, or the configuration for it, is bad\n"; - print "then these tests can kill or freeze the process here. That's not the DBI's fault.)\n"; - $SIG{ALRM} = sub { - die "Test aborted because a driver (one of: @drivers) hung while loading" - ." (almost certainly NOT a DBI problem)"; - }; - alarm(20); - - ## ---------------------------------------------------------------------------- - ## test installed_versions - - # scalar context - my $installed_versions = DBI->installed_versions; - - is(ref($installed_versions), 'HASH', '... we got a hash of installed versions'); - cmp_ok(scalar(keys(%{$installed_versions})), '>=', 1, '... make sure we have at least one'); - - # list context - my @installed_drivers = DBI->installed_versions; - - cmp_ok(scalar(@installed_drivers), '>=', 1, '... make sure we got at least one'); - like("@installed_drivers", qr/Sponge/, '... make sure at least one of them is DBD::Sponge'); -} - -## testing dbi_debug - -cmp_ok($DBI::dbi_debug, '==', 0, "... DBI::dbi_debug's initial state is 0"); - -SKIP: { - my $null = File::Spec->devnull(); - skip "cannot find : $null", 2 unless ($^O eq "MSWin32" || -e $null); - - DBI->trace(15,$null); - cmp_ok($DBI::dbi_debug, '==', 15, "... DBI::dbi_debug is 15"); - DBI->trace(0, undef); - cmp_ok($DBI::dbi_debug, '==', 0, "... DBI::dbi_debug is 0"); -} - -1; diff --git a/dbLifeLog/DBI-1.641/t/02dbidrv.t b/dbLifeLog/DBI-1.641/t/02dbidrv.t deleted file mode 100755 index 7a80ffe..0000000 --- a/dbLifeLog/DBI-1.641/t/02dbidrv.t +++ /dev/null @@ -1,254 +0,0 @@ -#!perl -w -# vim:sw=4:ts=8:et -$|=1; - -use strict; - -use Test::More tests => 53; - -## ---------------------------------------------------------------------------- -## 02dbidrv.t - ... -## ---------------------------------------------------------------------------- -# This test creates a Test Driver (DBD::Test) and then exercises it. -# NOTE: -# There are a number of tests as well that are embedded within the actual -# driver code as well -## ---------------------------------------------------------------------------- - -## load DBI - -BEGIN { - use_ok('DBI'); -} - -## ---------------------------------------------------------------------------- -## create a Test Driver (DBD::Test) - -## main Test Driver Package -{ - package DBD::Test; - - use strict; - use warnings; - - my $drh = undef; - - sub driver { - return $drh if $drh; - - Test::More::pass('... DBD::Test->driver called to getnew Driver handle'); - - my($class, $attr) = @_; - $class = "${class}::dr"; - ($drh) = DBI::_new_drh($class, { - Name => 'Test', - Version => '$Revision: 11.11 $', - }, - 77 # 'implementors data' - ); - - Test::More::ok($drh, "... new Driver handle ($drh) created successfully"); - Test::More::isa_ok($drh, 'DBI::dr'); - - return $drh; - } -} - -## Test Driver -{ - package DBD::Test::dr; - - use strict; - use warnings; - - $DBD::Test::dr::imp_data_size = 0; - - Test::More::cmp_ok($DBD::Test::dr::imp_data_size, '==', 0, '... check DBD::Test::dr::imp_data_size to avoid typo'); - - sub DESTROY { undef } - - sub data_sources { - my ($h) = @_; - - Test::More::ok($h, '... Driver object passed to data_sources'); - Test::More::isa_ok($h, 'DBI::dr'); - Test::More::ok(!tied $h, '... Driver object is not tied'); - - return ("dbi:Test:foo", "dbi:Test:bar"); - } -} - -## Test db package -{ - package DBD::Test::db; - - use strict; - - $DBD::Test::db::imp_data_size = 0; - - Test::More::cmp_ok($DBD::Test::db::imp_data_size, '==', 0, '... check DBD::Test::db::imp_data_size to avoid typo'); - - sub do { - my $h = shift; - - Test::More::ok($h, '... Database object passed to do'); - Test::More::isa_ok($h, 'DBI::db'); - Test::More::ok(!tied $h, '... Database object is not tied'); - - my $drh_i = $h->{Driver}; - - Test::More::ok($drh_i, '... got Driver object from Database object with Driver attribute'); - Test::More::isa_ok($drh_i, "DBI::dr"); - Test::More::ok(!tied %{$drh_i}, '... Driver object is not tied'); - - my $drh_o = $h->FETCH('Driver'); - - Test::More::ok($drh_o, '... got Driver object from Database object by FETCH-ing Driver attribute'); - Test::More::isa_ok($drh_o, "DBI::dr"); - SKIP: { - Test::More::skip "running DBI::PurePerl", 1 if $DBI::PurePerl; - Test::More::ok(tied %{$drh_o}, '... Driver object is not tied'); - } - - # return this to make our test pass - return 1; - } - - sub data_sources { - my ($dbh, $attr) = @_; - my @ds = $dbh->SUPER::data_sources($attr); - - Test::More::is_deeply(( - \@ds, - [ 'dbi:Test:foo', 'dbi:Test:bar' ] - ), - '... checking fetched datasources from Driver' - ); - - push @ds, "dbi:Test:baz"; - return @ds; - } - - sub disconnect { - shift->STORE(Active => 0); - } -} - -## ---------------------------------------------------------------------------- -## test the Driver (DBD::Test) - -$INC{'DBD/Test.pm'} = 'dummy'; # required to fool DBI->install_driver() - -# Note that install_driver should *not* normally be called directly. -# This test does so only because it's a test of install_driver! - -my $drh = DBI->install_driver('Test'); - -ok($drh, '... got a Test Driver object back from DBI->install_driver'); -isa_ok($drh, 'DBI::dr'); - -cmp_ok(DBI::_get_imp_data($drh), '==', 77, '... checking the DBI::_get_imp_data function'); - -my @ds1 = DBI->data_sources("Test"); -is_deeply(( - [ @ds1 ], - [ 'dbi:Test:foo', 'dbi:Test:bar' ] - ), '... got correct datasources from DBI->data_sources("Test")' -); - -SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($drh->{Kids}, '==', 0, '... this Driver does not yet have any Kids'); -} - -# create scope to test $dbh DESTROY behaviour -do { - - my $dbh = $drh->connect; - - ok($dbh, '... got a database handle from calling $drh->connect'); - isa_ok($dbh, 'DBI::db'); - - SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($drh->{Kids}, '==', 1, '... this Driver does not yet have any Kids'); - } - - my @ds2 = $dbh->data_sources(); - is_deeply(( - [ @ds2 ], - [ 'dbi:Test:foo', 'dbi:Test:bar', 'dbi:Test:baz' ] - ), '... got correct datasources from $dbh->data_sources()' - ); - - ok($dbh->do('dummy'), '... this will trigger more driver internal tests above in DBD::Test::db'); - - $dbh->disconnect; - - $drh->set_err("41", "foo 41 drh"); - cmp_ok($drh->err, '==', 41, '... checking Driver handle err set with set_err method'); - $dbh->set_err("42", "foo 42 dbh"); - cmp_ok($dbh->err, '==', 42, '... checking Database handle err set with set_err method'); - cmp_ok($drh->err, '==', 41, '... checking Database handle err set with Driver handle set_err method'); - -}; - -SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($drh->{Kids}, '==', 0, '... this Driver does not yet have any Kids') - or $drh->dump_handle("bad Kids",3); -} - -# copied up to drh from dbh when dbh was DESTROYd -cmp_ok($drh->err, '==', 42, '... $dbh->DESTROY should set $drh->err to 42'); - -$drh->set_err("99", "foo"); -cmp_ok($DBI::err, '==', 99, '... checking $DBI::err set with Driver handle set_err method'); -is($DBI::errstr, "foo 42 dbh [err was 42 now 99]\nfoo", '... checking $DBI::errstr'); - -$drh->default_user("",""); # just to reset err etc -$drh->set_err(1, "errmsg", "00000"); -is($DBI::state, "", '... checking $DBI::state'); - -$drh->set_err(1, "test error 1"); -is($DBI::state, 'S1000', '... checking $DBI::state'); - -$drh->set_err(2, "test error 2", "IM999"); -is($DBI::state, 'IM999', '... checking $DBI::state'); - -SKIP: { - skip "using DBI::PurePerl", 1 if $DBI::PurePerl; - eval { - $DBI::rows = 1 - }; - like($@, qr/Can't modify/, '... trying to assign to $DBI::rows should throw an excpetion'); #' -} - -is($drh->{FetchHashKeyName}, 'NAME', '... FetchHashKeyName is NAME'); -$drh->{FetchHashKeyName} = 'NAME_lc'; -is($drh->{FetchHashKeyName}, 'NAME_lc', '... FetchHashKeyName is now changed to NAME_lc'); - -ok(!$drh->disconnect_all, '... calling $drh->disconnect_all (not implemented but will fail silently)'); - -ok defined $drh->dbixs_revision, 'has dbixs_revision'; -ok($drh->dbixs_revision =~ m/^\d+$/, 'has integer dbixs_revision'); - -SKIP: { - skip "using DBI::PurePerl", 5 if $DBI::PurePerl; - my $can = $drh->can('FETCH'); - - ok($can, '... $drh can FETCH'); - is(ref($can), "CODE", '... and it returned a proper CODE ref'); - - my $name = $can->($drh, "Name"); - - ok($name, '... used FETCH returned from can to fetch the Name attribute'); - is($name, "Test", '... the Name attribute is equal to Test'); - - ok(!$drh->can('disconnect_all'), '... '); -} - -1; diff --git a/dbLifeLog/DBI-1.641/t/03handle.t b/dbLifeLog/DBI-1.641/t/03handle.t deleted file mode 100644 index 5ea61b8..0000000 --- a/dbLifeLog/DBI-1.641/t/03handle.t +++ /dev/null @@ -1,410 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use Test::More tests => 137; - -## ---------------------------------------------------------------------------- -## 03handle.t - tests handles -## ---------------------------------------------------------------------------- -# This set of tests exercises the different handles; Driver, Database and -# Statement in various ways, in particular in their interactions with one -# another -## ---------------------------------------------------------------------------- - -BEGIN { - use_ok( 'DBI' ); -} - -# installed drivers should start empty -my %drivers = DBI->installed_drivers(); -is(scalar keys %drivers, 0); - -## ---------------------------------------------------------------------------- -# get the Driver handle - -my $driver = "ExampleP"; - -my $drh = DBI->install_driver($driver); -isa_ok( $drh, 'DBI::dr' ); - -SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($drh->{Kids}, '==', 0, '... this Driver does not yet have any Kids'); -} - -# now the driver should be registered -%drivers = DBI->installed_drivers(); -is(scalar keys %drivers, 1); -ok(exists $drivers{ExampleP}); -ok($drivers{ExampleP}->isa('DBI::dr')); - -my $using_dbd_gofer = ($ENV{DBI_AUTOPROXY}||'') =~ /^dbi:Gofer.*transport=/i; - -## ---------------------------------------------------------------------------- -# do database handle tests inside do BLOCK to capture scope - -do { - my $dbh = DBI->connect("dbi:$driver:", '', ''); - isa_ok($dbh, 'DBI::db'); - - my $drh = $dbh->{Driver}; # (re)get drh here so tests can work using_dbd_gofer - - SKIP: { - skip "Kids and ActiveKids attributes not supported under DBI::PurePerl", 2 if $DBI::PurePerl; - - cmp_ok($drh->{Kids}, '==', 1, '... our Driver has one Kid'); - cmp_ok($drh->{ActiveKids}, '==', 1, '... our Driver has one ActiveKid'); - } - - my $sql = "select name from ?"; - - my $sth1 = $dbh->prepare_cached($sql); - isa_ok($sth1, 'DBI::st'); - ok($sth1->execute("."), '... execute ran successfully'); - - my $ck = $dbh->{CachedKids}; - is(ref($ck), "HASH", '... we got the CachedKids hash'); - - cmp_ok(scalar(keys(%{$ck})), '==', 1, '... there is one CachedKid'); - ok(eq_set( - [ values %{$ck} ], - [ $sth1 ] - ), - '... our statement handle should be in the CachedKids'); - - ok($sth1->{Active}, '... our first statement is Active'); - - { - my $warn = 0; # use this to check that we are warned - local $SIG{__WARN__} = sub { ++$warn if $_[0] =~ /still active/i }; - - my $sth2 = $dbh->prepare_cached($sql); - isa_ok($sth2, 'DBI::st'); - - is($sth1, $sth2, '... prepare_cached returned the same statement handle'); - cmp_ok($warn,'==', 1, '... we got warned about our first statement handle being still active'); - - ok(!$sth1->{Active}, '... our first statement is no longer Active since we re-prepared it'); - - my $sth3 = $dbh->prepare_cached($sql, { foo => 1 }); - isa_ok($sth3, 'DBI::st'); - - isnt($sth1, $sth3, '... prepare_cached returned a different statement handle now'); - cmp_ok(scalar(keys(%{$ck})), '==', 2, '... there are two CachedKids'); - ok(eq_set( - [ values %{$ck} ], - [ $sth1, $sth3 ] - ), - '... both statement handles should be in the CachedKids'); - - ok($sth1->execute("."), '... executing first statement handle again'); - ok($sth1->{Active}, '... first statement handle is now active again'); - - my $sth4 = $dbh->prepare_cached($sql, undef, 3); - isa_ok($sth4, 'DBI::st'); - - isnt($sth1, $sth4, '... our fourth statement handle is not the same as our first'); - ok($sth1->{Active}, '... first statement handle is still active'); - - cmp_ok(scalar(keys(%{$ck})), '==', 2, '... there are two CachedKids'); - ok(eq_set( - [ values %{$ck} ], - [ $sth2, $sth4 ] - ), - '... second and fourth statement handles should be in the CachedKids'); - - $sth1->finish; - ok(!$sth1->{Active}, '... first statement handle is no longer active'); - - ok($sth4->execute("."), '... fourth statement handle executed properly'); - ok($sth4->{Active}, '... fourth statement handle is Active'); - - my $sth5 = $dbh->prepare_cached($sql, undef, 1); - isa_ok($sth5, 'DBI::st'); - - cmp_ok($warn, '==', 1, '... we still only got one warning'); - - is($sth4, $sth5, '... fourth statement handle and fifth one match'); - ok(!$sth4->{Active}, '... fourth statement handle is not Active'); - ok(!$sth5->{Active}, '... fifth statement handle is not Active (shouldnt be its the same as fifth)'); - - cmp_ok(scalar(keys(%{$ck})), '==', 2, '... there are two CachedKids'); - ok(eq_set( - [ values %{$ck} ], - [ $sth2, $sth5 ] - ), - '... second and fourth/fifth statement handles should be in the CachedKids'); - } - - SKIP: { - skip "swap_inner_handle() not supported under DBI::PurePerl", 23 if $DBI::PurePerl; - - my $sth6 = $dbh->prepare($sql); - $sth6->execute("."); - my $sth1_driver_name = $sth1->{Database}{Driver}{Name}; - - ok( $sth6->{Active}, '... sixth statement handle is active'); - ok(!$sth1->{Active}, '... first statement handle is not active'); - - ok($sth1->swap_inner_handle($sth6), '... first statement handle becomes the sixth'); - ok(!$sth6->{Active}, '... sixth statement handle is now not active'); - ok( $sth1->{Active}, '... first statement handle is now active again'); - - ok($sth1->swap_inner_handle($sth6), '... first statement handle becomes the sixth'); - ok( $sth6->{Active}, '... sixth statement handle is active'); - ok(!$sth1->{Active}, '... first statement handle is not active'); - - ok($sth1->swap_inner_handle($sth6), '... first statement handle becomes the sixth'); - ok(!$sth6->{Active}, '... sixth statement handle is now not active'); - ok( $sth1->{Active}, '... first statement handle is now active again'); - - $sth1->{PrintError} = 0; - ok(!$sth1->swap_inner_handle($dbh), '... can not swap a sth with a dbh'); - cmp_ok( $sth1->errstr, 'eq', "Can't swap_inner_handle between sth and dbh"); - - ok($sth1->swap_inner_handle($sth6), '... first statement handle becomes the sixth'); - ok( $sth6->{Active}, '... sixth statement handle is active'); - ok(!$sth1->{Active}, '... first statement handle is not active'); - - $sth6->finish; - - ok(my $dbh_nullp = DBI->connect("dbi:NullP:", undef, undef, { go_bypass => 1 })); - ok(my $sth7 = $dbh_nullp->prepare("")); - - $sth1->{PrintError} = 0; - ok(!$sth1->swap_inner_handle($sth7), "... can't swap_inner_handle with handle from different parent"); - cmp_ok( $sth1->errstr, 'eq', "Can't swap_inner_handle with handle from different parent"); - - cmp_ok( $sth1->{Database}{Driver}{Name}, 'eq', $sth1_driver_name ); - ok( $sth1->swap_inner_handle($sth7,1), "... can swap to different parent if forced"); - cmp_ok( $sth1->{Database}{Driver}{Name}, 'eq', "NullP" ); - - $dbh_nullp->disconnect; - } - - ok( $dbh->ping, 'ping should be true before disconnect'); - $dbh->disconnect; - $dbh->{PrintError} = 0; # silence 'not connected' warning - ok( !$dbh->ping, 'ping should be false after disconnect'); - - SKIP: { - skip "Kids and ActiveKids attributes not supported under DBI::PurePerl", 2 if $DBI::PurePerl; - - cmp_ok($drh->{Kids}, '==', 1, '... our Driver has one Kid after disconnect'); - cmp_ok($drh->{ActiveKids}, '==', 0, '... our Driver has no ActiveKids after disconnect'); - } - -}; - -if ($using_dbd_gofer) { - $drh->{CachedKids} = {}; -} - -# make sure our driver has no more kids after this test -# NOTE: -# this also assures us that the next test has an empty slate as well -SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($drh->{Kids}, '==', 0, "... our $drh->{Name} driver should have 0 Kids after dbh was destoryed"); -} - -## ---------------------------------------------------------------------------- -# handle reference leak tests - -# NOTE: -# this test checks for reference leaks by testing the Kids attribute -# which is not supported by DBI::PurePerl, so we just do not run this -# for DBI::PurePerl all together. Even though some of the tests would -# pass, it does not make sense because in the end, what is actually -# being tested for will give a false positive - -sub work { - my (%args) = @_; - my $dbh = DBI->connect("dbi:$driver:", '', ''); - isa_ok( $dbh, 'DBI::db' ); - - cmp_ok($drh->{Kids}, '==', 1, '... the Driver should have 1 Kid(s) now'); - - if ( $args{Driver} ) { - isa_ok( $dbh->{Driver}, 'DBI::dr' ); - } else { - pass( "not testing Driver here" ); - } - - my $sth = $dbh->prepare_cached("select name from ?"); - isa_ok( $sth, 'DBI::st' ); - - if ( $args{Database} ) { - isa_ok( $sth->{Database}, 'DBI::db' ); - } else { - pass( "not testing Database here" ); - } - - $dbh->disconnect; - # both handles should be freed here -} - -SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 25 if $DBI::PurePerl; - skip "drh Kids not testable under DBD::Gofer", 25 if $using_dbd_gofer; - - foreach my $args ( - {}, - { Driver => 1 }, - { Database => 1 }, - { Driver => 1, Database => 1 }, - ) { - work( %{$args} ); - cmp_ok($drh->{Kids}, '==', 0, '... the Driver should have no Kids'); - } - - # make sure we have no kids when we end this - cmp_ok($drh->{Kids}, '==', 0, '... the Driver should have no Kids at the end of this test'); -} - -## ---------------------------------------------------------------------------- -# handle take_imp_data test - -SKIP: { - skip "take_imp_data test not supported under DBD::Gofer", 19 if $using_dbd_gofer; - - my $dbh = DBI->connect("dbi:$driver:", '', ''); - isa_ok($dbh, "DBI::db"); - my $drh = $dbh->{Driver}; # (re)get drh here so tests can work using_dbd_gofer - - cmp_ok($drh->{Kids}, '==', 1, '... our Driver should have 1 Kid(s) here') - unless $DBI::PurePerl && pass(); - - $dbh->prepare("select name from ?"); # destroyed at once - my $sth2 = $dbh->prepare("select name from ?"); # inactive - my $sth3 = $dbh->prepare("select name from ?"); # active: - $sth3->execute("."); - is $sth3->{Active}, 1; - is $dbh->{ActiveKids}, 1 - unless $DBI::PurePerl && pass(); - - my $ChildHandles = $dbh->{ChildHandles}; - - skip "take_imp_data test needs weakrefs", 15 if not $ChildHandles; - - ok $ChildHandles, 'we need weakrefs for take_imp_data to work safely with child handles'; - is @$ChildHandles, 3, 'should have 3 entries (implementation detail)'; - is grep({ defined } @$ChildHandles), 2, 'should have 2 defined handles'; - - my $imp_data = $dbh->take_imp_data; - ok($imp_data, '... we got some imp_data to test'); - # generally length($imp_data) = 112 for 32bit, 116 for 64 bit - # (as of DBI 1.37) but it can differ on some platforms - # depending on structure packing by the compiler - # so we just test that it's something reasonable: - cmp_ok(length($imp_data), '>=', 80, '... test that our imp_data is greater than or equal to 80, this is reasonable'); - - cmp_ok($drh->{Kids}, '==', 0, '... our Driver should have 0 Kid(s) after calling take_imp_data'); - - is ref $sth3, 'DBI::zombie', 'sth should be reblessed'; - eval { $sth3->finish }; - like $@, qr/Can't locate object method/; - - { - my @warn; - local $SIG{__WARN__} = sub { push @warn, $_[0] if $_[0] =~ /after take_imp_data/; print "warn: @_\n"; }; - - my $drh = $dbh->{Driver}; - ok(!defined $drh, '... our Driver should be undefined'); - - my $trace_level = $dbh->{TraceLevel}; - ok(!defined $trace_level, '... our TraceLevel should be undefined'); - - ok(!defined $dbh->disconnect, '... disconnect should return undef'); - - ok(!defined $dbh->quote(42), '... quote should return undefined'); - - cmp_ok(scalar @warn, '==', 4, '... we should have gotten 4 warnings'); - } - - my $dbh2 = DBI->connect("dbi:$driver:", '', '', { dbi_imp_data => $imp_data }); - isa_ok($dbh2, "DBI::db"); - # need a way to test dbi_imp_data has been used - - cmp_ok($drh->{Kids}, '==', 1, '... our Driver should have 1 Kid(s) again') - unless $DBI::PurePerl && pass(); - -} - -# we need this SKIP block on its own since we are testing the -# destruction of objects within the scope of the above SKIP -# block -SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($drh->{Kids}, '==', 0, '... our Driver has no Kids after this test'); -} - -## ---------------------------------------------------------------------------- -# NullP statement handle attributes without execute - -my $driver2 = "NullP"; - -my $drh2 = DBI->install_driver($driver); -isa_ok( $drh2, 'DBI::dr' ); - -SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($drh2->{Kids}, '==', 0, '... our Driver (2) has no Kids before this test'); -} - -do { - my $dbh = DBI->connect("dbi:$driver2:", '', ''); - isa_ok($dbh, "DBI::db"); - - my $sth = $dbh->prepare("foo bar"); - isa_ok($sth, "DBI::st"); - - cmp_ok($sth->{NUM_OF_PARAMS}, '==', 0, '... NUM_OF_PARAMS is 0'); - is($sth->{NUM_OF_FIELDS}, undef, '... NUM_OF_FIELDS should be undef'); - is($sth->{Statement}, "foo bar", '... Statement is "foo bar"'); - - ok(!defined $sth->{NAME}, '... NAME is undefined'); - ok(!defined $sth->{TYPE}, '... TYPE is undefined'); - ok(!defined $sth->{SCALE}, '... SCALE is undefined'); - ok(!defined $sth->{PRECISION}, '... PRECISION is undefined'); - ok(!defined $sth->{NULLABLE}, '... NULLABLE is undefined'); - ok(!defined $sth->{RowsInCache}, '... RowsInCache is undefined'); - ok(!defined $sth->{ParamValues}, '... ParamValues is undefined'); - # derived NAME attributes - ok(!defined $sth->{NAME_uc}, '... NAME_uc is undefined'); - ok(!defined $sth->{NAME_lc}, '... NAME_lc is undefined'); - ok(!defined $sth->{NAME_hash}, '... NAME_hash is undefined'); - ok(!defined $sth->{NAME_uc_hash}, '... NAME_uc_hash is undefined'); - ok(!defined $sth->{NAME_lc_hash}, '... NAME_lc_hash is undefined'); - - my $dbh_ref = ref($dbh); - my $sth_ref = ref($sth); - - ok($dbh_ref->can("prepare"), '... $dbh can call "prepare"'); - ok(!$dbh_ref->can("nonesuch"), '... $dbh cannot call "nonesuch"'); - ok($sth_ref->can("execute"), '... $sth can call "execute"'); - - # what is this test for?? - - # I don't know why this warning has the "(perhaps ...)" suffix, it shouldn't: - # Can't locate object method "nonesuch" via package "DBI::db" (perhaps you forgot to load "DBI::db"?) - eval { ref($dbh)->nonesuch; }; - - $dbh->disconnect; -}; - -SKIP: { - skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($drh2->{Kids}, '==', 0, '... our Driver (2) has no Kids after this test'); -} - -## ---------------------------------------------------------------------------- - -1; diff --git a/dbLifeLog/DBI-1.641/t/04mods.t b/dbLifeLog/DBI-1.641/t/04mods.t deleted file mode 100644 index 97638d0..0000000 --- a/dbLifeLog/DBI-1.641/t/04mods.t +++ /dev/null @@ -1,59 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use Test::More tests => 12; - -## ---------------------------------------------------------------------------- -## 04mods.t - ... -## ---------------------------------------------------------------------------- -# Note: -# the modules tested here are all marked as new and not guaranteed, so this if -# they change, these will fail. -## ---------------------------------------------------------------------------- - -BEGIN { - use_ok( 'DBI' ); - - # load these first, since the other two load them - # and we want to catch the error first - use_ok( 'DBI::Const::GetInfo::ANSI' ); - use_ok( 'DBI::Const::GetInfo::ODBC' ); - - use_ok( 'DBI::Const::GetInfoType', qw(%GetInfoType) ); - use_ok( 'DBI::Const::GetInfoReturn', qw(%GetInfoReturnTypes %GetInfoReturnValues) ); -} - -## test GetInfoType - -cmp_ok(scalar(keys(%GetInfoType)), '>', 1, '... we have at least one key in the GetInfoType hash'); - -is_deeply( - \%GetInfoType, - { %DBI::Const::GetInfo::ANSI::InfoTypes, %DBI::Const::GetInfo::ODBC::InfoTypes }, - '... the GetInfoType hash is constructed from the ANSI and ODBC hashes' - ); - -## test GetInfoReturnTypes - -cmp_ok(scalar(keys(%GetInfoReturnTypes)), '>', 1, '... we have at least one key in the GetInfoReturnType hash'); - -is_deeply( - \%GetInfoReturnTypes, - { %DBI::Const::GetInfo::ANSI::ReturnTypes, %DBI::Const::GetInfo::ODBC::ReturnTypes }, - '... the GetInfoReturnType hash is constructed from the ANSI and ODBC hashes' - ); - -## test GetInfoReturnValues - -cmp_ok(scalar(keys(%GetInfoReturnValues)), '>', 1, '... we have at least one key in the GetInfoReturnValues hash'); - -# ... testing GetInfoReturnValues any further would be difficult - -## test the two methods found in DBI::Const::GetInfoReturn - -can_ok('DBI::Const::GetInfoReturn', 'Format'); -can_ok('DBI::Const::GetInfoReturn', 'Explain'); - -1; diff --git a/dbLifeLog/DBI-1.641/t/05concathash.t b/dbLifeLog/DBI-1.641/t/05concathash.t deleted file mode 100644 index 554fc34..0000000 --- a/dbLifeLog/DBI-1.641/t/05concathash.t +++ /dev/null @@ -1,190 +0,0 @@ -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl CatHash.t' - -######################### - -# change 'tests => 1' to 'tests => last_test_to_print'; - -use strict; -use Benchmark qw(:all); -use Scalar::Util qw(looks_like_number); -no warnings 'uninitialized'; - -use Test::More tests => 41; - -BEGIN { use_ok('DBI') }; - -# null and undefs -- segfaults?; -is (DBI::_concat_hash_sorted(undef, "=", ":", 0, undef), undef); -is (DBI::_concat_hash_sorted({ }, "=", ":", 0, undef), ""); -eval { DBI::_concat_hash_sorted([], "=", ":", 0, undef) }; -like ($@ || "", qr/is not a hash reference/); -is (DBI::_concat_hash_sorted({ }, undef, ":", 0, undef), ""); -is (DBI::_concat_hash_sorted({ }, "=", undef, 0, undef), ""); -is (DBI::_concat_hash_sorted({ }, "=", ":", undef, undef),""); - -# simple cases -is (DBI::_concat_hash_sorted({ 1=>"a", 2=>"b" }, "=", ", ", undef, undef), "1='a', 2='b'"); -# nul byte in key sep and pair sep -# (nul byte in hash not supported) -is DBI::_concat_hash_sorted({ 1=>"a", 2=>"b" }, "=\000=", ":\000:", undef, undef), - "1=\000='a':\000:2=\000='b'", 'should work with nul bytes in kv_sep and pair_sep'; -is DBI::_concat_hash_sorted({ 1=>"a\000a", 2=>"b" }, "=", ":", 1, undef), - "1='a.a':2='b'", 'should work with nul bytes in hash value (neat)'; -is DBI::_concat_hash_sorted({ 1=>"a\000a", 2=>"b" }, "=", ":", 0, undef), - "1='a\000a':2='b'", 'should work with nul bytes in hash value (not neat)'; - -# Simple stress tests -# limit stress when performing automated testing -# eg http://www.nntp.perl.org/group/perl.cpan.testers/2009/06/msg4374116.html -my $stress = $ENV{AUTOMATED_TESTING} ? 1_000 : 10_000; -ok(DBI::_concat_hash_sorted({bob=>'two', fred=>'one' }, "="x$stress, ":", 1, undef)); -ok(DBI::_concat_hash_sorted({bob=>'two', fred=>'one' }, "=", ":"x$stress, 1, undef)); -ok(DBI::_concat_hash_sorted({map {$_=>undef} (1..1000)}, "="x$stress, ":", 1, undef)); -ok(DBI::_concat_hash_sorted({map {$_=>undef} (1..1000)}, "=", ":"x$stress, 1, undef), 'test'); -ok(DBI::_concat_hash_sorted({map {$_=>undef} (1..100)}, "="x$stress, ":"x$stress, 1, undef), 'test'); - -my $simple_hash = { - bob=>"there", - jack=>12, - fred=>"there", - norman=>"there", - # sam =>undef -}; - -my $simple_numeric = { - 1=>"there", - 2=>"there", - 16 => 'yo', - 07 => "buddy", - 49 => undef, -}; - -my $simple_mixed = { - bob=>"there", - jack=>12, - fred=>"there", - sam =>undef, - 1=>"there", - 32=>"there", - 16 => 'yo', - 07 => "buddy", - 49 => undef, -}; - -my $simple_float = { - 1.12 =>"there", - 3.1415926 =>"there", - 32=>"there", - 1.6 => 'yo', - 0.78 => "buddy", - 49 => undef, -}; - -#eval { -# DBI::_concat_hash_sorted($simple_hash, "=",,":",1,12); -#}; -ok(1," Unknown sort order"); -#like ($@, qr/Unknown sort order/, "Unknown sort order"); - - - -## Loopify and Add Neat - - -my %neats = ( - "Neat"=>0, - "Not Neat"=> 1 -); -my %sort_types = ( - guess=>undef, - numeric => 1, - lexical=> 0 -); -my %hashes = ( - Numeric=>$simple_numeric, - "Simple Hash" => $simple_hash, - "Mixed Hash" => $simple_mixed, - "Float Hash" => $simple_float -); - -for my $sort_type (keys %sort_types){ - for my $neat (keys %neats) { - for my $hash (keys %hashes) { - test_concat_hash($hash, $neat, $sort_type); - } - } -} - -sub test_concat_hash { - my ($hash, $neat, $sort_type) = @_; - my @args = ($hashes{$hash}, "=", ":",$neats{$neat}, $sort_types{$sort_type}); - is ( - DBI::_concat_hash_sorted(@args), - _concat_hash_sorted(@args), - "$hash - $neat $sort_type" - ); -} - -if (0) { - eval { - cmpthese(200_000, { - Perl => sub {_concat_hash_sorted($simple_hash, "=", ":",0,undef); }, - C=> sub {DBI::_concat_hash_sorted($simple_hash, "=", ":",0,1);} - }); - - print "\n"; - cmpthese(200_000, { - NotNeat => sub {DBI::_concat_hash_sorted( - $simple_hash, "=", ":",1,undef); - }, - Neat => sub {DBI::_concat_hash_sorted( - $simple_hash, "=", ":",0,undef); - } - }); - }; -} -#CatHash::_concat_hash_values({ }, ":-",,"::",1,1); - - -sub _concat_hash_sorted { - my ( $hash_ref, $kv_separator, $pair_separator, $use_neat, $num_sort ) = @_; - # $num_sort: 0=lexical, 1=numeric, undef=try to guess - - return undef unless defined $hash_ref; - die "hash is not a hash reference" unless ref $hash_ref eq 'HASH'; - my $keys = _get_sorted_hash_keys($hash_ref, $num_sort); - my $string = ''; - for my $key (@$keys) { - $string .= $pair_separator if length $string > 0; - my $value = $hash_ref->{$key}; - if ($use_neat) { - $value = DBI::neat($value, 0); - } - else { - $value = (defined $value) ? "'$value'" : 'undef'; - } - $string .= $key . $kv_separator . $value; - } - return $string; -} - -sub _get_sorted_hash_keys { - my ($hash_ref, $sort_type) = @_; - if (not defined $sort_type) { - my $sort_guess = 1; - $sort_guess = (not looks_like_number($_)) ? 0 : $sort_guess - for keys %$hash_ref; - $sort_type = $sort_guess; - } - - my @keys = keys %$hash_ref; - no warnings 'numeric'; - my @sorted = ($sort_type) - ? sort { $a <=> $b or $a cmp $b } @keys - : sort @keys; - #warn "$sort_type = @sorted\n"; - return \@sorted; -} - -1; diff --git a/dbLifeLog/DBI-1.641/t/06attrs.t b/dbLifeLog/DBI-1.641/t/06attrs.t deleted file mode 100644 index c7de7ed..0000000 --- a/dbLifeLog/DBI-1.641/t/06attrs.t +++ /dev/null @@ -1,331 +0,0 @@ -#!perl -w - -use strict; -use Storable qw(dclone); - -use Test::More; - -## ---------------------------------------------------------------------------- -## 06attrs.t - ... -## ---------------------------------------------------------------------------- -# This test checks the parameters and the values associated with them for -# the three different handles (Driver, Database, Statement) -## ---------------------------------------------------------------------------- - -BEGIN { - use_ok( 'DBI' ) -} - -$|=1; - -my $using_autoproxy = ($ENV{DBI_AUTOPROXY}); -my $dsn = 'dbi:ExampleP:dummy'; - -# Connect to the example driver. -my $dbh = DBI->connect($dsn, '', '', { - PrintError => 0, RaiseError => 1, -}); - -isa_ok( $dbh, 'DBI::db' ); - -# Clean up when we're done. -END { $dbh->disconnect if $dbh }; - -## ---------------------------------------------------------------------------- -# Check the database handle attributes. - -# bit flag attr -ok( $dbh->{Warn}, '... checking Warn attribute for dbh'); -ok( $dbh->{Active}, '... checking Active attribute for dbh'); -ok( $dbh->{AutoCommit}, '... checking AutoCommit attribute for dbh'); -ok(!$dbh->{CompatMode}, '... checking CompatMode attribute for dbh'); -ok(!$dbh->{InactiveDestroy}, '... checking InactiveDestroy attribute for dbh'); -ok(!$dbh->{AutoInactiveDestroy}, '... checking AutoInactiveDestroy attribute for dbh'); -ok(!$dbh->{PrintError}, '... checking PrintError attribute for dbh'); -ok( $dbh->{PrintWarn}, '... checking PrintWarn attribute for dbh'); # true because of perl -w above -ok( $dbh->{RaiseError}, '... checking RaiseError attribute for dbh'); -ok(!$dbh->{ShowErrorStatement}, '... checking ShowErrorStatement attribute for dbh'); -ok(!$dbh->{ChopBlanks}, '... checking ChopBlanks attribute for dbh'); -ok(!$dbh->{LongTruncOk}, '... checking LongTrunkOk attribute for dbh'); -ok(!$dbh->{TaintIn}, '... checking TaintIn attribute for dbh'); -ok(!$dbh->{TaintOut}, '... checking TaintOut attribute for dbh'); -ok(!$dbh->{Taint}, '... checking Taint attribute for dbh'); -ok(!$dbh->{Executed}, '... checking Executed attribute for dbh'); - -# other attr -cmp_ok($dbh->{ErrCount}, '==', 0, '... checking ErrCount attribute for dbh'); - -SKIP: { - skip "Kids and ActiveKids attribute not supported under DBI::PurePerl", 2 if $DBI::PurePerl; - - cmp_ok($dbh->{Kids}, '==', 0, '... checking Kids attribute for dbh');; - cmp_ok($dbh->{ActiveKids}, '==', 0, '... checking ActiveKids attribute for dbh');; -} - -is($dbh->{CachedKids}, undef, '... checking CachedKids attribute for dbh'); -ok(!defined $dbh->{HandleError}, '... checking HandleError attribute for dbh'); -ok(!defined $dbh->{Profile}, '... checking Profile attribute for dbh'); -ok(!defined $dbh->{Statement}, '... checking Statement attribute for dbh'); -ok(!defined $dbh->{RowCacheSize}, '... checking RowCacheSize attribute for dbh'); -ok(!defined $dbh->{ReadOnly}, '... checking ReadOnly attribute for dbh'); - -is($dbh->{FetchHashKeyName}, 'NAME', '... checking FetchHashKeyName attribute for dbh'); -is($dbh->{Name}, 'dummy', '... checking Name attribute for dbh') # fails for Multiplex - unless $using_autoproxy && ok(1); - -cmp_ok($dbh->{TraceLevel}, '==', $DBI::dbi_debug & 0xF, '... checking TraceLevel attribute for dbh'); -cmp_ok($dbh->{LongReadLen}, '==', 80, '... checking LongReadLen attribute for dbh'); - -is_deeply [ $dbh->FETCH_many(qw(HandleError FetchHashKeyName LongReadLen ErrCount)) ], - [ undef, qw(NAME 80 0) ], 'should be able to FETCH_many'; - -is $dbh->{examplep_private_dbh_attrib}, 42, 'should see driver-private dbh attribute value'; -is delete $dbh->{examplep_private_dbh_attrib}, 42, 'delete on non-private attribute acts like fetch'; -is $dbh->{examplep_private_dbh_attrib}, 42, 'value unchanged after delete'; - -$dbh->{private_foo} = 42; -is $dbh->{private_foo}, 42, 'should see private_foo dbh attribute value'; -is delete $dbh->{private_foo}, 42, 'delete should return private_foo dbh attribute value'; -is $dbh->{private_foo}, undef, 'value of private_foo after delete should be undef'; - -# Raise an error. -eval { - $dbh->do('select foo from foo') -}; -like($@, qr/^DBD::\w+::db do failed: Unknown field names: foo/ , '... catching exception'); - -ok(defined $dbh->err, '... $dbh->err is undefined'); -like($dbh->errstr, qr/^Unknown field names: foo\b/, '... checking $dbh->errstr'); - -is($dbh->state, 'S1000', '... checking $dbh->state'); - -ok($dbh->{Executed}, '... checking Executed attribute for dbh'); # even though it failed -$dbh->{Executed} = 0; # reset(able) -cmp_ok($dbh->{Executed}, '==', 0, '... checking Executed attribute for dbh (after reset)'); - -cmp_ok($dbh->{ErrCount}, '==', 1, '... checking ErrCount attribute for dbh (after error was generated)'); - -## ---------------------------------------------------------------------------- -# Test the driver handle attributes. - -my $drh = $dbh->{Driver}; -isa_ok( $drh, 'DBI::dr' ); - -ok($dbh->err, '... checking $dbh->err'); - -cmp_ok($drh->{ErrCount}, '==', 0, '... checking ErrCount attribute for drh'); - -ok( $drh->{Warn}, '... checking Warn attribute for drh'); -ok( $drh->{Active}, '... checking Active attribute for drh'); -ok( $drh->{AutoCommit}, '... checking AutoCommit attribute for drh'); -ok(!$drh->{CompatMode}, '... checking CompatMode attribute for drh'); -ok(!$drh->{InactiveDestroy}, '... checking InactiveDestroy attribute for drh'); -ok(!$drh->{AutoInactiveDestroy}, '... checking AutoInactiveDestroy attribute for drh'); -ok(!$drh->{PrintError}, '... checking PrintError attribute for drh'); -ok( $drh->{PrintWarn}, '... checking PrintWarn attribute for drh'); # true because of perl -w above -ok(!$drh->{RaiseError}, '... checking RaiseError attribute for drh'); -ok(!$drh->{ShowErrorStatement}, '... checking ShowErrorStatement attribute for drh'); -ok(!$drh->{ChopBlanks}, '... checking ChopBlanks attribute for drh'); -ok(!$drh->{LongTruncOk}, '... checking LongTrunkOk attribute for drh'); -ok(!$drh->{TaintIn}, '... checking TaintIn attribute for drh'); -ok(!$drh->{TaintOut}, '... checking TaintOut attribute for drh'); -ok(!$drh->{Taint}, '... checking Taint attribute for drh'); - -SKIP: { - skip "Executed attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - ok($drh->{Executed}, '... checking Executed attribute for drh') # due to the do() above -} - -SKIP: { - skip "Kids and ActiveKids attribute not supported under DBI::PurePerl", 2 if ($DBI::PurePerl or $dbh->{mx_handle_list}); - cmp_ok($drh->{Kids}, '==', 1, '... checking Kids attribute for drh'); - cmp_ok($drh->{ActiveKids}, '==', 1, '... checking ActiveKids attribute for drh'); -} - -is($drh->{CachedKids}, undef, '... checking CachedKids attribute for drh'); -ok(!defined $drh->{HandleError}, '... checking HandleError attribute for drh'); -ok(!defined $drh->{Profile}, '... checking Profile attribute for drh'); -ok(!defined $drh->{ReadOnly}, '... checking ReadOnly attribute for drh'); - -cmp_ok($drh->{TraceLevel}, '==', $DBI::dbi_debug & 0xF, '... checking TraceLevel attribute for drh'); -cmp_ok($drh->{LongReadLen}, '==', 80, '... checking LongReadLen attribute for drh'); - -is($drh->{FetchHashKeyName}, 'NAME', '... checking FetchHashKeyName attribute for drh'); -is($drh->{Name}, 'ExampleP', '... checking Name attribute for drh') - unless $using_autoproxy && ok(1); - -## ---------------------------------------------------------------------------- -# Test the statement handle attributes. - -# Create a statement handle. -my $sth = $dbh->prepare("select ctime, name from ?"); -isa_ok($sth, "DBI::st"); - -ok(!$sth->{Executed}, '... checking Executed attribute for sth'); -ok(!$dbh->{Executed}, '... checking Executed attribute for dbh'); -cmp_ok($sth->{ErrCount}, '==', 0, '... checking ErrCount attribute for sth'); - -# Trigger an exception. -eval { - $sth->execute("foo") -}; -# we don't check actual opendir error msg because of locale differences -like($@, qr/^DBD::\w+::st execute failed: .*opendir\(foo\): /msi, '... checking exception'); - -# Test all of the statement handle attributes. -like($sth->errstr, qr/opendir\(foo\): /, '... checking $sth->errstr'); -is($sth->state, 'S1000', '... checking $sth->state'); -ok($sth->{Executed}, '... checking Executed attribute for sth'); # even though it failed -ok($dbh->{Executed}, '... checking Exceuted attribute for dbh'); # due to $sth->prepare, even though it failed - -cmp_ok($sth->{ErrCount}, '==', 1, '... checking ErrCount attribute for sth'); - -$sth->{ErrCount} = 0; -cmp_ok($sth->{ErrCount}, '==', 0, '... checking ErrCount attribute for sth (after reset)'); - -# booleans -ok( $sth->{Warn}, '... checking Warn attribute for sth'); -ok(!$sth->{Active}, '... checking Active attribute for sth'); -ok(!$sth->{CompatMode}, '... checking CompatMode attribute for sth'); -ok(!$sth->{InactiveDestroy}, '... checking InactiveDestroy attribute for sth'); -ok(!$sth->{AutoInactiveDestroy}, '... checking AutoInactiveDestroy attribute for sth'); -ok(!$sth->{PrintError}, '... checking PrintError attribute for sth'); -ok( $sth->{PrintWarn}, '... checking PrintWarn attribute for sth'); -ok( $sth->{RaiseError}, '... checking RaiseError attribute for sth'); -ok(!$sth->{ShowErrorStatement}, '... checking ShowErrorStatement attribute for sth'); -ok(!$sth->{ChopBlanks}, '... checking ChopBlanks attribute for sth'); -ok(!$sth->{LongTruncOk}, '... checking LongTrunkOk attribute for sth'); -ok(!$sth->{TaintIn}, '... checking TaintIn attribute for sth'); -ok(!$sth->{TaintOut}, '... checking TaintOut attribute for sth'); -ok(!$sth->{Taint}, '... checking Taint attribute for sth'); - -# common attr -SKIP: { - skip "Kids and ActiveKids attribute not supported under DBI::PurePerl", 2 if $DBI::PurePerl; - cmp_ok($sth->{Kids}, '==', 0, '... checking Kids attribute for sth'); - cmp_ok($sth->{ActiveKids}, '==', 0, '... checking ActiveKids attribute for sth'); -} - -ok(!defined $sth->{CachedKids}, '... checking CachedKids attribute for sth'); -ok(!defined $sth->{HandleError}, '... checking HandleError attribute for sth'); -ok(!defined $sth->{Profile}, '... checking Profile attribute for sth'); -ok(!defined $sth->{ReadOnly}, '... checking ReadOnly attribute for sth'); - -cmp_ok($sth->{TraceLevel}, '==', $DBI::dbi_debug & 0xF, '... checking TraceLevel attribute for sth'); -cmp_ok($sth->{LongReadLen}, '==', 80, '... checking LongReadLen attribute for sth'); - -is($sth->{FetchHashKeyName}, 'NAME', '... checking FetchHashKeyName attribute for sth'); - -# sth specific attr -ok(!defined $sth->{CursorName}, '... checking CursorName attribute for sth'); - -cmp_ok($sth->{NUM_OF_FIELDS}, '==', 2, '... checking NUM_OF_FIELDS attribute for sth'); -cmp_ok($sth->{NUM_OF_PARAMS}, '==', 1, '... checking NUM_OF_PARAMS attribute for sth'); - -my $name = $sth->{NAME}; -is(ref($name), 'ARRAY', '... checking type of NAME attribute for sth'); -cmp_ok(scalar(@{$name}), '==', 2, '... checking number of elements returned'); -is_deeply($name, ['ctime', 'name' ], '... checking values returned'); - -my $name_lc = $sth->{NAME_lc}; -is(ref($name_lc), 'ARRAY', '... checking type of NAME_lc attribute for sth'); -cmp_ok(scalar(@{$name_lc}), '==', 2, '... checking number of elements returned'); -is_deeply($name_lc, ['ctime', 'name' ], '... checking values returned'); - -my $name_uc = $sth->{NAME_uc}; -is(ref($name_uc), 'ARRAY', '... checking type of NAME_uc attribute for sth'); -cmp_ok(scalar(@{$name_uc}), '==', 2, '... checking number of elements returned'); -is_deeply($name_uc, ['CTIME', 'NAME' ], '... checking values returned'); - -my $nhash = $sth->{NAME_hash}; -is(ref($nhash), 'HASH', '... checking type of NAME_hash attribute for sth'); -cmp_ok(scalar(keys(%{$nhash})), '==', 2, '... checking number of keys returned'); -cmp_ok($nhash->{ctime}, '==', 0, '... checking values returned'); -cmp_ok($nhash->{name}, '==', 1, '... checking values returned'); - -my $nhash_lc = $sth->{NAME_lc_hash}; -is(ref($nhash_lc), 'HASH', '... checking type of NAME_lc_hash attribute for sth'); -cmp_ok(scalar(keys(%{$nhash_lc})), '==', 2, '... checking number of keys returned'); -cmp_ok($nhash_lc->{ctime}, '==', 0, '... checking values returned'); -cmp_ok($nhash_lc->{name}, '==', 1, '... checking values returned'); - -my $nhash_uc = $sth->{NAME_uc_hash}; -is(ref($nhash_uc), 'HASH', '... checking type of NAME_uc_hash attribute for sth'); -cmp_ok(scalar(keys(%{$nhash_uc})), '==', 2, '... checking number of keys returned'); -cmp_ok($nhash_uc->{CTIME}, '==', 0, '... checking values returned'); -cmp_ok($nhash_uc->{NAME}, '==', 1, '... checking values returned'); - -if ( - ! $using_autoproxy - and - # Older Storable does not work properly with tied handles - # Instead of hard-depending on newer Storable, just skip this - # particular test outright - eval { Storable->VERSION("2.16") } -) { - # set ability to set sth attributes that are usually set internally - for $a (qw(NAME NAME_lc NAME_uc NAME_hash NAME_lc_hash NAME_uc_hash)) { - my $v = $sth->{$a}; - ok(eval { $sth->{$a} = dclone($sth->{$a}) }, "Can set sth $a"); - is_deeply($sth->{$a}, $v, "Can get set sth $a"); - } -} - -my $type = $sth->{TYPE}; -is(ref($type), 'ARRAY', '... checking type of TYPE attribute for sth'); -cmp_ok(scalar(@{$type}), '==', 2, '... checking number of elements returned'); -is_deeply($type, [ 4, 12 ], '... checking values returned'); - -my $null = $sth->{NULLABLE}; -is(ref($null), 'ARRAY', '... checking type of NULLABLE attribute for sth'); -cmp_ok(scalar(@{$null}), '==', 2, '... checking number of elements returned'); -is_deeply($null, [ 0, 0 ], '... checking values returned'); - -# Should these work? They don't. -my $prec = $sth->{PRECISION}; -is(ref($prec), 'ARRAY', '... checking type of PRECISION attribute for sth'); -cmp_ok(scalar(@{$prec}), '==', 2, '... checking number of elements returned'); -is_deeply($prec, [ 10, 1024 ], '... checking values returned'); - -my $scale = $sth->{SCALE}; -is(ref($scale), 'ARRAY', '... checking type of SCALE attribute for sth'); -cmp_ok(scalar(@{$scale}), '==', 2, '... checking number of elements returned'); -is_deeply($scale, [ 0, 0 ], '... checking values returned'); - -my $params = $sth->{ParamValues}; -is(ref($params), 'HASH', '... checking type of ParamValues attribute for sth'); -is($params->{1}, 'foo', '... checking values returned'); - -is($sth->{Statement}, "select ctime, name from ?", '... checking Statement attribute for sth'); -ok(!defined $sth->{RowsInCache}, '... checking type of RowsInCache attribute for sth'); - -is $sth->{examplep_private_sth_attrib}, 24, 'should see driver-private sth attribute value'; - -# $h->{TraceLevel} tests are in t/09trace.t - -note "Checking inheritance\n"; - -SKIP: { - skip "drh->dbh->sth inheritance test skipped with DBI_AUTOPROXY", 2 if $ENV{DBI_AUTOPROXY}; - -sub check_inherited { - my ($drh, $attr, $value, $skip_sth) = @_; - local $drh->{$attr} = $value; - local $drh->{PrintError} = 1; - my $dbh = $drh->connect("dummy"); - is $dbh->{$attr}, $drh->{$attr}, "dbh $attr value should be inherited from drh"; - unless ($skip_sth) { - my $sth = $dbh->prepare("select name from ."); - is $sth->{$attr}, $dbh->{$attr}, "sth $attr value should be inherited from dbh"; - } -} - -check_inherited($drh, "ReadOnly", 1, 0); - -} - -done_testing(); - -1; -# end diff --git a/dbLifeLog/DBI-1.641/t/07kids.t b/dbLifeLog/DBI-1.641/t/07kids.t deleted file mode 100644 index 8364ad2..0000000 --- a/dbLifeLog/DBI-1.641/t/07kids.t +++ /dev/null @@ -1,102 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use Test::More; - -use DBI 1.50; # also tests Exporter::require_version - -BEGIN { - plan skip_all => '$h->{Kids} attribute not supported for DBI::PurePerl' - if $DBI::PurePerl && $DBI::PurePerl; # doubled to avoid typo warning - plan tests => 20; -} - -## ---------------------------------------------------------------------------- -## 07kids.t -## ---------------------------------------------------------------------------- -# This test check the Kids and the ActiveKids attributes and how they act -# in various situations. -# -# Check the database handle's kids: -# - upon creation of handle -# - upon creation of statement handle -# - after execute of statement handle -# - after finish of statement handle -# - after destruction of statement handle -# Check the driver handle's kids: -# - after creation of database handle -# - after disconnection of database handle -# - after destruction of database handle -## ---------------------------------------------------------------------------- - - -# Connect to the example driver and create a database handle -my $dbh = DBI->connect('dbi:ExampleP:dummy', '', '', - { - PrintError => 1, - RaiseError => 0 - }); - -# check our database handle to make sure its good -isa_ok($dbh, 'DBI::db'); - -# check that it has no Kids or ActiveKids yet -cmp_ok($dbh->{Kids}, '==', 0, '... database handle has 0 Kid(s) at start'); -cmp_ok($dbh->{ActiveKids}, '==', 0, '... database handle has 0 ActiveKid(s) at start'); - -# create a scope for our $sth to live and die in -do { - - # create a statement handle - my $sth = $dbh->prepare('select uid from ./'); - - # verify that it is a correct statement handle - isa_ok($sth, "DBI::st"); - - # check our Kids and ActiveKids after prepare - cmp_ok($dbh->{Kids}, '==', 1, '... database handle has 1 Kid(s) after $dbh->prepare'); - cmp_ok($dbh->{ActiveKids}, '==', 0, '... database handle has 0 ActiveKid(s) after $dbh->prepare'); - - $sth->execute(); - - # check our Kids and ActiveKids after execute - cmp_ok($dbh->{Kids}, '==', 1, '... database handle has 1 Kid(s) after $sth->execute'); - cmp_ok($dbh->{ActiveKids}, '==', 1, '... database handle has 1 ActiveKid(s) after $sth->execute'); - - $sth->finish(); - - # check our Kids and Activekids after finish - cmp_ok($dbh->{Kids}, '==', 1, '... database handle has 1 Kid(s) after $sth->finish'); - cmp_ok($dbh->{ActiveKids}, '==', 0, '... database handle has 0 ActiveKid(s) after $sth->finish'); - -}; - -# now check it after the statement handle has been destroyed -cmp_ok($dbh->{Kids}, '==', 0, '... database handle has 0 Kid(s) after $sth is destroyed'); -cmp_ok($dbh->{ActiveKids}, '==', 0, '... database handle has 0 ActiveKid(s) after $sth is destroyed'); - -# get the database handles driver Driver -my $drh = $dbh->{Driver}; - -# check that is it a correct driver handle -isa_ok($drh, "DBI::dr"); - -# check the driver's Kids and ActiveKids -cmp_ok( $drh->{Kids}, '==', 1, '... driver handle has 1 Kid(s)'); -cmp_ok( $drh->{ActiveKids}, '==', 1, '... driver handle has 1 ActiveKid(s)'); - -$dbh->disconnect; - -# check the driver's Kids and ActiveKids after $dbh->disconnect -cmp_ok( $drh->{Kids}, '==', 1, '... driver handle has 1 Kid(s) after $dbh->disconnect'); -cmp_ok( $drh->{ActiveKids}, '==', 0, '... driver handle has 0 ActiveKid(s) after $dbh->disconnect'); - -undef $dbh; -ok(!defined($dbh), '... lets be sure that $dbh is not undefined'); - -# check the driver's Kids and ActiveKids after undef $dbh -cmp_ok( $drh->{Kids}, '==', 0, '... driver handle has 0 Kid(s) after undef $dbh'); -cmp_ok( $drh->{ActiveKids}, '==', 0, '... driver handle has 0 ActiveKid(s) after undef $dbh'); - diff --git a/dbLifeLog/DBI-1.641/t/08keeperr.t b/dbLifeLog/DBI-1.641/t/08keeperr.t deleted file mode 100644 index 9b63a20..0000000 --- a/dbLifeLog/DBI-1.641/t/08keeperr.t +++ /dev/null @@ -1,348 +0,0 @@ -#!perl -w - -use strict; - -use Test::More; - -## ---------------------------------------------------------------------------- -## 08keeperr.t -## ---------------------------------------------------------------------------- -# -## ---------------------------------------------------------------------------- - -BEGIN { - use_ok('DBI'); -} - -$|=1; -$^W=1; - -## ---------------------------------------------------------------------------- -# subclass DBI - -# DBI subclass -package My::DBI; -use base 'DBI'; - -# Database handle subclass -package My::DBI::db; -use base 'DBI::db'; - -# Statement handle subclass -package My::DBI::st; -use base 'DBI::st'; - -sub execute { - my $sth = shift; - # we localize an attribute here to check that the corresponding STORE - # at scope exit doesn't clear any recorded error - local $sth->{Warn} = 0; - my $rv = $sth->SUPER::execute(@_); - return $rv; -} - - -## ---------------------------------------------------------------------------- -# subclass the subclass of DBI - -package Test; - -use strict; -use base 'My::DBI'; - -use DBI; - -my @con_info = ('dbi:ExampleP:.', undef, undef, { PrintError => 0, RaiseError => 1 }); - -sub test_select { - my $dbh = shift; - eval { $dbh->selectrow_arrayref('select * from foo') }; - $dbh->disconnect; - return $@; -} - -my $err1 = test_select( My::DBI->connect(@con_info) ); -Test::More::like($err1, qr/^DBD::(ExampleP|Multiplex|Gofer)::db selectrow_arrayref failed: opendir/, '... checking error'); - -my $err2 = test_select( DBI->connect(@con_info) ); -Test::More::like($err2, qr/^DBD::(ExampleP|Multiplex|Gofer)::db selectrow_arrayref failed: opendir/, '... checking error'); - -package main; - -my $using_dbd_gofer = ( $ENV{DBI_AUTOPROXY} || '' ) =~ /^dbi:Gofer.*transport=/i; - - -# test ping does not destroy the errstr -sub ping_keeps_err { - my $dbh = DBI->connect('DBI:ExampleP:', undef, undef, { PrintError => 0 }); - - $dbh->set_err(42, "ERROR 42"); - is $dbh->err, 42; - is $dbh->errstr, "ERROR 42"; - ok $dbh->ping, "ping returns true"; - is $dbh->err, 42, "err unchanged after ping"; - is $dbh->errstr, "ERROR 42", "errstr unchanged after ping"; - - $dbh->disconnect; - - $dbh->set_err(42, "ERROR 42"); - is $dbh->err, 42, "err unchanged after ping"; - is $dbh->errstr, "ERROR 42", "errstr unchanged after ping"; - ok !$dbh->ping, "ping returns false"; - # it's reasonable for ping() to set err/errstr if it fails - # so here we just test that there is an error - ok $dbh->err, "err true after failed ping"; - ok $dbh->errstr, "errstr true after failed ping"; - - - # for a driver which doesn't have its own ping - $dbh = DBI->connect('DBI:Sponge:', undef, undef, { PrintError => 0 }); - $dbh->STORE(Active => 1); - - $dbh->set_err(42, "ERROR 42"); - is $dbh->err, 42; - is $dbh->errstr, "ERROR 42"; - ok $dbh->ping, "ping returns true: ".$dbh->ping; - is $dbh->err, 42, "err unchanged after ping"; - is $dbh->errstr, "ERROR 42", "errstr unchanged after ping"; - - $dbh->disconnect; - $dbh->STORE(Active => 0); - - $dbh->set_err(42, "ERROR 42"); - is $dbh->err, 42, "err unchanged after ping"; - is $dbh->errstr, "ERROR 42", "errstr unchanged after ping"; - ok !$dbh->ping, "ping returns false"; - # it's reasonable for ping() to set err/errstr if it fails - # so here we just test that there is an error - ok $dbh->err, "err true after failed ping"; - ok $dbh->errstr, "errstr true after failed ping"; - -} - -## ---------------------------------------------------------------------------- -print "Test HandleSetErr\n"; - -my $dbh = DBI->connect(@con_info); -isa_ok($dbh, "DBI::db"); - -$dbh->{RaiseError} = 1; -$dbh->{PrintError} = 1; -$dbh->{PrintWarn} = 1; - -# warning handler -my %warn; -my @handlewarn; - -sub reset_warn_counts { - %warn = ( failed => 0, warning => 0 ); - @handlewarn = (0,0,0); -} -reset_warn_counts(); - -$SIG{__WARN__} = sub { - my $msg = shift; - if ($msg =~ /^DBD::\w+::\S+\s+(\S+)\s+(\w+)/) { - ++$warn{$2}; - $msg =~ s/\n/\\n/g; - print "warn: '$msg'\n"; - return; - } - warn $msg; -}; - -# HandleSetErr handler -$dbh->{HandleSetErr} = sub { - my ($h, $err, $errstr, $state) = @_; - return 0 - unless defined $err; - ++$handlewarn[ $err ? 2 : length($err) ]; # count [info, warn, err] calls - return 1 - if $state && $state eq "return"; # for tests - ($_[1], $_[2], $_[3]) = (99, "errstr99", "OV123") - if $state && $state eq "override"; # for tests - return 0 - if $err; # be transparent for errors - local $^W; - print "HandleSetErr called: h=$h, err=$err, errstr=$errstr, state=$state\n"; - return 0; -}; - -# start our tests - -ok(!defined $DBI::err, '... $DBI::err is not defined'); - -# ---- - -$dbh->set_err("", "(got info)"); - -ok(defined $DBI::err, '... $DBI::err is defined'); # true -is($DBI::err, "", '... $DBI::err is an empty string'); -is($DBI::errstr, "(got info)", '... $DBI::errstr is as we expected'); -is($dbh->errstr, "(got info)", '... $dbh->errstr matches $DBI::errstr'); -cmp_ok($warn{failed}, '==', 0, '... $warn{failed} is 0'); -cmp_ok($warn{warning}, '==', 0, '... $warn{warning} is 0'); -is_deeply(\@handlewarn, [ 1, 0, 0 ], '... the @handlewarn array is (1, 0, 0)'); - -# ---- - -$dbh->set_err(0, "(got warn)", "AA001"); # triggers PrintWarn - -ok(defined $DBI::err, '... $DBI::err is defined'); -is($DBI::err, "0", '... $DBI::err is "0"'); -is($DBI::errstr, "(got info)\n(got warn)", - '... $DBI::errstr is as we expected'); -is($dbh->errstr, "(got info)\n(got warn)", - '... $dbh->errstr matches $DBI::errstr'); -is($DBI::state, "AA001", '... $DBI::state is AA001'); -cmp_ok($warn{warning}, '==', 1, '... $warn{warning} is 1'); -is_deeply(\@handlewarn, [ 1, 1, 0 ], '... the @handlewarn array is (1, 1, 0)'); - - -# ---- - -$dbh->set_err("", "(got more info)"); # triggers PrintWarn - -ok(defined $DBI::err, '... $DBI::err is defined'); -is($DBI::err, "0", '... $DBI::err is "0"'); # not "", ie it's still a warn -is($dbh->err, "0", '... $dbh->err is "0"'); -is($DBI::state, "AA001", '... $DBI::state is AA001'); -is($DBI::errstr, "(got info)\n(got warn)\n(got more info)", - '... $DBI::errstr is as we expected'); -is($dbh->errstr, "(got info)\n(got warn)\n(got more info)", - '... $dbh->errstr matches $DBI::errstr'); -cmp_ok($warn{warning}, '==', 2, '... $warn{warning} is 2'); -is_deeply(\@handlewarn, [ 2, 1, 0 ], '... the @handlewarn array is (2, 1, 0)'); - -# ---- - -$dbh->{RaiseError} = 0; -$dbh->{PrintError} = 1; - -# ---- - -$dbh->set_err("42", "(got error)", "AA002"); - -ok(defined $DBI::err, '... $DBI::err is defined'); -cmp_ok($DBI::err, '==', 42, '... $DBI::err is 42'); -cmp_ok($warn{warning}, '==', 2, '... $warn{warning} is 2'); -is($dbh->errstr, "(got info)\n(got warn)\n(got more info) [state was AA001 now AA002]\n(got error)", - '... $dbh->errstr is as we expected'); -is($DBI::state, "AA002", '... $DBI::state is AA002'); -is_deeply(\@handlewarn, [ 2, 1, 1 ], '... the @handlewarn array is (2, 1, 1)'); - -# ---- - -$dbh->set_err("", "(got info)"); - -ok(defined $DBI::err, '... $DBI::err is defined'); -cmp_ok($DBI::err, '==', 42, '... $DBI::err is 42'); -cmp_ok($warn{warning}, '==', 2, '... $warn{warning} is 2'); -is($dbh->errstr, "(got info)\n(got warn)\n(got more info) [state was AA001 now AA002]\n(got error)\n(got info)", - '... $dbh->errstr is as we expected'); -is_deeply(\@handlewarn, [ 3, 1, 1 ], '... the @handlewarn array is (3, 1, 1)'); - -# ---- - -$dbh->set_err("0", "(got warn)"); # no PrintWarn because it's already an err - -ok(defined $DBI::err, '... $DBI::err is defined'); -cmp_ok($DBI::err, '==', 42, '... $DBI::err is 42'); -cmp_ok($warn{warning}, '==', 2, '... $warn{warning} is 2'); -is($dbh->errstr, "(got info)\n(got warn)\n(got more info) [state was AA001 now AA002]\n(got error)\n(got info)\n(got warn)", - '... $dbh->errstr is as we expected'); -is_deeply(\@handlewarn, [ 3, 2, 1 ], '... the @handlewarn array is (3, 2, 1)'); - -# ---- - -$dbh->set_err("4200", "(got new error)", "AA003"); - -ok(defined $DBI::err, '... $DBI::err is defined'); -cmp_ok($DBI::err, '==', 4200, '... $DBI::err is 4200'); -cmp_ok($warn{warning}, '==', 2, '... $warn{warning} is 2'); -is($dbh->errstr, "(got info)\n(got warn)\n(got more info) [state was AA001 now AA002]\n(got error)\n(got info)\n(got warn) [err was 42 now 4200] [state was AA002 now AA003]\n(got new error)", - '... $dbh->errstr is as we expected'); -is_deeply(\@handlewarn, [ 3, 2, 2 ], '... the @handlewarn array is (3, 2, 2)'); - -# ---- - -$dbh->set_err(undef, "foo", "bar"); # clear error - -ok(!defined $dbh->errstr, '... $dbh->errstr is defined'); -ok(!defined $dbh->err, '... $dbh->err is defined'); -is($dbh->state, "", '... $dbh->state is an empty string'); - -# ---- - -reset_warn_counts(); - -# ---- - -my @ret; -@ret = $dbh->set_err(1, "foo"); # PrintError - -cmp_ok(scalar(@ret), '==', 1, '... only returned one value'); -ok(!defined $ret[0], '... the first value is undefined'); -ok(!defined $dbh->set_err(2, "bar"), '... $dbh->set_err returned undefiend'); # PrintError -ok(!defined $dbh->set_err(3, "baz"), '... $dbh->set_err returned undefiend'); # PrintError -ok(!defined $dbh->set_err(0, "warn"), '... $dbh->set_err returned undefiend'); # PrintError -is($dbh->errstr, "foo [err was 1 now 2]\nbar [err was 2 now 3]\nbaz\nwarn", - '... $dbh->errstr is as we expected'); -is($warn{failed}, 4, '... $warn{failed} is 4'); -is_deeply(\@handlewarn, [ 0, 1, 3 ], '... the @handlewarn array is (0, 1, 3)'); - -# ---- - -$dbh->set_err(undef, undef, undef); # clear error - -@ret = $dbh->set_err(1, "foo", "AA123", "method"); -cmp_ok(scalar @ret, '==', 1, '... only returned one value'); -ok(!defined $ret[0], '... the first value is undefined'); - -@ret = $dbh->set_err(1, "foo", "AA123", "method", "42"); -cmp_ok(scalar @ret, '==', 1, '... only returned one value'); -is($ret[0], "42", '... the first value is "42"'); - -@ret = $dbh->set_err(1, "foo", "return"); -cmp_ok(scalar @ret, '==', 0, '... returned no values'); - -# ---- - -$dbh->set_err(undef, undef, undef); # clear error - -@ret = $dbh->set_err("", "info", "override"); -cmp_ok(scalar @ret, '==', 1, '... only returned one value'); -ok(!defined $ret[0], '... the first value is undefined'); -cmp_ok($dbh->err, '==', 99, '... $dbh->err is 99'); -is($dbh->errstr, "errstr99", '... $dbh->errstr is as we expected'); -is($dbh->state, "OV123", '... $dbh->state is as we expected'); -$dbh->disconnect; - -# --- - -ping_keeps_err(); - -# --- - -reset_warn_counts(); - -SKIP: { - # we could test this with gofer is we used a different keep_err method other than STORE - # to trigger the set_err calls - skip 'set_err keep_error skipped for Gofer', 2 - if $using_dbd_gofer; - - $dbh->{examplep_set_err} = ""; # set information state - cmp_ok($warn{warning}, '==', 0, 'no extra warning generated for set_err("") in STORE'); - - $dbh->{examplep_set_err} = "0"; # set warning state - cmp_ok($warn{warning}, '==', 1, 'warning generated for set_err("0") in STORE'); -} - -# --- - -# ---- -done_testing(); - -1; -# end diff --git a/dbLifeLog/DBI-1.641/t/09trace.t b/dbLifeLog/DBI-1.641/t/09trace.t deleted file mode 100644 index 021bc5c..0000000 --- a/dbLifeLog/DBI-1.641/t/09trace.t +++ /dev/null @@ -1,137 +0,0 @@ -#!perl -w -# vim:sw=4:ts=8 - -use strict; - -use Test::More tests => 99; - -## ---------------------------------------------------------------------------- -## 09trace.t -## ---------------------------------------------------------------------------- -# -## ---------------------------------------------------------------------------- - -BEGIN { - $ENV{DBI_TRACE} = 0; # for PurePerl - ensure DBI_TRACE is in the env - use_ok( 'DBI' ); -} - -$|=1; - - -my $trace_file = "dbitrace$$.log"; - -1 while unlink $trace_file; -warn "Can't unlink existing $trace_file: $!" if -e $trace_file; - -my $orig_trace_level = DBI->trace; -DBI->trace(3, $trace_file); # enable trace before first driver load - -my $dbh = DBI->connect('dbi:ExampleP(AutoCommit=>1):', undef, undef); -die "Unable to connect to ExampleP driver: $DBI::errstr" unless $dbh; - -isa_ok($dbh, 'DBI::db'); - -$dbh->dump_handle("dump_handle test, write to log file", 2); - -DBI->trace(0, undef); # turn off and restore to STDERR - -SKIP: { - skip "cygwin has buffer flushing bug", 1 if ($^O =~ /cygwin/i); - ok( -s $trace_file, "trace file size = " . -s $trace_file); -} - -DBI->trace($orig_trace_level); # no way to restore previous outfile XXX - - -# Clean up when we're done. -END { $dbh->disconnect if $dbh; - 1 while unlink $trace_file; }; - -## ---------------------------------------------------------------------------- -# Check the database handle attributes. - -cmp_ok($dbh->{TraceLevel}, '==', $DBI::dbi_debug & 0xF, '... checking TraceLevel attribute'); - -1 while unlink $trace_file; - -$dbh->trace(0, $trace_file); -ok( -f $trace_file, '... trace file successfully created'); - -my @names = qw( - SQL - CON - ENC - DBD - TXN - foo bar baz boo bop -); -my %flag; -my $all_flags = 0; - -foreach my $name (@names) { - print "parse_trace_flag $name\n"; - ok( my $flag1 = $dbh->parse_trace_flag($name) ); - ok( my $flag2 = $dbh->parse_trace_flags($name) ); - is( $flag1, $flag2 ); - - $dbh->{TraceLevel} = $flag1; - is( $dbh->{TraceLevel}, $flag1 ); - - $dbh->{TraceLevel} = 0; - is( $dbh->{TraceLevel}, 0 ); - - $dbh->trace($flag1); - is $dbh->trace, $flag1; - is $dbh->{TraceLevel}, $flag1; - - $dbh->{TraceLevel} = $name; # set by name - $dbh->{TraceLevel} = undef; # check no change on undef - is( $dbh->{TraceLevel}, $flag1 ); - - $flag{$name} = $flag1; - $all_flags |= $flag1 - if defined $flag1; # reduce noise if there's a bug -} - -print "parse_trace_flag @names\n"; -ok(eq_set([ keys %flag ], [ @names ]), '...'); -$dbh->{TraceLevel} = 0; -$dbh->{TraceLevel} = join "|", @names; -is($dbh->{TraceLevel}, $all_flags, '...'); - -{ - print "inherit\n"; - my $sth = $dbh->prepare("select ctime, name from foo"); - isa_ok( $sth, 'DBI::st' ); - is( $sth->{TraceLevel}, $all_flags ); -} - -$dbh->{TraceLevel} = 0; -ok !$dbh->{TraceLevel}; -$dbh->{TraceLevel} = 'ALL'; -ok $dbh->{TraceLevel}; - -{ - print "test unknown parse_trace_flag\n"; - my $warn = 0; - local $SIG{__WARN__} = sub { - if ($_[0] =~ /unknown/i) { ++$warn; print "caught warn: ",@_ }else{ warn @_ } - }; - is $dbh->parse_trace_flag("nonesuch"), undef; - is $warn, 0; - is $dbh->parse_trace_flags("nonesuch"), 0; - is $warn, 1; - is $dbh->parse_trace_flags("nonesuch|SQL|nonesuch2"), $dbh->parse_trace_flag("SQL"); - is $warn, 2; -} - -$dbh->dump_handle("dump_handle test, write to log file", 2); - -$dbh->trace(0); -ok !$dbh->{TraceLevel}; -$dbh->trace(undef, "STDERR"); # close $trace_file -ok( -s $trace_file ); - -1; -# end diff --git a/dbLifeLog/DBI-1.641/t/10examp.t b/dbLifeLog/DBI-1.641/t/10examp.t deleted file mode 100644 index 3c8ca2e..0000000 --- a/dbLifeLog/DBI-1.641/t/10examp.t +++ /dev/null @@ -1,640 +0,0 @@ -#!perl -w - -use lib qw(blib/arch blib/lib); # needed since -T ignores PERL5LIB -use DBI qw(:sql_types); -use Config; -use Cwd; -use strict; -use Data::Dumper; - -$^W = 1; -$| = 1; - -require File::Basename; -require File::Spec; -require VMS::Filespec if $^O eq 'VMS'; - -use Test::More tests => 242; - -do { - # provide some protection against growth in size of '.' during the test - # which was probable cause of this failure - # http://www.nntp.perl.org/group/perl.cpan.testers/2009/09/msg5297317.html - my $tmpfile = "deleteme_$$"; - open my $fh, ">$tmpfile"; - close $fh; - unlink $tmpfile; -}; - -# "globals" -my ($r, $dbh); - -ok !eval { - $dbh = DBI->connect("dbi:NoneSuch:foobar", 1, 1, { RaiseError => 1, AutoCommit => 1 }); -}, 'connect should fail'; -like($@, qr/install_driver\(NoneSuch\) failed/, '... we should have an exception here'); -ok(!$dbh, '... $dbh2 should not be defined'); - -{ - my ($error, $tdbh); - eval { - $tdbh = DBI->connect('dbi:ExampleP:', '', []); - } or do { - $error= $@ || "Zombie Error"; - }; - like($error,qr/Usage:/,"connect with unblessed ref password should fail"); - ok(!defined($tdbh), '... $dbh should not be defined'); -} -{ - package Test::Secret; - use overload '""' => sub { return "" }; -} -{ - my ($error,$tdbh); - eval { - $tdbh = DBI->connect('dbi:ExampleP:', '', bless [], "Test::Secret"); - } or do { - $error= $@ || "Zombie Error"; - }; - ok(!$error,"connect with blessed ref password should not fail"); - ok(defined($tdbh), '... $dbh should be defined'); -} - -$dbh = DBI->connect('dbi:ExampleP:', '', ''); - -sub check_connect_cached { - # connect_cached - # ------------------------------------------ - # This test checks that connect_cached works - # and how it then relates to the CachedKids - # attribute for the driver. - - ok my $dbh_cached_1 = DBI->connect_cached('dbi:ExampleP:', '', '', { TraceLevel=>0, Executed => 0 }); - - ok my $dbh_cached_2 = DBI->connect_cached('dbi:ExampleP:', '', '', { TraceLevel=>0, Executed => 0 }); - - is($dbh_cached_1, $dbh_cached_2, '... these 2 handles are cached, so they are the same'); - - ok my $dbh_cached_3 = DBI->connect_cached('dbi:ExampleP:', '', '', { examplep_foo => 1 }); - - isnt($dbh_cached_3, $dbh_cached_2, '... this handle was created with different parameters, so it is not the same'); - - # check that cached_connect applies attributes to handles returned from the cache - # (The specific case of Executed is relevant to DBD::Gofer retry-on-error logic) - ok $dbh_cached_1->do("select * from ."); # set Executed flag - ok $dbh_cached_1->{Executed}, 'Executed should be true'; - ok my $dbh_cached_4 = DBI->connect_cached('dbi:ExampleP:', '', '', { TraceLevel=>0, Executed => 0 }); - is $dbh_cached_4, $dbh_cached_1, 'should return same handle'; - ok !$dbh_cached_4->{Executed}, 'Executed should be false because reset by connect attributes'; - - my $drh = $dbh->{Driver}; - isa_ok($drh, "DBI::dr"); - - my @cached_kids = values %{$drh->{CachedKids}}; - ok(eq_set(\@cached_kids, [ $dbh_cached_1, $dbh_cached_3 ]), '... these are our cached kids'); - - $drh->{CachedKids} = {}; - cmp_ok(scalar(keys %{$drh->{CachedKids}}), '==', 0, '... we have emptied out cache'); -} - -check_connect_cached(); - -$dbh->{AutoCommit} = 1; -$dbh->{PrintError} = 0; - -ok($dbh->{AutoCommit} == 1); -cmp_ok($dbh->{PrintError}, '==', 0, '... PrintError should be 0'); - -is($dbh->{FetchHashKeyName}, 'NAME', '... FetchHashKey is NAME'); - -# test access to driver-private attributes -like($dbh->{example_driver_path}, qr/DBD\/ExampleP\.pm$/, '... checking the example driver_path'); - -print "others\n"; -eval { $dbh->commit('dummy') }; -ok($@ =~ m/DBI commit: invalid number of arguments:/, $@) - unless $DBI::PurePerl && ok(1); - -ok($dbh->ping, "ping should return true"); - -# --- errors -my $cursor_e = $dbh->prepare("select unknown_field_name from ?"); -is($cursor_e, undef, "prepare should fail"); -ok($dbh->err, "sth->err should be true"); -ok($DBI::err, "DBI::err should be true"); -cmp_ok($DBI::err, 'eq', $dbh->err , "\$DBI::err should match \$dbh->err"); -like($DBI::errstr, qr/Unknown field names: unknown_field_name/, "\$DBI::errstr should contain error string"); -cmp_ok($DBI::errstr, 'eq', $dbh->errstr, "\$DBI::errstr should match \$dbh->errstr"); - -# --- func -ok($dbh->errstr eq $dbh->func('errstr')); - -my $std_sql = "select mode,size,name from ?"; -my $csr_a = $dbh->prepare($std_sql); -ok(ref $csr_a); -ok($csr_a->{NUM_OF_FIELDS} == 3); - -SKIP: { - skip "inner/outer handles not fully supported for DBI::PurePerl", 3 if $DBI::PurePerl; - ok(tied %{ $csr_a->{Database} }); # ie is 'outer' handle - ok($csr_a->{Database} eq $dbh, "$csr_a->{Database} ne $dbh") - unless $dbh->{mx_handle_list} && ok(1); # skip for Multiplex tests - ok(tied %{ $csr_a->{Database}->{Driver} }); # ie is 'outer' handle -} - -my $driver_name = $csr_a->{Database}->{Driver}->{Name}; -ok($driver_name eq 'ExampleP') - unless $ENV{DBI_AUTOPROXY} && ok(1); - -# --- FetchHashKeyName -$dbh->{FetchHashKeyName} = 'NAME_uc'; -my $csr_b = $dbh->prepare($std_sql); -$csr_b->execute('.'); -ok(ref $csr_b); - -ok($csr_a != $csr_b); - -ok("@{$csr_b->{NAME_lc}}" eq "mode size name"); # before NAME -ok("@{$csr_b->{NAME_uc}}" eq "MODE SIZE NAME"); -ok("@{$csr_b->{NAME}}" eq "mode size name"); -ok("@{$csr_b->{ $csr_b->{FetchHashKeyName} }}" eq "MODE SIZE NAME"); - -ok("@{[sort keys %{$csr_b->{NAME_lc_hash}}]}" eq "mode name size"); -ok("@{[sort values %{$csr_b->{NAME_lc_hash}}]}" eq "0 1 2"); -ok("@{[sort keys %{$csr_b->{NAME_uc_hash}}]}" eq "MODE NAME SIZE"); -ok("@{[sort values %{$csr_b->{NAME_uc_hash}}]}" eq "0 1 2"); - -do "./t/lib.pl"; - -# get a dir always readable on all platforms -#my $dir = getcwd() || cwd(); -#$dir = VMS::Filespec::unixify($dir) if $^O eq 'VMS'; -# untaint $dir -#$dir =~ m/(.*)/; $dir = $1 || die; -my $dir = test_dir (); - -# --- - -my($col0, $col1, $col2, $col3, $rows); -my(@row_a, @row_b); - -ok($csr_a->bind_columns(undef, \($col0, $col1, $col2)) ); -ok($csr_a->execute( $dir ), $DBI::errstr); - -@row_a = $csr_a->fetchrow_array; -ok(@row_a); - -# check bind_columns -is($row_a[0], $col0); -is($row_a[1], $col1); -is($row_a[2], $col2); - -ok( ! $csr_a->bind_columns(undef, \($col0, $col1)) ); -like $csr_a->errstr, '/bind_columns called with 2 values but 3 are needed/', 'errstr should contain error message'; -ok( ! $csr_a->bind_columns(undef, \($col0, $col1, $col2, $col3)) ); -like $csr_a->errstr, '/bind_columns called with 4 values but 3 are needed/', 'errstr should contain error message'; - -ok( $csr_a->bind_col(2, undef, { foo => 42 }) ); -ok ! eval { $csr_a->bind_col(0, undef) }; -like $@, '/bind_col: column 0 is not a valid column \(1..3\)/', 'errstr should contain error message'; -ok ! eval { $csr_a->bind_col(4, undef) }; -like $@, '/bind_col: column 4 is not a valid column \(1..3\)/', 'errstr should contain error message'; - -ok($csr_b->bind_param(1, $dir)); -ok($csr_b->execute()); -@row_b = @{ $csr_b->fetchrow_arrayref }; -ok(@row_b); - -ok("@row_a" eq "@row_b"); -@row_b = $csr_b->fetchrow_array; -ok("@row_a" ne "@row_b"); - -ok($csr_a->finish); -ok($csr_b->finish); - -$csr_a = undef; # force destruction of this cursor now -ok(1); - -print "fetchrow_hashref('NAME_uc')\n"; -ok($csr_b->execute()); -my $row_b = $csr_b->fetchrow_hashref('NAME_uc'); -ok($row_b); -ok($row_b->{MODE} == $row_a[0]); -ok($row_b->{SIZE} == $row_a[1]); -ok($row_b->{NAME} eq $row_a[2]); - -print "fetchrow_hashref('ParamValues')\n"; -ok($csr_b->execute()); -ok(!defined eval { $csr_b->fetchrow_hashref('ParamValues') } ); # PurePerl croaks - -print "FetchHashKeyName\n"; -ok($csr_b->execute()); -$row_b = $csr_b->fetchrow_hashref(); -ok($row_b); -ok(keys(%$row_b) == 3); -ok($row_b->{MODE} == $row_a[0]); -ok($row_b->{SIZE} == $row_a[1]); -ok($row_b->{NAME} eq $row_a[2]); - -print "fetchall_arrayref\n"; -ok($csr_b->execute()); -$r = $csr_b->fetchall_arrayref; -ok($r); -ok(@$r); -ok($r->[0]->[0] == $row_a[0]); -ok($r->[0]->[1] == $row_a[1]); -ok($r->[0]->[2] eq $row_a[2]); - -print "fetchall_arrayref array slice\n"; -ok($csr_b->execute()); -$r = $csr_b->fetchall_arrayref([2,1]); -ok($r && @$r); -ok($r->[0]->[1] == $row_a[1]); -ok($r->[0]->[0] eq $row_a[2]); - -print "fetchall_arrayref hash slice\n"; -ok($csr_b->execute()); -$r = $csr_b->fetchall_arrayref({ SizE=>1, nAMe=>1}); -ok($r && @$r); -ok($r->[0]->{SizE} == $row_a[1]); -ok($r->[0]->{nAMe} eq $row_a[2]); - -ok ! $csr_b->fetchall_arrayref({ NoneSuch=>1 }); -like $DBI::errstr, qr/Invalid column name/; - -print "fetchall_arrayref renaming hash slice\n"; -ok($csr_b->execute()); -$r = $csr_b->fetchall_arrayref(\{ 1 => "Koko", 2 => "Nimi"}); -ok($r && @$r); -ok($r->[0]->{Koko} == $row_a[1]); -ok($r->[0]->{Nimi} eq $row_a[2]); - -ok ! eval { $csr_b->fetchall_arrayref(\{ 9999 => "Koko" }) }; -like $@, qr/\Qis not a valid column/; - -print "fetchall_arrayref empty renaming hash slice\n"; -ok($csr_b->execute()); -$r = $csr_b->fetchall_arrayref(\{}); -ok($r && @$r); -ok(keys %{$r->[0]} == 0); - -ok($csr_b->execute()); -ok(!$csr_b->fetchall_arrayref(\[])); -like $DBI::errstr, qr/\Qfetchall_arrayref(REF) invalid/; - -print "fetchall_arrayref hash\n"; -ok($csr_b->execute()); -$r = $csr_b->fetchall_arrayref({}); -ok($r); -ok(keys %{$r->[0]} == 3); -ok("@{$r->[0]}{qw(MODE SIZE NAME)}" eq "@row_a", "'@{$r->[0]}{qw(MODE SIZE NAME)}' ne '@row_a'"); - -print "rows()\n"; # assumes previous fetch fetched all rows -$rows = $csr_b->rows; -ok($rows > 0, "row count $rows"); -ok($rows == @$r, "$rows vs ".@$r); -ok($rows == $DBI::rows, "$rows vs $DBI::rows"); - -print "fetchall_arrayref array slice and max rows\n"; -ok($csr_b->execute()); -$r = $csr_b->fetchall_arrayref([0], 1); -ok($r); -is_deeply($r, [[$row_a[0]]]); - -$r = $csr_b->fetchall_arrayref([], 1); -is @$r, 1, 'should fetch one row'; - -$r = $csr_b->fetchall_arrayref([], 99999); -ok @$r, 'should fetch all the remaining rows'; - -$r = $csr_b->fetchall_arrayref([], 99999); -is $r, undef, 'should return undef as there are no more rows'; - -# --- - -print "selectrow_array\n"; -@row_b = $dbh->selectrow_array($std_sql, undef, $dir); -ok(@row_b == 3); -ok("@row_b" eq "@row_a"); - -print "selectrow_hashref\n"; -$r = $dbh->selectrow_hashref($std_sql, undef, $dir); -ok(keys %$r == 3); -ok($r->{MODE} eq $row_a[0]); -ok($r->{SIZE} eq $row_a[1]); -ok($r->{NAME} eq $row_a[2]); - -print "selectall_arrayref\n"; -$r = $dbh->selectall_arrayref($std_sql, undef, $dir); -ok($r); -ok(@{$r->[0]} == 3); -ok("@{$r->[0]}" eq "@row_a"); -ok(@$r == $rows); - -print "selectall_arrayref Slice array slice\n"; -$r = $dbh->selectall_arrayref($std_sql, { Slice => [ 2, 0 ] }, $dir); -ok($r); -ok(@{$r->[0]} == 2); -ok("@{$r->[0]}" eq "$row_a[2] $row_a[0]", qq{"@{$r->[0]}" eq "$row_a[2] $row_a[0]"}); -ok(@$r == $rows); - -print "selectall_arrayref Columns array slice\n"; -$r = $dbh->selectall_arrayref($std_sql, { Columns => [ 3, 1 ] }, $dir); -ok($r); -ok(@{$r->[0]} == 2); -ok("@{$r->[0]}" eq "$row_a[2] $row_a[0]", qq{"@{$r->[0]}" eq "$row_a[2] $row_a[0]"}); -ok(@$r == $rows); - -print "selectall_arrayref hash slice\n"; -$r = $dbh->selectall_arrayref($std_sql, { Columns => { MoDe=>1, NamE=>1 } }, $dir); -ok($r); -ok(keys %{$r->[0]} == 2); -ok(exists $r->[0]{MoDe}); -ok(exists $r->[0]{NamE}); -ok($r->[0]{MoDe} eq $row_a[0]); -ok($r->[0]{NamE} eq $row_a[2]); -ok(@$r == $rows); - -print "selectall_array\n"; -$r = [ $dbh->selectall_array($std_sql, undef, $dir) ]; -ok($r); -ok(@{$r->[0]} == 3); -ok("@{$r->[0]}" eq "@row_a"); -ok(@$r == $rows); - -print "selectall_hashref\n"; -$r = $dbh->selectall_hashref($std_sql, 'NAME', undef, $dir); -ok($r, "selectall_hashref result"); -is(ref $r, 'HASH', "selectall_hashref HASH: ".ref $r); -is(scalar keys %$r, $rows); -is($r->{ $row_a[2] }{SIZE}, $row_a[1], qq{$r->{ $row_a[2] }{SIZE} eq $row_a[1]}); - -print "selectall_hashref by column number\n"; -$r = $dbh->selectall_hashref($std_sql, 3, undef, $dir); -ok($r); -ok($r->{ $row_a[2] }{SIZE} eq $row_a[1], qq{$r->{ $row_a[2] }{SIZE} eq $row_a[1]}); - -print "selectcol_arrayref\n"; -$r = $dbh->selectcol_arrayref($std_sql, undef, $dir); -ok($r); -ok(@$r == $rows); -ok($r->[0] eq $row_b[0]); - -print "selectcol_arrayref column slice\n"; -$r = $dbh->selectcol_arrayref($std_sql, { Columns => [3,2] }, $dir); -ok($r); -# warn Dumper([\@row_b, $r]); -ok(@$r == $rows * 2); -ok($r->[0] eq $row_b[2]); -ok($r->[1] eq $row_b[1]); - -# --- - -print "others...\n"; -my $csr_c; -$csr_c = $dbh->prepare("select unknown_field_name1 from ?"); -ok(!defined $csr_c); -ok($DBI::errstr =~ m/Unknown field names: unknown_field_name1/); - -print "RaiseError & PrintError & ShowErrorStatement\n"; -$dbh->{RaiseError} = 1; -ok($dbh->{RaiseError}); -$dbh->{ShowErrorStatement} = 1; -ok($dbh->{ShowErrorStatement}); - -my $error_sql = "select unknown_field_name2 from ?"; - -ok(! eval { $csr_c = $dbh->prepare($error_sql); 1; }); -#print "$@\n"; -like $@, qr/\Q$error_sql/; # ShowErrorStatement -like $@, qr/Unknown field names: unknown_field_name2/; - -# check attributes are inherited -my $se_sth1 = $dbh->prepare("select mode from ?"); -ok($se_sth1->{RaiseError}); -ok($se_sth1->{ShowErrorStatement}); - -# check ShowErrorStatement ParamValues are included and sorted -$se_sth1->bind_param($_, "val$_") for (1..11); -ok( !eval { $se_sth1->execute } ); -like $@, qr/\[for Statement "select mode from \?" with ParamValues: 1='val1', 2='val2', 3='val3', 4='val4', 5='val5', 6='val6', 7='val7', 8='val8', 9='val9', 10='val10', 11='val11'\]/; - -# this test relies on the fact that ShowErrorStatement is set above -TODO: { - local $TODO = "rt66127 not fixed yet"; - eval { - local $se_sth1->{PrintError} = 0; - $se_sth1->execute(1,2); - }; - unlike($@, qr/ParamValues:/, 'error string does not contain ParamValues'); - is($se_sth1->{ParamValues}, undef, 'ParamValues is empty') - or diag(Dumper($se_sth1->{ParamValues})); -}; -# check that $dbh->{Statement} tracks last _executed_ sth -$se_sth1 = $dbh->prepare("select mode from ?"); -ok($se_sth1->{Statement} eq "select mode from ?"); -ok($dbh->{Statement} eq "select mode from ?") or print "got: $dbh->{Statement}\n"; -my $se_sth2 = $dbh->prepare("select name from ?"); -ok($se_sth2->{Statement} eq "select name from ?"); -ok($dbh->{Statement} eq "select name from ?"); -$se_sth1->execute('.'); -ok($dbh->{Statement} eq "select mode from ?"); - -# show error param values -ok(! eval { $se_sth1->execute('first','second') }); # too many params -ok($@ =~ /\b1='first'/, $@); -ok($@ =~ /\b2='second'/, $@); - -$se_sth1->finish; -$se_sth2->finish; - -$dbh->{RaiseError} = 0; -ok(!$dbh->{RaiseError}); -$dbh->{ShowErrorStatement} = 0; -ok(!$dbh->{ShowErrorStatement}); - -{ - my @warn; - local($SIG{__WARN__}) = sub { push @warn, @_ }; - $dbh->{PrintError} = 1; - ok($dbh->{PrintError}); - ok(! $dbh->selectall_arrayref("select unknown_field_name3 from ?")); - ok("@warn" =~ m/Unknown field names: unknown_field_name3/); - $dbh->{PrintError} = 0; - ok(!$dbh->{PrintError}); -} - - -print "HandleError\n"; -my $HandleErrorReturn; -my $HandleError = sub { - my $msg = sprintf "HandleError: %s [h=%s, rv=%s, #=%d]", - $_[0],$_[1],(defined($_[2])?$_[2]:'undef'),scalar(@_); - die $msg if $HandleErrorReturn < 0; - print "$msg\n"; - $_[2] = 42 if $HandleErrorReturn == 2; - return $HandleErrorReturn; -}; - -$dbh->{HandleError} = $HandleError; -ok($dbh->{HandleError}); -ok($dbh->{HandleError} == $HandleError); - -$dbh->{RaiseError} = 1; -$dbh->{PrintError} = 0; -$error_sql = "select unknown_field_name2 from ?"; - -print "HandleError -> die\n"; -$HandleErrorReturn = -1; -ok(! eval { $csr_c = $dbh->prepare($error_sql); 1; }); -ok($@ =~ m/^HandleError:/, $@); - -print "HandleError -> 0 -> RaiseError\n"; -$HandleErrorReturn = 0; -ok(! eval { $csr_c = $dbh->prepare($error_sql); 1; }); -ok($@ =~ m/^DBD::(ExampleP|Multiplex|Gofer)::db prepare failed:/, $@); - -print "HandleError -> 1 -> return (original)undef\n"; -$HandleErrorReturn = 1; -$r = eval { $csr_c = $dbh->prepare($error_sql); }; -ok(!$@, $@); -ok(!defined($r), $r); - -print "HandleError -> 2 -> return (modified)42\n"; -$HandleErrorReturn = 2; -$r = eval { $csr_c = $dbh->prepare($error_sql); }; -ok(!$@, $@); -ok($r==42) unless $dbh->{mx_handle_list} && ok(1); # skip for Multiplex - -$dbh->{HandleError} = undef; -ok(!$dbh->{HandleError}); - -{ - # dump_results; - my $sth = $dbh->prepare($std_sql); - - isa_ok($sth, "DBI::st"); - - if (length(File::Spec->updir)) { - ok($sth->execute(File::Spec->updir)); - } else { - ok($sth->execute('../')); - } - - my $dump_file = "dumpcsr.tst.$$"; - SKIP: { - skip "# dump_results test skipped: unable to open $dump_file: $!\n", 4 - unless open(DUMP_RESULTS, ">$dump_file"); - ok($sth->dump_results("10", "\n", ",\t", \*DUMP_RESULTS)); - close(DUMP_RESULTS) or warn "close $dump_file: $!"; - ok(-s $dump_file > 0); - is( unlink( $dump_file ), 1, "Remove $dump_file" ); - ok( !-e $dump_file, "Actually gone" ); - } - -} - -note "table_info\n"; -# First generate a list of all subdirectories -$dir = File::Basename::dirname( $INC{"DBI.pm"} ); -my $dh; -ok(opendir($dh, $dir)); -my(%dirs, %unexpected, %missing); -while (defined(my $file = readdir($dh))) { - $dirs{$file} = 1 if -d File::Spec->catdir($dir,$file); -} -note( "Local $dir subdirs: @{[ keys %dirs ]}" ); -closedir($dh); -my $sth = $dbh->table_info($dir, undef, "%", "TABLE"); -ok($sth); -%unexpected = %dirs; -%missing = (); -while (my $ref = $sth->fetchrow_hashref()) { - if (exists($unexpected{$ref->{'TABLE_NAME'}})) { - delete $unexpected{$ref->{'TABLE_NAME'}}; - } else { - $missing{$ref->{'TABLE_NAME'}} = 1; - } -} -ok(keys %unexpected == 0) - or diag "Unexpected directories: ", join(",", keys %unexpected), "\n"; -ok(keys %missing == 0) - or diag "Missing directories: ", join(",", keys %missing), "\n"; - -note "tables\n"; -my @tables_expected = ( - q{"schema"."table"}, - q{"sch-ema"."table"}, - q{"schema"."ta-ble"}, - q{"sch ema"."table"}, - q{"schema"."ta ble"}, -); -my @tables = $dbh->tables(undef, undef, "%", "VIEW"); -ok(@tables == @tables_expected, "Table count mismatch".@tables_expected." vs ".@tables); -ok($tables[$_] eq $tables_expected[$_], "$tables[$_] ne $tables_expected[$_]") - foreach (0..$#tables_expected); - -for (my $i = 0; $i < 300; $i += 100) { - note "Testing the fake directories ($i).\n"; - ok($csr_a = $dbh->prepare("SELECT name, mode FROM long_list_$i")); - ok($csr_a->execute(), $DBI::errstr); - my $ary = $csr_a->fetchall_arrayref; - ok(@$ary == $i, @$ary." rows instead of $i"); - if ($i) { - my @n1 = map { $_->[0] } @$ary; - my @n2 = reverse map { "file$_" } 1..$i; - ok("@n1" eq "@n2", "'@n1' ne '@n2'"); - } - else { - ok(1); - } -} - - -SKIP: { - skip "test not tested with Multiplex", 1 - if $dbh->{mx_handle_list}; - note "Testing \$dbh->func().\n"; - my %tables; - %tables = map { $_ =~ /lib/ ? ($_, 1) : () } $dbh->tables(); - my @func_tables = $dbh->func('lib', 'examplep_tables'); - foreach my $t (@func_tables) { - defined(delete $tables{$t}) or print "Unexpected table: $t\n"; - } - is(keys(%tables), 0); -} - -{ - # some tests on special cases for the older tables call - # uses DBD::NullP and relies on 2 facts about DBD::NullP: - # 1) it has a get_info for for 29 - the quote chr - # 2) it has a table_info which returns some types and catalogs - my $dbhnp = DBI->connect('dbi:NullP:test'); - - # this special case should just return a list of table types - my @types = $dbhnp->tables('','','','%'); - ok(scalar(@types), 'we got some table types'); - my $defined = grep {defined($_)} @types; - is($defined, scalar(@types), 'all table types are defined'); - SKIP: { - skip "some table types were not defined", 1 if ($defined != scalar(@types)); - my $found_sep = grep {$_ =~ '\.'} @types; - is($found_sep, 0, 'no name separators in table types') or diag(Dumper(\@types)); - }; - - # this special case should just return a list of catalogs - my @catalogs = $dbhnp->tables('%', '', ''); - ok(scalar(@catalogs), 'we got some catalogs'); - SKIP: { - skip "no catalogs found", 1 if !scalar(@catalogs); - my $found_sep = grep {$_ =~ '\.'} @catalogs; - is($found_sep, 0, 'no name separators in catalogs') or diag(Dumper(\@catalogs)); - }; - $dbhnp->disconnect; -} - -$dbh->disconnect; -ok(!$dbh->{Active}); -ok(!$dbh->ping, "ping should return false after disconnect"); - -1; diff --git a/dbLifeLog/DBI-1.641/t/11fetch.t b/dbLifeLog/DBI-1.641/t/11fetch.t deleted file mode 100644 index 5f2fedc..0000000 --- a/dbLifeLog/DBI-1.641/t/11fetch.t +++ /dev/null @@ -1,124 +0,0 @@ -#!perl -w -# vim:ts=8:sw=4 -$|=1; - -use strict; - -use Test::More; -use DBI; -use Storable qw(dclone); -use Data::Dumper; - -$Data::Dumper::Indent = 1; -$Data::Dumper::Sortkeys = 1; -$Data::Dumper::Quotekeys = 0; - -plan tests => 24; - -my $dbh = DBI->connect("dbi:Sponge:foo","","", { - PrintError => 0, - RaiseError => 1, -}); - -my $source_rows = [ # data for DBD::Sponge to return via fetch - [ 41, "AAA", 9 ], - [ 41, "BBB", 9 ], - [ 42, "BBB", undef ], - [ 43, "ccc", 7 ], - [ 44, "DDD", 6 ], -]; - -sub go { - my $source = shift || $source_rows; - my $sth = $dbh->prepare("foo", { - rows => dclone($source), - NAME => [ qw(C1 C2 C3) ], - }); - ok($sth->execute(), $DBI::errstr); - return $sth; -} - -my($sth, $col0, $col1, $col2, $rows); - -# --- fetchrow_arrayref -# --- fetchrow_array -# etc etc - -# --- fetchall_hashref -my @fetchall_hashref_results = ( # single keys - C1 => { - 41 => { C1 => 41, C2 => 'BBB', C3 => 9 }, - 42 => { C1 => 42, C2 => 'BBB', C3 => undef }, - 43 => { C1 => 43, C2 => 'ccc', C3 => 7 }, - 44 => { C1 => 44, C2 => 'DDD', C3 => 6 } - }, - C2 => { - AAA => { C1 => 41, C2 => 'AAA', C3 => 9 }, - BBB => { C1 => 42, C2 => 'BBB', C3 => undef }, - DDD => { C1 => 44, C2 => 'DDD', C3 => 6 }, - ccc => { C1 => 43, C2 => 'ccc', C3 => 7 } - }, - [ 'C2' ] => { # single key within arrayref - AAA => { C1 => 41, C2 => 'AAA', C3 => 9 }, - BBB => { C1 => 42, C2 => 'BBB', C3 => undef }, - DDD => { C1 => 44, C2 => 'DDD', C3 => 6 }, - ccc => { C1 => 43, C2 => 'ccc', C3 => 7 } - }, -); -push @fetchall_hashref_results, ( # multiple keys - [ 'C1', 'C2' ] => { - '41' => { - AAA => { C1 => '41', C2 => 'AAA', C3 => 9 }, - BBB => { C1 => '41', C2 => 'BBB', C3 => 9 } - }, - '42' => { - BBB => { C1 => '42', C2 => 'BBB', C3 => undef } - }, - '43' => { - ccc => { C1 => '43', C2 => 'ccc', C3 => 7 } - }, - '44' => { - DDD => { C1 => '44', C2 => 'DDD', C3 => 6 } - } - }, -); - -my %dump; - -while (my $keyfield = shift @fetchall_hashref_results) { - my $expected = shift @fetchall_hashref_results; - my $k = (ref $keyfield) ? "[@$keyfield]" : $keyfield; - print "# fetchall_hashref($k)\n"; - ok($sth = go()); - my $result = $sth->fetchall_hashref($keyfield); - ok($result); - is_deeply($result, $expected); - # $dump{$k} = dclone $result; # just for adding tests -} - -warn Dumper \%dump if %dump; - -# test assignment to NUM_OF_FIELDS automatically alters the row buffer -$sth = go(); -my $row = $sth->fetchrow_arrayref; -is scalar @$row, 3; -is $sth->{NUM_OF_FIELDS}, 3; -is scalar @{ $sth->_get_fbav }, 3; -$sth->{NUM_OF_FIELDS} = 4; -is $sth->{NUM_OF_FIELDS}, 4; -is scalar @{ $sth->_get_fbav }, 4; -$sth->{NUM_OF_FIELDS} = 2; -is $sth->{NUM_OF_FIELDS}, 2; -is scalar @{ $sth->_get_fbav }, 2; - -$sth->finish; - - -if (0) { - my @perf = map { [ int($_/100), $_, $_ ] } 0..10000; - require Benchmark; - Benchmark::timethis(10, sub { go(\@perf)->fetchall_hashref([ 'C1','C2','C3' ]) }); -} - - -1; # end diff --git a/dbLifeLog/DBI-1.641/t/12quote.t b/dbLifeLog/DBI-1.641/t/12quote.t deleted file mode 100644 index c7dc948..0000000 --- a/dbLifeLog/DBI-1.641/t/12quote.t +++ /dev/null @@ -1,48 +0,0 @@ -#!perl -w - -use lib qw(blib/arch blib/lib); # needed since -T ignores PERL5LIB -use strict; - -use Test::More tests => 10; - -use DBI qw(:sql_types); -use Config; -use Cwd; - -$^W = 1; -$| = 1; - -my $dbh = DBI->connect('dbi:ExampleP:', '', ''); - -sub check_quote { - # checking quote - is($dbh->quote("quote's"), "'quote''s'", '... quoting strings with embedded single quotes'); - is($dbh->quote("42", SQL_VARCHAR), "'42'", '... quoting number as SQL_VARCHAR'); - is($dbh->quote("42", SQL_INTEGER), "42", '... quoting number as SQL_INTEGER'); - is($dbh->quote(undef), "NULL", '... quoting undef as NULL'); -} - -check_quote(); - -sub check_quote_identifier { - - is($dbh->quote_identifier('foo'), '"foo"', '... properly quotes foo as "foo"'); - is($dbh->quote_identifier('f"o'), '"f""o"', '... properly quotes f"o as "f""o"'); - is($dbh->quote_identifier('foo','bar'), '"foo"."bar"', '... properly quotes foo, bar as "foo"."bar"'); - is($dbh->quote_identifier(undef,undef,'bar'), '"bar"', '... properly quotes undef, undef, bar as "bar"'); - - is($dbh->quote_identifier('foo',undef,'bar'), '"foo"."bar"', '... properly quotes foo, undef, bar as "foo"."bar"'); - - SKIP: { - skip "Can't test alternate quote_identifier logic with DBI_AUTOPROXY", 1 - if $ENV{DBI_AUTOPROXY}; - my $qi = $dbh->{dbi_quote_identifier_cache} || die "test out of date with dbi internals?"; - $qi->[1] = '@'; # SQL_CATALOG_NAME_SEPARATOR - $qi->[2] = 2; # SQL_CATALOG_LOCATION - is($dbh->quote_identifier('foo',undef,'bar'), '"bar"@"foo"', '... now quotes it as "bar"@"foo" after flushing cache'); - } -} - -check_quote_identifier(); - -1; diff --git a/dbLifeLog/DBI-1.641/t/13taint.t b/dbLifeLog/DBI-1.641/t/13taint.t deleted file mode 100644 index 4fd1076..0000000 --- a/dbLifeLog/DBI-1.641/t/13taint.t +++ /dev/null @@ -1,133 +0,0 @@ -#!perl -wT - -use lib qw(blib/arch blib/lib); # needed since -T ignores PERL5LIB -use DBI qw(:sql_types); -use Config; -use Cwd; -use strict; - - -$^W = 1; -$| = 1; - -require VMS::Filespec if $^O eq 'VMS'; - -use Test::More; - -# Check Taint attribute works. This requires this test to be run -# manually with the -T flag: "perl -T -Mblib t/examp.t" -sub is_tainted { - my $foo; - return ! eval { ($foo=join('',@_)), kill 0; 1; }; -} -sub mk_tainted { - my $string = shift; - return substr($string.$^X, 0, length($string)); -} - -plan skip_all => "Taint attributes not supported with DBI::PurePerl" if $DBI::PurePerl; -plan skip_all => "Taint attribute tests require taint mode (perl -T)" unless is_tainted($^X); -plan skip_all => "Taint attribute tests not functional with DBI_AUTOPROXY" if $ENV{DBI_AUTOPROXY}; - -plan tests => 36; - -# get a dir always readable on all platforms -my $dir = getcwd() || cwd(); -$dir = VMS::Filespec::unixify($dir) if $^O eq 'VMS'; -$dir =~ m/(.*)/; $dir = $1 || die; # untaint $dir - -my ($r, $dbh); - -$dbh = DBI->connect('dbi:ExampleP:', '', '', { PrintError=>0, RaiseError=>1, Taint => 1 }); - -my $std_sql = "select mode,size,name from ?"; -my $csr_a = $dbh->prepare($std_sql); -ok(ref $csr_a); - -ok($dbh->{'Taint'}); -ok($dbh->{'TaintIn'} == 1); -ok($dbh->{'TaintOut'} == 1); - -$dbh->{'TaintOut'} = 0; -ok($dbh->{'Taint'} == 0); -ok($dbh->{'TaintIn'} == 1); -ok($dbh->{'TaintOut'} == 0); - -$dbh->{'Taint'} = 0; -ok($dbh->{'Taint'} == 0); -ok($dbh->{'TaintIn'} == 0); -ok($dbh->{'TaintOut'} == 0); - -$dbh->{'TaintIn'} = 1; -ok($dbh->{'Taint'} == 0); -ok($dbh->{'TaintIn'} == 1); -ok($dbh->{'TaintOut'} == 0); - -$dbh->{'TaintOut'} = 1; -ok($dbh->{'Taint'} == 1); -ok($dbh->{'TaintIn'} == 1); -ok($dbh->{'TaintOut'} == 1); - -$dbh->{'Taint'} = 0; -my $st; -eval { $st = $dbh->prepare($std_sql); }; -ok(ref $st); - -ok($st->{'Taint'} == 0); - -ok($st->execute( $dir ), 'should execute ok'); - -my @row = $st->fetchrow_array; -ok(@row); - -ok(!is_tainted($row[0])); -ok(!is_tainted($row[1])); -ok(!is_tainted($row[2])); - -print "TaintIn\n"; -$st->{'TaintIn'} = 1; - -@row = $st->fetchrow_array; -ok(@row); - -ok(!is_tainted($row[0])); -ok(!is_tainted($row[1])); -ok(!is_tainted($row[2])); - -print "TaintOut\n"; -$st->{'TaintOut'} = 1; - -@row = $st->fetchrow_array; -ok(@row); - -ok(is_tainted($row[0])); -ok(is_tainted($row[1])); -ok(is_tainted($row[2])); - -$st->finish; - -my $tainted_sql = mk_tainted($std_sql); -my $tainted_dot = mk_tainted('.'); - -$dbh->{'Taint'} = $csr_a->{'Taint'} = 1; -eval { $dbh->prepare($tainted_sql); 1; }; -ok($@ =~ /Insecure dependency/, $@); -eval { $csr_a->execute($tainted_dot); 1; }; -ok($@ =~ /Insecure dependency/, $@); -undef $@; - -$dbh->{'TaintIn'} = $csr_a->{'TaintIn'} = 0; - -eval { $dbh->prepare($tainted_sql); 1; }; -ok(!$@, $@); -eval { $csr_a->execute($tainted_dot); 1; }; -ok(!$@, $@); - -$csr_a->{Taint} = 0; -ok($csr_a->{Taint} == 0); - -$csr_a->finish; - -$dbh->disconnect; - -1; diff --git a/dbLifeLog/DBI-1.641/t/14utf8.t b/dbLifeLog/DBI-1.641/t/14utf8.t deleted file mode 100644 index c141e38..0000000 --- a/dbLifeLog/DBI-1.641/t/14utf8.t +++ /dev/null @@ -1,76 +0,0 @@ -#!perl -w -# vim:ts=8:sw=4 -$|=1; - -use Test::More; -use DBI; - -plan skip_all => "Requires perl 5.8" - unless $] >= 5.008; - -eval { - require Storable; - import Storable qw(dclone); - require Encode; - import Encode qw(_utf8_on _utf8_off is_utf8); -}; - -plan skip_all => "Unable to load required module ($@)" - unless defined &_utf8_on; - -plan tests => 16; - -$dbh = DBI->connect("dbi:Sponge:foo","","", { - PrintError => 0, - RaiseError => 1, -}); - -my $source_rows = [ # data for DBD::Sponge to return via fetch - [ 41, "AAA", 9 ], - [ 42, "BB", undef ], - [ 43, undef, 7 ], - [ 44, "DDD", 6 ], -]; - -my($sth, $col0, $col1, $col2, $rows); - -# set utf8 on one of the columns so we can check it carries through into the -# keys of fetchrow_hashref -my @col_names = qw(Col1 Col2 Col3); -_utf8_on($col_names[1]); -ok is_utf8($col_names[1]); -ok !is_utf8($col_names[0]); - -$sth = $dbh->prepare("foo", { - rows => dclone($source_rows), - NAME => \@col_names, -}); - -ok($sth->bind_columns(\($col0, $col1, $col2)) ); -ok($sth->execute(), $DBI::errstr); - -ok $sth->fetch; -cmp_ok $col1, 'eq', "AAA"; -ok !is_utf8($col1); - -# force utf8 flag on -_utf8_on($col1); -ok is_utf8($col1); - -ok $sth->fetch; -cmp_ok $col1, 'eq', "BB"; -# XXX sadly this test doesn't detect the problem when using DBD::Sponge -# because DBD::Sponge uses $sth->_set_fbav (correctly) and that uses -# sv_setsv which doesn't have the utf8 persistence that sv_setpv does. -ok !is_utf8($col1); # utf8 flag should have been reset - -ok $sth->fetch; -ok !defined $col1; # null -ok !is_utf8($col1); # utf8 flag should have been reset - -ok my $hash = $sth->fetchrow_hashref; -ok 1 == grep { is_utf8($_) } keys %$hash; - -$sth->finish; - -# end diff --git a/dbLifeLog/DBI-1.641/t/15array.t b/dbLifeLog/DBI-1.641/t/15array.t deleted file mode 100644 index 2b91001..0000000 --- a/dbLifeLog/DBI-1.641/t/15array.t +++ /dev/null @@ -1,254 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use Test::More tests => 55; - -## ---------------------------------------------------------------------------- -## 15array.t -## ---------------------------------------------------------------------------- -# -## ---------------------------------------------------------------------------- - -BEGIN { - use_ok('DBI'); -} - -# create a database handle -my $dbh = DBI->connect("dbi:Sponge:dummy", '', '', { - RaiseError => 1, - ShowErrorStatement => 1, - AutoCommit => 1 -}); - -# check that our db handle is good -isa_ok($dbh, "DBI::db"); - -my $rv; -my $rows = []; -my $tuple_status = []; -my $dumped; - -my $sth = $dbh->prepare("insert", { - rows => $rows, # where to 'insert' (push) the rows - NUM_OF_PARAMS => 4, - execute_hook => sub { # DBD::Sponge hook to make certain data trigger an error for that row - local $^W; - return $_[0]->set_err(1,"errmsg") if grep { $_ and $_ eq "B" } @_; - return 1; - } - }); - -isa_ok($sth, "DBI::st"); - -cmp_ok(scalar @{$rows}, '==', 0, '... we should have 0 rows'); - -# ----------------------------------------------- - -ok(! eval { - local $sth->{PrintError} = 0; - $sth->execute_array( - { - ArrayTupleStatus => $tuple_status - }, - [ 1, 2, 3 ], # array of integers - 42, # scalar 42 treated as array of 42's - undef, # scalar undef treated as array of undef's - [ qw(A B C) ], # array of strings - ) }, - '... execute_array should return false' -); -ok $@, 'execute_array failure with RaiseError should have died'; -like $sth->errstr, '/executing 3 generated 1 errors/'; - -cmp_ok(scalar @{$rows}, '==', 2, '... we should have 2 rows'); -cmp_ok(scalar @{$tuple_status}, '==', 3, '... we should have 3 tuple_status'); - -ok(eq_array( - $rows, - [ [1, 42, undef, 'A'], [3, 42, undef, 'C'] ] - ), - '... our rows are as expected'); - -ok(eq_array( - $tuple_status, - [1, [1, 'errmsg', 'S1000'], 1] - ), - '... our tuple_status is as expected'); - -# ----------------------------------------------- -# --- change one param and re-execute - -@$rows = (); -ok( $sth->bind_param_array(4, [ qw(a b c) ]), '... bind_param_array should return true'); -ok( $sth->execute_array({ ArrayTupleStatus => $tuple_status }), '... execute_array should return true'); - -cmp_ok(scalar @{$rows}, '==', 3, '... we should have 3 rows'); -cmp_ok(scalar @{$tuple_status}, '==', 3, '... we should have 3 tuple_status'); - -ok(eq_array( - $rows, - [ [1, 42, undef, 'a'], [2, 42, undef, 'b'], [3, 42, undef, 'c'] ] - ), - '... our rows are as expected'); - -ok(eq_array( - $tuple_status, - [1, 1, 1] - ), - '... our tuple_status is as expected'); - -# ----------------------------------------------- -# --- call execute_array in array context to get executed AND affected -@$rows = (); -my ($executed, $affected) = $sth->execute_array({ ArrayTupleStatus => $tuple_status }); -ok($executed, '... execute_array should return true'); -cmp_ok($executed, '==', 3, '... we should have executed 3 rows'); -cmp_ok($affected, '==', 3, '... we should have affected 3 rows'); - -# ----------------------------------------------- -# --- with no values for bind params, should execute zero times - -@$rows = (); -$rv = $sth->execute_array( { ArrayTupleStatus => $tuple_status }, [], [], [], []); -ok($rv, '... execute_array should return true'); -ok(!($rv+0), '... execute_array should return 0 (but true)'); - -cmp_ok(scalar @{$rows}, '==', 0, '... we should have 0 rows'); -cmp_ok(scalar @{$tuple_status}, '==', 0,'... we should have 0 tuple_status'); - -# ----------------------------------------------- -# --- with only scalar values for bind params, should execute just once - -@$rows = (); -$rv = $sth->execute_array( { ArrayTupleStatus => $tuple_status }, 5, 6, 7, 8); -cmp_ok($rv, '==', 1, '... execute_array should return 1'); - -cmp_ok(scalar @{$rows}, '==', 1, '... we should have 1 rows'); -ok(eq_array( $rows, [ [5,6,7,8] ]), '... our rows are as expected'); -cmp_ok(scalar @{$tuple_status}, '==', 1,'... we should have 1 tuple_status'); -ok(eq_array( $tuple_status, [1]), '... our tuple_status is as expected'); - -# ----------------------------------------------- -# --- with mix of scalar values and arrays only arrays control tuples - -@$rows = (); -$rv = $sth->execute_array( { ArrayTupleStatus => $tuple_status }, 5, [], 7, 8); -cmp_ok($rv, '==', 0, '... execute_array should return 0'); - -cmp_ok(scalar @{$rows}, '==', 0, '... we should have 0 rows'); -cmp_ok(scalar @{$tuple_status}, '==', 0,'... we should have 0 tuple_status'); - -# ----------------------------------------------- -# --- catch 'undefined value' bug with zero bind values - -@$rows = (); -my $sth_other = $dbh->prepare("insert", { - rows => $rows, # where to 'insert' (push) the rows - NUM_OF_PARAMS => 1, -}); - -isa_ok($sth_other, "DBI::st"); - -$rv = $sth_other->execute_array( {}, [] ); -ok($rv, '... execute_array should return true'); -ok(!($rv+0), '... execute_array should return 0 (but true)'); -# no ArrayTupleStatus - -cmp_ok(scalar @{$rows}, '==', 0, '... we should have 0 rows'); - -# ----------------------------------------------- -# --- ArrayTupleFetch code-ref tests --- - -my $index = 0; - -my $fetchrow = sub { # generate 5 rows of two integer values - return if $index >= 2; - $index +=1; - # There doesn't seem any reliable way to force $index to be - # treated as a string (and so dumped as such). We just have to - # make the test case allow either 1 or '1'. - return [ $index, 'a','b','c' ]; -}; - -@$rows = (); -ok( $sth->execute_array({ - ArrayTupleFetch => $fetchrow, - ArrayTupleStatus => $tuple_status - }), '... execute_array should return true'); - -cmp_ok(scalar @{$rows}, '==', 2, '... we should have 2 rows'); -cmp_ok(scalar @{$tuple_status}, '==', 2, '... we should have 2 tuple_status'); - -ok(eq_array( - $rows, - [ [1, 'a', 'b', 'c'], [2, 'a', 'b', 'c'] ] - ), - '... rows should match' -); - -ok(eq_array( - $tuple_status, - [1, 1] - ), - '... tuple_status should match' -); - -# ----------------------------------------------- -# --- ArrayTupleFetch sth tests --- - -my $fetch_sth = $dbh->prepare("foo", { - rows => [ map { [ $_,'x','y','z' ] } 7..9 ], - NUM_OF_FIELDS => 4 - }); - -isa_ok($fetch_sth, "DBI::st"); - -$fetch_sth->execute(); - -@$rows = (); - -ok( $sth->execute_array({ - ArrayTupleFetch => $fetch_sth, - ArrayTupleStatus => $tuple_status, - }), '... execute_array should return true'); - -cmp_ok(scalar @{$rows}, '==', 3, '... we should have 3 rows'); -cmp_ok(scalar @{$tuple_status}, '==', 3, '... we should have 3 tuple_status'); - -ok(eq_array( - $rows, - [ [7, 'x', 'y', 'z'], [8, 'x', 'y', 'z'], [9, 'x', 'y', 'z'] ] - ), - '... rows should match' -); - -ok(eq_array( - $tuple_status, - [1, 1, 1] - ), - '... tuple status should match' -); - -# ----------------------------------------------- -# --- error detection tests --- - -$sth->{RaiseError} = 0; -$sth->{PrintError} = 0; - -ok(!defined $sth->execute_array( { ArrayTupleStatus => $tuple_status }, [1],[2]), '... execute_array should return undef'); -is($sth->errstr, '2 bind values supplied but 4 expected', '... errstr is as expected'); - -ok(!defined $sth->execute_array( { ArrayTupleStatus => { } }, [ 1, 2, 3 ]), '... execute_array should return undef'); -is( $sth->errstr, 'ArrayTupleStatus attribute must be an arrayref', '... errstr is as expected'); - -ok(!defined $sth->execute_array( { ArrayTupleStatus => $tuple_status }, 1,{},3,4), '... execute_array should return undef'); -is( $sth->errstr, 'Value for parameter 2 must be a scalar or an arrayref, not a HASH', '... errstr is as expected'); - -ok(!defined $sth->bind_param_array(":foo", [ qw(a b c) ]), '... bind_param_array should return undef'); -is( $sth->errstr, "Can't use named placeholder ':foo' for non-driver supported bind_param_array", '... errstr is as expected'); - -$dbh->disconnect; - -1; diff --git a/dbLifeLog/DBI-1.641/t/16destroy.t b/dbLifeLog/DBI-1.641/t/16destroy.t deleted file mode 100644 index fa856d2..0000000 --- a/dbLifeLog/DBI-1.641/t/16destroy.t +++ /dev/null @@ -1,148 +0,0 @@ -#!perl -w - -use strict; - -use Test::More tests => 20; # use explicit plan to avoid race hazard - -BEGIN{ use_ok( 'DBI' ) } - -my $expect_active; - -## main Test Driver Package -{ - package DBD::Test; - - use strict; - use warnings; - - my $drh = undef; - - sub driver { - return $drh if $drh; - my ($class, $attr) = @_; - $class = "${class}::dr"; - ($drh) = DBI::_new_drh($class, { - Name => 'Test', - Version => '1.0', - }, 77 ); - return $drh; - } - - sub CLONE { undef $drh } -} - -## Test Driver -{ - package DBD::Test::dr; - - use warnings; - use Test::More; - - sub connect { # normally overridden, but a handy default - my($drh, $dbname, $user, $auth, $attrs)= @_; - my ($outer, $dbh) = DBI::_new_dbh($drh); - $dbh->STORE(Active => 1); - $dbh->STORE(AutoCommit => 1); - $dbh->STORE( $_ => $attrs->{$_}) for keys %$attrs; - return $outer; - } - - $DBD::Test::dr::imp_data_size = 0; - cmp_ok($DBD::Test::dr::imp_data_size, '==', 0, '... check DBD::Test::dr::imp_data_size to avoid typo'); -} - -## Test db package -{ - package DBD::Test::db; - - use strict; - use warnings; - use Test::More; - - $DBD::Test::db::imp_data_size = 0; - cmp_ok($DBD::Test::db::imp_data_size, '==', 0, '... check DBD::Test::db::imp_data_size to avoid typo'); - - sub STORE { - my ($dbh, $attrib, $value) = @_; - # would normally validate and only store known attributes - # else pass up to DBI to handle - if ($attrib eq 'AutoCommit') { - # convert AutoCommit values to magic ones to let DBI - # know that the driver has 'handled' the AutoCommit attribute - $value = ($value) ? -901 : -900; - } - return $dbh->{$attrib} = $value if $attrib =~ /^examplep_/; - return $dbh->SUPER::STORE($attrib, $value); - } - - sub DESTROY { - if ($expect_active < 0) { # inside child - my $self = shift; - exit ($self->FETCH('Active') || 0) unless $^O eq 'MSWin32'; - - # On Win32, the forked child is actually a thread. So don't exit, - # and report failure directly. - fail 'Child should be inactive on DESTROY' if $self->FETCH('Active'); - } else { - return $expect_active - ? ok( shift->FETCH('Active'), 'Should be active in DESTROY') - : ok( !shift->FETCH('Active'), 'Should not be active in DESTROY'); - } - } -} - -my $dsn = 'dbi:ExampleP:dummy'; - -$INC{'DBD/Test.pm'} = 'dummy'; # required to fool DBI->install_driver() -ok my $drh = DBI->install_driver('Test'), 'Install test driver'; - -NOSETTING: { - # Try defaults. - ok my $dbh = $drh->connect, 'Connect to test driver'; - ok $dbh->{Active}, 'Should start active'; - $expect_active = 1; -} - -IAD: { - # Try InactiveDestroy. - ok my $dbh = $drh->connect($dsn, '', '', { InactiveDestroy => 1 }), - 'Create with ActiveDestroy'; - ok $dbh->{InactiveDestroy}, 'InactiveDestroy should be set'; - ok $dbh->{Active}, 'Should start active'; - $expect_active = 0; -} - -AIAD: { - # Try AutoInactiveDestroy. - ok my $dbh = $drh->connect($dsn, '', '', { AutoInactiveDestroy => 1 }), - 'Create with AutoInactiveDestroy'; - ok $dbh->{AutoInactiveDestroy}, 'InactiveDestroy should be set'; - ok $dbh->{Active}, 'Should start active'; - $expect_active = 1; -} - -FORK: { - # Try AutoInactiveDestroy and fork. - ok my $dbh = $drh->connect($dsn, '', '', { AutoInactiveDestroy => 1 }), - 'Create with AutoInactiveDestroy again'; - ok $dbh->{AutoInactiveDestroy}, 'InactiveDestroy should be set'; - ok $dbh->{Active}, 'Should start active'; - - my $pid = eval { fork() }; - if (not defined $pid) { - chomp $@; - my $msg = "AutoInactiveDestroy destroy test skipped"; - diag "$msg because $@\n"; - pass $msg; # in lieu of the child status test - } - elsif ($pid) { - # parent. - $expect_active = 1; - wait; - ok $? == 0, 'Child should be inactive on DESTROY'; - } else { - # child. - $expect_active = -1; - } -} - diff --git a/dbLifeLog/DBI-1.641/t/19fhtrace.t b/dbLifeLog/DBI-1.641/t/19fhtrace.t deleted file mode 100644 index 8070e4b..0000000 --- a/dbLifeLog/DBI-1.641/t/19fhtrace.t +++ /dev/null @@ -1,306 +0,0 @@ -#!perl -w -# vim:sw=4:ts=8 - -use strict; - -use Test::More tests => 27; - -## ---------------------------------------------------------------------------- -## 09trace.t -## ---------------------------------------------------------------------------- -# -## ---------------------------------------------------------------------------- - -BEGIN { - use_ok( 'DBI' ); -} - -$|=1; - -our $fancylogfn = "fancylog$$.log"; -our $trace_file = "dbitrace$$.log"; - -# Clean up when we're done. -END { 1 while unlink $fancylogfn; - 1 while unlink $trace_file; }; - -package PerlIO::via::TraceDBI; - -our $logline; - -sub OPEN { - return 1; -} - -sub PUSHED -{ - my ($class,$mode,$fh) = @_; - # When writing we buffer the data - my $buf = ''; - return bless \$buf,$class; -} - -sub FILL -{ - my ($obj,$fh) = @_; - return $logline; -} - -sub READLINE -{ - my ($obj,$fh) = @_; - return $logline; -} - -sub WRITE -{ - my ($obj,$buf,$fh) = @_; -# print "\n*** WRITING $buf\n"; - $logline = $buf; - return length($buf); -} - -sub FLUSH -{ - my ($obj,$fh) = @_; - return 0; -} - -sub CLOSE { -# print "\n*** CLOSING!!!\n"; - $logline = "**** CERRADO! ***"; - return -1; -} - -1; - -package PerlIO::via::MyFancyLogLayer; - -sub OPEN { - my ($obj, $path, $mode, $fh) = @_; - $$obj = $path; - return 1; -} - -sub PUSHED -{ - my ($class,$mode,$fh) = @_; - # When writing we buffer the data - my $logger; - return bless \$logger,$class; -} - -sub WRITE -{ - my ($obj,$buf,$fh) = @_; - $$obj->log($buf); - return length($buf); -} - -sub FLUSH -{ - my ($obj,$fh) = @_; - return 0; -} - -sub CLOSE { - my $self = shift; - $$self->close(); - return 0; -} - -1; - -package MyFancyLogger; - -use Symbol qw(gensym); - -sub new -{ - my $self = {}; - my $fh = gensym(); - open $fh, '>', $fancylogfn; - $self->{_fh} = $fh; - $self->{_buf} = ''; - return bless $self, shift; -} - -sub log -{ - my $self = shift; - my $fh = $self->{_fh}; - $self->{_buf} .= shift; - print $fh "At ", scalar localtime(), ':', $self->{_buf}, "\n" and - $self->{_buf} = '' - if $self->{_buf}=~tr/\n//; -} - -sub close { - my $self = shift; - return unless exists $self->{_fh}; - my $fh = $self->{_fh}; - print $fh "At ", scalar localtime(), ':', $self->{_buf}, "\n" and - $self->{_buf} = '' - if $self->{_buf}; - close $fh; - delete $self->{_fh}; -} - -1; - -package main; - -## ---------------------------------------------------------------------------- -# Connect to the example driver. - -my $dbh = DBI->connect('dbi:ExampleP:dummy', '', '', - { PrintError => 0, - RaiseError => 1, - PrintWarn => 1, - }); -isa_ok( $dbh, 'DBI::db' ); - -# Clean up when we're done. -END { $dbh->disconnect if $dbh }; - -## ---------------------------------------------------------------------------- -# Check the database handle attributes. - -cmp_ok($dbh->{TraceLevel}, '==', $DBI::dbi_debug & 0xF, '... checking TraceLevel attribute'); - -1 while unlink $trace_file; - -my $tracefd; -## ---------------------------------------------------------------------------- -# First use regular filehandle -open $tracefd, '>>', $trace_file; - -my $oldfd = select($tracefd); -$| = 1; -select $oldfd; - -ok(-f $trace_file, '... regular fh: trace file successfully created'); - -$dbh->trace(2, $tracefd); -ok( 1, '... regular fh: filehandle successfully set'); - -# -# read current size of file -# -my $filesz = (stat $tracefd)[7]; -$dbh->trace_msg("First logline\n", 1); -# -# read new file size and verify its different -# -my $newfsz = (stat $tracefd)[7]; -SKIP: { - skip 'on VMS autoflush using select does not work', 1 if $^O eq 'VMS'; - ok(($filesz != $newfsz), '... regular fh: trace_msg'); -} - -$dbh->trace(undef, "STDOUT"); # close $trace_file -ok(-f $trace_file, '... regular fh: file successfully changed'); - -$filesz = (stat $tracefd)[7]; -$dbh->trace_msg("Next logline\n"); -# -# read new file size and verify its same -# -$newfsz = (stat $tracefd)[7]; -ok(($filesz == $newfsz), '... regular fh: trace_msg after changing trace output'); - -#1 while unlink $trace_file; - -$dbh->trace(0); # disable trace - -{ # Open trace to glob. started failing in perl-5.10 - my $tf = "foo.log.$$"; - 1 while unlink $tf; - 1 while unlink "*main::FOO"; - 1 while unlink "*main::STDERR"; - is (-f $tf, undef, "Tracefile removed"); - ok (open (FOO, ">", $tf), "Tracefile FOO opened"); - ok (-f $tf, "Tracefile created"); - DBI->trace (1, *FOO); - is (-f "*main::FOO", undef, "Regression test"); - DBI->trace_msg ("foo\n", 1); - DBI->trace (0, *STDERR); - close FOO; - open my $fh, "<", $tf; - is ((<$fh>)[-1], "foo\n", "Traced message"); - close $fh; - is (-f "*main::STDERR", undef, "Regression test"); - 1 while unlink $tf; - } - -SKIP: { - eval { require 5.008; }; - skip "Layered I/O not available in Perl $^V", 13 - if $@; -## ---------------------------------------------------------------------------- -# Then use layered filehandle -# -open TRACEFD, '+>:via(TraceDBI)', 'layeredtrace.out'; -print TRACEFD "*** Test our layer\n"; -my $result = ; -is $result, "*** Test our layer\n", "... layered fh: file is layered: $result\n"; - -$dbh->trace(1, \*TRACEFD); -ok( 1, '... layered fh: filehandle successfully set'); - -$dbh->trace_msg("Layered logline\n", 1); - -$result = ; -is $result, "Layered logline\n", "... layered fh: trace_msg: $result\n"; - -$dbh->trace(1, "STDOUT"); # close $trace_file -$result = ; -is $result, "Layered logline\n", "... layered fh: close doesn't close: $result\n"; - -$dbh->trace_msg("Next logline\n", 1); -$result = ; -is $result, "Layered logline\n", "... layered fh: trace_msg after change trace output: $result\n"; - -## ---------------------------------------------------------------------------- -# Then use scalar filehandle -# -my $tracestr; -open TRACEFD, '+>:scalar', \$tracestr; -print TRACEFD "*** Test our layer\n"; -ok 1, "... scalar trace: file is layered: $tracestr\n"; - -$dbh->trace(1, \*TRACEFD); -ok 1, '... scalar trace: filehandle successfully set'; - -$dbh->trace_msg("Layered logline\n", 1); -ok 1, "... scalar trace: $tracestr\n"; - -$dbh->trace(1, "STDOUT"); # close $trace_file -ok 1, "... scalar trace: close doesn't close: $tracestr\n"; - -$dbh->trace_msg("Next logline\n", 1); -ok 1, "... scalar trace: after change trace output: $tracestr\n"; - -## ---------------------------------------------------------------------------- -# Then use fancy logger -# -open my $fh, '>:via(MyFancyLogLayer)', MyFancyLogger->new(); - -$dbh->trace('SQL', $fh); - -$dbh->trace_msg("Layered logline\n", 1); -ok 1, "... logger: trace_msg\n"; - -$dbh->trace(1, "STDOUT"); # close $trace_file -ok 1, "... logger: close doesn't close\n"; - -$dbh->trace_msg("Next logline\n", 1); -ok 1, "... logger: trace_msg after change trace output\n"; - -close $fh; - -} - -1; - -# end diff --git a/dbLifeLog/DBI-1.641/t/20meta.t b/dbLifeLog/DBI-1.641/t/20meta.t deleted file mode 100644 index a8d609e..0000000 --- a/dbLifeLog/DBI-1.641/t/20meta.t +++ /dev/null @@ -1,32 +0,0 @@ -#!perl -w - -use strict; -use Test::More tests => 8; - -$|=1; -$^W=1; - -BEGIN { use_ok( 'DBI', ':sql_types' ) } -BEGIN { use_ok( 'DBI::DBD::Metadata' ) } # just to check for syntax errors etc - -my $dbh = DBI->connect("dbi:ExampleP:.","","", { FetchHashKeyName => 'NAME_lc' }) - or die "Unable to connect to ExampleP driver: $DBI::errstr"; - -isa_ok($dbh, 'DBI::db'); -#$dbh->trace(3); - -#use Data::Dumper; -#print Dumper($dbh->type_info_all); -#print Dumper($dbh->type_info); -#print Dumper($dbh->type_info(DBI::SQL_INTEGER)); - -my @ti = $dbh->type_info; -ok(@ti>0); - -is($dbh->type_info(SQL_INTEGER)->{DATA_TYPE}, SQL_INTEGER); -is($dbh->type_info(SQL_INTEGER)->{TYPE_NAME}, 'INTEGER'); - -is($dbh->type_info(SQL_VARCHAR)->{DATA_TYPE}, SQL_VARCHAR); -is($dbh->type_info(SQL_VARCHAR)->{TYPE_NAME}, 'VARCHAR'); - -1; diff --git a/dbLifeLog/DBI-1.641/t/30subclass.t b/dbLifeLog/DBI-1.641/t/30subclass.t deleted file mode 100644 index 9daae91..0000000 --- a/dbLifeLog/DBI-1.641/t/30subclass.t +++ /dev/null @@ -1,182 +0,0 @@ -#!perl -w - -use strict; - -$|=1; -$^W=1; - -my $calls = 0; -my %my_methods; - - -# ================================================= -# Example code for sub classing the DBI. -# -# Note that the extra ::db and ::st classes must be set up -# as sub classes of the corresponding DBI classes. -# -# This whole mechanism is new and experimental - it may change! - -package MyDBI; -@MyDBI::ISA = qw(DBI); - -# the MyDBI::dr::connect method is NOT called! -# you can either override MyDBI::connect() -# or use MyDBI::db::connected() - -package MyDBI::db; -@MyDBI::db::ISA = qw(DBI::db); - -sub prepare { - my($dbh, @args) = @_; - ++$my_methods{prepare}; - ++$calls; - my $sth = $dbh->SUPER::prepare(@args); - return $sth; -} - - -package MyDBI::st; -@MyDBI::st::ISA = qw(DBI::st); - -sub fetch { - my($sth, @args) = @_; - ++$my_methods{fetch}; - ++$calls; - # this is just to trigger (re)STORE on exit to test that the STORE - # doesn't clear any erro condition - local $sth->{Taint} = 0; - my $row = $sth->SUPER::fetch(@args); - if ($row) { - # modify fetched data as an example - $row->[1] = lc($row->[1]); - - # also demonstrate calling set_err() - return $sth->set_err(1,"Don't be so negative",undef,"fetch") - if $row->[0] < 0; - # ... and providing alternate results - # (although typically would trap and hide and error from SUPER::fetch) - return $sth->set_err(2,"Don't exaggerate",undef, undef, [ 42,"zz",0 ]) - if $row->[0] > 42; - } - return $row; -} - - -# ================================================= -package main; - -use Test::More tests => 43; - -BEGIN { - use_ok( 'DBI' ); -} - -my $tmp; - -#DBI->trace(2); -my $dbh = MyDBI->connect("dbi:Sponge:foo","","", { - PrintError => 0, - RaiseError => 1, - CompatMode => 1, # just for clone test -}); -isa_ok($dbh, 'MyDBI::db'); -is($dbh->{CompatMode}, 1); -undef $dbh; - -$dbh = DBI->connect("dbi:Sponge:foo","","", { - PrintError => 0, - RaiseError => 1, - RootClass => "MyDBI", - CompatMode => 1, # just for clone test - dbi_foo => 1, # just to help debugging clone etc -}); -isa_ok( $dbh, 'MyDBI::db'); -is($dbh->{CompatMode}, 1); - -#$dbh->trace(5); -my $sth = $dbh->prepare("foo", - # data for DBD::Sponge to return via fetch - { rows => [ - [ 40, "AAA", 9 ], - [ 41, "BB", 8 ], - [ -1, "C", 7 ], - [ 49, "DD", 6 ] - ], - } -); - -is($calls, 1); -isa_ok($sth, 'MyDBI::st'); - -my $row = $sth->fetch; -is($calls, 2); -is($row->[1], "aaa"); - -$row = $sth->fetch; -is($calls, 3); -is($row->[1], "bb"); - -is($DBI::err, undef); -$row = eval { $sth->fetch }; -my $eval_err = $@; -is(!defined $row, 1); -is(substr($eval_err,0,50), "DBD::Sponge::st fetch failed: Don't be so negative"); - -#$sth->trace(5); -#$sth->{PrintError} = 1; -$sth->{RaiseError} = 0; -$row = eval { $sth->fetch }; -isa_ok($row, 'ARRAY'); -is($row->[0], 42); -is($DBI::err, 2); -like($DBI::errstr, qr/Don't exaggerate/); -is($@ =~ /Don't be so negative/, $@); - - -my $dbh2 = $dbh->clone; -isa_ok( $dbh2, 'MyDBI::db', "Clone A" ); -is($dbh2 != $dbh, 1); -is($dbh2->{CompatMode}, 1); - -my $dbh3 = $dbh->clone({}); -isa_ok( $dbh3, 'MyDBI::db', 'Clone B' ); -is($dbh3 != $dbh, 1); -is($dbh3 != $dbh2, 1); -isa_ok( $dbh3, 'MyDBI::db'); -is($dbh3->{CompatMode}, 1); - -my $dbh2c = $dbh2->clone; -isa_ok( $dbh2c, 'MyDBI::db', "Clone of clone A" ); -is($dbh2c != $dbh2, 1); -is($dbh2c->{CompatMode}, 1); - -my $dbh3c = $dbh3->clone({ CompatMode => 0 }); -isa_ok( $dbh3c, 'MyDBI::db', 'Clone of clone B' ); -is((grep { $dbh3c == $_ } $dbh, $dbh2, $dbh3), 0); -isa_ok( $dbh3c, 'MyDBI::db'); -ok(!$dbh3c->{CompatMode}); - -$tmp = $dbh->sponge_test_installed_method('foo','bar'); -isa_ok( $tmp, "ARRAY", "installed method" ); -is_deeply( $tmp, [qw( foo bar )] ); -$tmp = eval { $dbh->sponge_test_installed_method() }; -is(!$tmp, 1); -is($dbh->err, 42); -is($dbh->errstr, "not enough parameters"); - - -$dbh = eval { DBI->connect("dbi:Sponge:foo","","", { - RootClass => 'nonesuch1', PrintError => 0, RaiseError => 0, }); -}; -ok( !defined($dbh), "Failed connect #1" ); -is(substr($@,0,25), "Can't locate nonesuch1.pm"); - -$dbh = eval { nonesuch2->connect("dbi:Sponge:foo","","", { - PrintError => 0, RaiseError => 0, }); -}; -ok( !defined($dbh), "Failed connect #2" ); -is(substr($@,0,36), q{Can't locate object method "connect"}); - -print "@{[ %my_methods ]}\n"; -1; diff --git a/dbLifeLog/DBI-1.641/t/31methcache.t b/dbLifeLog/DBI-1.641/t/31methcache.t deleted file mode 100644 index 28dabfb..0000000 --- a/dbLifeLog/DBI-1.641/t/31methcache.t +++ /dev/null @@ -1,157 +0,0 @@ -#!perl -w -# -# check that the inner-method lookup cache works -# (or rather, check that it doesn't cache things when it shouldn't) - -BEGIN { eval "use threads;" } # Must be first -my $use_threads_err = $@; -use Config qw(%Config); -# With this test code and threads, 5.8.1 has issues with freeing freed -# scalars, while 5.8.9 doesn't; I don't know about in-between - DAPM -my $has_threads = $Config{useithreads}; -die $use_threads_err if $has_threads && $use_threads_err; - - -use strict; - -$|=1; -$^W=1; - - - -use Test::More tests => 49; - -BEGIN { - use_ok( 'DBI' ); -} - -sub new_handle { - my $dbh = DBI->connect("dbi:Sponge:foo","","", { - PrintError => 0, - RaiseError => 1, - }); - - my $sth = $dbh->prepare("foo", - # data for DBD::Sponge to return via fetch - { rows => - [ - [ "row0" ], - [ "row1" ], - [ "row2" ], - [ "row3" ], - [ "row4" ], - [ "row5" ], - [ "row6" ], - ], - } - ); - - return ($dbh, $sth); -} - - -sub Foo::local1 { [ "local1" ] }; -sub Foo::local2 { [ "local2" ] }; - - -my $fetch_hook; -{ - package Bar; - @Bar::ISA = qw(DBD::_::st); - sub fetch { &$fetch_hook }; -} - -sub run_tests { - my ($desc, $dbh, $sth) = @_; - my $row = $sth->fetch; - is($row->[0], "row0", "$desc row0"); - - { - # replace CV slot - no warnings 'redefine'; - local *DBD::Sponge::st::fetch = sub { [ "local0" ] }; - $row = $sth->fetch; - is($row->[0], "local0", "$desc local0"); - } - $row = $sth->fetch; - is($row->[0], "row1", "$desc row1"); - - { - # replace GP - local *DBD::Sponge::st::fetch = *Foo::local1; - $row = $sth->fetch; - is($row->[0], "local1", "$desc local1"); - } - $row = $sth->fetch; - is($row->[0], "row2", "$desc row2"); - - { - # replace GV - local $DBD::Sponge::st::{fetch} = *Foo::local2; - $row = $sth->fetch; - is($row->[0], "local2", "$desc local2"); - } - $row = $sth->fetch; - is($row->[0], "row3", "$desc row3"); - - { - # @ISA = NoSuchPackage - local $DBD::Sponge::st::{fetch}; - local @DBD::Sponge::st::ISA = qw(NoSuchPackage); - eval { local $SIG{__WARN__} = sub {}; $row = $sth->fetch }; - like($@, qr/Can't locate DBI object method/, "$desc locate DBI object"); - } - $row = $sth->fetch; - is($row->[0], "row4", "$desc row4"); - - { - # @ISA = Bar - $fetch_hook = \&DBD::Sponge::st::fetch; - local $DBD::Sponge::st::{fetch}; - local @DBD::Sponge::st::ISA = qw(Bar); - $row = $sth->fetch; - is($row->[0], "row5", "$desc row5"); - $fetch_hook = sub { [ "local3" ] }; - $row = $sth->fetch; - is($row->[0], "local3", "$desc local3"); - } - $row = $sth->fetch; - is($row->[0], "row6", "$desc row6"); -} - -run_tests("plain", new_handle()); - - -SKIP: { - skip "no threads / perl < 5.8.9", 12 unless $has_threads; - # only enable this when handles are allowed to be shared across threads - #{ - # my @h = new_handle(); - # threads->new(sub { run_tests("threads", @h) })->join; - #} - threads->new(sub { run_tests("threads-h", new_handle()) })->join; -}; - -# using weaken attaches magic to the CV; see whether this interferes -# with the cache magic - -use Scalar::Util qw(weaken); -my $fetch_ref = \&DBI::st::fetch; -weaken $fetch_ref; -run_tests("magic", new_handle()); - -SKIP: { - skip "no threads / perl < 5.8.9", 12 unless $has_threads; - - skip "weaken itself is buggy on 5.8.1 (magic killbackrefs panic " - ."triggered by threads, fixed in 5.8.2)" - , 12 unless $] > 5.008001; - # only enable this when handles are allowed to be shared across threads - #{ - # my @h = new_handle(); - # threads->new(sub { run_tests("threads", @h) })->join; - #} - threads->new(sub { run_tests("magic threads-h", new_handle()) })->join; -}; - -1; diff --git a/dbLifeLog/DBI-1.641/t/35thrclone.t b/dbLifeLog/DBI-1.641/t/35thrclone.t deleted file mode 100644 index 185ebd0..0000000 --- a/dbLifeLog/DBI-1.641/t/35thrclone.t +++ /dev/null @@ -1,86 +0,0 @@ -#!perl -w -$|=1; - -# --- Test DBI support for threads created after the DBI was loaded - -BEGIN { eval "use threads;" } # Must be first -my $use_threads_err = $@; - -use strict; -use Config qw(%Config); -use Test::More; - -BEGIN { - if (!$Config{useithreads} || $] < 5.008001) { - plan skip_all => "this $^O perl $] not supported for DBI iThreads"; - } - die $use_threads_err if $use_threads_err; # need threads -} - -my $threads = 4; -plan tests => 4 + 4 * $threads; - -{ - package threads_sub; - use base qw(threads); -} - -use_ok('DBI'); - -$DBI::PurePerl = $DBI::PurePerl; # just to silence used only once warning -$DBI::neat_maxlen = 12345; -cmp_ok($DBI::neat_maxlen, '==', 12345, '... assignment of neat_maxlen was successful'); - -my @connect_args = ("dbi:ExampleP:", '', ''); - -my $dbh_parent = DBI->connect_cached(@connect_args); -isa_ok( $dbh_parent, 'DBI::db' ); - -# this our function for the threads to run - -sub testing { - cmp_ok($DBI::neat_maxlen, '==', 12345, '... DBI::neat_maxlen still holding its value'); - - my $dbh = DBI->connect_cached(@connect_args); - isa_ok( $dbh, 'DBI::db' ); - isnt($dbh, $dbh_parent, '... new $dbh is not the same instance as $dbh_parent'); - - SKIP: { - # skip seems broken with threads (5.8.3) - # skip "Kids attribute not supported under DBI::PurePerl", 1 if $DBI::PurePerl; - - cmp_ok($dbh->{Driver}->{Kids}, '==', 1, '... the Driver has one Kid') - unless $DBI::PurePerl && ok(1); - } - - # RT #77137: a thread created from a thread was crashing the - # interpreter - my $subthread = threads->new(sub {}); - - # provide a little insurance against thread scheduling issues (hopefully) - # http://www.nntp.perl.org/group/perl.cpan.testers/2009/06/msg4369660.html - eval { select undef, undef, undef, 0.2 }; - - $subthread->join(); -} - -# load up the threads - -my @thr; -push @thr, threads_sub->create( \&testing ) - or die "thread->create failed ($!)" - foreach (1..$threads); - -# join all the threads - -foreach my $thread (@thr) { - # provide a little insurance against thread scheduling issues (hopefully) - # http://www.nntp.perl.org/group/perl.cpan.testers/2009/06/msg4369660.html - eval { select undef, undef, undef, 0.2 }; - - $thread->join; -} - -pass('... all tests have passed'); - -1; diff --git a/dbLifeLog/DBI-1.641/t/40profile.t b/dbLifeLog/DBI-1.641/t/40profile.t deleted file mode 100644 index 7a71b8f..0000000 --- a/dbLifeLog/DBI-1.641/t/40profile.t +++ /dev/null @@ -1,485 +0,0 @@ -#!perl -w -$|=1; - -# -# test script for DBI::Profile -# - -use strict; - -use Config; -use DBI::Profile; -use DBI qw(dbi_time); -use Data::Dumper; -use File::Spec; -use Storable qw(dclone); - -use Test::More; - -BEGIN { - plan skip_all => "profiling not supported for DBI::PurePerl" - if $DBI::PurePerl; - - # tie methods (STORE/FETCH etc) get called different number of times - plan skip_all => "test results assume perl >= 5.8.2" - if $] <= 5.008001; - - # clock instability on xen systems is a reasonably common cause of failure - # http://www.nntp.perl.org/group/perl.cpan.testers/2009/05/msg3828158.html - # so we'll skip automated testing on those systems - plan skip_all => "skipping profile tests on xen (due to clock instability)" - if $Config{osvers} =~ /xen/ # eg 2.6.18-4-xen-amd64 - and $ENV{AUTOMATED_TESTING}; - - plan tests => 60; -} - -$Data::Dumper::Indent = 1; -$Data::Dumper::Terse = 1; - -# log file to store profile results -my $LOG_FILE = "test_output_profile$$.log"; -my $orig_dbi_debug = $DBI::dbi_debug; -DBI->trace($DBI::dbi_debug, $LOG_FILE); -END { - return if $orig_dbi_debug; - 1 while unlink $LOG_FILE; -} - - -print "Test enabling the profile\n"; - -# make sure profiling starts disabled -my $dbh = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1 }); -ok($dbh, 'connect'); -ok(!$dbh->{Profile} && !$ENV{DBI_PROFILE}, 'Profile and DBI_PROFILE not set'); - - -# can turn it on after the fact using a path number -$dbh = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1 }); -$dbh->{Profile} = "4"; -is_deeply sanitize_tree($dbh->{Profile}), bless { - 'Path' => [ '!MethodName' ], -} => 'DBI::Profile'; - -# using a package name -$dbh = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1 }); -$dbh->{Profile} = "/DBI::Profile"; -is_deeply sanitize_tree($dbh->{Profile}), bless { - 'Path' => [ ], -} => 'DBI::Profile'; - -# using a combined path and name -$dbh = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1 }); -$dbh->{Profile} = "20/DBI::Profile"; -is_deeply sanitize_tree($dbh->{Profile}), bless { - 'Path' => [ '!MethodName', '!Caller2' ], -} => 'DBI::Profile'; - -my $t_file = __FILE__; -$dbh->do("set foo=1"); my $line = __LINE__; -my $expected_caller = "40profile.t line $line"; -$expected_caller .= " via ${1}40profile.t line 4" - if $0 =~ /(zv\w+_)/; -print Dumper($dbh->{Profile}); -is_deeply sanitize_tree($dbh->{Profile}), bless { - 'Path' => [ '!MethodName', '!Caller2' ], - 'Data' => { 'do' => { - $expected_caller => [ 1, 0, 0, 0, 0, 0, 0 ] - } } -} => 'DBI::Profile' - or warn Dumper $dbh->{Profile}; - - -# can turn it on at connect -$dbh = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1, Profile=>6 }); -is_deeply $dbh->{Profile}{Path}, [ '!Statement', '!MethodName' ]; -cmp_ok(keys %{ $dbh->{Profile}{Data} }, '==', 1, 'on at connect, 1 key'); -cmp_ok(keys %{ $dbh->{Profile}{Data}{""} }, '>=', 1, 'on at connect, 1 key'); # at least STORE -ok(ref $dbh->{Profile}{Data}{""}{STORE}, 'STORE is ref'); - -print "dbi_profile\n"; -# Try to avoid rounding problem on double precision systems -# $got->[5] = '1150962858.01596498' -# $expected->[5] = '1150962858.015965' -# by treating as a string (because is_deeply stringifies) -my $t1 = DBI::dbi_time() . ""; -my $dummy_statement = "Hi mom"; -my $dummy_methname = "my_method_name"; -my $leaf = dbi_profile($dbh, $dummy_statement, $dummy_methname, $t1, $t1 + 1); -print Dumper($dbh->{Profile}); -cmp_ok(keys %{ $dbh->{Profile}{Data} }, '==', 2, 'avoid rounding, 1 key'); -cmp_ok(keys %{ $dbh->{Profile}{Data}{$dummy_statement} }, '==', 1, - 'avoid rounding, 1 dummy statement'); -is(ref($dbh->{Profile}{Data}{$dummy_statement}{$dummy_methname}), 'ARRAY', - 'dummy method name is array'); - -ok $leaf, "should return ref to leaf node"; -is ref $leaf, 'ARRAY', "should return ref to leaf node"; - -my $mine = $dbh->{Profile}{Data}{$dummy_statement}{$dummy_methname}; - -is $leaf, $mine, "should return ref to correct leaf node"; - -print "@$mine\n"; -is_deeply $mine, [ 1, 1, 1, 1, 1, $t1, $t1 ]; - -my $t2 = DBI::dbi_time() . ""; -dbi_profile($dbh, $dummy_statement, $dummy_methname, $t2, $t2 + 2); -print "@$mine\n"; -is_deeply $mine, [ 2, 3, 1, 1, 2, $t1, $t2 ]; - - -print "Test collected profile data\n"; - -$dbh = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1, Profile=>2 }); -# do a (hopefully) measurable amount of work -my $sql = "select mode,size,name from ?"; -my $sth = $dbh->prepare($sql); -for my $loop (1..50) { # enough work for low-res timers or v.fast cpus - $sth->execute("."); - while ( my $hash = $sth->fetchrow_hashref ) {} -} -$dbh->do("set foo=1"); - -print Dumper($dbh->{Profile}); - -# check that the proper key was set in Data -my $data = $dbh->{Profile}{Data}{$sql}; -ok($data, 'profile data'); -is(ref $data, 'ARRAY', 'ARRAY ref'); -ok(@$data == 7, '7 elements'); -ok((grep { defined($_) } @$data) == 7, 'all 7 defined'); -ok((grep { DBI::looks_like_number($_) } @$data) == 7, 'all 7 numeric'); -my ($count, $total, $first, $shortest, $longest, $time1, $time2) = @$data; -ok($count > 3, 'count is 3'); -ok($total > $first, ' total > first'); -ok($total > $longest, 'total > longest') or - warn "total $total > longest $longest: failed\n"; -ok($longest > 0, 'longest > 0') or - warn "longest $longest > 0: failed\n"; # XXX theoretically not reliable -ok($longest > $shortest, 'longest > shortest'); -ok($time1 >= $^T, 'time1 later than start time'); -ok($time2 >= $^T, 'time2 later than start time'); -ok($time1 <= $time2, 'time1 <= time2'); -my $next = int(dbi_time()) + 1; -ok($next > $time1, 'next > time1') or - warn "next $next > first $time1: failed\n"; -ok($next > $time2, 'next > time2') or - warn "next $next > last $time2: failed\n"; -if ($shortest < 0) { - my $sys = "$Config{archname} $Config{osvers}"; # ie sparc-linux 2.4.20-2.3sparcsmp - warn < -0.008; -} - - -my $tmp = sanitize_tree($dbh->{Profile}); -$tmp->{Data}{$sql}[0] = -1; # make test insensitive to local file count -is_deeply $tmp, (bless { - 'Path' => [ '!Statement' ], - 'Data' => { - '' => [ 6, 0, 0, 0, 0, 0, 0 ], - $sql => [ -1, 0, 0, 0, 0, 0, 0 ], - 'set foo=1' => [ 1, 0, 0, 0, 0, 0, 0 ], - } -} => 'DBI::Profile'), 'profile'; - -print "Test profile format\n"; -my $output = $dbh->{Profile}->format(); -print "Profile Output\n$output"; - -# check that output was produced in the expected format -ok(length $output, 'non zero length'); -ok($output =~ /^DBI::Profile:/, 'DBI::Profile'); -ok($output =~ /\((\d+) calls\)/, 'some calls'); -ok($1 >= $count, 'calls >= count'); - -# ----------------------------------------------------------------------------------- - -# try statement and method name and reference-to-scalar path -my $by_reference = 'foo'; -$dbh = DBI->connect("dbi:ExampleP:", 'usrnam', '', { - RaiseError => 1, - Profile => { Path => [ '{Username}', '!Statement', \$by_reference, '!MethodName' ] } -}); -$sql = "select name from ."; -$sth = $dbh->prepare($sql); -$sth->execute(); -$sth->fetchrow_hashref; -$by_reference = 'bar'; -$sth->finish; -undef $sth; # DESTROY - -$tmp = sanitize_tree($dbh->{Profile}); -ok $tmp->{Data}{usrnam}{""}{foo}{STORE}, 'username stored'; -$tmp->{Data}{usrnam}{""}{foo} = {}; -# make test insentitive to number of local files -#warn Dumper($tmp); -is_deeply $tmp, bless { - 'Path' => [ '{Username}', '!Statement', \$by_reference, '!MethodName' ], - 'Data' => { - '' => { # because Profile was enabled by DBI just before Username was set - '' => { - 'foo' => { - 'STORE' => [ 3, 0, 0, 0, 0, 0, 0 ], - } - } - }, - 'usrnam' => { - '' => { - 'foo' => { }, - }, - 'select name from .' => { - 'foo' => { - 'execute' => [ 1, 0, 0, 0, 0, 0, 0 ], - 'fetchrow_hashref' => [ 1, 0, 0, 0, 0, 0, 0 ], - 'prepare' => [ 1, 0, 0, 0, 0, 0, 0 ], - }, - 'bar' => { - 'DESTROY' => [ 1, 0, 0, 0, 0, 0, 0 ], - 'finish' => [ 1, 0, 0, 0, 0, 0, 0 ], - }, - }, - }, - }, -} => 'DBI::Profile'; - -$tmp = [ $dbh->{Profile}->as_node_path_list() ]; -is @$tmp, 8, 'should have 8 nodes'; -sanitize_profile_data_nodes($_->[0]) for @$tmp; -#warn Dumper($dbh->{Profile}->{Data}); -is_deeply $tmp, [ - [ [ 3, 0, 0, 0, 0, 0, 0 ], '', '', 'foo', 'STORE' ], - [ [ 2, 0, 0, 0, 0, 0, 0 ], 'usrnam', '', 'foo', 'STORE' ], - [ [ 1, 0, 0, 0, 0, 0, 0 ], 'usrnam', '', 'foo', 'connected' ], - [ [ 1, 0, 0, 0, 0, 0, 0 ], 'usrnam', 'select name from .', 'bar', 'DESTROY' ], - [ [ 1, 0, 0, 0, 0, 0, 0 ], 'usrnam', 'select name from .', 'bar', 'finish' ], - [ [ 1, 0, 0, 0, 0, 0, 0 ], 'usrnam', 'select name from .', 'foo', 'execute' ], - [ [ 1, 0, 0, 0, 0, 0, 0 ], 'usrnam', 'select name from .', 'foo', 'fetchrow_hashref' ], - [ [ 1, 0, 0, 0, 0, 0, 0 ], 'usrnam', 'select name from .', 'foo', 'prepare' ] -]; - - -print "testing '!File', '!Caller' and their variants in Path\n"; - -$dbh->{Profile}->{Path} = [ '!File', '!File2', '!Caller', '!Caller2' ]; -$dbh->{Profile}->{Data} = undef; - -my $file = (File::Spec->splitpath(__FILE__))[2]; # '40profile.t' -my ($line1, $line2); -sub a_sub { - $sth = $dbh->prepare("select name from ."); $line2 = __LINE__; -} -a_sub(); $line1 = __LINE__; - -$tmp = sanitize_profile_data_nodes($dbh->{Profile}{Data}); -#warn Dumper($tmp); -is_deeply $tmp, { - "$file" => { - "$file via $file" => { - "$file line $line2" => { - "$file line $line2 via $file line $line1" => [ 1, 0, 0, 0, 0, 0, 0 ] - } - } - } -}; - - -print "testing '!Time' and variants in Path\n"; - -undef $sth; -my $factor = 1_000_000; -$dbh->{Profile}->{Path} = [ '!Time', "!Time~$factor", '!MethodName' ]; -$dbh->{Profile}->{Data} = undef; - -# give up a timeslice in the hope that the following few lines -# run in well under a second even of slow/overloaded systems -$t1 = int(dbi_time())+1; 1 while int(dbi_time()-0.01) < $t1; # spin till just after second starts -$t2 = int($t1/$factor)*$factor; - -$sth = $dbh->prepare("select name from ."); -$tmp = sanitize_profile_data_nodes($dbh->{Profile}{Data}); - -# if actual "!Time" recorded is 'close enough' then we'll pass -# the test - it's not worth failing just because a system is slow -$t1 = (keys %$tmp)[0] if (abs($t1 - (keys %$tmp)[0]) <= 5); - -is_deeply $tmp, { - $t1 => { $t2 => { prepare => [ 1, 0, 0, 0, 0, 0, 0 ] }} -}, "!Time and !Time~$factor should work" - or warn Dumper([$t1, $t2, $tmp]); - - -print "testing &norm_std_n3 in Path\n"; - -$dbh->{Profile} = '&norm_std_n3'; # assign as string to get magic -is_deeply $dbh->{Profile}{Path}, [ - \&DBI::ProfileSubs::norm_std_n3 -]; -$dbh->{Profile}->{Data} = undef; -$sql = qq{insert into foo20060726 (a,b) values (42,"foo")}; -dbi_profile( { foo => $dbh, bar => undef }, $sql, 'mymethod', 100000000, 100000002); -$tmp = $dbh->{Profile}{Data}; -#warn Dumper($tmp); -is_deeply $tmp, { - 'insert into foo (a,b) values (,"")' => [ 1, '2', '2', '2', '2', '100000000', '100000000' ] -}, '&norm_std_n3 should normalize statement'; - - -# ----------------------------------------------------------------------------------- - -print "testing code ref in Path\n"; - -sub run_test1 { - my ($profile) = @_; - $dbh = DBI->connect("dbi:ExampleP:", 'usrnam', '', { - RaiseError => 1, - Profile => $profile, - }); - $sql = "select name from ."; - $sth = $dbh->prepare($sql); - $sth->execute(); - $sth->fetchrow_hashref; - $sth->finish; - undef $sth; # DESTROY - my $data = sanitize_profile_data_nodes($dbh->{Profile}{Data}, 1); - return ($data, $dbh) if wantarray; - return $data; -} - -$tmp = run_test1( { Path => [ 'foo', sub { 'bar' }, 'baz' ] }); -is_deeply $tmp, { 'foo' => { 'bar' => { 'baz' => [ 11, 0,0,0,0,0,0 ] } } }; - -$tmp = run_test1( { Path => [ 'foo', sub { 'ping','pong' } ] }); -is_deeply $tmp, { 'foo' => { 'ping' => { 'pong' => [ 11, 0,0,0,0,0,0 ] } } }; - -$tmp = run_test1( { Path => [ 'foo', sub { \undef } ] }); -is_deeply $tmp, { 'foo' => undef }, 'should be vetoed'; - -# check what code ref sees in $_ -$tmp = run_test1( { Path => [ sub { $_ } ] }); -is_deeply $tmp, { - '' => [ 6, 0, 0, 0, 0, 0, 0 ], - 'select name from .' => [ 5, 0, 0, 0, 0, 0, 0 ] -}, '$_ should contain statement'; - -# check what code ref sees in @_ -$tmp = run_test1( { Path => [ sub { my ($h,$method) = @_; return \undef if $method =~ /^[A-Z]+$/; return (ref $h, $method) } ] }); -is_deeply $tmp, { - 'DBI::db' => { - 'connected' => [ 1, 0, 0, 0, 0, 0, 0 ], - 'prepare' => [ 1, 0, 0, 0, 0, 0, 0 ], - }, - 'DBI::st' => { - 'fetchrow_hashref' => [ 1, 0, 0, 0, 0, 0, 0 ], - 'execute' => [ 1, 0, 0, 0, 0, 0, 0 ], - 'finish' => [ 1, 0, 0, 0, 0, 0, 0 ], - }, -}, 'should have @_ as keys'; - -# check we can filter by method -$tmp = run_test1( { Path => [ sub { return \undef unless $_[1] =~ /^fetch/; return $_[1] } ] }); -#warn Dumper($tmp); -is_deeply $tmp, { - 'fetchrow_hashref' => [ 1, 0, 0, 0, 0, 0, 0 ], -}, 'should be able to filter by method'; - -DBI->trace(0, "STDOUT"); # close current log to flush it -ok(-s $LOG_FILE, 'output should go to log file'); - -# ----------------------------------------------------------------------------------- - -print "testing as_text\n"; - -# check %N$ indices -$dbh->{Profile}->{Data} = { P1 => { P2 => [ 100, 400, 42, 43, 44, 45, 46, 47 ] } }; -my $as_text = $dbh->{Profile}->as_text({ - path => [ 'top' ], - separator => ':', - format => '%1$s %2$d [ %10$d %11$d %12$d %13$d %14$d %15$d %16$d %17$d ]', -}); -is($as_text, "top:P1:P2 4 [ 100 400 42 43 44 45 46 47 ]", 'as_text'); - -# test sortsub -$dbh->{Profile}->{Data} = { - A => { Z => [ 101, 1, 2, 3, 4, 5, 6, 7 ] }, - B => { Y => [ 102, 1, 2, 3, 4, 5, 6, 7 ] }, -}; -$as_text = $dbh->{Profile}->as_text({ - separator => ':', - format => '%1$s %10$d ', - sortsub => sub { my $ary=shift; @$ary = sort { $a->[2] cmp $b->[2] } @$ary } -}); -is($as_text, "B:Y 102 A:Z 101 ", 'as_text sortsub'); - -# general test, including defaults -($tmp, $dbh) = run_test1( { Path => [ 'foo', '!MethodName', 'baz' ] }); -$as_text = $dbh->{Profile}->as_text(); -$as_text =~ s/\.00+/.0/g; -#warn "[$as_text]"; -is $as_text, q{foo > DESTROY > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s) -foo > STORE > baz: 0.0s / 5 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s) -foo > connected > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s) -foo > execute > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s) -foo > fetchrow_hashref > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s) -foo > finish > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s) -foo > prepare > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s) -}, 'as_text general'; - -# ----------------------------------------------------------------------------------- - -print "dbi_profile_merge_nodes\n"; -my $total_time = dbi_profile_merge_nodes( - my $totals=[], - [ 10, 0.51, 0.11, 0.01, 0.22, 1023110000, 1023110010 ], - [ 15, 0.42, 0.12, 0.02, 0.23, 1023110005, 1023110009 ], -); -$_ = sprintf "%.2f", $_ for @$totals; # avoid precision issues -is("@$totals", "25.00 0.93 0.11 0.01 0.23 1023110000.00 1023110010.00", - 'merged nodes'); -is($total_time, 0.93, 'merged time'); - -$total_time = dbi_profile_merge_nodes( - $totals=[], { - foo => [ 10, 1.51, 0.11, 0.01, 0.22, 1023110000, 1023110010 ], - bar => [ 17, 1.42, 0.12, 0.02, 0.23, 1023110005, 1023110009 ], - } -); -$_ = sprintf "%.2f", $_ for @$totals; # avoid precision issues -is("@$totals", "27.00 2.93 0.11 0.01 0.23 1023110000.00 1023110010.00", - 'merged time foo/bar'); -is($total_time, 2.93, 'merged nodes foo/bar time'); - -exit 0; - - -sub sanitize_tree { - my $data = shift; - my $skip_clone = shift; - return $data unless ref $data; - $data = dclone($data) unless $skip_clone; - sanitize_profile_data_nodes($data->{Data}) if $data->{Data}; - return $data; -} - -sub sanitize_profile_data_nodes { - my $node = shift; - if (ref $node eq 'HASH') { - sanitize_profile_data_nodes($_) for values %$node; - } - elsif (ref $node eq 'ARRAY') { - if (@$node == 7 and DBI::looks_like_number($node->[0])) { - # sanitize the profile data node to simplify tests - $_ = 0 for @{$node}[1..@$node-1]; # not 0 - } - } - return $node; -} diff --git a/dbLifeLog/DBI-1.641/t/41prof_dump.t b/dbLifeLog/DBI-1.641/t/41prof_dump.t deleted file mode 100644 index c921893..0000000 --- a/dbLifeLog/DBI-1.641/t/41prof_dump.t +++ /dev/null @@ -1,105 +0,0 @@ -#!perl -wl -# Using -l to ensure ProfileDumper is isolated from changes to $/ and $\ and such - -$|=1; - -use strict; - -# -# test script for DBI::ProfileDumper -# - -use DBI; -use Config; -use Test::More; - -BEGIN { - plan skip_all => 'profiling not supported for DBI::PurePerl' - if $DBI::PurePerl; - - # clock instability on xen systems is a reasonably common cause of failure - # http://www.nntp.perl.org/group/perl.cpan.testers/2009/05/msg3828158.html - # so we'll skip automated testing on those systems - plan skip_all => "skipping profile tests on xen (due to clock instability)" - if $Config{osvers} =~ /xen/ # eg 2.6.18-4-xen-amd64 - and $ENV{AUTOMATED_TESTING}; - - plan tests => 15; -} - -BEGIN { - use_ok( 'DBI' ); - use_ok( 'DBI::ProfileDumper' ); -} - -my $prof_file = "dbi$$.prof"; -my $prof_backup = $prof_file . ".prev"; -END { 1 while unlink $prof_file; - 1 while unlink $prof_backup; } - -my $dbh = DBI->connect("dbi:ExampleP:", '', '', - { RaiseError=>1, Profile=>"2/DBI::ProfileDumper/File:$prof_file" }); -isa_ok( $dbh, 'DBI::db' ); -isa_ok( $dbh->{Profile}, "DBI::ProfileDumper" ); -isa_ok( $dbh->{Profile}{Data}, 'HASH' ); -isa_ok( $dbh->{Profile}{Path}, 'ARRAY' ); - -# do a little work -my $sql = "select mode,size,name from ?"; -my $sth = $dbh->prepare($sql); -isa_ok( $sth, 'DBI::st' ); -$sth->execute("."); - -# check that flush_to_disk doesn't change Path if Path is undef (it -# did before 1.49) -{ - local $dbh->{Profile}->{Path} = undef; - $sth->{Profile}->flush_to_disk(); - is($dbh->{Profile}->{Path}, undef); -} - -$sth->{Profile}->flush_to_disk(); -while ( my $hash = $sth->fetchrow_hashref ) {} - -# force output -undef $sth; -$dbh->disconnect; -undef $dbh; - -# wrote the profile to disk? -ok( -s $prof_file, 'Profile is on disk and nonzero size' ); - -# XXX We're breaking encapsulation here -open(PROF, $prof_file) or die $!; -my @prof = ; -close PROF; - -print @prof; - -# has a header? -like( $prof[0], '/^DBI::ProfileDumper\s+([\d.]+)/', 'Found a version number' ); - -# version matches VERSION? (DBI::ProfileDumper uses $self->VERSION so -# it's a stringified version object that looks like N.N.N) -$prof[0] =~ /^DBI::ProfileDumper\s+([\d.]+)/; -is( $1, DBI::ProfileDumper->VERSION, "Version numbers match in $prof[0]" ); - -like( $prof[1], qr{^Path\s+=\s+\[\s+\]}, 'Found the Path'); -ok( $prof[2] =~ m{^Program\s+=\s+(\S+)}, 'Found the Program'); - -# check that expected key is there -like(join('', @prof), qr/\+\s+1\s+\Q$sql\E/m); - -# unlink($prof_file); # now done by 'make clean' - -# should be able to load DBI::ProfileDumper::Apache outside apache -# this also naturally checks for syntax errors etc. -SKIP: { - skip "developer-only test", 1 - unless (-d ".svn" || -d ".git") && -f "MANIFEST.SKIP"; - skip "Apache module not installed", 1 - unless eval { require Apache }; - require_ok('DBI::ProfileDumper::Apache') -} - -1; diff --git a/dbLifeLog/DBI-1.641/t/42prof_data.t b/dbLifeLog/DBI-1.641/t/42prof_data.t deleted file mode 100644 index c7d9053..0000000 --- a/dbLifeLog/DBI-1.641/t/42prof_data.t +++ /dev/null @@ -1,156 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use DBI; -use Config; -use Test::More; -use Data::Dumper; - -BEGIN { - plan skip_all => 'profiling not supported for DBI::PurePerl' - if $DBI::PurePerl; - - # clock instability on xen systems is a reasonably common cause of failure - # http://www.nntp.perl.org/group/perl.cpan.testers/2009/05/msg3828158.html - # so we'll skip automated testing on those systems - plan skip_all => "skipping profile tests on xen (due to clock instability)" - if $Config{osvers} =~ /xen/ # eg 2.6.18-4-xen-amd64 - and $ENV{AUTOMATED_TESTING}; - - plan tests => 31; -} - -BEGIN { - use_ok( 'DBI::ProfileDumper' ); - use_ok( 'DBI::ProfileData' ); -} - -my $sql = "select mode,size,name from ?"; - -my $prof_file = "dbi$$.prof"; -my $prof_backup = $prof_file . ".prev"; -END { 1 while unlink $prof_file; - 1 while unlink $prof_backup; } - -my $dbh = DBI->connect("dbi:ExampleP:", '', '', - { RaiseError=>1, Profile=>"6/DBI::ProfileDumper/File:$prof_file" }); -isa_ok( $dbh, 'DBI::db', 'Created connection' ); - -require DBI::Profile; -DBI::Profile->import(qw(dbi_time)); - -# do enough work to avoid 0's on systems that are very fast or have low res timers -my $t1 = dbi_time(); -foreach (1..20) { - $dbh->do("set dummy=$_"); - my $sth = $dbh->prepare($sql); - for my $loop (1..90) { - $sth->execute("."); - $sth->fetchrow_hashref; - $sth->finish; - } - $sth->{Profile}->flush_to_disk(); -} -$dbh->disconnect; -undef $dbh; -my $t2 = dbi_time(); -note sprintf "DBI work done in %fs (%f - %f)", $t2-$t1, $t2, $t1; - - -# wrote the profile to disk? -ok(-s $prof_file, "Profile written to disk, non-zero size" ); - -# load up -my $prof = DBI::ProfileData->new( - File => $prof_file, - Filter => sub { - my ($path_ref, $data_ref) = @_; - $path_ref->[0] =~ s/set dummy=\d/set dummy=N/; - }, -); -isa_ok( $prof, 'DBI::ProfileData' ); -cmp_ok( $prof->count, '>=', 3, 'At least 3 profile data items' ); - -# try a few sorts -my $nodes = $prof->nodes; -$prof->sort(field => "longest"); -my $longest = $nodes->[0][4]; -ok($longest); -$prof->sort(field => "longest", reverse => 1); -cmp_ok( $nodes->[0][4], '<', $longest ); - -$prof->sort(field => "count"); -my $most = $nodes->[0]; -ok($most); -$prof->sort(field => "count", reverse => 1); -cmp_ok( $nodes->[0][0], '<', $most->[0] ); - -# remove the top count and make sure it's gone -my $clone = $prof->clone(); -isa_ok( $clone, 'DBI::ProfileData' ); -$clone->sort(field => "count"); -ok($clone->exclude(key1 => $most->[7])); - -# compare keys of the new first element and the old one to make sure -# exclude works -ok($clone->nodes()->[0][7] ne $most->[7] && - $clone->nodes()->[0][8] ne $most->[8]); - -# there can only be one -$clone = $prof->clone(); -isa_ok( $clone, 'DBI::ProfileData' ); -ok($clone->match(key1 => $clone->nodes->[0][7])); -ok($clone->match(key2 => $clone->nodes->[0][8])); -ok($clone->count == 1); - -# take a look through Data -my $Data = $prof->Data; -print "SQL: $_\n" for keys %$Data; -ok(exists($Data->{$sql}), "Data for '$sql' should exist") - or print Dumper($Data); -ok(exists($Data->{$sql}{execute}), "Data for '$sql'->{execute} should exist"); - -# did the Filter convert set dummy=1 (etc) into set dummy=N? -ok(exists($Data->{"set dummy=N"})); - -# test escaping of \n and \r in keys -$dbh = DBI->connect("dbi:ExampleP:", '', '', - { RaiseError=>1, Profile=>"6/DBI::ProfileDumper/File:$prof_file" }); -isa_ok( $dbh, 'DBI::db', 'Created connection' ); - -my $sql2 = 'select size from . where name = "LITERAL: \r\n"'; -my $sql3 = "select size from . where name = \"EXPANDED: \r\n\""; - -# do a little work -foreach (1,2,3) { - my $sth2 = $dbh->prepare($sql2); - isa_ok( $sth2, 'DBI::st' ); - $sth2->execute(); - $sth2->fetchrow_hashref; - $sth2->finish; - my $sth3 = $dbh->prepare($sql3); - isa_ok( $sth3, 'DBI::st' ); - $sth3->execute(); - $sth3->fetchrow_hashref; - $sth3->finish; -} -$dbh->disconnect; -undef $dbh; - -# load dbi.prof -$prof = DBI::ProfileData->new( File => $prof_file, DeleteFiles => 1 ); -isa_ok( $prof, 'DBI::ProfileData' ); - -ok(not(-e $prof_file), "file should be deleted when DeleteFiles set" ); - - -# make sure the keys didn't get garbled -$Data = $prof->Data; -ok(exists $Data->{$sql2}, "Data for '$sql2' should exist") - or print Dumper($Data); -ok(exists $Data->{$sql3}, "Data for '$sql3' should exist") - or print Dumper($Data); - -1; diff --git a/dbLifeLog/DBI-1.641/t/43prof_env.t b/dbLifeLog/DBI-1.641/t/43prof_env.t deleted file mode 100644 index 6726cf7..0000000 --- a/dbLifeLog/DBI-1.641/t/43prof_env.t +++ /dev/null @@ -1,52 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -# -# test script for using DBI_PROFILE env var to enable DBI::Profile -# and testing non-ref assignments to $h->{Profile} -# - -BEGIN { $ENV{DBI_PROFILE} = 6 } # prior to use DBI - -use DBI; -use DBI::Profile; -use Config; -use Data::Dumper; - -BEGIN { - if ($DBI::PurePerl) { - print "1..0 # Skipped: profiling not supported for DBI::PurePerl\n"; - exit 0; - } -} - -use Test::More tests => 11; - -DBI->trace(0, "STDOUT"); - -my $dbh1 = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1 }); -is(ref $dbh1->{Profile}, "DBI::Profile"); -is(ref $dbh1->{Profile}{Data}, 'HASH'); -is(ref $dbh1->{Profile}{Path}, 'ARRAY'); - -my $dbh2 = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1 }); -is(ref $dbh2->{Profile}, "DBI::Profile"); -is(ref $dbh2->{Profile}{Data}, 'HASH'); -is(ref $dbh2->{Profile}{Path}, 'ARRAY'); - -is $dbh1->{Profile}, $dbh2->{Profile}, '$h->{Profile} should be shared'; - -$dbh1->do("set dummy=1"); -$dbh1->do("set dummy=2"); - -my $profile = $dbh1->{Profile}; - -my $p_data = $profile->{Data}; -is keys %$p_data, 3; # '', $sql1, $sql2 -ok $p_data->{''}; -ok $p_data->{"set dummy=1"}; -ok $p_data->{"set dummy=2"}; - -__END__ diff --git a/dbLifeLog/DBI-1.641/t/48dbi_dbd_sqlengine.t b/dbLifeLog/DBI-1.641/t/48dbi_dbd_sqlengine.t deleted file mode 100644 index 6fb2f3c..0000000 --- a/dbLifeLog/DBI-1.641/t/48dbi_dbd_sqlengine.t +++ /dev/null @@ -1,91 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use Cwd; -use File::Path; -use File::Spec; -use Test::More; - -my $using_dbd_gofer = ($ENV{DBI_AUTOPROXY}||"") =~ /^dbi:Gofer.*transport=/i; - -my $tbl; -BEGIN { $tbl = "db_". $$ . "_" }; -#END { $tbl and unlink glob "${tbl}*" } - -use_ok ("DBI"); -use_ok ("DBI::DBD::SqlEngine"); -use_ok ("DBD::File"); - -my $sql_statement = DBI::DBD::SqlEngine::Statement->isa('SQL::Statement'); -my $dbh = DBI->connect( "DBI:File:", undef, undef, { PrintError => 0, RaiseError => 0, } ); # Can't use DBI::DBD::SqlEngine direct - -for my $sql ( split "\n", <<"" ) - CREATE TABLE foo (id INT, foo TEXT) - CREATE TABLE bar (id INT, baz TEXT) - INSERT INTO foo VALUES (1, 'Hello world') - INSERT INTO bar VALUES (1, 'Bugfixes welcome') - INSERT bar VALUES (2, 'Bug reports, too') - SELECT foo FROM foo where ID=1 - UPDATE bar SET id=5 WHERE baz='Bugfixes welcome' - DELETE FROM foo - DELETE FROM bar WHERE baz='Bugfixes welcome' - -{ - my $sth; - $sql =~ s/^\s+//; - eval { $sth = $dbh->prepare( $sql ); }; - ok( $sth, "prepare '$sql'" ); -} - -for my $line ( split "\n", <<"" ) - Junk -- Junk - CREATE foo (id INT, foo TEXT) -- missing table - INSERT INTO bar (1, 'Bugfixes welcome') -- missing "VALUES" - UPDATE bar id=5 WHERE baz="Bugfixes welcome" -- missing "SET" - DELETE * FROM foo -- waste between "DELETE" and "FROM" - -{ - my $sth; - $line =~ s/^\s+//; - my ($sql, $test) = ( $line =~ m/^([^-]+)\s+--\s+(.*)$/ ); - eval { $sth = $dbh->prepare( $sql ); }; - ok( !$sth, "$test: prepare '$sql'" ); -} - -SKIP: { - # some SQL::Statement / SQL::Parser related tests - skip( "Not running with SQL::Statement", 3 ) unless ($sql_statement); - for my $line ( split "\n", <<"" ) - Junk -- Junk - CREATE TABLE bar (id INT, baz CHARACTER VARYING(255)) -- invalid column type - - { - my $sth; - $line =~ s/^\s+//; - my ($sql, $test) = ( $line =~ m/^([^-]+)\s+--\s+(.*)$/ ); - eval { $sth = $dbh->prepare( $sql ); }; - ok( !$sth, "$test: prepare '$sql'" ); - } - - my $dbh2 = DBI->connect( "DBI:File:", undef, undef, { sql_dialect => "ANSI" } ); - my $sth; - eval { $sth = $dbh2->prepare( "CREATE TABLE foo (id INTEGER PRIMARY KEY, phrase CHARACTER VARYING(40) UNIQUE)" ); }; - ok( $sth, "prepared statement using ANSI dialect" ); - skip( "Gofer proxy prevents fetching embedded SQL::Parser object", 1 ); - my $sql_parser = $dbh2->FETCH("sql_parser_object"); - cmp_ok( $sql_parser->dialect(), "eq", "ANSI", "SQL::Parser has 'ANSI' as dialect" ); -} - -SKIP: { - skip( 'not running with DBIx::ContextualFetch', 2 ) - unless eval { require DBIx::ContextualFetch; 1; }; - - my $dbh; - - ok ($dbh = DBI->connect('dbi:File:','','', {RootClass => 'DBIx::ContextualFetch'})); - is ref $dbh, 'DBIx::ContextualFetch::db', 'root class is DBIx::ContextualFetch'; -} - -done_testing (); diff --git a/dbLifeLog/DBI-1.641/t/49dbd_file.t b/dbLifeLog/DBI-1.641/t/49dbd_file.t deleted file mode 100644 index 905bad4..0000000 --- a/dbLifeLog/DBI-1.641/t/49dbd_file.t +++ /dev/null @@ -1,266 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use Cwd; -use File::Path; -use File::Spec; -use Test::More; - -my $using_dbd_gofer = ($ENV{DBI_AUTOPROXY}||"") =~ /^dbi:Gofer.*transport=/i; - -my $tbl; -BEGIN { $tbl = "db_". $$ . "_" }; -#END { $tbl and unlink glob "${tbl}*" } - -use_ok ("DBI"); -use_ok ("DBD::File"); - -do "./t/lib.pl"; - -my $dir = test_dir (); - -my $rowidx = 0; -my @rows = ( [ "Hello World" ], [ "Hello DBI Developers" ], ); - -my $dbh; - -# Check if we can connect at all -ok ($dbh = DBI->connect ("dbi:File:"), "Connect clean"); -is (ref $dbh, "DBI::db", "Can connect to DBD::File driver"); - -my $f_versions = $dbh->func ("f_versions"); -note $f_versions; -ok ($f_versions, "f_versions"); - -# Check if all the basic DBI attributes are accepted -ok ($dbh = DBI->connect ("dbi:File:", undef, undef, { - RaiseError => 1, - PrintError => 1, - AutoCommit => 1, - ChopBlanks => 1, - ShowErrorStatement => 1, - FetchHashKeyName => "NAME_lc", - }), "Connect with DBI attributes"); - -# Check if all the f_ attributes are accepted, in two ways -ok ($dbh = DBI->connect ("dbi:File:f_ext=.txt;f_dir=.;f_encoding=cp1252;f_schema=test"), "Connect with driver attributes in DSN"); - -my $encoding = "iso-8859-1"; - -# now use dir to prove file existence -ok ($dbh = DBI->connect ("dbi:File:", undef, undef, { - f_ext => ".txt", - f_dir => $dir, - f_schema => undef, - f_encoding => $encoding, - f_lock => 0, - - RaiseError => 0, - PrintError => 0, - }), "Connect with driver attributes in hash"); - -my $sth; -ok ($sth = $dbh->prepare ("select * from t_sbdgf_53442Gz"), "Prepare select from non-existing file"); - -{ my @msg; - eval { - local $SIG{__DIE__} = sub { push @msg, @_ }; - $sth->execute; - }; - like ("@msg", qr{Cannot open .*t_sbdgf_}, "Cannot open non-existing file"); - eval { - note $dbh->f_get_meta ("t_sbdgf_53442Gz", "f_fqfn"); - }; - } - -SKIP: { - my $fh; - my $tbl2 = $tbl . "2"; - - my $tbl2_file1 = File::Spec->catfile ($dir, "$tbl2.txt"); - open $fh, ">", $tbl2_file1 or skip; - print $fh "You cannot read this anyway ..."; - close $fh; - - my $tbl2_file2 = File::Spec->catfile ($dir, "$tbl2"); - open $fh, ">", $tbl2_file2 or skip; - print $fh "Neither that"; - close $fh; - - ok ($dbh->do ("drop table if exists $tbl2"), "drop manually created table $tbl2 (first file)"); - ok (! -f $tbl2_file1, "$tbl2_file1 removed"); - ok ( -f $tbl2_file2, "$tbl2_file2 exists"); - ok ($dbh->do ("drop table if exists $tbl2"), "drop manually created table $tbl2 (second file)"); - ok (! -f $tbl2_file2, "$tbl2_file2 removed"); - } - -my @tfhl; - -# Now test some basic SQL statements -my $tbl_file = File::Spec->catfile (Cwd::abs_path ($dir), "$tbl.txt"); -ok ($dbh->do ("create table $tbl (txt varchar (20))"), "Create table $tbl") or diag $dbh->errstr; -ok (-f $tbl_file, "Test table exists"); - -is ($dbh->f_get_meta ($tbl, "f_fqfn"), $tbl_file, "get single table meta data"); -is_deeply ($dbh->f_get_meta ([$tbl, "t_sbdgf_53442Gz"], [qw(f_dir f_ext)]), - { - $tbl => { - f_dir => $dir, - f_ext => ".txt", - }, - t_sbdgf_53442Gz => { - f_dir => $dir, - f_ext => ".txt", - }, - }, - "get multiple meta data"); - -# Expected: ("unix", "perlio", "encoding(iso-8859-1)") -# use Data::Peek; DDumper [ @tfh ]; -my @layer = grep { $_ eq "encoding($encoding)" } @tfhl; -is (scalar @layer, 1, "encoding shows in layer"); - -my @tables = sort $dbh->func ("list_tables"); -is_deeply (\@tables, [sort "000_just_testing", $tbl], "Listing tables gives test table"); - -ok ($sth = $dbh->table_info (), "table_info"); -@tables = sort { $a->[2] cmp $b->[2] } @{$sth->fetchall_arrayref}; -is_deeply (\@tables, [ map { [ undef, undef, $_, 'TABLE', 'FILE' ] } sort "000_just_testing", $tbl ], "table_info gives test table"); - -SKIP: { - $using_dbd_gofer and skip "modifying meta data doesn't work with Gofer-AutoProxy", 6; - ok ($dbh->f_set_meta ($tbl, "f_dir", $dir), "set single meta datum"); - is ($tbl_file, $dbh->f_get_meta ($tbl, "f_fqfn"), "verify set single meta datum"); - ok ($dbh->f_set_meta ($tbl, { f_dir => $dir }), "set multiple meta data"); - is ($tbl_file, $dbh->f_get_meta ($tbl, "f_fqfn"), "verify set multiple meta attributes"); - - ok($dbh->f_new_meta("t_bsgdf_3544G2z", { - f_ext => undef, - f_dir => $dir, - }), "initialize new table (meta) with settings"); - - my $t_bsgdf_file = File::Spec->catfile (Cwd::abs_path ($dir), "t_bsgdf_3544G2z"); - is($t_bsgdf_file, $dbh->f_get_meta ("t_bsgdf_3544G2z", "f_fqfn"), "verify create meta from scratch"); - } - -ok ($sth = $dbh->prepare ("select * from $tbl"), "Prepare select * from $tbl"); -$rowidx = 0; -SKIP: { - $using_dbd_gofer and skip "method intrusion didn't work with proxying", 1; - ok ($sth->execute, "execute on $tbl"); - $dbh->errstr and diag $dbh->errstr; - } - -my $uctbl = uc ($tbl); -ok ($sth = $dbh->prepare ("select * from $uctbl"), "Prepare select * from $uctbl"); -$rowidx = 0; -SKIP: { - $using_dbd_gofer and skip "method intrusion didn't work with proxying", 1; - ok ($sth->execute, "execute on $uctbl"); - $dbh->errstr and diag $dbh->errstr; - } - -# ==================== ReadOnly tests ============================= -ok ($dbh = DBI->connect ("dbi:File:", undef, undef, { - f_ext => ".txt", - f_dir => $dir, - f_schema => undef, - f_encoding => $encoding, - f_lock => 0, - - sql_meta => { - $tbl => { - col_names => [qw(txt)], - } - }, - - RaiseError => 0, - PrintError => 0, - ReadOnly => 1, - }), "ReadOnly connect with driver attributes in hash"); - -ok ($sth = $dbh->prepare ("select * from $tbl"), "Prepare select * from $tbl"); -$rowidx = 0; -SKIP: { - $using_dbd_gofer and skip "method intrusion didn't work with proxying", 3; - ok ($sth->execute, "execute on $tbl"); - like ($_, qr{^[0-9]+$}, "TYPE is numeric") for @{$sth->{TYPE}}; - like ($_, qr{^[A-Z]\w+$}, "TYPE_NAME is set") for @{$sth->{TYPE_NAME}}; - $dbh->errstr and diag $dbh->errstr; - } - -ok ($sth = $dbh->prepare ("insert into $tbl (txt) values (?)"), "prepare 'insert into $tbl'"); -is ($sth->execute ("Perl rules"), undef, "insert failed intensionally"); - -ok ($sth = $dbh->prepare ("delete from $tbl"), "prepare 'delete from $tbl'"); -is ($sth->execute (), undef, "delete failed intensionally"); - -is ($dbh->do ("drop table $tbl"), undef, "table drop failed intensionally"); -is (-f $tbl_file, 1, "Test table not removed"); - -# ==================== ReadWrite again tests ====================== -ok ($dbh = DBI->connect ("dbi:File:", undef, undef, { - f_ext => ".txt", - f_dir => $dir, - f_schema => undef, - f_encoding => $encoding, - f_lock => 0, - - RaiseError => 0, - PrintError => 0, - }), "ReadWrite for drop connect with driver attributes in hash"); - -# XXX add a truncate test - -ok ($dbh->do ("drop table $tbl"), "table drop"); -is (-s $tbl_file, undef, "Test table removed"); # -s => size test - -# ==================== Nonexisting top-dir ======================== -my %drh = DBI->installed_drivers; -my $qer = qr{\bNo such directory}; -foreach my $tld ("./non-existing", "nonexisting_folder", "/Fr-dle/hurd0k/ok$$") { - is (DBI->connect ("dbi:File:", undef, undef, { - f_dir => $tld, - - RaiseError => 0, - PrintError => 0, - }), undef, "Should not be able to open a DB to $tld"); - like ($DBI::errstr, $qer, "Error message"); - $drh{File}->set_err (undef, ""); - is ($DBI::errstr, undef, "Cleared error"); - my $dbh; - eval { $dbh = DBI->connect ("dbi:File:", undef, undef, { - f_dir => $tld, - - RaiseError => 1, - PrintError => 0, - })}; - is ($dbh, undef, "connect () should die on $tld with RaiseError"); - like ($@, $qer, "croak message"); - like ($DBI::errstr, $qer, "Error message"); - } - -done_testing (); - -sub DBD::File::Table::fetch_row ($$) -{ - my ($self, $data) = @_; - my $meta = $self->{meta}; - if ($rowidx >= scalar @rows) { - $self->{row} = undef; - } - else { - $self->{row} = $rows[$rowidx++]; - } - return $self->{row}; - } # fetch_row - -sub DBD::File::Table::push_names ($$$) -{ - my ($self, $data, $row_aryref) = @_; - my $meta = $self->{meta}; - @tfhl = PerlIO::get_layers ($meta->{fh}); - @{$meta->{col_names}} = @{$row_aryref}; - } # push_names diff --git a/dbLifeLog/DBI-1.641/t/50dbm_simple.t b/dbLifeLog/DBI-1.641/t/50dbm_simple.t deleted file mode 100755 index 4aa196c..0000000 --- a/dbLifeLog/DBI-1.641/t/50dbm_simple.t +++ /dev/null @@ -1,270 +0,0 @@ -#!perl -w -$|=1; - -use strict; -use warnings; - -require DBD::DBM; - -use File::Path; -use File::Spec; -use Test::More; -use Cwd; -use Config qw(%Config); -use Storable qw(dclone); - -my $using_dbd_gofer = ($ENV{DBI_AUTOPROXY}||'') =~ /^dbi:Gofer.*transport=/i; - -use DBI; -use vars qw( @mldbm_types @dbm_types ); - -BEGIN { - - # 0=SQL::Statement if avail, 1=DBI::SQL::Nano - # next line forces use of Nano rather than default behaviour - # $ENV{DBI_SQL_NANO}=1; - # This is done in zv*n*_50dbm_simple.t - - push @mldbm_types, ''; - if (eval { require 'MLDBM.pm'; }) { - push @mldbm_types, qw(Data::Dumper Storable); # both in CORE - push @mldbm_types, 'FreezeThaw' if eval { require 'FreezeThaw.pm' }; - push @mldbm_types, 'YAML' if eval { require MLDBM::Serializer::YAML; }; - push @mldbm_types, 'JSON' if eval { require MLDBM::Serializer::JSON; }; - } - - # Potential DBM modules in preference order (SDBM_File first) - # skip NDBM and ODBM as they don't support EXISTS - my @dbms = qw(SDBM_File GDBM_File DB_File BerkeleyDB NDBM_File ODBM_File); - my @use_dbms = @ARGV; - if( !@use_dbms && $ENV{DBD_DBM_TEST_BACKENDS} ) { - @use_dbms = split ' ', $ENV{DBD_DBM_TEST_BACKENDS}; - } - - if (lc "@use_dbms" eq "all") { - # test with as many of the major DBM types as are available - @dbm_types = grep { eval { local $^W; require "$_.pm" } } @dbms; - } - elsif (@use_dbms) { - @dbm_types = @use_dbms; - } - else { - # we only test SDBM_File by default to avoid tripping up - # on any broken DBM's that may be installed in odd places. - # It's only DBD::DBM we're trying to test here. - # (However, if SDBM_File is not available, then use another.) - for my $dbm (@dbms) { - if (eval { local $^W; require "$dbm.pm" }) { - @dbm_types = ($dbm); - last; - } - } - } - - if( eval { require List::MoreUtils; } ) - { - List::MoreUtils->import("part"); - } - else - { - # XXX from PP part of List::MoreUtils - eval <<'EOP'; -sub part(&@) { - my ($code, @list) = @_; - my @parts; - push @{ $parts[$code->($_)] }, $_ for @list; - return @parts; -} -EOP - } -} - -my $dbi_sql_nano = not DBD::DBM::Statement->isa('SQL::Statement'); - -do "./t/lib.pl"; - -my $dir = test_dir (); - -my %tests_statement_results = ( - 2 => [ - "DROP TABLE IF EXISTS fruit", -1, - "CREATE TABLE fruit (dKey INT, dVal VARCHAR(10))", '0E0', - "INSERT INTO fruit VALUES (1,'oranges' )", 1, - "INSERT INTO fruit VALUES (2,'to_change' )", 1, - "INSERT INTO fruit VALUES (3, NULL )", 1, - "INSERT INTO fruit VALUES (4,'to delete' )", 1, - "INSERT INTO fruit VALUES (?,?); #5,via placeholders", 1, - "INSERT INTO fruit VALUES (6,'to delete' )", 1, - "INSERT INTO fruit VALUES (7,'to_delete' )", 1, - "DELETE FROM fruit WHERE dVal='to delete'", 2, - "UPDATE fruit SET dVal='apples' WHERE dKey=2", 1, - "DELETE FROM fruit WHERE dKey=7", 1, - "SELECT * FROM fruit ORDER BY dKey DESC", [ - [ 5, 'via placeholders' ], - [ 3, '' ], - [ 2, 'apples' ], - [ 1, 'oranges' ], - ], - "DELETE FROM fruit", 4, - $dbi_sql_nano ? () : ( "SELECT COUNT(*) FROM fruit", [ [ 0 ] ] ), - "DROP TABLE fruit", -1, - ], - 3 => [ - "DROP TABLE IF EXISTS multi_fruit", -1, - "CREATE TABLE multi_fruit (dKey INT, dVal VARCHAR(10), qux INT)", '0E0', - "INSERT INTO multi_fruit VALUES (1,'oranges' , 11 )", 1, - "INSERT INTO multi_fruit VALUES (2,'to_change', 0 )", 1, - "INSERT INTO multi_fruit VALUES (3, NULL , 13 )", 1, - "INSERT INTO multi_fruit VALUES (4,'to_delete', 14 )", 1, - "INSERT INTO multi_fruit VALUES (?,?,?); #5,via placeholders,15", 1, - "INSERT INTO multi_fruit VALUES (6,'to_delete', 16 )", 1, - "INSERT INTO multi_fruit VALUES (7,'to delete', 17 )", 1, - "INSERT INTO multi_fruit VALUES (8,'to remove', 18 )", 1, - "UPDATE multi_fruit SET dVal='apples', qux='12' WHERE dKey=2", 1, - "DELETE FROM multi_fruit WHERE dVal='to_delete'", 2, - "DELETE FROM multi_fruit WHERE qux=17", 1, - "DELETE FROM multi_fruit WHERE dKey=8", 1, - "SELECT * FROM multi_fruit ORDER BY dKey DESC", [ - [ 5, 'via placeholders', 15 ], - [ 3, undef, 13 ], - [ 2, 'apples', 12 ], - [ 1, 'oranges', 11 ], - ], - "DELETE FROM multi_fruit", 4, - $dbi_sql_nano ? () : ( "SELECT COUNT(*) FROM multi_fruit", [ [ 0 ] ] ), - "DROP TABLE multi_fruit", -1, - ], -); - -print "Using DBM modules: @dbm_types\n"; -print "Using MLDBM serializers: @mldbm_types\n" if @mldbm_types; - -my %test_statements; -my %expected_results; - -for my $columns ( 2 .. 3 ) -{ - my $i = 0; - my @tests = part { $i++ % 2 } @{ $tests_statement_results{$columns} }; - @{ $test_statements{$columns} } = @{$tests[0]}; - @{ $expected_results{$columns} } = @{$tests[1]}; -} - -unless (@dbm_types) { - plan skip_all => "No DBM modules available"; -} - -for my $mldbm ( @mldbm_types ) { - my $columns = ($mldbm) ? 3 : 2; - for my $dbm_type ( @dbm_types ) { - print "\n--- Using $dbm_type ($mldbm) ---\n"; - eval { do_test( $dbm_type, $mldbm, $columns) } - or warn $@; - } -} - -done_testing(); - -sub do_test { - my ($dtype, $mldbm, $columns) = @_; - - #diag ("Starting test: " . $starting_test_no); - - # The DBI can't test locking here, sadly, because of the risk it'll hang - # on systems with broken NFS locking daemons. - # (This test script doesn't test that locking actually works anyway.) - - # use f_lockfile in next release - use it here as test case only - my $dsn ="dbi:DBM(RaiseError=0,PrintError=1):dbm_type=$dtype;dbm_mldbm=$mldbm;f_lockfile=.lck"; - - if ($using_dbd_gofer) { - $dsn .= ";f_dir=$dir"; - } - - my $dbh = DBI->connect( $dsn ); - - my $dbm_versions; - if ($DBI::VERSION >= 1.37 # needed for install_method - && !$ENV{DBI_AUTOPROXY} # can't transparently proxy driver-private methods - ) { - $dbm_versions = $dbh->dbm_versions; - } - else { - $dbm_versions = $dbh->func('dbm_versions'); - } - note $dbm_versions; - ok($dbm_versions, 'dbm_versions'); - isa_ok($dbh, 'DBI::db'); - - # test if it correctly accepts valid $dbh attributes - SKIP: { - skip "Can't set attributes after connect using DBD::Gofer", 2 - if $using_dbd_gofer; - eval {$dbh->{f_dir}=$dir}; - ok(!$@); - eval {$dbh->{dbm_mldbm}=$mldbm}; - ok(!$@); - } - - # test if it correctly rejects invalid $dbh attributes - # - eval { - local $SIG{__WARN__} = sub { } if $using_dbd_gofer; - local $dbh->{RaiseError} = 1; - local $dbh->{PrintError} = 0; - $dbh->{dbm_bad_name}=1; - }; - ok($@); - - my @queries = @{$test_statements{$columns}}; - my @results = @{$expected_results{$columns}}; - - SKIP: - for my $idx ( 0 .. $#queries ) { - my $sql = $queries[$idx]; - $sql =~ s/\S*fruit/${dtype}_fruit/; # include dbm type in table name - $sql =~ s/;$//; - #diag($sql); - - # XXX FIX INSERT with NULL VALUE WHEN COLUMN NOT NULLABLE - $dtype eq 'BerkeleyDB' and !$mldbm and 0 == index($sql, 'INSERT') and $sql =~ s/NULL/''/; - - $sql =~ s/\s*;\s*(?:#(.*))//; - my $comment = $1; - - my $sth = $dbh->prepare($sql); - ok($sth, "prepare $sql") or diag($dbh->errstr || 'unknown error'); - - my @bind; - if($sth->{NUM_OF_PARAMS}) - { - @bind = split /,/, $comment; - } - # if execute errors we will handle it, not PrintError: - $sth->{PrintError} = 0; - my $n = $sth->execute(@bind); - ok($n, 'execute') or diag($sth->errstr || 'unknown error'); - next if (!defined($n)); - - is( $n, $results[$idx], $sql ) unless( 'ARRAY' eq ref $results[$idx] ); - TODO: { - local $TODO = "AUTOPROXY drivers might throw away sth->rows()" if($ENV{DBI_AUTOPROXY}); - is( $n, $sth->rows, '$sth->execute(' . $sql . ') == $sth->rows' ) if( $sql =~ m/^(?:UPDATE|DELETE)/ ); - } - next unless $sql =~ /SELECT/; - my $results=''; - my $allrows = $sth->fetchall_arrayref(); - my $expected_rows = $results[$idx]; - is( $sth->rows, scalar( @{$expected_rows} ), $sql ); - is_deeply( $allrows, $expected_rows, 'SELECT results' ); - } - - my $sth = $dbh->table_info(); - ok ($sth, "prepare table_info (without tables)"); - my @tables = $sth->fetchall_arrayref; - is_deeply( \@tables, [ [] ], "No tables delivered by table_info" ); - - $dbh->disconnect; - return 1; -} -1; diff --git a/dbLifeLog/DBI-1.641/t/51dbm_file.t b/dbLifeLog/DBI-1.641/t/51dbm_file.t deleted file mode 100644 index d9824cf..0000000 --- a/dbLifeLog/DBI-1.641/t/51dbm_file.t +++ /dev/null @@ -1,186 +0,0 @@ -#!perl -w -$| = 1; - -use strict; -use warnings; - -use File::Copy (); -use File::Path; -use File::Spec (); -use Test::More; - -my $using_dbd_gofer = ( $ENV{DBI_AUTOPROXY} || '' ) =~ /^dbi:Gofer.*transport=/i; - -use DBI; - -do "./t/lib.pl"; - -my $dir = test_dir(); - -my $dbh = DBI->connect( 'dbi:DBM:', undef, undef, { - f_dir => $dir, - sql_identifier_case => 1, # SQL_IC_UPPER - } -); - -ok( $dbh->do(q/drop table if exists FRED/), 'drop table' ); - -my $dirfext = $^O eq 'VMS' ? '.sdbm_dir' : '.dir'; - -$dbh->do(q/create table fred (a integer, b integer)/); -ok( -f File::Spec->catfile( $dir, "FRED$dirfext" ), "FRED$dirfext exists" ); - -rmtree $dir; -mkpath $dir; - -if ($using_dbd_gofer) -{ - # can't modify attributes when connect through a Gofer instance - $dbh->disconnect(); - $dbh = DBI->connect( 'dbi:DBM:', undef, undef, { - f_dir => $dir, - sql_identifier_case => 2, # SQL_IC_LOWER - } - ); -} -else -{ - $dbh->dbm_clear_meta('fred'); # otherwise the col_names are still known! - $dbh->{sql_identifier_case} = 2; # SQL_IC_LOWER -} - -$dbh->do(q/create table FRED (a integer, b integer)/); -ok( -f File::Spec->catfile( $dir, "fred$dirfext" ), "fred$dirfext exists" ); - -my $tblfext; -unless( $using_dbd_gofer ) -{ - $tblfext = $dbh->{dbm_tables}->{fred}->{f_ext} || ''; - $tblfext =~ s{/r$}{}; - ok( -f File::Spec->catfile( $dir, "fred$tblfext" ), "fred$tblfext exists" ); -} - -ok( $dbh->do(q/insert into fRED (a,b) values(1,2)/), 'insert into mixed case table' ); - -# but change fRED to FRED and it works. - -ok( $dbh->do(q/insert into FRED (a,b) values(2,1)/), 'insert into uppercase table' ); - -unless ($using_dbd_gofer) -{ - my $fn_tbl2 = $dbh->{dbm_tables}->{fred}->{f_fqfn}; - $fn_tbl2 =~ s/fred(\.[^.]*)?$/freddy$1/; - my @dbfiles = grep { -f $_ } ( - $dbh->{dbm_tables}->{fred}->{f_fqfn}, - $dbh->{dbm_tables}->{fred}->{f_fqln}, - $dbh->{dbm_tables}->{fred}->{f_fqbn} . ".dir" - ); - foreach my $fn (@dbfiles) - { - my $tgt_fn = $fn; - $tgt_fn =~ s/fred(\.[^.]*)?$/freddy$1/; - File::Copy::copy( $fn, $tgt_fn ); - } - $dbh->{dbm_tables}->{krueger}->{file} = $fn_tbl2; - - my $r = $dbh->selectall_arrayref(q/select * from Krueger/); - ok( @$r == 2, 'rows found via cloned mixed case table' ); - - ok( $dbh->do(q/drop table if exists KRUeGEr/), 'drop table' ); -} - -my $r = $dbh->selectall_arrayref(q/select * from Fred/); -ok( @$r == 2, 'rows found via mixed case table' ); - -SKIP: -{ - DBD::DBM::Statement->isa("SQL::Statement") or skip("quoted identifiers aren't supported by DBI::SQL::Nano",1); - my $abs_tbl = File::Spec->catfile( $dir, 'fred' ); - # work around SQL::Statement bug - DBD::DBM::Statement->isa("SQL::Statement") and SQL::Statement->VERSION() lt "1.32" and $abs_tbl =~ s|\\|/|g; - $r = $dbh->selectall_arrayref( sprintf( q|select * from "%s"|, $abs_tbl ) ); - ok( @$r == 2, 'rows found via select via fully qualified path' ); -} - -if( $using_dbd_gofer ) -{ - ok( $dbh->do(q/drop table if exists FRED/), 'drop table' ); - ok( !-f File::Spec->catfile( $dir, "fred$dirfext" ), "fred$dirfext removed" ); -} -else -{ - my $tbl_info = { file => "fred$tblfext" }; - - ok( $dbh->disconnect(), "disconnect" ); - $dbh = DBI->connect( 'dbi:DBM:', undef, undef, { - f_dir => $dir, - sql_identifier_case => 2, # SQL_IC_LOWER - dbm_tables => { fred => $tbl_info }, - } - ); - - my @tbl; - @tbl = $dbh->tables (undef, undef, undef, undef); - is( scalar @tbl, 1, "Found 1 tables"); - - $r = $dbh->selectall_arrayref(q/select * from Fred/); - ok( @$r == 2, 'rows found after reconnect using "dbm_tables"' ); - - my $deep_dir = File::Spec->catdir( $dir, 'deep' ); - mkpath $deep_dir; - - $dbh = DBI->connect( 'dbi:DBM:', undef, undef, { - f_dir => $deep_dir, - sql_identifier_case => 2, # SQL_IC_LOWER - } - ); - ok( $dbh->do( q{create table wilma (a integer, b char (10))} ), "Create wilma" ); - ok( $dbh->do( q{insert into wilma values (1, 'Barney')} ), "insert Barney" ); - ok( $dbh->disconnect(), "disconnect" ); - - $dbh = DBI->connect( 'dbi:DBM:', undef, undef, { - f_dir => $dir, - sql_identifier_case => 2, # SQL_IC_LOWER - } - ); - - # Make sure wilma is not found without f_dir_search - @tbl = $dbh->tables (undef, undef, undef, undef); - is( scalar @tbl, 1, "Found 1 table"); - ok( $dbh->disconnect(), "disconnect" ); - - $dbh = DBI->connect( 'dbi:DBM:', undef, undef, { - f_dir => $dir, - f_dir_search => [ $deep_dir ], - sql_identifier_case => 2, # SQL_IC_LOWER - } - ); - - @tbl = $dbh->tables (undef, undef, undef, undef); - is( scalar @tbl, 2, "Found 2 tables"); - # f_dir should always appear before f_dir_search - like( $tbl[0], qr{(?:^|\.)fred$}i, "Fred first" ); - like( $tbl[1], qr{(?:^|\.)wilma$}i, "Fred second" ); - - my( $n, $sth ); - ok( $sth = $dbh->prepare( 'select * from fred' ), "select from fred" ); - ok( $sth->execute, "execute fred" ); - $n = 0; - $n++ while $sth->fetch; - is( $n, 2, "2 entry in fred" ); - ok( $sth = $dbh->prepare( 'select * from wilma' ), "select from wilma" ); - ok( $sth->execute, "execute wilma" ); - $n = 0; - $n++ while $sth->fetch; - is( $n, 1, "1 entry in wilma" ); - - ok( $dbh->do(q/drop table if exists FRED/), 'drop table fred' ); - ok( !-f File::Spec->catfile( $dir, "fred$dirfext" ), "fred$dirfext removed" ); - ok( !-f File::Spec->catfile( $dir, "fred$tblfext" ), "fred$tblfext removed" ); - - ok( $dbh->do(q/drop table if exists wilma/), 'drop table wilma' ); - ok( !-f File::Spec->catfile( $deep_dir, "wilma$dirfext" ), "wilma$dirfext removed" ); - ok( !-f File::Spec->catfile( $deep_dir, "wilma$tblfext" ), "wilma$tblfext removed" ); -} - -done_testing(); diff --git a/dbLifeLog/DBI-1.641/t/52dbm_complex.t b/dbLifeLog/DBI-1.641/t/52dbm_complex.t deleted file mode 100644 index d952813..0000000 --- a/dbLifeLog/DBI-1.641/t/52dbm_complex.t +++ /dev/null @@ -1,359 +0,0 @@ -#!perl -w -$| = 1; - -use strict; -use warnings; - -require DBD::DBM; - -use File::Path; -use File::Spec; -use Test::More; -use Cwd; -use Config qw(%Config); -use Storable qw(dclone); - -my $using_dbd_gofer = ( $ENV{DBI_AUTOPROXY} || '' ) =~ /^dbi:Gofer.*transport=/i; - -use DBI; -use vars qw( @mldbm_types @dbm_types ); - -BEGIN -{ - - # 0=SQL::Statement if avail, 1=DBI::SQL::Nano - # next line forces use of Nano rather than default behaviour - # $ENV{DBI_SQL_NANO}=1; - # This is done in zv*n*_50dbm_simple.t - - if ( eval { require 'MLDBM.pm'; } ) - { - push @mldbm_types, qw(Data::Dumper Storable); # both in CORE - push @mldbm_types, 'FreezeThaw' if eval { require 'FreezeThaw.pm' }; - push @mldbm_types, 'YAML' if eval { require MLDBM::Serializer::YAML; }; - push @mldbm_types, 'JSON' if eval { require MLDBM::Serializer::JSON; }; - } - - # Potential DBM modules in preference order (SDBM_File first) - # skip NDBM and ODBM as they don't support EXISTS - my @dbms = qw(SDBM_File GDBM_File DB_File BerkeleyDB NDBM_File ODBM_File); - my @use_dbms = @ARGV; - if ( !@use_dbms && $ENV{DBD_DBM_TEST_BACKENDS} ) - { - @use_dbms = split ' ', $ENV{DBD_DBM_TEST_BACKENDS}; - } - - if ( lc "@use_dbms" eq "all" ) - { - # test with as many of the major DBM types as are available - @dbm_types = grep { - eval { local $^W; require "$_.pm" } - } @dbms; - } - elsif (@use_dbms) - { - @dbm_types = @use_dbms; - } - else - { - # we only test SDBM_File by default to avoid tripping up - # on any broken DBM's that may be installed in odd places. - # It's only DBD::DBM we're trying to test here. - # (However, if SDBM_File is not available, then use another.) - for my $dbm (@dbms) - { - if ( eval { local $^W; require "$dbm.pm" } ) - { - @dbm_types = ($dbm); - last; - } - } - } - - if ( eval { require List::MoreUtils; } ) - { - List::MoreUtils->import("part"); - } - else - { - # XXX from PP part of List::MoreUtils - eval <<'EOP'; -sub part(&@) { - my ($code, @list) = @_; - my @parts; - push @{ $parts[$code->($_)] }, $_ for @list; - return @parts; -} -EOP - } -} - -my $haveSS = DBD::DBM::Statement->isa('SQL::Statement'); - -plan skip_all => "DBI::SQL::Nano is being used" unless ( $haveSS ); -plan skip_all => "Not running with MLDBM" unless ( @mldbm_types ); - -do "./t/lib.pl"; - -my $dir = test_dir (); - -my $dbh = DBI->connect( 'dbi:DBM:', undef, undef, { f_dir => $dir, } ); - -my $suffix; -my $tbl_meta; - -sub break_at_warn -{ - note "break here"; -} -$SIG{__WARN__} = \&break_at_warn; -$SIG{__DIE__} = \&break_at_warn; - -sub load_tables -{ - my ( $dbmtype, $dbmmldbm ) = @_; - my $last_suffix; - - if ($using_dbd_gofer) - { - $dbh->disconnect(); - $dbh = DBI->connect( "dbi:DBM:", undef, undef, { f_dir => $dir, dbm_type => $dbmtype, dbm_mldbm => $dbmmldbm } ); - } - else - { - $last_suffix = $suffix; - $dbh->{dbm_type} = $dbmtype; - $dbh->{dbm_mldbm} = $dbmmldbm; - } - - (my $serializer = $dbmmldbm ) =~ s/::/_/g; - $suffix = join( "_", $$, $dbmtype, $serializer ); - - if ($last_suffix) - { - for my $table (qw(APPL_%s PREC_%s NODE_%s LANDSCAPE_%s CONTACT_%s NM_LANDSCAPE_%s APPL_CONTACT_%s)) - { - my $readsql = sprintf "SELECT * FROM $table", $last_suffix; - my $impsql = sprintf "CREATE TABLE $table AS IMPORT (?)", $suffix; - my ($readsth); - ok( $readsth = $dbh->prepare($readsql), "prepare: $readsql" ); - ok( $readsth->execute(), "execute: $readsql" ); - ok( $dbh->do( $impsql, {}, $readsth ), $impsql ) or warn $dbh->errstr(); - } - } - else - { - for my $sql ( split( "\n", join( '', <<'EOD' ) ) ) -CREATE TABLE APPL_%s (id INT, applname CHAR, appluniq CHAR, version CHAR, appl_type CHAR) -CREATE TABLE PREC_%s (id INT, appl_id INT, node_id INT, precedence INT) -CREATE TABLE NODE_%s (id INT, nodename CHAR, os CHAR, version CHAR) -CREATE TABLE LANDSCAPE_%s (id INT, landscapename CHAR) -CREATE TABLE CONTACT_%s (id INT, surname CHAR, familyname CHAR, phone CHAR, userid CHAR, mailaddr CHAR) -CREATE TABLE NM_LANDSCAPE_%s (id INT, ls_id INT, obj_id INT, obj_type INT) -CREATE TABLE APPL_CONTACT_%s (id INT, contact_id INT, appl_id INT, contact_type CHAR) - -INSERT INTO APPL_%s VALUES ( 1, 'ZQF', 'ZFQLIN', '10.2.0.4', 'Oracle DB') -INSERT INTO APPL_%s VALUES ( 2, 'YRA', 'YRA-UX', '10.2.0.2', 'Oracle DB') -INSERT INTO APPL_%s VALUES ( 3, 'PRN1', 'PRN1-4.B2', '1.1.22', 'CUPS' ) -INSERT INTO APPL_%s VALUES ( 4, 'PRN2', 'PRN2-4.B2', '1.1.22', 'CUPS' ) -INSERT INTO APPL_%s VALUES ( 5, 'PRN1', 'PRN1-4.B1', '1.1.22', 'CUPS' ) -INSERT INTO APPL_%s VALUES ( 7, 'PRN2', 'PRN2-4.B1', '1.1.22', 'CUPS' ) -INSERT INTO APPL_%s VALUES ( 8, 'sql-stmt', 'SQL::Statement', '1.21', 'Project Web-Site') -INSERT INTO APPL_%s VALUES ( 9, 'cpan.org', 'http://www.cpan.org/', '1.0', 'Web-Site') -INSERT INTO APPL_%s VALUES (10, 'httpd', 'cpan-apache', '2.2.13', 'Web-Server') -INSERT INTO APPL_%s VALUES (11, 'cpan-mods', 'cpan-mods', '8.4.1', 'PostgreSQL DB') -INSERT INTO APPL_%s VALUES (12, 'cpan-authors', 'cpan-authors', '8.4.1', 'PostgreSQL DB') - -INSERT INTO NODE_%s VALUES ( 1, 'ernie', 'RHEL', '5.2') -INSERT INTO NODE_%s VALUES ( 2, 'bert', 'RHEL', '5.2') -INSERT INTO NODE_%s VALUES ( 3, 'statler', 'FreeBSD', '7.2') -INSERT INTO NODE_%s VALUES ( 4, 'waldorf', 'FreeBSD', '7.2') -INSERT INTO NODE_%s VALUES ( 5, 'piggy', 'NetBSD', '5.0.2') -INSERT INTO NODE_%s VALUES ( 6, 'kermit', 'NetBSD', '5.0.2') -INSERT INTO NODE_%s VALUES ( 7, 'samson', 'NetBSD', '5.0.2') -INSERT INTO NODE_%s VALUES ( 8, 'tiffy', 'NetBSD', '5.0.2') -INSERT INTO NODE_%s VALUES ( 9, 'rowlf', 'Debian Lenny', '5.0') -INSERT INTO NODE_%s VALUES (10, 'fozzy', 'Debian Lenny', '5.0') - -INSERT INTO PREC_%s VALUES ( 1, 1, 1, 1) -INSERT INTO PREC_%s VALUES ( 2, 1, 2, 2) -INSERT INTO PREC_%s VALUES ( 3, 2, 2, 1) -INSERT INTO PREC_%s VALUES ( 4, 2, 1, 2) -INSERT INTO PREC_%s VALUES ( 5, 3, 5, 1) -INSERT INTO PREC_%s VALUES ( 6, 3, 7, 2) -INSERT INTO PREC_%s VALUES ( 7, 4, 6, 1) -INSERT INTO PREC_%s VALUES ( 8, 4, 8, 2) -INSERT INTO PREC_%s VALUES ( 9, 5, 7, 1) -INSERT INTO PREC_%s VALUES (10, 5, 5, 2) -INSERT INTO PREC_%s VALUES (11, 6, 8, 1) -INSERT INTO PREC_%s VALUES (12, 7, 6, 2) -INSERT INTO PREC_%s VALUES (13, 10, 9, 1) -INSERT INTO PREC_%s VALUES (14, 10, 10, 1) -INSERT INTO PREC_%s VALUES (15, 8, 9, 1) -INSERT INTO PREC_%s VALUES (16, 8, 10, 1) -INSERT INTO PREC_%s VALUES (17, 9, 9, 1) -INSERT INTO PREC_%s VALUES (18, 9, 10, 1) -INSERT INTO PREC_%s VALUES (19, 11, 3, 1) -INSERT INTO PREC_%s VALUES (20, 11, 4, 2) -INSERT INTO PREC_%s VALUES (21, 12, 4, 1) -INSERT INTO PREC_%s VALUES (22, 12, 3, 2) - -INSERT INTO LANDSCAPE_%s VALUES (1, 'Logistic') -INSERT INTO LANDSCAPE_%s VALUES (2, 'Infrastructure') -INSERT INTO LANDSCAPE_%s VALUES (3, 'CPAN') - -INSERT INTO CONTACT_%s VALUES ( 1, 'Hans Peter', 'Mueller', '12345', 'HPMUE', 'hp-mueller@here.com') -INSERT INTO CONTACT_%s VALUES ( 2, 'Knut', 'Inge', '54321', 'KINGE', 'k-inge@here.com') -INSERT INTO CONTACT_%s VALUES ( 3, 'Lola', 'Nguyen', '+1-123-45678-90', 'LNYUG', 'lola.ngyuen@customer.com') -INSERT INTO CONTACT_%s VALUES ( 4, 'Helge', 'Brunft', '+41-123-45678-09', 'HBRUN', 'helge.brunft@external-dc.at') - --- TYPE: 1: APPL 2: NODE 3: CONTACT -INSERT INTO NM_LANDSCAPE_%s VALUES ( 1, 1, 1, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES ( 2, 1, 2, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES ( 3, 3, 3, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES ( 4, 3, 4, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES ( 5, 2, 5, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES ( 6, 2, 6, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES ( 7, 2, 7, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES ( 8, 2, 8, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES ( 9, 3, 9, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES (10, 3,10, 2) -INSERT INTO NM_LANDSCAPE_%s VALUES (11, 1, 1, 1) -INSERT INTO NM_LANDSCAPE_%s VALUES (12, 2, 2, 1) -INSERT INTO NM_LANDSCAPE_%s VALUES (13, 2, 2, 3) -INSERT INTO NM_LANDSCAPE_%s VALUES (14, 3, 1, 3) - -INSERT INTO APPL_CONTACT_%s VALUES (1, 3, 1, 'OWNER') -INSERT INTO APPL_CONTACT_%s VALUES (2, 3, 2, 'OWNER') -INSERT INTO APPL_CONTACT_%s VALUES (3, 4, 3, 'ADMIN') -INSERT INTO APPL_CONTACT_%s VALUES (4, 4, 4, 'ADMIN') -INSERT INTO APPL_CONTACT_%s VALUES (5, 4, 5, 'ADMIN') -INSERT INTO APPL_CONTACT_%s VALUES (6, 4, 6, 'ADMIN') -EOD - { - chomp $sql; - $sql =~ s/^\s+//; - $sql =~ s/--.*$//; - $sql =~ s/\s+$//; - next if ( '' eq $sql ); - $sql = sprintf $sql, $suffix; - ok( $dbh->do($sql), $sql ); - } - } - - for my $table (qw(APPL_%s PREC_%s NODE_%s LANDSCAPE_%s CONTACT_%s NM_LANDSCAPE_%s APPL_CONTACT_%s)) - { - my $tbl_name = lc sprintf($table, $suffix); - $tbl_meta->{$tbl_name} = { dbm_type => $dbmtype, dbm_mldbm => $dbmmldbm }; - } - - unless ($using_dbd_gofer) - { - my $tbl_known_meta = $dbh->dbm_get_meta( "+", [ qw(dbm_type dbm_mldbm) ] ); - is_deeply( $tbl_known_meta, $tbl_meta, "Know meta" ); - } -} - -sub do_tests -{ - my ( $dbmtype, $serializer ) = @_; - - note "Running do_tests for $dbmtype + $serializer"; - - load_tables( $dbmtype, $serializer ); - - my %joins; - my $sql; - - $sql = join( " ", - q{SELECT applname, appluniq, version, nodename }, - sprintf( q{FROM APPL_%s, PREC_%s, NODE_%s }, ($suffix) x 3 ), - sprintf( q{WHERE appl_type LIKE '%%DB' AND APPL_%s.id=PREC_%s.appl_id AND}, ($suffix) x 2 ), - sprintf( q{PREC_%s.node_id=NODE_%s.id}, ($suffix) x 2 ), - ); - - $joins{$sql} = [ - 'ZQF~ZFQLIN~10.2.0.4~ernie', 'ZQF~ZFQLIN~10.2.0.4~bert', - 'YRA~YRA-UX~10.2.0.2~bert', 'YRA~YRA-UX~10.2.0.2~ernie', - 'cpan-mods~cpan-mods~8.4.1~statler', 'cpan-mods~cpan-mods~8.4.1~waldorf', - 'cpan-authors~cpan-authors~8.4.1~waldorf', 'cpan-authors~cpan-authors~8.4.1~statler', - ]; - - $sql = join( " ", - q{SELECT applname, appluniq, version, landscapename, nodename}, - sprintf( q{FROM APPL_%s, PREC_%s, NODE_%s, LANDSCAPE_%s, NM_LANDSCAPE_%s}, ($suffix) x 5 ), - sprintf( q{WHERE appl_type LIKE '%%DB' AND APPL_%s.id=PREC_%s.appl_id AND}, ($suffix) x 2 ), - sprintf( q{PREC_%s.node_id=NODE_%s.id AND NM_LANDSCAPE_%s.obj_id=APPL_%s.id AND}, ($suffix) x 4 ), - sprintf( q{NM_LANDSCAPE_%s.obj_type=1 AND NM_LANDSCAPE_%s.ls_id=LANDSCAPE_%s.id}, ($suffix) x 3 ), - ); - $joins{$sql} = [ - 'ZQF~ZFQLIN~10.2.0.4~Logistic~ernie', 'ZQF~ZFQLIN~10.2.0.4~Logistic~bert', - 'YRA~YRA-UX~10.2.0.2~Infrastructure~bert', 'YRA~YRA-UX~10.2.0.2~Infrastructure~ernie', - ]; - $sql = join( " ", - q{SELECT applname, appluniq, version, surname, familyname, phone, nodename}, - sprintf( q{FROM APPL_%s, PREC_%s, NODE_%s, CONTACT_%s, APPL_CONTACT_%s}, ($suffix) x 5 ), - sprintf( q{WHERE appl_type='CUPS' AND APPL_%s.id=PREC_%s.appl_id AND}, ($suffix) x 2 ), - sprintf( q{PREC_%s.node_id=NODE_%s.id AND APPL_CONTACT_%s.appl_id=APPL_%s.id AND}, ($suffix) x 4 ), - sprintf( q{APPL_CONTACT_%s.contact_id=CONTACT_%s.id AND PREC_%s.PRECEDENCE=1}, ($suffix) x 3 ), - ); - $joins{$sql} = [ - 'PRN1~PRN1-4.B2~1.1.22~Helge~Brunft~+41-123-45678-09~piggy', - 'PRN2~PRN2-4.B2~1.1.22~Helge~Brunft~+41-123-45678-09~kermit', - 'PRN1~PRN1-4.B1~1.1.22~Helge~Brunft~+41-123-45678-09~samson', - ]; - $sql = join( " ", - q{SELECT DISTINCT applname, appluniq, version, surname, familyname, phone, nodename}, - sprintf( q{FROM APPL_%s, PREC_%s, NODE_%s, CONTACT_%s, APPL_CONTACT_%s}, ($suffix) x 5 ), - sprintf( q{WHERE appl_type='CUPS' AND APPL_%s.id=PREC_%s.appl_id AND}, ($suffix) x 2 ), - sprintf( q{PREC_%s.node_id=NODE_%s.id AND APPL_CONTACT_%s.appl_id=APPL_%s.id}, ($suffix) x 4 ), - sprintf( q{AND APPL_CONTACT_%s.contact_id=CONTACT_%s.id}, ($suffix) x 2 ), - ); - $joins{$sql} = [ - 'PRN1~PRN1-4.B1~1.1.22~Helge~Brunft~+41-123-45678-09~piggy', - 'PRN1~PRN1-4.B2~1.1.22~Helge~Brunft~+41-123-45678-09~piggy', - 'PRN1~PRN1-4.B1~1.1.22~Helge~Brunft~+41-123-45678-09~samson', - 'PRN1~PRN1-4.B2~1.1.22~Helge~Brunft~+41-123-45678-09~samson', - 'PRN2~PRN2-4.B2~1.1.22~Helge~Brunft~+41-123-45678-09~kermit', - 'PRN2~PRN2-4.B2~1.1.22~Helge~Brunft~+41-123-45678-09~tiffy', - ]; - $sql = join( " ", - q{SELECT CONCAT('[% NOW %]') AS "timestamp", applname, appluniq, version, nodename}, - sprintf( q{FROM APPL_%s, PREC_%s, NODE_%s}, ($suffix) x 3 ), - sprintf( q{WHERE appl_type LIKE '%%DB' AND APPL_%s.id=PREC_%s.appl_id AND}, ($suffix) x 2 ), - sprintf( q{PREC_%s.node_id=NODE_%s.id}, ($suffix) x 2 ), - ); - $joins{$sql} = [ - '[% NOW %]~ZQF~ZFQLIN~10.2.0.4~ernie', - '[% NOW %]~ZQF~ZFQLIN~10.2.0.4~bert', - '[% NOW %]~YRA~YRA-UX~10.2.0.2~bert', - '[% NOW %]~YRA~YRA-UX~10.2.0.2~ernie', - '[% NOW %]~cpan-mods~cpan-mods~8.4.1~statler', - '[% NOW %]~cpan-mods~cpan-mods~8.4.1~waldorf', - '[% NOW %]~cpan-authors~cpan-authors~8.4.1~waldorf', - '[% NOW %]~cpan-authors~cpan-authors~8.4.1~statler', - ]; - - while ( my ( $sql, $result ) = each(%joins) ) - { - my $sth = $dbh->prepare($sql); - eval { $sth->execute() }; - warn $@ if $@; - my @res; - while ( my $row = $sth->fetchrow_arrayref() ) - { - push( @res, join( '~', @{$row} ) ); - } - is( join( '^', sort @res ), join( '^', sort @{$result} ), $sql ); - } -} - -foreach my $dbmtype (@dbm_types) -{ - foreach my $serializer (@mldbm_types) - { - do_tests( $dbmtype, $serializer ); - } -} - -done_testing(); diff --git a/dbLifeLog/DBI-1.641/t/53sqlengine_adv.t b/dbLifeLog/DBI-1.641/t/53sqlengine_adv.t deleted file mode 100644 index 6971729..0000000 --- a/dbLifeLog/DBI-1.641/t/53sqlengine_adv.t +++ /dev/null @@ -1,49 +0,0 @@ -#!perl -w -$| = 1; - -use strict; -use warnings; - -require DBD::DBM; - -use File::Path; -use File::Spec; -use Test::More; -use Cwd; -use Config qw(%Config); -use Storable qw(dclone); - -my $using_dbd_gofer = ( $ENV{DBI_AUTOPROXY} || '' ) =~ /^dbi:Gofer.*transport=/i; -plan skip_all => "Modifying driver state won't compute running behind Gofer" if($using_dbd_gofer); - -use DBI; - -# <[Sno]> what I could do is create a new test case where inserting into a DBD::DBM and after that clone the meta into a DBD::File $dbh -# <[Sno]> would that help to get a better picture? - -do "./t/lib.pl"; -my $dir = test_dir(); - -my $dbm_dbh = DBI->connect( 'dbi:DBM:', undef, undef, { - f_dir => $dir, - sql_identifier_case => 2, # SQL_IC_LOWER - } -); - -$dbm_dbh->do(q/create table FRED (a integer, b integer)/); -$dbm_dbh->do(q/insert into fRED (a,b) values(1,2)/); -$dbm_dbh->do(q/insert into FRED (a,b) values(2,1)/); - -my $f_dbh = DBI->connect( 'dbi:File:', undef, undef, { - f_dir => $dir, - sql_identifier_case => 2, # SQL_IC_LOWER - } -); - -my $dbm_fred_meta = $dbm_dbh->f_get_meta("fred", [qw(dbm_type)]); -$f_dbh->f_new_meta( "fred", {sql_table_class => "DBD::DBM::Table"} ); - -my $r = $f_dbh->selectall_arrayref(q/select * from Fred/); -ok( @$r == 2, 'rows found via mixed case table' ); - -done_testing(); diff --git a/dbLifeLog/DBI-1.641/t/54_dbd_mem.t b/dbLifeLog/DBI-1.641/t/54_dbd_mem.t deleted file mode 100644 index b680ab1..0000000 --- a/dbLifeLog/DBI-1.641/t/54_dbd_mem.t +++ /dev/null @@ -1,41 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use Cwd; -use File::Path; -use File::Spec; -use Test::More; - -my $using_dbd_gofer = ($ENV{DBI_AUTOPROXY}||"") =~ /^dbi:Gofer.*transport=/i; -$using_dbd_gofer and plan skip_all => "modifying meta data doesn't work with Gofer-AutoProxy"; - -my $tbl; -BEGIN { $tbl = "db_". $$ . "_" }; -#END { $tbl and unlink glob "${tbl}*" } - -use_ok ("DBI"); -use_ok ("DBD::Mem"); - -my $dbh = DBI->connect( "DBI:Mem:", undef, undef, { PrintError => 0, RaiseError => 0, } ); # Can't use DBI::DBD::SqlEngine direct - -for my $sql ( split "\n", <<"" ) - CREATE TABLE foo (id INT, foo TEXT) - CREATE TABLE bar (id INT, baz TEXT) - INSERT INTO foo VALUES (1, 'Hello world') - INSERT INTO bar VALUES (1, 'Bugfixes welcome') - INSERT bar VALUES (2, 'Bug reports, too') - SELECT foo FROM foo where ID=1 - UPDATE bar SET id=5 WHERE baz='Bugfixes welcome' - DELETE FROM foo - DELETE FROM bar WHERE baz='Bugfixes welcome' - -{ - my $done; - $sql =~ s/^\s+//; - eval { $done = $dbh->do( $sql ); }; - ok( $done, "executed '$sql'" ) or diag $dbh->errstr; -} - -done_testing (); diff --git a/dbLifeLog/DBI-1.641/t/60preparse.t b/dbLifeLog/DBI-1.641/t/60preparse.t deleted file mode 100755 index 6432feb..0000000 --- a/dbLifeLog/DBI-1.641/t/60preparse.t +++ /dev/null @@ -1,148 +0,0 @@ -#!perl -w - -use DBI qw(:preparse_flags); - -$|=1; - -use Test::More; - -BEGIN { - if ($DBI::PurePerl) { - plan skip_all => 'preparse not supported for DBI::PurePerl'; - } - else { - plan tests => 39; - } -} - -my $dbh = DBI->connect("dbi:ExampleP:", "", "", { - PrintError => 0, -}); -isa_ok( $dbh, 'DBI::db' ); - -sub pp { - my $dbh = shift; - my $rv = $dbh->preparse(@_); - return $rv; -} - -# --------------------------------------------------------------------- # -# DBIpp_cm_cs /* C style */ -# DBIpp_cm_hs /* # */ -# DBIpp_cm_dd /* -- */ -# DBIpp_cm_br /* {} */ -# DBIpp_cm_dw /* '-- ' dash dash whitespace */ -# DBIpp_cm_XX /* any of the above */ - -# DBIpp_ph_qm /* ? */ -# DBIpp_ph_cn /* :1 */ -# DBIpp_ph_cs /* :name */ -# DBIpp_ph_sp /* %s (as return only, not accept) */ -# DBIpp_ph_XX /* any of the above */ - -# DBIpp_st_qq /* '' char escape */ -# DBIpp_st_bs /* \ char escape */ -# DBIpp_st_XX /* any of the above */ - -# ===================================================================== # -# pp (h input return accept expected) # -# ===================================================================== # - -## Comments: - -is( pp($dbh, "a#b\nc", DBIpp_cm_cs, DBIpp_cm_hs), "a/*b*/\nc" ); -is( pp($dbh, "a#b\nc", DBIpp_cm_dw, DBIpp_cm_hs), "a-- b\nc" ); -is( pp($dbh, "a/*b*/c", DBIpp_cm_hs, DBIpp_cm_cs), "a#b\nc" ); -is( pp($dbh, "a{b}c", DBIpp_cm_cs, DBIpp_cm_br), "a/*b*/c" ); -is( pp($dbh, "a--b\nc", DBIpp_cm_br, DBIpp_cm_dd), "a{b}\nc" ); - -is( pp($dbh, "a-- b\n/*c*/d", DBIpp_cm_br, DBIpp_cm_cs|DBIpp_cm_dw), "a{ b}\n{c}d" ); -is( pp($dbh, "a/*b*/c#d\ne--f\nh-- i\nj{k}", 0, DBIpp_cm_XX), "a c\ne\nh\nj " ); - -## Placeholders: - -is( pp($dbh, "a = :1", DBIpp_ph_qm, DBIpp_ph_cn), "a = ?" ); -is( pp($dbh, "a = :1", DBIpp_ph_sp, DBIpp_ph_cn), "a = %s" ); -is( pp($dbh, "a = ?" , DBIpp_ph_cn, DBIpp_ph_qm), "a = :p1" ); -is( pp($dbh, "a = ?" , DBIpp_ph_sp, DBIpp_ph_qm), "a = %s" ); - -is( pp($dbh, "a = :name", DBIpp_ph_qm, DBIpp_ph_cs), "a = ?" ); -is( pp($dbh, "a = :name", DBIpp_ph_sp, DBIpp_ph_cs), "a = %s" ); - -is( pp($dbh, "a = ? b = ? c = ?", DBIpp_ph_cn, DBIpp_ph_XX), "a = :p1 b = :p2 c = :p3" ); - -## Placeholders inside comments (should be ignored where comments style is accepted): - -is( pp( $dbh, - "a = ? /*b = :1*/ c = ?", - DBIpp_cm_dw|DBIpp_ph_cn, - DBIpp_cm_cs|DBIpp_ph_qm), - "a = :p1 -- b = :1\n c = :p2" ); - -## Placeholders inside single and double quotes (should be ignored): - -is( pp( $dbh, - "a = ? 'b = :1' c = ?", - DBIpp_ph_cn, - DBIpp_ph_XX), - "a = :p1 'b = :1' c = :p2" ); - -is( pp( $dbh, - 'a = ? "b = :1" c = ?', - DBIpp_ph_cn, - DBIpp_ph_XX), - 'a = :p1 "b = :1" c = :p2' ); - -## Comments inside single and double quotes (should be ignored): - -is( pp( $dbh, - "a = ? '{b = :1}' c = ?", - DBIpp_cm_cs|DBIpp_ph_cn, - DBIpp_cm_XX|DBIpp_ph_qm), - "a = :p1 '{b = :1}' c = :p2" ); - -is( pp( $dbh, - 'a = ? "/*b = :1*/" c = ?', - DBIpp_cm_dw|DBIpp_ph_cn, - DBIpp_cm_XX|DBIpp_ph_qm), - 'a = :p1 "/*b = :1*/" c = :p2' ); - -## Single and double quoted strings starting inside comments (should be ignored): - -is( pp( $dbh, - 'a = ? /*"b = :1 */ c = ?', - DBIpp_cm_br|DBIpp_ph_cn, - DBIpp_cm_XX|DBIpp_ph_qm), - 'a = :p1 {"b = :1 } c = :p2' ); - -## Check error conditions are trapped: - -is( pp($dbh, "a = :value and b = :1", DBIpp_ph_qm, DBIpp_ph_cs|DBIpp_ph_cn), undef ); -ok( $DBI::err ); -is( $DBI::errstr, "preparse found mixed placeholder styles (:1 / :name)" ); - -is( pp($dbh, "a = :1 and b = :3", DBIpp_ph_qm, DBIpp_ph_cn), undef ); -ok( $DBI::err ); -is( $DBI::errstr, "preparse found placeholder :3 out of sequence, expected :2" ); - -is( pp($dbh, "foo ' comment", 0, 0), "foo ' comment" ); -ok( $DBI::err ); -is( $DBI::errstr, "preparse found unterminated single-quoted string" ); - -is( pp($dbh, 'foo " comment', 0, 0), 'foo " comment' ); -ok( $DBI::err ); -is( $DBI::errstr, "preparse found unterminated double-quoted string" ); - -is( pp($dbh, 'foo /* comment', DBIpp_cm_XX, DBIpp_cm_XX), 'foo /* comment' ); -ok( $DBI::err ); -is( $DBI::errstr, "preparse found unterminated bracketed C-style comment" ); - -is( pp($dbh, 'foo { comment', DBIpp_cm_XX, DBIpp_cm_XX), 'foo { comment' ); -ok( $DBI::err ); -is( $DBI::errstr, "preparse found unterminated bracketed {...} comment" ); - -# --------------------------------------------------------------------- # - -$dbh->disconnect; - -1; diff --git a/dbLifeLog/DBI-1.641/t/65transact.t b/dbLifeLog/DBI-1.641/t/65transact.t deleted file mode 100644 index f3d672b..0000000 --- a/dbLifeLog/DBI-1.641/t/65transact.t +++ /dev/null @@ -1,35 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -use DBI; - -use Test::More; - -plan skip_all => 'Transactions not supported by DBD::Gofer' - if $ENV{DBI_AUTOPROXY} && $ENV{DBI_AUTOPROXY} =~ /^dbi:Gofer/i; - -plan tests => 10; - -my $dbh = DBI->connect('dbi:ExampleP(AutoCommit=>1):', undef, undef) - or die "Unable to connect to ExampleP driver: $DBI::errstr"; - -print "begin_work...\n"; -ok($dbh->{AutoCommit}); -ok(!$dbh->{BegunWork}); - -ok($dbh->begin_work); -ok(!$dbh->{AutoCommit}); -ok($dbh->{BegunWork}); - -$dbh->commit; -ok($dbh->{AutoCommit}); -ok(!$dbh->{BegunWork}); - -ok($dbh->begin_work({})); -$dbh->rollback; -ok($dbh->{AutoCommit}); -ok(!$dbh->{BegunWork}); - -1; diff --git a/dbLifeLog/DBI-1.641/t/70callbacks.t b/dbLifeLog/DBI-1.641/t/70callbacks.t deleted file mode 100644 index 40903f9..0000000 --- a/dbLifeLog/DBI-1.641/t/70callbacks.t +++ /dev/null @@ -1,252 +0,0 @@ -#!perl -w -# vim:ts=8:sw=4 - -use strict; - -use Test::More; -use DBI; - -BEGIN { - plan skip_all => '$h->{Callbacks} attribute not supported for DBI::PurePerl' - if $DBI::PurePerl && $DBI::PurePerl; # doubled to avoid typo warning -} - -$| = 1; -my $dsn = "dbi:ExampleP:drv_foo=drv_bar"; -my %called; - -ok my $dbh = DBI->connect($dsn, '', ''), "Create dbh"; - -is $dbh->{Callbacks}, undef, "Callbacks initially undef"; -ok $dbh->{Callbacks} = my $cb = { }; -is ref $dbh->{Callbacks}, 'HASH', "Callbacks can be set to a hash ref"; -is $dbh->{Callbacks}, $cb, "Callbacks set to same hash ref"; - -$dbh->{Callbacks} = undef; -is $dbh->{Callbacks}, undef, "Callbacks set to undef again"; - -ok $dbh->{Callbacks} = { - ping => sub { - my $m = $_; - is $m, 'ping', '$m holds method name'; - is $_, 'ping', '$_ holds method name (not stolen)'; - is @_, 1, '@_ holds 1 values'; - is ref $_[0], 'DBI::db', 'first is $dbh'; - ok tied(%{$_[0]}), '$dbh is tied (outer) handle' - or DBI::dump_handle($_[0], 'tied?', 10); - $called{$_}++; - return; - }, - quote_identifier => sub { - is @_, 4, '@_ holds 4 values'; - my $dbh = shift; - is ref $dbh, 'DBI::db', 'first is $dbh'; - is $_[0], 'foo'; - is $_[1], 'bar'; - is $_[2], undef; - $_[2] = { baz => 1 }; - $called{$_}++; - return (1,2,3); # return something - which is not allowed - }, - disconnect => sub { # test die from within a callback - die "You can't disconnect that easily!\n"; - }, - "*" => sub { - $called{$_}++; - return; - } -}; -is keys %{ $dbh->{Callbacks} }, 4; - -is ref $dbh->{Callbacks}->{ping}, 'CODE'; - -$_ = 42; -ok $dbh->ping; -is $called{ping}, 1; -is $_, 42, '$_ not altered by callback'; - -ok $dbh->ping; -is $called{ping}, 2; - -ok $dbh->type_info_all; -is $called{type_info_all}, 1, 'fallback callback'; - -my $attr; -eval { $dbh->quote_identifier('foo','bar', $attr) }; -is $called{quote_identifier}, 1; -ok $@, 'quote_identifier callback caused fatal error'; -is ref $attr, 'HASH', 'param modified by callback - not recommended!'; - -ok !eval { $dbh->disconnect }; -ok $@, "You can't disconnect that easily!\n"; - -$dbh->{Callbacks} = undef; -ok $dbh->ping; -is $called{ping}, 2; # no change - - -# --- test skipping dispatch and fallback callbacks - -$dbh->{Callbacks} = { - ping => sub { - undef $_; # tell dispatch to not call the method - return "42 bells"; - }, - data_sources => sub { - my ($h, $values_to_return) = @_; - undef $_; # tell dispatch to not call the method - my @ret = 11..10+($values_to_return||0); - return @ret; - }, - commit => sub { # test using set_err within a callback - my $h = shift; - undef $_; # tell dispatch to not call the method - return $h->set_err(42, "faked commit failure"); - }, -}; - -# these tests are slightly convoluted because messing with the stack is bad for -# your mental health -my $rv = $dbh->ping; -is $rv, "42 bells"; -my @rv = $dbh->ping; -is scalar @rv, 1, 'should return a single value in list context'; -is "@rv", "42 bells"; -# test returning lists with different number of args to test -# the stack handling in the dispatch code -is join(":", $dbh->data_sources()), ""; -is join(":", $dbh->data_sources(0)), ""; -is join(":", $dbh->data_sources(1)), "11"; -is join(":", $dbh->data_sources(2)), "11:12"; - -{ -local $dbh->{RaiseError} = 1; -local $dbh->{PrintError} = 0; -is eval { $dbh->commit }, undef, 'intercepted commit should return undef'; -like $@, '/DBD::\w+::db commit failed: faked commit failure/'; -is $DBI::err, 42; -is $DBI::errstr, "faked commit failure"; -} - -# --- test connect_cached.* - -=for comment XXX - -The big problem here is that conceptually the Callbacks attribute -is applied to the $dbh _during_ the $drh->connect() call, so you can't -set a callback on "connect" on the $dbh because connect isn't called -on the dbh, but on the $drh. - -So a "connect" callback would have to be defined on the $drh, but that's -cumbersome for the user and then it would apply to all future connects -using that driver. - -The best thing to do is probably to special-case "connect", "connect_cached" -and (the already special-case) "connect_cached.reused". - -=cut - -my $driver_dsn = (DBI->parse_dsn($dsn))[4] or die 'panic'; - -my @args = ( - $dsn, 'u', 'p', { - Callbacks => { - "connect_cached.new" => sub { - my ($dbh, $cb_dsn, $user, $auth, $attr) = @_; - ok tied(%$dbh), 'connect_cached.new $h is tied (outer) handle' - if $dbh; # $dbh is typically undef or a dead/disconnected $dbh - like $cb_dsn, qr/\Q$driver_dsn/, 'dsn'; - is $user, 'u', 'user'; - is $auth, 'p', 'pass'; - $called{new}++; - return; - }, - "connect_cached.reused" => sub { - my ($dbh, $cb_dsn, $user, $auth, $attr) = @_; - ok tied(%$dbh), 'connect_cached.reused $h is tied (outer) handle'; - like $cb_dsn, qr/\Q$driver_dsn/, 'dsn'; - is $user, 'u', 'user'; - is $auth, 'p', 'pass'; - $called{cached}++; - return; - }, - "connect_cached.connected" => sub { - my ($dbh, $cb_dsn, $user, $auth, $attr) = @_; - ok tied(%$dbh), 'connect_cached.connected $h is tied (outer) handle'; - like $cb_dsn, qr/\Q$driver_dsn/, 'dsn'; - is $user, 'u', 'user'; - is $auth, 'p', 'pass'; - $called{connected}++; - return; - }, - } - } -); - -%called = (); - -ok $dbh = DBI->connect(@args), "Create handle with callbacks"; -is keys %called, 0, 'no callback for plain connect'; - -ok $dbh = DBI->connect_cached(@args), "Create handle with callbacks"; -is $called{new}, 1, "connect_cached.new called"; -is $called{cached}, undef, "connect_cached.reused not yet called"; -is $called{connected}, 1, "connect_cached.connected called"; - -ok $dbh = DBI->connect_cached(@args), "Create handle with callbacks"; -is $called{cached}, 1, "connect_cached.reused called"; -is $called{new}, 1, "connect_cached.new not called again"; -is $called{connected}, 1, "connect_cached.connected not called called"; - - -# --- test ChildCallbacks. -%called = (); -$args[-1] = { - Callbacks => my $dbh_callbacks = { - ping => sub { $called{ping}++; return; }, - ChildCallbacks => my $sth_callbacks = { - execute => sub { $called{execute}++; return; }, - fetch => sub { $called{fetch}++; return; }, - } - } -}; - -ok $dbh = DBI->connect(@args), "Create handle with ChildCallbacks"; -ok $dbh->ping, 'Ping'; -is $called{ping}, 1, 'Ping callback should have been called'; -ok my $sth = $dbh->prepare('SELECT name from t'), 'Prepare a statement handle (child)'; -ok $sth->{Callbacks}, 'child should have Callbacks'; -is $sth->{Callbacks}, $sth_callbacks, "child Callbacks should be ChildCallbacks of parent" - or diag "(dbh Callbacks is $dbh_callbacks)"; -ok $sth->execute, 'Execute'; -is $called{execute}, 1, 'Execute callback should have been called'; -ok $sth->fetch, 'Fetch'; -is $called{fetch}, 1, 'Fetch callback should have been called'; - -# stress test for stack reallocation and mark handling -- RT#86744 -my $stress_count = 3000; -my $place_holders = join(',', ('?') x $stress_count); -my @params = ('t') x $stress_count; -my $stress_dbh = DBI->connect( 'DBI:NullP:test'); -my $stress_sth = $stress_dbh->prepare("select 1"); -$stress_sth->{Callbacks}{execute} = sub { return; }; -$stress_sth->execute(@params); - - -done_testing(); - -__END__ - -A generic 'transparent' callback looks like this: -(this assumes only scalar context will be used) - - sub { - my $h = shift; - return if our $avoid_deep_recursion->{"$h $_"}++; - my $this = $h->$_(@_); - undef $_; # tell DBI not to call original method - return $this; # tell DBI to return this instead - }; - -XXX should add a test for this -XXX even better would be to run chunks of the test suite with that as a '*' callback. In theory everything should pass (except this test file, naturally).. diff --git a/dbLifeLog/DBI-1.641/t/72childhandles.t b/dbLifeLog/DBI-1.641/t/72childhandles.t deleted file mode 100644 index 48fbe37..0000000 --- a/dbLifeLog/DBI-1.641/t/72childhandles.t +++ /dev/null @@ -1,149 +0,0 @@ -#!perl -w -$|=1; - -use strict; - -# -# test script for the ChildHandles attribute -# - -use DBI; - -use Test::More; - -my $HAS_WEAKEN = eval { - require Scalar::Util; - # this will croak() if this Scalar::Util doesn't have a working weaken(). - Scalar::Util::weaken( my $test = [] ); # same test as in DBI.pm - 1; -}; -if (!$HAS_WEAKEN) { - chomp $@; - print "1..0 # Skipped: Scalar::Util::weaken not available ($@)\n"; - exit 0; -} - -plan tests => 16; - -my $using_dbd_gofer = ($ENV{DBI_AUTOPROXY}||'') =~ /^dbi:Gofer.*transport=/i; - -my $drh; - -{ - # make 10 connections - my @dbh; - for (1 .. 10) { - my $dbh = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1 }); - push @dbh, $dbh; - } - - # get the driver handle - $drh = $dbh[0]->{Driver}; - ok $drh; - - # get the kids, should be the same list of connections - my $db_handles = $drh->{ChildHandles}; - is ref $db_handles, 'ARRAY'; - is scalar @$db_handles, scalar @dbh; - - # make sure all the handles are there - my $found = 0; - foreach my $h (@dbh) { - ++$found if grep { $h == $_ } @$db_handles; - } - is $found, scalar @dbh; -} - -# now all the out-of-scope DB handles should be gone -{ - my $handles = $drh->{ChildHandles}; - my @db_handles = grep { defined } @$handles; - is scalar @db_handles, 0, "All handles should be undef now"; -} - -my $dbh = DBI->connect("dbi:ExampleP:", '', '', { RaiseError=>1 }); - -my $empty = $dbh->{ChildHandles}; -is_deeply $empty, [], "ChildHandles should be an array-ref if wekref is available"; - -# test child handles for statement handles -{ - my @sth; - my $sth_count = 20; - for (1 .. $sth_count) { - my $sth = $dbh->prepare('SELECT name FROM t'); - push @sth, $sth; - } - my $handles = $dbh->{ChildHandles}; - is scalar @$handles, scalar @sth; - - # test a recursive walk like the one in the docs - my @lines; - sub show_child_handles { - my ($h, $level) = @_; - $level ||= 0; - push(@lines, - sprintf "%sh %s %s\n", $h->{Type}, "\t" x $level, $h); - show_child_handles($_, $level + 1) - for (grep { defined } @{$h->{ChildHandles}}); - } - my $drh = $dbh->{Driver}; - show_child_handles($drh, 0); - print @lines[0..4]; - - is scalar @lines, $sth_count + 2; - like $lines[0], qr/^drh/; - like $lines[1], qr/^dbh/; - like $lines[2], qr/^sth/; -} - -my $handles = $dbh->{ChildHandles}; -my @live = grep { defined $_ } @$handles; -is scalar @live, 0, "handles should be gone now"; - -# test visit_child_handles -{ - my $info; - my $visitor = sub { - my ($h, $info) = @_; - my $type = $h->{Type}; - ++$info->{ $type }{ ($type eq 'st') ? $h->{Statement} : $h->{Name} }; - return $info; - }; - DBI->visit_handles($visitor, $info = {}); - is_deeply $info, { - 'dr' => { - 'ExampleP' => 1, - ($using_dbd_gofer) ? (Gofer => 1) : () - }, - 'db' => { '' => 1 }, - }; - - my $sth1 = $dbh->prepare('SELECT name FROM t'); - my $sth2 = $dbh->prepare('SELECT name FROM t'); - DBI->visit_handles($visitor, $info = {}); - is_deeply $info, { - 'dr' => { - 'ExampleP' => 1, - ($using_dbd_gofer) ? (Gofer => 1) : () - }, - 'db' => { '' => 1 }, - 'st' => { 'SELECT name FROM t' => 2 } - }; - -} - -# test that the childhandle array does not grow uncontrollably -SKIP: { - skip "slow tests avoided when using DBD::Gofer", 2 if $using_dbd_gofer; - - for (1 .. 1000) { - my $sth = $dbh->prepare('SELECT name FROM t'); - } - my $handles = $dbh->{ChildHandles}; - cmp_ok scalar @$handles, '<', 1000; - my @live = grep { defined } @$handles; - is scalar @live, 0; -} - -1; diff --git a/dbLifeLog/DBI-1.641/t/73cachedkids.t b/dbLifeLog/DBI-1.641/t/73cachedkids.t deleted file mode 100644 index 247d1a6..0000000 --- a/dbLifeLog/DBI-1.641/t/73cachedkids.t +++ /dev/null @@ -1,81 +0,0 @@ -use warnings; -use strict; -use Scalar::Util qw( weaken reftype refaddr blessed ); - -use DBI; -use B (); -use Tie::Hash (); -use Test::More; - -my (%weak_dbhs, %weak_caches); - -# past this scope everything should be gone -{ - -### get two identical connections - my @dbhs = map { DBI->connect('dbi:ExampleP::memory:', undef, undef, { RaiseError => 1 }) } (1,2); - -### get weakrefs on both handles - %weak_dbhs = map { refdesc($_) => $_ } @dbhs; - weaken $_ for values %weak_dbhs; - -### tie the first one's cache - if (1) { - ok( - tie( my %cache, 'Tie::StdHash'), - refdesc($dbhs[0]) . ' cache tied' - ); - $dbhs[0]->{CachedKids} = \%cache; - } - -### prepare something on both - $_->prepare_cached( 'SELECT name FROM .' ) - for @dbhs; - -### get weakrefs of both caches - %weak_caches = map { - sprintf( 'statement cache of %s (%s)', - refdesc($_), - refdesc($_->{CachedKids}) - ) => $_->{CachedKids} - } @dbhs; - weaken $_ for values %weak_caches; - -### check both caches have entries - is (scalar keys %{$weak_caches{$_}}, 1, "One cached statement found in $_") - for keys %weak_caches; - -### check both caches have sane refcounts - is ( refcount( $weak_caches{$_} ), 1, "Refcount of $_ correct") - for keys %weak_caches; - -### check both dbh have sane refcounts - is ( refcount( $weak_dbhs{$_} ), 1, "Refcount of $_ correct") - for keys %weak_dbhs; - - note "Exiting scope"; - @dbhs=(); -} - -# check both $dbh weakrefs are gone -is ($weak_dbhs{$_}, undef, "$_ garbage collected") - for keys %weak_dbhs; - -is ($weak_caches{$_}, undef, "$_ garbage collected") - for keys %weak_caches; - - - -sub refdesc { - sprintf '%s%s(0x%x)', - ( defined( $_[1] = blessed $_[0]) ? "$_[1]=" : '' ), - reftype $_[0], - refaddr($_[0]), - ; -} - -sub refcount { - B::svref_2object($_[0])->REFCNT; -} - -done_testing; diff --git a/dbLifeLog/DBI-1.641/t/80proxy.t b/dbLifeLog/DBI-1.641/t/80proxy.t deleted file mode 100644 index ab529b6..0000000 --- a/dbLifeLog/DBI-1.641/t/80proxy.t +++ /dev/null @@ -1,473 +0,0 @@ -#!perl -w # -*- perl -*- -# vim:sw=4:ts=8 - -require 5.004; -use strict; - - -use DBI; -use Config; -require VMS::Filespec if $^O eq 'VMS'; -require Cwd; - -my $haveFileSpec = eval { require File::Spec }; -my $failed_tests = 0; - -$| = 1; -$^W = 1; - -# $\ = "\n"; # XXX Triggers bug, check this later (JW, 1998-12-28) - -# Can we load the modules? If not, exit the test immediately: -# Reason is most probable a missing prerequisite. -# -# Is syslog available (required for the server)? - -eval { - local $SIG{__WARN__} = sub { $@ = shift }; - require Storable; - require DBD::Proxy; - require DBI::ProxyServer; - require RPC::PlServer; - require Net::Daemon::Test; -}; -if ($@) { - if ($@ =~ /^Can't locate (\S+)/) { - print "1..0 # Skipped: modules required for proxy are probably not installed (e.g., $1)\n"; - exit 0; - } - die $@; -} - -if ($DBI::PurePerl) { - # XXX temporary I hope - print "1..0 # Skipped: DBD::Proxy currently has a problem under DBI::PurePerl\n"; - exit 0; -} - -{ - my $numTest = 0; - sub _old_Test($;$) { - my $result = shift; my $str = shift || ''; - printf("%sok %d%s\n", ($result ? "" : "not "), ++$numTest, $str); - $result; - } - sub Test ($;$) { - my($ok, $msg) = @_; - $msg = ($msg) ? " ($msg)" : ""; - my $line = (caller)[2]; - ++$numTest; - ($ok) ? print "ok $numTest at line $line\n" : print "not ok $numTest\n"; - warn "# failed test $numTest at line ".(caller)[2]."$msg\n" unless $ok; - ++$failed_tests unless $ok; - return $ok; - } -} - - -# Create an empty config file to make sure that settings aren't -# overloaded by /etc/dbiproxy.conf -my $config_file = "dbiproxytst.conf"; -unlink $config_file; -(open(FILE, ">$config_file") and - (print FILE "{}\n") and - close(FILE)) - or die "Failed to create config file $config_file: $!"; - -my $debug = ($ENV{DBI_TRACE}||=0) ? 1 : 0; -my $dbitracelog = "dbiproxy.dbilog"; - -my ($handle, $port, @child_args); - -my $numTests = 136; - -if (@ARGV) { - $port = $ARGV[0]; -} -else { - - unlink $dbitracelog; - unlink "dbiproxy.log"; - unlink "dbiproxy.truss"; - - # Uncommentand adjust this to isolate pure-perl client from server settings: - # local $ENV{DBI_PUREPERL} = 0; - - # If desperate uncomment this and add '-d' after $^X below: - # local $ENV{PERLDB_OPTS} = "AutoTrace NonStop=1 LineInfo=dbiproxy.dbg"; - - # pass our @INC to children (e.g., so -Mblib passes through) - $ENV{PERL5LIB} = join($Config{path_sep}, @INC); - - # server DBI trace level always at least 1 - my $dbitracelevel = DBI->trace(0) || 1; - @child_args = ( - #'truss', '-o', 'dbiproxy.truss', - $^X, 'dbiproxy', '--test', # --test must be first command line arg - "--dbitrace=$dbitracelevel=$dbitracelog", # must be second arg - '--configfile', $config_file, - ($dbitracelevel >= 2 ? ('--debug') : ()), - '--mode=single', - '--logfile=STDERR', - '--timeout=90' - ); - warn " starting test dbiproxy process: @child_args\n" if DBI->trace(0); - ($handle, $port) = Net::Daemon::Test->Child($numTests, @child_args); -} - -my $dsn = "DBI:Proxy:hostname=127.0.0.1;port=$port;debug=$debug;dsn=DBI:ExampleP:"; - -print "Making a first connection and closing it immediately.\n"; -Test(eval { DBI->connect($dsn, '', '', { 'PrintError' => 1 }) }) - or print "Connect error: " . $DBI::errstr . "\n"; - -print "Making a second connection.\n"; -my $dbh; -Test($dbh = eval { DBI->connect($dsn, '', '', { 'PrintError' => 0 }) }) - or print "Connect error: " . $DBI::errstr . "\n"; - -print "example_driver_path=$dbh->{example_driver_path}\n"; -Test($dbh->{example_driver_path}); - -print "Setting AutoCommit\n"; -$@ = "old-error"; # should be preserved across DBI calls -Test($dbh->{AutoCommit} = 1); -Test($dbh->{AutoCommit}); -Test($@ eq "old-error", "\$@ now '$@'"); -#$dbh->trace(2); - -eval { - local $dbh->{ AutoCommit } = 1; # This breaks die! - die "BANG!!!\n"; -}; -Test($@ eq "BANG!!!\n", "\$@ value lost"); - - -print "begin_work...\n"; -Test($dbh->{AutoCommit}); -Test(!$dbh->{BegunWork}); - -Test($dbh->begin_work); -Test(!$dbh->{AutoCommit}); -Test($dbh->{BegunWork}); - -$dbh->commit; -Test(!$dbh->{BegunWork}); -Test($dbh->{AutoCommit}); - -Test($dbh->begin_work({})); -$dbh->rollback; -Test($dbh->{AutoCommit}); -Test(!$dbh->{BegunWork}); - - -print "Doing a ping.\n"; -$_ = $dbh->ping; -Test($_); -Test($_ eq '2'); # ping was DBD::ExampleP's ping - -print "Ensure CompatMode enabled.\n"; -Test($dbh->{CompatMode}); - -print "Trying local quote.\n"; -$dbh->{'proxy_quote'} = 'local'; -Test($dbh->quote("quote's") eq "'quote''s'"); -Test($dbh->quote(undef) eq "NULL"); - -print "Trying remote quote.\n"; -$dbh->{'proxy_quote'} = 'remote'; -Test($dbh->quote("quote's") eq "'quote''s'"); -Test($dbh->quote(undef) eq "NULL"); - -# XXX the $optional param is undocumented and may be removed soon -Test($dbh->quote_identifier('foo') eq '"foo"', $dbh->quote_identifier('foo')); -Test($dbh->quote_identifier('f"o') eq '"f""o"', $dbh->quote_identifier('f"o')); -Test($dbh->quote_identifier('foo','bar') eq '"foo"."bar"'); -Test($dbh->quote_identifier('foo',undef,'bar') eq '"foo"."bar"'); -Test($dbh->quote_identifier(undef,undef,'bar') eq '"bar"'); - -print "Trying commit with invalid number of parameters.\n"; -eval { $dbh->commit('dummy') }; -Test($@ =~ m/^DBI commit: invalid number of arguments:/) - unless $DBI::PurePerl && Test(1); - -print "Trying select with unknown field name.\n"; -my $cursor_e = $dbh->prepare("select unknown_field_name from ?"); -Test(defined $cursor_e); -Test(!$cursor_e->execute('a')); -Test($DBI::err); -Test($DBI::err == $dbh->err); -Test($DBI::errstr =~ m/unknown_field_name/, $DBI::errstr); - -Test($DBI::errstr eq $dbh->errstr); -Test($dbh->errstr eq $dbh->func('errstr')); - -my $dir = Cwd::cwd(); # a dir always readable on all platforms -$dir = VMS::Filespec::unixify($dir) if $^O eq 'VMS'; - -print "Trying a real select.\n"; -my $csr_a = $dbh->prepare("select mode,name from ?"); -Test(ref $csr_a); -Test($csr_a->execute($dir)) - or print "Execute failed: ", $csr_a->errstr(), "\n"; - -print "Repeating the select with second handle.\n"; -my $csr_b = $dbh->prepare("select mode,name from ?"); -Test(ref $csr_b); -Test($csr_b->execute($dir)); -Test($csr_a != $csr_b); -Test($csr_a->{NUM_OF_FIELDS} == 2); -if ($DBI::PurePerl) { - $csr_a->trace(2); - use Data::Dumper; - warn Dumper($csr_a->{Database}); -} -Test($csr_a->{Database}->{Driver}->{Name} eq 'Proxy', "Name=$csr_a->{Database}->{Driver}->{Name}"); -$csr_a->trace(0), die if $DBI::PurePerl; - -my($col0, $col1); -my(@row_a, @row_b); - -#$csr_a->trace(2); -print "Trying bind_columns.\n"; -Test($csr_a->bind_columns(undef, \($col0, $col1)) ); -Test($csr_a->execute($dir)); -@row_a = $csr_a->fetchrow_array; -Test(@row_a); -Test($row_a[0] eq $col0); -Test($row_a[1] eq $col1); - -print "Trying bind_param.\n"; -Test($csr_b->bind_param(1, $dir)); -Test($csr_b->execute()); -@row_b = @{ $csr_b->fetchrow_arrayref }; -Test(@row_b); - -Test("@row_a" eq "@row_b"); -@row_b = $csr_b->fetchrow_array; -Test("@row_a" ne "@row_b") - or printf("Expected something different from '%s', got '%s'\n", "@row_a", - "@row_b"); - -print "Trying fetchrow_hashref.\n"; -Test($csr_b->execute()); -my $row_b = $csr_b->fetchrow_hashref; -Test($row_b); -print "row_a: @{[ @row_a ]}\n"; -print "row_b: @{[ %$row_b ]}\n"; -Test($row_b->{mode} == $row_a[0]); -Test($row_b->{name} eq $row_a[1]); - -print "Trying fetchrow_hashref with FetchHashKeyName.\n"; -do { -#local $dbh->{TraceLevel} = 9; -local $dbh->{FetchHashKeyName} = 'NAME_uc'; -Test($dbh->{FetchHashKeyName} eq 'NAME_uc'); -my $csr_c = $dbh->prepare("select mode,name from ?"); -Test($csr_c->execute($dir), $DBI::errstr); -$row_b = $csr_c->fetchrow_hashref; -Test($row_b); -print "row_b: @{[ %$row_b ]}\n"; -Test($row_b->{MODE} eq $row_a[0]); -}; - -print "Trying finish.\n"; -Test($csr_a->finish); -#Test($csr_b->finish); -Test(1); - -print "Forcing destructor.\n"; -$csr_a = undef; # force destruction of this cursor now -Test(1); - -print "Trying fetchall_arrayref.\n"; -Test($csr_b->execute()); -my $r = $csr_b->fetchall_arrayref; -Test($r); -Test(@$r); -Test($r->[0]->[0] == $row_a[0]); -Test($r->[0]->[1] eq $row_a[1]); - -Test($csr_b->finish); - - -print "Retrying unknown field name.\n"; -my $csr_c; -$csr_c = $dbh->prepare("select unknown_field_name1 from ?"); -Test($csr_c); -Test(!$csr_c->execute($dir)); -Test($DBI::errstr =~ m/Unknown field names: unknown_field_name1/) - or printf("Wrong error string: %s", $DBI::errstr); - -print "Trying RaiseError.\n"; -$dbh->{RaiseError} = 1; -Test($dbh->{RaiseError}); -Test($csr_c = $dbh->prepare("select unknown_field_name2 from ?")); -Test(!eval { $csr_c->execute(); 1 }); -#print "$@\n"; -Test($@ =~ m/Unknown field names: unknown_field_name2/); -$dbh->{RaiseError} = 0; -Test(!$dbh->{RaiseError}); - -print "Trying warnings.\n"; -{ - my @warn; - local($SIG{__WARN__}) = sub { push @warn, @_ }; - $dbh->{PrintError} = 1; - Test($dbh->{PrintError}); - Test(($csr_c = $dbh->prepare("select unknown_field_name3 from ?"))); - Test(!$csr_c->execute()); - Test("@warn" =~ m/Unknown field names: unknown_field_name3/); - $dbh->{PrintError} = 0; - Test(!$dbh->{PrintError}); -} -$csr_c->finish(); - - -print "Trying type_info_all.\n"; -my $array = $dbh->type_info_all(); -Test($array and ref($array) eq 'ARRAY') - or printf("Expected ARRAY, got %s, error %s\n", DBI::neat($array), - $dbh->errstr()); -Test($array->[0] and ref($array->[0]) eq 'HASH'); -my $ok = 1; -for (my $i = 1; $i < @{$array}; $i++) { - print "$array->[$i]\n"; - $ok = 0 unless ($array->[$i] and ref($array->[$i]) eq 'ARRAY'); - print "$ok\n"; -} -Test($ok); - -# Test the table_info method -# First generate a list of all subdirectories -$dir = $haveFileSpec ? File::Spec->curdir() : "."; -Test(opendir(DIR, $dir)); -my(%dirs, %unexpected, %missing); -while (defined(my $file = readdir(DIR))) { - $dirs{$file} = 1 if -d $file; -} -closedir(DIR); -my $sth = $dbh->table_info(undef, undef, undef, undef); -Test($sth) or warn "table_info failed: ", $dbh->errstr(), "\n"; -%missing = %dirs; -%unexpected = (); -while (my $ref = $sth->fetchrow_hashref()) { - print "table_info: Found table $ref->{'TABLE_NAME'}\n"; - if (exists($missing{$ref->{'TABLE_NAME'}})) { - delete $missing{$ref->{'TABLE_NAME'}}; - } else { - $unexpected{$ref->{'TABLE_NAME'}} = 1; - } -} -Test(!$sth->errstr()) - or print "Fetching table_info rows failed: ", $sth->errstr(), "\n"; -Test(keys %unexpected == 0) - or print "Unexpected directories: ", join(",", keys %unexpected), "\n"; -Test(keys %missing == 0) - or print "Missing directories: ", join(",", keys %missing), "\n"; - -# Test the tables method -%missing = %dirs; -%unexpected = (); -print "Expecting directories ", join(",", keys %dirs), "\n"; -foreach my $table ($dbh->tables()) { - print "tables: Found table $table\n"; - if (exists($missing{$table})) { - delete $missing{$table}; - } else { - $unexpected{$table} = 1; - } -} -Test(!$sth->errstr()) - or print "Fetching table_info rows failed: ", $sth->errstr(), "\n"; -Test(keys %unexpected == 0) - or print "Unexpected directories: ", join(",", keys %unexpected), "\n"; -Test(keys %missing == 0) - or print "Missing directories: ", join(",", keys %missing), "\n"; - - -# Test large recordsets -for (my $i = 0; $i <= 300; $i += 100) { - print "Testing the fake directories ($i).\n"; - Test($csr_a = $dbh->prepare("SELECT name, mode FROM long_list_$i")); - Test($csr_a->execute(), $DBI::errstr); - my $ary = $csr_a->fetchall_arrayref; - Test(!$DBI::errstr, $DBI::errstr); - Test(@$ary == $i, "expected $i got ".@$ary); - if ($i) { - my @n1 = map { $_->[0] } @$ary; - my @n2 = reverse map { "file$_" } 1..$i; - Test("@n1" eq "@n2"); - } - else { - Test(1); - } -} - - -# Test the RowCacheSize attribute -Test($csr_a = $dbh->prepare("SELECT * FROM ?")); -Test($dbh->{'RowCacheSize'} == 20); -Test($csr_a->{'RowCacheSize'} == 20); -Test($csr_a->execute('long_list_50')); -Test($csr_a->fetchrow_arrayref()); -Test($csr_a->{'proxy_data'} and @{$csr_a->{'proxy_data'}} == 19); -Test($csr_a->finish()); - -Test($dbh->{'RowCacheSize'} = 30); -Test($dbh->{'RowCacheSize'} == 30); -Test($csr_a->{'RowCacheSize'} == 30); -Test($csr_a->execute('long_list_50')); -Test($csr_a->fetchrow_arrayref()); -Test($csr_a->{'proxy_data'} and @{$csr_a->{'proxy_data'}} == 29) - or print("Expected 29 records in cache, got " . @{$csr_a->{'proxy_data'}} . - "\n"); -Test($csr_a->finish()); - - -Test($csr_a->{'RowCacheSize'} = 10); -Test($dbh->{'RowCacheSize'} == 30); -Test($csr_a->{'RowCacheSize'} == 10); -Test($csr_a->execute('long_list_50')); -Test($csr_a->fetchrow_arrayref()); -Test($csr_a->{'proxy_data'} and @{$csr_a->{'proxy_data'}} == 9) - or print("Expected 9 records in cache, got " . @{$csr_a->{'proxy_data'}} . - "\n"); -Test($csr_a->finish()); - -$dbh->disconnect; - -# Test $dbh->func() -# print "Testing \$dbh->func().\n"; -# my %tables = map { $_ =~ /lib/ ? ($_, 1) : () } $dbh->tables(); -# $ok = 1; -# foreach my $t ($dbh->func('lib', 'examplep_tables')) { -# defined(delete $tables{$t}) or print "Unexpected table: $t\n"; -# } -# Test(%tables == 0); - -if ($failed_tests) { - warn "Proxy: @child_args\n"; - for my $class (qw(Net::Daemon RPC::PlServer Storable)) { - (my $pm = $class) =~ s/::/\//g; $pm .= ".pm"; - my $version = eval { $class->VERSION } || '?'; - warn sprintf "Using %-13s %-6s %s\n", $class, $version, $INC{$pm}; - } - warn join(", ", map { "$_=$ENV{$_}" } grep { /^LC_|LANG/ } keys %ENV)."\n"; - warn "More info can be found in $dbitracelog\n"; - #system("cat $dbitracelog"); -} - - -END { - local $?; - $handle->Terminate() if $handle; - undef $handle; - unlink $config_file if $config_file; - if (!$failed_tests) { - unlink 'dbiproxy.log'; - unlink $dbitracelog if $dbitracelog; - } -}; - -1; diff --git a/dbLifeLog/DBI-1.641/t/85gofer.t b/dbLifeLog/DBI-1.641/t/85gofer.t deleted file mode 100644 index 985bbbe..0000000 --- a/dbLifeLog/DBI-1.641/t/85gofer.t +++ /dev/null @@ -1,265 +0,0 @@ -#!perl -w # -*- perl -*- -# vim:sw=4:ts=8 -$|=1; - -use strict; -use warnings; - -use Cwd; -use Config; -use Data::Dumper; -use Test::More 0.84; -use Getopt::Long; - -use DBI qw(dbi_time); - -if (my $ap = $ENV{DBI_AUTOPROXY}) { # limit the insanity - plan skip_all => "transport+policy tests skipped with non-gofer DBI_AUTOPROXY" - if $ap !~ /^dbi:Gofer/i; - plan skip_all => "transport+policy tests skipped with non-pedantic policy in DBI_AUTOPROXY" - if $ap !~ /policy=pedantic\b/i; -} - -do "./t/lib.pl"; - -# 0=SQL::Statement if avail, 1=DBI::SQL::Nano -# next line forces use of Nano rather than default behaviour -# $ENV{DBI_SQL_NANO}=1; -# This is done in zvn_50dbm.t - -GetOptions( - 'c|count=i' => \(my $opt_count = (-t STDOUT ? 100 : 0)), - 'dbm=s' => \my $opt_dbm, - 'v|verbose!' => \my $opt_verbose, - 't|transport=s' => \my $opt_transport, - 'p|policy=s' => \my $opt_policy, -) or exit 1; - - -# so users can try others from the command line -if (!$opt_dbm) { - # pick first available, starting with SDBM_File - for (qw( SDBM_File GDBM_File DB_File BerkeleyDB )) { - if (eval { local $^W; require "$_.pm" }) { - $opt_dbm = ($_); - last; - } - } - plan skip_all => 'No DBM modules available' if !$opt_dbm; -} - -my @remote_dsns = DBI->data_sources( "dbi:DBM:", { - dbm_type => $opt_dbm, - f_lock => 0, - f_dir => test_dir() } ); -my $remote_dsn = $remote_dsns[0]; -( my $remote_driver_dsn = $remote_dsn ) =~ s/dbi:dbm://i; -# Long timeout for slow/overloaded systems (incl virtual machines with low priority) -my $timeout = 240; - -if ($ENV{DBI_AUTOPROXY}) { - # this means we have DBD::Gofer => DBD::Gofer => DBD::DBM! - # rather than disable it we let it run because we're twisted - # and because it helps find more bugs (though debugging can be painful) - warn "\n$0 is running with DBI_AUTOPROXY enabled ($ENV{DBI_AUTOPROXY})\n" - unless $0 =~ /\bzv/; # don't warn for t/zvg_85gofer.t -} - -# ensure subprocess (for pipeone and stream transport) will use the same modules as us, ie ./blib -local $ENV{PERL5LIB} = join $Config{path_sep}, @INC; - -my %durations; -my $getcwd = getcwd(); -my $username = eval { getpwuid($>) } || ''; # fails on windows -my $can_ssh = ($username && $username eq 'timbo' && -d '.svn' - && system("sh -c 'echo > /dev/tcp/localhost/22' 2>/dev/null")==0 -); -my $perl = "$^X -Mblib=$getcwd/blib"; # ensure sameperl and our blib (note two spaces) - -my %trials = ( - null => {}, - pipeone => { perl=>$perl, timeout=>$timeout }, - stream => { perl=>$perl, timeout=>$timeout }, - stream_ssh => ($can_ssh) - ? { perl=>$perl, timeout=>$timeout, url => "ssh:$username\@localhost" } - : undef, - #http => { url => "http://localhost:8001/gofer" }, -); - -# too dependent on local config to make a standard test -delete $trials{http} unless $username eq 'timbo' && -d '.svn'; - -my @transports = ($opt_transport) ? ($opt_transport) : (sort keys %trials); -note("Transports: @transports"); -my @policies = ($opt_policy) ? ($opt_policy) : qw(pedantic classic rush); -note("Policies: @policies"); -note("Count: $opt_count"); - -for my $trial (@transports) { - (my $transport = $trial) =~ s/_.*//; - my $trans_attr = $trials{$trial} - or next; - - # XXX temporary restrictions, hopefully - if ( ($^O eq 'MSWin32') || ($^O eq 'VMS') ) { - # stream needs Fcntl macro F_GETFL for non-blocking - # and pipe seems to hang on some windows systems - next if $transport eq 'stream' or $transport eq 'pipeone'; - } - - for my $policy_name (@policies) { - - eval { run_tests($transport, $trans_attr, $policy_name) }; - ($@) ? fail("$trial: $@") : pass(); - - } -} - -# to get baseline for comparisons if doing performance testing -run_tests('no', {}, 'pedantic') if $opt_count; - -while ( my ($activity, $stats_hash) = each %durations ) { - note(""); - $stats_hash->{'~baseline~'} = delete $stats_hash->{"no+pedantic"}; - for my $perf_tag (reverse sort keys %$stats_hash) { - my $dur = $stats_hash->{$perf_tag} || 0.0000001; - note sprintf " %6s %-16s: %.6fsec (%5d/sec)", - $activity, $perf_tag, $dur/$opt_count, $opt_count/$dur; - my $baseline_dur = $stats_hash->{'~baseline~'}; - note sprintf " %+5.1fms", (($dur-$baseline_dur)/$opt_count)*1000 - unless $perf_tag eq '~baseline~'; - note ""; - } -} - - -sub run_tests { - my ($transport, $trans_attr, $policy_name) = @_; - - my $policy = get_policy($policy_name); - my $skip_gofer_checks = ($transport eq 'no'); - - - my $test_run_tag = "Testing $transport transport with $policy_name policy"; - note "============="; - note "$test_run_tag"; - - my $driver_dsn = "transport=$transport;policy=$policy_name"; - $driver_dsn .= join ";", '', map { "$_=$trans_attr->{$_}" } keys %$trans_attr - if %$trans_attr; - - my $dsn = "dbi:Gofer:$driver_dsn;dsn=$remote_dsn"; - $dsn = $remote_dsn if $transport eq 'no'; - note " $dsn"; - - my $dbh = DBI->connect($dsn, undef, undef, { RaiseError => 1, PrintError => 0, ShowErrorStatement => 1 } ); - die "$test_run_tag aborted: $DBI::errstr\n" unless $dbh; # no point continuing - ok $dbh, sprintf "should connect to %s", $dsn; - - is $dbh->{Name}, ($policy->skip_connect_check) - ? $driver_dsn - : $remote_driver_dsn; - - END { unlink glob "fruit.???" } - ok $dbh->do("DROP TABLE IF EXISTS fruit"); - ok $dbh->do("CREATE TABLE fruit (dKey INT, dVal VARCHAR(10))"); - die "$test_run_tag aborted ($DBI::errstr)\n" if $DBI::err; - - my $sth = do { - local $dbh->{RaiseError} = 0; - $dbh->prepare("complete non-sql gibberish"); - }; - ($policy->skip_prepare_check) - ? isa_ok $sth, 'DBI::st' - : is $sth, undef, 'should detect prepare failure'; - - ok my $ins_sth = $dbh->prepare("INSERT INTO fruit VALUES (?,?)"); - ok $ins_sth->execute(1, 'oranges'); - ok $ins_sth->execute(2, 'oranges'); - - my $rowset; - ok $rowset = $dbh->selectall_arrayref("SELECT dKey, dVal FROM fruit ORDER BY dKey"); - is_deeply($rowset, [ [ '1', 'oranges' ], [ '2', 'oranges' ] ]); - - ok $dbh->do("UPDATE fruit SET dVal='apples' WHERE dVal='oranges'"); - ok $dbh->{go_response}->executed_flag_set, 'go_response executed flag should be true' - unless $skip_gofer_checks && pass(); - - ok $sth = $dbh->prepare("SELECT dKey, dVal FROM fruit"); - ok $sth->execute; - ok $rowset = $sth->fetchall_hashref('dKey'); - is_deeply($rowset, { '1' => { dKey=>1, dVal=>'apples' }, 2 => { dKey=>2, dVal=>'apples' } }); - - if ($opt_count and $transport ne 'pipeone') { - note "performance check - $opt_count selects and inserts"; - my $start = dbi_time(); - $dbh->selectall_arrayref("SELECT dKey, dVal FROM fruit") - for (1000..1000+$opt_count); - $durations{select}{"$transport+$policy_name"} = dbi_time() - $start; - - # some rows in to get a (*very* rough) idea of overheads - $start = dbi_time(); - $ins_sth->execute($_, 'speed') - for (1000..1000+$opt_count); - $durations{insert}{"$transport+$policy_name"} = dbi_time() - $start; - } - - note "Testing go_request_count and caching of simple values"; - my $go_request_count = $dbh->{go_request_count}; - ok $go_request_count - unless $skip_gofer_checks && pass(); - - ok $dbh->do("DROP TABLE fruit"); - is ++$go_request_count, $dbh->{go_request_count} - unless $skip_gofer_checks && pass(); - - # tests go_request_count, caching, and skip_default_methods policy - my $use_remote = ($policy->skip_default_methods) ? 0 : 1; - $use_remote = 1; # XXX since DBI::DBD::SqlEngine::db implements own data_sources this is always done remotely - note sprintf "use_remote=%s (policy=%s, transport=%s) %s", - $use_remote, $policy_name, $transport, DBI::neat($dbh->{dbi_default_methods})||''; - -SKIP: { - skip "skip_default_methods checking doesn't work with Gofer over Gofer", 3 - if $ENV{DBI_AUTOPROXY} or $skip_gofer_checks; - $dbh->data_sources({ foo_bar => $go_request_count }); - is $dbh->{go_request_count}, $go_request_count + 1*$use_remote; - $dbh->data_sources({ foo_bar => $go_request_count }); # should use cache - is $dbh->{go_request_count}, $go_request_count + 1*$use_remote; - @_=$dbh->data_sources({ foo_bar => $go_request_count }); # no cached yet due to wantarray - is $dbh->{go_request_count}, $go_request_count + 2*$use_remote; -} - -SKIP: { - skip "caching of metadata methods returning sth not yet implemented", 2; - note "Testing go_request_count and caching of sth"; - $go_request_count = $dbh->{go_request_count}; - my $sth_ti1 = $dbh->table_info("%", "%", "%", "TABLE", { foo_bar => $go_request_count }); - is $go_request_count + 1, $dbh->{go_request_count}; - - my $sth_ti2 = $dbh->table_info("%", "%", "%", "TABLE", { foo_bar => $go_request_count }); # should use cache - is $go_request_count + 1, $dbh->{go_request_count}; -} - - ok $dbh->disconnect; -} - -sub get_policy { - my ($policy_class) = @_; - $policy_class = "DBD::Gofer::Policy::$policy_class" unless $policy_class =~ /::/; - _load_class($policy_class) or die $@; - return $policy_class->new(); -} - -sub _load_class { # return true or false+$@ - my $class = shift; - (my $pm = $class) =~ s{::}{/}g; - $pm .= ".pm"; - return 1 if eval { require $pm }; - delete $INC{$pm}; # shouldn't be needed (perl bug?) and assigning undef isn't enough - undef; # error in $@ -} - -done_testing; - -1; diff --git a/dbLifeLog/DBI-1.641/t/86gofer_fail.t b/dbLifeLog/DBI-1.641/t/86gofer_fail.t deleted file mode 100644 index 9a7b82b..0000000 --- a/dbLifeLog/DBI-1.641/t/86gofer_fail.t +++ /dev/null @@ -1,168 +0,0 @@ -#!perl -w # -*- perl -*- -# vim:sw=4:ts=8 -$|=1; - -use strict; -use warnings; - -use DBI; -use Data::Dumper; -use Test::More; -sub between_ok; - -# here we test the DBI_GOFER_RANDOM mechanism -# and how gofer deals with failures - -plan skip_all => "requires Callbacks which are not supported with PurePerl" if $DBI::PurePerl; - -if (my $ap = $ENV{DBI_AUTOPROXY}) { # limit the insanity - plan skip_all => "Gofer DBI_AUTOPROXY" if $ap =~ /^dbi:Gofer/i; - - # this means we have DBD::Gofer => DBD::Gofer => DBD::whatever - # rather than disable it we let it run because we're twisted - # and because it helps find more bugs (though debugging can be painful) - warn "\n$0 is running with DBI_AUTOPROXY enabled ($ENV{DBI_AUTOPROXY})\n" - unless $0 =~ /\bzv/; # don't warn for t/zvg_85gofer.t -} - -plan 'no_plan'; - -my $tmp; -my $dbh; -my $fails; - -# we'll use the null transport for simplicity and speed -# and the rush policy to limit the number of interactions with the gofer executor - -# silence the "DBI_GOFER_RANDOM..." warnings -my @warns; -$SIG{__WARN__} = sub { ("@_" =~ /^DBI_GOFER_RANDOM/) ? push(@warns, @_) : warn @_; }; - -# --- 100% failure rate - -($fails, $dbh) = trial_impact("fail=100%,do", 10, "", sub { $_->do("set foo=1") }); -is $fails, 100, 'should fail 100% of the time'; -ok $@, '$@ should be set'; -like $@, '/fake error from do method induced by DBI_GOFER_RANDOM/'; -ok $dbh->errstr, 'errstr should be set'; -like $dbh->errstr, '/DBI_GOFER_RANDOM/', 'errstr should contain DBI_GOFER_RANDOM'; -ok !$dbh->{go_response}->executed_flag_set, 'go_response executed flag should be false'; - - -# XXX randomness can't be predicted, so it's just possible these will fail -srand(42); # try to limit occasional failures (effect will vary by platform etc) - -sub trial_impact { - my ($spec, $count, $dsn_attr, $code, $verbose) = @_; - local $ENV{DBI_GOFER_RANDOM} = $spec; - my $dbh = dbi_connect("policy=rush;$dsn_attr"); - local $_ = $dbh; - my $fail_percent = percentage_exceptions(200, $code, $verbose); - return $fail_percent unless wantarray; - return ($fail_percent, $dbh); -} - -# --- 50% failure rate, with no retries - -$fails = trial_impact("fail=50%,do", 200, "retry_limit=0", sub { $_->do("set foo=1") }); -print "target approx 50% random failures, got $fails%\n"; -between_ok $fails, 10, 90, "should fail about 50% of the time, but at least between 10% and 90%"; - -# --- 50% failure rate, with many retries (should yield low failure rate) - -$fails = trial_impact("fail=50%,prepare", 200, "retry_limit=5", sub { $_->prepare("set foo=1") }); -print "target less than 20% effective random failures (ideally 0), got $fails%\n"; -cmp_ok $fails, '<', 20, 'should fail < 20%'; - -# --- 10% failure rate, with many retries (should yield zero failure rate) - -$fails = trial_impact("fail=10,do", 200, "retry_limit=10", sub { $_->do("set foo=1") }); -cmp_ok $fails, '<', 1, 'should fail < 1%'; - -# --- 50% failure rate, test is_idempotent - -$ENV{DBI_GOFER_RANDOM} = "fail=50%,do"; # 50% - -# test go_retry_hook and that ReadOnly => 1 retries a non-idempotent statement -ok my $dbh_50r1ro = dbi_connect("policy=rush;retry_limit=1", { - go_retry_hook => sub { return ($_[0]->is_idempotent) ? 1 : 0 }, - ReadOnly => 1, -} ); -between_ok percentage_exceptions(100, sub { $dbh_50r1ro->do("set foo=1") }), - 10, 40, 'should fail ~25% (ie 50% with one retry)'; -between_ok $dbh_50r1ro->{go_transport}->meta->{request_retry_count}, - 20, 80, 'transport request_retry_count should be around 50'; - -# test as above but with ReadOnly => 0 -ok my $dbh_50r1rw = dbi_connect("policy=rush;retry_limit=1", { - go_retry_hook => sub { return ($_[0]->is_idempotent) ? 1 : 0 }, - ReadOnly => 0, -} ); -between_ok percentage_exceptions(100, sub { $dbh_50r1rw->do("set foo=1") }), - 20, 80, 'should fail ~50%, ie no retries'; -ok !$dbh_50r1rw->{go_transport}->meta->{request_retry_count}, - 'transport request_retry_count should be zero or undef'; - - -# --- check random is random and non-random is non-random - -my %fail_percents; -for (1..5) { - $fails = trial_impact("fail=50%,do", 10, "", sub { $_->do("set foo=1") }); - ++$fail_percents{$fails}; -} -cmp_ok scalar keys %fail_percents, '>=', 2, 'positive percentage should fail randomly'; - -%fail_percents = (); -for (1..5) { - $fails = trial_impact("fail=-50%,do", 10, "", sub { $_->do("set foo=1") }); - ++$fail_percents{$fails}; -} -is scalar keys %fail_percents, 1, 'negative percentage should fail non-randomly'; - -# --- -print "Testing random delay\n"; - -$ENV{DBI_GOFER_RANDOM} = "delay0.1=51%,do"; # odd percentage to force warn()s -@warns = (); -ok $dbh = dbi_connect("policy=rush;retry_limit=0"); -is percentage_exceptions(20, sub { $dbh->do("set foo=1") }), - 0, "should not fail for DBI_GOFER_RANDOM='$ENV{DBI_GOFER_RANDOM}'"; -my $delays = grep { m/delaying execution/ } @warns; -between_ok $delays, 1, 19, 'should be delayed around 5 times'; - -exit 0; - -# --- subs --- -# -sub between_ok { - my ($got, $min, $max, $label) = @_; - local $Test::Builder::Level = 2; - cmp_ok $got, '>=', $min, "$label (got $got)"; - cmp_ok $got, '<=', $max, "$label (got $got)"; -} - -sub dbi_connect { - my ($gdsn, $attr) = @_; - return DBI->connect("dbi:Gofer:transport=null;$gdsn;dsn=dbi:ExampleP:", 0, 0, { - RaiseError => 1, PrintError => 0, ($attr) ? %$attr : () - }); -} - -sub percentage_exceptions { - my ($count, $sub, $verbose) = @_; - my $i = $count; - my $exceptions = 0; - while ($i--) { - eval { $sub->() }; - warn sprintf("percentage_exceptions $i: %s\n", $@|| $DBI::errstr || '') if $verbose; - if ($@) { - die "Unexpected failure: $@" unless $@ =~ /DBI_GOFER_RANDOM/; - ++$exceptions; - } - } - warn sprintf "percentage_exceptions %f/%f*100 = %f\n", - $exceptions, $count, $exceptions/$count*100 - if $verbose; - return $exceptions/$count*100; -} diff --git a/dbLifeLog/DBI-1.641/t/87gofer_cache.t b/dbLifeLog/DBI-1.641/t/87gofer_cache.t deleted file mode 100644 index 58757d0..0000000 --- a/dbLifeLog/DBI-1.641/t/87gofer_cache.t +++ /dev/null @@ -1,108 +0,0 @@ -#!perl -w # -*- perl -*- -# vim:sw=4:ts=8 -$|=1; - -use strict; -use warnings; - -use DBI; -use Data::Dumper; -use Test::More; -use DBI::Util::CacheMemory; - -plan skip_all => "Gofer DBI_AUTOPROXY" if (($ENV{DBI_AUTOPROXY}||'') =~ /^dbi:Gofer/i); - -plan 'no_plan'; - - -my $dsn = "dbi:Gofer:transport=null;policy=classic;dsn=dbi:ExampleP:"; - -my @cache_classes = qw(DBI::Util::CacheMemory); -push @cache_classes, "Cache::Memory" if eval { require Cache::Memory }; -push @cache_classes, "1"; # test alias for DBI::Util::CacheMemory - -for my $cache_class (@cache_classes) { - my $cache_obj = ($cache_class eq "1") ? $cache_class : $cache_class->new(); - run_tests($cache_obj); -} - - -sub run_tests { - my $cache_obj = shift; - - my $tmp; - print "\n --- using $cache_obj for $dsn\n"; - - my $dbh = DBI->connect($dsn, undef, undef, { - go_cache => $cache_obj, - RaiseError => 1, PrintError => 0, ShowErrorStatement => 1, - } ); - ok my $go_transport = $dbh->{go_transport}; - ok my $go_cache = $go_transport->go_cache; - - # setup - $go_cache->clear; - is $go_cache->count, 0, 'cache should be empty after clear'; - - $go_transport->transmit_count(0); - is $go_transport->transmit_count, 0, 'transmit_count should be 0'; - - $go_transport->cache_hit(0); - $go_transport->cache_miss(0); - $go_transport->cache_store(0); - - # request 1 - ok my $rows1 = $dbh->selectall_arrayref("select name from ?", {}, "."); - cmp_ok $go_cache->count, '>', 0, 'cache should not be empty after select'; - - my $expected = ($ENV{DBI_AUTOPROXY}) ? 2 : 1; - is $go_transport->cache_hit, 0; - is $go_transport->cache_miss, $expected; - is $go_transport->cache_store, $expected; - - is $go_transport->transmit_count, $expected, "should make $expected round trip"; - $go_transport->transmit_count(0); - is $go_transport->transmit_count, 0, 'transmit_count should be 0'; - - # request 2 - ok my $rows2 = $dbh->selectall_arrayref("select name from ?", {}, "."); - is_deeply $rows2, $rows1; - is $go_transport->transmit_count, 0, 'should make 0 round trip'; - - is $go_transport->cache_hit, $expected, 'cache_hit'; - is $go_transport->cache_miss, $expected, 'cache_miss'; - is $go_transport->cache_store, $expected, 'cache_store'; -} - - -print "test per-sth go_cache\n"; - -my $dbh = DBI->connect($dsn, undef, undef, { - go_cache => 1, - RaiseError => 1, PrintError => 0, ShowErrorStatement => 1, -} ); -ok my $go_transport = $dbh->{go_transport}; -ok my $dbh_cache = $go_transport->go_cache; -$dbh_cache->clear; # discard ping from connect - -my $cache2 = DBI::Util::CacheMemory->new( namespace => "foo2" ); -ok $cache2; -ok $cache2 != $dbh_cache; - -my $sth1 = $dbh->prepare("select name from ?"); -is $sth1->go_cache, $dbh_cache; -is $dbh_cache->size, 0; -ok $dbh->selectall_arrayref($sth1, undef, "."); -ok $dbh_cache->size; - -my $sth2 = $dbh->prepare("select * from ?", { go_cache => $cache2 }); -is $sth2->go_cache, $cache2; -is $cache2->size, 0; -ok $dbh->selectall_arrayref($sth2, undef, "."); -ok $cache2->size; - -cmp_ok $cache2->size, '>', $dbh_cache->size; - - - -1; diff --git a/dbLifeLog/DBI-1.641/t/90sql_type_cast.t b/dbLifeLog/DBI-1.641/t/90sql_type_cast.t deleted file mode 100644 index f5510e8..0000000 --- a/dbLifeLog/DBI-1.641/t/90sql_type_cast.t +++ /dev/null @@ -1,153 +0,0 @@ -# $Id$ -# Test DBI::sql_type_cast -use strict; -#use warnings; this script generate warnings deliberately as part of the test -use Test::More; -use DBI qw(:sql_types :utils); -use Config; - -my $jx = eval {require JSON::XS;}; -my $dp = eval {require Data::Peek;}; -my $pp = $DBI::PurePerl && $DBI::PurePerl; # doubled to avoid typo warning - -# NOTE: would have liked to use DBI::neat to test the cast value is what -# we expect but unfortunately neat uses SvNIOK(sv) so anything that looks -# like a number is printed as a number without quotes even if it has -# a pv. - -use constant INVALID_TYPE => -2; -use constant SV_IS_UNDEF => -1; -use constant NO_CAST_STRICT => 0; -use constant NO_CAST_NO_STRICT => 1; -use constant CAST_OK => 2; - -my @tests = ( - ['undef', undef, SQL_INTEGER, SV_IS_UNDEF, -1, q{[null]}], - ['invalid sql type', '99', 123456789, 0, INVALID_TYPE, q{["99"]}], - ['non numeric cast to int', 'aa', SQL_INTEGER, 0, NO_CAST_NO_STRICT, - q{["aa"]}], - ['non numeric cast to int (strict)', 'aa', SQL_INTEGER, - DBIstcf_STRICT, NO_CAST_STRICT, q{["aa"]}], - ['small int cast to int', "99", SQL_INTEGER, 0, CAST_OK, q{["99"]}], - ['2 byte max signed int cast to int', "32767", SQL_INTEGER, 0, - CAST_OK, q{["32767"]}], - ['2 byte max unsigned int cast to int', "65535", - SQL_INTEGER, 0, CAST_OK, q{["65535"]}], - ['4 byte max signed int cast to int', "2147483647", - SQL_INTEGER, 0, CAST_OK, q{["2147483647"]}], - ['4 byte max unsigned int cast to int', "4294967295", - SQL_INTEGER, 0, CAST_OK, q{["4294967295"]}], - ['small int cast to int (discard)', - '99', SQL_INTEGER, DBIstcf_DISCARD_STRING, CAST_OK, q{[99]}], - - ['non numeric cast to numeric', 'aa', SQL_NUMERIC, - 0, NO_CAST_NO_STRICT, q{["aa"]}], - ['non numeric cast to numeric (strict)', 'aa', SQL_NUMERIC, - DBIstcf_STRICT, NO_CAST_STRICT, q{["aa"]}], - ); - -if (!$pp) { - # some tests cannot be performed with PurePerl as numbers don't - # overflow in the same way as XS. - push @tests, - ( - ['very large int cast to int', - '99999999999999999999', SQL_INTEGER, 0, NO_CAST_NO_STRICT, - q{["99999999999999999999"]}], - ['very large int cast to int (strict)', - '99999999999999999999', SQL_INTEGER, DBIstcf_STRICT, - NO_CAST_STRICT, q{["99999999999999999999"]}], - ['float cast to int', '99.99', SQL_INTEGER, 0, - NO_CAST_NO_STRICT, q{["99.99"]}], - ['float cast to int (strict)', '99.99', SQL_INTEGER, DBIstcf_STRICT, - NO_CAST_STRICT, q{["99.99"]}], - ['float cast to double', '99.99', SQL_DOUBLE, 0, CAST_OK, - q{["99.99"]}] - ); - if ($Config{ivsize} == 4) { - push @tests, - ['4 byte max unsigned int cast to int (ivsize=4)', "4294967296", - SQL_INTEGER, 0, NO_CAST_NO_STRICT, q{["4294967296"]}]; - } elsif ($Config{ivsize} >= 8) { - push @tests, - ['4 byte max unsigned int cast to int (ivsize>8)', "4294967296", - SQL_INTEGER, 0, CAST_OK, q{["4294967296"]}]; - } -} - -if ($] >= 5.010001) { - # Some numeric tests fail the return value test on Perls before 5.10.1 - # because sv_2nv leaves NOK set - changed in 5.10.1 probably via the - # following change: - # The public IV and NV flags are now not set if the string - # value has trailing "garbage". This behaviour is consistent with not - # setting the public IV or NV flags if the value is out of range for the - # type. - push @tests, ( - ['non numeric cast to double', 'aabb', SQL_DOUBLE, 0, - NO_CAST_NO_STRICT, q{["aabb"]}], - ['non numeric cast to double (strict)', 'aabb', SQL_DOUBLE, - DBIstcf_STRICT, NO_CAST_STRICT, q{["aabb"]}] - ); -} - -my $tests = @tests; -$tests *= 2 if $jx; -foreach (@tests) { - $tests++ if ($dp) && ($_->[3] & DBIstcf_DISCARD_STRING); - $tests++ if ($dp) && ($_->[2] == SQL_DOUBLE); -} - -plan tests => $tests; - -foreach my $test(@tests) { - my $val = $test->[1]; - #diag(join(",", map {neat($_)} Data::Peek::DDual($val))); - my $result; - { - no warnings; # lexical but also affects XS sub - local $^W = 0; # needed for PurePerl tests - $result = sql_type_cast($val, $test->[2], $test->[3]); - } - is($result, $test->[4], "result, $test->[0]"); - if ($jx) { - - SKIP: { - skip 'DiscardString not supported in PurePerl', 1 - if $pp && ($test->[3] & DBIstcf_DISCARD_STRING); - - my $json = JSON::XS->new->encode([$val]); - #diag(neat($val), ",", $json); - # This test is about quotation of the value, not about the - # style/formatting of JSON. Strip all leading/trailing - # whitespace that is not part of the test, treating '[99]' - # identical to ' [ 99 ] ' or '[99 ]' - $json =~ s{^\s*\[\s*(.*?)\s*\]\s*$}{[$1]}; - is($json, $test->[5], "json $test->[0]"); - }; - } - - my ($pv, $iv, $nv, $rv, $hm); - ($pv, $iv, $nv, $rv, $hm) = Data::Peek::DDual($val) if $dp; - - if ($dp && ($test->[3] & DBIstcf_DISCARD_STRING)) { - #diag("D::P ",neat($pv), ",", neat($iv), ",", neat($nv), - # ",", neat($rv)); - SKIP: { - skip 'DiscardString not supported in PurePerl', 1 if $pp; - - ok(!defined($pv), "discard works, $test->[0]") if $dp; - }; - } - if (($test->[2] == SQL_DOUBLE) && ($dp)) { - #diag("D::P ", neat($pv), ",", neat($iv), ",", neat($nv), - # ",", neat($rv)); - if ($test->[4] == CAST_OK) { - ok(defined($nv), "nv defined $test->[0]"); - } else { - ok(!defined($nv) || !$nv, "nv not defined $test->[0]"); - } - } -} - -1; diff --git a/dbLifeLog/DBI-1.641/t/91_store_warning.t b/dbLifeLog/DBI-1.641/t/91_store_warning.t deleted file mode 100644 index 0b7509b..0000000 --- a/dbLifeLog/DBI-1.641/t/91_store_warning.t +++ /dev/null @@ -1,37 +0,0 @@ -# Test if a warning can be recorded in the STORE method -# which it couldn't in DBI 1.628 -# see https://rt.cpan.org/Ticket/Display.html?id=89015 -# This is all started from the fact that the SQLite ODBC Driver cannot set the -# ReadOnly attribute (which is mapped to ODBC SQL_ACCESS_MODE) - it -# legitimately returns SQL_SUCCESS_WITH_INFO option value changed. -# It was decided that this should record a warning but when it was added to DBD::ODBC -# DBI did not show the warning - keep_err? -# Tim's comment on #dbi was: -# the dispatcher has logic to notice if ErrCount went up during a call and disables keep_err in that case. -# I think something similar might be needed for err. E.g., "if it's defined now but wasn't defined before" then -# act appropriately. - -use strict; -use warnings; -use Test::More; -use DBI; - -my $warning; - -$SIG{__WARN__} = sub { $warning = $_[0] }; - -my $dbh = DBI->connect('dbi:NullP:', '', '', {PrintWarn => 1}); - -is $warning, undef, 'initially not set'; - -$dbh->set_err("0", "warning plain"); -like $warning, qr/^DBD::\w+::db set_err warning: warning plain/, "Warning recorded by store"; - -$dbh->set_err(undef, undef); -undef $warning; - -$dbh->set_err("0", "warning \N{U+263A} smiley face"); -like $warning, qr/^DBD::\w+::db set_err warning: warning \x{263A} smiley face/, "Warning recorded by store" - or warn DBI::data_string_desc($warning); - -done_testing; diff --git a/dbLifeLog/DBI-1.641/t/lib.pl b/dbLifeLog/DBI-1.641/t/lib.pl deleted file mode 100644 index 655af7f..0000000 --- a/dbLifeLog/DBI-1.641/t/lib.pl +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/perl - -# lib.pl is the file where database specific things should live, -# wherever possible. For example, you define certain constants -# here and the like. - -use strict; - -use File::Basename; -use File::Path; -use File::Spec; - -my $test_dir; -END { defined( $test_dir ) and rmtree $test_dir } - -sub test_dir -{ - unless( defined( $test_dir ) ) - { - $test_dir = File::Spec->rel2abs( File::Spec->curdir () ); - $test_dir = File::Spec->catdir ( $test_dir, "test_output_" . $$ ); - $test_dir = VMS::Filespec::unixify($test_dir) if $^O eq 'VMS'; - rmtree $test_dir if -d $test_dir; - mkpath $test_dir; - # There must be at least one directory in the test directory, - # and nothing guarantees that dot or dot-dot directories will exist. - mkpath ( File::Spec->catdir( $test_dir, '000_just_testing' ) ); - } - - return $test_dir; -} - -1; diff --git a/dbLifeLog/DBI-1.641/t/pod-coverage.t b/dbLifeLog/DBI-1.641/t/pod-coverage.t deleted file mode 100644 index 64c2d58..0000000 --- a/dbLifeLog/DBI-1.641/t/pod-coverage.t +++ /dev/null @@ -1,8 +0,0 @@ -#!perl -T - -use Test::More; -eval "use Test::Pod::Coverage 1.04"; -plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; -plan skip_all => "Currently a developer-only test" unless -d '.svn' || -d ".git"; -plan skip_all => "Currently FAILS FOR MANY MODULES!"; -all_pod_coverage_ok(); diff --git a/dbLifeLog/DBI-1.641/t/pod.t b/dbLifeLog/DBI-1.641/t/pod.t deleted file mode 100644 index 5abfd6a..0000000 --- a/dbLifeLog/DBI-1.641/t/pod.t +++ /dev/null @@ -1,8 +0,0 @@ -#!perl -w - -use Test::More; -eval "use Test::Pod 1.41"; -plan skip_all => "Test::Pod 1.41 required for testing POD" if $@; -all_pod_files_ok(); - -1; diff --git a/dbLifeLog/DBI-1.641/t/zvg_01basics.t b/dbLifeLog/DBI-1.641/t/zvg_01basics.t deleted file mode 100644 index c15e3a6..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_01basics.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/01basics.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_02dbidrv.t b/dbLifeLog/DBI-1.641/t/zvg_02dbidrv.t deleted file mode 100644 index f79cd50..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_02dbidrv.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/02dbidrv.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_03handle.t b/dbLifeLog/DBI-1.641/t/zvg_03handle.t deleted file mode 100644 index 4a7eb8f..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_03handle.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/03handle.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_04mods.t b/dbLifeLog/DBI-1.641/t/zvg_04mods.t deleted file mode 100644 index 79b63db..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_04mods.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/04mods.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_05concathash.t b/dbLifeLog/DBI-1.641/t/zvg_05concathash.t deleted file mode 100644 index f4a67e2..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_05concathash.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/05concathash.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_06attrs.t b/dbLifeLog/DBI-1.641/t/zvg_06attrs.t deleted file mode 100644 index 84af024..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_06attrs.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/06attrs.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_07kids.t b/dbLifeLog/DBI-1.641/t/zvg_07kids.t deleted file mode 100644 index 32bfbcf..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_07kids.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/07kids.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_08keeperr.t b/dbLifeLog/DBI-1.641/t/zvg_08keeperr.t deleted file mode 100644 index ab1a67c..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_08keeperr.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/08keeperr.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_09trace.t b/dbLifeLog/DBI-1.641/t/zvg_09trace.t deleted file mode 100644 index 35a0a82..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_09trace.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/09trace.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_10examp.t b/dbLifeLog/DBI-1.641/t/zvg_10examp.t deleted file mode 100644 index 74b3475..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_10examp.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/10examp.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_11fetch.t b/dbLifeLog/DBI-1.641/t/zvg_11fetch.t deleted file mode 100644 index 860a4fd..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_11fetch.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/11fetch.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_12quote.t b/dbLifeLog/DBI-1.641/t/zvg_12quote.t deleted file mode 100644 index 939b451..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_12quote.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/12quote.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_13taint.t b/dbLifeLog/DBI-1.641/t/zvg_13taint.t deleted file mode 100644 index 8d3e91e..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_13taint.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -wT -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/13taint.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_14utf8.t b/dbLifeLog/DBI-1.641/t/zvg_14utf8.t deleted file mode 100644 index b705535..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_14utf8.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/14utf8.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_15array.t b/dbLifeLog/DBI-1.641/t/zvg_15array.t deleted file mode 100644 index e7b5a53..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_15array.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/15array.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_16destroy.t b/dbLifeLog/DBI-1.641/t/zvg_16destroy.t deleted file mode 100644 index 59fe964..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_16destroy.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/16destroy.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_19fhtrace.t b/dbLifeLog/DBI-1.641/t/zvg_19fhtrace.t deleted file mode 100644 index 250feb9..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_19fhtrace.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/19fhtrace.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_20meta.t b/dbLifeLog/DBI-1.641/t/zvg_20meta.t deleted file mode 100644 index e03ac3f..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_20meta.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/20meta.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_30subclass.t b/dbLifeLog/DBI-1.641/t/zvg_30subclass.t deleted file mode 100644 index 8a01811..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_30subclass.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/30subclass.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_31methcache.t b/dbLifeLog/DBI-1.641/t/zvg_31methcache.t deleted file mode 100644 index 4215fc5..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_31methcache.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/31methcache.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_35thrclone.t b/dbLifeLog/DBI-1.641/t/zvg_35thrclone.t deleted file mode 100644 index a07af56..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_35thrclone.t +++ /dev/null @@ -1,5 +0,0 @@ -#!perl -w -use threads; -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/35thrclone.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_40profile.t b/dbLifeLog/DBI-1.641/t/zvg_40profile.t deleted file mode 100644 index 4095435..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_40profile.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/40profile.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_41prof_dump.t b/dbLifeLog/DBI-1.641/t/zvg_41prof_dump.t deleted file mode 100644 index da99a35..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_41prof_dump.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/41prof_dump.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_42prof_data.t b/dbLifeLog/DBI-1.641/t/zvg_42prof_data.t deleted file mode 100644 index 848b3e8..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_42prof_data.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/42prof_data.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_43prof_env.t b/dbLifeLog/DBI-1.641/t/zvg_43prof_env.t deleted file mode 100644 index 07d3fae..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_43prof_env.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/43prof_env.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_48dbi_dbd_sqlengine.t b/dbLifeLog/DBI-1.641/t/zvg_48dbi_dbd_sqlengine.t deleted file mode 100644 index 888f1f6..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_48dbi_dbd_sqlengine.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/48dbi_dbd_sqlengine.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_49dbd_file.t b/dbLifeLog/DBI-1.641/t/zvg_49dbd_file.t deleted file mode 100644 index 81acf17..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_49dbd_file.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/49dbd_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_50dbm_simple.t b/dbLifeLog/DBI-1.641/t/zvg_50dbm_simple.t deleted file mode 100644 index 24c68fe..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_50dbm_simple.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/50dbm_simple.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_51dbm_file.t b/dbLifeLog/DBI-1.641/t/zvg_51dbm_file.t deleted file mode 100644 index 41714bf..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_51dbm_file.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/51dbm_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_52dbm_complex.t b/dbLifeLog/DBI-1.641/t/zvg_52dbm_complex.t deleted file mode 100644 index a3b4430..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_52dbm_complex.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/52dbm_complex.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_53sqlengine_adv.t b/dbLifeLog/DBI-1.641/t/zvg_53sqlengine_adv.t deleted file mode 100644 index 39bb868..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_53sqlengine_adv.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/53sqlengine_adv.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_54_dbd_mem.t b/dbLifeLog/DBI-1.641/t/zvg_54_dbd_mem.t deleted file mode 100644 index 0778d27..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_54_dbd_mem.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/54_dbd_mem.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_60preparse.t b/dbLifeLog/DBI-1.641/t/zvg_60preparse.t deleted file mode 100644 index 84d03e5..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_60preparse.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/60preparse.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_65transact.t b/dbLifeLog/DBI-1.641/t/zvg_65transact.t deleted file mode 100644 index 465f19d..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_65transact.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/65transact.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_70callbacks.t b/dbLifeLog/DBI-1.641/t/zvg_70callbacks.t deleted file mode 100644 index 9ad9579..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_70callbacks.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/70callbacks.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_72childhandles.t b/dbLifeLog/DBI-1.641/t/zvg_72childhandles.t deleted file mode 100644 index f789139..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_72childhandles.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/72childhandles.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_73cachedkids.t b/dbLifeLog/DBI-1.641/t/zvg_73cachedkids.t deleted file mode 100644 index 68a4de8..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_73cachedkids.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/73cachedkids.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_80proxy.t b/dbLifeLog/DBI-1.641/t/zvg_80proxy.t deleted file mode 100644 index 9ed5d14..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_80proxy.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/80proxy.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_85gofer.t b/dbLifeLog/DBI-1.641/t/zvg_85gofer.t deleted file mode 100644 index c779189..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_85gofer.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/85gofer.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_86gofer_fail.t b/dbLifeLog/DBI-1.641/t/zvg_86gofer_fail.t deleted file mode 100644 index 77d7726..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_86gofer_fail.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/86gofer_fail.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_87gofer_cache.t b/dbLifeLog/DBI-1.641/t/zvg_87gofer_cache.t deleted file mode 100644 index d10d52a..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_87gofer_cache.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/87gofer_cache.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_90sql_type_cast.t b/dbLifeLog/DBI-1.641/t/zvg_90sql_type_cast.t deleted file mode 100644 index 3f90638..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_90sql_type_cast.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/90sql_type_cast.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvg_91_store_warning.t b/dbLifeLog/DBI-1.641/t/zvg_91_store_warning.t deleted file mode 100644 index 4021d16..0000000 --- a/dbLifeLog/DBI-1.641/t/zvg_91_store_warning.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -require './t/91_store_warning.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvn_48dbi_dbd_sqlengine.t b/dbLifeLog/DBI-1.641/t/zvn_48dbi_dbd_sqlengine.t deleted file mode 100644 index 31a1ce9..0000000 --- a/dbLifeLog/DBI-1.641/t/zvn_48dbi_dbd_sqlengine.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/48dbi_dbd_sqlengine.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvn_49dbd_file.t b/dbLifeLog/DBI-1.641/t/zvn_49dbd_file.t deleted file mode 100644 index e720a46..0000000 --- a/dbLifeLog/DBI-1.641/t/zvn_49dbd_file.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/49dbd_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvn_50dbm_simple.t b/dbLifeLog/DBI-1.641/t/zvn_50dbm_simple.t deleted file mode 100644 index 4d2c4fb..0000000 --- a/dbLifeLog/DBI-1.641/t/zvn_50dbm_simple.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/50dbm_simple.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvn_51dbm_file.t b/dbLifeLog/DBI-1.641/t/zvn_51dbm_file.t deleted file mode 100644 index fedc52a..0000000 --- a/dbLifeLog/DBI-1.641/t/zvn_51dbm_file.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/51dbm_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvn_52dbm_complex.t b/dbLifeLog/DBI-1.641/t/zvn_52dbm_complex.t deleted file mode 100644 index 705b59c..0000000 --- a/dbLifeLog/DBI-1.641/t/zvn_52dbm_complex.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/52dbm_complex.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvn_85gofer.t b/dbLifeLog/DBI-1.641/t/zvn_85gofer.t deleted file mode 100644 index afdd601..0000000 --- a/dbLifeLog/DBI-1.641/t/zvn_85gofer.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/85gofer.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_01basics.t b/dbLifeLog/DBI-1.641/t/zvp_01basics.t deleted file mode 100644 index b6bcc73..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_01basics.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/01basics.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_02dbidrv.t b/dbLifeLog/DBI-1.641/t/zvp_02dbidrv.t deleted file mode 100644 index 1e011ff..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_02dbidrv.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/02dbidrv.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_03handle.t b/dbLifeLog/DBI-1.641/t/zvp_03handle.t deleted file mode 100644 index 0d10e3a..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_03handle.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/03handle.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_04mods.t b/dbLifeLog/DBI-1.641/t/zvp_04mods.t deleted file mode 100644 index a1a57fd..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_04mods.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/04mods.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_05concathash.t b/dbLifeLog/DBI-1.641/t/zvp_05concathash.t deleted file mode 100644 index 49f702a..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_05concathash.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/05concathash.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_06attrs.t b/dbLifeLog/DBI-1.641/t/zvp_06attrs.t deleted file mode 100644 index 8e93f4d..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_06attrs.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/06attrs.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_07kids.t b/dbLifeLog/DBI-1.641/t/zvp_07kids.t deleted file mode 100644 index 48b0ae7..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_07kids.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/07kids.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_08keeperr.t b/dbLifeLog/DBI-1.641/t/zvp_08keeperr.t deleted file mode 100644 index 2fa47f7..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_08keeperr.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/08keeperr.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_09trace.t b/dbLifeLog/DBI-1.641/t/zvp_09trace.t deleted file mode 100644 index 9469658..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_09trace.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/09trace.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_10examp.t b/dbLifeLog/DBI-1.641/t/zvp_10examp.t deleted file mode 100644 index 2f4fbea..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_10examp.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/10examp.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_11fetch.t b/dbLifeLog/DBI-1.641/t/zvp_11fetch.t deleted file mode 100644 index 1e8b7e2..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_11fetch.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/11fetch.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_12quote.t b/dbLifeLog/DBI-1.641/t/zvp_12quote.t deleted file mode 100644 index bf991e0..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_12quote.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/12quote.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_13taint.t b/dbLifeLog/DBI-1.641/t/zvp_13taint.t deleted file mode 100644 index 6b3a80b..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_13taint.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -wT -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/13taint.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_14utf8.t b/dbLifeLog/DBI-1.641/t/zvp_14utf8.t deleted file mode 100644 index a5089a4..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_14utf8.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/14utf8.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_15array.t b/dbLifeLog/DBI-1.641/t/zvp_15array.t deleted file mode 100644 index 4a6a04b..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_15array.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/15array.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_16destroy.t b/dbLifeLog/DBI-1.641/t/zvp_16destroy.t deleted file mode 100644 index 4575638..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_16destroy.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/16destroy.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_19fhtrace.t b/dbLifeLog/DBI-1.641/t/zvp_19fhtrace.t deleted file mode 100644 index 00c1e3d..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_19fhtrace.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/19fhtrace.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_20meta.t b/dbLifeLog/DBI-1.641/t/zvp_20meta.t deleted file mode 100644 index 12e1235..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_20meta.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/20meta.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_30subclass.t b/dbLifeLog/DBI-1.641/t/zvp_30subclass.t deleted file mode 100644 index 8dc946a..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_30subclass.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/30subclass.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_31methcache.t b/dbLifeLog/DBI-1.641/t/zvp_31methcache.t deleted file mode 100644 index b5c9304..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_31methcache.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/31methcache.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_35thrclone.t b/dbLifeLog/DBI-1.641/t/zvp_35thrclone.t deleted file mode 100644 index 5f55ec2..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_35thrclone.t +++ /dev/null @@ -1,5 +0,0 @@ -#!perl -w -use threads; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/35thrclone.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_40profile.t b/dbLifeLog/DBI-1.641/t/zvp_40profile.t deleted file mode 100644 index 15f6e8d..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_40profile.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/40profile.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_41prof_dump.t b/dbLifeLog/DBI-1.641/t/zvp_41prof_dump.t deleted file mode 100644 index b8daff7..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_41prof_dump.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/41prof_dump.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_42prof_data.t b/dbLifeLog/DBI-1.641/t/zvp_42prof_data.t deleted file mode 100644 index 6fdb60d..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_42prof_data.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/42prof_data.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_43prof_env.t b/dbLifeLog/DBI-1.641/t/zvp_43prof_env.t deleted file mode 100644 index b7c26ad..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_43prof_env.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/43prof_env.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_48dbi_dbd_sqlengine.t b/dbLifeLog/DBI-1.641/t/zvp_48dbi_dbd_sqlengine.t deleted file mode 100644 index cd51d56..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_48dbi_dbd_sqlengine.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/48dbi_dbd_sqlengine.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_49dbd_file.t b/dbLifeLog/DBI-1.641/t/zvp_49dbd_file.t deleted file mode 100644 index 4c7b2c6..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_49dbd_file.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/49dbd_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_50dbm_simple.t b/dbLifeLog/DBI-1.641/t/zvp_50dbm_simple.t deleted file mode 100644 index 35e2f14..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_50dbm_simple.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/50dbm_simple.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_51dbm_file.t b/dbLifeLog/DBI-1.641/t/zvp_51dbm_file.t deleted file mode 100644 index 39c9802..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_51dbm_file.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/51dbm_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_52dbm_complex.t b/dbLifeLog/DBI-1.641/t/zvp_52dbm_complex.t deleted file mode 100644 index b3e2a50..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_52dbm_complex.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/52dbm_complex.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_53sqlengine_adv.t b/dbLifeLog/DBI-1.641/t/zvp_53sqlengine_adv.t deleted file mode 100644 index 4cece27..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_53sqlengine_adv.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/53sqlengine_adv.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_54_dbd_mem.t b/dbLifeLog/DBI-1.641/t/zvp_54_dbd_mem.t deleted file mode 100644 index b84359c..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_54_dbd_mem.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/54_dbd_mem.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_60preparse.t b/dbLifeLog/DBI-1.641/t/zvp_60preparse.t deleted file mode 100644 index ac068ea..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_60preparse.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/60preparse.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_65transact.t b/dbLifeLog/DBI-1.641/t/zvp_65transact.t deleted file mode 100644 index a3ac2c8..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_65transact.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/65transact.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_70callbacks.t b/dbLifeLog/DBI-1.641/t/zvp_70callbacks.t deleted file mode 100644 index 0eaee67..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_70callbacks.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/70callbacks.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_72childhandles.t b/dbLifeLog/DBI-1.641/t/zvp_72childhandles.t deleted file mode 100644 index bf02458..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_72childhandles.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/72childhandles.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_73cachedkids.t b/dbLifeLog/DBI-1.641/t/zvp_73cachedkids.t deleted file mode 100644 index 41e6959..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_73cachedkids.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/73cachedkids.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_80proxy.t b/dbLifeLog/DBI-1.641/t/zvp_80proxy.t deleted file mode 100644 index 728b7c8..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_80proxy.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/80proxy.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_85gofer.t b/dbLifeLog/DBI-1.641/t/zvp_85gofer.t deleted file mode 100644 index 412a9b7..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_85gofer.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/85gofer.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_86gofer_fail.t b/dbLifeLog/DBI-1.641/t/zvp_86gofer_fail.t deleted file mode 100644 index 50a594c..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_86gofer_fail.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/86gofer_fail.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_87gofer_cache.t b/dbLifeLog/DBI-1.641/t/zvp_87gofer_cache.t deleted file mode 100644 index 3e3a090..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_87gofer_cache.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/87gofer_cache.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_90sql_type_cast.t b/dbLifeLog/DBI-1.641/t/zvp_90sql_type_cast.t deleted file mode 100644 index d2a798d..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_90sql_type_cast.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/90sql_type_cast.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvp_91_store_warning.t b/dbLifeLog/DBI-1.641/t/zvp_91_store_warning.t deleted file mode 100644 index 6a77c07..0000000 --- a/dbLifeLog/DBI-1.641/t/zvp_91_store_warning.t +++ /dev/null @@ -1,4 +0,0 @@ -#!perl -w -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/91_store_warning.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgn_48dbi_dbd_sqlengine.t b/dbLifeLog/DBI-1.641/t/zvxgn_48dbi_dbd_sqlengine.t deleted file mode 100644 index 5473eb4..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgn_48dbi_dbd_sqlengine.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/48dbi_dbd_sqlengine.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgn_49dbd_file.t b/dbLifeLog/DBI-1.641/t/zvxgn_49dbd_file.t deleted file mode 100644 index c8e2461..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgn_49dbd_file.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/49dbd_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgn_50dbm_simple.t b/dbLifeLog/DBI-1.641/t/zvxgn_50dbm_simple.t deleted file mode 100644 index 9a7fbe2..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgn_50dbm_simple.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/50dbm_simple.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgn_51dbm_file.t b/dbLifeLog/DBI-1.641/t/zvxgn_51dbm_file.t deleted file mode 100644 index 9f2d3e5..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgn_51dbm_file.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/51dbm_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgn_52dbm_complex.t b/dbLifeLog/DBI-1.641/t/zvxgn_52dbm_complex.t deleted file mode 100644 index e7377a3..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgn_52dbm_complex.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/52dbm_complex.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgn_85gofer.t b/dbLifeLog/DBI-1.641/t/zvxgn_85gofer.t deleted file mode 100644 index d4f9857..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgn_85gofer.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -require './t/85gofer.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgnp_48dbi_dbd_sqlengine.t b/dbLifeLog/DBI-1.641/t/zvxgnp_48dbi_dbd_sqlengine.t deleted file mode 100644 index 270f7db..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgnp_48dbi_dbd_sqlengine.t +++ /dev/null @@ -1,8 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/48dbi_dbd_sqlengine.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgnp_49dbd_file.t b/dbLifeLog/DBI-1.641/t/zvxgnp_49dbd_file.t deleted file mode 100644 index 94d1b34..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgnp_49dbd_file.t +++ /dev/null @@ -1,8 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/49dbd_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgnp_50dbm_simple.t b/dbLifeLog/DBI-1.641/t/zvxgnp_50dbm_simple.t deleted file mode 100644 index 18111a5..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgnp_50dbm_simple.t +++ /dev/null @@ -1,8 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/50dbm_simple.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgnp_51dbm_file.t b/dbLifeLog/DBI-1.641/t/zvxgnp_51dbm_file.t deleted file mode 100644 index ad7a603..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgnp_51dbm_file.t +++ /dev/null @@ -1,8 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/51dbm_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgnp_52dbm_complex.t b/dbLifeLog/DBI-1.641/t/zvxgnp_52dbm_complex.t deleted file mode 100644 index f778437..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgnp_52dbm_complex.t +++ /dev/null @@ -1,8 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/52dbm_complex.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgnp_85gofer.t b/dbLifeLog/DBI-1.641/t/zvxgnp_85gofer.t deleted file mode 100644 index c86fc2e..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgnp_85gofer.t +++ /dev/null @@ -1,8 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/85gofer.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_01basics.t b/dbLifeLog/DBI-1.641/t/zvxgp_01basics.t deleted file mode 100644 index e161755..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_01basics.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/01basics.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_02dbidrv.t b/dbLifeLog/DBI-1.641/t/zvxgp_02dbidrv.t deleted file mode 100644 index 2703407..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_02dbidrv.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/02dbidrv.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_03handle.t b/dbLifeLog/DBI-1.641/t/zvxgp_03handle.t deleted file mode 100644 index 350d47f..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_03handle.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/03handle.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_04mods.t b/dbLifeLog/DBI-1.641/t/zvxgp_04mods.t deleted file mode 100644 index d871078..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_04mods.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/04mods.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_05concathash.t b/dbLifeLog/DBI-1.641/t/zvxgp_05concathash.t deleted file mode 100644 index db4b17f..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_05concathash.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/05concathash.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_06attrs.t b/dbLifeLog/DBI-1.641/t/zvxgp_06attrs.t deleted file mode 100644 index 69f4a80..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_06attrs.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/06attrs.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_07kids.t b/dbLifeLog/DBI-1.641/t/zvxgp_07kids.t deleted file mode 100644 index 8a583d8..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_07kids.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/07kids.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_08keeperr.t b/dbLifeLog/DBI-1.641/t/zvxgp_08keeperr.t deleted file mode 100644 index 2931833..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_08keeperr.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/08keeperr.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_09trace.t b/dbLifeLog/DBI-1.641/t/zvxgp_09trace.t deleted file mode 100644 index 06dfb6c..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_09trace.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/09trace.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_10examp.t b/dbLifeLog/DBI-1.641/t/zvxgp_10examp.t deleted file mode 100644 index 29fd8e1..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_10examp.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/10examp.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_11fetch.t b/dbLifeLog/DBI-1.641/t/zvxgp_11fetch.t deleted file mode 100644 index f3b3e58..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_11fetch.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/11fetch.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_12quote.t b/dbLifeLog/DBI-1.641/t/zvxgp_12quote.t deleted file mode 100644 index 3aba1ac..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_12quote.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/12quote.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_13taint.t b/dbLifeLog/DBI-1.641/t/zvxgp_13taint.t deleted file mode 100644 index 54ae540..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_13taint.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -wT -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/13taint.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_14utf8.t b/dbLifeLog/DBI-1.641/t/zvxgp_14utf8.t deleted file mode 100644 index b5eddd4..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_14utf8.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/14utf8.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_15array.t b/dbLifeLog/DBI-1.641/t/zvxgp_15array.t deleted file mode 100644 index 42568db..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_15array.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/15array.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_16destroy.t b/dbLifeLog/DBI-1.641/t/zvxgp_16destroy.t deleted file mode 100644 index c87e42a..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_16destroy.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/16destroy.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_19fhtrace.t b/dbLifeLog/DBI-1.641/t/zvxgp_19fhtrace.t deleted file mode 100644 index b58cb1d..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_19fhtrace.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/19fhtrace.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_20meta.t b/dbLifeLog/DBI-1.641/t/zvxgp_20meta.t deleted file mode 100644 index 4ec9dc5..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_20meta.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/20meta.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_30subclass.t b/dbLifeLog/DBI-1.641/t/zvxgp_30subclass.t deleted file mode 100644 index 0babc6f..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_30subclass.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/30subclass.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_31methcache.t b/dbLifeLog/DBI-1.641/t/zvxgp_31methcache.t deleted file mode 100644 index 2075770..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_31methcache.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/31methcache.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_35thrclone.t b/dbLifeLog/DBI-1.641/t/zvxgp_35thrclone.t deleted file mode 100644 index 83fdf80..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_35thrclone.t +++ /dev/null @@ -1,7 +0,0 @@ -#!perl -w -use threads; -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/35thrclone.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_40profile.t b/dbLifeLog/DBI-1.641/t/zvxgp_40profile.t deleted file mode 100644 index 7c25bba..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_40profile.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/40profile.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_41prof_dump.t b/dbLifeLog/DBI-1.641/t/zvxgp_41prof_dump.t deleted file mode 100644 index 08f3e4c..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_41prof_dump.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/41prof_dump.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_42prof_data.t b/dbLifeLog/DBI-1.641/t/zvxgp_42prof_data.t deleted file mode 100644 index 2d10b1d..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_42prof_data.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/42prof_data.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_43prof_env.t b/dbLifeLog/DBI-1.641/t/zvxgp_43prof_env.t deleted file mode 100644 index 41f3f64..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_43prof_env.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/43prof_env.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_48dbi_dbd_sqlengine.t b/dbLifeLog/DBI-1.641/t/zvxgp_48dbi_dbd_sqlengine.t deleted file mode 100644 index 06040ba..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_48dbi_dbd_sqlengine.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/48dbi_dbd_sqlengine.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_49dbd_file.t b/dbLifeLog/DBI-1.641/t/zvxgp_49dbd_file.t deleted file mode 100644 index 79f446e..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_49dbd_file.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/49dbd_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_50dbm_simple.t b/dbLifeLog/DBI-1.641/t/zvxgp_50dbm_simple.t deleted file mode 100644 index d941a0b..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_50dbm_simple.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/50dbm_simple.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_51dbm_file.t b/dbLifeLog/DBI-1.641/t/zvxgp_51dbm_file.t deleted file mode 100644 index 5763f48..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_51dbm_file.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/51dbm_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_52dbm_complex.t b/dbLifeLog/DBI-1.641/t/zvxgp_52dbm_complex.t deleted file mode 100644 index 35e6745..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_52dbm_complex.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/52dbm_complex.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_53sqlengine_adv.t b/dbLifeLog/DBI-1.641/t/zvxgp_53sqlengine_adv.t deleted file mode 100644 index 1ca0838..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_53sqlengine_adv.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/53sqlengine_adv.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_54_dbd_mem.t b/dbLifeLog/DBI-1.641/t/zvxgp_54_dbd_mem.t deleted file mode 100644 index 5dfc66e..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_54_dbd_mem.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/54_dbd_mem.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_60preparse.t b/dbLifeLog/DBI-1.641/t/zvxgp_60preparse.t deleted file mode 100644 index 9667190..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_60preparse.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/60preparse.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_65transact.t b/dbLifeLog/DBI-1.641/t/zvxgp_65transact.t deleted file mode 100644 index 55a9fff..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_65transact.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/65transact.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_70callbacks.t b/dbLifeLog/DBI-1.641/t/zvxgp_70callbacks.t deleted file mode 100644 index 9f87dde..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_70callbacks.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/70callbacks.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_72childhandles.t b/dbLifeLog/DBI-1.641/t/zvxgp_72childhandles.t deleted file mode 100644 index f388228..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_72childhandles.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/72childhandles.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_73cachedkids.t b/dbLifeLog/DBI-1.641/t/zvxgp_73cachedkids.t deleted file mode 100644 index b61cecf..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_73cachedkids.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/73cachedkids.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_80proxy.t b/dbLifeLog/DBI-1.641/t/zvxgp_80proxy.t deleted file mode 100644 index 2db54b1..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_80proxy.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/80proxy.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_85gofer.t b/dbLifeLog/DBI-1.641/t/zvxgp_85gofer.t deleted file mode 100644 index 304c472..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_85gofer.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/85gofer.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_86gofer_fail.t b/dbLifeLog/DBI-1.641/t/zvxgp_86gofer_fail.t deleted file mode 100644 index 456c3b0..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_86gofer_fail.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/86gofer_fail.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_87gofer_cache.t b/dbLifeLog/DBI-1.641/t/zvxgp_87gofer_cache.t deleted file mode 100644 index 674fe70..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_87gofer_cache.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/87gofer_cache.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_90sql_type_cast.t b/dbLifeLog/DBI-1.641/t/zvxgp_90sql_type_cast.t deleted file mode 100644 index a8c8bf6..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_90sql_type_cast.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/90sql_type_cast.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxgp_91_store_warning.t b/dbLifeLog/DBI-1.641/t/zvxgp_91_store_warning.t deleted file mode 100644 index c2095fb..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxgp_91_store_warning.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_AUTOPROXY} = 'dbi:Gofer:transport=null;policy=pedantic'; -END { delete $ENV{DBI_AUTOPROXY}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/91_store_warning.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxnp_48dbi_dbd_sqlengine.t b/dbLifeLog/DBI-1.641/t/zvxnp_48dbi_dbd_sqlengine.t deleted file mode 100644 index b79a502..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxnp_48dbi_dbd_sqlengine.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/48dbi_dbd_sqlengine.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxnp_49dbd_file.t b/dbLifeLog/DBI-1.641/t/zvxnp_49dbd_file.t deleted file mode 100644 index 8636402..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxnp_49dbd_file.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/49dbd_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxnp_50dbm_simple.t b/dbLifeLog/DBI-1.641/t/zvxnp_50dbm_simple.t deleted file mode 100644 index 3fe6803..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxnp_50dbm_simple.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/50dbm_simple.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxnp_51dbm_file.t b/dbLifeLog/DBI-1.641/t/zvxnp_51dbm_file.t deleted file mode 100644 index b7873c9..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxnp_51dbm_file.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/51dbm_file.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxnp_52dbm_complex.t b/dbLifeLog/DBI-1.641/t/zvxnp_52dbm_complex.t deleted file mode 100644 index 15f7248..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxnp_52dbm_complex.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/52dbm_complex.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/t/zvxnp_85gofer.t b/dbLifeLog/DBI-1.641/t/zvxnp_85gofer.t deleted file mode 100644 index a8f5802..0000000 --- a/dbLifeLog/DBI-1.641/t/zvxnp_85gofer.t +++ /dev/null @@ -1,6 +0,0 @@ -#!perl -w -$ENV{DBI_SQL_NANO} = 1; -END { delete $ENV{DBI_SQL_NANO}; }; -$ENV{DBI_PUREPERL} = 2; -END { delete $ENV{DBI_PUREPERL}; }; -require './t/85gofer.t'; # or warn $!; diff --git a/dbLifeLog/DBI-1.641/test.pl b/dbLifeLog/DBI-1.641/test.pl deleted file mode 100755 index 4d011cb..0000000 --- a/dbLifeLog/DBI-1.641/test.pl +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/local/bin/perl -w - -# $Id$ -# -# Copyright (c) 1994-1998 Tim Bunce -# -# See COPYRIGHT section in DBI.pm for usage and distribution rights. - - -# This is now mostly an empty shell I experiment with. -# The real tests have moved to t/*.t -# See t/*.t for more detailed tests. - - -BEGIN { - print "$0 @ARGV\n"; - print q{DBI test application $Revision$}."\n"; - $| = 1; -} - -use blib; - -use DBI; - -use DBI::DBD; # simple test to make sure it's okay - -use Config; -use Getopt::Long; -use strict; - -our $has_devel_leak = eval { - local $^W = 0; # silence "Use of uninitialized value $DynaLoader::args[0] in subroutine entry"; - require Devel::Leak; -}; - -$::opt_d = 0; -$::opt_l = ''; -$::opt_h = 0; -$::opt_m = 0; # basic memory leak test: "perl test.pl -m NullP" -$::opt_t = 0; # thread test -$::opt_n = 0; # counter for other options - -GetOptions(qw(d=i h=i l=s m=i t=i n=i)) - or die "Usage: $0 [-d n] [-h n] [-m n] [-t n] [-n n] [drivername]\n"; - -my $count = 0; -my $ps = (-d '/proc') ? "ps -lp " : "ps -l"; -my $driver = $ARGV[0] || ($::opt_m ? 'NullP' : 'ExampleP'); - -# Now ask for some information from the DBI Switch -my $switch = DBI->internal; -$switch->trace($::opt_h); # 2=detailed handle trace - -DBI->trace($::opt_d, $::opt_l) if $::opt_d || $::opt_l; - -print "Switch: $switch->{'Attribution'}, $switch->{'Version'}\n"; - -print "Available Drivers: ",join(", ",DBI->available_drivers(1)),"\n"; - - -my $dbh = DBI->connect("dbi:$driver:", '', '', { RaiseError=>1 }) or die; -$dbh->trace($::opt_h); - -if (0) { - DBI->trace(3); - my $h = DBI->connect('dbi:NullP:','','', { RootClass=>'MyTestDBI', DbTypeSubclass=>'foo, bar' }); - DBI->trace(0); - { # only works after 5.004_04: - warn "RaiseError= '$h->{RaiseError}' (pre local)\n"; - local($h->{RaiseError});# = undef; - warn "RaiseError= '$h->{RaiseError}' (post local)\n"; - } - warn "RaiseError= '$h->{RaiseError}' (post local block)\n"; - exit 1; -} - -if ($::opt_m) { - #$dbh->trace(9); - my $level = $::opt_m; - my $cnt = $::opt_n || 10000; - - print "Using $driver, same dbh...\n"; - for (my $i=0; $i<$cnt; ++$i) { mem_test($dbh, undef, $level, undef, undef, undef) } - - print "Using NullP, reconnecting each time...\n"; - for (my $i=0; $i<$cnt; ++$i) { mem_test(undef, ['dbi:NullP:'], $level, undef, undef, undef) } - - print "Using ExampleP, reconnecting each time...\n"; - my $r_develleak = 0; - mem_test(undef, ['dbi:NullP:'], $level, undef, undef, \$r_develleak) while 1; - #mem_test(undef, ['dbi:mysql:VC'], $level, "select * from campaigns where length(?)>0", 0, undef) while 1; -} -elsif ($::opt_t) { - thread_test(); -} -else { - - # new experimental connect_test_perf method - DBI->connect_test_perf("dbi:$driver:", '', '', { - dbi_loops=>3, dbi_par=>20, dbi_verb=>1 - }); - - require Benchmark; - print "Testing handle creation speed...\n"; - my $null_dbh = DBI->connect('dbi:NullP:','',''); - my $null_sth = $null_dbh->prepare(''); # create one to warm up - $count = 20_000; - $count /= 10 if $ENV{DBI_AUTOPROXY}; - my $i = $count; - my $t1 = new Benchmark; - $null_dbh->prepare('') while $i--; - my $td = Benchmark::timediff(Benchmark->new, $t1); - my $tds= Benchmark::timestr($td); - my $dur = $td->cpu_a || (1/$count); # fudge if cpu_a==0 - - printf "%5d NullP sth/s perl %8s %s (%s %s %s) %fs\n\n", - $count/$dur, $], $Config{archname}, - $Config{gccversion} ? 'gcc' : $Config{cc}, - (split / /, $Config{gccversion}||$Config{ccversion}||'')[0]||'', - $Config{optimize}, - $dur/$count; - - $null_dbh->disconnect; -} - -$dbh->disconnect; - -#DBI->trace(4); -print "$0 done\n"; -exit 0; - - -sub mem_test { # harness to help find basic leaks - my ($orig_dbh, $connect, $level, $select, $params, $r_develleak) = @_; - $select ||= "select mode,ino,name from ?"; - $params ||= [ '.' ]; - - # this can be used to force a 'leak' to check memory use reporting - #$main::leak .= " " x 1000; - system("echo $count; $ps$$") if (($count++ % 2000) == 0); - - my $dbh = $orig_dbh || do { - my ($dsn, $u, $p, $attr) = @$connect; - $attr->{RaiseError} = 1; - DBI->connect($dsn, $u, $p, $attr); - }; - my $cursor_a; - - my ($dl_count, $dl_handle); - if ($has_devel_leak && $$r_develleak++) { - $dbh->trace(2); - $dl_count = Devel::Leak::NoteSV($dl_handle); - } - - my $rows; - $cursor_a = $dbh->prepare($select) if $level >= 2; - $cursor_a->execute(@$params) if $level >= 3; - $cursor_a->fetchrow_hashref() if $level >= 4; - $rows = $cursor_a->fetchall_arrayref({}) if $level >= 4; - $cursor_a->finish if $cursor_a && $cursor_a->{Active}; - undef $cursor_a; - - @{$dbh->{ChildHandles}} = (); - - die Devel::Leak::CheckSV($dl_handle)-$dl_count - if $dl_handle; - - $dbh->disconnect unless $orig_dbh; - undef $dbh; - -} - - -sub thread_test { - require Thread; - my $dbh = DBI->connect("dbi:ExampleP:.", "", "") || die $DBI::err; - #$dbh->trace(4); - my @t; - print "Starting $::opt_t threads:\n"; - foreach(1..$::opt_t) { - print "$_\n"; - push @t, Thread->new(\&thread_test_loop, $dbh, $::opt_n||99); - } - print "Small sleep to allow threads to progress\n"; - sleep 2; - print "Joining threads:\n"; - foreach(@t) { - print "$_\n"; - $_->join - } -} - -sub thread_test_loop { - my $dbh = shift; - my $i = shift || 10; - while($i-- > 0) { - $dbh->selectall_arrayref("select * from ?", undef, "."); - } -} - -# end. diff --git a/dbLifeLog/DBI-1.641/typemap b/dbLifeLog/DBI-1.641/typemap deleted file mode 100644 index c06ec2f..0000000 --- a/dbLifeLog/DBI-1.641/typemap +++ /dev/null @@ -1,3 +0,0 @@ -const char * T_PV -imp_xxh_t * T_PTROBJ -DBI_imp_data_ * T_PTROBJ diff --git a/dbLifeLog/cat b/dbLifeLog/cat deleted file mode 100644 index db5b98c..0000000 --- a/dbLifeLog/cat +++ /dev/null @@ -1 +0,0 @@ -192.168.0.16 diff --git a/dbLifeLog/data_config_test_log.db b/dbLifeLog/data_config_test_log.db deleted file mode 100644 index 06204cb31b901b21ddf840ef569c81bbb8ecbaa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 zcmeI(&u`Oa7zc2_v6Ci<#*?Zks>Y-T1w^9-t4R@JXc9AN%BrI#al{$`scd@JHcvB%VTh&QavY-+RfGdzECLnWs}rg_RXHpC*Y- zyJp(z$*iWG1Wl6KR%`zsqKZMMWfkSk`fjab?buekb$lm_$T=!qRx^cfSI!J=+9I)O z%ZKEwT(CK@IQB1B;@FM$9q~z>h%E~AUhbZlPI2~=v@)1n7ungCK>mPUoR`0JOkcfG z`uM!rY__{%{ai2NLmtGdkSi^Vm`wje5g#-NKmY;|fB*y_009U<00Izz00jPb0+(2t zZ4|R=b-i-qYNdL$TCpqFZmw5vZd5jJQ!U_5#0MAU^M5w)EBaIYvF_>X`M>kO<)4TG z8U!E!0SG_<0uX=z1Rwwb2teS|1&pl5zPz_~&kr8TjRHQBkDdU|1p2chpdqs5*^{*e3wI&?#M;l48>cRUec#HGSA4O}OfQ8b%y<2y}bg=wz- zqevWg6dj5`ocH_vqks>}H0C@K!ON%qlwqhEySSa%orMt}Q^Oy&Cp>WE1PYVd+sn#G z#(GL)#iqLDjyNTg-c2}=#p7Awp~xD~FqoDrZg;(K!u!IC54QY(rbll7Asu;rVLcT0 z$HN$0?2U6`EwlPFMSrco(qHJ$^}qB#_1{GS4FV8=00bZa0SG_<0uX=z1Rwx`|FA$> zWo#`g`{I)9DI@y}Y1!vA*=JPQt0`5@<>dQ+@lXF~5P$##AOHafKmY;|fB*y_009Vm k#sc#FKc4?T;|0d8K>z{}fB*y_009U<00Izz00e}<8#FT|+5i9m diff --git a/dbLifeLog/data_log.db b/dbLifeLog/data_log.db deleted file mode 100644 index db4d3044792acd8d6b10987418a08d2678c1d269..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 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