Hello community,

here is the log from the commit of package perl-Mojo-SQLite for 
openSUSE:Factory checked in at 2017-07-21 22:50:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Mojo-SQLite (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Mojo-SQLite.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Mojo-SQLite"

Fri Jul 21 22:50:39 2017 rev:6 rq:511755 version:3.000

Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Mojo-SQLite/perl-Mojo-SQLite.changes        
2017-06-07 09:56:33.317086128 +0200
+++ /work/SRC/openSUSE:Factory/.perl-Mojo-SQLite.new/perl-Mojo-SQLite.changes   
2017-07-21 22:50:40.377947910 +0200
@@ -1,0 +2,17 @@
+Fri Jul 21 05:50:16 UTC 2017 - [email protected]
+
+- updated to 3.000
+   see /usr/share/doc/packages/perl-Mojo-SQLite/Changes
+
+  3.000     2017-07-20 01:16:50 EDT
+    - Changed default for max_connections attribute to 1.
+    - Added support for sharing the database connection cache between multiple
+      Mojo::SQLite objects. (based on Mojo::Pg 4.0)
+    - Added parent attribute to Mojo::SQLite.
+    - Fixed database connection leak with automatic migrations.
+    - Removed deprecated Mojo::SQLite::PubSub and associated methods and 
attributes.
+      SQLite's serverless nature means it does not have the ability to support
+      client notifications, so it is not possible to implement an efficient
+      pubsub system as in for example PostgreSQL, Redis, or websockets.
+
+-------------------------------------------------------------------

Old:
----
  Mojo-SQLite-2.002.tar.gz

New:
----
  Mojo-SQLite-3.000.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ perl-Mojo-SQLite.spec ++++++
--- /var/tmp/diff_new_pack.3HMY20/_old  2017-07-21 22:50:41.153838461 +0200
+++ /var/tmp/diff_new_pack.3HMY20/_new  2017-07-21 22:50:41.157837896 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           perl-Mojo-SQLite
-Version:        2.002
+Version:        3.000
 Release:        0
 %define cpan_name Mojo-SQLite
 Summary:        Tiny Mojolicious Wrapper for Sqlite
@@ -34,7 +34,7 @@
 BuildRequires:  perl(DBI) >= 1.627
 BuildRequires:  perl(Module::Build::Tiny) >= 0.034
 BuildRequires:  perl(Module::Metadata)
-BuildRequires:  perl(Mojolicious) >= 7.15
+BuildRequires:  perl(Mojolicious) >= 7.32
 BuildRequires:  perl(SQL::Abstract) >= 1.81
 BuildRequires:  perl(Test::More) >= 0.88
 BuildRequires:  perl(URI) >= 1.69
@@ -42,7 +42,7 @@
 BuildRequires:  perl(URI::file) >= 4.21
 Requires:       perl(DBD::SQLite) >= 1.50
 Requires:       perl(DBI) >= 1.627
-Requires:       perl(Mojolicious) >= 7.15
+Requires:       perl(Mojolicious) >= 7.32
 Requires:       perl(SQL::Abstract) >= 1.81
 Requires:       perl(URI) >= 1.69
 Requires:       perl(URI::db) >= 0.15
@@ -52,7 +52,9 @@
 %description
 Mojo::SQLite is a tiny wrapper around DBD::SQLite that makes at
 https://www.sqlite.org/ a lot of fun to use with the at https://mojolico.us
-real-time web framework.
+real-time web framework. Use all at http://sqlite.org/lang.html SQLite has
+to offer, generate CRUD queries from data structures, and manage your
+database schema with migrations.
 
 Database and statement handles are cached automatically, so they can be
 reused transparently to increase performance. And you can handle connection
@@ -84,7 +86,10 @@
 Log" journal is enabled for all connections, allowing multiple processes to
 read and write concurrently to the same database file (but only one can
 write at a time). You can prevent this mode from being enabled by passing
-the option 'no_wal'. See http://sqlite.org/wal.html for more information.
+the option 'no_wal', but note that this is incompatible with SQLite
+databases that have already had WAL mode enabled. See
+http://sqlite.org/wal.html and DBD::SQLite/"journal_mode" for more
+information.
 
   # Performed concurrently
   my $pid = fork || die $!;

++++++ Mojo-SQLite-2.002.tar.gz -> Mojo-SQLite-3.000.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/Build.PL 
new/Mojo-SQLite-3.000/Build.PL
--- old/Mojo-SQLite-2.002/Build.PL      2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/Build.PL      2017-07-20 07:16:52.000000000 +0200
@@ -84,7 +84,7 @@
         "Dan Book <dbook\@cpan.org>"
       ],
       "dist_name" => "Mojo-SQLite",
-      "dist_version" => "2.002",
+      "dist_version" => "3.000",
       "license" => "artistic_2",
       "module_name" => "Mojo::SQLite",
       "recursive_test_files" => 1,
@@ -94,7 +94,7 @@
         "DBI" => "1.627",
         "File::Spec::Functions" => 0,
         "File::Temp" => 0,
-        "Mojolicious" => "7.15",
+        "Mojolicious" => "7.32",
         "SQL::Abstract" => "1.81",
         "Scalar::Util" => 0,
         "URI" => "1.69",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/Changes 
new/Mojo-SQLite-3.000/Changes
--- old/Mojo-SQLite-2.002/Changes       2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/Changes       2017-07-20 07:16:52.000000000 +0200
@@ -1,3 +1,14 @@
+3.000     2017-07-20 01:16:50 EDT
+  - Changed default for max_connections attribute to 1.
+  - Added support for sharing the database connection cache between multiple
+    Mojo::SQLite objects. (based on Mojo::Pg 4.0)
+  - Added parent attribute to Mojo::SQLite.
+  - Fixed database connection leak with automatic migrations.
+  - Removed deprecated Mojo::SQLite::PubSub and associated methods and 
attributes.
+    SQLite's serverless nature means it does not have the ability to support
+    client notifications, so it is not possible to implement an efficient
+    pubsub system as in for example PostgreSQL, Redis, or websockets.
+
 2.002     2017-06-01 14:16:34 EDT
   - Add no_wal option to prevent enabling WAL mode on connection.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/MANIFEST 
new/Mojo-SQLite-3.000/MANIFEST
--- old/Mojo-SQLite-2.002/MANIFEST      2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/MANIFEST      2017-07-20 07:16:52.000000000 +0200
@@ -16,6 +16,7 @@
 examples/blog/lib/Blog/Model/Posts.pm
 examples/blog/migrations/blog.sql
 examples/blog/script/blog
+examples/blog/t/blog.t
 examples/blog/templates/layouts/blog.html.ep
 examples/blog/templates/posts/_form.html.ep
 examples/blog/templates/posts/create.html.ep
@@ -39,5 +40,3 @@
 t/sqlite_lite_app.t
 xt/author/pod-coverage.t
 xt/author/pod-syntax.t
-xt/deprecated/database.t
-xt/deprecated/pubsub.t
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/META.json 
new/Mojo-SQLite-3.000/META.json
--- old/Mojo-SQLite-2.002/META.json     2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/META.json     2017-07-20 07:16:52.000000000 +0200
@@ -43,7 +43,7 @@
             "DBI" : "1.627",
             "File::Spec::Functions" : "0",
             "File::Temp" : "0",
-            "Mojolicious" : "7.15",
+            "Mojolicious" : "7.32",
             "SQL::Abstract" : "1.81",
             "Scalar::Util" : "0",
             "URI" : "1.69",
@@ -66,28 +66,28 @@
    "provides" : {
       "Mojo::SQLite" : {
          "file" : "lib/Mojo/SQLite.pm",
-         "version" : "2.002"
+         "version" : "3.000"
       },
       "Mojo::SQLite::Database" : {
          "file" : "lib/Mojo/SQLite/Database.pm",
-         "version" : "2.002"
+         "version" : "3.000"
       },
       "Mojo::SQLite::Migrations" : {
          "file" : "lib/Mojo/SQLite/Migrations.pm",
-         "version" : "2.002"
+         "version" : "3.000"
       },
       "Mojo::SQLite::PubSub" : {
          "file" : "lib/Mojo/SQLite/PubSub.pm",
-         "version" : "2.002",
+         "version" : "3.000",
          "x_deprecated" : 1
       },
       "Mojo::SQLite::Results" : {
          "file" : "lib/Mojo/SQLite/Results.pm",
-         "version" : "2.002"
+         "version" : "3.000"
       },
       "Mojo::SQLite::Transaction" : {
          "file" : "lib/Mojo/SQLite/Transaction.pm",
-         "version" : "2.002"
+         "version" : "3.000"
       }
    },
    "release_status" : "stable",
