The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes.ttl 034
META.yml 35
Makefile.PL 46
README 124
SIGNATURE 8282
inc/Module/Install/Base.pm 11
inc/Module/Install/Can.pm 11
inc/Module/Install/Fetch.pm 11
inc/Module/Install/Makefile.pm 22
inc/Module/Install/Metadata.pm 33
inc/Module/Install/Scripts.pm 11
inc/Module/Install/Win32.pm 11
inc/Module/Install/WriteAll.pm 11
inc/Module/Install.pm 99
lib/RDF/Trine/Error.pm 22
lib/RDF/Trine/Exporter/CSV.pm 22
lib/RDF/Trine/Exporter/RDFPatch.pm 22
lib/RDF/Trine/Graph.pm 22
lib/RDF/Trine/Iterator/Bindings/Materialized.pm 22
lib/RDF/Trine/Iterator/Bindings.pm 1345
lib/RDF/Trine/Iterator/Boolean.pm 22
lib/RDF/Trine/Iterator/Graph/Materialized.pm 22
lib/RDF/Trine/Iterator/Graph.pm 193
lib/RDF/Trine/Iterator/JSONHandler.pm 22
lib/RDF/Trine/Iterator/SAXHandler.pm 22
lib/RDF/Trine/Iterator.pm 22
lib/RDF/Trine/Model/Dataset.pm 22
lib/RDF/Trine/Model/StatementFilter.pm 22
lib/RDF/Trine/Model/Union.pm 22
lib/RDF/Trine/Model.pm 22
lib/RDF/Trine/Namespace.pm 22
lib/RDF/Trine/NamespaceMap.pm 22
lib/RDF/Trine/Node/Blank.pm 22
lib/RDF/Trine/Node/Literal.pm 22
lib/RDF/Trine/Node/Nil.pm 22
lib/RDF/Trine/Node/Resource.pm 22
lib/RDF/Trine/Node/Variable.pm 22
lib/RDF/Trine/Node.pm 230
lib/RDF/Trine/Parser/LineProtocol.pm 22
lib/RDF/Trine/Parser/NQuads.pm 22
lib/RDF/Trine/Parser/NTriples.pm 22
lib/RDF/Trine/Parser/RDFJSON.pm 22
lib/RDF/Trine/Parser/RDFPatch.pm 22
lib/RDF/Trine/Parser/RDFXML.pm 22
lib/RDF/Trine/Parser/RDFa.pm 22
lib/RDF/Trine/Parser/Redland.pm 22
lib/RDF/Trine/Parser/TriG.pm 22
lib/RDF/Trine/Parser/Turtle/Constants.pm 22
lib/RDF/Trine/Parser/Turtle/Lexer.pm 22
lib/RDF/Trine/Parser/Turtle/Token.pm 02
lib/RDF/Trine/Parser/Turtle.pm 22
lib/RDF/Trine/Parser.pm 22
lib/RDF/Trine/Pattern.pm 45254
lib/RDF/Trine/Serializer/NQuads.pm 22
lib/RDF/Trine/Serializer/NTriples/Canonical.pm 22
lib/RDF/Trine/Serializer/NTriples.pm 22
lib/RDF/Trine/Serializer/RDFJSON.pm 22
lib/RDF/Trine/Serializer/RDFPatch.pm 22
lib/RDF/Trine/Serializer/RDFXML.pm 22
lib/RDF/Trine/Serializer/TSV.pm 22
lib/RDF/Trine/Serializer/TriG.pm 22
lib/RDF/Trine/Serializer/Turtle.pm 22
lib/RDF/Trine/Serializer.pm 35
lib/RDF/Trine/Statement/Quad.pm 22
lib/RDF/Trine/Statement.pm 22
lib/RDF/Trine/Store/DBI/Pg.pm 22
lib/RDF/Trine/Store/DBI/SQLite.pm 22
lib/RDF/Trine/Store/DBI/mysql.pm 22
lib/RDF/Trine/Store/DBI.pm 22
lib/RDF/Trine/Store/Dydra.pm 22
lib/RDF/Trine/Store/Hexastore.pm 2437
lib/RDF/Trine/Store/Memory.pm 33
lib/RDF/Trine/Store/Redis.pm 22
lib/RDF/Trine/Store/Redland.pm 1976
lib/RDF/Trine/Store/SPARQL.pm 33
lib/RDF/Trine/Store.pm 22
lib/RDF/Trine/VariableBindings.pm 22
lib/RDF/Trine.pm 22
lib/Test/RDF/Trine/Store.pm 22
t/iterator-bindings.t 239
80 files changed (This is a version diff) 353778
@@ -10,6 +10,40 @@
         dcterms:references      <http://kasei.us/code/rdf-trine/#project> .
 
 
+<http://kasei.us/code/files/RDF-Trine-1.010.tar.gz>
+        dcterms:isVersionOf <http://kasei.us/code/rdf-trine/#project> ;
+        dcterms:replaces    <http://kasei.us/code/files/RDF-Trine-1.009.tar.gz> ;
+
+        doap:Version    [
+                        doap:revision     "1.010" ;
+                        doap:created      "2014-10-03" ;
+                        ];
+        asc:changes     [
+                        asc:update      "Fixed bug in SPARQL store that wasn't properly decoding HTTP response content (github issue #118)." ;
+                        asc:update      "Refactored part of RDF::Trine::Iterator::Graph->as_hashref into RDF::Trine::Node->as_hashref (github issue #117)." ;
+                        asc:update      "Update RDF::Trine::Pattern with heuristic pattern sorter (github pull request #114 from Kjetil Kjernsmo)." ;
+                        asc:update      "Added IRC resource to Makefile.PL." ;
+                        ] .
+
+
+<http://kasei.us/code/files/RDF-Trine-1.009.tar.gz>
+        dcterms:isVersionOf <http://kasei.us/code/rdf-trine/#project> ;
+        dcterms:replaces    <http://kasei.us/code/files/RDF-Trine-1.008.tar.gz> ;
+
+        doap:Version    [
+                        doap:revision     "1.009" ;
+                        doap:created      "2014-08-06" ;
+                        ];
+        asc:changes     [
+                        asc:addition    "Adding model sync/bulk ops to redland store (Dorian Taylor)." ;
+                        asc:update      "Optimized use of regular expressions (Dorian Taylor)." ;
+                        asc:update      "Optimized Hexastore store class (Dorian Taylor)." ;
+                        asc:update      "Log an info message if there is a cartesian product (Kjetil Kjernsmo)." ;
+                        asc:update      "Use a base64 encoded digest for Memory store etags (Kjetil Kjernsmo)." ;
+                        asc:update      "Updated RDF::Trine::Iterator::Bindings->as_statements to accept a RDF::Trine::Pattern argument (github issue #104)." ;
+                        ] .
+
+
 <http://kasei.us/code/files/RDF-Trine-1.008.tar.gz>
         dcterms:isVersionOf <http://kasei.us/code/rdf-trine/#project> ;
         dcterms:replaces    <http://kasei.us/code/files/RDF-Trine-1.007.tar.gz> ;
@@ -5,6 +5,7 @@ author:
   - 'Gregory Todd Williams <gwilliams@cpan.org>'
 build_requires:
   ExtUtils::MakeMaker: 6.59
+  Test::Deep: 0
   Test::Exception: 0
   Test::JSON: 0
   Test::More: 0.88
@@ -13,7 +14,7 @@ configure_requires:
   ExtUtils::MakeMaker: 6.59
 distribution_type: module
 dynamic_config: 1
-generated_by: 'Module::Install version 1.08'
+generated_by: 'Module::Install version 1.12'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -40,7 +41,7 @@ requires:
   HTTP::Negotiate: 0
   JSON: 2
   LWP::UserAgent: 0
-  List::Util: 0
+  List::Util: 1.33
   Log::Log4perl: 0
   Math::BigInt: 0
   Module::Load::Conditional: 0.38
@@ -58,8 +59,9 @@ requires:
   XML::SAX: 0.96
   perl: 5.10.0
 resources:
+  IRC: irc://irc.perl.org/#perlrdf
   bugtracker: https://github.com/kasei/perlrdf/issues
   homepage: http://search.cpan.org/dist/RDF-Trine/
   license: http://dev.perl.org/licenses/
   repository: http://github.com/kasei/perlrdf/
-version: '1.008'
+version: '1.010'
@@ -9,6 +9,7 @@ author				'Gregory Todd Williams <gwilliams@cpan.org>';
 license				'perl';
 
 build_requires		'Test::More'				=> 0.88;
+build_requires		'Test::Deep'				=> 0;
 build_requires		'Test::Exception'			=> 0;
 build_requires		'Test::JSON'				=> 0;
 build_requires		'TryCatch'					=> 0;
@@ -28,7 +29,7 @@ requires			'Error'						=> 0;
 requires			'HTTP::Negotiate'			=> 0;
 requires			'JSON'						=> 2;
 requires			'LWP::UserAgent'			=> 0;
-requires			'List::Util'				=> 0;
+requires			'List::Util'				=> 1.33;
 requires			'Log::Log4perl'				=> 0;
 requires			'Math::BigInt'				=> 0;
 requires			'Algorithm::Combinatorics'	=> 0;
@@ -47,9 +48,10 @@ recommends			'XML::LibXML'				=> 1.70;
 recommends			'Term::ANSIColor'			=> 0;
 
 resources(
-	'homepage'   => "http://search.cpan.org/dist/RDF-Trine/",
-	'repository' => "http://github.com/kasei/perlrdf/",
-	'bugtracker' => "https://github.com/kasei/perlrdf/issues"
+	'homepage'		=> "http://search.cpan.org/dist/RDF-Trine/",
+	'repository'	=> "http://github.com/kasei/perlrdf/",
+	'bugtracker'	=> "https://github.com/kasei/perlrdf/issues",
+	'IRC'			=> "irc://irc.perl.org/#perlrdf",
 );
 
 author_tests('xt');
@@ -68,7 +68,30 @@ INSTALLATION
 
 VERSION HISTORY
 