@@ -103,7 +103,7 @@
       },
       "x_IRC" : "irc://irc.perl.org/#mojo"
    },
-   "version" : "2.002",
+   "version" : "3.000",
    "x_Dist_Zilla" : {
       "perl" : {
          "version" : "5.026000"
@@ -170,7 +170,7 @@
             "class" : "Dist::Zilla::Plugin::Git::Contributors",
             "config" : {
                "Dist::Zilla::Plugin::Git::Contributors" : {
-                  "git_version" : "2.5.5",
+                  "git_version" : "2.9.4",
                   "include_authors" : 0,
                   "include_releaser" : 1,
                   "order_by" : "name",
@@ -211,7 +211,7 @@
                   "changelog" : "Changes"
                },
                "Dist::Zilla::Role::Git::Repo" : {
-                  "git_version" : "2.5.5",
+                  "git_version" : "2.9.4",
                   "repo_root" : "."
                }
             },
@@ -280,7 +280,7 @@
                   "changelog" : "Changes"
                },
                "Dist::Zilla::Role::Git::Repo" : {
-                  "git_version" : "2.5.5",
+                  "git_version" : "2.9.4",
                   "repo_root" : "."
                },
                "Dist::Zilla::Role::Git::StringFormatter" : {
@@ -297,12 +297,12 @@
                   "branch" : null,
                   "changelog" : "Changes",
                   "signed" : 0,
-                  "tag" : "v2.002",
+                  "tag" : "v3.000",
                   "tag_format" : "v%v",
                   "tag_message" : "v%v"
                },
                "Dist::Zilla::Role::Git::Repo" : {
-                  "git_version" : "2.5.5",
+                  "git_version" : "2.9.4",
                   "repo_root" : "."
                },
                "Dist::Zilla::Role::Git::StringFormatter" : {
@@ -345,7 +345,7 @@
                   "changelog" : "Changes"
                },
                "Dist::Zilla::Role::Git::Repo" : {
-                  "git_version" : "2.5.5",
+                  "git_version" : "2.9.4",
                   "repo_root" : "."
                },
                "Dist::Zilla::Role::Git::StringFormatter" : {
@@ -365,7 +365,7 @@
                   "remotes_must_exist" : 1
                },
                "Dist::Zilla::Role::Git::Repo" : {
-                  "git_version" : "2.5.5",
+                  "git_version" : "2.9.4",
                   "repo_root" : "."
                }
             },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/META.yml 
new/Mojo-SQLite-3.000/META.yml
--- old/Mojo-SQLite-2.002/META.yml      2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/META.yml      2017-07-20 07:16:52.000000000 +0200
@@ -26,30 +26,30 @@
 provides:
   Mojo::SQLite:
     file: lib/Mojo/SQLite.pm
-    version: '2.002'
+    version: '3.000'
   Mojo::SQLite::Database:
     file: lib/Mojo/SQLite/Database.pm
-    version: '2.002'
+    version: '3.000'
   Mojo::SQLite::Migrations:
     file: lib/Mojo/SQLite/Migrations.pm
-    version: '2.002'
+    version: '3.000'
   Mojo::SQLite::PubSub:
     file: lib/Mojo/SQLite/PubSub.pm
-    version: '2.002'
+    version: '3.000'
     x_deprecated: 1
   Mojo::SQLite::Results:
     file: lib/Mojo/SQLite/Results.pm
-    version: '2.002'
+    version: '3.000'
   Mojo::SQLite::Transaction:
     file: lib/Mojo/SQLite/Transaction.pm
-    version: '2.002'
+    version: '3.000'
 requires:
   Carp: '0'
   DBD::SQLite: '1.50'
   DBI: '1.627'
   File::Spec::Functions: '0'
   File::Temp: '0'
-  Mojolicious: '7.15'
+  Mojolicious: '7.32'
   SQL::Abstract: '1.81'
   Scalar::Util: '0'
   URI: '1.69'
@@ -61,7 +61,7 @@
   bugtracker: https://github.com/Grinnz/Mojo-SQLite/issues
   homepage: https://github.com/Grinnz/Mojo-SQLite
   repository: https://github.com/Grinnz/Mojo-SQLite.git
-version: '2.002'
+version: '3.000'
 x_Dist_Zilla:
   perl:
     version: '5.026000'
@@ -113,7 +113,7 @@
       class: Dist::Zilla::Plugin::Git::Contributors
       config:
         Dist::Zilla::Plugin::Git::Contributors:
-          git_version: 2.5.5
+          git_version: 2.9.4
           include_authors: 0
           include_releaser: 1
           order_by: name
@@ -145,7 +145,7 @@
           allow_dirty_match: []
           changelog: Changes
         Dist::Zilla::Role::Git::Repo:
-          git_version: 2.5.5
+          git_version: 2.9.4
           repo_root: .
       name: '@Author::DBOOK/Git::Check'
       version: '2.042'
@@ -198,7 +198,7 @@
           allow_dirty_match: []
           changelog: Changes
         Dist::Zilla::Role::Git::Repo:
-          git_version: 2.5.5
+          git_version: 2.9.4
           repo_root: .
         Dist::Zilla::Role::Git::StringFormatter:
           time_zone: local
@@ -211,11 +211,11 @@
           branch: ~
           changelog: Changes
           signed: 0
-          tag: v2.002
+          tag: v3.000
           tag_format: v%v
           tag_message: v%v
         Dist::Zilla::Role::Git::Repo:
-          git_version: 2.5.5
+          git_version: 2.9.4
           repo_root: .
         Dist::Zilla::Role::Git::StringFormatter:
           time_zone: local
@@ -246,7 +246,7 @@
             - (?^:^(?:lib|script|bin)/)
           changelog: Changes
         Dist::Zilla::Role::Git::Repo:
-          git_version: 2.5.5
+          git_version: 2.9.4
           repo_root: .
         Dist::Zilla::Role::Git::StringFormatter:
           time_zone: local
@@ -260,7 +260,7 @@
             - origin
           remotes_must_exist: 1
         Dist::Zilla::Role::Git::Repo:
-          git_version: 2.5.5
+          git_version: 2.9.4
           repo_root: .
       name: '@Author::DBOOK/Git::Push'
       version: '2.042'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/README new/Mojo-SQLite-3.000/README
--- old/Mojo-SQLite-2.002/README        2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/README        2017-07-20 07:16:52.000000000 +0200
@@ -59,7 +59,10 @@
 
     Mojo::SQLite is a tiny wrapper around DBD::SQLite that makes SQLite
     <https://www.sqlite.org/> a lot of fun to use with the Mojolicious
-    <https://mojolico.us> real-time web framework.
+    <https://mojolico.us> real-time web framework. Use all SQL features
+    <http://sqlite.org/lang.html> SQLite has to offer, generate CRUD
+    queries from data structures, and manage your database schema with
+    migrations.
 
     Database and statement handles are cached automatically, so they can be
     reused transparently to increase performance. And you can handle
@@ -93,8 +96,10 @@
     "Write-Ahead Log" journal is enabled for all connections, allowing
     multiple processes to read and write concurrently to the same database
     file (but only one can write at a time). You can prevent this mode from
-    being enabled by passing the option no_wal. See
-    http://sqlite.org/wal.html for more information.
+    being enabled by passing the option no_wal, but note that this is
+    incompatible with SQLite databases that have already had WAL mode
+    enabled. See http://sqlite.org/wal.html and "journal_mode" in
+    DBD::SQLite for more information.
 
       # Performed concurrently
       my $pid = fork || die $!;
@@ -131,9 +136,9 @@
 
     This distribution also contains a well-structured example blog
     application
-    <https://github.com/kraih/mojo-pg/tree/master/examples/blog> you can
-    use for inspiration. This application shows how to apply the MVC design
-    pattern in practice.
+    <https://github.com/Grinnz/Mojo-SQLite/tree/master/examples/blog> you
+    can use for inspiration. This application shows how to apply the MVC
+    design pattern in practice.
 
 EVENTS
 
@@ -171,7 +176,7 @@
       $sql     = $sql->auto_migrate($bool);
 
     Automatically migrate to the latest database schema with "migrations",
-    as soon as the first database connection has been established.
+    as soon as "db" has been called for the first time.
 
  database_class
 
@@ -195,7 +200,7 @@
       $sql    = $sql->max_connections(3);
 
     Maximum number of idle database handles to cache for future use,
-    defaults to 5.
+    defaults to 1.
 
  migrations
 
@@ -220,9 +225,13 @@
     "ATTRIBUTES COMMON TO ALL HANDLES" in DBI and "DRIVER PRIVATE
     ATTRIBUTES" in DBD::SQLite for more information on available options.
 