-  Version 1.008 (2014-05-20)
+  Version 1.010 (2014-10-03)
+
+     * BUG FIXES
+         	Fixed bug in SPARQL store that wasn't properly decoding HTTP response content (github issue #118).
+     * NEW FEATURES
+         	Refactored part of RDF::Trine::Iterator::Graph->as_hashref into RDF::Trine::Node->as_hashref (github issue #117).
+     * ENHANCEMENTS
+         	Update RDF::Trine::Pattern with heuristic pattern sorter (github pull request #114 from Kjetil Kjernsmo).
+     * OTHER
+         	Added IRC resource to Makefile.PL.
+
+  Version 1.009 (2014-08-06)
+
+     * NEW FEATURES
+         	Adding model sync/bulk ops to redland store (Dorian Taylor).
+     * ENHANCEMENTS
+         	Optimized use of regular expressions (Dorian Taylor).
+         	Optimized Hexastore store class (Dorian Taylor).
+         	Use a base64 encoded digest for Memory store etags (Kjetil Kjernsmo).
+         	Updated RDF::Trine::Iterator::Bindings->as_statements to accept a RDF::Trine::Pattern argument (github issue #104).
+     * OTHER
+         	Log an info message if there is a cartesian product (Kjetil Kjernsmo).
+
+  Version 1.009 (2014-05-20)
 
      * BUG FIXES
          	Fixed bug in Turtle lexer that was failing to anchor matches of PNAME_LN (GH issue #96 by Tobias Kuhn).
@@ -14,11 +14,11 @@ not run its Makefile.PL or Build.PL.
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-SHA1 8a080614aaa51d811d0ce9731d90ce230944803a Changes.ttl
+SHA1 1bec99b989514e62032d0722e429d5a6f17ae85b Changes.ttl
 SHA1 22a368e748a13b1d961d4b069bb52a470669c637 MANIFEST
-SHA1 d644f39da03bb480f339025b4de95eaa86cc7f5a META.yml
-SHA1 436d1d4da25a99b21fc67b3203bf4f6043616aaf Makefile.PL
-SHA1 8bb548c3a9adfc72bcac3ebab7f3693e0cf595c3 README
+SHA1 9ead4941e63033db1570db3baad72d806fd4e29b META.yml
+SHA1 a2c5d6f0501dfc7cb72419ea691688c3dd0d7b89 Makefile.PL
+SHA1 51f226cdfcfbd324306257cbed07a133b930e754 README
 SHA1 de1a886d4a10836f9a9f7bfb07c01df6bc14ce1f bin/cliapi
 SHA1 6b887e866f74e6f823724001c49146ee906c558a bin/graph.pl
 SHA1 6b250506c12423fc465c493af38c65ef5b310274 bin/rdf_init_store.pl
@@ -36,81 +36,81 @@ SHA1 be0338e5e9faea24cd684515c93c58b07d58bde4 bin/turtle_parse.pl
 SHA1 9a8c63f53beb5203aed53d9c28478a13d1ed02d1 bin/turtle_tokenize.pl
 SHA1 54c909523bd47ad798dfc9bc97a64ecd768a51fb examples/foaf_labels.pl
 SHA1 e25f036a2f1cb94b03dd008032109b0bbfbd53f8 extra/mysql.sql
-SHA1 dc13ce0dbb488a5de81c3f6519ee31acda17397a inc/Module/Install.pm
+SHA1 9b5001bfa9cf8607b3b3935284d9253e0391c9f1 inc/Module/Install.pm
 SHA1 d001b4b9a48395a8c4134b234a0e1789138427c5 inc/Module/Install/AuthorTests.pm
-SHA1 91c20cbda8ca41b4e8f9e0390faff635c2ebe839 inc/Module/Install/Base.pm
-SHA1 eaf50ccbacecb797f0527deb0221c8264f6c8bd8 inc/Module/Install/Can.pm
-SHA1 363c8931cc183444907684b71d6a379e4fc8edcb inc/Module/Install/Fetch.pm
-SHA1 26ae1c0f5f352037b560414f216d7e3ac682f936 inc/Module/Install/Makefile.pm
-SHA1 ff97eb025b44c343d026c2a56a73d50c65319e95 inc/Module/Install/Metadata.pm
-SHA1 45b8ad29be4f0108076da44ac8393156d6513be0 inc/Module/Install/Scripts.pm
-SHA1 4c5ce519d404e242418f51dfe761287469e18e3a inc/Module/Install/Win32.pm
-SHA1 47a52cf8719a283c0efa2edab0088b5d67e0f23a inc/Module/Install/WriteAll.pm
-SHA1 fb4ac5b0e96bed114571b367a0218fd6b2c097f0 lib/RDF/Trine.pm
-SHA1 772c8165bc69669aa44ae1a1b028e0b0be15994b lib/RDF/Trine/Error.pm
-SHA1 913d7de5feae431131c0681c51dac576e2193a13 lib/RDF/Trine/Exporter/CSV.pm
-SHA1 c9337b7cf7ae22616b8e191381414ecfe1f9b97e lib/RDF/Trine/Exporter/RDFPatch.pm
-SHA1 1af2a9f3702591eb8c72dc556df38431d6f653ae lib/RDF/Trine/Graph.pm
-SHA1 7237daa1039224ca684da6e631ead5e57f02c9a0 lib/RDF/Trine/Iterator.pm
-SHA1 81de66a4c114b3650d9e40caed8505e21df12f80 lib/RDF/Trine/Iterator/Bindings.pm
-SHA1 0eb3af713ca9bc2332d0e902b4d1e34f80fe9838 lib/RDF/Trine/Iterator/Bindings/Materialized.pm
-SHA1 0a7b5df0b010c2233ca2499a185652c5c775bea2 lib/RDF/Trine/Iterator/Boolean.pm
-SHA1 b3ba51b66fb89af6ee9f3314a1a6b79d0f65ac2c lib/RDF/Trine/Iterator/Graph.pm
-SHA1 b0ef08ffadab74c543e5061f3b5ad73347706291 lib/RDF/Trine/Iterator/Graph/Materialized.pm
-SHA1 ab7b431d2a207162fa4de6304352c48b6f16a7cf lib/RDF/Trine/Iterator/JSONHandler.pm
-SHA1 ad3f62f4bdf46a7dbebaa82fca192017d28de506 lib/RDF/Trine/Iterator/SAXHandler.pm
-SHA1 1ad03114e8197d0149ec7cd2ad6f4a6546727419 lib/RDF/Trine/Model.pm
-SHA1 44fc08d76ebe474e36a2ad462a46703ae6c65a2f lib/RDF/Trine/Model/Dataset.pm
-SHA1 dc7a92d8ea7e259206c741834c6aef5061fd17a7 lib/RDF/Trine/Model/StatementFilter.pm
-SHA1 5d9006c70c61062fb1e0fd74b683e71ab277c178 lib/RDF/Trine/Model/Union.pm
-SHA1 cdccaed0afaf577b09cf1666aedeedad169a36aa lib/RDF/Trine/Namespace.pm
-SHA1 426ca22dc300e539e0696720c4bb94aaa760d795 lib/RDF/Trine/NamespaceMap.pm
-SHA1 19ff9b7b19731bc9554d0c8334f2d0ba0afb1270 lib/RDF/Trine/Node.pm
-SHA1 6b2e110a55238ddea138942cdb3aa95ad4559911 lib/RDF/Trine/Node/Blank.pm
-SHA1 0343de095c7dc76213edaadfa173a56c0f5561b5 lib/RDF/Trine/Node/Literal.pm
-SHA1 736a780f65d343211c24eebe39d613092d5fb78e lib/RDF/Trine/Node/Nil.pm
-SHA1 540355ec95ea2af78d0e0beb5c05e93665069532 lib/RDF/Trine/Node/Resource.pm
-SHA1 e5705a23f9213251cae100e9e8a6107b15d10d11 lib/RDF/Trine/Node/Variable.pm
-SHA1 43ef6e03cdbef13bed361a1390c55519afc4bafe lib/RDF/Trine/Parser.pm
-SHA1 583af1f2b8cd223fa01af6612f29fff7a87ac33f lib/RDF/Trine/Parser/LineProtocol.pm
-SHA1 593a5cc57191a902b26dd8446792444d31230220 lib/RDF/Trine/Parser/NQuads.pm
-SHA1 6b53506166f60a11009d753b3bd0313d562642ec lib/RDF/Trine/Parser/NTriples.pm
-SHA1 264268eff36bfb1caf63854c2d56944f648c41ad lib/RDF/Trine/Parser/RDFJSON.pm
-SHA1 6455fdf587698c61b134a286bf5f966cadd0bd64 lib/RDF/Trine/Parser/RDFPatch.pm
-SHA1 69f64fe578ae1a54a519bbe2f760aef78209d5d5 lib/RDF/Trine/Parser/RDFXML.pm
-SHA1 835fa4efaeaf623bacbadd829a8c414e0f813ef5 lib/RDF/Trine/Parser/RDFa.pm
-SHA1 8115397219ed0d0fcdd531d344e58555dbefcc23 lib/RDF/Trine/Parser/Redland.pm
-SHA1 73843b3561ea3cc03c6cdf993ba78561c65e12c8 lib/RDF/Trine/Parser/TriG.pm
-SHA1 67c388095d347acdac72a536eeb976a457d65df8 lib/RDF/Trine/Parser/Turtle.pm
-SHA1 deec5477d827d94790ad4135de389b4c188d476d lib/RDF/Trine/Parser/Turtle/Constants.pm
-SHA1 94e83937ab68b0215df60edf28f4a4082efa3a9c lib/RDF/Trine/Parser/Turtle/Lexer.pm
-SHA1 c210d2369f1be2469fb59ec14dc2749de1e88ff3 lib/RDF/Trine/Parser/Turtle/Token.pm
-SHA1 04f83876fb690b7d2005953108176401c581d96c lib/RDF/Trine/Pattern.pm
-SHA1 94b1a9b13d3ff147941d764bfa3dfc66e8c1326a lib/RDF/Trine/Serializer.pm
-SHA1 46892fd7b0545ff64ae108b44f7b042a552a6950 lib/RDF/Trine/Serializer/NQuads.pm
-SHA1 c3b39f0c32b6bd38ec01989845911b7e0689598d lib/RDF/Trine/Serializer/NTriples.pm
-SHA1 231646d806ad32b75828d6e47d396bcf3cd89654 lib/RDF/Trine/Serializer/NTriples/Canonical.pm
-SHA1 0ee1cd018c2d359b43a13fe6b02094d05a6f01c7 lib/RDF/Trine/Serializer/RDFJSON.pm
-SHA1 23c67317e3020080f067f8229da8c0837cb28f7d lib/RDF/Trine/Serializer/RDFPatch.pm
-SHA1 bd184ee3e762e3048ffedf5f1c5241c5ae5c852d lib/RDF/Trine/Serializer/RDFXML.pm
-SHA1 0b755b803df97407f2d0fcd92fa8a0c26e5107b5 lib/RDF/Trine/Serializer/TSV.pm
-SHA1 48daf42b9cb1e814b8bd0428accf1b3df79b2cdc lib/RDF/Trine/Serializer/TriG.pm
-SHA1 1c9ff00a3406cf44bdac9a67440ba836bc5c03b3 lib/RDF/Trine/Serializer/Turtle.pm
-SHA1 689b7237cd9807db80343b9d4ee9c60c937e07e4 lib/RDF/Trine/Statement.pm
-SHA1 066aca1fb422ad81e1573c3f59312cc2c2305f7f lib/RDF/Trine/Statement/Quad.pm
-SHA1 1a01e4c884f430e7bd50af2fb00ee982f69393ee lib/RDF/Trine/Store.pm
-SHA1 e125a861c34b035abaf22927d5b91f654891055f lib/RDF/Trine/Store/DBI.pm
-SHA1 3b012618f61b7caf3f24aa4a19e52de33989a4d4 lib/RDF/Trine/Store/DBI/Pg.pm
-SHA1 a0feef3272ab79e9b3dfb8d87865e03f040d914a lib/RDF/Trine/Store/DBI/SQLite.pm
-SHA1 a4d67331181d140c3f68edb05bf8ffe8aba5c5bf lib/RDF/Trine/Store/DBI/mysql.pm
-SHA1 c052c27521fb14a46fbe6721d759e6e66cff044a lib/RDF/Trine/Store/Dydra.pm
-SHA1 69b397fa891e85a5ee51db5b6e754904e2d13c5f lib/RDF/Trine/Store/Hexastore.pm
-SHA1 d39aadce6e256a21a35b47766fae6143c6acbfd5 lib/RDF/Trine/Store/Memory.pm
-SHA1 1445fb5705d1831b22edddac447a32fa50bb1e33 lib/RDF/Trine/Store/Redis.pm
-SHA1 0f4ff27a820599d01e9bc12ba05d83f7032935a0 lib/RDF/Trine/Store/Redland.pm
-SHA1 feac9960d968b70e3ff2d1f8f5dafac393fbaff5 lib/RDF/Trine/Store/SPARQL.pm
-SHA1 7dfbe116876f6cb3d69ab39403343f03adb7e27c lib/RDF/Trine/VariableBindings.pm
-SHA1 d8b5c402bb910e92f4d7e260e671553043f7cea8 lib/Test/RDF/Trine/Store.pm
+SHA1 cab0e564f9bdf658535f683aa197157e06d0dcea inc/Module/Install/Base.pm
+SHA1 a1559b5b3b40f68efbbd256f4fef85970891b3ae inc/Module/Install/Can.pm
+SHA1 f15c1ba85f6d52e70c48c64bf0752c90a4ad66f9 inc/Module/Install/Fetch.pm
+SHA1 eb48df8bafd07c6a862126d9b274df42b4395742 inc/Module/Install/Makefile.pm
+SHA1 95c73873c6c3cb7024614c225c53863e1e90c134 inc/Module/Install/Metadata.pm
+SHA1 a1820d820772de5eb9c190425babf2c29a2caaf7 inc/Module/Install/Scripts.pm
+SHA1 f8b2ae3386f6ba26c33408968a953d450842eade inc/Module/Install/Win32.pm
+SHA1 f302bc703d76299cff243e5b44cecd61aac27b76 inc/Module/Install/WriteAll.pm
+SHA1 80936d5be37af3d15ffcbbed3774d8502ce81d95 lib/RDF/Trine.pm
+SHA1 a22684da9791d6447414756f02787a5036145f5b lib/RDF/Trine/Error.pm
+SHA1 2b2c56cef8cf85fc5dac017a1e34d52b6983c510 lib/RDF/Trine/Exporter/CSV.pm
+SHA1 fb7c260bb0c64d20aaf66f132afbe00bafe68ce4 lib/RDF/Trine/Exporter/RDFPatch.pm
+SHA1 8290b2d2c1edcac3f3dc5a2f869807119f67a94a lib/RDF/Trine/Graph.pm
+SHA1 0e8e59acc2c3ce8572addacb1eeec2f5d2ce0758 lib/RDF/Trine/Iterator.pm
+SHA1 758d7e1b4668526066b57c3088645dc8a9992c44 lib/RDF/Trine/Iterator/Bindings.pm
+SHA1 07f48a4f94836faa84c8a1ac2410ebafa24056b0 lib/RDF/Trine/Iterator/Bindings/Materialized.pm
+SHA1 f47a1958bc8bd11bcdd17bcd86cc1e6289d8c60a lib/RDF/Trine/Iterator/Boolean.pm
+SHA1 86247c129c23061354a1b0af3fafd08bfb7d5e1c lib/RDF/Trine/Iterator/Graph.pm
+SHA1 0b005883913ca6a7d69986afe331dc331d87dd56 lib/RDF/Trine/Iterator/Graph/Materialized.pm
+SHA1 1a07f077aae6d3e0b93fcc1ebcfc79ada4b1d097 lib/RDF/Trine/Iterator/JSONHandler.pm
+SHA1 5945206810244106567077a22f217bb6ddaea081 lib/RDF/Trine/Iterator/SAXHandler.pm
+SHA1 4addc9fa2d020e2d5d8361dfb7e1f378859e904e lib/RDF/Trine/Model.pm
+SHA1 a19648a990a035fcd8341202364bb6273ac94e23 lib/RDF/Trine/Model/Dataset.pm
+SHA1 807ff3f03f8c69eb9f0737a48341c17136b16310 lib/RDF/Trine/Model/StatementFilter.pm
+SHA1 cfe10ec88a62be30b5bb9d879df5a6e00e6a2763 lib/RDF/Trine/Model/Union.pm
+SHA1 b1a4abf63291fe2b57afb9c52986a235291bf713 lib/RDF/Trine/Namespace.pm
+SHA1 674eb8256450a5c23bb2e87e44ccf59032d77e40 lib/RDF/Trine/NamespaceMap.pm
+SHA1 fba090c9fccc15e6e9d2c9df52d15676d1a7f0b7 lib/RDF/Trine/Node.pm
+SHA1 ef800258cdb547c5f7b5ed7ee2356a01cd0477c0 lib/RDF/Trine/Node/Blank.pm
+SHA1 29466376a7540783a0011913ba1b403af38f2606 lib/RDF/Trine/Node/Literal.pm
+SHA1 00cc4374ae4c13197091ef06c4c3a5664d100c87 lib/RDF/Trine/Node/Nil.pm
+SHA1 3b618ecb2200acc5b044a674f3450a8164093616 lib/RDF/Trine/Node/Resource.pm
+SHA1 6757a3a6131383c090b0f2211b91c902153b7a5b lib/RDF/Trine/Node/Variable.pm
+SHA1 55d9634330eb019e8b485ee6d7149f2d4498821a lib/RDF/Trine/Parser.pm
+SHA1 766cdda0a54094ca30c1360306b6c9299aac8269 lib/RDF/Trine/Parser/LineProtocol.pm
+SHA1 7698bf9c9e6129fd3ac5f6a2c210d7732da7bf13 lib/RDF/Trine/Parser/NQuads.pm
+SHA1 c31b210e31473e39a0833dd8dfde03f731e8277c lib/RDF/Trine/Parser/NTriples.pm
+SHA1 7a6aaf3b73c4b6a8802f57e44b982aeccf0fa21b lib/RDF/Trine/Parser/RDFJSON.pm
+SHA1 f11c2cfb3838f03fd688aa5bd447203abb42ced9 lib/RDF/Trine/Parser/RDFPatch.pm
+SHA1 819e1d4d500deee331e2fed8a9966a084dffc645 lib/RDF/Trine/Parser/RDFXML.pm
+SHA1 428b430d827e5fb27238757fbe4a59b8e30eeef2 lib/RDF/Trine/Parser/RDFa.pm
+SHA1 82946c0c505f1d6c478466e56b7786ccac396035 lib/RDF/Trine/Parser/Redland.pm
+SHA1 bf2d4ff189e6ab9cf5485155f0a3760e2c596427 lib/RDF/Trine/Parser/TriG.pm
+SHA1 f4ecad61edf65a0249ee5a440b6470b768b38ce5 lib/RDF/Trine/Parser/Turtle.pm
+SHA1 7464941fdee5142c5f663684221afb7fedfb49cc lib/RDF/Trine/Parser/Turtle/Constants.pm
+SHA1 be737b519d1b7c47daf8c360dfa1b0442567bf62 lib/RDF/Trine/Parser/Turtle/Lexer.pm
+SHA1 acaeb13199572b3c2a5f7da0dcd1c85788ea8ec6 lib/RDF/Trine/Parser/Turtle/Token.pm
+SHA1 12c99e461d3405c2617bf0de7651cd9300105acd lib/RDF/Trine/Pattern.pm
+SHA1 a346caa870fce3a8ccc8897ac19fe0fe7bbd212d lib/RDF/Trine/Serializer.pm
+SHA1 06762a37048cd3d6209d5b704ef0bb46c1c901ad lib/RDF/Trine/Serializer/NQuads.pm
+SHA1 e04bbc03f99dce594f6018c929a26f37ff8f7424 lib/RDF/Trine/Serializer/NTriples.pm
+SHA1 ff896a8900a5326c289bd15ded25bef21239e65a lib/RDF/Trine/Serializer/NTriples/Canonical.pm
+SHA1 8417e50eb0d66125d1a0d1e94c159637748155e0 lib/RDF/Trine/Serializer/RDFJSON.pm
+SHA1 7610a12c7ee9a63cc8ba9f00973cd978c3f1c993 lib/RDF/Trine/Serializer/RDFPatch.pm
+SHA1 14288cd9fb154a68c557a2f032819f71bd0ceffc lib/RDF/Trine/Serializer/RDFXML.pm
+SHA1 3bcc42373a526fb4fb1d5666a654a250fd85f507 lib/RDF/Trine/Serializer/TSV.pm
+SHA1 9a591937423c8cdab72279f86728ac013256ff50 lib/RDF/Trine/Serializer/TriG.pm
+SHA1 bb8a0cd2a7b249fe342d686818cf35e47f41f12d lib/RDF/Trine/Serializer/Turtle.pm
+SHA1 811a4c9ad045a1540ca14e27edec39d92f92e91a lib/RDF/Trine/Statement.pm
+SHA1 d46408eed16c6bd15b74e2185b68d4761d932424 lib/RDF/Trine/Statement/Quad.pm
+SHA1 8ea116c318a639e194c83570447d1bf7c6dcfea3 lib/RDF/Trine/Store.pm
+SHA1 b7bfb422eb8fc0bbe72af12e6e539c1a6ecd0c98 lib/RDF/Trine/Store/DBI.pm
+SHA1 af59eb450ba7ac7e3b072880307b2b592e8e889a lib/RDF/Trine/Store/DBI/Pg.pm
+SHA1 1ac6c4dd459f128c1a8c81e4ae6446c26e56fb6d lib/RDF/Trine/Store/DBI/SQLite.pm
+SHA1 d86f198959dcf7be602c28ecab046486e9fde974 lib/RDF/Trine/Store/DBI/mysql.pm
+SHA1 dce2e8351362ba7cec6092533902ab71bfe46e02 lib/RDF/Trine/Store/Dydra.pm
+SHA1 0d120409ef8f94faa3a30bb38fb9842d8cf5a9f8 lib/RDF/Trine/Store/Hexastore.pm
+SHA1 237412055db55a81964c3f0e54d5b8790aa6ee0a lib/RDF/Trine/Store/Memory.pm
+SHA1 445ee18050b8ed1ca6ed4a10528e88cd4a73fd05 lib/RDF/Trine/Store/Redis.pm
+SHA1 39d97fad92d92353256a8c38f172bcff8b100584 lib/RDF/Trine/Store/Redland.pm
+SHA1 617a4cd5ed003aa0502d864bdbf6adb44294208f lib/RDF/Trine/Store/SPARQL.pm
+SHA1 cbfd9989cfd7ef6382d8cd3658946695258ac583 lib/RDF/Trine/VariableBindings.pm
+SHA1 d1c8e8a5265312c24487f78286c1fcd6f409df02 lib/Test/RDF/Trine/Store.pm
 SHA1 3d6f8b1b1edbb40c4bae20dfc977fcf67d97ff28 t/00.load.t
 SHA1 403973466abf1be3a25ac53e0e4eeaee06e1a669 t/data/bugs/ttl-with-bom.ttl
 SHA1 171b51b6ee76df5df278cd9b8946edbc2dade2b4 t/data/rdfa/test-sd.nt
@@ -1323,7 +1323,7 @@ SHA1 77d3ecc040080e5dc649bd56090b0aeedeceff90 t/graph-subgraphs.t
 SHA1 0155808c901e925f4dd0af99a62ce4988dac6c33 t/graph.t
 SHA1 eeb60d81a3ba5aed1c7bbdfb865e8606a0803c4f t/iterator-bindings-join.t
 SHA1 0434eb1940161be055f80b36976266761db4b1e3 t/iterator-bindings-materialize.t
-SHA1 63c4eeeaca8fda906a89b1ca02faa7a20b27db7b t/iterator-bindings.t
+SHA1 631b98035778a9aebf3cb73a88a928a4c4bde24b t/iterator-bindings.t
 SHA1 6d40cb41c4ba2c1c1fe15e96b6bcf3f54b79cbc7 t/iterator-boolean.t
 SHA1 3c27b9c168a8f53d3339b9f271702cfbe9bec15f t/iterator-graph-materialize.t
 SHA1 29608bb2ceeac144565bd392958962c935ff12d4 t/iterator-graph.t
@@ -1401,7 +1401,7 @@ SHA1 0d59038cf8ba6efd00638de2bcf3c56bbd3e7da1 xt/store-sparql.t
 Version: GnuPG v1
 Comment: GPGTools - http://gpgtools.org
 
-iEYEARECAAYFAlN73UwACgkQhPK6VMqoyC3fHwCfU5tbML8rDmNOl2e58/DmC++r
-SCwAn1hLtcOHETnrBnbyWeD35wzmuC21
-=ILYD
+iEYEARECAAYFAlQvEN8ACgkQhPK6VMqoyC2C5ACdH9BLnjxZG+gI3BjbuASksjHm
+auMAniqT/T5tPaky7vchjTrbphjQGFNY
+=HHv3
 -----END PGP SIGNATURE-----
@@ -4,7 +4,7 @@ package Module::Install::Base;
 use strict 'vars';
 use vars qw{$VERSION};
 BEGIN {
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 }
 
 # Suspend handler for "redefined" warnings
@@ -8,7 +8,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -8,7 +8,7 @@ use Fcntl qw/:flock :seek/;
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -133,7 +133,7 @@ sub makemaker_args {
 	return $args;
 }
 
-# For mm args that take multiple space-seperated args,
+# For mm args that take multiple space-separated args,
 # append an argument to the current list.
 sub makemaker_append {
 	my $self = shift;
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -347,7 +347,7 @@ sub name_from {
 		^ \s*
 		package \s*
 		([\w:]+)
-		\s* ;
+		[\s|;]*
 		/ixms
 	) {
 		my ($name, $module_name) = ($1, $1);
@@ -705,7 +705,7 @@ sub _write_mymeta_data {
 	my @yaml = Parse::CPAN::Meta::LoadFile('META.yml');
 	my $meta = $yaml[0];
 
-	# Overwrite the non-configure dependency hashs
+	# Overwrite the non-configure dependency hashes
 	delete $meta->{requires};
 	delete $meta->{build_requires};
 	delete $meta->{recommends};
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 	@ISA     = qw{Module::Install::Base};
 	$ISCORE  = 1;
 }
@@ -17,7 +17,7 @@ package Module::Install;
 #     3. The ./inc/ version of Module::Install loads
 # }
 
-use 5.005;
+use 5.006;
 use strict 'vars';
 use Cwd        ();
 use File::Find ();
@@ -31,7 +31,7 @@ BEGIN {
 	# This is not enforced yet, but will be some time in the next few
 	# releases once we can make sure it won't clash with custom
 	# Module::Install extensions.
-	$VERSION = '1.08';
+	$VERSION = '1.12';
 
 	# Storage for the pseudo-singleton
 	$MAIN    = undef;
@@ -156,10 +156,10 @@ END_DIE
 sub autoload {
 	my $self = shift;
 	my $who  = $self->_caller;
-	my $cwd  = Cwd::cwd();
+	my $cwd  = Cwd::getcwd();
 	my $sym  = "${who}::AUTOLOAD";
 	$sym->{$cwd} = sub {
-		my $pwd = Cwd::cwd();
+		my $pwd = Cwd::getcwd();
 		if ( my $code = $sym->{$pwd} ) {
 			# Delegate back to parent dirs
 			goto &$code unless $cwd eq $pwd;
@@ -239,7 +239,7 @@ sub new {
 
 	# ignore the prefix on extension modules built from top level.
 	my $base_path = Cwd::abs_path($FindBin::Bin);
-	unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
+	unless ( Cwd::abs_path(Cwd::getcwd()) eq $base_path ) {
 		delete $args{prefix};
 	}
 	return $args{_self} if $args{_self};
@@ -338,7 +338,7 @@ sub find_extensions {
 		if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
 			my $content = Module::Install::_read($subpath . '.pm');
 			my $in_pod  = 0;
-			foreach ( split //, $content ) {
+			foreach ( split /\n/, $content ) {
 				$in_pod = 1 if /^=\w/;
 				$in_pod = 0 if /^=cut/;
 				next if ($in_pod || /^=cut/);  # skip pod text
@@ -434,7 +434,7 @@ END_OLD
 
 # _version is for processing module versions (eg, 1.03_05) not
 # Perl versions (eg, 5.8.1).
-sub _version ($) {
+sub _version {
 	my $s = shift || 0;
 	my $d =()= $s =~ /(\.)/g;
 	if ( $d >= 2 ) {
@@ -450,12 +450,12 @@ sub _version ($) {
 	return $l + 0;
 }
 
-sub _cmp ($$) {
+sub _cmp {
 	_version($_[1]) <=> _version($_[2]);
 }
 
 # Cloned from Params::Util::_CLASS
-sub _CLASS ($) {
+sub _CLASS {
 	(
 		defined $_[0]
 		and
@@ -7,7 +7,7 @@ RDF::Trine::Error - Error classes for RDF::Trine
 
 =head1 VERSION
 
-This document describes RDF::Trine::Error version 1.008
+This document describes RDF::Trine::Error version 1.010
 
 =head1 SYNOPSIS
 
@@ -38,7 +38,7 @@ use base qw(Error);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Exporter::CSV - Export RDF data to CSV
 
 =head1 VERSION
 
-This document describes RDF::Trine::Exporter::CSV version 1.008
+This document describes RDF::Trine::Exporter::CSV version 1.010
 
 =head1 SYNOPSIS
 
@@ -33,7 +33,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 =head1 METHODS
@@ -7,7 +7,7 @@ RDF::Trine::Exporter::RDFPatch - RDF-Patch Export
 
 =head1 VERSION
 
-This document describes RDF::Trine::Exporter::RDFPatch version 1.008
+This document describes RDF::Trine::Exporter::RDFPatch version 1.010
 
 =head1 SYNOPSIS
 
@@ -44,7 +44,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Graph - Materialized RDF Graphs for testing isomorphism
 
 =head1 VERSION
 
-This document describes RDF::Trine::Graph version 1.008
+This document describes RDF::Trine::Graph version 1.010
 
 =head1 SYNOPSIS
 
@@ -40,7 +40,7 @@ use Algorithm::Combinatorics qw(permutations);
 our ($VERSION, $debug, $AUTOLOAD);
 BEGIN {
 	$debug		= 0;
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 use overload
@@ -7,7 +7,7 @@ RDF::Trine::Iterator::Bindings::Materialized - Materialized bindings class
 
 =head1 VERSION
 
-This document describes RDF::Trine::Iterator::Bindings::Materialized version 1.008
+This document describes RDF::Trine::Iterator::Bindings::Materialized version 1.010
 
 =head1 SYNOPSIS
 
@@ -51,7 +51,7 @@ use Scalar::Util qw(blessed reftype);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 =item C<< new ( \@results, \@names, %args ) >>
@@ -7,7 +7,7 @@ RDF::Trine::Iterator::Bindings - Iterator class for bindings query results
 
 =head1 VERSION
 
-This document describes RDF::Trine::Iterator::Bindings version 1.008
+This document describes RDF::Trine::Iterator::Bindings version 1.010
 
 =head1 SYNOPSIS
 
@@ -51,7 +51,7 @@ use Carp qw(croak);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 =item C<new ( \@results, \@names, %args )>
@@ -483,25 +483,57 @@ sub as_string {
 	}
 }
 
-=item C<< as_statements ( @names ) >>
+=item C<< as_statements ( $pattern | @names ) >>
 
 Returns a L<RDF::Trine::Iterator::Graph> with the statements of the stream.
 
+If C<$pattern>, an RDF::Trine::Pattern object, is given as an argument, each of
+its triples are instantiated with variable bindings from each row of the
+iterator, and returned as RDF::Trine::Statement objects from a new
+RDF::Trine::Iterator::Graph iterator.
+
+If 3 variable C<@names> are supplied, their corresponding variable bindings
+in each row of the iterator are used (in order) as the subject, predicate, and
+object of new RDF::Trine::Statement objects and returned from a new
+RDF::Trine::Iterator::Graph iterator.
+
 =cut
 
 sub as_statements {
 	my $self	= shift;
 	my @names	= @_;
-	my $sub		= sub {
-		my $row	= $self->next;
-		return unless (defined $row);
-		my @values	= @{ $row }{ @names };
-		my $statement	= (scalar(@values) == 3 or not(defined($values[3])))
-						? RDF::Trine::Statement->new( @values[ 0 .. 2 ] )
-						: RDF::Trine::Statement::Quad->new( @values );
-		return $statement;
-	};
-	return RDF::Trine::Iterator::Graph->new( $sub )
+	if (scalar(@names) == 1 and $names[0]->can('triples')) {
+		my $pattern	= shift;
+		my @triples	= $pattern->triples;
+		my @queue;
+		my $sub		= sub {
+			while (1) {
+				if (scalar(@queue)) {
+					return shift(@queue);
+				}
+				my $row	= $self->next;
+				return unless (defined $row);
+				foreach my $t (@triples) {
+					my $st	= $t->bind_variables($row);
+					if ($st->rdf_compatible) {
+						push(@queue, $st);
+					}
+				}
+			}
+		};
+		return RDF::Trine::Iterator::Graph->new( $sub );
+	} else {
+		my $sub		= sub {
+			my $row	= $self->next;
+			return unless (defined $row);
+			my @values	= @{ $row }{ @names };
+			my $statement	= (scalar(@values) == 3 or not(defined($values[3])))
+							? RDF::Trine::Statement->new( @values[ 0 .. 2 ] )
+							: RDF::Trine::Statement::Quad->new( @values );
+			return $statement;
+		};
+		return RDF::Trine::Iterator::Graph->new( $sub );
+	}
 }
 
 =item C<< print_xml ( $fh, $max_size ) >>
@@ -7,7 +7,7 @@ RDF::Trine::Iterator::Boolean - Iterator class for boolean query results
 
 =head1 VERSION
 
-This document describes RDF::Trine::Iterator::Boolean version 1.008
+This document describes RDF::Trine::Iterator::Boolean version 1.010
 
 =head1 SYNOPSIS
 
@@ -38,7 +38,7 @@ use JSON 2.0;
 use base qw(RDF::Trine::Iterator);
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 =item C<new ( \@results, %args )>
@@ -7,7 +7,7 @@ RDF::Trine::Iterator::Graph::Materialized - Materialized graph class
 
 =head1 VERSION
 
-This document describes RDF::Trine::Iterator::Graph::Materialized version 1.008
+This document describes RDF::Trine::Iterator::Graph::Materialized version 1.010
 
 =head1 SYNOPSIS
 
@@ -48,7 +48,7 @@ use base qw(RDF::Trine::Iterator::Graph);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 =item C<< new ( \@results, %args ) >>
@@ -7,7 +7,7 @@ RDF::Trine::Iterator::Graph - Iterator class for graph query results
 
 =head1 VERSION
 
-This document describes RDF::Trine::Iterator::Graph version 1.008
+This document describes RDF::Trine::Iterator::Graph version 1.010
 
 =head1 SYNOPSIS
 
@@ -47,7 +47,7 @@ use base qw(RDF::Trine::Iterator);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -334,23 +334,7 @@ sub as_hashref {
 			('_:'.$statement->subject->blank_identifier) :
 			$statement->subject->uri ;
 		my $p = $statement->predicate->uri ;
-		
-		my $o = {};
-		if ($statement->object->isa('RDF::Trine::Node::Literal')) {
-			$o->{'type'}		= 'literal';
-			$o->{'value'}		= $statement->object->literal_value;
-			$o->{'lang'}		= $statement->object->literal_value_language
-				if $statement->object->has_language;
-			$o->{'datatype'}	= $statement->object->literal_datatype
-				if $statement->object->has_datatype;
-		} else {
-			$o->{'type'}		= $statement->object->isa('RDF::Trine::Node::Blank') ? 'bnode' : 'uri';
-			$o->{'value'}		= $statement->object->isa('RDF::Trine::Node::Blank') ? 
-				('_:'.$statement->object->blank_identifier) :
-				$statement->object->uri ;
-		}
-
-		push @{ $index->{$s}->{$p} }, $o;
+		push @{ $index->{$s}->{$p} }, $statement->object->as_hashref;
 	}
 	return $index;
 }
@@ -7,7 +7,7 @@ RDF::Trine::Iterator::JSONHandler - JSON Handler for parsing SPARQL JSON Results
 
 =head1 VERSION
 
-This document describes RDF::Trine::Iterator::JSONHandler version 1.008
+This document describes RDF::Trine::Iterator::JSONHandler version 1.010
 
 =head1 STATUS
 
@@ -40,7 +40,7 @@ use RDF::Trine::VariableBindings;
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 =item C<< new >>
@@ -7,7 +7,7 @@ RDF::Trine::Iterator::SAXHandler - SAX Handler for parsing SPARQL XML Results fo
 
 =head1 VERSION
 
-This document describes RDF::Trine::Iterator::SAXHandler version 1.008
+This document describes RDF::Trine::Iterator::SAXHandler version 1.010
 
 =head1 STATUS
 
@@ -45,7 +45,7 @@ use RDF::Trine::VariableBindings;
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 my %strings;
@@ -7,7 +7,7 @@ RDF::Trine::Iterator - Iterator class for SPARQL query results
 
 =head1 VERSION
 
-This document describes RDF::Trine::Iterator version 1.008.
+This document describes RDF::Trine::Iterator version 1.010.
 
 =head1 SYNOPSIS
 
@@ -43,7 +43,7 @@ use RDF::Trine::Iterator::JSONHandler;
 
 our ($VERSION, @ISA, @EXPORT_OK);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	
 	require Exporter;
 	@ISA		= qw(Exporter);
@@ -7,7 +7,7 @@ RDF::Trine::Model::Dataset - Model for SPARQL datasets
 
 =head1 VERSION
 
-This document describes RDF::Trine::Model::Dataset version 1.008
+This document describes RDF::Trine::Model::Dataset version 1.010
 
 =head1 STATUS
 
@@ -37,7 +37,7 @@ use RDF::Trine::Model;
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ################################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Model::StatementFilter - Model for filtering statements based on a u
 
 =head1 VERSION
 
-This document describes RDF::Trine::Model::StatementFilter version 1.008
+This document describes RDF::Trine::Model::StatementFilter version 1.010
 
 =head1 METHODS
 
@@ -33,7 +33,7 @@ use RDF::Trine::Iterator qw(sgrep);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ################################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Model::Union - Union models for joining multiple stores together
 
 =head1 VERSION
 
-This document describes RDF::Trine::Model::Union version 1.008
+This document describes RDF::Trine::Model::Union version 1.010
 
 =head1 METHODS
 
@@ -31,7 +31,7 @@ use RDF::Trine::Store;
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ################################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Model - Model class
 
 =head1 VERSION
 
-This document describes RDF::Trine::Model version 1.008
+This document describes RDF::Trine::Model version 1.010
 
 =head1 METHODS
 
@@ -23,7 +23,7 @@ no warnings 'redefine';
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 use Scalar::Util qw(blessed refaddr);
@@ -8,7 +8,7 @@ RDF::Trine::Namespace - Abbreviated syntax for constructing RDF node objects
 
 =head1 VERSION
 
-This document describes RDF::Trine::Namespace version 1.008
+This document describes RDF::Trine::Namespace version 1.010
 
 =head1 SYNOPSIS
 
@@ -44,7 +44,7 @@ use base qw(XML::Namespace);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -8,7 +8,7 @@ RDF::Trine::NamespaceMap - Collection of Namespaces
 
 =head1 VERSION
 
-This document describes RDF::Trine::NamespaceMap version 1.008
+This document describes RDF::Trine::NamespaceMap version 1.010
 
 =head1 SYNOPSIS
 
@@ -43,7 +43,7 @@ use Data::Dumper;
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Node::Blank - RDF Node class for blank nodes
 
 =head1 VERSION
 
-This document describes RDF::Trine::Node::Blank version 1.008
+This document describes RDF::Trine::Node::Blank version 1.010
 
 =cut
 
@@ -26,7 +26,7 @@ use Carp qw(carp croak confess);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Node::Literal - RDF Node class for literals
 
 =head1 VERSION
 
-This document describes RDF::Trine::Node::Literal version 1.008
+This document describes RDF::Trine::Node::Literal version 1.010
 
 =cut
 
@@ -27,7 +27,7 @@ use Carp qw(carp croak confess);
 
 our ($VERSION, $USE_XMLLITERALS, $USE_FORMULAE);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	eval "use RDF::Trine::Node::Literal::XML;";	## no critic (ProhibitStringyEval)
 	$USE_XMLLITERALS	= (RDF::Trine::Node::Literal::XML->can('new')) ? 1 : 0;
 	eval "use RDF::Trine::Node::Formula;";	## no critic (ProhibitStringyEval)
@@ -7,7 +7,7 @@ RDF::Trine::Node::Nil - RDF Node class for the nil node
 
 =head1 VERSION
 
-This document describes RDF::Trine::Node::Nil version 1.008
+This document describes RDF::Trine::Node::Nil version 1.010
 
 =cut
 
@@ -27,7 +27,7 @@ use Carp qw(carp croak confess);
 my $NIL_NODE;
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Node::Resource - RDF Node class for IRI resources
 
 =head1 VERSION
 
-This document describes RDF::Trine::Node::Resource version 1.008
+This document describes RDF::Trine::Node::Resource version 1.010
 
 =cut
 
@@ -29,7 +29,7 @@ use Carp qw(carp croak confess);
 
 our ($VERSION, %sse, %ntriples);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Node::Variable - RDF Node class for variables
 
 =head1 VERSION
 
-This document describes RDF::Trine::Node::Variable version 1.008
+This document describes RDF::Trine::Node::Variable version 1.010
 
 =cut
 
@@ -26,7 +26,7 @@ use Carp qw(carp croak confess);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Node - Base class for RDF Nodes
 
 =head1 VERSION
 
-This document describes RDF::Trine::Node version 1.008
+This document describes RDF::Trine::Node version 1.010
 
 =cut
 
@@ -19,7 +19,7 @@ no warnings 'redefine';
 
 our ($VERSION, @ISA, @EXPORT_OK);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	
 	require Exporter;
 	@ISA		= qw(Exporter);
@@ -200,6 +200,34 @@ sub compare {
 	}
 }
 
+=item C<< as_hashref >>
+
+Returns a hashref representing the node in an RDF/JSON-like manner.
+
+See C<< as_hashref >> at L<RDF::Trine::Model> for full documentation of the
+hashref format.
+
+=cut
+
+sub as_hashref {
+	my $self	= shift;
+	my $o = {};
+	if ($self->isa('RDF::Trine::Node::Literal')) {
+		$o->{'type'}		= 'literal';
+		$o->{'value'}		= $self->literal_value;
+		$o->{'lang'}		= $self->literal_value_language
+			if $self->has_language;
+		$o->{'datatype'}	= $self->literal_datatype
+			if $self->has_datatype;
+	} else {
+		$o->{'type'}		= $self->isa('RDF::Trine::Node::Blank') ? 'bnode' : 'uri';
+		$o->{'value'}		= $self->isa('RDF::Trine::Node::Blank') ? 
+			('_:'.$self->blank_identifier) :
+			$self->uri ;
+	}
+	return $o;
+}
+
 =item C<< from_sse ( $string, $context ) >>
 
 Parses the supplied SSE-encoded string and returns a RDF::Trine::Node object.
@@ -7,7 +7,7 @@ RDF::Trine::Parser::LineProtocol - RDF LineProtocol Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::LineProtocol version 1.008
+This document describes RDF::Trine::Parser::LineProtocol version 1.010
 
 =head1 SYNOPSIS
 
@@ -36,7 +36,7 @@ use base qw(RDF::Trine::Parser::RDFPatch);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Parser::NQuads - N-Quads Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::NQuads version 1.008
+This document describes RDF::Trine::Parser::NQuads version 1.010
 
 =head1 SYNOPSIS
 
@@ -51,7 +51,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Parser::parser_names{ 'nquads' }	= __PACKAGE__;
 	$RDF::Trine::Parser::format_uris{ 'http://sw.deri.org/2008/07/n-quads/#n-quads' }	= __PACKAGE__;
 	foreach my $ext (qw(nq)) {
@@ -7,7 +7,7 @@ RDF::Trine::Parser::NTriples - N-Triples Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::NTriples version 1.008
+This document describes RDF::Trine::Parser::NTriples version 1.010
 
 =head1 SYNOPSIS
 
@@ -51,7 +51,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Parser::parser_names{ 'ntriples' }	= __PACKAGE__;
 	foreach my $ext (qw(nt)) {
 		$RDF::Trine::Parser::file_extensions{ $ext }	= __PACKAGE__;
@@ -7,7 +7,7 @@ RDF::Trine::Parser::RDFJSON - RDF/JSON RDF Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::RDFJSON version 1.008
+This document describes RDF::Trine::Parser::RDFJSON version 1.010
 
 =head1 SYNOPSIS
 
@@ -51,7 +51,7 @@ use JSON;
 our ($VERSION, $rdf, $xsd);
 our ($r_boolean, $r_comment, $r_decimal, $r_double, $r_integer, $r_language, $r_lcharacters, $r_line, $r_nameChar_extra, $r_nameStartChar_minus_underscore, $r_scharacters, $r_ucharacters, $r_booltest, $r_nameStartChar, $r_nameChar, $r_prefixName, $r_qname, $r_resource_test, $r_nameChar_test);
 BEGIN {
-	$VERSION				= '1.008';
+	$VERSION				= '1.010';
 	$RDF::Trine::Parser::parser_names{ 'rdfjson' }	= __PACKAGE__;
 	foreach my $ext (qw(json js)) {
 		$RDF::Trine::Parser::file_extensions{ $ext }	= __PACKAGE__;
@@ -7,7 +7,7 @@ RDF::Trine::Parser::RDFPatch - RDF-Patch Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::RDFPatch version 1.008
+This document describes RDF::Trine::Parser::RDFPatch version 1.010
 
 =head1 SYNOPSIS
 
@@ -46,7 +46,7 @@ use RDF::Trine::Parser::Turtle::Constants;
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Parser::RDFXML - RDF/XML Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::RDFXML version 1.008
+This document describes RDF::Trine::Parser::RDFXML version 1.010
 
 =head1 SYNOPSIS
 
@@ -53,7 +53,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION, $HAS_XML_LIBXML);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Parser::parser_names{ 'rdfxml' }	= __PACKAGE__;
 	foreach my $ext (qw(rdf xrdf rdfx)) {
 		$RDF::Trine::Parser::file_extensions{ $ext }	= __PACKAGE__;
@@ -7,7 +7,7 @@ RDF::Trine::Parser::RDFa - RDFa Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::RDFa version 1.008
+This document describes RDF::Trine::Parser::RDFa version 1.010
 
 =head1 SYNOPSIS
 
@@ -50,7 +50,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION, $HAVE_RDFA_PARSER);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	if (can_load( modules => { 'RDF::RDFa::Parser' => 0.30 })) {
 		$HAVE_RDFA_PARSER	= 1;
 		$RDF::Trine::Parser::parser_names{ 'rdfa' }	= __PACKAGE__;
@@ -7,7 +7,7 @@ RDF::Trine::Parser::Redland - RDF Parser using the Redland library
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::Redland version 1.008
+This document describes RDF::Trine::Parser::Redland version 1.010
 
 =head1 SYNOPSIS
 
@@ -85,7 +85,7 @@ BEGIN {
 				],
 	);
 	
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	for my $format (keys %FORMATS) {
 		$RDF::Trine::Parser::parser_names{$format} = $FORMATS{$format}[0];
 		$RDF::Trine::Parser::format_uris{ $FORMATS{$format}[1] } = $FORMATS{$format}[0]
@@ -7,7 +7,7 @@ RDF::Trine::Parser::TriG - TriG RDF Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::TriG version 1.008
+This document describes RDF::Trine::Parser::TriG version 1.010
 
 =head1 SYNOPSIS
 
@@ -41,7 +41,7 @@ use RDF::Trine qw(literal);
 
 our ($VERSION);
 BEGIN {
-	$VERSION				= '1.008';
+	$VERSION				= '1.010';
 	$RDF::Trine::Parser::parser_names{ 'trig' }	= __PACKAGE__;
 	foreach my $ext (qw(trig)) {
 		$RDF::Trine::Parser::file_extensions{ $ext }	= __PACKAGE__;
@@ -7,7 +7,7 @@ RDF::Trine::Parser::Turtle::Constants - Constant definitions for use in parsing
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::Turtle::Constants version 1.008
+This document describes RDF::Trine::Parser::Turtle::Constants version 1.010
 
 =head1 SYNOPSIS
 
@@ -28,7 +28,7 @@ use 5.010;
 our $VERSION;
 our @EXPORT;
 BEGIN {
-	$VERSION				= '1.008';
+	$VERSION				= '1.010';
 	@EXPORT = qw(
 		LBRACKET
 		RBRACKET
@@ -7,7 +7,7 @@ RDF::Trine::Parser::Turtle::Lexer - Tokenizer for parsing Turtle, TriG, and N-Tr
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::Turtle::Lexer version 1.008
+This document describes RDF::Trine::Parser::Turtle::Lexer version 1.010
 
 =head1 SYNOPSIS
 
@@ -35,7 +35,7 @@ use RDF::Trine::Error;
 
 our $VERSION;
 BEGIN {
-	$VERSION				= '1.008';
+	$VERSION				= '1.010';
 }
 
 my $r_nameChar_extra		= qr'[-0-9\x{B7}\x{0300}-\x{036F}\x{203F}-\x{2040}]'o;
@@ -43,3 +43,5 @@ __PACKAGE__->meta->make_immutable;
 1;
 
 =end private
+
+=cut
@@ -7,7 +7,7 @@ RDF::Trine::Parser::Turtle - Turtle RDF Parser
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser::Turtle version 1.008
+This document describes RDF::Trine::Parser::Turtle version 1.010
 
 =head1 SYNOPSIS
 
@@ -44,7 +44,7 @@ use RDF::Trine::Parser::Turtle::Token;
 
 our $VERSION;
 BEGIN {
-	$VERSION				= '1.008';
+	$VERSION				= '1.010';
 	foreach my $ext (qw(ttl)) {
 		$RDF::Trine::Parser::file_extensions{ $ext }	= __PACKAGE__;
 	}
@@ -7,7 +7,7 @@ RDF::Trine::Parser - RDF Parser class
 
 =head1 VERSION
 
-This document describes RDF::Trine::Parser version 1.008
+This document describes RDF::Trine::Parser version 1.010
 
 =head1 SYNOPSIS
 
@@ -53,7 +53,7 @@ our %format_uris;
 our %encodings;
 
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	can_load( modules => {
 		'Data::UUID'	=> undef,
 		'UUID::Tiny'	=> undef,
@@ -7,7 +7,7 @@ RDF::Trine::Pattern - Class for basic graph patterns
 
 =head1 VERSION
 
-This document describes RDF::Trine::Pattern version 1.008
+This document describes RDF::Trine::Pattern version 1.010
 
 =cut
 
@@ -20,14 +20,16 @@ no warnings 'redefine';
 use Data::Dumper;
 use Log::Log4perl;
 use Scalar::Util qw(blessed refaddr);
+use List::Util qw(any);
 use Carp qw(carp croak confess);
 use RDF::Trine::Iterator qw(smap);
+use RDF::Trine qw(iri);
 
 ######################################################################
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -167,73 +169,272 @@ sub subsumes {
 	return 0;
 }
 
+=item C<< merge_patterns ( @patterns ) >>
+
+Given an array of patterns, this will merge them into one.
+
+=cut
+
+sub merge_patterns {
+	my ($class, @patterns) = @_;
+	my @all_triples;
+	foreach my $pattern (@patterns) {
+		unless (blessed($pattern) and $pattern->isa('RDF::Trine::Pattern')) {
+			throw RDF::Trine::Error -text => "Patterns to be merged must be patterns themselves";
+		}
+		push(@all_triples, $pattern->triples);
+	}
+	return $class->new(@all_triples);
+}
+
 =item C<< sort_for_join_variables >>
 
-Returns a new pattern object with the subpatterns of the referrant sorted so
-that they may be joined in order while avoiding cartesian products (if possible).
+Returns a new pattern object with the subpatterns of the referrant
+sorted based on heuristics that ensure firstly that patterns can be
+joined on the same variable and secondly on the usual selectivity
+(i.e. how quickly the engine can drill down to the answer) of triple
+patterns. Calls C<< subgroup >>, C<< sort_triples >> and C<<
+merge_patterns >> in that order.
 
 =cut
 
 sub sort_for_join_variables {
 	my $self	= shift;
 	my $class	= ref($self);
-	my @triples	= $self->triples;
-	my %triples_by_tid;
-	foreach my $t (@triples) {
-		$triples_by_tid{ refaddr($t) }	= $t;
+	my $l		= Log::Log4perl->get_logger("rdf.trine.pattern");
+	$l->debug('Reordering ' . scalar $self->triples . ' triples for heuristical optimizations');
+	my @sorted_triple_patterns = $self->subgroup;
+
+	my @patterns;
+	foreach my $pattern (@sorted_triple_patterns) {
+		my $sorted = $pattern->sort_triples;
+		push(@patterns, $sorted);
 	}
-	
-	my %triples_with_variable;
+	return $class->merge_patterns(@patterns);
+}
+
+
+=item C<< subgroup >>
+
+Splits the pattern object up in an array of pattern objects where the
+same triple patterns occur. It will group on common variables, so that
+triple patterns can be joined together is in a group together. It will
+also group triples that have no connection to other triples in a
+group. It will then order the groups, first by number triples with
+common variables, then by number of literals, then by the total number
+of terms that are not variables.
+
+
+=cut
+
+sub subgroup {
+	my $self = shift;
+	my @triples = $self->triples;
+	my $l		= Log::Log4perl->get_logger("rdf.trine.pattern");
+	my %structure_counts;
+	my %triples_by_tid;
+	# First, we loop the dataset to compile some numbers for the
+	# variables in each triple pattern.  This is to break the pattern
+	# into subpatterns that can be joined on the same variable
 	foreach my $t (@triples) {
-		my $tid	= refaddr($t);
+		my $tid = refaddr($t);
+		$triples_by_tid{$tid}  = $t;
+		my $not_variable = 0;
 		foreach my $n ($t->nodes) {
 			if ($n->isa('RDF::Trine::Node::Variable')) {
-				my $var	= $n->name;
-				$triples_with_variable{ $var }{ $tid }++;
+				my $name = $n->name;
+				$structure_counts{ $name }{ 'name' } = $name; # TODO: Worth doing in an array?
+				push(@{$structure_counts{$name}{'claimed_patterns'}}, $tid);
+				$structure_counts{ $name }{ 'common_variable_count' }++;
+				$structure_counts{ $name }{ 'not_variable_count' } = 0 unless ($structure_counts{ $name }{ 'not_variable_count' });
+				$structure_counts{ $name }{ 'literal_count' } = 0 unless ($structure_counts{ $name }{ 'literal_count' });
+				foreach my $char (split(//, $n->as_string)) { # TODO: Use a more standard format
+					$structure_counts{ $name }{ 'string_sum' } += ord($char);
+				}
+				foreach my $o ($t->nodes) {
+					unless ($o->isa('RDF::Trine::Node::Variable')) {
+						$structure_counts{ $name }{ 'not_variable_count' }++;
+					}
+					elsif ($o->isa('RDF::Trine::Node::Literal')) {
+						$structure_counts{ $name }{ 'literal_count' }++;
+					}
+				}
+			} else {
+				$not_variable++;
 			}
 		}
+		if ($not_variable == 3) { # Then, there are no variables in the pattern
+			my $name = '_no_definite';
+			$structure_counts{ $name }{ 'not_variable_count' } = $not_variable;
+			$structure_counts{ $name }{ 'common_variable_count' } = 0;
+			$structure_counts{ $name }{ 'literal_count' } = 0; # Doesn't mean anything now
+			$structure_counts{ $name }{ 'string_sum' } = 0; # Doesn't mean anything now
+			push(@{$structure_counts{$name}{'claimed_patterns'}}, $tid);
+		}
+
 	}
-	foreach my $var (keys %triples_with_variable) {
-		my @tids	= sort { $a <=> $b } keys %{ $triples_with_variable{ $var } };
-		$triples_with_variable{ $var }	= \@tids;
+
+	# Group triple subpatterns with just one triple pattern
+	my $just_ones;
+	while (my ($name, $data) = each(%structure_counts)) {
+		if($data->{'common_variable_count'} <= 1) {
+			$just_ones->{'common_variable_count'} = 1;
+			$just_ones->{'string_sum'} = 1;
+			$just_ones->{'literal_count'} += $data->{'literal_count'};
+			$just_ones->{'not_variable_count'} += $data->{'not_variable_count'};
+			my @claimed = @{$data->{'claimed_patterns'}};
+			unless (any { $_ == $claimed[0] } @{$just_ones->{'claimed_patterns'}}) {
+				push(@{$just_ones->{'claimed_patterns'}}, $claimed[0]);
+			}
+			delete $structure_counts{$name};
+		}
 	}
-	
-	my %variables_in_triple;
-	foreach my $var (keys %triples_with_variable) {
-		foreach my $tid (@{ $triples_with_variable{ $var } }) {
-			$variables_in_triple{ $tid }{ $var }++;
+
+	$l->trace('Results of structural analysis: ' . Dumper(\%structure_counts));
+	$l->trace('Block of single-triple patterns: ' . Dumper($just_ones));
+
+	# Now, sort the patterns in the order specified by first the number
+	# of occurances of common variables, then the number of literals
+	# and then the number of terms that are not variables
+	my @sorted_patterns = sort {     $b->{'common_variable_count'} <=> $a->{'common_variable_count'} 
+											or $b->{'literal_count'}         <=> $a->{'literal_count'}
+											or $b->{'not_variable_count'}    <=> $a->{'not_variable_count'}
+											or $b->{'string_sum'}            <=> $a->{'string_sum'} 
+										} values(%structure_counts);
+
+	push (@sorted_patterns, $just_ones);
+
+	my @sorted_triple_patterns;
+
+	# Now, loop through the sorted patterns, let the one with most
+	# weight first select the triples it wants to join.  Within those
+	# subpatterns, apply the sort order of triple pattern heuristic
+	foreach my $item (@sorted_patterns) {
+		my @triple_patterns;
+		my $triples_left = scalar keys(%triples_by_tid);
+		if ($triples_left > 2) {
+			foreach my $tid (@{$item->{'claimed_patterns'}}) {
+				if (defined($triples_by_tid{$tid})) {
+					push(@triple_patterns, $triples_by_tid{$tid});
+					delete $triples_by_tid{$tid};
+				}
+			}
+			$l->debug("There are $triples_left triples left");
+			push(@sorted_triple_patterns, RDF::Trine::Pattern->new(@triple_patterns)); # TODO: Better way to call ourselves?
+		} else {
+			$l->debug("There is a rest of $triples_left triples");
+			push(@sorted_triple_patterns, RDF::Trine::Pattern->new(values(%triples_by_tid)));
+			last;
 		}
 	}
-	foreach my $tid (keys %variables_in_triple) {
-		my @vars	= sort keys %{ $variables_in_triple{ $tid } };
-		$variables_in_triple{ $tid }	= \@vars;
+
+	return @sorted_triple_patterns;
+}
+
+=item C<< sort_triples >>
+
+Will sort the triple patterns based on heuristics that looks at how
+many variables the patterns have, and where they occur, see REFERENCES
+for details. Returns a new sorted pattern object.
+
+=cut
+
+sub sort_triples {
+	my $self = shift;
+	return $self->_hsp_heuristic_1_4_triple_pattern_order;
+}
+
+sub _hsp_heuristic_1_4_triple_pattern_order { # Heuristic 1 and 4 of HSP
+	my $self	= shift;
+	my $class	= ref($self);
+	my @triples	= @$self;
+	return $self if (scalar @triples == 1);
+	my %triples_by_tid;
+	foreach my $t (@triples) {
+		my $tid = refaddr($t);
+		$triples_by_tid{$tid}{'tid'} = $tid; # TODO: Worth doing this in an array?
+		$triples_by_tid{$tid}{'triple'} = $t;
+		$triples_by_tid{$tid}{'sum'} = _hsp_heuristic_triple_sum($t);
 	}
-	
-	my %used_vars;
-	my %used_tids;
-	my @sorted;
-	my $first	= shift(@triples);	# start with the first triple in syntactic order
-	push(@sorted, $first);
-	$used_tids{ refaddr($first) }++;
-	foreach my $var (@{ $variables_in_triple{ refaddr($first) } }) {
-		$used_vars{ $var }++;
+	my @sorted_tids = sort { $a->{'sum'} <=> $b->{'sum'} } values(%triples_by_tid);
+	my @sorted_triples;
+	foreach my $entry (@sorted_tids) {
+		push(@sorted_triples, $triples_by_tid{$entry->{'tid'}}->{'triple'});
 	}
-	while (@triples) {
-		my @candidate_tids	= grep { not($used_tids{$_}) } map { @{ $triples_with_variable{ $_ } } } (keys %used_vars);
-		last unless scalar(@candidate_tids);
-		my $next_id	= shift(@candidate_tids);
-		my $next	= $triples_by_tid{ $next_id };
-		push(@sorted, $next);
-		$used_tids{ refaddr($next) }++;
-		foreach my $var (@{ $variables_in_triple{ refaddr($next) } }) {
-			$used_vars{ $var }++;
+	return $class->new(@sorted_triples);
+}
+
+# The below function finds a number to aid sorting
+# It takes into account Heuristic 1 and 4 of the HSP paper, see REFERENCES
+# as well as that it was noted in the text that rdf:type is usually less selective.
+
+# By assigning the integers to nodes, depending on whether they are in
+# triple (subject, predicate, object), variables, rdf:type and
+# literals, and sum them, they may be sorted. See code for the actual
+# values used.
+
+# Denoting s for bound subject, p for bound predicate, a for rdf:type
+# as predicate, o for bound object and l for literal object and ? for
+# variable, we get the following order, most of which are identical to
+# the HSP:
+
+# spl: 6
+# spo: 8
+# sao: 10
+# s?l: 14
+# s?p: 16
+# ?pl: 25
+# ?po: 27
+# sp?: 30
+# sa?: 32
+# ??l: 33
+# ??o: 35
+# s??: 38
+# ?p?: 49
+# ?a?: 51
+# ???: 57
+
+# Note that this number is not intended as an estimate of selectivity,
+# merely a sorting key, but further research may possibly create such
+# numbers.
+
+sub _hsp_heuristic_triple_sum {
+	my $t = shift;
+	my $sum = 0;
+	if ($t->subject->is_variable) {
+		$sum = 20;
+	} else {
+		$sum = 1;
+	}
+	if ($t->predicate->is_variable) {
+		$sum += 10;
+	} else {
+		if ($t->predicate->equal(iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'))) {
+			$sum += 4;
+		} else {
+			$sum += 2;
 		}
-		@triples	= grep { refaddr($_) != $next_id } @triples;
 	}
-	push(@sorted, @triples);
-	return $class->new(@sorted);
+	if ($t->object->is_variable) {
+		$sum += 27;
+	} elsif ($t->object->is_literal) {
+		$sum += 3;
+	} else {
+		$sum += 5;
+	}
+	my $l		= Log::Log4perl->get_logger("rdf.trine.pattern");
+	# Now a trick to get an deterministic sort order, hard to test without.
+	$sum *= 10000000;
+	foreach my $c (split(//,$t->as_string)) {
+		$sum += ord($c);
+	}
+	$l->debug($t->as_string . " triple has sorting sum " . $sum);
+	return $sum;
 }
 
+
+	
+
 1;
 
 __END__
@@ -245,10 +446,18 @@ __END__
 Please report any bugs or feature requests to through the GitHub web interface
 at L<https://github.com/kasei/perlrdf/issues>.
 
+=head1 REFERENCES
+
+The heuristics to order triple patterns in this module is strongly
+influenced by L<The ICS-FORTH Heuristics-based SPARQL Planner
+(HSP)|http://www.ics.forth.gr/isl/index_main.php?l=e&c=645>.
+
 =head1 AUTHOR
 
 Gregory Todd Williams  C<< <gwilliams@cpan.org> >>
 
+Kjetil Kjernsmo C<< <kjetilk@cpan.org> >>
+
 =head1 COPYRIGHT
 
 Copyright (c) 2006-2012 Gregory Todd Williams. This
@@ -7,7 +7,7 @@ RDF::Trine::Serializer::NQuads - N-Quads Serializer
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer::NQuads version 1.008
+This document describes RDF::Trine::Serializer::NQuads version 1.010
 
 =head1 SYNOPSIS
 
@@ -47,7 +47,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'nquads' }	= __PACKAGE__;
 	$RDF::Trine::Serializer::format_uris{ 'http://sw.deri.org/2008/07/n-quads/#n-quads' }	= __PACKAGE__;
 	foreach my $type (qw(text/x-nquads)) {
@@ -4,7 +4,7 @@ RDF::Trine::Serializer::NTriples::Canonical - Canonical representation of an RDF
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer::NTriples::Canonical version 1.008
+This document describes RDF::Trine::Serializer::NTriples::Canonical version 1.010
 
 =head1 SYNOPSIS
 
@@ -64,7 +64,7 @@ use base qw(RDF::Trine::Serializer::NTriples);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'ntriples-canonical' }	= __PACKAGE__;
 # 	foreach my $type (qw(text/plain)) {
 # 		$RDF::Trine::Serializer::media_types{ $type }	= __PACKAGE__;
@@ -7,7 +7,7 @@ RDF::Trine::Serializer::NTriples - N-Triples Serializer
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer::NTriples version 1.008
+This document describes RDF::Trine::Serializer::NTriples version 1.010
 
 =head1 SYNOPSIS
 
@@ -47,7 +47,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'ntriples' }	= __PACKAGE__;
 	$RDF::Trine::Serializer::format_uris{ 'http://www.w3.org/ns/formats/N-Triples' }	= __PACKAGE__;
 	foreach my $type (qw(text/plain)) {
@@ -7,7 +7,7 @@ RDF::Trine::Serializer::RDFJSON - RDF/JSON Serializer
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer::RDF/JSON version 1.008
+This document describes RDF::Trine::Serializer::RDF/JSON version 1.010
 
 =head1 SYNOPSIS
 
@@ -48,7 +48,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'rdfjson' }	= __PACKAGE__;
 	foreach my $type (qw(application/json application/x-rdf+json)) {
 		$RDF::Trine::Serializer::media_types{ $type }	= __PACKAGE__;
@@ -7,7 +7,7 @@ RDF::Trine::Serializer::RDFPatch - RDF-Patch Serializer
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer::RDFPatch version 1.008
+This document describes RDF::Trine::Serializer::RDFPatch version 1.010
 
 =head1 SYNOPSIS
 
@@ -49,7 +49,7 @@ use RDF::Trine::Exporter::RDFPatch;
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'rdfpatch' }	= __PACKAGE__;
 # 	$RDF::Trine::Serializer::format_uris{ 'http://www.w3.org/ns/formats/RDF-Patch' }	= __PACKAGE__;
 	foreach my $type (qw(application/rdf-patch)) {
@@ -7,7 +7,7 @@ RDF::Trine::Serializer::RDFXML - RDF/XML Serializer
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer::RDFXML version 1.008
+This document describes RDF::Trine::Serializer::RDFXML version 1.010
 
 =head1 SYNOPSIS
 
@@ -48,7 +48,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'rdfxml' }	= __PACKAGE__;
 	$RDF::Trine::Serializer::format_uris{ 'http://www.w3.org/ns/formats/RDF_XML' }	= __PACKAGE__;
 	foreach my $type (qw(application/rdf+xml)) {
@@ -7,7 +7,7 @@ RDF::Trine::Serializer::TSV - TSV Serializer
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store version 1.008
+This document describes RDF::Trine::Store version 1.010
 
 =head1 SYNOPSIS
 
@@ -47,7 +47,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'tsv' }	= __PACKAGE__;
 	$RDF::Trine::Serializer::format_uris{ 'http://www.w3.org/ns/formats/TSV' }	= __PACKAGE__;
 	foreach my $type (qw(text/tsv)) {
@@ -7,7 +7,7 @@ RDF::Trine::Serializer::TriG - TriG Serializer
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer::TriG version 1.008
+This document describes RDF::Trine::Serializer::TriG version 1.010
 
 =head1 SYNOPSIS
 
@@ -48,7 +48,7 @@ use RDF::Trine::Error qw(:try);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'trig' }	= __PACKAGE__;
 # 	$RDF::Trine::Serializer::format_uris{ 'http://sw.deri.org/2008/07/n-quads/#n-quads' }	= __PACKAGE__;
 # 	foreach my $type (qw(text/x-nquads)) {
@@ -7,7 +7,7 @@ RDF::Trine::Serializer::Turtle - Turtle Serializer
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer::Turtle version 1.008
+This document describes RDF::Trine::Serializer::Turtle version 1.010
 
 =head1 SYNOPSIS
 
@@ -53,7 +53,7 @@ use RDF::Trine::Namespace qw(rdf);
 our ($VERSION, $debug);
 BEGIN {
 	$debug		= 0;
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	$RDF::Trine::Serializer::serializer_names{ 'turtle' }	= __PACKAGE__;
 	$RDF::Trine::Serializer::format_uris{ 'http://www.w3.org/ns/formats/Turtle' }	= __PACKAGE__;
 	foreach my $type (qw(application/x-turtle application/turtle text/turtle text/rdf+n3)) {
@@ -7,7 +7,7 @@ RDF::Trine::Serializer - RDF Serializer class
 
 =head1 VERSION
 
-This document describes RDF::Trine::Serializer version 1.008
+This document describes RDF::Trine::Serializer version 1.010
 
 =head1 SYNOPSIS
 
@@ -34,7 +34,7 @@ our %serializer_names;
 our %format_uris;
 our %media_types;
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 use RDF::Trine::Serializer::NQuads;
@@ -96,7 +96,7 @@ RDF::Trine::Serializer object as decided by L<HTTP::Negotiate>.  If
 the C<< 'request_headers' >> key-value is supplied, the C<<
 $request_headers >> is passed to C<< HTTP::Negotiate::choose >>.  The
 option C<< 'restrict' >>, set to a list of serializer names, can be
-used to limit the serializers to choose from. Finally, an C<<'extends' >> 
+used to limit the serializers to choose from. Finally, an C<<'extend' >> 
 option can be set to a hashref that contains MIME-types
 as keys and a custom variant as value. This will enable the user to
 use this negotiator to return a type that isn't supported by any
@@ -361,6 +361,8 @@ sub string {
 
 =end private
 
+=cut
+
 1;
 
 __END__
@@ -7,7 +7,7 @@ RDF::Trine::Statement::Quad - Class for quads and quad patterns
 
 =head1 VERSION
 
-This document describes RDF::Trine::Statement::Quad version 1.008
+This document describes RDF::Trine::Statement::Quad version 1.010
 
 =cut
 
@@ -25,7 +25,7 @@ use Carp qw(croak);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine::Statement - Class for triples and triple patterns
 
 =head1 VERSION
 
-This document describes RDF::Trine::Statement version 1.008
+This document describes RDF::Trine::Statement version 1.010
 
 =cut
 
@@ -29,7 +29,7 @@ use Encode;
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -4,7 +4,7 @@ RDF::Trine::Store::DBI::Pg - PostgreSQL subclass of DBI store
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::DBI::Pg version 1.008
+This document describes RDF::Trine::Store::DBI::Pg version 1.010
 
 =head1 SYNOPSIS
 
@@ -25,7 +25,7 @@ use Scalar::Util qw(blessed reftype refaddr);
 
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 }
@@ -4,7 +4,7 @@ RDF::Trine::Store::DBI::SQLite - SQLite subclass of DBI store
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::DBI::SQLite version 1.008
+This document describes RDF::Trine::Store::DBI::SQLite version 1.010
 
 =head1 SYNOPSIS
 
@@ -34,7 +34,7 @@ use Scalar::Util qw(blessed reftype refaddr);
 
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 }
@@ -4,7 +4,7 @@ RDF::Trine::Store::DBI::mysql - Mysql subclass of DBI store
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::DBI::mysql version 1.008
+This document describes RDF::Trine::Store::DBI::mysql version 1.010
 
 =head1 SYNOPSIS
 
@@ -25,7 +25,7 @@ use Scalar::Util qw(blessed reftype refaddr);
 
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 }
@@ -4,7 +4,7 @@ RDF::Trine::Store::DBI - Persistent RDF storage based on DBI
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::DBI version 1.008
+This document describes RDF::Trine::Store::DBI version 1.010
 
 =head1 SYNOPSIS
 
@@ -65,7 +65,7 @@ use RDF::Trine::Store::DBI::Pg;
 
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 }
@@ -4,7 +4,7 @@ RDF::Trine::Store::Dydra - RDF Store proxy for a Dydra endpoint
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::Dydra version 1.008
+This document describes RDF::Trine::Store::Dydra version 1.010
 
 =head1 SYNOPSIS
 
@@ -38,7 +38,7 @@ use RDF::Trine::Error qw(:try);
 my @pos_names;
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 	@pos_names	= qw(subject predicate object context);
@@ -4,7 +4,7 @@ RDF::Trine::Store::Hexastore - RDF store implemented with the hexastore index
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::Hexastore version 1.008
+This document describes RDF::Trine::Store::Hexastore version 1.010
 
 =head1 SYNOPSIS
 
@@ -32,6 +32,7 @@ use Scalar::Util qw(refaddr reftype blessed);
 use Storable qw(nstore retrieve);
 use Carp qw(croak);
 use Time::HiRes qw ( time );
+use Log::Log4perl;
 
 use constant NODES		=> qw(subject predicate object);
 use constant NODEMAP	=> { subject => 0, predicate => 1, object => 2, context => 3 };
@@ -45,7 +46,7 @@ use constant OTHERNODES	=> {
 
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 }
@@ -98,25 +99,25 @@ The base URI to be used for a parsed file.
 
 The following example initializes a Hexastore store based on a local file and a remote URL:
 
-  my $store = RDF::Trine::Store->new_with_config(
-                {storetype => 'Hexastore',
-		 sources => [
-			      {
-			       file => 'test-23.ttl',
-			       syntax => 'turtle',
-			      },
-			      {
-			       url => 'http://www.kjetil.kjernsmo.net/foaf',
-			       syntax => 'rdfxml',
-		      	      }
-	        ]});
+  my $store = RDF::Trine::Store->new_with_config( {
+      storetype => 'Hexastore',
+      sources => [
+          {
+              file => 'test-23.ttl',
+              syntax => 'turtle',
+          },
+          {
+              url => 'http://www.kjetil.kjernsmo.net/foaf',
+              syntax => 'rdfxml',
+          }
+  ]});
 
 
 =cut
 
 sub new {
 	my $class	= shift;
-	my $self        = bless({}, $class);
+	my $self	= bless({}, $class);
 	$self->nuke; # nuke resets the store, thus doing the same thing as init should do
 	return $self;
 }
@@ -463,7 +464,8 @@ sub get_pattern {
 			}
 			return RDF::Trine::Iterator::Bindings->new( \@results, [ $bgp->referenced_variables ] );
 		} else {
-# 			warn 'no shared variable -- cartesian product';
+			my $l		= Log::Log4perl->get_logger("rdf.trine.store.hexastore");
+			$l->info('No shared variable -- cartesian product');
 			# no shared variable -- cartesian product
 			my $i1	= $self->SUPER::_get_pattern( RDF::Trine::Pattern->new( $t1 ) );
 			my $i2	= $self->SUPER::_get_pattern( RDF::Trine::Pattern->new( $t2 ) );
@@ -538,14 +540,19 @@ sub add_statement {
 	my $self	= shift;
 	my $st		= shift;
 	my $added	= 0;
+
+	# believe it or not, these calls add up.
+	my %stmt = map { $_ => $st->$_ } NODES;
+	my %ids  = map { $_ => $self->_node2id($stmt{$_}) } NODES;
+
 	foreach my $first (NODES) {
-		my $firstnode	= $st->$first();
-		my $id1			= $self->_node2id( $firstnode );
+		my $firstnode	= $stmt{$first};
+		my $id1			= $ids{$first};
 		my @others		= @{ OTHERNODES->{ $first } };
 		my @orders		= ([@others], [reverse @others]);
 		foreach my $order (@orders) {
 			my ($second, $third)	= @$order;
-			my ($id2, $id3)	= map { $self->_node2id( $st->$_() ) } ($second, $third);
+			my ($id2, $id3) = @ids{$second, $third};
 			my $list	= $self->_get_terminal_list( $first => $id1, $second => $id2 );
 			if ($self->_add_node_to_page( $list, $id3 )) {
 				$added++;
@@ -569,7 +576,7 @@ sub remove_statement {
 	my $st		= shift;
 	my @ids		= map { $self->_node2id( $st->$_() ) } NODES;
 # 	warn "*** removing statement @ids\n";
-	
+
 	my $removed	= 0;
 	foreach my $first (NODES) {
 		my $firstnode	= $st->$first();
@@ -587,7 +594,7 @@ sub remove_statement {
 # 			warn "\t- remaining: [" . join(', ', @$list) . "]\n";
 		}
 	}
-	
+
 	if ($removed) {
 		$self->{ size }--;
 		$self->{etag} = time;
@@ -691,10 +698,16 @@ sub _node2id {
 	my $node	= shift;
 	return unless (blessed($node));
 	return if ($node->isa('RDF::Trine::Node::Variable'));
-	if (exists( $self->{ node2id }{ $node->as_string } )) {
-		return $self->{ node2id }{ $node->as_string };
+
+	# this gets called so much it actually significantly impacts run
+	# time. call it once per invocation of _node2id instead of twice.
+	my $str = $node->as_string;
+	my $id = $self->{ node2id }{ $str };
+
+	if (defined $id) {
+		return $id;
 	} else {
-		my $id	= ($self->{ node2id }{ $node->as_string } = $self->{ next_id }++);
+		$id	= ($self->{ node2id }{ $str } = $self->{ next_id }++);
 		$self->{ id2node }{ $id }	= $node;
 		return $id
 	}
@@ -4,7 +4,7 @@ RDF::Trine::Store::Memory - Simple in-memory RDF store
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::Memory version 1.008
+This document describes RDF::Trine::Store::Memory version 1.010
 
 =head1 SYNOPSIS
 
@@ -39,7 +39,7 @@ use RDF::Trine::Error;
 my @pos_names;
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 	@pos_names	= qw(subject predicate object context);
@@ -616,7 +616,7 @@ change. This token is acceptable for use as an HTTP ETag.
 
 sub etag {
 	my $self	= shift;
-	return $self->{hash}->hexdigest;
+	return $self->{hash}->b64digest;
 }
 
 =item C<< size >>
@@ -4,7 +4,7 @@ RDF::Trine::Store::Redis - RDF Store for Redis
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::Redis version 1.008
+This document describes RDF::Trine::Store::Redis version 1.010
 
 =head1 SYNOPSIS
 
@@ -44,7 +44,7 @@ our $CACHING	= 1;
 my @pos_names;
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 	@pos_names	= qw(subject predicate object context);
@@ -4,7 +4,7 @@ RDF::Trine::Store::Redland - Redland-backed RDF store for RDF::Trine
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::Redland version 1.008
+This document describes RDF::Trine::Store::Redland version 1.010
 
 =head1 SYNOPSIS
 
@@ -37,10 +37,26 @@ use RDF::Trine::Error;
 our $NIL_TAG;
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 	$NIL_TAG	= 'tag:gwilliams@cpan.org,2010-01-01:RT:NIL';
+
+	# XXX THE FOLLOWING IS TO KEEP DATA::DUMPER FROM CRAPPING OUT
+
+	# insert these guys until we can get a fix into redland
+	my $fk = sub { 'DUMMY' };
+	my $nk = sub { undef };
+	my $f  = sub { 'REDLAND PLEASE FIX YOUR API' };
+
+	*_p_librdf_storage_s::FIRSTKEY = $fk;
+	*_p_librdf_storage_s::NEXTKEY  = $nk;
+	*_p_librdf_storage_s::FETCH	= $f;
+	*_p_librdf_model_s::FIRSTKEY   = $fk;
+	*_p_librdf_model_s::NEXTKEY	= $nk;
+	*_p_librdf_model_s::FETCH	  = $f;
+
+	# too bad these aren't implemented, since they could be useful
 }
 
 ######################################################################
@@ -95,6 +111,7 @@ sub new {
 	my $model	= shift;
 	my $self	= bless({
 		model	=> $model,
+		bulk	=> 0,
 	}, $class);
 	return $self;
 }
@@ -110,13 +127,15 @@ sub _new_with_string {
 
 sub _new_with_config {
 	my $class	= shift;
-	my $config	= shift;
-	my $store	= RDF::Redland::Storage->new(
-						     $config->{store_name},
-						     $config->{name},
-						     $config->{options}
-						    );
-	my $model	= RDF::Redland::Model->new( $store, '' );
+	my $config	= shift || { store_name => 'memory' };
+
+	my $store	= RDF::Redland::Storage->new
+		(@{$config}{qw(store_name name options)})
+			or throw RDF::Trine::Error::DatabaseError
+				-text => "Couldn't initialize Redland storage";
+	my $model	= RDF::Redland::Model->new( $store, '' )
+		or throw RDF::Trine::Error::DatabaseError
+			-text => "Couldn't initialize Redland model";
 	return $class->new( $model );
 }
 
@@ -263,7 +282,7 @@ sub add_statement {
 	my $self	= shift;
 	my $st		= shift;
 	my $context	= shift;
-	
+
 	my $nil	= RDF::Trine::Node::Nil->new();
 	if ($st->isa( 'RDF::Trine::Statement::Quad' )) {
 		if (blessed($context)) {
@@ -277,12 +296,18 @@ sub add_statement {
 			$st	= RDF::Trine::Statement::Quad->new( @nodes[0..2], $nil );
 		}
 	}
-	
+
 	my $model	= $self->_model;
 	my @nodes	= $st->nodes;
 	my @rnodes	= map { _cast_to_redland($_) } @nodes;
 	my $rst		= RDF::Redland::Statement->new( @rnodes[0..2] );
-	$model->add_statement( $rst, $rnodes[3] );
+	my $ret	 = $model->add_statement( $rst, $rnodes[3] );
+
+	# redland needs to be synced
+	$model->sync unless $self->{bulk};
+
+	# for any code that was expecting this
+	$ret;
 }
 
 =item C<< remove_statement ( $statement [, $context]) >>
@@ -312,7 +337,14 @@ sub remove_statement {
 
 	my @nodes	= $st->nodes;
 	my @rnodes	= map { _cast_to_redland($_) } @nodes;
-	$self->_model->remove_statement( @rnodes );
+	my $model   = $self->_model;
+	my $ret	 = $model->remove_statement( @rnodes );
+
+	# redland needs to be synced
+	$model->sync unless $self->{bulk};
+
+	# for any code that was expecting this
+	$ret;
 }
 
 =item C<< remove_statements ( $subject, $predicate, $object [, $context]) >>
@@ -323,14 +355,24 @@ Removes the specified C<$statement> from the underlying model.
 
 sub remove_statements {
 	my $self	= shift;
-	my $subj	= shift;
-	my $pred	= shift;
-	my $obj		= shift;
-	my $context	= shift;
-	my $iter	= $self->get_statements( $subj, $pred, $obj, $context );
+	my $iter	= $self->get_statements(@_);
+
+	# temporarily store the value for bulk so we don't sync over and over
+	my $bulk	= $self->{bulk};
+	$self->{bulk} = 1;
+
+	my $count = 0;
 	while (my $st = $iter->next) {
 		$self->remove_statement( $st );
+		$count++;
 	}
+
+	# now put it back
+	$self->{bulk} = $bulk;
+	$self->_model->sync unless $bulk;
+
+	# might as well return how many statements got deleted
+	$count;
 }
 
 =item C<< count_statements ( $subject, $predicate, $object, $context ) >>
@@ -345,9 +387,13 @@ sub count_statements {
 	my $self	= shift;
 	my @nodes	= @_;
 	if (scalar(@nodes) < 4) {
+		# if it isn't 4, then make damn sure it's 3
+		push @nodes, (undef) x (3 - @nodes);
+
 # 		warn "restricting count_statements to triple semantics";
 		my @rnodes	= map { _cast_to_redland($_) } @nodes[0..2];
-		my $st		= RDF::Redland::Statement->new( @rnodes );
+		# force a 3-element list or you'll be sorry
+		my $st		= RDF::Redland::Statement->new( @rnodes[0..2] );
 		my $iter	= $self->_model->find_statements( $st );
 		my $count	= 0;
 		my %seen;
@@ -395,6 +441,16 @@ sub supports {
 	return;
 }
 
+sub _begin_bulk_ops {
+	shift->{bulk} = 1;
+}
+
+sub _end_bulk_ops {
+	my $self = shift;
+	$self->{bulk} = 0;
+	$self->_model->sync;
+}
+
 sub _model {
 	my $self	= shift;
 	return $self->{model};
@@ -447,6 +503,7 @@ sub _cast_to_local {
 	}
 }
 
+
 1;
 
 __END__
@@ -4,7 +4,7 @@ RDF::Trine::Store::SPARQL - RDF Store proxy for a SPARQL endpoint
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store::SPARQL version 1.008
+This document describes RDF::Trine::Store::SPARQL version 1.010
 
 =head1 SYNOPSIS
 
@@ -37,7 +37,7 @@ use RDF::Trine::Error qw(:try);
 my @pos_names;
 our $VERSION;
 BEGIN {
-	$VERSION	= "1.008";
+	$VERSION	= "1.010";
 	my $class	= __PACKAGE__;
 	$RDF::Trine::Store::STORE_CLASSES{ $class }	= $VERSION;
 	@pos_names	= qw(subject predicate object context);
@@ -523,7 +523,7 @@ sub get_sparql {
 	my $url		= $self->{url} . $urlchar . 'query=' . uri_escape($sparql);
 	my $response	= $ua->get( $url );
 	if ($response->is_success) {
-		$p->parse_string( $response->content );
+		$p->parse_string( $response->decoded_content );
 		return $handler->iterator;
 	} else {
 		my $status		= $response->status_line;
@@ -7,7 +7,7 @@ RDF::Trine::Store - RDF triplestore base class
 
 =head1 VERSION
 
-This document describes RDF::Trine::Store version 1.008
+This document describes RDF::Trine::Store version 1.010
 
 =head1 DESCRIPTION
 
@@ -83,7 +83,7 @@ use RDF::Trine::Store::SPARQL;
 
 our ($VERSION, $HAVE_REDLAND, %STORE_CLASSES);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	if ($RDF::Redland::VERSION) {
 		$HAVE_REDLAND	= 1;
 	}
@@ -7,7 +7,7 @@ RDF::Trine::VariableBindings - Variable bindings
 
 =head1 VERSION
 
-This document describes RDF::Trine::VariableBindings version 1.008
+This document describes RDF::Trine::VariableBindings version 1.010
 
 =head1 SYNOPSIS
 
@@ -53,7 +53,7 @@ use Scalar::Util qw(blessed refaddr);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 ######################################################################
@@ -7,7 +7,7 @@ RDF::Trine - An RDF Framework for Perl
 
 =head1 VERSION
 
-This document describes RDF::Trine version 1.008
+This document describes RDF::Trine version 1.010
 
 =head1 SYNOPSIS
 
@@ -89,7 +89,7 @@ use LWP::UserAgent;
 our ($debug, @ISA, $VERSION, @EXPORT_OK);
 BEGIN {
 	$debug		= 0;
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 	
 	require Exporter;
 	@ISA		= qw(Exporter);
@@ -4,7 +4,7 @@ Test::RDF::Trine::Store - A collection of functions to test RDF::Trine::Stores
 
 =head1 VERSION
 
-This document describes RDF::Trine version 1.008
+This document describes RDF::Trine version 1.010
 
 =head1 SYNOPSIS
 
@@ -58,7 +58,7 @@ use RDF::Trine::Namespace qw(xsd);
 
 our ($VERSION);
 BEGIN {
-	$VERSION	= '1.008';
+	$VERSION	= '1.010';
 }
 
 use Log::Log4perl;
@@ -1,4 +1,4 @@
-use Test::More tests => 10;
+use Test::More;
 use Test::JSON;
 
 use strict;
@@ -7,7 +7,7 @@ no warnings 'redefine';
 
 use URI::file;
 
-use RDF::Trine;
+use RDF::Trine qw(statement iri literal variable);
 use RDF::Trine::Node;
 use_ok( 'RDF::Trine::Iterator::Bindings' );
 
@@ -52,3 +52,40 @@ use_ok( 'RDF::Trine::Iterator::Bindings' );
 	my $expect	= '{"head":{"vars":["a", "b", "c"]},"results":{"bindings":[],"distinct":false,"ordered":false}}';
 	is_json( $iter->as_json, $expect, 'as_json empty bindings iterator with names' );
 }
+
+{
+	my $t1		= statement(variable('subj'), iri('pred1'), literal('foo'));
+	my $t2		= statement(variable('subj'), iri('pred2'), variable('obj'));
+	my $pattern	= RDF::Trine::Pattern->new($t1, $t2);
+	my @bindings	= (
+		{ 'subj' => iri('http://example.org/x1') },
+		{ 'subj' => iri('http://example.org/x2'), 'obj' => literal('bar') },
+	);
+	my $iter	= RDF::Trine::Iterator::Bindings->new( sub { return shift(@bindings) } );
+	my $sts		= $iter->as_statements($pattern);
+	my @triples	= $sts->get_all;
+	is(scalar(@triples), 3, 'expected triple count from as_statements with pattern');
+	
+	ok(
+		$triples[0]->subsumes(
+			statement(iri('http://example.org/x1'), iri('pred1'), literal('foo'))
+		),
+		'expected triple 1/3'
+	);
+	
+	ok(
+		$triples[1]->subsumes(
+			statement(iri('http://example.org/x2'), iri('pred1'), literal('foo'))
+		),
+		'expected triple 2/3'
+	);
+	
+	ok(
+		$triples[2]->subsumes(
+			statement(iri('http://example.org/x2'), iri('pred2'), literal('bar'))
+		),
+		'expected triple 3/3'
+	);
+}
+
+done_testing();