- pubsub
+ parent
 
-    This attribute is DEPRECATED.
+      my $parent = $sql->parent;
+      $sql       = $sql->parent(Mojo::SQLite->new);
+
+    Another Mojo::SQLite object to use for connection management, instead
+    of establishing and caching our own database connections.
 
 METHODS
 
@@ -234,6 +243,7 @@
       my $sql = Mojo::SQLite->new;
       my $sql = Mojo::SQLite->new('file:test.db);
       my $sql = Mojo::SQLite->new('sqlite:test.db');
+      my $sql = Mojo::SQLite->new(Mojo::SQLite->new);
 
     Construct a new Mojo::SQLite object and parse connection string with
     "from_string" if necessary.
@@ -292,16 +302,17 @@
       $sql = $sql->from_string('file:test.db');
       $sql = $sql->from_string('file:///C:/foo/bar.db');
       $sql = $sql->from_string('sqlite:C:%5Cfoo%5Cbar.db');
+      $sql = $sql->from_string(Mojo::SQLite->new);
 
-    Parse configuration from connection string. Connection strings are
-    parsed as URLs, so you should construct them using a module like
-    Mojo::URL, URI::file, or URI::db. For portability on non-Unix-like
-    systems, either construct the URL with the sqlite scheme, or use "new"
-    in URI::file to construct a URL with the file scheme. A URL with no
-    scheme will be parsed as a file URL, and file URLs are parsed according
-    to the current operating system. If specified, the hostname must be
-    localhost. If the URL has a query string, it will be parsed and applied
-    to "options".
+    Parse configuration from connection string or use another Mojo::SQLite
+    object as "parent". Connection strings are parsed as URLs, so you
+    should construct them using a module like Mojo::URL, URI::file, or
+    URI::db. For portability on non-Unix-like systems, either construct the
+    URL with the sqlite scheme, or use "new" in URI::file to construct a
+    URL with the file scheme. A URL with no scheme will be parsed as a file
+    URL, and file URLs are parsed according to the current operating
+    system. If specified, the hostname must be localhost. If the URL has a
+    query string, it will be parsed and applied to "options".
 
       # Absolute filename
       $sql->from_string('sqlite:////home/fred/data.db');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/cpanfile 
new/Mojo-SQLite-3.000/cpanfile
--- old/Mojo-SQLite-2.002/cpanfile      2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/cpanfile      2017-07-20 07:16:52.000000000 +0200
@@ -4,7 +4,7 @@
 requires 'DBD::SQLite'     => '1.50'; # for json support
 requires 'File::Spec::Functions';
 requires 'File::Temp';
-requires 'Mojolicious'     => '7.15';
+requires 'Mojolicious'     => '7.32';
 requires 'Scalar::Util';
 requires 'SQL::Abstract'   => '1.81';
 requires 'URI'             => '1.69';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/examples/blog/t/blog.t 
new/Mojo-SQLite-3.000/examples/blog/t/blog.t
--- old/Mojo-SQLite-2.002/examples/blog/t/blog.t        1970-01-01 
01:00:00.000000000 +0100
+++ new/Mojo-SQLite-3.000/examples/blog/t/blog.t        2017-07-20 
07:16:52.000000000 +0200
@@ -0,0 +1,48 @@
+use Mojo::Base -strict;
+
+use Test::More;
+
+use Mojo::SQLite;
+use Mojo::URL;
+use Test::Mojo;
+
+# Override configuration for testing
+my $t = Test::Mojo->new(Blog => {sqlite => ':temp:', secrets => 
['test_s3cret']});
+$t->ua->max_redirects(10);
+
+# No posts yet
+$t->get_ok('/')->status_is(200)->text_is('title' => 'Blog')
+  ->text_is('body > a' => 'New post')->element_exists_not('h2');
+
+# Create a new post
+$t->get_ok('/posts/create')->status_is(200)->text_is('title' => 'New post')
+  ->element_exists('form input[name=title]')
+  ->element_exists('form textarea[name=body]');
+$t->post_ok('/posts' => form => {title => 'Testing', body => 'This is a 
test.'})
+  ->status_is(200)->text_is('title' => 'Testing')->text_is('h2' => 'Testing')
+  ->text_like('p' => qr/This is a test/);
+
+# Read the post
+$t->get_ok('/')->status_is(200)->text_is('title' => 'Blog')
+  ->text_is('h2 a' => 'Testing')->text_like('p' => qr/This is a test/);
+$t->get_ok('/posts/1')->status_is(200)->text_is('title' => 'Testing')
+  ->text_is('h2' => 'Testing')->text_like('p' => qr/This is a test/)
+  ->text_is('body > a' => 'Edit');
+
+# Update the post
+$t->get_ok('/posts/1/edit')->status_is(200)->text_is('title' => 'Edit post')
+  ->element_exists('form input[name=title][value=Testing]')
+  ->text_like('form textarea[name=body]' => qr/This is a test/)
+  ->element_exists('form input[value=Remove]');
+$t->post_ok(
+  '/posts/1?_method=PUT' => form => {title => 'Again', body => 'It works.'})
+  ->status_is(200)->text_is('title' => 'Again')->text_is('h2' => 'Again')
+  ->text_like('p' => qr/It works/);
+$t->get_ok('/posts/1')->status_is(200)->text_is('title' => 'Again')
+  ->text_is('h2' => 'Again')->text_like('p' => qr/It works/);
+
+# Delete the post
+$t->post_ok('/posts/1?_method=DELETE')->status_is(200)
+  ->text_is('title' => 'Blog')->element_exists_not('h2');
+
+done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Mojo-SQLite-2.002/examples/blog/templates/posts/index.html.ep 
new/Mojo-SQLite-3.000/examples/blog/templates/posts/index.html.ep
--- old/Mojo-SQLite-2.002/examples/blog/templates/posts/index.html.ep   
2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/examples/blog/templates/posts/index.html.ep   
2017-07-20 07:16:52.000000000 +0200
@@ -1,7 +1,7 @@
 % layout 'blog', title => 'Blog';
 % for my $post (@$posts) {
+  <h2><%= link_to $post->{title} => show_post => {id => $post->{id}} %></h2>
   <p>
-    <h2><%= link_to $post->{title} => show_post => {id => $post->{id}} %></h2>
     %= $post->{body}
   </p>
 % }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/lib/Mojo/SQLite/Database.pm 
new/Mojo-SQLite-3.000/lib/Mojo/SQLite/Database.pm
--- old/Mojo-SQLite-2.002/lib/Mojo/SQLite/Database.pm   2017-06-01 
20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/lib/Mojo/SQLite/Database.pm   2017-07-20 
07:16:52.000000000 +0200
@@ -1,5 +1,5 @@
 package Mojo::SQLite::Database;
-use Mojo::Base 'Mojo::EventEmitter';
+use Mojo::Base -base;
 
 use Carp qw(croak shortmess);
 use DBI 'SQL_VARCHAR';
@@ -7,21 +7,15 @@
 use Mojo::JSON 'to_json';
 use Mojo::SQLite::Results;
 use Mojo::SQLite::Transaction;
-use Mojo::Util qw(deprecated monkey_patch);
+use Mojo::Util 'monkey_patch';
 use Scalar::Util 'weaken';
 
-our $VERSION = '2.002';
+our $VERSION = '3.000';
 
 our @CARP_NOT = qw(Mojo::SQLite::Migrations);
 
-use constant DEBUG => $ENV{MOJO_PUBSUB_DEBUG} || 0;
-
 has [qw(dbh sqlite)];
-has notification_poll_interval => sub {
-  deprecated 'The notification_poll_interval attribute is deprecated and 
should no longer be used';
-  return 0.5;
-};
-has results_class              => 'Mojo::SQLite::Results';
+has results_class => 'Mojo::SQLite::Results';
 
 for my $name (qw(delete insert select update)) {
   monkey_patch __PACKAGE__, $name, sub {
@@ -49,53 +43,9 @@
 
 sub disconnect {
   my $self = shift;
-  $self->_unwatch;
   $self->dbh->disconnect;
 }
 
-our $_QUERY_NOTIFICATIONS;
-
-sub is_listening {
-  deprecated 'The is_listening method is deprecated and should no longer be 
used' unless $_QUERY_NOTIFICATIONS;
-  return !!keys %{shift->{listen} || {}};
-}
-
-sub listen {
-  my ($self, $name) = @_;
-
-  deprecated 'The listen method is deprecated and should no longer be used';
-
-  warn qq{$self listening on channel "$name"\n} if DEBUG;
-  $self->{listen}{$name}++;
-  $self->_init_pubsub;
-  $self->_watch;
-  $self->dbh->do('insert or ignore into mojo_pubsub_listen
-    (listener_id, channel) values (?, ?)', undef, $self->{listener_id}, $name);
-
-  return $self;
-}
-
-sub notify {
-  my ($self, $name, $payload) = @_;
-
-  deprecated 'The notify method is deprecated and should no longer be used';
-
-  $payload //= '';
-  warn qq{$self sending notification on channel "$name": $payload\n} if DEBUG;
-  $self->_init_pubsub;
-
-  my $dbh = $self->dbh;
-  $dbh->do('insert into mojo_pubsub_notify (channel, payload)
-    values (?, ?)', undef, $name, $payload);
-  my $notify_id = $dbh->{private_mojo_last_insert_id} // croak 'Failed to 
retrieve notify ID';
-  $dbh->do('insert into mojo_pubsub_queue (listener_id, notify_id)
-    select listener_id, ? from mojo_pubsub_listen where channel=?', undef, 
$notify_id, $name);
-
-  $self->_notifications;
-
-  return $self;
-}
-
 sub ping { shift->dbh->ping }
 
 sub query {
@@ -131,11 +81,7 @@
     $results->{last_insert_id} = $dbh->{private_mojo_last_insert_id};
   }
 
-  unless ($cb) { # blocking
-    local $_QUERY_NOTIFICATIONS = 1; # no deprecated message
-    $self->_notifications;
-    return $results;
-  }
+  return $results unless $cb; # blocking
 
   # Still blocking, but call the callback on the next tick
   $error = $dbh->err ? $dbh->errstr : $errored ? ($error || 'Error running 
SQLite query') : undef;
@@ -149,26 +95,6 @@
   return [grep { !$names{$_}++ } @tables];
 }
 
-sub unlisten {
-  my ($self, $name) = @_;
-
-  deprecated 'The unlisten method is deprecated and should no longer be used';
-
-  warn qq{$self is no longer listening on channel "$name"\n} if DEBUG;
-  my $dbh = $self->dbh;
-  if ($name eq '*') {
-    delete $self->{listen};
-    $dbh->do('delete from mojo_pubsub_listen where listener_id=?', undef, 
$self->{listener_id});
-  } else {
-    delete $self->{listen}{$name};
-    $dbh->do('delete from mojo_pubsub_listen where listener_id=? and 
channel=?', undef,
-      $self->{listener_id}, $name);
-  }
-  $self->_unwatch unless $self->is_listening;
-
-  return $self;
-}
-
 sub _bind_params {
   my $sth = shift;
   return $sth unless @_;
@@ -189,89 +115,6 @@
   return $sth;
 }
 
-sub _cleanup_pubsub {
-  my $self = shift;
-  # Delete any stale listeners and their queues
-  my $dbh = $self->dbh;
-  my $listener_ids = $dbh->selectcol_arrayref(q{select id from 
mojo_pubsub_listener
-    where last_checked < strftime('%s','now','-1 days')});
-  if (@$listener_ids) {
-    warn qq{$self cleaning up stale listeners @$listener_ids\n"} if DEBUG;
-    my $in_str = join ',', ('?')x@$listener_ids;
-    $dbh->do("delete from mojo_pubsub_queue where listener_id in ($in_str)", 
undef, @$listener_ids);
-    $dbh->do("delete from mojo_pubsub_listen where listener_id in ($in_str)", 
undef, @$listener_ids);
-    $dbh->do("delete from mojo_pubsub_listener where id in ($in_str)", undef, 
@$listener_ids);
-  }
-  # Delete any notifications that are no longer queued
-  my $notify_ids = $dbh->selectcol_arrayref('select n.id from 
mojo_pubsub_notify as n
-    left join mojo_pubsub_queue as q on q.notify_id=n.id where q.notify_id is 
null');
-  if (@$notify_ids) {
-    warn qq{$self cleaning up unqueued notifications @$notify_ids\n} if DEBUG;
-    my $in_str = join ',', ('?')x@$notify_ids;
-    $dbh->do("delete from mojo_pubsub_notify where id in ($in_str)", undef, 
@$notify_ids);
-  }
-}
-
-sub _init_pubsub {
-  my $self = shift;
-  return $self if $self->{init_pubsub} || $self->{init_pubsub}++;
-  $self->sqlite->migrations->name('pubsub')->from_data->migrate;
-  $self->_cleanup_pubsub;
-}
-
-sub _notifications {
-  my $self = shift;
-  if ($self->is_listening) {
-    my $dbh = $self->dbh;
-    $dbh->do(q{update mojo_pubsub_listener set 
last_checked=strftime('%s','now')
-      where id=?}, undef, $self->{listener_id});
-    my $notifies = $dbh->selectall_arrayref('select n.id, n.channel, n.payload
-      from mojo_pubsub_notify as n inner join mojo_pubsub_queue as q on 
q.notify_id=n.id
-      where q.listener_id=? order by n.id asc', { Slice => {} }, 
$self->{listener_id});
-    if ($notifies and @$notifies) {
-      do { my @ids = map { $_->{id} } @$notifies; warn qq{$self has received 
notifications @ids\n} } if DEBUG;
-      my $in_str = join ',', ('?')x@$notifies;
-      $dbh->do("delete from mojo_pubsub_queue where listener_id=? and 
notify_id in ($in_str)", undef,
-        $self->{listener_id}, map { $_->{id} } @$notifies);
-      $self->_cleanup_pubsub;
-      foreach my $notify (@$notifies) {
-        $self->emit(notification => @{$notify}{qw(channel payload)})
-          if exists $self->{listen}{$notify->{channel}};
-      }
-    }
-  }
-}
-
-sub _unwatch {
-  my $self = shift;
-  return $self unless delete $self->{watching};
-  warn qq{$self is no longer watching for notifications\n} if DEBUG;
-  Mojo::IOLoop->remove($self->{pubsub_timer});
-  my $pid = delete $self->{listener_pid};
-  if ($pid and $pid eq $$) {
-    local $@;
-    eval { $self->dbh->do('delete from mojo_pubsub_listener where id=?', 
undef, delete $self->{listener_id}) };
-  }
-  $self->emit('close') if $self->is_listening;
-}
-
-sub _watch {
-  my $self = shift;
-  return $self if $self->{watching} || $self->{watching}++;
-  warn qq{$self now watching for notifications\n} if DEBUG;
-  Mojo::IOLoop->remove($self->{pubsub_timer}) if exists $self->{pubsub_timer};
-  my $interval = $self->notification_poll_interval;
-  $self->{pubsub_timer} = Mojo::IOLoop->recurring($interval => sub {
-    local $@;
-    $self->_unwatch if !eval { $self->_notifications; 1 }
-      or !$self->is_listening;
-  });
-  my $dbh = $self->dbh;
-  $dbh->do('insert into mojo_pubsub_listener default values');
-  $self->{listener_id} = $dbh->{private_mojo_last_insert_id} // die 'Unable to 
retrieve listener ID';
-  $self->{listener_pid} = $$;
-}
-
 1;
 
 =encoding utf8
@@ -293,30 +136,6 @@
 L<Mojo::SQLite::Database> is a container for L<DBD::SQLite> database handles
 used by L<Mojo::SQLite>.
 
-=head1 EVENTS
-
-L<Mojo::SQLite::Database> inherits all events from L<Mojo::EventEmitter> and
-can emit the following new ones.
-
-=head2 close
-
-  $db->on(close => sub {
-    my $db = shift;
-    ...
-  });
-
-Emitted when the database connection gets closed while waiting for
-notifications.
-
-=head2 notification
-
-  $db->on(notification => sub {
-    my ($db, $name, $payload) = @_;
-    ...
-  });
-
-Emitted when a notification has been received.
-
 =head1 ATTRIBUTES
 
 L<Mojo::SQLite::Database> implements the following attributes.
@@ -331,10 +150,6 @@
   # Use DBI utility methods
   my $quoted = $db->dbh->quote_identifier('foo.bar');
 
-=head2 notification_poll_interval
-
-This attribute is L<DEPRECATED|Mojo::SQLite::PubSub/"DESCRIPTION">.
-
 =head2 results_class
 
   my $class = $db->results_class;
@@ -432,18 +247,6 @@
   # "insert into some_table (foo, baz) values ('bar', 'yada')"
   $db->insert('some_table', {foo => 'bar', baz => 'yada'});
 
-=head2 is_listening
-
-This method is L<DEPRECATED|Mojo::SQLite::PubSub/"DESCRIPTION">.
-
-=head2 listen
-
-This method is L<DEPRECATED|Mojo::SQLite::PubSub/"DESCRIPTION">.
-
-=head2 notify
-
-This method is L<DEPRECATED|Mojo::SQLite::PubSub/"DESCRIPTION">.
-
 =head2 ping
 
   my $bool = $db->ping;
@@ -530,10 +333,6 @@
   # Names of all tables
   say for @{$db->tables};
 
-=head2 unlisten
-
-This method is L<DEPRECATED|Mojo::SQLite::PubSub/"DESCRIPTION">.
-
 =head2 update
 
   my $results = $db->update($table, \%fieldvals, \%where);
@@ -576,47 +375,3 @@
 =head1 SEE ALSO
 
 L<Mojo::SQLite>
-
-=cut
-
-__DATA__
-
-@@ pubsub
--- 1 down
-drop table mojo_pubsub_listener;
-drop table mojo_pubsub_listen;
-drop table mojo_pubsub_notify;
-drop table mojo_pubsub_queue;
-
--- 1 up
-drop table if exists mojo_pubsub_listener;
-drop table if exists mojo_pubsub_listen;
-drop table if exists mojo_pubsub_notify;
-drop table if exists mojo_pubsub_queue;
-
-create table mojo_pubsub_listener (
-  id integer primary key autoincrement,
-  last_checked integer not null default (strftime('%s','now'))
-);
-create index mojo_listener_last_checked_idx on mojo_pubsub_listener 
(last_checked);
-
-create table mojo_pubsub_listen (
-  listener_id integer not null,
-  channel text not null,
-  primary key (listener_id, channel)
-);
-create index mojo_listen_channel_idx on mojo_pubsub_listen (channel);
-
-create table mojo_pubsub_notify (
-  id integer primary key autoincrement,
-  channel text not null,
-  payload text not null default ''
-);
-create index mojo_notify_channel_idx on mojo_pubsub_notify (channel);
-
-create table mojo_pubsub_queue (
-  listener_id integer not null,
-  notify_id integer not null,
-  primary key (listener_id, notify_id)
-);
-create index mojo_queue_notify_id_idx on mojo_pubsub_queue (notify_id);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/lib/Mojo/SQLite/Migrations.pm 
new/Mojo-SQLite-3.000/lib/Mojo/SQLite/Migrations.pm
--- old/Mojo-SQLite-2.002/lib/Mojo/SQLite/Migrations.pm 2017-06-01 
20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/lib/Mojo/SQLite/Migrations.pm 2017-07-20 
07:16:52.000000000 +0200
@@ -8,7 +8,7 @@
 
 use constant DEBUG => $ENV{MOJO_MIGRATIONS_DEBUG} || 0;
 
-our $VERSION = '2.002';
+our $VERSION = '3.000';
 
 has name => 'migrations';
 has 'sqlite';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/lib/Mojo/SQLite/PubSub.pm 
new/Mojo-SQLite-3.000/lib/Mojo/SQLite/PubSub.pm
--- old/Mojo-SQLite-2.002/lib/Mojo/SQLite/PubSub.pm     2017-06-01 
20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/lib/Mojo/SQLite/PubSub.pm     2017-07-20 
07:16:52.000000000 +0200
@@ -1,80 +1,11 @@
 package Mojo::SQLite::PubSub;
-use Mojo::Base 'Mojo::EventEmitter';
+use Mojo::Base -strict;
 
-use Mojo::JSON qw(from_json to_json);
 use Mojo::Util 'deprecated';
-use Scalar::Util 'weaken';
 
-our $VERSION = '2.002';
+our $VERSION = '3.000';
 
-has [qw(poll_interval sqlite)];
-
-sub new {
-  my $class = shift;
-  deprecated 'Mojo::SQLite::PubSub is deprecated and should no longer be used';
-  return $class->SUPER::new(@_);
-}
-
-sub DESTROY { shift->_cleanup }
-
-sub json { ++$_[0]{json}{$_[1]} and return $_[0] }
-
-sub listen {
-  my ($self, $name, $cb) = @_;
-  $self->_db->listen($name) unless @{$self->{chans}{$name} ||= []};
-  push @{$self->{chans}{$name}}, $cb;
-  return $cb;
-}
-
-sub notify { $_[0]->_db->notify(_json(@_)) and return $_[0] }
-
-sub unlisten {
-  my ($self, $name, $cb) = @_;
-  my $chan = $self->{chans}{$name};
-  @$chan = $cb ? grep { $cb ne $_ } @$chan : ();
-  $self->_db->unlisten($name) and delete $self->{chans}{$name} unless @$chan;
-  return $self;
-}
-
-sub _cleanup {
-  my $self = shift;
-  $self->{db}->_unwatch;
-  delete @$self{qw(chans db pid)};
-}
-
-sub _db {
-  my $self = shift;
-
-  # Fork-safety
-  $self->_cleanup unless ($self->{pid} //= $$) eq $$;
-
-  return $self->{db} if $self->{db};
-
-  my $db = $self->{db} = $self->sqlite->db;
-  $db->notification_poll_interval($self->poll_interval) if defined 
$self->poll_interval;
-  weaken $db->{sqlite};
-  weaken $self;
-  $db->on(
-    notification => sub {
-      my ($db, $name, $payload) = @_;
-      $payload = eval { from_json $payload } if $self->{json}{$name};
-      for my $cb (@{$self->{chans}{$name}}) { $self->$cb($payload) }
-    }
-  );
-  $db->once(
-    close => sub {
-      local $@;
-      delete $self->{db};
-      eval { $self->_db };
-    }
-  );
-  $db->listen($_) for keys %{$self->{chans}}, 'mojo.pubsub';
-  $self->emit(reconnect => $db);
-
-  return $db;
-}
-
-sub _json { $_[1], $_[0]{json}{$_[1]} ? to_json $_[2] : $_[2] }
+deprecated 'Mojo::SQLite::PubSub is deprecated and should no longer be used';
 
 1;
 
@@ -86,12 +17,12 @@
 
 =head1 DESCRIPTION
 
-L<Mojo::SQLite::PubSub> is DEPRECATED. It was originally written as a toy
-following the API of L<Mojo::Pg::PubSub>, but as SQLite is serverless and has
-no ability to notify clients, it is not possible to implement an efficient
-pubsub system as in for example PostgreSQL, Redis, or websockets. Consider
-instead using the pubsub facilities of L<Mojo::Pg>, L<Mojo::Redis2>, or
-L<Mercury|mercury>.
+L<Mojo::SQLite::PubSub> is DEPRECATED and now an empty package. It was
+originally written as a toy following the API of L<Mojo::Pg::PubSub>, but as
+SQLite is serverless and has no ability to notify clients, it is not possible
+to implement an efficient pubsub system as in for example PostgreSQL, Redis, or
+websockets. Consider instead using the pubsub facilities of L<Mojo::Pg>,
+L<Mojo::Redis2>, or L<Mercury|mercury>.
 
 =head1 SEE ALSO
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/lib/Mojo/SQLite/Results.pm 
new/Mojo-SQLite-3.000/lib/Mojo/SQLite/Results.pm
--- old/Mojo-SQLite-2.002/lib/Mojo/SQLite/Results.pm    2017-06-01 
20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/lib/Mojo/SQLite/Results.pm    2017-07-20 
07:16:52.000000000 +0200
@@ -5,7 +5,7 @@
 use Mojo::JSON 'from_json';
 use Mojo::Util 'tablify';
 
-our $VERSION = '2.002';
+our $VERSION = '3.000';
 
 has 'sth';
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/lib/Mojo/SQLite/Transaction.pm 
new/Mojo-SQLite-3.000/lib/Mojo/SQLite/Transaction.pm
--- old/Mojo-SQLite-2.002/lib/Mojo/SQLite/Transaction.pm        2017-06-01 
20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/lib/Mojo/SQLite/Transaction.pm        2017-07-20 
07:16:52.000000000 +0200
@@ -3,7 +3,7 @@
 
 use Carp 'croak';
 
-our $VERSION = '2.002';
+our $VERSION = '3.000';
 
 has 'db';
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/lib/Mojo/SQLite.pm 
new/Mojo-SQLite-3.000/lib/Mojo/SQLite.pm
--- old/Mojo-SQLite-2.002/lib/Mojo/SQLite.pm    2017-06-01 20:16:36.000000000 
+0200
+++ new/Mojo-SQLite-3.000/lib/Mojo/SQLite.pm    2017-07-20 07:16:52.000000000 
+0200
@@ -8,19 +8,18 @@
 use File::Temp;
 use Mojo::SQLite::Database;
 use Mojo::SQLite::Migrations;
-use Mojo::SQLite::PubSub;
-use Scalar::Util 'weaken';
+use Scalar::Util qw(blessed weaken);
 use SQL::Abstract;
 use URI;
 use URI::db;
 
-our $VERSION = '2.002';
+our $VERSION = '3.000';
 
 has abstract => sub { SQL::Abstract->new(name_sep => '.', quote_char => '"') };
 has 'auto_migrate';
 has database_class  => 'Mojo::SQLite::Database';
 has dsn             => sub { _url_from_file(shift->_tempfile)->dbi_dsn };
-has max_connections => 5;
+has max_connections => 1;
 has migrations      => sub {
   my $migrations = Mojo::SQLite::Migrations->new(sqlite => shift);
   weaken $migrations->{sqlite};
@@ -35,21 +34,19 @@
     sqlite_unicode      => 1,
   };
 };
-has pubsub => sub {
-  my $pubsub = Mojo::SQLite::PubSub->new(sqlite => shift);
-  weaken $pubsub->{sqlite};
-  return $pubsub;
-};
+has 'parent';
 
 sub new { @_ > 1 ? shift->SUPER::new->from_string(@_) : shift->SUPER::new }
 
-sub db { $_[0]->database_class->new(dbh => $_[0]->_dequeue, sqlite => $_[0]) }
+sub db { $_[0]->database_class->new(dbh => $_[0]->_prepare, sqlite => $_[0]) }
 
 sub from_filename { shift->from_string(_url_from_file(shift, shift)) }
 
 sub from_string {
   my ($self, $str) = @_;
   return $self unless $str;
+  return $self->parent($str) if blessed $str and $str->isa('Mojo::SQLite');
+
   my $url = URI->new($str);
 
   # Options
@@ -96,9 +93,6 @@
     $weakdbh->{private_mojo_last_insert_id} = $_[3] if $_[0] == 
DBD::SQLite::INSERT;
   });
 
-  # Automatic migrations
-  ++$self->{migrated} and $self->migrations->migrate
-    if !$self->{migrated} && $self->auto_migrate;
   $self->emit(connection => $dbh);
 
   return $dbh;
@@ -106,11 +100,25 @@
 
 sub _enqueue {
   my ($self, $dbh) = @_;
+
+  if (my $parent = $self->parent) { return $parent->_enqueue($dbh) }
+
   my $queue = $self->{queue} ||= [];
   push @$queue, $dbh if $dbh->{Active};
   shift @$queue while @$queue > $self->max_connections;
 }
 
+sub _prepare {
+  my $self = shift;
+
+  # Automatic migrations
+  ++$self->{migrated} and $self->migrations->migrate
+    if !$self->{migrated} && $self->auto_migrate;
+
+  my $parent = $self->parent;
+  return $parent ? $parent->_prepare : $self->_dequeue;
+}
+
 sub _tempfile { catfile(shift->{tempdir} = File::Temp->newdir, 'sqlite.db') }
 
 sub _url_from_file {
@@ -184,7 +192,9 @@
 
 L<Mojo::SQLite> is a tiny wrapper around L<DBD::SQLite> that makes
 L<SQLite|https://www.sqlite.org/> a lot of fun to use with the
-L<Mojolicious|https://mojolico.us> real-time web framework.
+L<Mojolicious|https://mojolico.us> real-time web framework. Use all
+L<SQL features|http://sqlite.org/lang.html> SQLite has to offer, generate CRUD
+queries from data structures, and manage your database schema with migrations.
 
 Database and statement handles are cached automatically, so they can be reused
 transparently to increase performance. And you can handle connection timeouts
@@ -216,7 +226,9 @@
 journal is enabled for all connections, allowing multiple processes to read and
 write concurrently to the same database file (but only one can write at a
 time). You can prevent this mode from being enabled by passing the option
-C<no_wal>. See L<http://sqlite.org/wal.html> for more information.
+C<no_wal>, but note that this is incompatible with SQLite databases that have
+already had WAL mode enabled. See L<http://sqlite.org/wal.html> and
+L<DBD::SQLite/"journal_mode"> for more information.
 
   # Performed concurrently
   my $pid = fork || die $!;
@@ -251,7 +263,7 @@
 =head1 EXAMPLES
 
 This distribution also contains a well-structured example
-L<blog application|https://github.com/kraih/mojo-pg/tree/master/examples/blog>
+L<blog 
application|https://github.com/Grinnz/Mojo-SQLite/tree/master/examples/blog>
 you can use for inspiration. This application shows how to apply the MVC design
 pattern in practice.
 
@@ -291,7 +303,7 @@
   $sql     = $sql->auto_migrate($bool);
 
 Automatically migrate to the latest database schema with L</"migrations">, as
-soon as the first database connection has been established.
+soon as L</"db"> has been called for the first time.
 
 =head2 database_class
 
@@ -315,7 +327,7 @@
   $sql    = $sql->max_connections(3);
 
 Maximum number of idle database handles to cache for future use, defaults to
-C<5>.
+C<1>.
 
 =head2 migrations
 
@@ -341,9 +353,13 @@
 L<DBD::SQLite/"DRIVER PRIVATE ATTRIBUTES"> for more information on available
 options.
 
-=head2 pubsub
+=head2 parent
+
+  my $parent = $sql->parent;
+  $sql       = $sql->parent(Mojo::SQLite->new);
 
-This attribute is L<DEPRECATED|Mojo::SQLite::PubSub/"DESCRIPTION">.
+Another L<Mojo::SQLite> object to use for connection management, instead of
+establishing and caching our own database connections.
 
 =head1 METHODS
 
@@ -355,6 +371,7 @@
   my $sql = Mojo::SQLite->new;
   my $sql = Mojo::SQLite->new('file:test.db);
   my $sql = Mojo::SQLite->new('sqlite:test.db');
+  my $sql = Mojo::SQLite->new(Mojo::SQLite->new);
 
 Construct a new L<Mojo::SQLite> object and parse connection string with
 L</"from_string"> if necessary.
@@ -412,15 +429,17 @@
   $sql = $sql->from_string('file:test.db');
   $sql = $sql->from_string('file:///C:/foo/bar.db');
   $sql = $sql->from_string('sqlite:C:%5Cfoo%5Cbar.db');
+  $sql = $sql->from_string(Mojo::SQLite->new);
 
-Parse configuration from connection string. Connection strings are parsed as
-URLs, so you should construct them using a module like L<Mojo::URL>,
-L<URI::file>, or L<URI::db>. For portability on non-Unix-like systems, either
-construct the URL with the C<sqlite> scheme, or use L<URI::file/"new"> to
-construct a URL with the C<file> scheme. A URL with no scheme will be parsed as
-a C<file> URL, and C<file> URLs are parsed according to the current operating
-system. If specified, the hostname must be C<localhost>. If the URL has a query
-string, it will be parsed and applied to L</"options">.
+Parse configuration from connection string or use another L<Mojo::SQLite>
+object as L</"parent">. Connection strings are parsed as URLs, so you should
+construct them using a module like L<Mojo::URL>, L<URI::file>, or L<URI::db>.
+For portability on non-Unix-like systems, either construct the URL with the
+C<sqlite> scheme, or use L<URI::file/"new"> to construct a URL with the C<file>
+scheme. A URL with no scheme will be parsed as a C<file> URL, and C<file> URLs
+are parsed according to the current operating system. If specified, the
+hostname must be C<localhost>. If the URL has a query string, it will be parsed
+and applied to L</"options">.
 
   # Absolute filename
   $sql->from_string('sqlite:////home/fred/data.db');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/t/00-report-prereqs.dd 
new/Mojo-SQLite-3.000/t/00-report-prereqs.dd
--- old/Mojo-SQLite-2.002/t/00-report-prereqs.dd        2017-06-01 
20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/t/00-report-prereqs.dd        2017-07-20 
07:16:52.000000000 +0200
@@ -18,7 +18,7 @@
                                       'DBI' => '1.627',
                                       'File::Spec::Functions' => '0',
                                       'File::Temp' => '0',
-                                      'Mojolicious' => '7.15',
+                                      'Mojolicious' => '7.32',
                                       'SQL::Abstract' => '1.81',
                                       'Scalar::Util' => '0',
                                       'URI' => '1.69',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/t/database.t 
new/Mojo-SQLite-3.000/t/database.t
--- old/Mojo-SQLite-2.002/t/database.t  2017-06-01 20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/t/database.t  2017-07-20 07:16:52.000000000 +0200
@@ -88,7 +88,7 @@
 
 # Connection cache
 {
-  is $sql->max_connections, 5, 'right default';
+  is $sql->max_connections, 1, 'right default';
   my @dbhs = map { $_->dbh } $sql->db, $sql->db, $sql->db, $sql->db, $sql->db;
   is_deeply \@dbhs,
     [map { $_->dbh } $sql->db, $sql->db, $sql->db, $sql->db, $sql->db],
@@ -195,6 +195,26 @@
   $sql->unsubscribe('connection');
 }
 
+# Shared connection cache
+{
+  my $sql2 = Mojo::SQLite->new($sql);
+  is $sql2->parent, $sql, 'right parent';
+  my $dbh = $sql->db->dbh;
+  is $sql->db->dbh,  $dbh, 'same database handle';
+  is $sql2->db->dbh, $dbh, 'same database handle';
+  is $sql->db->dbh,  $dbh, 'same database handle';
+  is $sql2->db->dbh, $dbh, 'same database handle';
+  my $db = $sql->db;
+  is_deeply $db->query('select 1 as one')->hashes->to_array, [{one => 1}],
+    'right structure';
+  $dbh = $db->dbh;
+  $db->disconnect;
+  $db = $sql2->db;
+  is_deeply $db->query('select 1 as one')->hashes->to_array, [{one => 1}],
+    'right structure';
+  isnt $db->dbh, $dbh, 'different database handle';
+}
+
 # Blocking error
 eval { $sql->db->query('does_not_exist') };
 like $@, qr/does_not_exist.*database\.t/s, 'right error';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/t/migrations.t 
new/Mojo-SQLite-3.000/t/migrations.t
--- old/Mojo-SQLite-2.002/t/migrations.t        2017-06-01 20:16:36.000000000 
+0200
+++ new/Mojo-SQLite-3.000/t/migrations.t        2017-07-20 07:16:52.000000000 
+0200
@@ -94,7 +94,7 @@
 eval { $sql2->migrations->migrate };
 like $@, qr/does_not_exist/, 'right error';
 is $sql2->migrations->migrate(3)->active, 3, 'active version is 3';
-is $sql2->migrations->migrate(2)->active, 2, 'active version is 3';
+is $sql2->migrations->migrate(2)->active, 2, 'active version is 2';
 is $sql->migrations->active, 0, 'active version is still 0';
 is $sql->migrations->migrate->active, 10, 'active version is 10';
 is_deeply $sql2->db->query('select * from migration_test_three')
@@ -104,8 +104,8 @@
 is $sql2->migrations->migrate(0)->active, 0, 'active version is 0';
 
 # Migrate automatically
-$sql = Mojo::SQLite->new->from_filename($tempfile);
-$sql->migrations->name('migrations_test')->from_string(<<EOF);
+my $sql3 = Mojo::SQLite->new->from_filename($tempfile);
+$sql3->migrations->name('migrations_test')->from_string(<<'EOF');
 -- 5 up
 create table if not exists migration_test_six (foo text);
 -- 6 up
@@ -115,14 +115,24 @@
 -- 6 down
 delete from migration_test_six;
 EOF
-$sql->auto_migrate(1)->db;
-is $sql->migrations->active, 6, 'active version is 6';
-is_deeply $sql->db->query('select * from migration_test_six')->hashes,
+$sql3->auto_migrate(1)->db;
+is $sql3->migrations->active, 6, 'active version is 6';
+is_deeply $sql3->db->query('select * from migration_test_six')->hashes,
   [{foo => 'works!'}], 'right structure';
-is $sql->migrations->migrate(5)->active, 5, 'active version is 5';
-is_deeply $sql->db->query('select * from migration_test_six')->hashes, [],
+is $sql3->migrations->migrate(5)->active, 5, 'active version is 5';
+is_deeply $sql3->db->query('select * from migration_test_six')->hashes, [],
   'right structure';
-is $sql->migrations->migrate(0)->active, 0, 'active version is 0';
+is $sql3->migrations->migrate(0)->active, 0, 'active version is 0';
+
+# Migrate automatically with shared connection cache
+my $sql4 = Mojo::SQLite->new->from_filename($tempfile);
+my $sql5 = Mojo::SQLite->new($sql4);
+$sql4->auto_migrate(1)->migrations->name('test1')->from_data;
+$sql5->auto_migrate(1)->migrations->name('test3')->from_data;
+is_deeply $sql5->db->query('select * from migration_test_four')
+  ->hashes->to_array, [{test => 10}], 'right structure';
+is_deeply $sql5->db->query('select * from 
migration_test_six')->hashes->to_array,
+  [], 'right structure';
 
 # Unknown version
 eval { $sql->migrations->migrate(23) };
@@ -155,7 +165,7 @@
 __DATA__
 @@ test1
 -- 7 up
-create table migration_test_four (test integer));
+create table migration_test_four (test integer);
 
 -- 10 up
 insert into migration_test_four values (10);
@@ -163,3 +173,7 @@
 @@ test2
 -- 2 up
 create table migration_test_five (test integer);
+
+@@ test3
+-- 2 up
+create table migration_test_six (test integer);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/xt/deprecated/database.t 
new/Mojo-SQLite-3.000/xt/deprecated/database.t
--- old/Mojo-SQLite-2.002/xt/deprecated/database.t      2017-06-01 
20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/xt/deprecated/database.t      1970-01-01 
01:00:00.000000000 +0100
@@ -1,87 +0,0 @@
-use Mojo::Base -strict;
-
-BEGIN { $ENV{MOJO_REACTOR} = 'Mojo::Reactor::Poll' }
-
-use Test::More;
-use Mojo::SQLite;
-use Mojo::IOLoop;
-
-# Connected
-my $sql = Mojo::SQLite->new;
-
-# Notifications
-{
-  my $db = $sql->db->notification_poll_interval(0.1);
-  ok !$db->is_listening, 'not listening';
-  ok $db->listen('dbtest')->is_listening, 'listening';
-  my $db2 = $sql->db->notification_poll_interval(0.1)->listen('dbtest');
-  my @notifications;
-  Mojo::IOLoop->delay(
-    sub {
-      my $delay = shift;
-      $db->once(notification => $delay->begin);
-      $db2->once(notification => $delay->begin);
-      Mojo::IOLoop->next_tick(sub { $db2->notify(dbtest => 'foo') });
-    },
-    sub {
-      my ($delay, $name, $payload, $name2, $payload2) = @_;
-      push @notifications, [$name, $payload], [$name2, $payload2];
-      $db->once(notification => $delay->begin);
-      $db2->unlisten('dbtest');
-      Mojo::IOLoop->next_tick(sub { $sql->db->notify('dbtest') });
-    },
-    sub {
-      my ($delay, $name, $payload) = @_;
-      push @notifications, [$name, $payload];
-      $db2->listen('dbtest2')->once(notification => $delay->begin);
-      Mojo::IOLoop->next_tick(sub { $db2->notify(dbtest2 => 'bar') });
-    },
-    sub {
-      my ($delay, $name, $payload) = @_;
-      push @notifications, [$name, $payload];
-      $db2->once(notification => $delay->begin);
-      my $tx = $db2->begin;
-      Mojo::IOLoop->next_tick(
-        sub {
-          $db2->notify(dbtest2 => 'baz');
-          $tx->commit;
-        }
-      );
-    },
-    sub {
-      my ($delay, $name, $payload) = @_;
-      push @notifications, [$name, $payload];
-    }
-  )->wait;
-  ok !$db->unlisten('dbtest')->is_listening, 'not listening';
-  ok !$db2->unlisten('*')->is_listening,     'not listening';
-  is $notifications[0][0], 'dbtest',  'right channel name';
-  is $notifications[0][1], 'foo',     'right payload';
-  is $notifications[1][0], 'dbtest',  'right channel name';
-  is $notifications[1][1], 'foo',     'right payload';
-  is $notifications[2][0], 'dbtest',  'right channel name';
-  is $notifications[2][1], '',        'no payload';
-  is $notifications[3][0], 'dbtest2', 'right channel name';
-  is $notifications[3][1], 'bar',     'no payload';
-  is $notifications[4][0], 'dbtest2', 'right channel name';
-  is $notifications[4][1], 'baz',     'no payload';
-  is $notifications[5], undef, 'no more notifications';
-
-  # Stop listening for all notifications
-  ok !$db->is_listening, 'not listening';
-  ok 
$db->listen('dbtest')->listen('dbtest2')->unlisten('dbtest2')->is_listening,
-    'listening';
-  ok !$db->unlisten('*')->is_listening, 'not listening';
-
-  # Connection close while listening for notifications
-  {
-    ok $db->listen('dbtest')->is_listening, 'listening';
-    my $close = 0;
-    $db->on(close => sub { $close++ });
-    $db->dbh->disconnect;
-    Mojo::IOLoop->start;
-    is $close, 1, 'close event has been emitted once';
-  }
-}
-
-done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojo-SQLite-2.002/xt/deprecated/pubsub.t 
new/Mojo-SQLite-3.000/xt/deprecated/pubsub.t
--- old/Mojo-SQLite-2.002/xt/deprecated/pubsub.t        2017-06-01 
20:16:36.000000000 +0200
+++ new/Mojo-SQLite-3.000/xt/deprecated/pubsub.t        1970-01-01 
01:00:00.000000000 +0100
@@ -1,177 +0,0 @@
-use Mojo::Base -strict;
-
-BEGIN { $ENV{MOJO_REACTOR} = 'Mojo::Reactor::Poll' }
-
-use Test::More;
-
-use File::Spec::Functions 'catfile';
-use File::Temp;
-use Mojo::IOLoop;
-use Mojo::JSON 'true';
-use Mojo::SQLite;
-use Scalar::Util 'weaken';
-
-my $tempdir = File::Temp->newdir;
-my $tempfile = catfile($tempdir, 'test.db');
-
-my @all_dbs;
-my $on_reconnect = sub { push @all_dbs, pop; weaken $all_dbs[-1]; };
-
-# Notifications with event loop
-{
-  my $sql = Mojo::SQLite->new->from_filename($tempfile);
-  $sql->pubsub->on(reconnect => $on_reconnect);
-  my ($db, @all, @test);
-  $sql->pubsub->poll_interval(0.1)->on(reconnect => sub { $db = pop });
-  $sql->pubsub->listen(
-    pstest => sub {
-      my ($pubsub, $payload) = @_;
-      push @test, $payload;
-      if ($payload eq 'stop') {
-        Mojo::IOLoop->stop;
-      } else {
-        Mojo::IOLoop->next_tick(sub { $pubsub->sqlite->db->notify(pstest => 
'stop') });
-      }
-    }
-  );
-  is $db->notification_poll_interval, 0.1, 'set notification poll interval';
-  $db->on(notification => sub { push @all, [@_[1, 2]] });
-  $sql->db->notify(pstest => '♥test♥');
-  Mojo::IOLoop->start;
-  is_deeply \@test, ['♥test♥', 'stop'], 'right messages';
-  is_deeply \@all, [['pstest', '♥test♥'], ['pstest', 'stop']],
-    'right notifications';
-}
-
-# JSON
-{
-  my $sql = Mojo::SQLite->new->from_filename($tempfile)->max_connections(1);
-  $sql->pubsub->on(reconnect => $on_reconnect);
-  my (@json, @raw);
-  $sql->pubsub->poll_interval(0.1)->json('pstest')->listen(
-    pstest => sub {
-      my ($pubsub, $payload) = @_;
-      push @json, $payload;
-      Mojo::IOLoop->stop if ref $payload eq 'HASH' && $payload->{msg} eq 
'stop';
-    }
-  );
-  $sql->pubsub->listen(
-    pstest2 => sub {
-      my ($pubsub, $payload) = @_;
-      push @raw, $payload;
-    }
-  );
-  Mojo::IOLoop->next_tick(
-    sub {
-      $sql->db->notify(pstest => 'fail');
-      $sql->pubsub->notify('pstest')->notify(pstest => {msg => '♥works♥'})
-        ->notify(pstest => [1, 2, 3])->notify(pstest => true)
-        ->notify(pstest2 => '♥works♥')->notify(pstest => {msg => 'stop'});
-    }
-  );
-  Mojo::IOLoop->start;
-  is_deeply \@json,
-    [undef, undef, {msg => '♥works♥'}, [1, 2, 3], true, {msg => 'stop'}],
-    'right data structures';
-  is_deeply \@raw, ['♥works♥'], 'right messages';
-}
-
-# Unsubscribe
-{
-  my $sql = Mojo::SQLite->new->from_filename($tempfile);
-  $sql->pubsub->on(reconnect => $on_reconnect);
-  my ($db, @all, @test);
-  $sql->pubsub->poll_interval(0.1)->on(reconnect => sub { $db = pop });
-  my $first  = $sql->pubsub->listen(pstest => sub { push @test, pop });
-  my $second = $sql->pubsub->listen(pstest => sub { push @test, pop });
-  $db->on(notification => sub { push @all, [@_[1, 2]] });
-  $sql->pubsub->notify('pstest')->notify(pstest => 'first');
-  is_deeply \@test, ['', '', 'first', 'first'], 'right messages';
-  is_deeply \@all, [['pstest', ''], ['pstest', 'first']], 'right 
notifications';
-  $sql->pubsub->unlisten(pstest => $first)->notify(pstest => 'second');
-  is_deeply \@test, ['', '', 'first', 'first', 'second'], 'right messages';
-  is_deeply \@all, [['pstest', ''], ['pstest', 'first'], ['pstest', 'second']],
-    'right notifications';
-  $sql->pubsub->unlisten(pstest => $second)->notify(pstest => 'third');
-  is_deeply \@test, ['', '', 'first', 'first', 'second'], 'right messages';
-  is_deeply \@all, [['pstest', ''], ['pstest', 'first'], ['pstest', 'second']],
-    'right notifications';
-  @all = @test = ();
-  my $third  = $sql->pubsub->listen(pstest => sub { push @test, pop });
-  my $fourth = $sql->pubsub->listen(pstest => sub { push @test, pop });
-  $sql->pubsub->notify(pstest => 'first');
-  is_deeply \@test, ['first', 'first'], 'right messages';
-  $sql->pubsub->notify(pstest => 'second');
-  is_deeply \@test, ['first', 'first', 'second', 'second'], 'right messages';
-  $sql->pubsub->unlisten('pstest')->notify(pstest => 'third');
-  is_deeply \@test, ['first', 'first', 'second', 'second'], 'right messages';
-}
-
-# Reconnect while listening
-{
-  my $sql = Mojo::SQLite->new->from_filename($tempfile);
-  $sql->pubsub->on(reconnect => $on_reconnect);
-  my (@dbhs, @test);
-  $sql->pubsub->poll_interval(0.1)->on(reconnect => sub { push @dbhs, pop->dbh 
});
-  $sql->pubsub->listen(pstest => sub { push @test, pop });
-  ok $dbhs[0], 'database handle';
-  is_deeply \@test, [], 'no messages';
-  {
-    $sql->pubsub->on(
-      reconnect => sub { shift->notify(pstest => 'works'); Mojo::IOLoop->stop 
});
-    $dbhs[0]->disconnect;
-    Mojo::IOLoop->start;
-    ok $dbhs[1], 'database handle';
-    isnt $dbhs[0], $dbhs[1], 'different database handles';
-    is_deeply \@test, ['works'], 'right messages';
-  }
-}
-
-# Reconnect while not listening
-{
-  my $sql = Mojo::SQLite->new->from_filename($tempfile);
-  $sql->pubsub->on(reconnect => $on_reconnect);
-  my (@dbhs, @test);
-  $sql->pubsub->poll_interval(0.1)->on(reconnect => sub { push @dbhs, pop->dbh 
});
-  $sql->pubsub->notify(pstest => 'fail');
-  ok $dbhs[0], 'database handle';
-  is_deeply \@test, [], 'no messages';
-  {
-    $sql->pubsub->on(reconnect => sub { Mojo::IOLoop->stop });
-    $dbhs[0]->disconnect;
-    Mojo::IOLoop->start;
-    ok $dbhs[1], 'database handle';
-    isnt $dbhs[0], $dbhs[1], 'different database handles';
-    $sql->pubsub->listen(pstest => sub { push @test, pop });
-    $sql->pubsub->notify(pstest => 'works too');
-    is_deeply \@test, ['works too'], 'right messages';
-  }
-}
-
-# Fork-safety
-{
-  my $sql = Mojo::SQLite->new->from_filename($tempfile);
-  $sql->pubsub->on(reconnect => $on_reconnect);
-  my (@dbhs, @test);
-  $sql->pubsub->poll_interval(0.1)->on(reconnect => sub { push @dbhs, pop->dbh 
});
-  $sql->pubsub->listen(pstest => sub { push @test, pop });
-  ok $dbhs[0], 'database handle';
-  $sql->pubsub->notify(pstest => 'first');
-  is_deeply \@test, ['first'], 'right messages';
-  {
-    local $$ = -23;
-    $sql->pubsub->notify(pstest => 'second');
-    ok $dbhs[1], 'database handle';
-    isnt $dbhs[0], $dbhs[1], 'different database handles';
-    is_deeply \@test, ['first'], 'right messages';
-    $sql->pubsub->listen(pstest => sub { push @test, pop });
-    $sql->pubsub->notify(pstest => 'third');
-    ok !$dbhs[2], 'no database handle';
-    is_deeply \@test, ['first', 'third'], 'right messages';
-  }
-}
-
-# Make sure nothing is listening
-$_->unlisten('*') for grep { defined } @all_dbs;
-
-done_testing();


Reply via email to