[tracker] Import rasqal r14939 into repository



commit 0bd40670f86e1dd20890429f23d2a04eba6a5bc5
Author: Jürg Billeter <j bitron ch>
Date:   Thu Apr 9 10:42:24 2009 +0200

    Import rasqal r14939 into repository
---
 configure.ac                              |   29 +-
 po/POTFILES.skip                          |    2 +
 src/Makefile.am                           |    2 +
 src/rasqal/Makefile.am                    |   95 +
 src/rasqal/fix-bison                      |   65 +
 src/rasqal/fix-flex                       |   84 +
 src/rasqal/rasqal.h                       | 1368 ++++++++++++
 src/rasqal/rasqal_algebra.c               | 1403 +++++++++++++
 src/rasqal/rasqal_config.h                |    2 +
 src/rasqal/rasqal_datetime.c              |  802 ++++++++
 src/rasqal/rasqal_decimal.c               |  941 +++++++++
 src/rasqal/rasqal_engine.c                | 1783 ++++++++++++++++
 src/rasqal/rasqal_engine_algebra.c        |  398 ++++
 src/rasqal/rasqal_engine_sort.c           |  375 ++++
 src/rasqal/rasqal_expr.c                  | 2547 +++++++++++++++++++++++
 src/rasqal/rasqal_feature.c               |  224 ++
 src/rasqal/rasqal_general.c               | 1128 ++++++++++
 src/rasqal/rasqal_graph.c                 |  459 +++++
 src/rasqal/rasqal_graph_pattern.c         |  864 ++++++++
 src/rasqal/rasqal_internal.h              | 1200 +++++++++++
 src/rasqal/rasqal_literal.c               | 3198 +++++++++++++++++++++++++++++
 src/rasqal/rasqal_map.c                   |  319 +++
 src/rasqal/rasqal_query.c                 | 2382 +++++++++++++++++++++
 src/rasqal/rasqal_query_results.c         | 1425 +++++++++++++
 src/rasqal/rasqal_query_transform.c       | 1320 ++++++++++++
 src/rasqal/rasqal_raptor.c                |  816 ++++++++
 src/rasqal/rasqal_redland.c               |  474 +++++
 src/rasqal/rasqal_result_formats.c        |  676 ++++++
 src/rasqal/rasqal_row.c                   |  509 +++++
 src/rasqal/rasqal_rowsource.c             |  712 +++++++
 src/rasqal/rasqal_rowsource_empty.c       |  194 ++
 src/rasqal/rasqal_rowsource_filter.c      |  241 +++
 src/rasqal/rasqal_rowsource_join.c        |  677 ++++++
 src/rasqal/rasqal_rowsource_project.c     |  410 ++++
 src/rasqal/rasqal_rowsource_rowsequence.c |  464 +++++
 src/rasqal/rasqal_rowsource_sort.c        |  260 +++
 src/rasqal/rasqal_rowsource_triples.c     |  720 +++++++
 src/rasqal/rasqal_rowsource_union.c       |  579 ++++++
 src/rasqal/rasqal_skiplist.c              |  604 ++++++
 src/rasqal/rasqal_sparql_xml.c            | 1067 ++++++++++
 src/rasqal/rasqal_triples_source.c        |  236 +++
 src/rasqal/rasqal_variable.c              |  688 +++++++
 src/rasqal/rasqal_xsd_datatypes.c         |  981 +++++++++
 src/rasqal/rdql_common.h                  |   63 +
 src/rasqal/rdql_lexer.l                   | 1238 +++++++++++
 src/rasqal/rdql_parser.y                  |  937 +++++++++
 src/rasqal/sparql_common.h                |   63 +
 src/rasqal/sparql_lexer.l                 | 1610 +++++++++++++++
 src/rasqal/sparql_parser.y                | 3068 +++++++++++++++++++++++++++
 src/rasqal/strcasecmp.c                   |  118 ++
 src/rasqal/win32_rasqal_config.h          |  129 ++
 51 files changed, 39948 insertions(+), 1 deletions(-)

diff --git a/configure.ac b/configure.ac
index 4e4cdb7..dfa89a8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -209,10 +209,36 @@ AC_SUBST(UUID_CFLAGS)
 AC_SUBST(UUID_LIBS)
 
 # Check for Raptor
-PKG_CHECK_MODULES(RAPTOR, [raptor >= 1.4.17])
+PKG_CHECK_MODULES(RAPTOR, [raptor >= 1.4.18])
 AC_SUBST(RAPTOR_CFLAGS)
 AC_SUBST(RAPTOR_LIBS)
 
+AC_PROG_LEX
+if test "$LEX" = :; then
+        AC_MSG_ERROR([flex not found but required])
+fi
+
+AC_CHECK_PROGS(YACC, 'bison -y' byacc yacc, :)
+if test "$YACC" = :; then
+        AC_MSG_ERROR([bison not found but required])
+fi
+
+AC_CHECK_FUNCS(strcasecmp)
+
+AC_DEFINE_UNQUOTED(RASQAL_VERSION_MAJOR, 0, [Major version number])
+AC_DEFINE_UNQUOTED(RASQAL_VERSION_MINOR, 9, [Minor version number])
+AC_DEFINE_UNQUOTED(RASQAL_VERSION_RELEASE, 17, [Release version number])
+AC_DEFINE_UNQUOTED(RASQAL_VERSION_DECIMAL, 917, [Release version as a decimal])
+AC_DEFINE([RAPTOR_TRIPLES_SOURCE_RAPTOR], 1, [Use raptor to provide triples])
+AC_DEFINE(RASQAL_REGEX_POSIX, 1, [Use posix regex library])
+AC_DEFINE([RASQAL_DECIMAL_NONE], 1, [Decimal without a library])
+AC_DEFINE(RASQAL_QUERY_RDQL, 1, [Building RDQL query])
+AC_DEFINE(RASQAL_QUERY_LAQRS, 1, [Building LAQRS query])
+AC_DEFINE(RASQAL_QUERY_SPARQL, 1, [Building SPARQL query])
+AM_CONDITIONAL(RASQAL_QUERY_RDQL, true)
+AM_CONDITIONAL(RASQAL_QUERY_LAQRS, true)
+AM_CONDITIONAL(RASQAL_QUERY_SPARQL, true)
+
 # Check we have the DBUS binding tool we need
 AC_PATH_PROG(DBUSBINDINGTOOL, dbus-binding-tool)
 if test -z $DBUSBINDINGTOOL; then
@@ -1377,6 +1403,7 @@ AC_CONFIG_FILES([
 	src/libtracker/Makefile
 	src/Makefile
 	src/qdbm/Makefile
+	src/rasqal/Makefile
 	src/tracker-applet/Makefile
 	src/tracker-applet/tracker-applet.desktop.in
 	src/trackerd/Makefile
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 1c3deb0..43a1ef1 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -2,6 +2,8 @@
 # Please keep this file sorted alphabetically.
 
 data/trackerd.desktop.in
+src/rasqal/rdql_parser.c
+src/rasqal/sparql_parser.c
 src/tracker-applet/tracker-applet.desktop.in
 src/tracker-preferences/tracker-preferences.desktop.in
 src/tracker-search-tool/tracker-search-tool.desktop.in
diff --git a/src/Makefile.am b/src/Makefile.am
index 138d238..bbb6553 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ SUBDIRS = 					\
 	libstemmer				\
 	$(build_qdbm)				\
 	$(build_libinotify)			\
+	rasqal		 			\
 	libtracker-common 			\
 	libtracker-db				\
 	libtracker-data				\
@@ -51,6 +52,7 @@ DIST_SUBDIRS = 					\
 	libstemmer				\
 	qdbm					\
 	libinotify				\
+	rasqal		 			\
 	libtracker-common 			\
 	libtracker-db				\
 	libtracker-data				\
diff --git a/src/rasqal/Makefile.am b/src/rasqal/Makefile.am
new file mode 100644
index 0000000..fbf4bf3
--- /dev/null
+++ b/src/rasqal/Makefile.am
@@ -0,0 +1,95 @@
+# -*- Mode: Makefile -*-
+#
+# Makefile.am - automake file for Rasqal RDF query language library
+#
+# Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+# Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+# 
+# This package is Free Software and part of Redland http://librdf.org/
+# 
+# It is licensed under the following three licenses as alternatives:
+#   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+#   2. GNU General Public License (GPL) V2 or any newer version
+#   3. Apache License, V2.0 or any newer version
+# 
+# You may not use this file except in compliance with at least one of
+# the above three licenses.
+# 
+# See LICENSE.html or LICENSE.txt at the top of this package for the
+# complete terms and further detail along with the license texts for
+# the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+# 
+
+noinst_LTLIBRARIES = librasqal.la
+
+noinst_HEADERS = rasqal.h rasqal_internal.h rasqal_config.h win32_rasqal_config.h
+
+MAINTAINERCLEANFILES=rdql_lexer.c rdql_lexer.h \
+rdql_parser.c rdql_parser.h rdql_parser.output \
+sparql_lexer.c sparql_lexer.h \
+sparql_parser.c sparql_parser.h sparql_parser.output
+
+INCLUDES =			\
+	-DRASQAL_INTERNAL=1	\
+	-DVERSION=\""0.9.17"\"	\
+	$(RAPTOR_CFLAGS)
+
+librasqal_la_SOURCES = \
+rasqal_algebra.c \
+rasqal_expr.c rasqal_general.c rasqal_query.c rasqal_query_results.c \
+rasqal_engine.c rasqal_raptor.c rasqal_literal.c \
+rasqal_graph_pattern.c rasqal_map.c rasqal_feature.c \
+rasqal_result_formats.c rasqal_xsd_datatypes.c rasqal_decimal.c \
+rasqal_datetime.c rasqal_rowsource.c rasqal_sparql_xml.c \
+rasqal_variable.c rasqal_rowsource_empty.c rasqal_rowsource_union.c \
+rasqal_rowsource_rowsequence.c rasqal_query_transform.c rasqal_row.c \
+rasqal_engine_algebra.c rasqal_triples_source.c \
+rasqal_rowsource_triples.c rasqal_rowsource_filter.c \
+rasqal_rowsource_sort.c rasqal_engine_sort.c \
+rasqal_rowsource_project.c rasqal_rowsource_join.c
+
+if RASQAL_QUERY_RDQL
+librasqal_la_SOURCES += rdql_lexer.c rdql_lexer.h \
+rdql_parser.c rdql_parser.h rdql_common.h
+endif
+if RASQAL_QUERY_SPARQL
+librasqal_la_SOURCES += sparql_lexer.c sparql_lexer.h \
+sparql_parser.c sparql_parser.h sparql_common.h
+endif
+
+librasqal_la_LIBADD = $(RAPTOR_LIBS)
+
+
+EXTRA_DIST= \
+rdql_lexer.l rdql_parser.y \
+sparql_lexer.l sparql_parser.y \
+fix-flex fix-bison \
+rasqal.vapi
+
+LEX= LEX@
+YACC= YACC@
+
+# Actually it needs rdql_parser.h but nevermind
+rdql_lexer.c: $(srcdir)/rdql_lexer.l rdql_parser.c $(srcdir)/fix-flex
+	$(LEX) -o$@ $(srcdir)/rdql_lexer.l
+	$(PERL) $(srcdir)/fix-flex $@ > rdql_lexer.t
+	mv rdql_lexer.t $@
+
+rdql_parser.c: $(srcdir)/rdql_parser.y $(srcdir)/fix-bison
+	$(YACC) -b rdql_parser -p rdql_parser_ -d -v $(srcdir)/rdql_parser.y
+	$(PERL) $(srcdir)/fix-bison rdql_parser.tab.c > $@
+	mv rdql_parser.tab.h rdql_parser.h
+	rm -f rdql_parser.tab.c
+
+# Actually it needs sparql_parser.h but nevermind
+sparql_lexer.c: $(srcdir)/sparql_lexer.l sparql_parser.c $(srcdir)/fix-flex
+	$(LEX) -o$@ $(srcdir)/sparql_lexer.l
+	$(PERL) $(srcdir)/fix-flex $@ > sparql_lexer.t
+	mv sparql_lexer.t $@
+
+sparql_parser.c: $(srcdir)/sparql_parser.y $(srcdir)/fix-bison
+	$(YACC) -b sparql_parser -p sparql_parser_ -d -v $(srcdir)/sparql_parser.y
+	$(PERL) $(srcdir)/fix-bison sparql_parser.tab.c > $@
+	mv sparql_parser.tab.h sparql_parser.h
+	rm -f sparql_parser.tab.c
+
diff --git a/src/rasqal/fix-bison b/src/rasqal/fix-bison
new file mode 100755
index 0000000..188118b
--- /dev/null
+++ b/src/rasqal/fix-bison
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+#
+# $Id: fix-bison 14688 2008-10-10 06:51:17Z laalto $
+#
+# Format output generated by bison
+#
+# Usage:
+#  bison -b brql_parser -p brql_parser_ -d -v brql_parser.y
+#  perl fix-bison brql_parser.tab.c > $tmp
+#  mv $tmp brql_parser.tab.c
+#
+# Copyright (C) 2004-2006, David Beckett http://purl.org/net/dajobe/
+# Copyright (C) 2004, University of Bristol, UK http://www.bristol.ac.uk/
+#
+
+my $seen_yyerrlab1=0;
+my $line_offset=1; # #line directives always refer to the NEXT line
+while(<>) {
+  # HACK: Pass YYPARSE_PARAM* to %destructors
+  s/(yydestruct\s*\()const/$1void *YYPARSE_PARAM, const/; # yydestruct() definition sig 1
+  if(/(yydestruct\s*\()yymsg(.*)$/) { # yydestruct() defintion sig 2
+    print "$1YYPARSE_PARAM, yymsg$2\n    void *YYPARSE_PARAM;\n";
+    $line_offset++; # added a line
+    next;
+  }
+  s/(yydestruct\s*\()(".*)$/$1YYPARSE_PARAM, $2/; # yydestruct() calls
+
+  # Remove code that causes a warning
+  if(/Suppress GCC warning that yyerrlab1/) {
+    do {
+      $_=<>;
+      $line_offset--; # skipped a line
+    } while(!/^\#endif/);
+    $line_offset--; # skipped a line
+    next;
+  }
+
+  $seen_yyerrlab1=1 if /goto yyerrlab1/;
+
+  s/^yyerrlab1:// unless $seen_yyerrlab1;
+
+  # Do not use macro name for a temporary variable
+  s/unsigned int yylineno = /unsigned int yylineno_tmp = /;
+  s/yyrule - 1, yylineno\)/yyrule - 1, yylineno_tmp\)/;
+
+  # Do not (re)define prototypes that the system did better
+  if(m%^void \*malloc\s*\(%) {
+    $line_offset--; # skipped a line
+    next;
+  }
+  if(m%^void free\s*\(%) {
+    $line_offset--; # skipped a line
+    next; 
+  }
+
+  # Suppress warnings about empty declarations
+  s/(^static int .*_init_globals.*);$/$1/;
+
+  # Fixup pending filename renaming, see above.
+  # Fix line numbers.
+  my $line=$. +$line_offset;
+  s/^(\#line) \d+ (.*)\.tab\.c/$1 $line $2.c/;
+
+  print;
+}
diff --git a/src/rasqal/fix-flex b/src/rasqal/fix-flex
new file mode 100755
index 0000000..54be711
--- /dev/null
+++ b/src/rasqal/fix-flex
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+#
+# $Id: fix-flex 14390 2008-08-25 11:18:52Z laalto $
+#
+# Format output generated by flex 2.5.31
+#
+# Usage:
+#  flex -o$output $input
+#  perl fix-flex $output > $tmp
+#  mv $tmp $output
+#
+# Copyright (C) 2004-2006, David Beckett http://purl.org/net/dajobe/
+# Copyright (C) 2004, University of Bristol, UK http://www.bristol.ac.uk/
+#
+
+my $line_offset=1; # #line directives always refer to the NEXT line
+
+print <<'EOT';
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+EOT
+$line_offset+=8; # added 8 lines to output
+
+my $prefix=undef;
+
+while(<>) {
+  # Remove generated yy_fatal_error declaration and definition to avoid warnings about unused/non-defined static function
+  # declaration
+  if(/^static void yy_fatal_error\s*\(.*\)\s*\;\s*$/) {
+    $line_offset--; # skipped 1 line
+    next;
+  }
+  # definition
+  if(/^static void yy_fatal_error\s*\(.*\)\s*[^\;]\s*$/) {
+    do {
+      $_=<>;
+      $line_offset--; # skipped 1 line
+    } while(!/^}/);
+    $line_offset--; # skipped 1 line
+    next;
+  }
+
+  # Replace calls to yy_fatal_error("msg", yyscanner) to YY_FATAL_ERROR("msg") macro
+  s/(^\s*)yy_fatal_error\s*\(\s*(\".*\")\s*,\s*yyscanner\s*\)/$1YY_FATAL_ERROR($2)/;
+
+  # flex has %option nounistd however it does not work in 2.5.31
+  # It is safe to add yet another wrapper. 
+  if(m%^(\#include \<unistd.h\>)$%) {
+    $_=<<"EOT";
+#ifndef YY_NO_UNISTD_H
+$1
+#endif
+EOT
+    $line_offset+=2; # added 2 lines to output
+  }
+
+  # Add $prefix_cleanup() call at the end of $prefix_lex_destroy()
+  # find the start of lex_destroy function definition and capture prefix
+  if(/^int\s+(\S+)_lex_destroy\s*\(.*\)\s*[^\;]\s*$/) { $prefix=$1; }
+  # look for lexer_free(yyscanner, yyscanner) statement within the function and place the cleanup call before it
+  if($prefix) {
+    if(/(^\s*)(${prefix}_free\s*\(\s*yyscanner\s*,\s*yyscanner\s*\)\s*\;)\s*$/) {
+      $_=<<"EOT";
+$1/* clean up leaks if any before freeing yyscanner */
+$1${prefix}_cleanup(yyscanner);
+$1$2
+EOT
+      $line_offset+=2; # added 2 lines to output
+      $prefix=undef; # lex_destroy() patched
+    }
+  }
+
+  # Fix .[ch] line references because we have added lines to it
+  my $line = $. +$line_offset;
+  s/^#line \d+ (\".*\.[ch]\")/#line $line $1/;
+
+  print;
+}
diff --git a/src/rasqal/rasqal.h b/src/rasqal/rasqal.h
new file mode 100644
index 0000000..225e34e
--- /dev/null
+++ b/src/rasqal/rasqal.h
@@ -0,0 +1,1368 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal.h - Rasqal RDF Query library interfaces and definition
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+
+#ifndef RASQAL_H
+#define RASQAL_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * RASQAL_API:
+ *
+ * Macro for wrapping API function call declarations.
+ *
+ */
+#ifndef RASQAL_API
+#  ifdef WIN32
+#    ifdef __GNUC__
+#      undef _declspec
+#      define _declspec(x) __declspec(x)
+#    endif
+#    ifdef RASQAL_STATIC
+#      define RASQAL_API
+#    else
+#      ifdef RASQAL_INTERNAL
+#        define RASQAL_API _declspec(dllexport)
+#      else
+#        define RASQAL_API _declspec(dllimport)
+#      endif
+#    endif
+#  else
+#    define RASQAL_API
+#  endif
+#endif
+
+/* Use gcc 3.1+ feature to allow marking of deprecated API calls.
+ * This gives a warning during compiling.
+ */
+#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3
+#ifdef __APPLE_CC__
+/* OSX gcc cpp-precomp is broken */
+#define RASQAL_DEPRECATED
+#else
+#define RASQAL_DEPRECATED __attribute__((deprecated))
+#endif
+#else
+#define RASQAL_DEPRECATED
+#endif
+
+
+#ifndef LIBRDF_OBJC_FRAMEWORK
+#include <raptor.h>
+#else
+#include <Redland/raptor.h>
+#endif
+
+#ifndef RAPTOR_WORLD_DECLARED
+#define RAPTOR_WORLD_DECLARED 1
+/* Declare raptor_world type unless it is declared in raptor.h */
+typedef struct raptor_world_s raptor_world;
+#endif
+
+/* Public statics */
+RASQAL_API
+extern const char * const rasqal_short_copyright_string;
+RASQAL_API
+extern const char * const rasqal_copyright_string;
+RASQAL_API
+extern const char * const rasqal_version_string;
+RASQAL_API
+extern const unsigned int rasqal_version_major;
+RASQAL_API
+extern const unsigned int rasqal_version_minor;
+RASQAL_API
+extern const unsigned int rasqal_version_release;
+RASQAL_API
+extern const unsigned int rasqal_version_decimal;
+RASQAL_API
+extern const char * const rasqal_license_string;
+RASQAL_API
+extern const char * const rasqal_home_url_string;
+
+
+/* Public structures */
+
+#ifndef RASQAL_WORLD_DECLARED
+#define RASQAL_WORLD_DECLARED 1
+/**
+ * rasqal_world:
+ *
+ * Rasqal world class.
+ */
+typedef struct rasqal_world_s rasqal_world;
+#endif
+
+/**
+ * rasqal_query:
+ *
+ * Rasqal query class.
+ */
+typedef struct rasqal_query_s rasqal_query;
+
+/**
+ * rasqal_query_results:
+ *
+ * Rasqal query results class.
+ */
+typedef struct rasqal_query_results_s rasqal_query_results;
+
+
+#ifndef RASQAL_QUERY_RESULTS_FORMATTER_DECLARED
+#define RASQAL_QUERY_RESULTS_FORMATTER_DECLARED 1
+/**
+ * rasqal_query_results_formatter:
+ *
+ * Rasqal query results formatter class.
+ */
+typedef struct rasqal_query_results_formatter_s rasqal_query_results_formatter;
+#endif
+
+
+typedef struct rasqal_literal_s rasqal_literal;
+
+/**
+ * rasqal_graph_pattern:
+ *
+ * Rasqal graph pattern class.
+ */
+typedef struct rasqal_graph_pattern_s rasqal_graph_pattern;
+
+/**
+ * rasqal_algebra_node:
+ *
+ * Rasqal graph pattern class.
+ */
+typedef struct rasqal_algebra_node_s rasqal_algebra_node;
+
+/**
+ * rasqal_feature:
+ * @RASQAL_FEATURE_NO_NET: Deny network requests.
+ * @RASQAL_FEATURE_LAST: Internal.
+ *
+ * Query features.
+ *
+ * None currently defined.
+ */
+typedef enum {
+  RASQAL_FEATURE_NO_NET,
+  RASQAL_FEATURE_LAST = RASQAL_FEATURE_NO_NET
+} rasqal_feature;
+
+
+/**
+ * rasqal_prefix:
+ * @prefix: short prefix string
+ * @uri: URI associated with the prefix.
+ * @declared: Internal flag.
+ * @depth: Internal flag.
+ * @world: rasqal_world object
+ *
+ * Namespace (prefix, uri) pair.
+ *
+ * Includes internal flags used for marking when prefixes are
+ * declared and at what XML element depth when used in XML formats.
+ */
+typedef struct {
+  const unsigned char *prefix;
+  raptor_uri* uri;
+  int declared;
+  int depth;
+  rasqal_world* world;
+} rasqal_prefix;
+
+
+/**
+ * rasqal_variable_type:
+ * @RASQAL_VARIABLE_TYPE_NORMAL: The regular variable type.
+ * @RASQAL_VARIABLE_TYPE_ANONYMOUS: Anonymous variable type.
+ * @RASQAL_VARIABLE_TYPE_UNKNOWN: Internal.
+ *
+ * Rasqal variable types.
+ *
+ * ANONYMOUS can be used in queries but cannot be returned in a
+ * result.
+ */
+typedef enum {
+  RASQAL_VARIABLE_TYPE_UNKNOWN   = 0,
+  RASQAL_VARIABLE_TYPE_NORMAL    = 1,
+  RASQAL_VARIABLE_TYPE_ANONYMOUS = 2
+} rasqal_variable_type;
+
+
+/* forward reference */
+struct rasqal_expression_s;
+
+/**
+ * rasqal_variable:
+ * @name: Variable name.
+ * @value: Variable value or NULL if unbound.
+ * @offset: Internal.
+ * @type: Variable type.
+ * @expression: Expression when the variable is a computed SELECT expression 
+ *
+ * Binding between a variable name and a value.
+ *
+ * Includes internal field @offset for recording the offset into the
+ * (internal) rasqal_query variables array.
+ */
+typedef struct {
+  const unsigned char *name;
+  rasqal_literal* value;
+  int offset;
+  rasqal_variable_type type;
+  struct rasqal_expression_s* expression;
+} rasqal_variable;
+
+
+/**
+ * rasqal_data_graph_flags:
+ * @RASQAL_DATA_GRAPH_NONE: Internal.
+ * @RASQAL_DATA_GRAPH_NAMED: Graphs with a source and name.
+ * @RASQAL_DATA_GRAPH_BACKGROUND: Graphs with a source only.
+ *
+ * Flags for the type of #rasqal_data_graph.
+ *
+ * These are used by rasqal_query_add_data_graph(). See #rasqal_data_graph.
+ */
+typedef enum {
+  RASQAL_DATA_GRAPH_NONE  = 0,
+  RASQAL_DATA_GRAPH_NAMED = 1,
+  RASQAL_DATA_GRAPH_BACKGROUND = 2,
+} rasqal_data_graph_flags;
+
+
+/**
+ * rasqal_data_graph:
+ * @uri: source URI
+ * @name_uri: name of graph for %RASQAL_DATA_NAMED
+ * @flags: %RASQAL_DATA_GRAPH_NAMED or %RASQAL_DATA_GRAPH_BACKGROUND
+ * @world: rasqal_world object
+ *
+ * A source of RDF data for querying. 
+ *
+ * The #uri is the original source (base URI) of the content.  It may
+ * also have an additional name @name_uri as long as @flags is
+ * %RASQAL_DATA_NAMED
+ */
+typedef struct {
+  raptor_uri* uri;
+  raptor_uri* name_uri;
+  int flags;
+  rasqal_world* world;
+} rasqal_data_graph;
+
+
+/**
+ * rasqal_literal_type:
+ * @RASQAL_LITERAL_BLANK: RDF blank node literal (SPARQL r:bNode)
+ * @RASQAL_LITERAL_URI: RDF URI Literal (SPARQL r:URI)
+ * @RASQAL_LITERAL_STRING: RDF Literal / xsd:string (SPARQL r:Literal)
+ * @RASQAL_LITERAL_BOOLEAN: Boolean literal xsd:boolean.
+ * @RASQAL_LITERAL_INTEGER: Integer literal xsd:integer.
+ * @RASQAL_LITERAL_DOUBLE: Double floating point literal xsd:double.
+ * @RASQAL_LITERAL_FLOAT: Floating point literal xsd:float.
+ * @RASQAL_LITERAL_DECIMAL: Decimal integer xsd:decimal.
+ * @RASQAL_LITERAL_DATETIME: Date/Time literal xsd:dateTime.
+ * @RASQAL_LITERAL_PATTERN: Pattern literal for a regex.
+ * @RASQAL_LITERAL_QNAME: XML Qname literal.
+ * @RASQAL_LITERAL_VARIABLE: Variable literal.
+ * @RASQAL_LITERAL_UNKNOWN: Internal.
+ * @RASQAL_LITERAL_FIRST_XSD: Internal.
+ * @RASQAL_LITERAL_LAST_XSD: Internal.
+ * @RASQAL_LITERAL_LAST: Internal.
+ *
+ * Types of literal.
+ *
+ * The order in the enumeration is significant as it encodes
+ * the SPARQL term ordering conditions:
+ *
+ *   Blank Nodes << IRIs << RDF literals << typed literals
+ *
+ * which coresponds to in enum values
+ *
+ *   BLANK << URI << STRING << 
+ *     (BOOLEAN | INTEGER | DOUBLE | FLOAT | DECIMAL | DATETIME)
+ *
+ *     (RASQAL_LITERAL_FIRST_XSD ... RASQAL_LITERAL_LAST_XSD)
+ *
+ * Not used (internal): PATTERN, QNAME, VARIABLE
+ *
+ * See rasqal_literal_compare() when used with flags
+ * %RASQAL_COMPARE_XQUERY
+ */
+typedef enum {
+  /* internal */
+  RASQAL_LITERAL_UNKNOWN,
+  RASQAL_LITERAL_BLANK,
+  RASQAL_LITERAL_URI,
+  RASQAL_LITERAL_STRING,
+  RASQAL_LITERAL_BOOLEAN,
+  RASQAL_LITERAL_INTEGER,
+  RASQAL_LITERAL_DOUBLE,
+  RASQAL_LITERAL_FLOAT,
+  RASQAL_LITERAL_DECIMAL,
+  RASQAL_LITERAL_DATETIME,
+  /* internal */
+  RASQAL_LITERAL_FIRST_XSD = RASQAL_LITERAL_STRING,
+  /* internal */
+  RASQAL_LITERAL_LAST_XSD = RASQAL_LITERAL_DATETIME,
+  RASQAL_LITERAL_PATTERN,
+  RASQAL_LITERAL_QNAME,
+  RASQAL_LITERAL_VARIABLE,
+  /* internal */
+  RASQAL_LITERAL_LAST= RASQAL_LITERAL_VARIABLE
+} rasqal_literal_type;
+
+
+/**
+ * rasqal_xsd_decimal:
+ *
+ * Rasqal XSD Decimal class.
+ */
+typedef struct rasqal_xsd_decimal_s rasqal_xsd_decimal;
+
+/**
+ * rasqal_literal:
+ * @usage: Usage count.
+ * @type: Type of literal.
+ * @string: String form of literal for literal types UTF-8 string, pattern, qname, blank, double, float, decimal, datetime.
+ * @string_len: Length of @string.
+ * @value: Alternate value content.
+ * @language: Language for string literal type.
+ * @datatype: Datatype for string literal type.
+ * @flags: Flags for literal types
+ *
+ * Rasqal literal class.
+ *
+ */
+struct rasqal_literal_s {
+  int usage;
+  rasqal_literal_type type;
+  /* UTF-8 string, pattern, qname, blank, double, float, decimal, datetime */
+  const unsigned char *string;
+  unsigned int string_len;
+  
+  union {
+    /* integer and boolean types */
+    int integer;
+    /* double and float */
+    double floating;
+    /* uri (can be temporarily NULL if a qname, see flags below) */
+    raptor_uri* uri;
+    /* variable */
+    rasqal_variable* variable;
+    /* decimal */
+    rasqal_xsd_decimal* decimal;
+  } value;
+
+  /* for string */
+  const char *language;
+  raptor_uri *datatype;
+
+  /* various flags for literal types:
+   *  pattern  regex flags
+   *  string   datatype of qname
+   *  uri      qname of URI not yet expanded (temporary)
+   */
+  const unsigned char *flags;
+
+  /* parent XSD type if any or RASQAL_LITERAL_UNKNOWN */
+  rasqal_literal_type parent_type;
+
+  /* world object */
+  rasqal_world *world;
+};
+
+
+/**
+ * rasqal_op:
+ * @RASQAL_EXPR_AND: Expression for AND(A, B)
+ * @RASQAL_EXPR_OR: Expression for OR(A, B)
+ * @RASQAL_EXPR_EQ: Expression for A equals B
+ * @RASQAL_EXPR_NEQ: Expression for A not equals B.
+ * @RASQAL_EXPR_LT: Expression for A less than B.
+ * @RASQAL_EXPR_GT: Expression for A greather than B.
+ * @RASQAL_EXPR_LE: Expression for A less than or equal to B.
+ * @RASQAL_EXPR_GE: Expression for A greater than or equal to B.
+ * @RASQAL_EXPR_UMINUS: Expression for -A.
+ * @RASQAL_EXPR_PLUS: Expression for +A.
+ * @RASQAL_EXPR_MINUS: Expression for A-B.
+ * @RASQAL_EXPR_STAR: Expression for A*B.
+ * @RASQAL_EXPR_SLASH: Expression for A/B.
+ * @RASQAL_EXPR_REM: Expression for A/B remainder.
+ * @RASQAL_EXPR_STR_EQ: Expression for A string equals B.
+ * @RASQAL_EXPR_STR_NEQ: Expression for A string not-equals B.
+ * @RASQAL_EXPR_STR_MATCH: Expression for string A matches literal regex B with flags.
+ * @RASQAL_EXPR_STR_NMATCH: Expression for string A not-matches literal regex B with flags.
+ * @RASQAL_EXPR_REGEX: Expression for string A matches expression regex B with flags.
+ * @RASQAL_EXPR_TILDE: Expression for binary not A.
+ * @RASQAL_EXPR_BANG: Expression for logical not A.
+ * @RASQAL_EXPR_LITERAL: Expression for a #rasqal_literal.
+ * @RASQAL_EXPR_FUNCTION: Expression for a function A with arguments (B...).
+ * @RASQAL_EXPR_BOUND: Expression for SPARQL ISBOUND(A).
+ * @RASQAL_EXPR_STR: Expression for SPARQL STR(A).
+ * @RASQAL_EXPR_LANG: Expression for SPARQL LANG(A).
+ * @RASQAL_EXPR_LANGMATCHES: Expression for SPARQL LANGMATCHES(A, B).
+ * @RASQAL_EXPR_DATATYPE: Expression for SPARQL DATATYPE(A).
+ * @RASQAL_EXPR_ISURI: Expression for SPARQL ISURI(A).
+ * @RASQAL_EXPR_ISBLANK: Expression for SPARQL ISBLANK(A).
+ * @RASQAL_EXPR_ISLITERAL: Expression for SPARQL ISLITERAL(A).
+ * @RASQAL_EXPR_CAST: Expression for cast literal A to type B.
+ * @RASQAL_EXPR_ORDER_COND_ASC: Expression for SPARQL order condition ascending.
+ * @RASQAL_EXPR_ORDER_COND_DESC: Expression for SPARQL order condition descending.
+ * @RASQAL_EXPR_GROUP_COND_ASC: Expression for LAQRS group condition ascending.
+ * @RASQAL_EXPR_GROUP_COND_DESC: Expression for LAQRS group condition descending.
+ * @RASQAL_EXPR_COUNT: Expression for LAQRS select COUNT()
+ * @RASQAL_EXPR_VARSTAR: Expression for LAQRS select Variable *
+ * @RASQAL_EXPR_SAMETERM: Expression for SPARQL sameTerm
+ * @RASQAL_EXPR_UNKNOWN: Internal
+ * @RASQAL_EXPR_LAST: Internal
+ *
+ * Rasqal expression operators.  A mixture of unary, binary and
+ * tertiary operators (string matches).  Also includes casting and
+ * two ordering operators from ORDER BY in SPARQL.
+ */
+typedef enum {
+  /* internal */
+  RASQAL_EXPR_UNKNOWN,
+  RASQAL_EXPR_AND,
+  RASQAL_EXPR_OR,
+  RASQAL_EXPR_EQ,
+  RASQAL_EXPR_NEQ,
+  RASQAL_EXPR_LT,
+  RASQAL_EXPR_GT,
+  RASQAL_EXPR_LE,
+  RASQAL_EXPR_GE,
+  RASQAL_EXPR_UMINUS,
+  RASQAL_EXPR_PLUS,
+  RASQAL_EXPR_MINUS,
+  RASQAL_EXPR_STAR,
+  RASQAL_EXPR_SLASH,
+  RASQAL_EXPR_REM,
+  RASQAL_EXPR_STR_EQ,
+  RASQAL_EXPR_STR_NEQ,
+  RASQAL_EXPR_STR_MATCH,
+  RASQAL_EXPR_STR_NMATCH,
+  RASQAL_EXPR_TILDE,
+  RASQAL_EXPR_BANG,
+  RASQAL_EXPR_LITERAL,
+  RASQAL_EXPR_FUNCTION,
+  RASQAL_EXPR_BOUND,
+  RASQAL_EXPR_STR,
+  RASQAL_EXPR_LANG,
+  RASQAL_EXPR_DATATYPE,
+  RASQAL_EXPR_ISURI,
+  RASQAL_EXPR_ISBLANK,
+  RASQAL_EXPR_ISLITERAL,
+  RASQAL_EXPR_CAST,
+  RASQAL_EXPR_ORDER_COND_ASC,
+  RASQAL_EXPR_ORDER_COND_DESC,
+  RASQAL_EXPR_LANGMATCHES,
+  RASQAL_EXPR_REGEX,
+  RASQAL_EXPR_GROUP_COND_ASC,
+  RASQAL_EXPR_GROUP_COND_DESC,
+  RASQAL_EXPR_COUNT,
+  RASQAL_EXPR_VARSTAR,
+  RASQAL_EXPR_SAMETERM,
+  /* internal */
+  RASQAL_EXPR_LAST= RASQAL_EXPR_SAMETERM
+} rasqal_op;
+
+
+/**
+ * rasqal_expression:
+ *
+ * expression (arg1), unary op (arg1), binary op (arg1,arg2),
+ * literal or variable 
+ */
+struct rasqal_expression_s {
+  int usage; /* reference count - 1 for itself */
+
+  rasqal_op op;
+  struct rasqal_expression_s* arg1;
+  struct rasqal_expression_s* arg2;
+  struct rasqal_expression_s* arg3; /* optional 3rd arg for EXPR_REGEX */
+  rasqal_literal* literal;
+  unsigned char *value; /* UTF-8 value */
+
+  /* for extension function qname(args...) and cast-to-uri */
+  raptor_uri* name;
+  raptor_sequence* args;
+  
+  /* rasqal_world object */
+  rasqal_world* world;
+};
+typedef struct rasqal_expression_s rasqal_expression;
+
+
+/**
+ * rasqal_triple_flags:
+ * @RASQAL_TRIPLE_FLAGS_EXACT: Not used.
+ * @RASQAL_TRIPLE_FLAGS_OPTIONAL: Not used.
+ * @RASQAL_TRIPLE_FLAGS_LAST: Internal.
+ *
+ * Flags for triple patterns.
+ */
+typedef enum {
+
+  /* Not used - was only used internally in the execution engine */
+  RASQAL_TRIPLE_FLAGS_EXACT=1,
+
+  /* Not used - this is now a property of a graph pattern */
+  RASQAL_TRIPLE_FLAGS_OPTIONAL=2,
+
+  RASQAL_TRIPLE_FLAGS_LAST=RASQAL_TRIPLE_FLAGS_OPTIONAL
+} rasqal_triple_flags;
+
+
+/**
+ * rasqal_triple:
+ * @subject: Triple subject.
+ * @predicate: Triple predicate.
+ * @object: Triple object.
+ * @origin: Triple origin.
+ * @flags: Or of enum #rasqal_triple_flags bits.
+ *
+ * A triple pattern or RDF triple.
+ *
+ * This is used as a triple pattern in queries and
+ * an RDF triple when generating RDF triples such as with SPARQL CONSTRUCT.
+ */
+typedef struct {
+  rasqal_literal* subject;
+  rasqal_literal* predicate;
+  rasqal_literal* object;
+  rasqal_literal* origin;
+  unsigned int flags;
+} rasqal_triple;
+
+
+/**
+ * rasqal_pattern_flags:
+ * @RASQAL_PATTERN_FLAGS_OPTIONAL: True when the graph pattern is an optional match.
+ * @RASQAL_PATTERN_FLAGS_LAST: Internal
+ *
+ * Flags for #rasqal_graph_pattern.
+ */
+typedef enum {
+  RASQAL_PATTERN_FLAGS_OPTIONAL=1,
+
+  RASQAL_PATTERN_FLAGS_LAST=RASQAL_PATTERN_FLAGS_OPTIONAL
+} rasqal_pattern_flags;
+
+
+typedef unsigned char* (*rasqal_generate_bnodeid_handler)(rasqal_query* query, void *user_data, unsigned char *user_bnodeid);
+
+
+/**
+ * rasqal_query_verb:
+ * @RASQAL_QUERY_VERB_SELECT: RDQL/SPARQL query select verb. 
+ * @RASQAL_QUERY_VERB_CONSTRUCT: SPARQL query construct verb.
+ * @RASQAL_QUERY_VERB_DESCRIBE: SPARQL query describe verb.
+ * @RASQAL_QUERY_VERB_ASK: SPARQL query ask verb.
+ * @RASQAL_QUERY_VERB_DELETE: LAQRS query delete verb.
+ * @RASQAL_QUERY_VERB_INSERT: LAQRS query insert verb.
+ * @RASQAL_QUERY_VERB_UNKNOWN: Internal
+ * @RASQAL_QUERY_VERB_LAST: Internal
+ *
+ * Query main operation verbs describing the major type of query
+ * being performed.
+ */
+typedef enum {
+  /* internal */
+  RASQAL_QUERY_VERB_UNKNOWN   = 0,
+  RASQAL_QUERY_VERB_SELECT    = 1,
+  RASQAL_QUERY_VERB_CONSTRUCT = 2,
+  RASQAL_QUERY_VERB_DESCRIBE  = 3,
+  RASQAL_QUERY_VERB_ASK       = 4,
+  RASQAL_QUERY_VERB_DELETE    = 5,
+  RASQAL_QUERY_VERB_INSERT    = 6,
+
+  /* internal */
+  RASQAL_QUERY_VERB_LAST=RASQAL_QUERY_VERB_INSERT
+} rasqal_query_verb;
+
+
+/**
+ * rasqal_graph_pattern_operator:
+ * @RASQAL_GRAPH_PATTERN_OPERATOR_BASIC: Just triple patterns and constraints.
+ * @RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL: Set of graph patterns (ANDed) and constraints.
+ * @RASQAL_GRAPH_PATTERN_OPERATOR_UNION: Set of graph patterns (UNIONed) and constraints.
+ * @RASQAL_GRAPH_PATTERN_OPERATOR_GROUP: Set of graph patterns (ANDed) and constraints.
+ * @RASQAL_GRAPH_PATTERN_OPERATOR_GRAPH: A graph term + a graph pattern and constraints.
+ * @RASQAL_GRAPH_PATTERN_OPERATOR_FILTER: A filter graph pattern with an expression
+ * @RASQAL_GRAPH_PATTERN_OPERATOR_UNKNOWN: Internal.
+ * @RASQAL_GRAPH_PATTERN_OPERATOR_LAST: Internal.
+ *
+ * Graph pattern operators
+ */
+typedef enum {
+  RASQAL_GRAPH_PATTERN_OPERATOR_UNKNOWN   = 0,
+  RASQAL_GRAPH_PATTERN_OPERATOR_BASIC     = 1,
+  RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL  = 2,
+  RASQAL_GRAPH_PATTERN_OPERATOR_UNION     = 3,
+  RASQAL_GRAPH_PATTERN_OPERATOR_GROUP     = 4,
+  RASQAL_GRAPH_PATTERN_OPERATOR_GRAPH     = 5,
+  RASQAL_GRAPH_PATTERN_OPERATOR_FILTER    = 6,
+
+  RASQAL_GRAPH_PATTERN_OPERATOR_LAST=RASQAL_GRAPH_PATTERN_OPERATOR_FILTER
+} rasqal_graph_pattern_operator;
+
+
+/**
+ * rasqal_graph_pattern_visit_fn:
+ * @query: #rasqal_query containing the graph pattern
+ * @gp: current graph_pattern
+ * @user_data: user data passed in
+ *
+ * User function to visit an graph_pattern and operate on it with
+ * rasqal_graph_pattern_visit() or rasqal_query_graph_pattern_visit()
+ *
+ * Return value: 0 to truncate the visit
+ */
+typedef int (*rasqal_graph_pattern_visit_fn)(rasqal_query* query, rasqal_graph_pattern* gp, void *user_data);
+
+
+/* RASQAL API */
+
+/* Public functions */
+
+RASQAL_API
+rasqal_world *rasqal_new_world(void);
+RASQAL_API
+int rasqal_world_open(rasqal_world* world);
+RASQAL_API
+void rasqal_free_world(rasqal_world* world);
+
+RASQAL_API
+void rasqal_world_set_raptor(rasqal_world* world, raptor_world* raptor_world_ptr);
+RASQAL_API
+raptor_world *rasqal_world_get_raptor(rasqal_world* world);
+
+/* Features */
+RASQAL_API
+int rasqal_features_enumerate(rasqal_world* world, const rasqal_feature feature, const char **name, raptor_uri **uri, const char **label);
+RASQAL_API
+unsigned int rasqal_get_feature_count(void);
+RASQAL_API
+rasqal_feature rasqal_feature_from_uri(rasqal_world* world, raptor_uri *uri);
+RASQAL_API
+int rasqal_feature_value_type(const rasqal_feature feature);
+
+RASQAL_API
+int rasqal_languages_enumerate(rasqal_world* world, unsigned int counter, const char **name, const char **label, const unsigned char **uri_string);
+
+RASQAL_API
+int rasqal_language_name_check(rasqal_world* world, const char *name);
+
+
+/* Query class */
+
+/* Create */
+RASQAL_API
+rasqal_query* rasqal_new_query(rasqal_world* world, const char *name, const unsigned char *uri);
+
+/* Destroy */
+RASQAL_API
+void rasqal_free_query(rasqal_query* query);
+
+/* Methods */
+RASQAL_API
+const char* rasqal_query_get_name(rasqal_query* query);
+RASQAL_API
+const char* rasqal_query_get_label(rasqal_query* query);
+RASQAL_API
+void rasqal_query_set_fatal_error_handler(rasqal_query* query, void *user_data, raptor_message_handler handler);
+RASQAL_API
+void rasqal_query_set_error_handler(rasqal_query* query, void *user_data, raptor_message_handler handler);
+RASQAL_API
+void rasqal_query_set_warning_handler(rasqal_query* query, void *user_data, raptor_message_handler handler);
+RASQAL_API
+int rasqal_query_set_feature(rasqal_query* query, rasqal_feature feature, int value);
+RASQAL_API
+int rasqal_query_set_feature_string(rasqal_query *query, rasqal_feature feature, const unsigned char *value);
+RASQAL_API
+int rasqal_query_get_feature(rasqal_query *query, rasqal_feature feature);
+RASQAL_API
+const unsigned char* rasqal_query_get_feature_string(rasqal_query *query, rasqal_feature feature);
+RASQAL_API
+void rasqal_query_set_default_generate_bnodeid_parameters(rasqal_query* rdf_query, char *prefix, int base);
+RASQAL_API
+void rasqal_query_set_generate_bnodeid_handler(rasqal_query* query, void *user_data, rasqal_generate_bnodeid_handler handler);
+
+RASQAL_API
+rasqal_query_verb rasqal_query_get_verb(rasqal_query* query);
+RASQAL_API
+int rasqal_query_get_wildcard(rasqal_query* query);
+RASQAL_API
+int rasqal_query_get_distinct(rasqal_query* query);
+RASQAL_API
+void rasqal_query_set_distinct(rasqal_query* query, int distinct_mode);
+RASQAL_API
+int rasqal_query_get_explain(rasqal_query* query);
+RASQAL_API
+void rasqal_query_set_explain(rasqal_query* query, int is_explain);
+RASQAL_API
+int rasqal_query_get_limit(rasqal_query* query);
+RASQAL_API
+void rasqal_query_set_limit(rasqal_query* query, int limit);
+RASQAL_API
+int rasqal_query_get_offset(rasqal_query* query);
+RASQAL_API
+void rasqal_query_set_offset(rasqal_query* query, int offset);
+
+RASQAL_API
+int rasqal_query_add_data_graph(rasqal_query* query, raptor_uri* uri, raptor_uri* name_uri, int flags);
+RASQAL_API
+raptor_sequence* rasqal_query_get_data_graph_sequence(rasqal_query* query);
+RASQAL_API
+rasqal_data_graph* rasqal_query_get_data_graph(rasqal_query* query, int idx);
+RASQAL_API
+int rasqal_query_dataset_contains_named_graph(rasqal_query* query, raptor_uri *graph_uri);
+
+RASQAL_API
+int rasqal_query_add_variable(rasqal_query* query, rasqal_variable* var);
+RASQAL_API
+raptor_sequence* rasqal_query_get_bound_variable_sequence(rasqal_query* query);
+RASQAL_API
+raptor_sequence* rasqal_query_get_anonymous_variable_sequence(rasqal_query* query);
+RASQAL_API
+raptor_sequence* rasqal_query_get_all_variable_sequence(rasqal_query* query);
+RASQAL_API
+rasqal_variable* rasqal_query_get_variable(rasqal_query* query, int idx);
+RASQAL_API
+int rasqal_query_has_variable(rasqal_query* query, const unsigned char *name);
+RASQAL_API
+int rasqal_query_set_variable(rasqal_query* query, const unsigned char *name, rasqal_literal* value);
+RASQAL_API
+raptor_sequence* rasqal_query_get_triple_sequence(rasqal_query* query);
+RASQAL_API
+rasqal_triple* rasqal_query_get_triple(rasqal_query* query, int idx);
+RASQAL_API
+int rasqal_query_add_prefix(rasqal_query* query, rasqal_prefix* prefix);
+RASQAL_API
+raptor_sequence* rasqal_query_get_prefix_sequence(rasqal_query* query);
+RASQAL_API
+rasqal_prefix* rasqal_query_get_prefix(rasqal_query* query, int idx);
+RASQAL_API
+raptor_sequence* rasqal_query_get_order_conditions_sequence(rasqal_query* query);
+RASQAL_API
+rasqal_expression* rasqal_query_get_order_condition(rasqal_query* query, int idx);
+RASQAL_API
+raptor_sequence* rasqal_query_get_group_conditions_sequence(rasqal_query* query);
+RASQAL_API
+rasqal_expression* rasqal_query_get_group_condition(rasqal_query* query, int idx);
+RASQAL_API
+raptor_sequence* rasqal_query_get_construct_triples_sequence(rasqal_query* query);
+RASQAL_API
+rasqal_triple* rasqal_query_get_construct_triple(rasqal_query* query, int idx);
+RASQAL_API
+void rasqal_query_graph_pattern_visit(rasqal_query* query, rasqal_graph_pattern_visit_fn visit_fn, void* data);
+RASQAL_API
+int rasqal_query_write(raptor_iostream* iostr, rasqal_query* query, raptor_uri* format_uri, raptor_uri* base_uri);
+
+/* graph patterns */
+RASQAL_API
+rasqal_graph_pattern* rasqal_query_get_query_graph_pattern(rasqal_query* query);
+RASQAL_API
+raptor_sequence* rasqal_query_get_graph_pattern_sequence(rasqal_query* query);
+RASQAL_API
+rasqal_graph_pattern* rasqal_query_get_graph_pattern(rasqal_query* query, int idx);
+RASQAL_API
+int rasqal_graph_pattern_add_sub_graph_pattern(rasqal_graph_pattern* graph_pattern, rasqal_graph_pattern* sub_graph_pattern);
+RASQAL_API
+rasqal_triple* rasqal_graph_pattern_get_triple(rasqal_graph_pattern* graph_pattern, int idx);
+RASQAL_API
+raptor_sequence* rasqal_graph_pattern_get_sub_graph_pattern_sequence(rasqal_graph_pattern* graph_pattern);
+RASQAL_API
+rasqal_graph_pattern* rasqal_graph_pattern_get_sub_graph_pattern(rasqal_graph_pattern* graph_pattern, int idx);
+RASQAL_API
+rasqal_graph_pattern_operator rasqal_graph_pattern_get_operator(rasqal_graph_pattern* graph_pattern);
+RASQAL_API
+const char* rasqal_graph_pattern_operator_as_string(rasqal_graph_pattern_operator op);
+RASQAL_API
+void rasqal_graph_pattern_print(rasqal_graph_pattern* gp, FILE* fh);
+RASQAL_API RASQAL_DEPRECATED
+int rasqal_graph_pattern_add_constraint(rasqal_graph_pattern* gp, rasqal_expression* expr);
+RASQAL_API RASQAL_DEPRECATED
+raptor_sequence* rasqal_graph_pattern_get_constraint_sequence(rasqal_graph_pattern* gp);
+RASQAL_API RASQAL_DEPRECATED
+rasqal_expression* rasqal_graph_pattern_get_constraint(rasqal_graph_pattern* gp, int idx);
+RASQAL_API
+int rasqal_graph_pattern_set_filter_expression(rasqal_graph_pattern* gp, rasqal_expression* expr);
+RASQAL_API
+rasqal_expression* rasqal_graph_pattern_get_filter_expression(rasqal_graph_pattern* gp);
+RASQAL_API
+int rasqal_graph_pattern_visit(rasqal_query* query, rasqal_graph_pattern *gp, rasqal_graph_pattern_visit_fn fn, void* user_data);
+RASQAL_API
+int rasqal_graph_pattern_get_index(rasqal_graph_pattern* gp);
+
+/* Utility methods */
+RASQAL_API
+const char* rasqal_query_verb_as_string(rasqal_query_verb verb);
+RASQAL_API
+void rasqal_query_print(rasqal_query* query, FILE* fh);
+
+/* Query */
+RASQAL_API
+int rasqal_query_prepare(rasqal_query* query, const unsigned char *query_string, raptor_uri *base_uri);
+RASQAL_API
+rasqal_query_results* rasqal_query_execute(rasqal_query* query);
+
+RASQAL_API
+void* rasqal_query_get_user_data(rasqal_query* query);
+RASQAL_API
+void rasqal_query_set_user_data(rasqal_query* query, void *user_data);
+
+/* query results */
+RASQAL_API
+void rasqal_free_query_results(rasqal_query_results *query_results);
+
+RASQAL_API
+rasqal_query* rasqal_query_results_get_query(rasqal_query_results* query_results);
+
+/* Bindings result format */
+RASQAL_API
+int rasqal_query_results_is_bindings(rasqal_query_results *query_results);
+RASQAL_API
+int rasqal_query_results_get_count(rasqal_query_results *query_results);
+RASQAL_API
+int rasqal_query_results_next(rasqal_query_results *query_results);
+RASQAL_API
+int rasqal_query_results_finished(rasqal_query_results *query_results);
+RASQAL_API
+int rasqal_query_results_get_bindings(rasqal_query_results *query_results, const unsigned char ***names, rasqal_literal ***values);
+RASQAL_API
+rasqal_literal* rasqal_query_results_get_binding_value(rasqal_query_results *query_results, int offset);
+RASQAL_API
+const unsigned char* rasqal_query_results_get_binding_name(rasqal_query_results *query_results, int offset);
+RASQAL_API
+rasqal_literal* rasqal_query_results_get_binding_value_by_name(rasqal_query_results *query_results, const unsigned char *name);
+RASQAL_API
+int rasqal_query_results_get_bindings_count(rasqal_query_results *query_results);
+
+/* Boolean result format */
+RASQAL_API
+int rasqal_query_results_is_boolean(rasqal_query_results *query_results);
+RASQAL_API
+int rasqal_query_results_get_boolean(rasqal_query_results *query_results);
+
+/* Graph result format */
+RASQAL_API
+int rasqal_query_results_is_graph(rasqal_query_results *query_results);
+RASQAL_API
+raptor_statement* rasqal_query_results_get_triple(rasqal_query_results *query_results);
+RASQAL_API
+int rasqal_query_results_next_triple(rasqal_query_results *query_results);
+
+/* Syntax result format */
+RASQAL_API
+int rasqal_query_results_is_syntax(rasqal_query_results* query_results);
+
+RASQAL_API
+int rasqal_query_results_write(raptor_iostream *iostr, rasqal_query_results *results, raptor_uri *format_uri, raptor_uri *base_uri);
+RASQAL_API
+int rasqal_query_results_read(raptor_iostream *iostr, rasqal_query_results *results, raptor_uri *format_uri, raptor_uri *base_uri);
+
+
+/**
+ * RASQAL_QUERY_RESULTS_FORMAT_FLAG_READER:
+ *
+ * Flag for rasqal_query_results_formats_enumerate() to get query results formats that can be read.
+ */
+#define RASQAL_QUERY_RESULTS_FORMAT_FLAG_READER 1
+
+/**
+ * RASQAL_QUERY_RESULTS_FORMAT_FLAG_WRITER:
+ *
+ * Flag for rasqal_query_results_formats_enumerate() to get query results formats that can be written.
+ */
+#define RASQAL_QUERY_RESULTS_FORMAT_FLAG_WRITER 2
+
+RASQAL_API
+int rasqal_query_results_formats_enumerate(rasqal_world* world, unsigned int counter, const char **name, const char **label, const unsigned char **uri_string, const char **mime_type, int* flags);
+RASQAL_API
+int rasqal_query_results_formats_check(rasqal_world* world, const char *name, raptor_uri* uri, const char *mime_type);
+RASQAL_API
+rasqal_query_results_formatter* rasqal_new_query_results_formatter(rasqal_world* world, const char *name, raptor_uri* format_uri);
+RASQAL_API
+rasqal_query_results_formatter* rasqal_new_query_results_formatter_by_mime_type(rasqal_world* world, const char *mime_type);
+RASQAL_API
+void rasqal_free_query_results_formatter(rasqal_query_results_formatter* formatter);
+RASQAL_API
+int rasqal_query_results_formatter_write(raptor_iostream *iostr, rasqal_query_results_formatter* formatter, rasqal_query_results* results, raptor_uri *base_uri);
+RASQAL_API
+int rasqal_query_results_formatter_read(rasqal_world* world, raptor_iostream *iostr, rasqal_query_results_formatter* formatter, rasqal_query_results* results, raptor_uri *base_uri);
+RASQAL_API
+const char* rasqal_query_results_formatter_get_mime_type(rasqal_query_results_formatter *formatter);
+
+RASQAL_API
+int rasqal_query_iostream_write_escaped_counted_string(rasqal_query* query, raptor_iostream* iostr, const unsigned char* string, size_t len);
+RASQAL_API
+unsigned char* rasqal_query_escape_counted_string(rasqal_query* query, const unsigned char *string, size_t len, size_t* output_len_p);
+
+
+/* Data graph class */
+RASQAL_API
+rasqal_data_graph* rasqal_new_data_graph(rasqal_world* world, raptor_uri* uri, raptor_uri* name_uri, int flags);
+RASQAL_API
+void rasqal_free_data_graph(rasqal_data_graph* dg);
+RASQAL_API
+void rasqal_data_graph_print(rasqal_data_graph* dg, FILE* fh);
+
+
+/**
+ * rasqal_compare_flags:
+ * @RASQAL_COMPARE_NOCASE: String comparisons are case independent.
+ * @RASQAL_COMPARE_XQUERY: XQuery comparsion rules apply.
+ * @RASQAL_COMPARE_RDF:    RDF Term comparsion rules apply.
+ * @RASQAL_COMPARE_URI:    Allow comparison of URIs
+ *
+ * Flags for rasqal_expression_evaluate() or rasqal_literal_compare().
+ */
+typedef enum {
+  RASQAL_COMPARE_NOCASE = 1,
+  RASQAL_COMPARE_XQUERY = 2,
+  RASQAL_COMPARE_RDF    = 4,
+  RASQAL_COMPARE_URI    = 8
+} rasqal_compare_flags;
+
+
+/* Expression class */
+RASQAL_API
+rasqal_expression* rasqal_new_0op_expression(rasqal_world* world, rasqal_op op);
+RASQAL_API
+rasqal_expression* rasqal_new_1op_expression(rasqal_world* world, rasqal_op op, rasqal_expression* arg);
+RASQAL_API
+rasqal_expression* rasqal_new_2op_expression(rasqal_world* world, rasqal_op op, rasqal_expression* arg1, rasqal_expression* arg2);
+RASQAL_API
+rasqal_expression* rasqal_new_3op_expression(rasqal_world* world, rasqal_op op, rasqal_expression* arg1,  rasqal_expression* arg2, rasqal_expression* arg3);
+RASQAL_API
+rasqal_expression* rasqal_new_string_op_expression(rasqal_world* world, rasqal_op op, rasqal_expression* arg1, rasqal_literal* literal);
+RASQAL_API
+rasqal_expression* rasqal_new_literal_expression(rasqal_world* world, rasqal_literal* literal);
+RASQAL_API
+rasqal_expression* rasqal_new_function_expression(rasqal_world* world, raptor_uri* name, raptor_sequence* args);
+RASQAL_API
+rasqal_expression* rasqal_new_cast_expression(rasqal_world* world, raptor_uri* name, rasqal_expression *value);
+RASQAL_API
+rasqal_expression* rasqal_new_expression_from_expression(rasqal_expression* e);
+
+RASQAL_API
+void rasqal_free_expression(rasqal_expression* e);
+RASQAL_API
+void rasqal_expression_print_op(rasqal_expression* e, FILE* fh);
+RASQAL_API
+void rasqal_expression_print(rasqal_expression* e, FILE* fh);
+RASQAL_API
+rasqal_literal* rasqal_expression_evaluate_v2(rasqal_world *world, raptor_locator *locator, rasqal_expression* e, int flags);
+RASQAL_API RASQAL_DEPRECATED
+rasqal_literal* rasqal_expression_evaluate(rasqal_query* query, rasqal_expression* e, int flags);
+
+/**
+ * rasqal_expression_visit_fn:
+ * @user_data: user data passed in with rasqal_expression_visit()
+ * @e: current expression
+ *
+ * User function to visit an expression and operate on it with
+ * rasqal_expression_visit()
+ *
+ * Return value: 0 to truncate the visit
+ */
+typedef int (*rasqal_expression_visit_fn)(void *user_data, rasqal_expression *e);
+RASQAL_API
+int rasqal_expression_visit(rasqal_expression* e, rasqal_expression_visit_fn fn, void *user_data);
+
+
+/* Literal class */
+RASQAL_API
+rasqal_literal* rasqal_new_integer_literal(rasqal_world* world, rasqal_literal_type type, int integer);
+RASQAL_API
+rasqal_literal* rasqal_new_typed_literal(rasqal_world* world, rasqal_literal_type type, const unsigned char* string);
+RASQAL_API
+rasqal_literal* rasqal_new_double_literal(rasqal_world* world, double d);
+RASQAL_API
+rasqal_literal* rasqal_new_float_literal(rasqal_world* world, float f);
+RASQAL_API
+rasqal_literal* rasqal_new_uri_literal(rasqal_world* world, raptor_uri* uri);
+RASQAL_API
+rasqal_literal* rasqal_new_pattern_literal(rasqal_world* world, const unsigned char *pattern, const char *flags);
+RASQAL_API
+rasqal_literal* rasqal_new_string_literal(rasqal_world* world, const unsigned char *string, const char *language, raptor_uri *datatype, const unsigned char *datatype_qname);
+RASQAL_API
+rasqal_literal* rasqal_new_simple_literal(rasqal_world* world, rasqal_literal_type type, const unsigned char *string);
+RASQAL_API
+rasqal_literal* rasqal_new_boolean_literal(rasqal_world* world, int value);
+RASQAL_API
+rasqal_literal* rasqal_new_variable_literal(rasqal_world* world, rasqal_variable *variable);
+RASQAL_API
+rasqal_literal* rasqal_new_decimal_literal(rasqal_world* world, const unsigned char *string);
+RASQAL_API
+rasqal_literal* rasqal_new_decimal_literal_from_decimal(rasqal_world* world, const unsigned char *string, rasqal_xsd_decimal* decimal);
+
+RASQAL_API
+rasqal_literal* rasqal_new_literal_from_literal(rasqal_literal* l);
+RASQAL_API
+void rasqal_free_literal(rasqal_literal* l);
+RASQAL_API
+void rasqal_literal_print(rasqal_literal* l, FILE* fh);
+RASQAL_API
+void rasqal_literal_print_type(rasqal_literal* l, FILE* fh);
+RASQAL_API
+rasqal_variable* rasqal_literal_as_variable(rasqal_literal* l);
+RASQAL_API
+const unsigned char* rasqal_literal_as_string(rasqal_literal* l);
+RASQAL_API
+const unsigned char* rasqal_literal_as_string_flags(rasqal_literal* l, int flags, int *error);
+RASQAL_API
+rasqal_literal* rasqal_literal_as_node(rasqal_literal* l);
+RASQAL_API
+raptor_uri* rasqal_literal_datatype(rasqal_literal* l);
+RASQAL_API
+rasqal_literal* rasqal_literal_value(rasqal_literal* l);
+
+RASQAL_API
+int rasqal_literal_compare(rasqal_literal* l1, rasqal_literal* l2, int flags, int *error);
+RASQAL_API
+int rasqal_literal_equals(rasqal_literal* l1, rasqal_literal* l2);
+
+RASQAL_API
+rasqal_prefix* rasqal_new_prefix(rasqal_world* world, const unsigned char* prefix, raptor_uri* uri);
+RASQAL_API
+void rasqal_free_prefix(rasqal_prefix* p);
+RASQAL_API
+void rasqal_prefix_print(rasqal_prefix* p, FILE* fh);
+
+/* Triple class */
+RASQAL_API
+rasqal_triple* rasqal_new_triple(rasqal_literal* subject, rasqal_literal* predicate, rasqal_literal* object);
+RASQAL_API
+rasqal_triple* rasqal_new_triple_from_triple(rasqal_triple* t);
+RASQAL_API
+void rasqal_free_triple(rasqal_triple* t);
+RASQAL_API
+void rasqal_triple_print(rasqal_triple* t, FILE* fh);
+RASQAL_API
+void rasqal_triple_set_origin(rasqal_triple* t, rasqal_literal *l);
+RASQAL_API
+rasqal_literal* rasqal_triple_get_origin(rasqal_triple* t);
+
+/* Variable class */
+RASQAL_API
+rasqal_variable* rasqal_new_variable_typed(rasqal_query* rq, rasqal_variable_type type, unsigned char *name, rasqal_literal *value);
+RASQAL_API
+rasqal_variable* rasqal_new_variable(rasqal_query* rq, unsigned char *name, rasqal_literal *value);
+RASQAL_API
+rasqal_variable* rasqal_new_variable_from_variable(rasqal_variable* v);
+RASQAL_API
+void rasqal_free_variable(rasqal_variable* v);
+RASQAL_API
+void rasqal_variable_print(rasqal_variable* v, FILE* fh);
+RASQAL_API
+void rasqal_variable_set_value(rasqal_variable* v, rasqal_literal* l);
+
+/* memory functions */
+RASQAL_API
+void rasqal_free_memory(void *ptr);
+RASQAL_API
+void* rasqal_alloc_memory(size_t size);
+RASQAL_API
+void* rasqal_calloc_memory(size_t nmemb, size_t size);
+
+
+/* decimal functions */
+RASQAL_API
+rasqal_xsd_decimal* rasqal_new_xsd_decimal(void);
+RASQAL_API
+void rasqal_free_xsd_decimal(rasqal_xsd_decimal* dec);
+RASQAL_API
+int rasqal_xsd_decimal_set_string(rasqal_xsd_decimal* dec, const char* string);
+RASQAL_API
+double rasqal_xsd_decimal_get_double(rasqal_xsd_decimal* dec);
+RASQAL_API
+char* rasqal_xsd_decimal_as_string(rasqal_xsd_decimal* dec);
+RASQAL_API
+char* rasqal_xsd_decimal_as_counted_string(rasqal_xsd_decimal* dec, size_t* len_p);
+RASQAL_API
+int rasqal_xsd_decimal_set_long(rasqal_xsd_decimal* dec, long l);
+RASQAL_API
+int rasqal_xsd_decimal_set_double(rasqal_xsd_decimal* dec, double d);
+RASQAL_API
+int rasqal_xsd_decimal_print(rasqal_xsd_decimal* dec, FILE* stream);
+RASQAL_API
+int rasqal_xsd_decimal_add(rasqal_xsd_decimal* result, rasqal_xsd_decimal* a, rasqal_xsd_decimal* b);
+RASQAL_API
+int rasqal_xsd_decimal_subtract(rasqal_xsd_decimal* result, rasqal_xsd_decimal* a, rasqal_xsd_decimal* b);
+RASQAL_API
+int rasqal_xsd_decimal_multiply(rasqal_xsd_decimal* result, rasqal_xsd_decimal* a, rasqal_xsd_decimal* b);
+RASQAL_API
+int rasqal_xsd_decimal_divide(rasqal_xsd_decimal* result, rasqal_xsd_decimal* a, rasqal_xsd_decimal* b);
+RASQAL_API
+int rasqal_xsd_decimal_negate(rasqal_xsd_decimal* result, rasqal_xsd_decimal* a);
+RASQAL_API
+int rasqal_xsd_decimal_compare(rasqal_xsd_decimal* a, rasqal_xsd_decimal* b);
+RASQAL_API
+int rasqal_xsd_decimal_equals(rasqal_xsd_decimal* a, rasqal_xsd_decimal* b);
+RASQAL_API
+int rasqal_xsd_decimal_is_zero(rasqal_xsd_decimal* d);
+
+/* rasqal_engine.c */
+
+/**
+ * rasqal_triple_parts:
+ * @RASQAL_TRIPLE_SUBJECT: Subject present in a triple.
+ * @RASQAL_TRIPLE_PREDICATE: Predicate present in a triple.
+ * @RASQAL_TRIPLE_OBJECT: Object present in a triple.
+ * @RASQAL_TRIPLE_ORIGIN: Origin/graph present in a triple.
+ * @RASQAL_TRIPLE_GRAPH:  Alias for RASQAL_TRIPLE_ORIGIN
+ * @RASQAL_TRIPLE_SPO: Subject, Predicate and Object present in a triple.
+ * @RASQAL_TRIPLE_SPOG: Subject, Predicate, Object, Graph present in a triple.
+ *
+ * Flags for parts of a triple.
+ */
+typedef enum {
+  RASQAL_TRIPLE_SUBJECT  = 1,
+  RASQAL_TRIPLE_PREDICATE= 2,
+  RASQAL_TRIPLE_OBJECT   = 4,
+  RASQAL_TRIPLE_ORIGIN   = 8,
+  RASQAL_TRIPLE_GRAPH    = RASQAL_TRIPLE_ORIGIN,
+  RASQAL_TRIPLE_SPO      = RASQAL_TRIPLE_SUBJECT | RASQAL_TRIPLE_PREDICATE | RASQAL_TRIPLE_OBJECT,
+  RASQAL_TRIPLE_SPOG     = RASQAL_TRIPLE_SPO | RASQAL_TRIPLE_GRAPH
+} rasqal_triple_parts;
+
+
+
+/**
+ * rasqal_triples_match:
+ * @user_data: User data pointer for factory methods.
+ * @bind_match: The [4]array (s,p,o,origin) bindings against the current triple match only touching triple parts given. Returns parts that were bound or 0 on failure.
+ * @next_match: Move to next match.
+ * @is_end: Check for end of triple match - return non-0 if is end.
+ * @finish: Finish triples match and destroy any allocated memory.
+ * @world: rasqal_world object
+ * 
+ * Triples match structure as initialised by #rasqal_triples_source
+ * method init_triples_match.
+ */
+struct rasqal_triples_match_s {
+  void *user_data;
+
+  rasqal_triple_parts (*bind_match)(struct rasqal_triples_match_s* rtm, void *user_data, rasqal_variable *bindings[4], rasqal_triple_parts parts);
+
+  void (*next_match)(struct rasqal_triples_match_s* rtm, void *user_data);
+
+  int (*is_end)(struct rasqal_triples_match_s* rtm, void *user_data);
+
+  void (*finish)(struct rasqal_triples_match_s* rtm, void *user_data);
+
+  rasqal_world *world;
+};
+typedef struct rasqal_triples_match_s rasqal_triples_match;
+
+/**
+ * rasqal_triple_meta:
+ * @bindings: Variable bindings for this triple+origin to set.
+ * @triples_match: The matcher that is setting these bindings.
+ * @context: Context data used by the matcher.
+ * @parts: Parts of the triple to match/bindings to set.
+ * @is_exact: non-0 if all parts of the triple are given
+ * @executed: non-0 if the triple pattern has been fully executed
+ *
+ * Triple matching metadata for one triple pattern.
+ */
+typedef struct {
+  /* triple (subject, predicate, object) and origin */
+  rasqal_variable* bindings[4];
+
+  rasqal_triples_match *triples_match;
+
+  void *context;
+
+  rasqal_triple_parts parts;
+
+  /* non-0 if the associated triple pattern contains no variables */
+  int is_exact;
+
+  /* non-0 if the triple pattern has been fully executed */
+  int executed;
+} rasqal_triple_meta;
+
+
+/**
+ * rasqal_triples_source:
+ * @query: Source for this query.
+ * @user_data: Context user data passed into the factory methods.
+ * @init_triples_match: Factory method to initalise a new #rasqal_triples_match.
+ * @triple_present: Factory method to return presence or absence of a complete triple.
+ * @free_triples_source: Factory method to deallocate resources.
+ *
+ * Triples source as initialised by a #rasqal_triples_source_factory.
+ */
+struct rasqal_triples_source_s {
+  rasqal_query* query;
+
+  void *user_data;
+
+  int (*init_triples_match)(rasqal_triples_match* rtm, struct rasqal_triples_source_s* rts, void *user_data, rasqal_triple_meta *m, rasqal_triple *t);
+
+  int (*triple_present)(struct rasqal_triples_source_s* rts, void *user_data, rasqal_triple *t);
+
+  void (*free_triples_source)(void *user_data);
+};
+typedef struct rasqal_triples_source_s rasqal_triples_source;
+
+
+/**
+ * rasqal_triples_source_factory:
+ * @user_data: User data for triples_source_factory.
+ * @user_data_size: Size Of @user_data for new_triples_source.
+ * @new_triples_source: Create a new triples source - returns non-zero on failure &lt; 0 is a 'no rdf data error', &gt; 0 is an unspecified error..
+ *
+ * A factory that initialises #rasqal_triples_source structures
+ * to returning matches to a triple pattern.
+ */
+typedef struct {
+  void *user_data;
+  size_t user_data_size;
+
+  int (*new_triples_source)(rasqal_query* query, void *factory_user_data, void *user_data, rasqal_triples_source* rts);
+} rasqal_triples_source_factory;
+  
+
+/* set the triples_source_factory */
+RASQAL_API
+void rasqal_set_triples_source_factory(rasqal_world* world, void (*register_fn)(rasqal_triples_source_factory *factory), void* user_data);
+
+
+
+/* The info below is solely for gtk-doc - ignore it */
+
+/**
+ * RASQAL_QUERY_RESULTS_FORMATTER_DECLARED:
+ *
+ * Internal
+ */
+
+/**
+ * RASQAL_WORLD_DECLARED:
+ *
+ * Internal
+ */
+
+/**
+ * rasqal_expression_s:
+ * @usage: Internal
+ * @op: Internal
+ * @arg1: Internal
+ * @arg2: Internal
+ * @arg3: Internal
+ * @literal: Internal
+ * @value: Internal
+ * @name: Internal
+ * @args: Internal
+ *
+ * Internal - see #rasqal_expression.
+ *
+ */
+
+/**
+ * bind_match:
+ * @rtm: triples match context
+ * @user_data: user data
+ * @bindings: variable binding for parts of triple (s, p, o, g)
+ * @parts: parts of triple to match
+ *
+ * Internal - see #rasqal_triples_match
+ *
+ * Return value: match parts
+*/
+
+/**
+ * next_match:
+ * @rtm: triples match context
+ * @user_data: user data
+ * 
+ * Internal - see #rasqal_triples_match
+ */
+
+/**
+ * is_end:
+ * @rtm: triples match context
+ * @user_data: user data
+ *
+ * Internal - see #rasqal_triples_match
+ *
+ * Return value: non-0 if end of match
+ */
+
+/**
+ * finish:
+ * @rtm: triples match context
+ * @user_data: user data
+ *
+ * Internal - see #rasqal_triples_match
+ */
+
+/**
+ * init_triples_match:
+ * @rtm: triples match context
+ * @rts: triples match source
+ * @user_data: user data
+ * @m: triple meta
+ * @t: triple
+ *
+ * Internal - see #rasqal_triples_source
+ *
+ * Return value: non-0 on failure
+ */
+
+/**
+ * triple_present:
+ * @rts: triples match source
+ * @user_data: user data
+ * @t: triple to test for presence
+ *
+ * Internal - see #rasqal_triples_source
+ *
+ * Return value: non-0 on failure
+ */
+
+/**
+ * free_triples_source:
+ * @user_data: user data
+ *
+ * Internal - see #rasqal_triples_source
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/rasqal/rasqal_algebra.c b/src/rasqal/rasqal_algebra.c
new file mode 100644
index 0000000..6c25c65
--- /dev/null
+++ b/src/rasqal/rasqal_algebra.c
@@ -0,0 +1,1403 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_algebra.c - Rasqal algebra class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#ifndef STANDALONE
+
+static rasqal_algebra_node* rasqal_algebra_graph_pattern_to_algebra(rasqal_query* query, rasqal_graph_pattern* gp);
+
+/*
+ * rasqal_new_algebra_node:
+ * @query: #rasqal_algebra_node query object
+ * @op: enum #rasqal_algebra_operator operator
+ *
+ * INTERNAL - Create a new algebra object.
+ * 
+ * Return value: a new #rasqal_algebra object or NULL on failure
+ **/
+static rasqal_algebra_node*
+rasqal_new_algebra_node(rasqal_query* query, rasqal_algebra_node_operator op)
+{
+  rasqal_algebra_node* node;
+
+  if(!query)
+    return NULL;
+  
+  node = (rasqal_algebra_node*)RASQAL_CALLOC(rasqal_algebra, 1, 
+                                             sizeof(rasqal_algebra_node));
+  if(!node)
+    return NULL;
+
+  node->op = op;
+  node->query = query;
+  return node;
+}
+
+
+/*
+ * rasqal_new_filter_algebra_node:
+ * @query: #rasqal_query query object
+ * @expr: FILTER expression
+ * @node: algebra node being filtered
+ *
+ * INTERNAL - Create a new algebra node for an expression over a node
+ * 
+ * Return value: a new #rasqal_algebra_node object or NULL on failure
+ **/
+rasqal_algebra_node*
+rasqal_new_filter_algebra_node(rasqal_query* query,
+                               rasqal_expression* expr,
+                               rasqal_algebra_node* node)
+{
+  rasqal_algebra_node* new_node;
+
+  if(!query || !expr)
+    return NULL;
+  
+  new_node = rasqal_new_algebra_node(query, RASQAL_ALGEBRA_OPERATOR_FILTER);
+  if(!new_node)
+    return NULL;
+
+  new_node->expr = expr;
+  new_node->node1 = node;
+
+  return new_node;
+}
+
+
+/*
+ * rasqal_new_triples_algebra_node:
+ * @query: #rasqal_query query object
+ * @triples: triples sequence (SHARED) (or NULL for empty BGP)
+ * @start_column: first triple
+ * @end_column: last triple
+ *
+ * INTERNAL - Create a new algebra node for Basic Graph Pattern
+ * 
+ * Return value: a new #rasqal_algebra_node object or NULL on failure
+ **/
+rasqal_algebra_node*
+rasqal_new_triples_algebra_node(rasqal_query* query,
+                                raptor_sequence* triples,
+                                int start_column, int end_column)
+{
+  rasqal_algebra_node* node;
+
+  if(!query)
+    return NULL;
+  
+  node = rasqal_new_algebra_node(query, RASQAL_ALGEBRA_OPERATOR_BGP);
+  if(!node)
+    return NULL;
+
+  node->triples = triples;
+  if(!triples) {
+    start_column= -1;
+    end_column= -1;
+  }
+  node->start_column = start_column;
+  node->end_column = end_column;
+
+  return node;
+}
+
+
+/*
+ * rasqal_new_empty_algebra_node:
+ * @query: #rasqal_query query object
+ *
+ * INTERNAL - Create a new empty algebra node
+ * 
+ * Return value: a new #rasqal_algebra_node object or NULL on failure
+ **/
+rasqal_algebra_node*
+rasqal_new_empty_algebra_node(rasqal_query* query)
+{
+  rasqal_algebra_node* node;
+
+  if(!query)
+    return NULL;
+  
+  node = rasqal_new_algebra_node(query, RASQAL_ALGEBRA_OPERATOR_BGP);
+  if(!node)
+    return NULL;
+
+  node->triples = NULL;
+  node->start_column= -1;
+  node->end_column= -1;
+
+  return node;
+}
+
+
+/*
+ * rasqal_new_2op_algebra_node:
+ * @query: #rasqal_query query object
+ * @op: operator 
+ * @node1: 1st algebra node
+ * @node2: 2nd algebra node (pr NULL for #RASQAL_ALGEBRA_OPERATOR_TOLIST only)
+ *
+ * INTERNAL - Create a new algebra node for 1 or 2 graph patterns
+ *
+ * node1 and ndoe2 become owned by the new node
+ *
+ * Return value: a new #rasqal_algebra_node object or NULL on failure
+ **/
+rasqal_algebra_node*
+rasqal_new_2op_algebra_node(rasqal_query* query,
+                            rasqal_algebra_node_operator op,
+                            rasqal_algebra_node* node1,
+                            rasqal_algebra_node* node2)
+{
+  rasqal_algebra_node* node;
+
+  if(!query || !node1)
+    goto fail;
+  if(op != RASQAL_ALGEBRA_OPERATOR_TOLIST && !node2)
+    goto fail;
+  
+  node = rasqal_new_algebra_node(query, op);
+  if(node) {
+    node->node1 = node1;
+    node->node2 = node2;
+    
+    return node;
+  }
+
+  fail:
+  if(node1)
+    rasqal_free_algebra_node(node1);
+  if(node2)
+    rasqal_free_algebra_node(node2);
+  return NULL;
+}
+
+
+/*
+ * rasqal_new_leftjoin_algebra_node:
+ * @query: #rasqal_query query object
+ * @node1: 1st algebra node
+ * @node2: 2nd algebra node
+ * @expr: expression
+ *
+ * INTERNAL - Create a new LEFTJOIN algebra node for 2 graph patterns
+ * 
+ * node1 and ndoe2 become owned by the new node
+ *
+ * Return value: a new #rasqal_algebra_node object or NULL on failure
+ **/
+rasqal_algebra_node*
+rasqal_new_leftjoin_algebra_node(rasqal_query* query,
+                                 rasqal_algebra_node* node1,
+                                 rasqal_algebra_node* node2,
+                                 rasqal_expression* expr)
+{
+  rasqal_algebra_node* node;
+
+  if(!query || !node1 || !node2 || !expr)
+    goto fail;
+
+  node = rasqal_new_algebra_node(query, RASQAL_ALGEBRA_OPERATOR_LEFTJOIN);
+  if(node) {
+    node->node1 = node1;
+    node->node2 = node2;
+    node->expr = expr;
+    
+    return node;
+  }
+
+  fail:
+  if(node1)
+    rasqal_free_algebra_node(node1);
+  if(node2)
+    rasqal_free_algebra_node(node2);
+  if(expr)
+    rasqal_free_expression(expr);
+  return NULL;
+}
+
+
+/*
+ * rasqal_new_orderby_algebra_node:
+ * @query: #rasqal_query query object
+ * @node1: inner algebra node
+ * @seq: sequence of order condition #rasqal_expression
+ *
+ * INTERNAL - Create a new ORDERBY algebra node for a sequence of order conditions
+ * 
+ * #node and #seq become owned by the new node
+ *
+ * Return value: a new #rasqal_algebra_node object or NULL on failure
+ **/
+rasqal_algebra_node*
+rasqal_new_orderby_algebra_node(rasqal_query* query,
+                                rasqal_algebra_node* node1,
+                                raptor_sequence* seq)
+{
+  rasqal_algebra_node* node;
+
+  if(!query || !node1 || !seq || !raptor_sequence_size(seq))
+    goto fail;
+
+  node = rasqal_new_algebra_node(query, RASQAL_ALGEBRA_OPERATOR_ORDERBY);
+  if(node) {
+    node->node1 = node1;
+    node->seq = seq;
+    
+    return node;
+  }
+
+  fail:
+  if(node1)
+    rasqal_free_algebra_node(node1);
+  if(seq)
+    raptor_free_sequence(seq);
+
+  return NULL;
+}
+
+
+/*
+ * rasqal_new_project_algebra_node:
+ * @query: #rasqal_query query object
+ * @node1: inner algebra node
+ * @vars_seq: sequence of variables
+ *
+ * INTERNAL - Create a new PROJECT algebra node for a sequence of variables over an inner node
+ * 
+ * The inputs @node and @seq become owned by the new node
+ *
+ * Return value: a new #rasqal_algebra_node object or NULL on failure
+ **/
+rasqal_algebra_node*
+rasqal_new_project_algebra_node(rasqal_query* query,
+                                rasqal_algebra_node* node1,
+                                raptor_sequence* vars_seq)
+{
+  rasqal_algebra_node* node;
+
+  if(!query || !node1 || !vars_seq)
+    goto fail;
+
+  node = rasqal_new_algebra_node(query, RASQAL_ALGEBRA_OPERATOR_PROJECT);
+  if(node) {
+    node->node1 = node1;
+    node->vars_seq = vars_seq;
+    
+    return node;
+  }
+
+  fail:
+  if(node1)
+    rasqal_free_algebra_node(node1);
+  if(vars_seq)
+    raptor_free_sequence(vars_seq);
+
+  return NULL;
+}
+
+
+/*
+ * rasqal_free_algebra_node:
+ * @gp: #rasqal_algebra_node object
+ *
+ * INTERNAL - Free an algebra node object.
+ * 
+ **/
+void
+rasqal_free_algebra_node(rasqal_algebra_node* node)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(node, rasqal_algebra_node);
+
+  /* node->triples is SHARED with the query - not freed here */
+
+  if(node->node1)
+    rasqal_free_algebra_node(node->node1);
+
+  if(node->node2)
+    rasqal_free_algebra_node(node->node2);
+
+  if(node->expr)
+    rasqal_free_expression(node->expr);
+
+  if(node->seq)
+    raptor_free_sequence(node->seq);
+
+  if(node->vars_seq)
+    raptor_free_sequence(node->vars_seq);
+
+  RASQAL_FREE(rasqal_algebra, node);
+}
+
+
+/**
+ * rasqal_algebra_node_get_operator:
+ * @algebra_node: #rasqal_algebra_node algebra node object
+ *
+ * Get the algebra node operator .
+ * 
+ * The operator for the given algebra node. See also
+ * rasqal_algebra_node_operator_as_string().
+ *
+ * Return value: algebra node operator
+ **/
+rasqal_algebra_node_operator
+rasqal_algebra_node_get_operator(rasqal_algebra_node* node)
+{
+  return node->op;
+}
+
+
+static const char* const rasqal_algebra_node_operator_labels[RASQAL_ALGEBRA_OPERATOR_LAST+1] = {
+  "UNKNOWN",
+  "BGP",
+  "Filter",
+  "Join",
+  "Diff",
+  "LeftJoin",
+  "Union",
+  "ToList",
+  "OrderBy",
+  "Project",
+  "Distinct",
+  "Reduced",
+  "Slice"
+};
+
+
+/**
+ * rasqal_algebra_node_operator_as_string:
+ * @op: the #rasqal_algebra_node_operator verb of the query
+ *
+ * Get a string for the query verb.
+ * 
+ * Return value: pointer to a shared string label for the query verb
+ **/
+const char*
+rasqal_algebra_node_operator_as_string(rasqal_algebra_node_operator op)
+{
+  if(op <= RASQAL_ALGEBRA_OPERATOR_UNKNOWN || 
+     op > RASQAL_ALGEBRA_OPERATOR_LAST)
+    op = RASQAL_ALGEBRA_OPERATOR_UNKNOWN;
+
+  return rasqal_algebra_node_operator_labels[(int)op];
+}
+  
+
+
+#define SPACES_LENGTH 80
+static const char spaces[SPACES_LENGTH+1] = "                                                                                ";
+
+static void
+rasqal_algebra_write_indent(raptor_iostream *iostr, int indent) 
+{
+  while(indent > 0) {
+    int sp = (indent > SPACES_LENGTH) ? SPACES_LENGTH : indent;
+    raptor_iostream_write_bytes(iostr, spaces, sizeof(char), sp);
+    indent -= sp;
+  }
+}
+
+static int
+rasqal_algebra_algebra_node_write_internal(rasqal_algebra_node *node, 
+                                           raptor_iostream* iostr, int indent)
+{
+  const char* op_string = rasqal_algebra_node_operator_as_string(node->op);
+  int arg_count = 0;
+  int indent_delta;
+  
+  if(node->op == RASQAL_ALGEBRA_OPERATOR_BGP && !node->triples) {
+    raptor_iostream_write_byte(iostr, 'Z');
+    return 0;
+  }
+  
+  indent_delta = strlen(op_string);
+
+  raptor_iostream_write_counted_string(iostr, op_string, indent_delta);
+  raptor_iostream_write_counted_string(iostr, "(\n", 2);
+  indent_delta++;
+  
+  indent += indent_delta;
+  rasqal_algebra_write_indent(iostr, indent);
+
+  if(node->op == RASQAL_ALGEBRA_OPERATOR_BGP) {
+    int i;
+    
+    for(i = node->start_column; i <= node->end_column; i++) {
+      rasqal_triple *t;
+      t = (rasqal_triple*)raptor_sequence_get_at(node->triples, i);
+      if(arg_count) {
+        raptor_iostream_write_counted_string(iostr, " ,\n", 3);
+        rasqal_algebra_write_indent(iostr, indent);
+      }
+      rasqal_triple_write(t, iostr);
+      arg_count++;
+    }
+  }
+  if(node->node1) {
+    if(arg_count) {
+      raptor_iostream_write_counted_string(iostr, " ,\n", 3);
+      rasqal_algebra_write_indent(iostr, indent);
+    }
+    rasqal_algebra_algebra_node_write_internal(node->node1, iostr, indent);
+    arg_count++;
+    if(node->node2) {
+      if(arg_count) {
+        raptor_iostream_write_counted_string(iostr, " ,\n", 3);
+        rasqal_algebra_write_indent(iostr, indent);
+      }
+      rasqal_algebra_algebra_node_write_internal(node->node2, iostr, indent);
+      arg_count++;
+    }
+  }
+
+  /* look for FILTER expression */
+  if(node->expr) {
+    if(arg_count) {
+      raptor_iostream_write_counted_string(iostr, " ,\n", 3);
+      rasqal_algebra_write_indent(iostr, indent);
+    }
+    rasqal_expression_write(node->expr, iostr);
+    arg_count++;
+  }
+
+  if(node->seq && node->op == RASQAL_ALGEBRA_OPERATOR_ORDERBY) {
+    int order_size = raptor_sequence_size(node->seq);
+    if(order_size) {
+      int i;
+      
+      if(arg_count) {
+        raptor_iostream_write_counted_string(iostr, " ,\n", 3);
+        rasqal_algebra_write_indent(iostr, indent);
+      }
+      raptor_iostream_write_counted_string(iostr, "Conditions([ ", 13);
+      for(i = 0; i < order_size; i++) {
+        rasqal_expression* e;
+        e = (rasqal_expression*)raptor_sequence_get_at(node->seq, i);
+        if(i > 0)
+          raptor_iostream_write_counted_string(iostr, ", ", 2);
+        rasqal_expression_write(e, iostr);
+        arg_count++;
+      }
+      raptor_iostream_write_counted_string(iostr, " ])", 3);
+    }
+  }
+
+  if(node->vars_seq && node->op == RASQAL_ALGEBRA_OPERATOR_PROJECT) {
+    int vars_size = raptor_sequence_size(node->vars_seq);
+    int i;
+      
+    if(arg_count) {
+      raptor_iostream_write_counted_string(iostr, " ,\n", 3);
+      rasqal_algebra_write_indent(iostr, indent);
+    }
+    raptor_iostream_write_counted_string(iostr, "Variables([ ", 12);
+    for(i = 0; i < vars_size; i++) {
+      rasqal_variable* v;
+      v = (rasqal_variable*)raptor_sequence_get_at(node->vars_seq, i);
+      if(i > 0)
+        raptor_iostream_write_counted_string(iostr, ", ", 2);
+      rasqal_variable_write(v, iostr);
+      arg_count++;
+    }
+    raptor_iostream_write_counted_string(iostr, " ])", 3);
+  }
+
+  if(node->op == RASQAL_ALGEBRA_OPERATOR_SLICE) {
+    if(arg_count) {
+      raptor_iostream_write_counted_string(iostr, " ,\n", 3);
+      rasqal_algebra_write_indent(iostr, indent);
+    }
+    raptor_iostream_write_string(iostr, "slice start ");
+    raptor_iostream_write_decimal(iostr, node->start);
+    raptor_iostream_write_string(iostr, " length ");
+    raptor_iostream_write_decimal(iostr, node->length);
+    raptor_iostream_write_byte(iostr, '\n');
+    arg_count++;
+  }
+
+  raptor_iostream_write_byte(iostr, '\n');
+  indent-= indent_delta;
+
+  rasqal_algebra_write_indent(iostr, indent);
+  raptor_iostream_write_byte(iostr, ')');
+
+  return 0;
+}
+
+
+int
+rasqal_algebra_algebra_node_write(rasqal_algebra_node *node, 
+                                  raptor_iostream* iostr)
+{
+  return rasqal_algebra_algebra_node_write_internal(node, iostr, 0);
+}
+  
+
+/**
+ * rasqal_algebra_node_print:
+ * @gp: the #rasqal_algebra_node object
+ * @fh: the #FILE* handle to print to
+ *
+ * Print a #rasqal_algebra_node in a debug format.
+ * 
+ * The print debug format may change in any release.
+ * 
+ **/
+void
+rasqal_algebra_node_print(rasqal_algebra_node* node, FILE* fh)
+{
+  raptor_iostream* iostr;
+
+  iostr = raptor_new_iostream_to_file_handle(fh);
+  rasqal_algebra_algebra_node_write(node, iostr);
+  raptor_free_iostream(iostr);
+}
+
+/**
+ * rasqal_algebra_node_visit:
+ * @query: #rasqal_query to operate on
+ * @node: #rasqal_algebra_node graph pattern
+ * @fn: pointer to function to apply that takes user data and graph pattern parameters
+ * @user_data: user data for applied function 
+ * 
+ * Visit a user function over a #rasqal_algebra_node
+ *
+ * If the user function @fn returns 0, the visit is truncated.
+ *
+ * Return value: 0 if the visit was truncated.
+ **/
+int
+rasqal_algebra_node_visit(rasqal_query *query,
+                          rasqal_algebra_node* node,
+                          rasqal_algebra_node_visit_fn fn,
+                          void *user_data)
+{
+  int result;
+  
+  result = fn(query, node, user_data);
+  if(result)
+    return result;
+  
+  if(node->node1) {
+    result = rasqal_algebra_node_visit(query, node->node1, fn, user_data);
+    if(result)
+      return result;
+  }
+  if(node->node2) {
+    result = rasqal_algebra_node_visit(query, node->node2, fn, user_data);
+    if(result)
+      return result;
+  }
+
+  return 0;
+}
+
+
+static rasqal_algebra_node*
+rasqal_algebra_basic_graph_pattern_to_algebra(rasqal_query* query,
+                                              rasqal_graph_pattern* gp)
+{
+  rasqal_algebra_node* node = NULL;
+  rasqal_expression* fs = NULL;
+  
+  node = rasqal_new_triples_algebra_node(query, 
+                                         rasqal_query_get_triple_sequence(query),
+                                         gp->start_column, gp->end_column);
+  if(!node)
+    goto fail;
+
+  if(gp->filter_expression) {
+    rasqal_expression* e;
+    e = rasqal_new_expression_from_expression(gp->filter_expression);
+    if(!e) {
+      RASQAL_DEBUG1("rasqal_new_expression_from_expression() failed");
+      goto fail;
+    }
+    fs = fs ? rasqal_new_2op_expression(query->world, RASQAL_EXPR_AND, fs, e) : e;
+  }
+
+  if(fs) {
+    node = rasqal_new_filter_algebra_node(query, fs, node);
+    if(!node) {
+      RASQAL_DEBUG1("rasqal_new_filter_algebra_node() failed");
+      goto fail;
+    }
+    fs = NULL; /* now owned by node */
+  }
+
+
+  return node;
+  
+  fail:
+  if(node)
+    rasqal_free_algebra_node(node);
+  if(fs)
+    rasqal_free_expression(fs);
+  
+  return node;
+}
+
+static rasqal_algebra_node*
+rasqal_algebra_union_graph_pattern_to_algebra(rasqal_query* query,
+                                              rasqal_graph_pattern* gp)
+{
+  int idx = 0;
+  rasqal_algebra_node* node = NULL;
+
+  while(1) {
+    rasqal_graph_pattern* sgp;
+    rasqal_algebra_node* gnode;
+    
+    sgp = rasqal_graph_pattern_get_sub_graph_pattern(gp, idx);
+    if(!sgp)
+      break;
+    
+    gnode = rasqal_algebra_graph_pattern_to_algebra(query, sgp);
+    if(!gnode) {
+      RASQAL_DEBUG1("rasqal_algebra_graph_pattern_to_algebra() failed");
+      goto fail;
+    }
+    
+    if(!node)
+      node = gnode;
+    else {
+      node = rasqal_new_2op_algebra_node(query, RASQAL_ALGEBRA_OPERATOR_UNION,
+                                         node, gnode);
+      if(!node) {
+        RASQAL_DEBUG1("rasqal_new_2op_algebra_node() failed");
+        goto fail;
+      }
+    }
+    
+    idx++;
+  }
+
+  return node;
+
+  fail:
+  if(node)
+    rasqal_free_algebra_node(node);
+
+  return NULL;
+}
+
+
+static rasqal_algebra_node*
+rasqal_algebra_group_graph_pattern_to_algebra(rasqal_query* query,
+                                              rasqal_graph_pattern* gp)
+{
+  int idx = 0;
+  /* Let FS := the empty set */
+  rasqal_expression* fs = NULL;
+  /* Let G := the empty pattern, Z, a basic graph pattern which
+   * is the empty set. */
+  rasqal_algebra_node* gnode = NULL;
+
+  gnode = rasqal_new_empty_algebra_node(query);
+  if(!gnode) {
+    RASQAL_DEBUG1("rasqal_new_empty_algebra_node() failed");
+    goto fail;
+  }
+
+  for(idx = 0; 1; idx++) {
+    rasqal_graph_pattern* egp;
+    egp = rasqal_graph_pattern_get_sub_graph_pattern(gp, idx);
+    if(!egp)
+      break;
+
+    if(egp->filter_expression) {
+      /* If E is of the form FILTER(expr)
+         FS := FS set-union {expr} 
+      */
+      rasqal_expression* e;
+
+      /* add all gp->conditions_sequence to FS */
+      e = rasqal_new_expression_from_expression(egp->filter_expression);
+      if(!e) {
+        RASQAL_DEBUG1("rasqal_new_expression_from_expression() failed");
+        goto fail;
+      }
+      fs = fs ? rasqal_new_2op_expression(query->world, RASQAL_EXPR_AND, fs, e) : e;
+
+      if(egp->op == RASQAL_GRAPH_PATTERN_OPERATOR_FILTER)
+        continue;
+    }
+
+    if(egp->op == RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL) {
+      /*  If E is of the form OPTIONAL{P} */
+      int sgp_idx = 0;
+      int sgp_size = raptor_sequence_size(egp->graph_patterns);
+
+      /* walk through all optionals */
+      for(sgp_idx = 0; sgp_idx < sgp_size; sgp_idx++) {
+        rasqal_graph_pattern* sgp;
+        rasqal_algebra_node* anode;
+
+        sgp = rasqal_graph_pattern_get_sub_graph_pattern(egp, sgp_idx);
+
+        /* Let A := Transform(P) */
+        anode = rasqal_algebra_graph_pattern_to_algebra(query, sgp);
+        if(!anode) {
+          RASQAL_DEBUG1("rasqal_algebra_graph_pattern_to_algebra() failed");
+          goto fail;
+        }
+        
+        if(anode->op == RASQAL_ALGEBRA_OPERATOR_FILTER) {
+          rasqal_expression* f_expr = anode->expr;
+          rasqal_algebra_node *a2node = anode->node1;
+          /* If A is of the form Filter(F, A2)
+             G := LeftJoin(G, A2, F)
+          */
+          gnode = rasqal_new_leftjoin_algebra_node(query, gnode, a2node,
+                                                   f_expr);
+          if(!gnode) {
+            RASQAL_DEBUG1("rasqal_new_leftjoin_algebra_node() failed");
+            goto fail;
+          }
+
+          anode->expr = NULL;
+          anode->node1 = NULL;
+          rasqal_free_algebra_node(anode);
+        } else  {
+          rasqal_literal *true_lit = NULL;
+          rasqal_expression *true_expr = NULL;
+
+          true_lit = rasqal_new_boolean_literal(query->world, 1);
+          if(!true_lit) {
+            RASQAL_DEBUG1("rasqal_new_boolean_literal() failed");
+            goto fail;
+          }
+          
+          true_expr = rasqal_new_literal_expression(query->world, true_lit);
+          if(!true_expr) {
+            RASQAL_DEBUG1("rasqal_new_literal_expression() failed");
+            goto fail;
+          }
+          true_lit = NULL; /* now owned by true_expr */
+
+          /* G := LeftJoin(G, A, true) */
+          gnode = rasqal_new_leftjoin_algebra_node(query, gnode, anode,
+                                                   true_expr);
+          if(!gnode) {
+            RASQAL_DEBUG1("rasqal_new_leftjoin_algebra_node() failed");
+            rasqal_free_expression(true_expr);
+            goto fail;
+          }
+
+          true_expr = NULL; /* now owned by gnode */
+        }
+      } /* end for all optional */
+    } else {
+      /* If E is any other form:*/
+      rasqal_algebra_node* anode;
+
+      /* Let A := Transform(E) */
+      anode = rasqal_algebra_graph_pattern_to_algebra(query, egp);
+      if(!anode) {
+        RASQAL_DEBUG1("rasqal_algebra_graph_pattern_to_algebra() failed");
+        goto fail;
+      }
+
+      /* G := Join(G, A) */
+      gnode = rasqal_new_2op_algebra_node(query, RASQAL_ALGEBRA_OPERATOR_JOIN,
+                                          gnode, anode);
+      if(!gnode) {
+        RASQAL_DEBUG1("rasqal_new_2op_algebra_node() failed");
+        goto fail;
+      }
+    }
+
+  }
+
+  /*
+    If FS is not empty:
+    Let X := Conjunction of expressions in FS
+    G := Filter(X, G)
+    
+    The result is G.
+  */
+  if(fs) {
+    gnode = rasqal_new_filter_algebra_node(query, fs, gnode);
+    if(!gnode) {
+      RASQAL_DEBUG1("rasqal_new_filter_algebra_node() failed");
+      goto fail;
+    }
+    fs = NULL; /* now owned by gnode */
+  }
+
+  if(gnode)
+    return gnode;
+
+  fail:
+
+  if(gnode)
+    rasqal_free_algebra_node(gnode);
+  if(fs)
+    rasqal_free_expression(fs);
+  return NULL;
+}
+
+
+static rasqal_algebra_node*
+rasqal_algebra_graph_pattern_to_algebra(rasqal_query* query,
+                                        rasqal_graph_pattern* gp)
+{
+  rasqal_algebra_node* node = NULL;
+  
+  switch(gp->op) {
+    case RASQAL_GRAPH_PATTERN_OPERATOR_BASIC:
+      node = rasqal_algebra_basic_graph_pattern_to_algebra(query, gp);
+      break;
+
+    case RASQAL_GRAPH_PATTERN_OPERATOR_UNION:
+      node = rasqal_algebra_union_graph_pattern_to_algebra(query, gp);
+      break;
+      
+    case RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL:
+    case RASQAL_GRAPH_PATTERN_OPERATOR_GROUP:
+      node = rasqal_algebra_group_graph_pattern_to_algebra(query, gp);
+      break;
+      
+    case RASQAL_GRAPH_PATTERN_OPERATOR_FILTER:
+    case RASQAL_GRAPH_PATTERN_OPERATOR_GRAPH:
+
+    case RASQAL_GRAPH_PATTERN_OPERATOR_UNKNOWN:
+    default:
+      RASQAL_DEBUG3("Unsupported graph pattern operator %s (%d)\n",
+                    rasqal_graph_pattern_operator_as_string(gp->op),
+                    gp->op);
+      break;
+  }
+
+#if RASQAL_DEBUG
+  if(!node)
+    abort();
+#endif
+  
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG1("Resulting node:\n");
+  rasqal_algebra_node_print(node, stderr);
+  fputc('\n', stderr);
+#endif
+
+  return node;
+}
+
+
+/*
+ * rasqal_algebra_node_is_empty:
+ * @node: #rasqal_algebra_node node
+ *
+ * INTERNAL - Check if a an algebra node is empty
+ * 
+ * Return value: non-0 if empty
+ **/
+int
+rasqal_algebra_node_is_empty(rasqal_algebra_node* node)
+{
+  return (node->op == RASQAL_ALGEBRA_OPERATOR_BGP && !node->triples);
+}
+
+
+static int
+rasqal_algebra_remove_znodes(rasqal_query* query, rasqal_algebra_node* node,
+                             void* data)
+{
+  int* modified = (int*)data;
+  int is_z1;
+  int is_z2;
+  
+  /* Look at 2-node operations and see if they can be merged */
+  if(!node->node1 || !node->node2)
+    return 0;
+
+  is_z1 = rasqal_algebra_node_is_empty(node->node1);
+  is_z2 = rasqal_algebra_node_is_empty(node->node2);
+  
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG1("Checking node\n");
+  rasqal_algebra_node_print(node, stderr);
+  fprintf(stderr, "\nNode 1 (%s): %s\n", 
+          is_z1 ? "empty" : "not empty",
+          rasqal_algebra_node_operator_as_string(node->node1->op));
+  fprintf(stderr, "Node 2 (%s): %s\n", 
+          is_z2 ? "empty" : "not empty",
+          rasqal_algebra_node_operator_as_string(node->node2->op));
+#endif
+
+  if(is_z1 && !is_z2) {
+    /* Replace join(Z, A) by A */
+    /* an empty node has no extra things to free */
+    RASQAL_FREE(rasqal_algebra_node, node->node1);
+    memcpy(node, node->node2, sizeof(rasqal_algebra_node));
+    *modified = 1;
+  } else if(!is_z1 && is_z2) {
+    /* Replace join(A, Z) by A */
+    /* ditto */
+    RASQAL_FREE(rasqal_algebra_node, node->node2);
+    memcpy(node, node->node1, sizeof(rasqal_algebra_node));
+    *modified = 1;
+  }
+
+  return 0;
+}
+
+
+/**
+ * rasqal_algebra_query_to_algebra:
+ * @query: #rasqal_query to operate on
+ *
+ * Turn a graph pattern into query algebra structure
+ *
+ * Return value: algebra expression or NULL on failure
+ */
+rasqal_algebra_node*
+rasqal_algebra_query_to_algebra(rasqal_query* query)
+{
+  rasqal_graph_pattern* query_gp;
+  rasqal_algebra_node* node;
+  int modified = 0;
+
+  query_gp = rasqal_query_get_query_graph_pattern(query);
+  if(!query_gp)
+    return NULL;
+  
+  node = rasqal_algebra_graph_pattern_to_algebra(query, query_gp);
+
+  if(!node)
+    return node;
+
+
+  rasqal_algebra_node_visit(query, node, 
+                            rasqal_algebra_remove_znodes,
+                            &modified);
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("modified=%d after remove zones, algebra node now:\n  ", modified);
+  rasqal_algebra_node_print(node, stderr);
+  fputs("\n", stderr);
+#endif
+
+  if(query->order_conditions_sequence) {
+    int order_size = raptor_sequence_size(query->order_conditions_sequence);
+    if(order_size) {
+      int i;
+      raptor_sequence* seq;
+
+      /* Make a deep copy of the query order conditions sequence for
+       * the ORDERBY algebra node
+       */
+      seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_expression, (raptor_sequence_print_handler*)rasqal_expression_print);
+      if(!seq) {
+        rasqal_free_algebra_node(node);
+        return NULL;
+      }
+      for(i = 0; i < order_size; i++) {
+        rasqal_expression* e;
+        e = (rasqal_expression*)raptor_sequence_get_at(query->order_conditions_sequence, i);
+        raptor_sequence_push(seq, rasqal_new_expression_from_expression(e));
+      }
+
+      node = rasqal_new_orderby_algebra_node(query, node, seq);
+      modified = 1;
+    }
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("modified=%d after adding orderby node, algebra node now:\n  ", modified);
+  rasqal_algebra_node_print(node, stderr);
+  fputs("\n", stderr);
+#endif
+
+  }
+
+
+  /* FIXME - do not always need a PROJECT node */
+  if(1) {
+    int vars_size = raptor_sequence_size(query->selects);
+    raptor_sequence* vars_seq;
+    int i;
+    
+    vars_seq = raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_variable_print);
+    if(!vars_seq) {
+      rasqal_free_algebra_node(node);
+      return NULL;
+    }
+    for(i = 0; i < vars_size; i++) {
+      rasqal_variable* v;
+      v = (rasqal_variable*)raptor_sequence_get_at(query->selects, i);
+      raptor_sequence_push(vars_seq, rasqal_new_variable_from_variable(v));
+    }
+
+    node = rasqal_new_project_algebra_node(query, node, vars_seq);
+    modified = 1;
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("modified=%d after adding project node, algebra node now:\n  ", modified);
+  rasqal_algebra_node_print(node, stderr);
+  fputs("\n", stderr);
+#endif
+  }
+
+
+  return node;
+}
+
+
+#endif
+
+#ifdef STANDALONE
+#include <stdio.h>
+
+#define QUERY_LANGUAGE "sparql"
+#define QUERY_FORMAT "\
+         PREFIX ex: <http://example.org/ns#/> \
+         SELECT $subject \
+         FROM <http://librdf.org/rasqal/rasqal.rdf> \
+         WHERE \
+         { $subject ex:predicate $value . \
+           FILTER (($value + 1) < 10) \
+         }"
+
+
+int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[]) {
+  char const *program = rasqal_basename(*argv);
+  const char *query_language_name = QUERY_LANGUAGE;
+  const unsigned char *query_format = (const unsigned char *)QUERY_FORMAT;
+  int failures = 0;
+#define FAIL do { failures++; goto tidy; } while(0)
+  rasqal_world *world;
+  rasqal_query* query = NULL;
+  rasqal_literal *lit1 = NULL, *lit2 = NULL;
+  rasqal_expression *expr1 = NULL, *expr2 = NULL;
+  rasqal_expression* expr = NULL;
+  rasqal_expression* expr3 = NULL;
+  rasqal_expression* expr4 = NULL;
+  rasqal_algebra_node* node0 = NULL;
+  rasqal_algebra_node* node1 = NULL;
+  rasqal_algebra_node* node2 = NULL;
+  rasqal_algebra_node* node3 = NULL;
+  rasqal_algebra_node* node4 = NULL;
+  rasqal_algebra_node* node5 = NULL;
+  rasqal_algebra_node* node6 = NULL;
+  rasqal_algebra_node* node7 = NULL;
+  rasqal_algebra_node* node8 = NULL;
+  rasqal_algebra_node* node9 = NULL;
+  raptor_uri *base_uri = NULL;
+  unsigned char *uri_string;
+  rasqal_graph_pattern* query_gp;
+  rasqal_graph_pattern* sgp;
+  raptor_sequence* triples;
+  raptor_sequence* conditions = NULL;
+  rasqal_literal* lit3 = NULL;
+  rasqal_literal* lit4 = NULL;
+
+  world = rasqal_new_world();
+  if(!world || rasqal_world_open(world))
+    FAIL;
+  
+  uri_string = raptor_uri_filename_to_uri_string("");
+  if(!uri_string)
+    FAIL;
+#ifdef RAPTOR_V2_AVAILABLE
+  base_uri = raptor_new_uri_v2(world->raptor_world_ptr, uri_string);
+#else
+  base_uri = raptor_new_uri(uri_string);
+#endif
+  if(!base_uri)
+    FAIL;
+  raptor_free_memory(uri_string);
+  
+  query = rasqal_new_query(world, query_language_name, NULL);
+  if(!query) {
+    fprintf(stderr, "%s: creating query in language %s FAILED\n", program,
+            query_language_name);
+    FAIL;
+  }
+
+  if(rasqal_query_prepare(query, query_format, base_uri)) {
+    fprintf(stderr, "%s: %s query prepare FAILED\n", program, 
+            query_language_name);
+    FAIL;
+  }
+
+  lit1 = rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, 1);
+  if(!lit1)
+    FAIL;
+  expr1 = rasqal_new_literal_expression(world, lit1);
+  if(!expr1)
+    FAIL;
+  lit1 = NULL; /* now owned by expr1 */
+
+  lit2 = rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, 1);
+  if(!lit2)
+    FAIL;
+  expr2 = rasqal_new_literal_expression(world, lit2);
+  if(!expr2)
+    FAIL;
+  lit2 = NULL; /* now owned by expr2 */
+
+  expr = rasqal_new_2op_expression(world, RASQAL_EXPR_PLUS, expr1, expr2);
+  if(!expr)
+    FAIL;
+  expr1 = NULL; expr2 = NULL; /* now owned by expr */
+  
+  node0 = rasqal_new_empty_algebra_node(query);
+  if(!node0)
+    FAIL;
+
+  node1 = rasqal_new_filter_algebra_node(query, expr, node0);
+  if(!node1) {
+    fprintf(stderr, "%s: rasqal_new_filter_algebra_node() failed\n", program);
+    FAIL;
+  }
+  node0 = NULL; expr = NULL; /* now owned by node1 */
+  
+  fprintf(stderr, "%s: node result: \n", program);
+  rasqal_algebra_node_print(node1, stderr);
+  fputc('\n', stderr);
+
+  rasqal_free_algebra_node(node1);
+
+
+  /* construct abstract nodes from query structures */
+  query_gp = rasqal_query_get_query_graph_pattern(query);
+
+#ifdef RASQAL_DEBUG
+  fprintf(stderr, "%s: query graph pattern: \n", program);
+  rasqal_graph_pattern_print(query_gp, stderr);
+  fputc('\n', stderr);
+#endif
+
+  /* make a filter node around 2nd GP - a FILTER gp */
+  sgp = rasqal_graph_pattern_get_sub_graph_pattern(query_gp, 1);
+  expr = rasqal_graph_pattern_get_filter_expression(sgp);
+  if(!expr) {
+    fprintf(stderr, "%s: rasqal_graph_pattern_get_constraint() failed\n", program);
+    FAIL;
+  }
+  expr = rasqal_new_expression_from_expression(expr);
+  if(!expr) {
+    fprintf(stderr, "%s: rasqal_new_expression_from_expression() failed\n", program);
+    FAIL;
+  }
+
+  node8 = rasqal_new_empty_algebra_node(query);
+  if(!node8)
+    FAIL;
+  node1 = rasqal_new_filter_algebra_node(query, expr, node8);
+  if(!node1) {
+    fprintf(stderr, "%s: rasqal_new_filter_algebra_node() failed\n", program);
+    FAIL;
+  }
+  /* these are now owned by node1 */
+  node8 = NULL;
+  expr = NULL;
+
+  fprintf(stderr, "%s: node1 result: \n", program);
+  rasqal_algebra_node_print(node1, stderr);
+  fputc('\n', stderr);
+
+
+  /* make an triples node around first (and only) triple pattern */
+  triples = rasqal_query_get_triple_sequence(query);
+  node2 = rasqal_new_triples_algebra_node(query, triples, 0, 0);
+  if(!node2)
+    FAIL;
+
+  fprintf(stderr, "%s: node2 result: \n", program);
+  rasqal_algebra_node_print(node2, stderr);
+  fputc('\n', stderr);
+
+
+  node3 = rasqal_new_2op_algebra_node(query,
+                                      RASQAL_ALGEBRA_OPERATOR_JOIN,
+                                      node1, node2);
+
+  if(!node3)
+    FAIL;
+  
+  /* these become owned by node3 */
+  node1 = node2 = NULL;
+  
+  fprintf(stderr, "%s: node3 result: \n", program);
+  rasqal_algebra_node_print(node3, stderr);
+  fputc('\n', stderr);
+
+  node4 = rasqal_new_empty_algebra_node(query);
+  if(!node4)
+    FAIL;
+
+  fprintf(stderr, "%s: node4 result: \n", program);
+  rasqal_algebra_node_print(node4, stderr);
+  fputc('\n', stderr);
+
+  node5 = rasqal_new_2op_algebra_node(query,
+                                      RASQAL_ALGEBRA_OPERATOR_UNION,
+                                      node3, node4);
+
+  if(!node5)
+    FAIL;
+  
+  /* these become owned by node5 */
+  node3 = node4 = NULL;
+  
+  fprintf(stderr, "%s: node5 result: \n", program);
+  rasqal_algebra_node_print(node5, stderr);
+  fputc('\n', stderr);
+
+
+
+  lit1 = rasqal_new_boolean_literal(world, 1);
+  if(!lit1)
+    FAIL;
+  expr1 = rasqal_new_literal_expression(world, lit1);
+  if(!expr1)
+    FAIL;
+  lit1 = NULL; /* now owned by expr1 */
+
+  node6 = rasqal_new_empty_algebra_node(query);
+  if(!node6)
+    FAIL;
+
+  node7 = rasqal_new_leftjoin_algebra_node(query, node5, node6, expr1);
+  if(!node7)
+    FAIL;
+  /* these become owned by node7 */
+  node5 = node6 = NULL;
+  expr1 = NULL;
+  
+  fprintf(stderr, "%s: node7 result: \n", program);
+  rasqal_algebra_node_print(node7, stderr);
+  fputc('\n', stderr);
+
+  /* This is an artificial order conditions sequence equivalent to
+   * ORDER BY 1, 2 which would probably never appear in a query.
+   */
+  conditions = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_expression, (raptor_sequence_print_handler*)rasqal_expression_print);
+  if(!conditions)
+    FAIL;
+  lit3 = rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, 1);
+  if(!lit3)
+    FAIL;
+  expr3 = rasqal_new_literal_expression(world, lit3);
+  if(!expr3)
+    FAIL;
+  lit3 = NULL; /* now owned by expr3 */
+
+  raptor_sequence_push(conditions, expr3);
+  expr3 = NULL; /* now owned by conditions */
+  
+  lit4 = rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, 2);
+  if(!lit4)
+    FAIL;
+  expr4 = rasqal_new_literal_expression(world, lit4);
+  if(!expr4)
+    FAIL;
+  lit4 = NULL; /* now owned by expr4 */
+
+  raptor_sequence_push(conditions, expr4);
+  expr4 = NULL; /* now owned by conditions */
+  
+  node9 = rasqal_new_orderby_algebra_node(query, node7, conditions);
+  if(!node9)
+    FAIL;
+  /* these become owned by node9 */
+  node7 = NULL;
+  conditions = NULL;
+  
+  fprintf(stderr, "%s: node9 result: \n", program);
+  rasqal_algebra_node_print(node9, stderr);
+  fputc('\n', stderr);
+
+
+  tidy:
+  if(lit1)
+    rasqal_free_literal(lit1);
+  if(lit2)
+    rasqal_free_literal(lit2);
+  if(lit3)
+    rasqal_free_literal(lit3);
+  if(expr1)
+    rasqal_free_expression(expr1);
+  if(expr2)
+    rasqal_free_expression(expr2);
+  if(expr3)
+    rasqal_free_expression(expr3);
+
+  if(node9)
+    rasqal_free_algebra_node(node9);
+  if(node8)
+    rasqal_free_algebra_node(node8);
+  if(node7)
+    rasqal_free_algebra_node(node7);
+  if(node6)
+    rasqal_free_algebra_node(node6);
+  if(node5)
+    rasqal_free_algebra_node(node5);
+  if(node4)
+    rasqal_free_algebra_node(node4);
+  if(node3)
+    rasqal_free_algebra_node(node3);
+  if(node2)
+    rasqal_free_algebra_node(node2);
+  if(node1)
+    rasqal_free_algebra_node(node1);
+  if(node0)
+    rasqal_free_algebra_node(node0);
+
+  if(query)
+    rasqal_free_query(query);
+  if(base_uri)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(world->raptor_world_ptr, base_uri);
+#else
+    raptor_free_uri(base_uri);
+#endif
+  if(world)
+    rasqal_free_world(world);
+  
+  return failures;
+}
+#endif
diff --git a/src/rasqal/rasqal_config.h b/src/rasqal/rasqal_config.h
new file mode 100644
index 0000000..968f9d4
--- /dev/null
+++ b/src/rasqal/rasqal_config.h
@@ -0,0 +1,2 @@
+#include "config.h"
+
diff --git a/src/rasqal/rasqal_datetime.c b/src/rasqal/rasqal_datetime.c
new file mode 100644
index 0000000..592decb
--- /dev/null
+++ b/src/rasqal/rasqal_datetime.c
@@ -0,0 +1,802 @@
+/*
+ * rasqal_datetime.c - Rasqal XSD dateTime
+ *
+ * Copyright (C) 2007-2008, David Beckett http://www.dajobe.org/
+ *
+ * Contributions:
+ *   Copyright (C) 2007, Lauri Aalto <laalto iki fi>
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+#include <limits.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+/* Local definitions */
+ 
+/**
+ * rasqal_xsd_datetime:
+ *
+ * INTERNAL - XML schema dateTime datatype
+ *
+ * Signed types are required for normalization process where a value
+ * can be negative temporarily.
+ */
+typedef struct {
+  signed int year;
+  /* the following fields are integer values not characters */
+  unsigned char month;
+  unsigned char day;
+  signed char hour;
+  signed char minute;
+  signed char second;
+  /* second_frac is a string of 1-3 length (+1 for NUL)
+   * supports only up to milliseconds
+   */
+  char second_frac[3+1];
+  /* have_tz is an integer flag: non-0 if 'Z'ulu timezone is present */
+  char have_tz;
+}  rasqal_xsd_datetime;
+
+
+static int rasqal_xsd_datetime_parse_and_normalize(const unsigned char *datetime_string, rasqal_xsd_datetime *result);
+static unsigned char *rasqal_xsd_datetime_to_string(const rasqal_xsd_datetime *dt);
+static unsigned int days_per_month(int month, int year);
+
+
+#ifndef ISNUM
+#define ISNUM(c) ((c)>='0'&&(c)<='9')
+#endif
+
+
+/**
+ * rasqal_xsd_datetime_normalize:
+ * @datetime: date time
+ *
+ * INTERNAl - Normalize a date time into the allowed range
+ *
+ * Return value: zero on success, non zero on failure.
+ */
+static int
+rasqal_xsd_datetime_normalize(rasqal_xsd_datetime *datetime)
+{
+  int t;
+  
+  /* second & second parts: no need to normalize as they are not
+   * touched after range check
+   */
+  
+  /* minute */
+  if(datetime->minute < 0) {
+    datetime->minute += 60;
+    datetime->hour--;
+  } else if(datetime->minute > 59) {
+    datetime->minute -= 60;
+    datetime->hour++;
+  }
+  
+  /* hour */
+  if(datetime->hour < 0) {
+    datetime->hour += 24;
+    datetime->day--;
+  } else if(datetime->hour > 23) {
+    datetime->hour -= 24;
+    datetime->day++;
+  }
+  
+  /* day */
+  if(datetime->day < 1) {
+    int y2;
+    t = --datetime->month;
+    /* going back beyond year boundary? */
+    if(!t) {
+      t = 12;
+      y2 = datetime->year-1;
+    } else
+      y2 = datetime->year;
+    datetime->day += days_per_month(t, y2);
+  } else if(datetime->day > (t=days_per_month(datetime->month, datetime->year))) {
+    datetime->day -= t;
+    datetime->month++;
+  }
+  
+  /* month & year */
+  if(datetime->month < 1) {
+    datetime->month += 12;
+    datetime->year--;
+    /* there is no year 0 - go backwards to year -1 */
+    if(!datetime->year)
+      datetime->year--;
+  } else if(datetime->month > 12) {
+    datetime->month -= 12;
+    datetime->year++;
+    /* there is no year 0 - go forwards to year 1 */
+    if(!datetime->year)
+      datetime->year++;
+  }
+
+  /* success */
+  return 0;
+}
+
+
+/**
+ * rasqal_xsd_datetime_parse_and_normalize:
+ * @datetime_string: xsd:dateTime as lexical form string
+ * @result: target struct for holding dateTime components
+ *
+ * INTERNAL - Parse a xsd:dateTime string to a normalized #rasqal_xsd_datetime struct.
+ *
+ * http://www.w3.org/TR/xmlschema-2/#dt-dateTime
+ *
+ * "The lexical space of dateTime consists of finite-length sequences of
+ * characters of the form:
+ * '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?,
+ * where
+ *
+ * * '-'? yyyy is a four-or-more digit optionally negative-signed numeral that
+ *   represents the year; if more than four digits, leading zeros are
+ *   prohibited, and '0000' is prohibited (see the Note above (3.2.7); also
+ *   note that a plus sign is not permitted);
+ * * the remaining '-'s are separators between parts of the date portion;
+ * * the first mm is a two-digit numeral that represents the month;
+ * * dd is a two-digit numeral that represents the day;
+ * * 'T' is a separator indicating that time-of-day follows;
+ * * hh is a two-digit numeral that represents the hour; '24' is permitted if
+ *   the minutes and seconds represented are zero, and the dateTime value so
+ *   represented is the first instant of the following day (the hour property
+ *   of a dateTime object in the value space cannot have a value greater
+ *   than 23);
+ * * ':' is a separator between parts of the time-of-day portion;
+ * * the second mm is a two-digit numeral that represents the minute;
+ * * ss is a two-integer-digit numeral that represents the whole seconds;
+ * * '.' s+ (if present) represents the fractional seconds;
+ * * zzzzzz (if present) represents the timezone"
+ *
+ * Return value: zero on success, non zero on failure.
+ */
+int
+rasqal_xsd_datetime_parse_and_normalize(const unsigned char *datetime_string,
+                                        rasqal_xsd_datetime *result)
+{
+  const char *p, *q; 
+  char b[16];
+  unsigned int l, t, t2, is_neg;
+  unsigned long u;
+
+  if(!datetime_string || !result)
+    return -1;
+  
+  p=(const char *)datetime_string;
+  is_neg=0;
+
+  /* Parse year */
+  
+  /* negative years permitted */
+  if(*p == '-') {
+    is_neg=1;
+    p++;
+  }
+  for(q=p; ISNUM(*p); p++)
+    ;
+  l=p-q;
+  
+  /* error if
+     - less than 4 digits in year
+     - more than 4 digits && leading zeros
+     - '-' does not follow numbers
+   */
+  if(l < 4 || (l > 4 && *q=='0') || *p!='-')
+    return -1;
+
+  l=(l < sizeof(b)-1 ? l : sizeof(b)-1);
+  strncpy(b, q, l);
+  b[l]=0; /* ensure nul termination */
+  u=strtoul(b, 0, 10);
+  
+  /* year "0000" not permitted
+   * restrict to signed int range
+   * >= instead of > to allow for +-1 year adjustment in normalization
+   * (however, these +-INT_MAX years cannot be parsed back in if
+   * converted to string)
+   */
+  if(!u || u >= INT_MAX)
+    return -1;
+    
+  result->year=is_neg ? -(int)u : (int)u;
+
+  /* parse month */
+  
+  for(q=++p; ISNUM(*p); p++)
+    ;
+  l=p-q;
+  
+  /* error if month is not 2 digits or '-' is not the separator */
+  if(l != 2 || *p!='-')
+    return -2;
+  
+  t=(*q++-'0')*10;
+  t+=*q-'0';
+  
+  /* month must be 1..12 */
+  if(t < 1 || t > 12)
+    return -2;
+  
+  result->month=t;
+  
+  /* parse day */
+  
+  for(q=++p; ISNUM(*p); p++)
+    ;
+  l=p-q;
+  
+  /* error if day is not 2 digits or 'T' is not the separator */
+  if(l != 2 || *p != 'T')
+    return -3;
+  
+  t=(*q++-'0')*10;
+  t+=*q-'0';
+  
+  /* day must be 1..days_per_month */
+  if(t < 1 || t > days_per_month(result->month, result->year))
+    return -3;
+    
+  result->day=t;
+  
+  /* parse hour */
+  
+  for(q=++p; ISNUM(*p); p++)
+    ;
+  l=p-q;
+  
+  /* error if hour is not 2 digits or ':' is not the separator */
+  if(l != 2 || *p != ':')
+    return -4;
+   
+  t=(*q++-'0')*10;
+  t+=*q-'0';
+ 
+  /* hour must be 0..24 - will handle special case 24 later
+   * (no need to check for < 0)
+   */
+  if(t > 24)
+    return -4;
+    
+  result->hour=t;
+ 
+  /* parse minute */
+
+  for(q=++p; ISNUM(*p); p++)
+    ;
+  l=p-q;
+  
+  /* error if minute is not 2 digits or ':' is not the separator */
+  if(l != 2 || *p != ':')
+    return -5;
+   
+  t=(*q++-'0')*10;
+  t+=*q-'0';
+ 
+  /* minute must be 0..59
+   * (no need to check for < 0)
+   */
+  if(t > 59)
+    return -5;
+
+  result->minute=t;
+  
+  /* parse second whole part */
+  
+  for(q=++p; ISNUM(*p); p++)
+    ;
+  l=p-q;
+  
+  /* error if second is not 2 digits or separator is not 
+   * '.' (second fraction)
+   * 'Z' (utc)
+   * '+' or '-' (timezone offset)
+   * nul (end of string - second fraction and timezone are optional)
+   */
+  if(l != 2 || (*p && *p != '.' && *p != 'Z' && *p != '+' && *p != '-'))
+    return -6;
+    
+  t=(*q++-'0')*10;
+  t+=*q-'0';
+
+  /* second must be 0..59
+  * (no need to check for < 0)
+  */
+  if(t > 59)
+    return -6;
+
+  result->second=t;
+
+  /* now that we have hour, minute and second, we can check
+   * if hour == 24 -> only 24:00:00 permitted (normalized later)
+   */
+  if(result->hour==24 && (result->minute || result->second))
+    return -7;
+  
+  /* parse fraction seconds if any */
+  result->second_frac[0]=0;
+  if(*p == '.') {
+    for(q=++p; ISNUM(*p); p++)
+      ;
+
+    /* ignore trailing zeros */
+    while(*--p == '0')
+      ;
+    p++;
+
+    if(!(*q=='0' && q==p)) {
+      /* allow ".0" */
+      l=p-q;
+      /* support only to milliseconds with truncation */
+      if(l > sizeof(result->second_frac)-1)
+        l=sizeof(result->second_frac)-1;
+
+      if(l<1) /* need at least 1 num */
+        return -8;
+
+      for(t2=0; t2 < l; ++t2)
+        result->second_frac[t2]=*q++;
+
+      result->second_frac[l]=0;
+    }
+
+    /* skip ignored trailing zeros */
+    while(*p == '0')
+      p++;
+  }
+  
+  /* parse & adjust timezone offset */
+  /* result is normalized later */
+  result->have_tz=0;
+  if(*p) {
+    if(*p == 'Z') {
+      /* utc timezone - no need to adjust */
+      p++;
+      result->have_tz=1;
+    } else if(*p=='+' || *p=='-') {
+      /* work out timezone offsets */
+      is_neg=*p == '-';
+     
+      /* timezone hours */
+      for(q=++p; ISNUM(*p); p++)
+        ;
+      l=p-q;
+      if(l != 2 || *p!=':')
+        return -9;
+
+      t2=(*q++ - '0')*10;
+      t2+=*q - '0';
+      if(t2 > 14)
+        /* tz offset hours are restricted to 0..14
+         * (no need to check for < 0)
+         */
+        return -9;
+    
+      /* negative tz offset adds to the result */
+      result->hour+=is_neg ? t2 : -t2;
+
+      /* timezone minutes */    
+      for(q=++p; ISNUM(*p); p++)
+        ;
+      l=p-q;
+      if(l!=2)
+        return -10;
+
+      t=(*q++ - '0')*10;
+      t+=*q - '0';
+      if(t > 59 || (t2 == 14 && t!=0)) {
+        /* tz offset minutes are restricted to 0..59
+         * (no need to check for < 0)
+         * or 0 if hour offset is exactly +-14 
+         */
+        return -10;
+      }
+    
+      /* negative tz offset adds to the result */
+      result->minute += is_neg ? t : -t;
+      result->have_tz=1;
+    }
+    
+    /* failure if extra chars after the timezone part */
+    if(*p)
+      return -11;
+
+  }
+
+  return rasqal_xsd_datetime_normalize(result);
+}
+
+
+/**
+ * rasqal_xsd_datetime_to_string:
+ * @dt: datetime struct
+ *
+ * INTERNAL - Convert a #rasqal_xsd_datetime struct to a xsd:dateTime lexical form string.
+ *
+ * Caller should RASQAL_FREE() the returned string.
+ *
+ * Return value: lexical form string or NULL on failure.
+ */
+static unsigned char*
+rasqal_xsd_datetime_to_string(const rasqal_xsd_datetime *dt)
+{
+  unsigned char *ret=0;
+  int is_neg;
+  int r=0;
+  int i;
+   
+  if(!dt)
+    return NULL;
+    
+  is_neg=dt->year<0;
+
+  /* format twice: first with null buffer of zero size to get the
+   * required buffer size second time to the allocated buffer
+   */
+  for(i=0; i < 2; i++) {
+    r=snprintf((char*)ret, r, "%s%04d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d%s%s%s",
+      is_neg ? "-" : "",
+      is_neg ? -dt->year : dt->year,
+      dt->month,
+      dt->day,
+      dt->hour,
+      dt->minute,
+      dt->second,
+      *dt->second_frac ? "." : "",
+      dt->second_frac,
+      dt->have_tz ? "Z" : "");
+
+    /* error? */
+    if(r<0) {
+      if(ret)
+        RASQAL_FREE(cstring, ret);
+      return NULL;
+    }
+
+    /* alloc return buffer on first pass */
+    if(!i) {
+      ret=(unsigned char *)RASQAL_MALLOC(cstring, ++r);
+      if(!ret)
+        return NULL;
+    }
+  }
+  return ret;
+}
+
+
+/**
+ * rasqal_xsd_datetime_string_to_canonical:
+ * @datetime_string: xsd:dateTime as lexical form string
+ *
+ * Convert a XML Schema dateTime lexical form string to its canonical form.
+ *
+ * Caller should RASQAL_FREE() the returned string.
+ *
+ * Return value: canonical lexical form string or NULL on failure.
+ *
+ *
+ * http://www.w3.org/TR/xmlschema-2/#dateTime-canonical-representation
+ * 
+ * "Except for trailing fractional zero digits in the seconds representation,
+ * '24:00:00' time representations, and timezone (for timezoned values),
+ * the mapping from literals to values is one-to-one.
+ * Where there is more than one possible representation,
+ * the canonical representation is as follows:
+ *    * The 2-digit numeral representing the hour must not be '24';
+ *    * The fractional second string, if present, must not end in '0';
+ *    * for timezoned values, the timezone must be represented with 'Z'
+ *      (All timezoned dateTime values are UTC.)."
+ */
+const unsigned char*
+rasqal_xsd_datetime_string_to_canonical(const unsigned char* datetime_string)
+{
+  rasqal_xsd_datetime d; /* allocated on stack */
+
+  /* parse_and_normalize makes the rasqal_xsd_datetime canonical... */
+  if(rasqal_xsd_datetime_parse_and_normalize(datetime_string, &d))
+    return NULL;
+  /* ... so return a string representation of it */
+  return rasqal_xsd_datetime_to_string(&d);
+}
+
+
+
+
+/**
+ * days_per_month:
+ * @month: month 1-12
+ * @year: gregorian year
+ *
+ * INTERNAL - returns the number of days in given month and year.
+ *
+ * Return value: number of days or 0 on invalid arguments
+ */
+static unsigned int
+days_per_month(int month, int year) {
+  switch(month) {
+    case 1:
+    case 3:
+    case 5:
+    case 7:
+    case 8:
+    case 10:
+    case 12:
+      return 31;
+  
+    case 4:
+    case 6:
+    case 9:
+    case 11:
+      return 30;
+  
+    case 2:
+      /* any of bottom 2 bits non-zero -> not 0 mod 4 -> not leap year */
+      if(year & 3)
+        return 28;
+
+      /* 0 mod 400 and 0 mod 4 -> leap year */
+      if(!(year % 400))
+        return 29;
+
+      /* 0 mod 100 and not 0 mod 400 and 0 mod 4 -> not leap year */
+      if(!(year % 100))
+        return 28;
+
+      /* other 0 mod 4 years -> leap year */
+      return 29;
+
+    default:
+       /* error */
+      return 0;
+  }
+}
+
+
+int
+rasqal_xsd_datetime_check(const unsigned char* string)
+{
+  rasqal_xsd_datetime d;
+  
+  /* This should be correct according to 
+   * http://www.w3.org/TR/xmlschema-2/#dateTime
+   */
+  return !rasqal_xsd_datetime_parse_and_normalize(string, &d);
+}
+
+
+#ifdef STANDALONE
+#include <stdio.h>
+
+int main(int argc, char *argv[]);
+
+#define MYASSERT(c) \
+  if(!(c)) { \
+    fprintf(stderr, "%s: assertion failed at %s:%d: %s\n", program, __FILE__, __LINE__, #c); \
+    exit(1); \
+  }
+
+
+static int test_datetime_parser_tostring(const char *in_str, const char *out_expected)
+{
+  unsigned char const *s;
+  int r=1;
+  s=rasqal_xsd_datetime_string_to_canonical((const unsigned char *)in_str);
+  if(s) {
+    r=strcmp((char*)s, out_expected);
+    if(r)
+      fprintf(stderr, "input \"%s\" converted to canonical \"%s\", expected \"%s\"\n", in_str, s, out_expected);
+    RASQAL_FREE(cstring, (void*)s);
+  } else
+    fprintf(stderr, "input \"%s\" converted to canonical (null), expected \"%s\"\n", in_str, out_expected);
+  return r;
+}
+
+
+int
+main(int argc, char *argv[]) {
+  char const *program=rasqal_basename(*argv);
+  rasqal_xsd_datetime d;
+
+  /* days_per_month */
+  
+  MYASSERT(!days_per_month(0,287));
+  
+  MYASSERT(days_per_month(1,467) == 31);
+
+  MYASSERT(days_per_month(2,1900) == 28);  
+  MYASSERT(days_per_month(2,1901) == 28);
+  MYASSERT(days_per_month(2,2000) == 29);
+  MYASSERT(days_per_month(2,2004) == 29);
+  
+  MYASSERT(days_per_month(3,1955) == 31);
+  MYASSERT(days_per_month(4,3612) == 30);
+  MYASSERT(days_per_month(5,467) == 31);
+  MYASSERT(days_per_month(6,398) == 30);
+  MYASSERT(days_per_month(7,1832) == 31);
+  MYASSERT(days_per_month(8,8579248) == 31);
+  MYASSERT(days_per_month(9,843) == 30);
+  MYASSERT(days_per_month(10,84409) == 31);
+  MYASSERT(days_per_month(11,398) == 30);
+  MYASSERT(days_per_month(12,4853) == 31);
+  MYASSERT(!days_per_month(13,45894));
+  
+  /* rasqal_xsd_datetime_parse_and_normalize,
+     rasqal_xsd_datetime_to_string and
+     rasqal_xsd_datetime_string_to_canonical */
+  
+  #define PARSE_AND_NORMALIZE(_s,_d) \
+    rasqal_xsd_datetime_parse_and_normalize((const unsigned char*)_s, _d)
+  
+  /* generic */
+
+  MYASSERT(!rasqal_xsd_datetime_to_string(0));
+
+  MYASSERT(PARSE_AND_NORMALIZE(0,0));
+  MYASSERT(PARSE_AND_NORMALIZE("uhgsufi",0));
+  MYASSERT(PARSE_AND_NORMALIZE(0,&d));
+  MYASSERT(PARSE_AND_NORMALIZE("fsdhufhdsuifhidu",&d));
+  
+  /* year */
+  
+  MYASSERT(PARSE_AND_NORMALIZE("123-12-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("-123-12-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("0000-12-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("01234-12-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("-01234-12-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("1234a12-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("-1234b12-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("g162-12-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("5476574658746587465874-12-12T12:12:12Z",&d));
+  
+  MYASSERT(test_datetime_parser_tostring("1234-12-12T12:12:12Z", "1234-12-12T12:12:12Z")==0);
+  MYASSERT(test_datetime_parser_tostring("-1234-12-12T12:12:12Z", "-1234-12-12T12:12:12Z")==0);
+  MYASSERT(test_datetime_parser_tostring("1234567890-12-12T12:12:12Z", "1234567890-12-12T12:12:12Z")==0);
+  MYASSERT(test_datetime_parser_tostring("-1234567890-12-12T12:12:12Z", "-1234567890-12-12T12:12:12Z")==0);
+  
+  /* month */
+  
+  MYASSERT(PARSE_AND_NORMALIZE("2004-v-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-00-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("PARSE_AND_NORMALIZE-011-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-13-12T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-12.12T12:12:12Z",&d));
+
+  MYASSERT(test_datetime_parser_tostring("2004-01-01T12:12:12Z", "2004-01-01T12:12:12Z")==0);
+
+  /* day */
+  
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-ffT12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-00T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-007T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-32T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01t12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01- 1T12:12:12Z",&d));
+  
+  MYASSERT(PARSE_AND_NORMALIZE("2005-02-29T12:12:12Z",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2005-02-28T12:12:12Z",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-02-29T12:12:12Z",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2000-02-29T12:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("1900-02-29T12:12:12Z",&d));
+
+  MYASSERT(test_datetime_parser_tostring("2012-04-12T12:12:12Z", "2012-04-12T12:12:12Z")==0);
+  
+  /* hour */
+
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01Tew:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T-1:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T001:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T25:12:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T01.12:12Z",&d));
+  
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T24:12:00Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T24:00:34Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T24:12:34Z",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T24:00:00Z",&d));
+  
+  MYASSERT(test_datetime_parser_tostring("2012-04-12T24:00:00", "2012-04-13T00:00:00")==0);
+  
+  /* minute */
+  
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:ij:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:-1:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:042:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:69:12Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12.12Z",&d));
+  
+  /* second */
+
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:ijZ",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:-1",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:054Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:69Z",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12z",&d));
+  
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12",&d));
+  
+  /* fraction second */
+  
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12.",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12.i",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12.0",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12.01",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12.1",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12.100",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12.1000000000000000000000000000000000000000000",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12.5798459847598743987549",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12.1d",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12.1Z",&d));
+
+  MYASSERT(test_datetime_parser_tostring("2006-05-18T18:36:03.01Z", "2006-05-18T18:36:03.01Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2006-05-18T18:36:03.10Z", "2006-05-18T18:36:03.1Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2006-05-18T18:36:03.010Z", "2006-05-18T18:36:03.01Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2006-05-18T18:36:03.1234Z", "2006-05-18T18:36:03.123Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2006-05-18T18:36:03.1234", "2006-05-18T18:36:03.123")==0);
+  MYASSERT(test_datetime_parser_tostring("2006-05-18T18:36:03.1239Z", "2006-05-18T18:36:03.123Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2006-05-18T18:36:03.1239", "2006-05-18T18:36:03.123")==0);
+
+  /* timezones + normalization */
+
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12-",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+00.00",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+aa:bb",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+15:00",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+14:01",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12+14:00",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12-14:01",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12-14:00",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+10:99",&d));
+  MYASSERT(!PARSE_AND_NORMALIZE("2004-01-01T12:12:12+10:59",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+10:059",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+010:59",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+10:59a",&d));
+  MYASSERT(PARSE_AND_NORMALIZE("2004-01-01T12:12:12+10:059",&d));
+
+  MYASSERT(test_datetime_parser_tostring("2004-12-31T23:50:22-01:15", "2005-01-01T01:05:22Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2005-01-01T01:00:05+02:12", "2004-12-31T22:48:05Z")==0);
+  MYASSERT(test_datetime_parser_tostring("0001-01-01T00:00:00+00:01", "-0001-12-31T23:59:00Z")==0);
+  MYASSERT(test_datetime_parser_tostring("-0001-12-31T23:59:00-00:01", "0001-01-01T00:00:00Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2005-03-01T00:00:00+01:00", "2005-02-28T23:00:00Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2004-03-01T00:00:00+01:00", "2004-02-29T23:00:00Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2005-02-28T23:00:00-01:00", "2005-03-01T00:00:00Z")==0);
+  MYASSERT(test_datetime_parser_tostring("2004-02-29T23:00:00-01:00", "2004-03-01T00:00:00Z")==0);
+
+  return 0;
+}
+
+#endif
diff --git a/src/rasqal/rasqal_decimal.c b/src/rasqal/rasqal_decimal.c
new file mode 100644
index 0000000..1051224
--- /dev/null
+++ b/src/rasqal/rasqal_decimal.c
@@ -0,0 +1,941 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_decimal.c - Rasqal XSD Decimal
+ *
+ * Copyright (C) 2007-2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+/* prototypes */
+static void rasqal_xsd_decimal_init(rasqal_xsd_decimal* dec);
+static void rasqal_xsd_decimal_clear(rasqal_xsd_decimal* dec);
+
+
+#ifdef RASQAL_DECIMAL_C99
+/* C99 Decimal
+ * Based on http://www2.hursley.ibm.com/decimal/
+ */
+
+#include <float.h>
+#define RASQAL_DECIMAL_RAW _Decimal64
+#define RASQAL_DECIMAL_ROUNDING int
+
+#else
+#ifdef RASQAL_DECIMAL_MPFR
+/* MPFR multiple-precision floating-point computations with correct rounding
+ * http://www.mpfr.org/
+ */
+
+#ifdef HAVE_MPFR_H
+#include <mpfr.h>
+#endif
+#define RASQAL_DECIMAL_RAW mpfr_t
+#define RASQAL_DECIMAL_ROUNDING mp_rnd_t
+
+#else
+#ifdef RASQAL_DECIMAL_GMP
+/* GNU MP - GNU Multiple Precision Arithmetic Library
+ * http://gmplib.org/
+ */
+#ifdef HAVE_GMP_H
+#include <gmp.h>
+#endif
+#define RASQAL_DECIMAL_RAW mpf_t
+#define RASQAL_DECIMAL_ROUNDING int
+
+#else
+
+/* No implementation - use double. */
+#define RASQAL_DECIMAL_RAW double
+#define RASQAL_DECIMAL_ROUNDING int
+
+#endif
+#endif
+#endif
+
+struct rasqal_xsd_decimal_s {
+  unsigned int precision_digits;
+  unsigned int precision_bits;
+  RASQAL_DECIMAL_RAW raw;
+  RASQAL_DECIMAL_ROUNDING rounding;
+  char* string;
+  size_t string_len;
+};
+
+
+/**
+ * rasqal_new_xsd_decimal:
+ * 
+ * Create a new XSD Decimal object.
+ * 
+ * Return value: new xsd:decimal object or NULL on failure.
+ **/
+rasqal_xsd_decimal*
+rasqal_new_xsd_decimal(void)
+{
+  rasqal_xsd_decimal* dec;
+  dec=(rasqal_xsd_decimal*)RASQAL_MALLOC(decimal, sizeof(rasqal_xsd_decimal));
+  if(dec)
+    rasqal_xsd_decimal_init(dec);
+  return dec;
+}
+
+
+/**
+ * rasqal_free_xsd_decimal:
+ * @dec: Decimal object
+ * 
+ * Destroy XSD Decimal object.
+ **/
+void
+rasqal_free_xsd_decimal(rasqal_xsd_decimal* dec)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(dec, rasqal_xsd_decimal);
+  
+  rasqal_xsd_decimal_clear(dec);
+  RASQAL_FREE(decimal, dec);
+}
+
+
+static void
+rasqal_xsd_decimal_init(rasqal_xsd_decimal* dec)
+{
+  /* XSD wants min of 18 decimal (base 10) digits 
+   * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#decimal
+   */
+  dec->precision_digits= 32;
+  /* over-estimate bits since log(10)/log(2) = 3.32192809488736234789 < 4 */
+  dec->precision_bits= dec->precision_digits*4;
+  
+#ifdef RASQAL_DECIMAL_C99
+  dec->raw= 0DD;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  mpfr_init2(dec->raw, dec->precision_bits);
+
+  /* GMP_RNDD, GMP_RNDU, GMP_RNDN, GMP_RNDZ */
+  dec->rounding=mpfr_get_default_rounding_mode();
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_init2(dec->raw, dec->precision_bits);
+#endif
+#ifdef RASQAL_DECIMAL_NONE
+  dec->raw= 0e0;
+#endif
+
+  dec->string=NULL;
+  dec->string_len=0;
+}
+
+
+static void
+rasqal_xsd_decimal_clear_string(rasqal_xsd_decimal* dec)
+{
+  if(dec->string) {
+    RASQAL_FREE(cstring, dec->string);
+    dec->string=NULL;
+  }
+  dec->string_len=0;
+}  
+
+
+static void
+rasqal_xsd_decimal_clear(rasqal_xsd_decimal* dec)
+{
+  rasqal_xsd_decimal_clear_string(dec);
+#ifdef RASQAL_DECIMAL_C99
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  mpfr_clear(dec->raw);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_clear(dec->raw);
+#endif
+#ifdef RASQAL_DECIMAL_NONE
+  dec->raw= 0e0;
+#endif
+}  
+
+
+/**
+ * rasqal_xsd_decimal_set_string:
+ * @dec: XSD Decimal
+ * @string: lexical form
+ * 
+ * Set an XSD Decimal value from a string lexical form
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_set_string(rasqal_xsd_decimal* dec, const char* string)
+{
+  int rc=0;
+  size_t len;
+  
+  if(!string)
+    return 1;
+
+  rasqal_xsd_decimal_clear_string(dec);
+
+  len=strlen(string);
+  dec->string=(char*)RASQAL_MALLOC(cstring, len+1);
+  if(!dec->string)
+    return 1;
+  strncpy(dec->string, string, len+1);
+  dec->string_len=len;
+  
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  dec->raw=strtod(string, NULL);
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  rc=mpfr_set_str(dec->raw, string, 10, dec->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  rc=mpf_set_str(dec->raw, string, 10);
+#endif
+
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_set_long:
+ * @dec: XSD Decimal
+ * @l: long
+ * 
+ * Set an XSD Decimal value from a long.
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_set_long(rasqal_xsd_decimal* dec, long l)
+{
+  int rc=0;
+  
+  rasqal_xsd_decimal_clear_string(dec);
+
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  dec->raw=l;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  rc=mpfr_set_si(dec->raw, l, dec->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_set_si(dec->raw, l);
+#endif
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_set_double:
+ * @dec: XSD Decimal
+ * @d: double
+ * 
+ * Set an XSD Decimal value from a double.
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_set_double(rasqal_xsd_decimal* dec, double d)
+{
+  int rc=0;
+  
+  rasqal_xsd_decimal_clear_string(dec);
+
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  dec->raw=d;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  mpfr_set_d(dec->raw, d, dec->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_set_d(dec->raw, d);
+#endif
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_get_double:
+ * @dec: XSD Decimal
+ * 
+ * Get an XSD Decimal as a double (may lose precision)
+ * 
+ * Return value: double value.
+ **/
+double
+rasqal_xsd_decimal_get_double(rasqal_xsd_decimal* dec)
+{
+  double result=0e0;
+
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  result=(double)dec->raw;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  result=mpfr_get_d(dec->raw, dec->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  result=mpf_get_d(dec->raw);
+#endif
+
+  return result;
+}
+
+
+/**
+ * rasqal_xsd_decimal_as_string:
+ * @dec: XSD Decimal
+ * 
+ * Get an XSD Decimal as a string lexical form.
+ *
+ * The returned string is shared and owned by the @dec object and
+ * must be copied.
+ * 
+ * Return value: lexical form string or NULL on failure.
+ **/
+char*
+rasqal_xsd_decimal_as_string(rasqal_xsd_decimal* dec)
+{
+  char *s=NULL;
+  size_t len=0;
+#if defined(RASQAL_DECIMAL_MPFR) || defined(RASQAL_DECIMAL_GMP)
+  mp_exp_t expo;
+  char *mpf_s;
+#endif
+  
+  if(dec->string)
+    return dec->string;
+  
+#ifdef RASQAL_DECIMAL_C99
+  len=dec->precision_digits;
+  s=RASQAL_MALLOC(cstring, len+1);
+  if(!s)
+    return NULL;
+  /* NOTE: Never seen a sprintf that supports _Decimal yet */
+  snprintf(s, len, "%DDf", dec->raw);
+  len=strlen(s);
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  mpf_s=mpfr_get_str(NULL, &expo, 10, 0, dec->raw, dec->rounding);
+  if(mpf_s) {
+    size_t from_len=strlen(mpf_s);
+    char *from_p=mpf_s;
+    size_t to_len;
+
+    /* 7=strlen("0.0e0")+1 for sign */
+    to_len=!from_len ? 6 : (from_len*2);
+
+    s=(char*)RASQAL_MALLOC(cstring, to_len);
+    if(!s) {
+      mpfr_free_str((char*)mpf_s);
+      return NULL;
+    }
+    /* first digit of mantissa */
+    if(!*from_p || *from_p == '0') {
+      len=5;
+      strncpy(s, "0.0e0", len+1);
+    } else {
+      char* to_p=s;
+      int n;
+      
+      if(*from_p == '-') {
+        *to_p++ = *from_p++;
+        from_len--;
+      }
+
+      *to_p++ = *from_p++;
+      from_len--;
+      *to_p++ = '.';
+      /* rest of mantissa */
+      /* remove trailing 0s */
+      while(from_len > 1 && from_p[from_len-1]=='0')
+        from_len--;
+      strncpy(to_p, from_p, from_len);
+      to_p += from_len;
+      /* exp */
+      n=sprintf(to_p, "e%ld", expo-1);
+      len=to_p+n-s;
+    }
+    mpfr_free_str((char*)mpf_s);
+  }
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_s=mpf_get_str(NULL, &expo, 10, 0, dec->raw);
+  if(mpf_s) {
+    size_t from_len=strlen(mpf_s);
+    char *from_p=mpf_s;
+    size_t to_len;
+
+    /* 7=strlen("0.0e0")+1 for sign */
+    to_len=!from_len ? 6 : (from_len*2);
+
+    s=RASQAL_MALLOC(cstring, to_len+1);
+    if(!s) {
+      free(mpf_s);
+      return NULL;
+    }
+    /* first digit of mantissa */
+    if(!*from_p || *from_p == '0') {
+      len=5;
+      strncpy(s, "0.0e0", len+1);
+    } else {
+      char *to_p=s;
+      int n;
+      
+      if(*from_p == '-') {
+        *to_p++ = *from_p++;
+        from_len--;
+      }
+
+      *to_p++ = *from_p++;
+      from_len--;
+      *to_p++ = '.';
+      /* rest of mantissa */
+      strncpy(to_p, from_p, from_len);
+      to_p+= from_len;
+      /* exp */
+      n=sprintf(to_p, "e%ld", expo-1);
+      len=to_p+n-s;
+    }
+    free(mpf_s);
+  }
+#endif
+#ifdef RASQAL_DECIMAL_NONE
+  {
+    char *p, *p2;
+    char fmt[16];
+    /* construct a format string */
+    snprintf(fmt, sizeof(fmt), "%%.%de", dec->precision_digits);
+    
+    /* snprintf with no buffer to get buffer length */
+    len=snprintf(NULL, 0, fmt, dec->raw)+1;
+    s=(char*)RASQAL_MALLOC(cstring, len);
+    if(!s)
+      return NULL;
+
+    /* format with snprintf */
+    snprintf(s, len, fmt, dec->raw);
+
+    /* "1.2000e+02"
+     * - remove zeros before 'e', leave one for ".0"
+     * - remove '+' after 'e' (leave '-')
+     * - remove leading zero after 'e' */
+
+    /* find 'e' */
+    p=strchr(s, 'e');
+
+    /* move 'e' and everything that follows on top of the trailing zeros */
+    for(p2=p; *--p2 == '0'; ) ;
+    if(*p2=='.') p2++; /* leave ".0" */
+    p2++;
+    
+    /* move string tail if required */
+    if(p != p2)
+      while((*p2++=*p++)) ;
+
+    /* adjust p to the first char after 'e' */
+    p=strchr(s, 'e');
+    p++;
+
+    /* leave '-' but remove '+' */
+    if(*p=='-') {
+      p++;
+      p2=p;
+    } else {
+      p2=p+1;
+    }
+    /* skip leading zero afer "e[+-]" */
+    if(*p2=='0') p2++;
+
+    /* move string tail if required */
+    if(p != p2)
+      while((*p++=*p2++)) ;
+
+    len=strlen(s);
+  }
+#endif
+
+  dec->string=s;
+  dec->string_len=len;
+  return s;
+}
+
+
+/**
+ * rasqal_xsd_decimal_as_counted_string:
+ * @dec: XSD Decimal
+ * @len_p: pointer to length variable (or NULL)
+ * 
+ * Get an XSD Decimal as a string lexical form with optional length.
+ *
+ * The returned string is shared and owned by the @dec object and
+ * must be copied.  If @len_p is not NULL, the length of the returned
+ * string is stored.
+ * 
+ * Return value: lexical form string or NULL on failure.
+ **/
+char*
+rasqal_xsd_decimal_as_counted_string(rasqal_xsd_decimal* dec, size_t* len_p)
+{
+  char* s=rasqal_xsd_decimal_as_string(dec);
+  if(s && len_p)
+    *len_p=dec->string_len;
+  return s;
+}
+
+
+/**
+ * rasqal_xsd_decimal_print:
+ * @dec: XSD Decimal
+ * @stream: FILE* stream
+ * 
+ * Write an XSD Decimal to a FILE* stream
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_print(rasqal_xsd_decimal* dec, FILE* stream)
+{
+  char* s=NULL;
+  size_t len=0;
+  
+  s=rasqal_xsd_decimal_as_counted_string(dec, &len);
+  if(!s)
+    return 1;
+  
+  fwrite(s, 1, len, stream);
+  return 0;
+}
+
+
+/**
+ * rasqal_xsd_decimal_add:
+ * @result: result variable
+ * @a: argment decimal 1
+ * @b: argument decimal 2
+ * 
+ * Add two XSD Decimals and store in result XSD Decimal
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_add(rasqal_xsd_decimal* result, 
+                       rasqal_xsd_decimal* a, rasqal_xsd_decimal* b)
+{
+  int rc=0;
+
+  rasqal_xsd_decimal_clear_string(result);
+  
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  result->raw = a->raw + b->raw;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  rc=mpfr_add(result->raw, a->raw, b->raw, result->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_add(result->raw, a->raw, b->raw);
+#endif
+
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_subtract:
+ * @result: result variable
+ * @a: argment decimal 1
+ * @b: argument decimal 2
+ * 
+ * Subtract two XSD Decimals and store in result XSD Decimal
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_subtract(rasqal_xsd_decimal* result, 
+                            rasqal_xsd_decimal* a, rasqal_xsd_decimal* b)
+{
+  int rc=0;
+  
+  rasqal_xsd_decimal_clear_string(result);
+  
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  result->raw = a->raw - b->raw;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  rc=mpfr_sub(result->raw, a->raw, b->raw, result->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_sub(result->raw, a->raw, b->raw);
+#endif
+
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_multiply:
+ * @result: result variable
+ * @a: argment decimal 1
+ * @b: argument decimal 2
+ * 
+ * Multiply two XSD Decimals and store in result XSD Decimal
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_multiply(rasqal_xsd_decimal* result, 
+                            rasqal_xsd_decimal* a, rasqal_xsd_decimal* b)
+{
+  int rc=0;
+  
+  rasqal_xsd_decimal_clear_string(result);
+  
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  result->raw = a->raw * b->raw;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  rc=mpfr_mul(result->raw, a->raw, b->raw, result->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_mul(result->raw, a->raw, b->raw);
+#endif
+
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_is_zero:
+ * @d: decimal
+ * 
+ * Test if an XSD decimal is zero.
+ *
+ * Return value: non-0 if decimal is zero
+ **/
+int
+rasqal_xsd_decimal_is_zero(rasqal_xsd_decimal* d)
+{
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  if(!d->raw)
+    return 1;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  if(mpfr_zero_p(d->raw))
+    return 1;
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  if(!mpf_sgn(d->raw))
+    return 1;
+#endif
+
+  return 0;
+}
+
+
+/**
+ * rasqal_xsd_decimal_divide:
+ * @result: result variable
+ * @a: argment decimal 1
+ * @b: argument decimal 2
+ * 
+ * Divide two XSD Decimals and store in result XSD Decimal
+ *
+ * If the divisor @b is 0, failure is returned
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_divide(rasqal_xsd_decimal* result, 
+                          rasqal_xsd_decimal* a, rasqal_xsd_decimal* b)
+{
+  int rc=0;
+  
+  rasqal_xsd_decimal_clear_string(result);
+
+  if(rasqal_xsd_decimal_is_zero(b))
+    return 1;
+  
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  result->raw = a->raw / b->raw;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  rc=mpfr_div(result->raw, a->raw, b->raw, result->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_div(result->raw, a->raw, b->raw);
+#endif
+
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_negate:
+ * @result: result variable
+ * @a: argment decimal
+ * 
+ * Negate an XSD Decimal
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_xsd_decimal_negate(rasqal_xsd_decimal* result, rasqal_xsd_decimal* a)
+{
+  int rc=0;
+  
+  rasqal_xsd_decimal_clear_string(result);
+  
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  result->raw = -a->raw;
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  rc=mpfr_neg(result->raw, a->raw, result->rounding);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  mpf_neg(result->raw, a->raw);
+#endif
+
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_compare:
+ * @a: first XSD decimal
+ * @b: second XSD decimal
+ * 
+ * Compare two XSD Decimals
+ * 
+ * Return value: <0 if @a is less than @b, 0 if equal, >1 otherwise
+ **/
+int
+rasqal_xsd_decimal_compare(rasqal_xsd_decimal* a, rasqal_xsd_decimal* b)
+{
+  int rc=0;
+  
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  rc= (int)(b->raw - a->raw);
+#endif
+#ifdef RASQAL_DECIMAL_MPFR
+  rc=mpfr_cmp(a->raw, b->raw);
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+  rc=mpf_cmp(a->raw, b->raw);
+#endif
+
+  return rc;
+}
+
+
+/**
+ * rasqal_xsd_decimal_equals:
+ * @a: first XSD Decimal
+ * @b: second XSD Decimal
+ * 
+ * Compare two XSD Decimals for equality.
+ * 
+ * Return value: non-0 if equal.
+ **/
+int
+rasqal_xsd_decimal_equals(rasqal_xsd_decimal* a, rasqal_xsd_decimal* b)
+{
+  int rc;
+  
+#if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE)
+  rc= (b->raw == a->raw);
+#elif defined(RASQAL_DECIMAL_MPFR)
+  rc=mpfr_equal_p(a->raw, b->raw);
+#elif defined(RASQAL_DECIMAL_GMP)
+  /* NOTE: Not using mpf_eq() but could do, with sufficient bits */
+  rc=!mpf_cmp(a->raw, b->raw);
+#else
+#error RASQAL_DECIMAL flagging error
+#endif
+
+  return rc;
+}
+
+
+#ifdef STANDALONE
+#include <stdio.h>
+
+int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[]) {
+  char const *program=rasqal_basename(*argv);
+  int failures=0;
+  rasqal_xsd_decimal a;
+  rasqal_xsd_decimal b;
+  rasqal_xsd_decimal *result;
+  rasqal_xsd_decimal *result2;
+  double result_d;
+  char *result_s;
+  int result_i;
+  const long a_long=1234567890L;
+  const double a_double=1234567890e0;
+  const char* b_string="123456789012345678e0";
+  const char* expected_a_plus_b="1.23456790246913568e17";
+  const char* expected_a_plus_b_minus_b="1.23456789e9";
+  const char* expected_a_plus_b_minus_b_minus_a="0.0e0";
+  const char* expected_negative_b="-1.23456789012345678e17";
+  int expected_a_compare_b= -1;
+  int expected_a_equals_b= 0;
+
+#ifdef RASQAL_DECIMAL_MPFR
+  fprintf(stderr, "%s: Using MPFR %s\n", program, mpfr_get_version());
+#endif
+#ifdef RASQAL_DECIMAL_GMP
+#ifdef HAVE_GMP_VERSION
+  fprintf(stderr, "%s: Using GMP %s\n", program, gmp_version);
+#else
+  fprintf(stderr, "%s: Using GMP version unknown\n", program);
+#endif
+#endif
+#ifdef RASQAL_DECIMAL_NONE
+  fprintf(stderr, "%s: Using double\n", program);
+#endif
+
+#ifdef RASQAL_DECIMAL_NONE
+#define FAIL_LABEL
+#define FAIL failures++
+#else
+#define FAIL_LABEL tidy:
+#define FAIL failures++; goto tidy
+#endif
+
+  rasqal_xsd_decimal_init(&a);
+  rasqal_xsd_decimal_init(&b);
+
+  result=rasqal_new_xsd_decimal();
+  result2=rasqal_new_xsd_decimal();
+  if(!result || !result2) {
+    fprintf(stderr, "%s: rasqal_new_xsd_decimal() failed\n", program);
+    FAIL;
+  }
+
+  rasqal_xsd_decimal_set_long(&a, a_long);
+  rasqal_xsd_decimal_set_string(&b, b_string);
+
+  result_d=rasqal_xsd_decimal_get_double(&a);
+  if(result_d != a_double) {
+    fprintf(stderr, "FAILED: a=%f expected %f\n", result_d, a_double);
+    FAIL;
+  }
+
+  result_s=rasqal_xsd_decimal_as_string(&b);
+  if(strcmp(result_s, b_string)) {
+    fprintf(stderr, "FAILED: b=%s expected %s\n", result_s, b_string);
+    FAIL;
+  }
+
+  /* result = a+b */
+  rasqal_xsd_decimal_add(result, &a, &b);
+
+  result_s=rasqal_xsd_decimal_as_string(result);
+  if(strcmp(result_s, expected_a_plus_b)) {
+    fprintf(stderr, "FAILED: a+b=%s expected %s\n", result_s, 
+            expected_a_plus_b);
+    FAIL;
+  }
+  
+  /* result2 = result-b */
+  rasqal_xsd_decimal_subtract(result2, result, &b);
+
+  result_s=rasqal_xsd_decimal_as_string(result2);
+  if(strcmp(result_s, expected_a_plus_b_minus_b)) {
+    fprintf(stderr, "FAILED: (a+b)-b=%s expected %s\n", result_s, 
+            expected_a_plus_b_minus_b);
+    FAIL;
+  }
+
+  /* result = result2-a */
+  rasqal_xsd_decimal_subtract(result, result2, &a);
+
+  result_s=rasqal_xsd_decimal_as_string(result);
+  if(strcmp(result_s, expected_a_plus_b_minus_b_minus_a)) {
+    fprintf(stderr, "FAILED: (a+b)-b-a=%s expected %s\n", result_s, 
+            expected_a_plus_b_minus_b_minus_a);
+    FAIL;
+  }
+
+  result_i=rasqal_xsd_decimal_compare(&a, &b);
+  if((expected_a_compare_b < 0 && result_i >= 0) ||
+     (expected_a_compare_b > 0 && result_i <= 0) ||
+     (expected_a_compare_b == 0 && result_i != 0))
+  {
+    fprintf(stderr, "FAILED: a compare b = %d expected %d\n",
+            result_i, expected_a_compare_b);
+    FAIL;
+  }
+
+  result_i=rasqal_xsd_decimal_equals(&a, &b);
+  if(result_i != expected_a_equals_b) {
+    fprintf(stderr, "FAILED: a equals b = %d expected %d\n",
+            result_i, expected_a_equals_b);
+    FAIL;
+  }
+
+  /* result2 = -b */
+  rasqal_xsd_decimal_negate(result, &b);
+
+  result_s=rasqal_xsd_decimal_as_string(result);
+  if(strcmp(result_s, expected_negative_b)) {
+    fprintf(stderr, "FAILED: -b=%s expected %s\n", result_s, 
+            expected_negative_b);
+    FAIL;
+  }
+
+
+  FAIL_LABEL
+  rasqal_xsd_decimal_clear(&a);
+  rasqal_xsd_decimal_clear(&b);
+  if(result)
+     rasqal_free_xsd_decimal(result);
+  if(result2)
+     rasqal_free_xsd_decimal(result2);
+
+#ifdef RASQAL_DECIMAL_NONE
+  if(failures)
+    fprintf(stderr, "%s: ignoring %d failures as RASQAL_DECIMAL_NONE specified\n", program, failures);
+  return 0;
+#else
+  return failures;
+#endif
+}
+#endif
diff --git a/src/rasqal/rasqal_engine.c b/src/rasqal/rasqal_engine.c
new file mode 100644
index 0000000..f27aeca
--- /dev/null
+++ b/src/rasqal/rasqal_engine.c
@@ -0,0 +1,1783 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_engine.c - Rasqal query engine
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+/**
+ *
+ * Query Engine 1 Internals
+ *
+ * This is the rasqal 0.9.16 and earlier query engine.
+ *
+ * This query engine is based on executing directly the query graph
+ * pattern structure by using graph-pattern specific data objects
+ * to preserve execution state.
+ *
+ * This version was refactored from earlier version code to return
+ * #rasqal_row on demand or all rows in one go if required.
+ *
+ * The lower-level query engine operates over a triples source
+ * factory that returns triples that match a triple pattern for a
+ * graph and bindings variables or determines if a triple is present
+ * in a graph.
+ *
+ * Each graph pattern data records information per-triple pattern
+ * (#rasqal_triple_meta), the current 'column' aka absolute triple#
+ * being executed and various flags and counts.  It iterates over the
+ * triple patterns until they are all exhausted.
+ *
+ * For a basic graph pattern (#RASQAL_GRAPH_PATTERN_OPERATOR_BASIC),
+ * every triple_meta in every column must match for a result to be
+ * returned.  A match may bind 0 or more variables per triple.
+ *
+ * For an optional graph pattern
+ * (#RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL), a result may be
+ * returned even if there are no matches; i.e. an optional graph
+ * pattern always succeeds.  This is the flaw in this execution
+ * engine since in the case where there are multiple optionals it
+ * cannot properly iterate across them when some match and some do
+ * not.
+ *
+ * The execution engine also does not understand group graph patterns
+ * and expects a single top-level sequence of graph patterns (group)
+ * that are basic graph patterns or optional.  Filters are expected
+ * to be contained in the basic or optional graph patterns and
+ * rasqal_query_engine_1_execute_transform_hack() is used to
+ * transform via a hack to turn the query structure into one that can
+ * be executed.
+ *
+ * An internal rowsource is constructed by
+ * rasqal_engine_make_rowsource() in order to get all result rows
+ * in rasqal_query_engine_1_get_all_rows() but is otherwise only
+ * referenced.
+ */
+
+
+#if 0
+#undef RASQAL_DEBUG
+#define RASQAL_DEBUG 2
+#endif
+
+
+#define DEBUG_FH stderr
+
+
+
+/* local types */
+
+/* The execution data here is a sequence of
+ * rasqal_graph_pattern_data execution data of size
+ * query->graph_pattern_count with each rasqal_graph_pattern_data
+ */
+typedef struct {
+  rasqal_query* query;
+  rasqal_query_results* query_results;
+                          
+  raptor_sequence* seq;
+
+  rasqal_triples_source* triples_source;
+
+  /* New variables bound from during the current 'next result' run */
+  int new_bindings_count;
+
+  /* Source of rows that are filling the query result */
+  rasqal_rowsource* rowsource;
+
+  /* how many results already found (for get_row to check limit/offset) */
+  int result_count;
+
+  /* number of variables in a row */
+  int size;
+} rasqal_engine_execution_data;
+
+
+typedef enum {
+  STEP_UNKNOWN,
+  STEP_SEARCHING,
+  STEP_GOT_MATCH,
+  STEP_FINISHED,
+  STEP_ERROR,
+
+  STEP_LAST = STEP_ERROR
+} rasqal_engine_step;
+
+
+#ifdef RASQAL_DEBUG
+static const char * rasqal_engine_step_names[STEP_LAST+1] = {
+  "<unknown>",
+  "searching",
+  "got match",
+  "finished",
+  "error"
+};
+#endif
+
+
+
+/* local prototypes */
+static rasqal_engine_step rasqal_engine_check_constraint(rasqal_engine_execution_data* execution_data, rasqal_graph_pattern *gp);
+static int rasqal_engine_graph_pattern_init(rasqal_engine_execution_data* execution_data, rasqal_graph_pattern *gp);
+
+
+typedef struct {
+  rasqal_graph_pattern* gp;
+  
+  /* An array of items, one per triple in the pattern graph */
+  rasqal_triple_meta* triple_meta;
+
+  /* Executing column in the current graph pattern */
+  int column;
+
+  /* first graph_pattern in sequence with flags RASQAL_TRIPLE_FLAGS_OPTIONAL */
+  int optional_graph_pattern;
+
+  /* current position in the sequence */
+  int current_graph_pattern;
+
+  /* Count of all optional matches for the current mandatory matches */
+  int optional_graph_pattern_matches_count;
+
+  /* Number of matches returned */
+  int matches_returned;
+
+  /* true when this graph pattern matched last time */
+  int matched;
+
+  /* true when an optional graph pattern finished last time round */
+  int finished;
+
+  /* Max optional graph pattern allowed so far to stop backtracking
+   * going over old graph patterns
+   */
+  int max_optional_graph_pattern;
+
+} rasqal_engine_gp_data;
+
+
+static rasqal_engine_gp_data*
+rasqal_new_engine_gp_data(rasqal_graph_pattern* gp) 
+{
+  rasqal_engine_gp_data* gp_data;
+  
+  gp_data = (rasqal_engine_gp_data*)RASQAL_CALLOC(rasqal_engine_gp_data, 1,
+                                                  sizeof(rasqal_engine_gp_data));
+  if(!gp_data)
+    return NULL;
+  
+  gp_data->gp = gp;
+  
+  gp_data->optional_graph_pattern= -1;
+  gp_data->matches_returned = 0;
+  gp_data->column= -1;
+
+  return gp_data;
+}
+
+
+static void
+rasqal_free_gp_data(rasqal_engine_gp_data* gp_data)
+{
+  rasqal_graph_pattern* gp;
+
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(gp_data, rasqal_engine_gp_data);
+  
+  gp = gp_data->gp;
+  if(gp_data->triple_meta) {
+    if(gp) {
+      while(gp_data->column >= gp->start_column) {
+        rasqal_triple_meta *m;
+        m = &gp_data->triple_meta[gp_data->column - gp->start_column];
+        rasqal_reset_triple_meta(m);
+        gp_data->column--;
+      }
+    }
+    RASQAL_FREE(rasqal_triple_meta, gp_data->triple_meta);
+    gp_data->triple_meta = NULL;
+  }
+
+  RASQAL_FREE(rasqal_engine_gp_data, gp_data);
+  return;
+}
+
+
+/**
+ * rasqal_engine_group_graph_pattern_get_next_match:
+ * @query_results: Query results to execute
+ * @gp: group graph pattern
+ *
+ * INTERNAL - Get the next match in a group graph pattern
+ *
+ * return: <0 failure, 0 end of results, >0 match
+ */
+static int
+rasqal_engine_group_graph_pattern_get_next_match(rasqal_engine_execution_data* execution_data,
+                                                 rasqal_graph_pattern* gp)
+{
+  rasqal_query* query;
+  rasqal_query_results* query_results;
+
+  query = execution_data->query;
+  query_results = execution_data->query_results;
+
+#if 0
+  rasqal_engine_gp_data* gp_data;
+
+  gp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                           gp->gp_index);
+#endif
+
+  /* FIXME - sequence of graph_patterns not implemented, finish */
+  rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                          &query->locator,
+                          "Graph pattern %s operation is not implemented yet. Ending query execution.", 
+                          rasqal_graph_pattern_operator_as_string(gp->op));
+  
+  RASQAL_DEBUG1("Failing query with sequence of graph_patterns\n");
+  return -1;
+}
+
+
+/**
+ * rasqal_engine_triple_graph_pattern_get_next_match:
+ * @query_results: Query results to execute
+ * @gp: graph pattern to use
+ *
+ * INTERNAL - Get the next match in a triple graph pattern
+ *
+ * return: <0 failure, 0 end of results, >0 match
+ */
+static int
+rasqal_engine_triple_graph_pattern_get_next_match(rasqal_engine_execution_data* execution_data,
+                                                  rasqal_graph_pattern* gp) 
+{
+  rasqal_query* query;
+  rasqal_query_results* query_results;
+  int rc = 0;
+  rasqal_engine_gp_data* gp_data;
+  
+  query = execution_data->query;
+  query_results = execution_data->query_results;
+  gp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                           gp->gp_index);
+
+  while(gp_data->column >= gp->start_column) {
+    rasqal_triple_meta *m;
+    rasqal_triple *t;
+
+    m = &gp_data->triple_meta[gp_data->column - gp->start_column];
+    t = (rasqal_triple*)raptor_sequence_get_at(gp->triples, gp_data->column);
+
+    rc = 1;
+
+    if(!m) {
+      /* error recovery - no match */
+      gp_data->column--;
+      rc= -1;
+      return rc;
+    }
+    
+    if(m->executed) {
+      RASQAL_DEBUG2("triplesMatch already executed in column %d\n", 
+                    gp_data->column);
+      gp_data->column--;
+      continue;
+    }
+      
+    if (m->is_exact) {
+      /* exact triple match wanted */
+
+      if(!rasqal_triples_source_triple_present(execution_data->triples_source, t)) {
+        /* failed */
+        RASQAL_DEBUG2("exact match failed for column %d\n", gp_data->column);
+        gp_data->column--;
+      }
+#ifdef RASQAL_DEBUG
+      else
+        RASQAL_DEBUG2("exact match OK for column %d\n", gp_data->column);
+#endif
+
+      RASQAL_DEBUG2("end of exact triplesMatch for column %d\n", 
+                    gp_data->column);
+      m->executed = 1;
+      
+    } else {
+      /* triple pattern match wanted */
+      int parts;
+
+      if(!m->triples_match) {
+        /* Column has no triplesMatch so create a new query */
+        m->triples_match = rasqal_new_triples_match(execution_data->query,
+                                                    execution_data->triples_source,
+                                                    m, t);
+        if(!m->triples_match) {
+          rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                                  &query->locator,
+                                  "Failed to make a triple match for column%d",
+                                  gp_data->column);
+          /* failed to match */
+          gp_data->column--;
+          rc= -1;
+          return rc;
+        }
+        RASQAL_DEBUG2("made new triplesMatch for column %d\n", gp_data->column);
+      }
+
+
+      if(rasqal_triples_match_is_end(m->triples_match)) {
+        int resets = 0;
+
+        RASQAL_DEBUG2("end of pattern triplesMatch for column %d\n",
+                      gp_data->column);
+        m->executed = 1;
+
+        resets = rasqal_reset_triple_meta(m);
+        execution_data->new_bindings_count-= resets;
+        if(execution_data->new_bindings_count < 0)
+          execution_data->new_bindings_count = 0;
+
+        gp_data->column--;
+        continue;
+      }
+
+      if(m->parts) {
+        parts = rasqal_triples_match_bind_match(m->triples_match, m->bindings,
+                                                m->parts);
+        RASQAL_DEBUG3("bind_match for column %d returned parts %d\n",
+                      gp_data->column, parts);
+        if(!parts)
+          rc = 0;
+        if(parts & RASQAL_TRIPLE_SUBJECT)
+          execution_data->new_bindings_count++;
+        if(parts & RASQAL_TRIPLE_PREDICATE)
+          execution_data->new_bindings_count++;
+        if(parts & RASQAL_TRIPLE_OBJECT)
+          execution_data->new_bindings_count++;
+        if(parts & RASQAL_TRIPLE_ORIGIN)
+          execution_data->new_bindings_count++;
+      } else {
+        RASQAL_DEBUG2("Nothing to bind_match for column %d\n", gp_data->column);
+      }
+
+      rasqal_triples_match_next_match(m->triples_match);
+      if(!rc)
+        continue;
+
+    }
+    
+    if(gp_data->column == gp->end_column) {
+      /* Done all conjunctions */ 
+      
+      /* exact match, so column must have ended */
+      if(m->is_exact)
+        gp_data->column--;
+
+      /* return with result (rc is 1) */
+      return rc;
+    } else if (gp_data->column >= gp->start_column)
+      gp_data->column++;
+
+  }
+
+  if(gp_data->column < gp->start_column)
+    rc = 0;
+  
+  return rc;
+}
+
+
+
+/**
+ * rasqal_engine_graph_pattern_get_next_match:
+ * @query_results: Query results to execute
+ * @gp: graph pattern to use
+ *
+ * INTERNAL -Get the next match in a graph pattern
+ *
+ * return: <0 failure, 0 end of results, >0 match
+ */
+static int
+rasqal_engine_graph_pattern_get_next_match(rasqal_engine_execution_data* execution_data,
+                                           rasqal_graph_pattern* gp) 
+{
+  if(gp->graph_patterns)
+    return rasqal_engine_group_graph_pattern_get_next_match(execution_data,
+                                                            gp);
+  else
+    return rasqal_engine_triple_graph_pattern_get_next_match(execution_data,
+                                                             gp);
+}
+
+
+
+#if 0
+static int
+rasqal_engine_graph_pattern_order(const void *a, const void *b)
+{
+  rasqal_graph_pattern *gp_a = *(rasqal_graph_pattern**)a;
+  rasqal_graph_pattern *gp_b = *(rasqal_graph_pattern**)b;
+
+  return (gp_a->op == RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL) -
+         (gp_b->op == RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL);
+}
+#endif
+
+
+/**
+ * rasqal_engine_graph_pattern_init:
+ * @query_results: query results to execute
+ * @gp: graph pattern in query results.
+ *
+ * INTERNAL - once only per execution initialisation of a graph pattern.
+ *
+ * Return value: non-0 on failure
+ **/
+static int
+rasqal_engine_graph_pattern_init(rasqal_engine_execution_data* execution_data,
+                                 rasqal_graph_pattern *gp)
+{
+  rasqal_query *query = execution_data->query;
+  rasqal_engine_gp_data* gp_data;
+
+  RASQAL_DEBUG2("Initing execution graph pattern #%d\n", gp->gp_index);
+
+  gp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                           gp->gp_index);
+  if(!gp_data)
+    return -1;
+  
+  gp_data->optional_graph_pattern= -1;
+  gp_data->current_graph_pattern= -1;
+  gp_data->column= -1;
+  gp_data->matches_returned= 0;
+  
+  gp_data->matched= 0;
+  gp_data->finished= 0;
+
+  if(gp->graph_patterns)
+    gp_data->current_graph_pattern = 0;
+
+  if(gp->triples) {
+    int triples_count = gp->end_column - gp->start_column+1;
+    
+    gp_data->column = gp->start_column;
+    if(gp_data->triple_meta) {
+      /* reset any previous execution */
+      rasqal_reset_triple_meta(gp_data->triple_meta);
+      memset(gp_data->triple_meta, '\0',
+             sizeof(rasqal_triple_meta)*triples_count);
+    } else {
+      gp_data->triple_meta = (rasqal_triple_meta*)RASQAL_CALLOC(rasqal_triple_meta, triples_count, sizeof(rasqal_triple_meta));
+      if(!gp_data->triple_meta)
+        return -1;
+    }
+  }
+
+  if(gp->graph_patterns) {
+    int i;
+
+#if 0
+    /* sort graph patterns, optional graph triples last */
+    raptor_sequence_sort(gp->graph_patterns, rasqal_engine_graph_pattern_order);
+#endif
+
+    for(i = 0; i < raptor_sequence_size(gp->graph_patterns); i++) {
+      int rc;
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+      rc = rasqal_engine_graph_pattern_init(execution_data, sgp);
+      if(rc)
+        return rc;
+      
+      if((sgp->op == RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL) &&
+         gp_data->optional_graph_pattern < 0)
+        gp_data->optional_graph_pattern = i;
+    }
+
+  }
+  
+  if(gp->triples) {
+    int i;
+    
+    for(i = gp->start_column; i <= gp->end_column; i++) {
+      rasqal_triple_meta *m;
+      rasqal_triple *t;
+      rasqal_variable* v;
+
+      m = &gp_data->triple_meta[i - gp->start_column];
+      if(!m)
+        return -1;
+      m->parts = (rasqal_triple_parts)0;
+
+      t = (rasqal_triple*)raptor_sequence_get_at(gp->triples, i);
+      
+      if((v = rasqal_literal_as_variable(t->subject)) &&
+         query->variables_declared_in[v->offset] == i)
+        m->parts= (rasqal_triple_parts)(m->parts | RASQAL_TRIPLE_SUBJECT);
+      
+      if((v = rasqal_literal_as_variable(t->predicate)) &&
+         query->variables_declared_in[v->offset] == i)
+        m->parts= (rasqal_triple_parts)(m->parts | RASQAL_TRIPLE_PREDICATE);
+      
+      if((v = rasqal_literal_as_variable(t->object)) &&
+         query->variables_declared_in[v->offset] == i)
+        m->parts= (rasqal_triple_parts)(m->parts | RASQAL_TRIPLE_OBJECT);
+
+      if(t->origin &&
+         (v = rasqal_literal_as_variable(t->origin)) &&
+         query->variables_declared_in[v->offset] == i)
+        m->parts= (rasqal_triple_parts)(m->parts | RASQAL_TRIPLE_ORIGIN);
+
+      RASQAL_DEBUG4("graph pattern #%d Triple %d has parts %d\n",
+                    gp->gp_index, i, m->parts);
+
+      /* exact if there are no variables in the triple parts */
+      m->is_exact = 1;
+      if(rasqal_literal_as_variable(t->predicate) ||
+         rasqal_literal_as_variable(t->subject) ||
+         rasqal_literal_as_variable(t->object))
+        m->is_exact = 0;
+
+    }
+
+  }
+  
+  return 0;
+}
+
+
+static int
+rasqal_engine_remove_filter_graph_patterns(rasqal_query* query,
+                                           rasqal_graph_pattern* gp,
+                                           void *data)
+{
+  int i;
+  int saw_filter_gp = 0;
+  raptor_sequence *seq;
+  int* modified_p = (int*)data;
+  rasqal_graph_pattern* prev_gp = NULL;
+  
+  if(!gp->graph_patterns)
+    return 0;
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("Checking graph pattern #%d:\n  ", gp->gp_index);
+  rasqal_graph_pattern_print(gp, stdout);
+  fputs("\n", stdout);
+#endif
+
+  for(i = 0; i < raptor_sequence_size(gp->graph_patterns); i++) {
+    rasqal_graph_pattern *sgp;
+    sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+    if(sgp->op == RASQAL_GRAPH_PATTERN_OPERATOR_FILTER) {
+      /* One is enough to know we need to rewrite */
+      saw_filter_gp = 1;
+      break;
+    }
+  }
+
+  if(!saw_filter_gp) {
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG2("Ending graph pattern #%d - saw no filter GPs\n",
+                  gp->gp_index);
+#endif
+    return 0;
+  }
+  
+  
+  seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print);
+  if(!seq) {
+    RASQAL_DEBUG1("Cannot create new gp sequence\n");
+    *modified_p = -1;
+    return 1;
+  }
+
+
+  while(raptor_sequence_size(gp->graph_patterns) > 0) {
+    rasqal_graph_pattern *sgp;
+    sgp = (rasqal_graph_pattern*)raptor_sequence_unshift(gp->graph_patterns);
+    if(sgp->op == RASQAL_GRAPH_PATTERN_OPERATOR_FILTER) {
+      if(prev_gp)
+        rasqal_graph_pattern_move_constraints(prev_gp, sgp);
+      rasqal_free_graph_pattern(sgp);
+      continue;
+    }
+    if(raptor_sequence_push(seq, sgp)) {
+      RASQAL_DEBUG1("Cannot push to gp sequence\n");
+      raptor_free_sequence(seq);
+      *modified_p = -1;
+      return 1;
+    }
+    prev_gp = sgp;
+  }
+  raptor_free_sequence(gp->graph_patterns);
+  gp->graph_patterns = seq;
+
+  if(!*modified_p)
+    *modified_p = 1;
+  
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("Ending graph pattern #%d\n  ", gp->gp_index);
+  rasqal_graph_pattern_print(gp, stdout);
+  fputs("\n\n", stdout);
+#endif
+
+  return 0;
+}
+
+
+static void
+rasqal_engine_move_to_graph_pattern(rasqal_engine_execution_data* execution_data,
+                                    rasqal_graph_pattern *gp,
+                                    int delta)
+{
+  rasqal_engine_gp_data* gp_data;
+  int graph_patterns_size = raptor_sequence_size(gp->graph_patterns);
+  int i;
+  
+  gp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                           gp->gp_index);
+
+  if(gp_data->optional_graph_pattern  < 0 ) {
+    gp_data->current_graph_pattern += delta;
+    RASQAL_DEBUG3("Moved to graph pattern %d (delta %d)\n", 
+                  gp_data->current_graph_pattern, delta);
+    return;
+  }
+  
+  /* Otherwise, there are optionals */
+
+  if(delta > 0) {
+    gp_data->current_graph_pattern++;
+    if(gp_data->current_graph_pattern == gp_data->optional_graph_pattern) {
+      RASQAL_DEBUG1("Moved to first optional graph pattern\n");
+      for(i = gp_data->current_graph_pattern; i < graph_patterns_size; i++) {
+        rasqal_graph_pattern *gp2;
+        gp2 = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+        rasqal_engine_graph_pattern_init(execution_data, gp2);
+      }
+      gp_data->max_optional_graph_pattern = graph_patterns_size-1;
+    }
+    gp_data->optional_graph_pattern_matches_count = 0;
+  } else {
+    RASQAL_DEBUG1("Moving to previous graph pattern\n");
+
+    if(gp_data->current_graph_pattern > gp_data->optional_graph_pattern) {
+      rasqal_graph_pattern *gp2;
+      gp2 = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns,
+                                                          gp_data->current_graph_pattern);
+      rasqal_engine_graph_pattern_init(execution_data, gp2);
+    }
+    gp_data->current_graph_pattern--;
+  }
+}
+
+
+static rasqal_engine_step
+rasqal_engine_check_constraint(rasqal_engine_execution_data* execution_data,
+                               rasqal_graph_pattern *gp)
+{
+  rasqal_query* query;
+  rasqal_query_results* query_results;
+  rasqal_engine_step step = STEP_SEARCHING;
+  rasqal_literal* result;
+  int bresult = 1; /* constraint succeeds */
+  int error = 0;
+    
+  query = execution_data->query;
+  query_results = execution_data->query_results;
+
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG1("filter expression:\n");
+  rasqal_expression_print(gp->filter_expression, DEBUG_FH);
+  fputc('\n', DEBUG_FH);
+#endif
+    
+  result = rasqal_expression_evaluate_v2(query->world, &query->locator,
+                                         gp->filter_expression, 
+                                         query->compare_flags);
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG1("filter expression result:\n");
+  if(!result)
+    fputs("type error", DEBUG_FH);
+  else
+    rasqal_literal_print(result, DEBUG_FH);
+  fputc('\n', DEBUG_FH);
+#endif
+  if(!result) {
+    bresult = 0;
+    step = STEP_ERROR;
+  } else {
+    bresult = rasqal_literal_as_boolean(result, &error);
+    if(error) {
+      RASQAL_DEBUG1("filter boolean expression returned error\n");
+      step = STEP_ERROR;
+    }
+#ifdef RASQAL_DEBUG
+    else
+      RASQAL_DEBUG2("filter boolean expression result: %d\n", bresult);
+#endif
+    rasqal_free_literal(result);
+  }
+
+  if(!bresult)
+    /* Constraint failed so move to try next match */
+    return STEP_SEARCHING;
+  
+  return STEP_GOT_MATCH;
+}
+
+
+/**
+ * rasqal_engine_do_step:
+ * @execution_data: execution data
+ * @outergp: outer graph pattern
+ * @gp: inner graph pattern
+ *
+ * INTERNAL - Execute a graph pattern inside an outer graph pattern
+ *
+ * return: <0 failure, 0 end of results, >0 match
+ */
+static rasqal_engine_step
+rasqal_engine_do_step(rasqal_engine_execution_data* execution_data,
+                      rasqal_graph_pattern* outergp, rasqal_graph_pattern* gp)
+{
+  int graph_patterns_size = raptor_sequence_size(outergp->graph_patterns);
+  rasqal_engine_step step = STEP_SEARCHING;
+  int rc;
+  rasqal_engine_gp_data* outergp_data;
+  rasqal_engine_gp_data* gp_data;
+
+  outergp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                                outergp->gp_index);
+  gp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                           gp->gp_index);
+  
+  /*  return: <0 failure, 0 end of results, >0 match */
+  rc = rasqal_engine_graph_pattern_get_next_match(execution_data, gp);
+  
+  RASQAL_DEBUG3("Graph pattern %d returned %d\n",
+                outergp_data->current_graph_pattern, rc);
+  
+  /* no matches is always a failure */
+  if(rc < 0)
+    return STEP_ERROR;
+  
+  if(!rc) {
+    /* otherwise this is the end of the results */
+    RASQAL_DEBUG2("End of non-optional graph pattern %d\n",
+                  outergp_data->current_graph_pattern);
+    
+    return STEP_FINISHED;
+  }
+
+
+  if(gp->filter_expression) {
+    step = rasqal_engine_check_constraint(execution_data, gp);
+    if(step != STEP_GOT_MATCH)
+      return step;
+  }
+
+  if(outergp->filter_expression) {
+    step = rasqal_engine_check_constraint(execution_data, outergp);
+    if(step != STEP_GOT_MATCH)
+      return step;
+  }
+ 
+  /* got match */
+  RASQAL_DEBUG1("Got match\n");
+  gp_data->matched = 1;
+    
+  /* if this is a match but not the last graph pattern in the
+   * sequence move to the next graph pattern
+   */
+  if(outergp_data->current_graph_pattern < graph_patterns_size-1) {
+    RASQAL_DEBUG1("Not last graph pattern\n");
+    rasqal_engine_move_to_graph_pattern(execution_data, outergp, +1);
+    return STEP_SEARCHING;
+  }
+  
+  return STEP_GOT_MATCH;
+}
+
+
+/**
+ * rasqal_engine_do_optional_step:
+ * @execution_data: execution data
+ * @outergp: outer graph pattern
+ * @gp: inner graph pattern
+ *
+ * INTERNAL - Execute an OPTIONAL graph pattern inside an outer graph pattern
+ *
+ * return: <0 failure, 0 end of results, >0 match
+ */
+static rasqal_engine_step
+rasqal_engine_do_optional_step(rasqal_engine_execution_data* execution_data,
+                               rasqal_graph_pattern *outergp,
+                               rasqal_graph_pattern *gp)
+{
+  rasqal_query* query; 
+  rasqal_query_results* query_results;
+  int graph_patterns_size = raptor_sequence_size(outergp->graph_patterns);
+  rasqal_engine_step step = STEP_SEARCHING;
+  int rc;
+  rasqal_engine_gp_data* gp_data;
+  rasqal_engine_gp_data* outergp_data;
+
+  query = execution_data->query;
+  query_results = execution_data->query_results;
+
+  gp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                           gp->gp_index);
+  outergp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                                outergp->gp_index);
+  
+  if(gp_data->finished) {
+    if(!outergp_data->current_graph_pattern) {
+      step = STEP_FINISHED;
+      RASQAL_DEBUG1("Ended first graph pattern - finished\n");
+      return STEP_FINISHED;
+    }
+    
+    RASQAL_DEBUG2("Ended graph pattern %d, backtracking\n",
+                  outergp_data->current_graph_pattern);
+    
+    /* backtrack optionals */
+    rasqal_engine_move_to_graph_pattern(execution_data, outergp, -1);
+    return STEP_SEARCHING;
+  }
+  
+  
+  /*  return: <0 failure, 0 end of results, >0 match */
+  rc = rasqal_engine_graph_pattern_get_next_match(execution_data, gp);
+  
+  RASQAL_DEBUG3("Graph pattern %d returned %d\n",
+                outergp_data->current_graph_pattern, rc);
+  
+  /* count all optional matches */
+  if(rc > 0)
+    outergp_data->optional_graph_pattern_matches_count++;
+
+  if(rc < 0) {
+    /* optional always matches */
+    RASQAL_DEBUG2("Optional graph pattern %d failed to match, continuing\n", 
+                  outergp_data->current_graph_pattern);
+    step = STEP_SEARCHING;
+  }
+  
+  if(!rc) {
+    int i;
+    int mandatory_matches = 0;
+    int optional_matches = 0;
+    
+    /* end of graph_pattern results */
+    step = STEP_FINISHED;
+    
+    /* if this is not the last (optional graph pattern) in the
+     * sequence, move on and continue 
+     */
+    RASQAL_DEBUG2("End of optionals graph pattern %d\n",
+                  outergp_data->current_graph_pattern);
+
+    gp_data->matched = 0;
+    
+    /* Next time we get here, backtrack */
+    gp_data->finished = 1;
+    
+    if(outergp_data->current_graph_pattern < outergp_data->max_optional_graph_pattern) {
+      RASQAL_DEBUG1("More optionals graph patterns to search\n");
+      rasqal_engine_move_to_graph_pattern(execution_data, outergp, +1);
+      return STEP_SEARCHING;
+    }
+
+    outergp_data->max_optional_graph_pattern--;
+    RASQAL_DEBUG2("Max optional graph patterns lowered to %d\n",
+                  outergp_data->max_optional_graph_pattern);
+    
+    /* Last optional match ended.
+     * If we got any non optional matches, then we have a result.
+     */
+    for(i = 0; i < graph_patterns_size; i++) {
+      rasqal_graph_pattern *gp2;
+      rasqal_engine_gp_data* gp2_data;
+
+      gp2 = (rasqal_graph_pattern*)raptor_sequence_get_at(outergp->graph_patterns, i);
+      gp2_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                                gp2->gp_index);
+
+      if(outergp_data->optional_graph_pattern >= 0 &&
+         i >= outergp_data->optional_graph_pattern)
+        optional_matches += gp2_data->matched;
+      else
+        mandatory_matches += gp2_data->matched;
+    }
+    
+    
+    RASQAL_DEBUG2("Optional graph pattern has %d matches returned\n", 
+                  outergp_data->matches_returned);
+    
+    RASQAL_DEBUG2("Found %d query optional graph pattern matches\n", 
+                  outergp_data->optional_graph_pattern_matches_count);
+    
+    RASQAL_DEBUG3("Found %d mandatory matches, %d optional matches\n", 
+                  mandatory_matches, optional_matches);
+    RASQAL_DEBUG2("Found %d new binds\n", execution_data->new_bindings_count);
+    
+    if(optional_matches) {
+      RASQAL_DEBUG1("Found some matches, returning a result\n");
+      return STEP_GOT_MATCH;
+    }
+
+    if(gp_data->matches_returned) { 
+      if(!outergp_data->current_graph_pattern) {
+        RASQAL_DEBUG1("No matches this time and first graph pattern was optional, finished\n");
+        return STEP_FINISHED;
+      }
+
+      RASQAL_DEBUG1("No matches this time, some earlier, backtracking\n");
+      rasqal_engine_move_to_graph_pattern(execution_data, outergp, -1);
+      return STEP_SEARCHING;
+    }
+
+
+    if(execution_data->new_bindings_count > 0) {
+      RASQAL_DEBUG2("%d new bindings, returning a result\n",
+                    execution_data->new_bindings_count);
+      return STEP_GOT_MATCH;
+    }
+    RASQAL_DEBUG1("no new bindings, continuing searching\n");
+    return STEP_SEARCHING;
+  }
+
+  
+  if(gp->filter_expression) {
+    step = rasqal_engine_check_constraint(execution_data, gp);
+    if(step != STEP_GOT_MATCH) {
+      /* The constraint failed or we have an error - no bindings count */
+      execution_data->new_bindings_count = 0;
+      return step;
+    }
+  }
+
+
+  /* got match */
+   
+ /* if this is a match but not the last graph pattern in the
+  * sequence move to the next graph pattern
+  */
+ if(outergp_data->current_graph_pattern < graph_patterns_size-1) {
+   RASQAL_DEBUG1("Not last graph pattern\n");
+   rasqal_engine_move_to_graph_pattern(execution_data, outergp, +1);
+   return STEP_SEARCHING;
+ }
+ 
+
+  if(outergp->filter_expression) {
+    step = rasqal_engine_check_constraint(execution_data, outergp);
+    if(step != STEP_GOT_MATCH) {
+      /* The constraint failed or we have an error - no bindings count */
+      execution_data->new_bindings_count = 0;
+      return STEP_SEARCHING;
+    }
+  }
+
+
+ /* is the last graph pattern so we have a solution */
+
+  RASQAL_DEBUG1("Got match\n");
+  gp_data->matched = 1;
+
+  return STEP_GOT_MATCH;
+}
+
+
+/**
+ * rasqal_engine_get_next_result:
+ * @query_results: query results object
+ *
+ * INTERNAL - Get the next result from a query execution
+ *
+ * return: <0 failure, 0 end of results, >0 match
+ */
+static int
+rasqal_engine_get_next_result(rasqal_engine_execution_data* execution_data)
+{
+  rasqal_query* query;
+  rasqal_query_results *query_results;
+  int graph_patterns_size;
+  rasqal_engine_step step;
+  int i;
+  rasqal_graph_pattern *outergp;
+  rasqal_engine_gp_data* outergp_data;
+
+  query = execution_data->query;
+  query_results = execution_data->query_results;
+
+  outergp = query->query_graph_pattern;
+  if(!outergp || !outergp->graph_patterns) {
+    /* FIXME - no graph patterns in query - end results */
+    rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                            &query->locator,
+                            "No graph patterns in query. Ending query execution.");
+    return -1;
+  }
+  
+  graph_patterns_size = raptor_sequence_size(outergp->graph_patterns);
+  if(!graph_patterns_size) {
+    /* FIXME - no graph patterns in query - end results */
+    rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                            &query->locator,
+                            "No graph patterns in query. Ending query execution.");
+    return -1;
+  }
+
+  outergp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                                outergp->gp_index);
+
+  execution_data->new_bindings_count = 0;
+
+  step = STEP_SEARCHING;
+  while(step == STEP_SEARCHING) {
+    rasqal_graph_pattern* gp;
+    rasqal_engine_gp_data* gp_data;
+    int values_returned = 0;
+    int optional_step;
+    
+    gp = (rasqal_graph_pattern*)raptor_sequence_get_at(outergp->graph_patterns,
+                                                       outergp_data->current_graph_pattern);
+    gp_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                             gp->gp_index);
+    if(!gp_data)
+      return -1;
+
+    RASQAL_DEBUG3("Handling graph_pattern %d %s\n",
+                  outergp_data->current_graph_pattern,
+                  rasqal_graph_pattern_operator_as_string(gp->op));
+
+    if(gp->graph_patterns) {
+      /* FIXME - sequence of graph_patterns not implemented, finish */
+      rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                              &query->locator,
+                              "Graph pattern %s operation is not implemented yet. Ending query execution.", 
+                              rasqal_graph_pattern_operator_as_string(gp->op));
+
+      RASQAL_DEBUG1("Failing query with sequence of graph_patterns\n");
+      step = STEP_ERROR;
+      break;
+    }
+
+    gp_data->matched = 0;
+    optional_step = (gp->op == RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL);
+    
+    if(optional_step)
+      step = rasqal_engine_do_optional_step(execution_data, outergp, gp);
+    else
+      step = rasqal_engine_do_step(execution_data, outergp, gp);
+
+    RASQAL_DEBUG2("Returned step is %s\n",
+                  rasqal_engine_step_names[step]);
+
+    /* Count actual bound values */
+    for(i = 0; i < execution_data->size; i++) {
+      rasqal_variable* v = rasqal_variables_table_get(query->vars_table, i);
+      if(v->value)
+        values_returned++;
+    }
+    RASQAL_DEBUG2("Solution binds %d values\n", values_returned);
+    RASQAL_DEBUG2("New bindings %d\n", execution_data->new_bindings_count);
+
+    if(!values_returned && optional_step &&
+       step != STEP_FINISHED && step != STEP_SEARCHING) {
+      RASQAL_DEBUG1("An optional pass set no bindings, continuing searching\n");
+      step = STEP_SEARCHING;
+    }
+
+  }
+
+
+  RASQAL_DEBUG3("Ending with step %s and graph pattern %d\n",
+                rasqal_engine_step_names[step],
+                outergp_data->current_graph_pattern);
+  
+  if(step == STEP_ERROR)
+    return -1;
+  
+  if(step == STEP_GOT_MATCH) {
+    for(i = 0; i < graph_patterns_size; i++) {
+      rasqal_graph_pattern *gp2;
+      rasqal_engine_gp_data* gp2_data;
+
+      gp2 = (rasqal_graph_pattern*)raptor_sequence_get_at(outergp->graph_patterns, i);
+      gp2_data = (rasqal_engine_gp_data*)raptor_sequence_get_at(execution_data->seq, 
+                                                                gp2->gp_index);
+      if(gp2_data->matched)
+        gp2_data->matches_returned++;
+    }
+
+    /* Got a valid result */
+#ifdef RASQAL_DEBUG
+    RASQAL_DEBUG1("Returning solution[");
+    for(i = 0; i< execution_data->size; i++) {
+      rasqal_variable* v = rasqal_variables_table_get(query->vars_table, i);
+      if(i>0)
+        fputs(", ", DEBUG_FH);
+      fprintf(DEBUG_FH, "%s=", v->name);
+      if(v->value)
+        rasqal_literal_print(v->value, DEBUG_FH);
+      else
+        fputs("NULL", DEBUG_FH);
+    }
+    fputs("]\n", DEBUG_FH);
+#endif
+  }
+
+  /* return 0 = finished, >0 got match */
+  return (step == STEP_GOT_MATCH);
+}
+
+
+/**
+ * rasqal_engine_row_update:
+ * @row: query result row
+ * @offset: integer offset into result values array
+ *
+ * INTERNAL - Update row values from query variables
+ *
+ * Return value: non-0 on failure 
+ */
+static int
+rasqal_engine_row_update(rasqal_query* query, rasqal_row* row, int offset)
+{
+  rasqal_row_set_values_from_variables_table(row, query->vars_table);
+
+  if(row->order_size)
+    rasqal_engine_rowsort_calculate_order_values(query, row);
+  
+  row->offset = offset;
+  
+  return 0;
+}
+
+
+typedef struct 
+{
+  rasqal_query* query;
+  rasqal_query_results* results;
+  rasqal_engine_execution_data* execution_data;
+  rasqal_map* map;
+  raptor_sequence* seq;
+  int need_store_results;
+  int finished;
+  int failed;
+  int offset;
+  int order_size;
+} rasqal_rowsource_engine_context;
+
+
+/* Local handlers for getting rows from a query execution */
+
+static int
+rasqal_rowsource_engine_init(rasqal_rowsource* rowsource, void *user_data) 
+{
+  rasqal_rowsource_engine_context* con;
+
+  con = (rasqal_rowsource_engine_context*)user_data;
+  con->offset = 0;
+  con->finished = 0;
+  con->failed = 0;
+  return 0;
+}
+
+
+static int
+rasqal_rowsource_engine_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_rowsource_engine_context* con;
+
+  con = (rasqal_rowsource_engine_context*)user_data;
+  if(con->map)
+    rasqal_free_map(con->map);
+  if(con->seq)
+    raptor_free_sequence(con->seq);
+  RASQAL_FREE(rasqal_rowsource_engine_context, con);
+
+  return 0;
+}
+
+
+static void
+rasqal_rowsource_engine_process(rasqal_rowsource* rowsource,
+                                rasqal_rowsource_engine_context* con,
+                                int read_all)
+{
+  if(con->finished || con->failed)
+    return;
+  
+  while(1) {
+    rasqal_row* row;
+    int rc;
+
+    /* query_results->results_sequence is NOT assigned before here 
+     * so that this function does the regular query results next
+     * operation.
+     */
+    rc = rasqal_engine_get_next_result(con->execution_data);
+    if(rc == 0) {
+      /* =0 end of results */
+      con->finished = 1;
+      break;
+    }
+    
+    if(rc < 0) {
+      /* <0 failure */
+      con->finished = 1;
+      con->failed = 1;
+      
+      if(con->map) {
+        rasqal_free_map(con->map);
+        con->map = NULL;
+      }
+      raptor_free_sequence(con->seq);
+      con->seq = NULL;
+      break;
+    }
+    
+    /* otherwise is >0 match */
+    row = rasqal_new_row(rowsource);
+    if(!row) {
+      raptor_free_sequence(con->seq); con->seq = NULL;
+      if(con->map) {
+        rasqal_free_map(con->map); con->map = NULL;
+      }
+      con->failed = 1;
+      return;
+    }
+    
+    rc = rasqal_row_set_order_size(row, con->order_size);
+    if(rc) {
+      rasqal_free_row(row);
+      raptor_free_sequence(con->seq); con->seq = NULL;
+      if(con->map) {
+        rasqal_free_map(con->map); con->map = NULL;
+      }
+      con->failed = 1;
+      return;
+    }
+
+    rasqal_engine_row_update(con->query, row, con->offset);
+
+    if(!con->map) {
+      /* no map. after this, row is owned by sequence */
+      raptor_sequence_push(con->seq, row);
+      con->offset++;
+    } else {
+      /* map. after this, row is owned by map */
+      if(!rasqal_engine_rowsort_map_add_row(con->map, row))
+        con->offset++;
+    }
+
+    /* if a row was returned and not storing result, end loop */
+    if(!read_all && !con->need_store_results)
+      return;
+  }
+  
+#ifdef RASQAL_DEBUG
+  if(con->map) {
+    fputs("resulting ", DEBUG_FH);
+    rasqal_map_print(con->map, DEBUG_FH);
+    fputs("\n", DEBUG_FH);
+  }
+#endif
+  
+  if(con->map) {
+    /* do sort/distinct: walk map in order, adding rows to sequence */
+    rasqal_engine_rowsort_map_to_sequence(con->map, con->seq);
+    rasqal_free_map(con->map); con->map = NULL;
+  }
+}
+
+
+static int
+rasqal_rowsource_engine_ensure_variables(rasqal_rowsource* rowsource,
+                                         void *user_data)
+{
+  rasqal_rowsource_engine_context* con;
+  rasqal_query* query;
+
+  con = (rasqal_rowsource_engine_context*)user_data;
+  query = con->query;
+
+  rowsource->size = con->execution_data->size;
+
+  return 0;
+}
+
+
+static rasqal_row*
+rasqal_rowsource_engine_read_row(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_rowsource_engine_context* con;
+
+  con = (rasqal_rowsource_engine_context*)user_data;
+
+  if(con->finished || con->failed)
+    return NULL;
+
+  rasqal_rowsource_engine_process(rowsource, con, 0);
+  if(con->finished || con->failed)
+    return NULL;
+
+  return (rasqal_row*)raptor_sequence_unshift(con->seq);
+}
+
+
+static raptor_sequence*
+rasqal_rowsource_engine_read_all_rows(rasqal_rowsource* rowsource,
+                                      void *user_data)
+{
+  rasqal_rowsource_engine_context* con;
+  raptor_sequence* seq;
+  
+  con = (rasqal_rowsource_engine_context*)user_data;
+
+  if(con->finished || con->failed)
+    return NULL;
+
+  rasqal_rowsource_engine_process(rowsource, con, 1);
+  if(con->failed)
+    return NULL;
+  
+  seq = con->seq;
+  con->seq = NULL;
+  
+  return seq;
+}
+
+
+static const rasqal_rowsource_handler rasqal_rowsource_engine_handler = {
+  /* .version = */ 1,
+  "engine V1",
+  /* .init = */ rasqal_rowsource_engine_init,
+  /* .finish = */ rasqal_rowsource_engine_finish,
+  /* .ensure_variables = */ rasqal_rowsource_engine_ensure_variables,
+  /* .read_row = */ rasqal_rowsource_engine_read_row,
+  /* .read_all_rows = */ rasqal_rowsource_engine_read_all_rows
+};
+
+
+static rasqal_rowsource*
+rasqal_engine_make_rowsource(rasqal_query* query,
+                             rasqal_query_results* results,
+                             rasqal_engine_execution_data* execution_data,
+                             int need_store_results)
+{
+  rasqal_rowsource_engine_context* con;
+  
+  con = (rasqal_rowsource_engine_context*)RASQAL_CALLOC(rasqal_rowsource_engine_context, 1, sizeof(rasqal_rowsource_engine_context));
+  if(!con)
+    return NULL;
+
+  con->query = query;
+  con->results = results;
+  con->execution_data = execution_data;
+  con->need_store_results = need_store_results;
+
+  if(con->need_store_results) {
+    /* make a row:NULL map in order to sort or do distinct */
+    con->map = rasqal_engine_new_rowsort_map(query->distinct,
+                                             query->compare_flags,
+                                             query->order_conditions_sequence);
+    if(!con->map) {
+      rasqal_rowsource_engine_finish(NULL, con);
+      return NULL;
+    }
+
+    if(query->order_conditions_sequence)
+      con->order_size = raptor_sequence_size(query->order_conditions_sequence);
+  }
+  
+  con->seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_row, (raptor_sequence_print_handler*)rasqal_row_print);
+  if(!con->seq) {
+    rasqal_rowsource_engine_finish(NULL, con);
+    return NULL;
+  }
+  
+  return rasqal_new_rowsource_from_handler(query->world, query,
+                                           con,
+                                           &rasqal_rowsource_engine_handler,
+                                           query->vars_table,
+                                           0);
+}
+
+
+/**
+ * rasqal_query_engine_1_get_row:
+ * @ex_data: execution data
+ * @error_p: execution error (OUT variable)
+ *
+ * INTERNAL - Execute a query to get one result, finished or failure.
+ * 
+ * Return value: new row or NULL on finished or failure
+ */
+static rasqal_row*
+rasqal_query_engine_1_get_row(void* ex_data, rasqal_engine_error *error_p)
+{
+  rasqal_engine_execution_data* execution_data;
+  rasqal_query_results* query_results;
+  rasqal_row* row = NULL;
+  
+  execution_data = (rasqal_engine_execution_data*)ex_data;
+
+  query_results = execution_data->query_results;
+
+  if(*error_p != RASQAL_ENGINE_OK)
+    return NULL;
+
+  while(1) {
+    int rc;
+    
+    /* rc<0 error rc=0 end of results,  rc>0 got a result */
+    rc = rasqal_engine_get_next_result(execution_data);
+
+    if(rc < 1) {
+      /* <0 failure OR =0 end of results */
+      *error_p = RASQAL_ENGINE_FINISHED;
+
+      /* <0 failure */
+      if(rc < 0)
+        *error_p = RASQAL_ENGINE_FAILED;
+      break;
+    }
+    
+    /* otherwise is >0 match */
+    execution_data->result_count++;
+
+    /* finished if beyond result range */
+    if(rasqal_query_results_check_limit_offset(query_results) > 0) {
+      execution_data->result_count--;
+      break;
+    }
+
+    /* continue if before start of result range */
+    if(rasqal_query_results_check_limit_offset(query_results) < 0)
+      continue;
+
+    /* else got result or finished */
+    break;
+
+  } /* while */
+
+  if(*error_p == RASQAL_ENGINE_OK) {
+    row = rasqal_new_row(execution_data->rowsource);
+
+    if(row)
+      rasqal_engine_row_update(execution_data->query, row,
+                               execution_data->result_count);
+  }
+  
+  return row;
+}
+
+
+/**
+ * rasqal_query_engine_1_execute_transform_hack:
+ * @query: query object
+ *
+ * INTERNAL - Transform queries in the new query algebra into an executable form understood by the old query engine.
+ *
+ * That means in particular:
+ *
+ * 1) removing RASQAL_GRAPH_PATTERN_OPERATOR_FILTER graph patterns
+ * and moving the constraints to the previous GP in the sequence.
+ * Filter GPs always appear after another GP.
+ *
+ * 2) Ensuring that the root graph pattern is a GROUP even if
+ * there is only 1 GP inside it.
+ *
+ * Return value: non-0 on failure
+ */
+static int
+rasqal_query_engine_1_execute_transform_hack(rasqal_query* query) 
+{
+  if(query->query_graph_pattern) {
+    int modified = 0;
+
+    /* modified is set to 1 if a change was made and -1 on failure */
+    rasqal_query_graph_pattern_visit(query,
+                                     rasqal_engine_remove_filter_graph_patterns,
+                                     &modified);
+      
+#if RASQAL_DEBUG > 1
+    fprintf(DEBUG_FH, "modified=%d after remove filter GPs, query graph pattern now:\n  ", modified);
+    rasqal_graph_pattern_print(query->query_graph_pattern, DEBUG_FH);
+    fputs("\n", DEBUG_FH);
+#endif
+
+    if(modified < 0)
+      return 1;
+
+    if(query->query_graph_pattern->op != RASQAL_GRAPH_PATTERN_OPERATOR_GROUP) {
+      rasqal_graph_pattern* new_qgp;
+
+      new_qgp = rasqal_new_graph_pattern_from_sequence(query, NULL,
+                                                       RASQAL_GRAPH_PATTERN_OPERATOR_GROUP);
+      if(!new_qgp)
+        return 1;
+
+      new_qgp->gp_index = (query->graph_pattern_count++);
+      if(rasqal_graph_pattern_add_sub_graph_pattern(new_qgp,
+                                                    query->query_graph_pattern)) {
+        rasqal_free_graph_pattern(new_qgp);
+        query->query_graph_pattern = NULL;
+        return 1;
+      }
+
+      query->query_graph_pattern = new_qgp;
+
+#if RASQAL_DEBUG > 1
+    fprintf(DEBUG_FH, "after insert top level group GPs, query graph pattern now:\n");
+    rasqal_graph_pattern_print(query->query_graph_pattern, DEBUG_FH);
+    fputs("\n", DEBUG_FH);
+#endif
+    }
+
+  }
+
+  return 0;
+}  
+
+
+/**
+ * rasqal_query_engine_1_execute_init:
+ * @ex_data: execution data
+ * @query: query to execute
+ * @query_results: query results to put results in
+ * @error_p: execution error (OUT variable)
+ *
+ * INTERNAL - Prepare to execute a query.
+ *
+ * Initialises all state for a new query execution but do not
+ * start executing it.
+ *
+ * Return value: non-0 on failure
+ */
+static int
+rasqal_query_engine_1_execute_init(void* ex_data,
+                                   rasqal_query* query,
+                                   rasqal_query_results* query_results,
+                                   int flags,
+                                   rasqal_engine_error *error_p)
+{
+  rasqal_engine_execution_data* execution_data;
+  int rc = 0;
+  int need_store_results= (flags & 1);
+
+  execution_data = (rasqal_engine_execution_data*)ex_data;
+
+  if(!query->triples) {
+    *error_p = RASQAL_ENGINE_FAILED;
+    return 1;
+  }
+  
+  /* FIXME - invoke a temporary transformation to turn queries in the
+   * new query algebra into an executable form understood by this
+   * query engine.
+   */
+  if(rasqal_query_engine_1_execute_transform_hack(query)) {
+    *error_p = RASQAL_ENGINE_FAILED;
+    return 1;
+  }
+  
+
+  /* initialise the execution_data filelds */
+  execution_data->query = query;
+  execution_data->query_results = query_results;
+  execution_data->result_count = 0;
+
+  if(!execution_data->triples_source) {
+    execution_data->triples_source = rasqal_new_triples_source(execution_data->query);
+    if(!execution_data->triples_source) {
+      *error_p = RASQAL_ENGINE_FAILED;
+      return 1;
+    }
+  }
+
+  execution_data->seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_gp_data, NULL);
+  if(!execution_data->seq) {
+    *error_p = RASQAL_ENGINE_FAILED;
+    return 1;
+  }
+
+
+  /* calculate number of variables returned per row */
+  if(query->constructs)
+    execution_data->size = rasqal_variables_table_get_named_variables_count(query->vars_table);
+  else
+    execution_data->size = query->select_variables_count;
+
+
+  /* create all graph pattern-specific execution data */
+  if(query->graph_patterns_sequence) {
+    int i;
+    
+    for(i = 0; i < query->graph_pattern_count; i++) {
+      rasqal_graph_pattern* gp;
+      rasqal_engine_gp_data* gp_data;
+    
+      gp = (rasqal_graph_pattern*)raptor_sequence_get_at(query->graph_patterns_sequence, i);
+      gp_data = rasqal_new_engine_gp_data(gp);
+      if(!gp_data || raptor_sequence_set_at(execution_data->seq, i, gp_data)) {
+        *error_p = RASQAL_ENGINE_FAILED;
+        return 1;
+      }
+    }
+  }
+
+  /* initialise all the graph pattern-specific data */
+  if(query->query_graph_pattern) {
+    rc = rasqal_engine_graph_pattern_init(execution_data, 
+                                          query->query_graph_pattern);
+    if(rc) {
+      *error_p = RASQAL_ENGINE_FAILED;
+      return 1;
+    }
+  }
+
+
+  /* Initialise the rowsource */
+  if(execution_data->rowsource)
+    rasqal_free_rowsource(execution_data->rowsource);
+  execution_data->rowsource = rasqal_engine_make_rowsource(query, query_results,
+                                                           execution_data,
+                                                           need_store_results);
+  if(!execution_data->rowsource) {
+    *error_p = RASQAL_ENGINE_FAILED;
+    return 1;
+  }
+
+  return rc;
+}
+
+
+/**
+ * rasqal_query_engine_1_get_all_rows:
+ * @ex_data: execution data
+ * @error_p: execution error (OUT variable)
+ *
+ * INTERNAL - Execute a query to get all results
+ * 
+ * Return value: all rows or NULL on failure
+ */
+static raptor_sequence*
+rasqal_query_engine_1_get_all_rows(void* ex_data, rasqal_engine_error *error_p)
+{
+  rasqal_engine_execution_data* execution_data;
+  raptor_sequence* seq;
+
+  execution_data = (rasqal_engine_execution_data*)ex_data;
+
+  seq = rasqal_rowsource_read_all_rows(execution_data->rowsource);
+  rasqal_free_rowsource(execution_data->rowsource);
+  execution_data->rowsource = NULL;
+
+  if(!seq)
+    *error_p = RASQAL_ENGINE_FAILED;
+  
+  return seq;
+}
+
+
+/**
+ * rasqal_query_engine_1_execute_finish:
+ * @ex_data: execution data
+ * @error_p: execution error (OUT variable)
+ *
+ * INTERNAL - Finish execution of a query
+ * 
+ * Return value: non-0 on failure
+ */
+static int
+rasqal_query_engine_1_execute_finish(void* ex_data,
+                                     rasqal_engine_error *error_p)
+{
+  rasqal_engine_execution_data* execution_data;
+  execution_data = (rasqal_engine_execution_data*)ex_data;
+
+  if(!execution_data) {
+    *error_p = RASQAL_ENGINE_FAILED;
+    return -1;
+  }
+
+  if(execution_data->triples_source) {
+    rasqal_free_triples_source(execution_data->triples_source);
+    execution_data->triples_source = NULL;
+  }
+
+  if(execution_data->rowsource) {
+    rasqal_free_rowsource(execution_data->rowsource);
+    execution_data->rowsource = NULL;
+  }
+
+  if(execution_data->seq) {
+    raptor_free_sequence(execution_data->seq);
+    execution_data->seq = NULL;
+  }
+
+  return 0;
+}
+
+
+static void
+rasqal_query_engine_1_finish_factory(rasqal_query_execution_factory* factory)
+{
+  return;
+}
+
+
+const rasqal_query_execution_factory rasqal_query_engine_1 =
+{
+  /* .name=                */ "rasqal 0.9.16 engine",
+  /* .execution_data_size= */ sizeof(rasqal_engine_execution_data),
+  /* .execute_init=        */ rasqal_query_engine_1_execute_init,
+  /* .get_all_rows=        */ rasqal_query_engine_1_get_all_rows,
+  /* .get_row=             */ rasqal_query_engine_1_get_row,
+  /* .execute_finish=      */ rasqal_query_engine_1_execute_finish,
+  /* .finish_factory=      */ rasqal_query_engine_1_finish_factory
+};
diff --git a/src/rasqal/rasqal_engine_algebra.c b/src/rasqal/rasqal_engine_algebra.c
new file mode 100644
index 0000000..9415fe1
--- /dev/null
+++ b/src/rasqal/rasqal_engine_algebra.c
@@ -0,0 +1,398 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_engine_algebra.c - Rasqal query engine over query algebra
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#define DEBUG_FH stderr
+
+
+typedef struct {
+  rasqal_query* query;
+  rasqal_query_results* query_results;
+
+  /* query algebra representation of query */
+  rasqal_algebra_node* algebra_node;
+
+  /* number of nodes in #algebra_node tree */
+  int nodes_count;
+
+  /* rowsource that provides the result rows */
+  rasqal_rowsource* rowsource;
+
+  rasqal_triples_source* triples_source;
+} rasqal_engine_algebra_data;
+
+
+static rasqal_rowsource* rasqal_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data, rasqal_algebra_node* node, rasqal_engine_error *error_p);
+
+
+static int
+rasqal_engine_algebra_count_nodes(rasqal_query* query,
+                                  rasqal_algebra_node* node,
+                                  void* data)
+{
+  int *count_p = (int*)data;
+  (*count_p)++;
+  
+  return 0;
+}
+
+
+static rasqal_rowsource*
+rasqal_algebra_basic_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data,
+                                               rasqal_algebra_node* node,
+                                               rasqal_engine_error *error_p)
+{
+  rasqal_query *query = execution_data->query;
+  int size;
+  int *declared_in;
+  int i;
+  
+  size = rasqal_variables_table_get_named_variables_count(query->vars_table);
+  declared_in = (int*)RASQAL_CALLOC(intarray, size+1, sizeof(int));
+  if(!declared_in)
+    return NULL;
+
+  for(i = 0; i < size; i++)
+    declared_in[i] = query->variables_declared_in[i];
+
+  return rasqal_new_triples_rowsource(query->world, query,
+                                      execution_data->triples_source,
+                                      node->triples,
+                                      node->start_column, node->end_column,
+                                      declared_in);
+}
+
+
+static rasqal_rowsource*
+rasqal_algebra_filter_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data,
+                                                rasqal_algebra_node* node,
+                                                rasqal_engine_error *error_p)
+{
+  rasqal_query *query = execution_data->query;
+  rasqal_rowsource *rs;
+
+  rs = rasqal_algebra_node_to_rowsource(execution_data, node->node1, error_p);
+  if(!rs || *error_p)
+    return NULL;
+
+  return rasqal_new_filter_rowsource(query->world, query, rs, node->expr);
+}
+
+
+static rasqal_rowsource*
+rasqal_algebra_orderby_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data,
+                                                 rasqal_algebra_node* node,
+                                                 rasqal_engine_error *error_p)
+{
+  rasqal_query *query = execution_data->query;
+  rasqal_rowsource *rs;
+
+  rs = rasqal_algebra_node_to_rowsource(execution_data, node->node1, error_p);
+  if(!rs || *error_p)
+    return NULL;
+
+  return rasqal_new_sort_rowsource(query->world, query, rs, node->seq);
+}
+
+
+static rasqal_rowsource*
+rasqal_algebra_union_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data,
+                                               rasqal_algebra_node* node,
+                                               rasqal_engine_error *error_p)
+{
+  rasqal_query *query = execution_data->query;
+  rasqal_rowsource *left_rs;
+  rasqal_rowsource *right_rs;
+
+  left_rs = rasqal_algebra_node_to_rowsource(execution_data, node->node1,
+                                             error_p);
+  if(!left_rs || *error_p)
+    return NULL;
+
+  right_rs = rasqal_algebra_node_to_rowsource(execution_data, node->node2,
+                                              error_p);
+  if(!right_rs || *error_p) {
+    rasqal_free_rowsource(left_rs);
+    return NULL;
+  }
+
+  return rasqal_new_union_rowsource(query->world, query, left_rs, right_rs);
+}
+
+
+static rasqal_rowsource*
+rasqal_algebra_project_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data,
+                                                 rasqal_algebra_node* node,
+                                                 rasqal_engine_error *error_p)
+{
+  rasqal_query *query = execution_data->query;
+  rasqal_rowsource *rs;
+
+  rs = rasqal_algebra_node_to_rowsource(execution_data, node->node1,
+                                        error_p);
+  if(!rs || *error_p)
+    return NULL;
+
+  return rasqal_new_project_rowsource(query->world, query, rs, node->vars_seq);
+}
+
+
+static rasqal_rowsource*
+rasqal_algebra_leftjoin_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data,
+                                                  rasqal_algebra_node* node,
+                                                  rasqal_engine_error *error_p)
+{
+  rasqal_query *query = execution_data->query;
+  rasqal_rowsource *left_rs;
+  rasqal_rowsource *right_rs;
+
+  left_rs = rasqal_algebra_node_to_rowsource(execution_data, node->node1,
+                                             error_p);
+  if(!left_rs || *error_p)
+    return NULL;
+
+  right_rs = rasqal_algebra_node_to_rowsource(execution_data, node->node2,
+                                              error_p);
+  if(!right_rs || *error_p) {
+    rasqal_free_rowsource(left_rs);
+    return NULL;
+  }
+
+  return rasqal_new_join_rowsource(query->world, query, left_rs, right_rs, 0, node->expr);
+}
+
+
+static rasqal_rowsource*
+rasqal_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data,
+                                 rasqal_algebra_node* node,
+                                 rasqal_engine_error *error_p)
+{
+  rasqal_rowsource* rs = NULL;
+  
+  switch(node->op) {
+    case RASQAL_ALGEBRA_OPERATOR_BGP:
+      rs = rasqal_algebra_basic_algebra_node_to_rowsource(execution_data,
+                                                          node, error_p);
+      break;
+
+    case RASQAL_ALGEBRA_OPERATOR_FILTER:
+      rs = rasqal_algebra_filter_algebra_node_to_rowsource(execution_data,
+                                                           node, error_p);
+      break;
+
+    case RASQAL_ALGEBRA_OPERATOR_ORDERBY:
+      rs = rasqal_algebra_orderby_algebra_node_to_rowsource(execution_data,
+                                                            node, error_p);
+      break;
+
+    case RASQAL_ALGEBRA_OPERATOR_UNION:
+      rs = rasqal_algebra_union_algebra_node_to_rowsource(execution_data,
+                                                          node, error_p);
+      break;
+
+    case RASQAL_ALGEBRA_OPERATOR_PROJECT:
+      rs = rasqal_algebra_project_algebra_node_to_rowsource(execution_data,
+                                                            node, error_p);
+      break;
+
+    case RASQAL_ALGEBRA_OPERATOR_LEFTJOIN:
+      rs = rasqal_algebra_leftjoin_algebra_node_to_rowsource(execution_data,
+                                                             node, error_p);
+      break;
+
+    case RASQAL_ALGEBRA_OPERATOR_UNKNOWN:
+    case RASQAL_ALGEBRA_OPERATOR_JOIN:
+    case RASQAL_ALGEBRA_OPERATOR_DIFF:
+    case RASQAL_ALGEBRA_OPERATOR_TOLIST:
+    case RASQAL_ALGEBRA_OPERATOR_DISTINCT:
+    case RASQAL_ALGEBRA_OPERATOR_REDUCED:
+    case RASQAL_ALGEBRA_OPERATOR_SLICE:
+    default:
+      RASQAL_DEBUG2("Unsupported algebra node operator %s\n",
+                    rasqal_algebra_node_operator_as_string(node->op));
+      break;
+  }
+
+#if RASQAL_DEBUG
+  if(!rs)
+    abort();
+#endif
+  
+  return rs;
+}
+
+
+
+static int
+rasqal_query_engine_algebra_execute_init(void* ex_data,
+                                         rasqal_query* query,
+                                         rasqal_query_results* query_results,
+                                         int flags,
+                                         rasqal_engine_error *error_p)
+{
+  rasqal_engine_algebra_data* execution_data;
+  rasqal_engine_error error;
+  int rc = 0;
+  
+  execution_data = (rasqal_engine_algebra_data*)ex_data;
+
+  /* initialise the execution_data fields */
+  execution_data->query = query;
+  execution_data->query_results = query_results;
+
+  if(!execution_data->triples_source) {
+    execution_data->triples_source = rasqal_new_triples_source(execution_data->query);
+    if(!execution_data->triples_source) {
+      *error_p = RASQAL_ENGINE_FAILED;
+      return 1;
+    }
+  }
+
+  execution_data->algebra_node = rasqal_algebra_query_to_algebra(query);
+  if(!execution_data->algebra_node)
+    return 1;
+
+  execution_data->nodes_count = 0; 
+  rasqal_algebra_node_visit(query, execution_data->algebra_node,
+                            rasqal_engine_algebra_count_nodes,
+                            &execution_data->nodes_count);
+  
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG1("algebra result: \n");
+  rasqal_algebra_node_print(execution_data->algebra_node, DEBUG_FH);
+  fputc('\n', DEBUG_FH);
+#endif
+  RASQAL_DEBUG2("algebra nodes: %d\n", execution_data->nodes_count);
+
+  error = RASQAL_ENGINE_OK;
+  execution_data->rowsource = rasqal_algebra_node_to_rowsource(execution_data,
+                                                               execution_data->algebra_node,
+                                                               &error);
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG1("rowsource (query plan) result: \n");
+  rasqal_rowsource_print(execution_data->rowsource, DEBUG_FH);
+  fputc('\n', DEBUG_FH);
+#endif
+  if(error != RASQAL_ENGINE_OK)
+    rc = 1;
+  
+  return rc;
+}
+
+
+static raptor_sequence*
+rasqal_query_engine_algebra_get_all_rows(void* ex_data,
+                                         rasqal_engine_error *error_p)
+{
+  rasqal_engine_algebra_data* execution_data;
+  raptor_sequence *seq = NULL;
+  
+  execution_data = (rasqal_engine_algebra_data*)ex_data;
+
+  if(execution_data->rowsource) {
+    seq = rasqal_rowsource_read_all_rows(execution_data->rowsource);
+    if(!seq)
+      *error_p = RASQAL_ENGINE_FAILED;
+  } else
+    *error_p = RASQAL_ENGINE_FAILED;
+
+  return seq;
+}
+
+
+static rasqal_row*
+rasqal_query_engine_algebra_get_row(void* ex_data,
+                                    rasqal_engine_error *error_p)
+{
+  rasqal_engine_algebra_data* execution_data;
+  rasqal_row *row = NULL;
+  
+  execution_data = (rasqal_engine_algebra_data*)ex_data;
+
+  if(execution_data->rowsource) {
+    row = rasqal_rowsource_read_row(execution_data->rowsource);
+    if(!row)
+      *error_p = RASQAL_ENGINE_FINISHED;
+  } else
+    *error_p = RASQAL_ENGINE_FAILED;
+
+  return row;
+}
+
+
+static int
+rasqal_query_engine_algebra_execute_finish(void* ex_data,
+                                           rasqal_engine_error *error_p)
+{
+  rasqal_engine_algebra_data* execution_data;
+
+  execution_data = (rasqal_engine_algebra_data*)ex_data;
+
+  if(execution_data->algebra_node)
+    rasqal_free_algebra_node(execution_data->algebra_node);
+
+  if(execution_data->triples_source)
+    rasqal_free_triples_source(execution_data->triples_source);
+
+  if(execution_data->rowsource)
+    rasqal_free_rowsource(execution_data->rowsource);
+
+  return 0;
+}
+
+
+static void
+rasqal_query_engine_algebra_finish_factory(rasqal_query_execution_factory* factory)
+{
+  return;
+}
+
+
+const rasqal_query_execution_factory rasqal_query_engine_algebra =
+{
+  /* .name=                */ "rasqal query algebra query engine",
+  /* .execution_data_size= */ sizeof(rasqal_engine_algebra_data),
+  /* .execute_init=        */ rasqal_query_engine_algebra_execute_init,
+  /* .get_all_rows=        */ rasqal_query_engine_algebra_get_all_rows,
+  /* .get_row=             */ rasqal_query_engine_algebra_get_row,
+  /* .execute_finish=      */ rasqal_query_engine_algebra_execute_finish,
+  /* .finish_factory=      */ rasqal_query_engine_algebra_finish_factory
+};
diff --git a/src/rasqal/rasqal_engine_sort.c b/src/rasqal/rasqal_engine_sort.c
new file mode 100644
index 0000000..f5f10eb
--- /dev/null
+++ b/src/rasqal/rasqal_engine_sort.c
@@ -0,0 +1,375 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_engine_sort.c - Rasqal query engine row sorting routines
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#define DEBUG_FH stderr
+
+
+/**
+ * rasqal_engine_rowsort_compare_literals_sequence:
+ * @compare_flags: comparison flags for rasqal_literal_compare()
+ * @values_a: first array of literals
+ * @values_b: second array of literals
+ * @expr_sequence: array of expressions
+ * @size: size of arrays
+ *
+ * INTERNAL - compare two arrays of literals evaluated in an array of expressions
+ *
+ * Return value: <0, 0 or >1 comparison
+ */
+static int
+rasqal_engine_rowsort_compare_literals_sequence(int compare_flags,
+                                                rasqal_literal** values_a,
+                                                rasqal_literal** values_b,
+                                                raptor_sequence* expr_sequence,
+                                                int size)
+{
+  int result = 0;
+  int i;
+
+  for(i = 0; i < size; i++) {
+    rasqal_expression* e = NULL;
+    int error = 0;
+    rasqal_literal* literal_a = values_a[i];
+    rasqal_literal* literal_b = values_b[i];
+    
+    if(expr_sequence)
+      e = (rasqal_expression*)raptor_sequence_get_at(expr_sequence, i);
+
+#ifdef RASQAL_DEBUG
+    RASQAL_DEBUG1("Comparing ");
+    rasqal_literal_print(literal_a, DEBUG_FH);
+    fputs(" to ", DEBUG_FH);
+    rasqal_literal_print(literal_b, DEBUG_FH);
+    fputs("\n", DEBUG_FH);
+#endif
+
+    if(!literal_a || !literal_b) {
+      if(!literal_a && !literal_b)
+        result = 0;
+      else {
+        result = literal_a ? 1 : -1;
+#ifdef RASQAL_DEBUG
+        RASQAL_DEBUG2("Got one NULL literal comparison, returning %d\n", result);
+#endif
+        break;
+      }
+    }
+    
+    result = rasqal_literal_compare(literal_a, literal_b,
+                                    compare_flags | RASQAL_COMPARE_URI,
+                                    &error);
+
+    if(error) {
+#ifdef RASQAL_DEBUG
+      RASQAL_DEBUG2("Got literal comparison error at expression %d, returning 0\n", i);
+#endif
+      result = 0;
+      break;
+    }
+        
+    if(!result)
+      continue;
+
+    if(e && e->op == RASQAL_EXPR_ORDER_COND_DESC)
+      result= -result;
+    /* else Order condition is RASQAL_EXPR_ORDER_COND_ASC so nothing to do */
+    
+#ifdef RASQAL_DEBUG
+    RASQAL_DEBUG3("Returning comparison result %d at expression %d\n", result, i);
+#endif
+    break;
+  }
+
+  return result;
+}
+
+
+/**
+ * rasqal_engine_rowsort_literal_sequence_equals:
+ * @values_a: first array of literals
+ * @values_b: second array of literals
+ * @size: size of arrays
+ *
+ * INTERNAL - compare two arrays of literals for equality
+ *
+ * Return value: non-0 if equal
+ */
+static int
+rasqal_engine_rowsort_literal_sequence_equals(rasqal_literal** values_a,
+                                              rasqal_literal** values_b,
+                                              int size)
+{
+  int result = 1; /* equal */
+  int i;
+  int error = 0;
+
+  for(i = 0; i < size; i++) {
+    rasqal_literal* literal_a = values_a[i];
+    rasqal_literal* literal_b = values_b[i];
+    
+    result = rasqal_literal_equals_flags(literal_a, literal_b,
+                                         RASQAL_COMPARE_RDF, &error);
+#ifdef RASQAL_DEBUG
+    RASQAL_DEBUG1("Comparing ");
+    rasqal_literal_print(literal_a, DEBUG_FH);
+    fputs(" to ", DEBUG_FH);
+    rasqal_literal_print(literal_b, DEBUG_FH);
+    fprintf(DEBUG_FH, " gave %s\n", (result ? "equality" : "not equal"));
+#endif
+
+    if(error)
+      result = 0;
+    
+    /* if different, end */
+    if(!result)
+      break;
+  }
+
+  return result;
+}
+
+
+typedef struct 
+{ 
+  int is_distinct;
+  int compare_flags;
+  raptor_sequence* order_conditions_sequence;
+} rowsort_compare_data;
+
+
+static void
+rasqal_engine_rowsort_free_compare_data(const void* user_data)
+{
+  rowsort_compare_data* rcd = (rowsort_compare_data*)user_data;
+
+  RASQAL_FREE(rowsort_compare_data,  rcd);
+}
+
+
+/**
+ * rasqal_engine_rowsort_row_compare:
+ * @user_data: comparison user data pointer
+ * @a: pointer to address of first #row
+ * @b: pointer to address of second #row
+ *
+ * INTERNAL - compare two pointers to #row objects
+ *
+ * Suitable for use as a compare function in qsort_r() or similar.
+ *
+ * Return value: <0, 0 or >1 comparison
+ */
+static int
+rasqal_engine_rowsort_row_compare(void* user_data, const void *a, const void *b)
+{
+  rasqal_row* row_a;
+  rasqal_row* row_b;
+  rowsort_compare_data* rcd;
+  int result = 0;
+  rcd = (rowsort_compare_data*)user_data;
+  row_a = *(rasqal_row**)a;
+  row_b = *(rasqal_row**)b;
+
+  if(rcd->is_distinct) {
+    result = !rasqal_engine_rowsort_literal_sequence_equals(row_a->values,
+                                                            row_b->values,
+                                                            row_a->size);
+    
+    if(!result)
+      /* duplicate, so return that */
+      return 0;
+  }
+  
+  /* now order it */
+  result = rasqal_engine_rowsort_compare_literals_sequence(rcd->compare_flags,
+                                                           row_a->order_values,
+                                                           row_b->order_values,
+                                                           rcd->order_conditions_sequence,
+                                                           row_a->order_size);
+  
+  /* still equal?  make sort stable by using the original order */
+  if(!result) {
+    result = row_a->offset - row_b->offset;
+    RASQAL_DEBUG2("Got equality result so using offsets, returning %d\n",
+                  result);
+  }
+  
+  return result;
+}
+
+
+static void
+rasqal_engine_rowsort_map_free_row(const void *key, const void *value)
+{
+  if(key)
+    rasqal_free_row((rasqal_row*)key);
+  if(value)
+    rasqal_free_row((rasqal_row*)value);
+}
+
+
+static void
+rasqal_engine_rowsort_map_print_row(void *object, FILE *fh)
+{
+  if(object)
+    rasqal_row_print((rasqal_row*)object, fh);
+  else
+    fputs("NULL", fh);
+}
+
+
+/**
+ * rasqal_engine_new_rowsort_map:
+ * @flags: 1: do distinct
+ *
+ * INTERNAL - create a new map for sorting rows
+ *
+ */
+rasqal_map*
+rasqal_engine_new_rowsort_map(int is_distinct, int compare_flags,
+                              raptor_sequence* order_conditions_sequence)
+{
+  rowsort_compare_data* rcd;
+
+  rcd = (rowsort_compare_data*)RASQAL_MALLOC(rowsort_compare_data,
+                                             sizeof(rowsort_compare_data));
+  if(!rcd)
+    return NULL;
+  
+  rcd->is_distinct = is_distinct;
+  rcd->compare_flags = compare_flags;
+  rcd->order_conditions_sequence = order_conditions_sequence;
+  
+  return rasqal_new_map(rasqal_engine_rowsort_row_compare, rcd,
+                        rasqal_engine_rowsort_free_compare_data,
+                        rasqal_engine_rowsort_map_free_row,
+                        rasqal_engine_rowsort_map_print_row,
+                        NULL,
+                        0);
+}
+
+
+/**
+ * rasqal_engine_rowsort_map_add_row:
+ * @map: row map
+ * @row: row to add
+ *
+ * INTERNAL - Add a row o a rowsort_map for sorting
+ *
+ * return value: non-0 if the row was a duplicate (and not added)
+ */
+int
+rasqal_engine_rowsort_map_add_row(rasqal_map* map, rasqal_row* row)
+{
+  /* map. after this, row is owned by map */
+  if(!rasqal_map_add_kv(map, row, NULL))
+    return 0;
+
+  /* duplicate, and not added so delete it */
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG1("Got duplicate row ");
+  rasqal_row_print(row, DEBUG_FH);
+  fputc('\n', DEBUG_FH);
+#endif
+  rasqal_free_row(row);
+
+  return 1;
+}
+
+
+static void
+rasqal_engine_rowsort_map_add_to_sequence(void *key, void *value,
+                                          void *user_data)
+{
+  rasqal_row* row;
+  row = rasqal_new_row_from_row((rasqal_row*)key);
+  raptor_sequence_push((raptor_sequence*)user_data, row);
+}
+
+
+raptor_sequence*
+rasqal_engine_rowsort_map_to_sequence(rasqal_map* map, raptor_sequence* seq)
+{
+
+  /* do sort/distinct: walk map in order, adding rows to seq */
+  rasqal_map_visit(map, rasqal_engine_rowsort_map_add_to_sequence, (void*)seq);
+
+  return seq;
+}
+
+
+/**
+ * rasqal_engine_rowsort_calculate_order_values:
+ * @query: query object
+ * @row: row
+ *
+ * INTERNAL - Calculate the order condition values for a row
+ *
+ * Return value: non-0 on failure 
+ */
+int
+rasqal_engine_rowsort_calculate_order_values(rasqal_query* query,
+                                             rasqal_row* row)
+{
+  int i;
+  
+  if(!row->order_size)
+    return 1;
+  
+  for(i = 0; i < row->order_size; i++) {
+    rasqal_expression* e;
+    rasqal_literal *l;
+    
+    e = (rasqal_expression*)raptor_sequence_get_at(query->order_conditions_sequence, i);
+    l = rasqal_expression_evaluate_v2(query->world, &query->locator,
+                                      e, query->compare_flags);
+    if(row->order_values[i])
+      rasqal_free_literal(row->order_values[i]);
+    if(l) {
+      row->order_values[i] = rasqal_new_literal_from_literal(rasqal_literal_value(l));
+      rasqal_free_literal(l);
+    } else
+      row->order_values[i] = NULL;
+  }
+  
+  return 0;
+}
diff --git a/src/rasqal/rasqal_expr.c b/src/rasqal/rasqal_expr.c
new file mode 100644
index 0000000..07d99fd
--- /dev/null
+++ b/src/rasqal/rasqal_expr.c
@@ -0,0 +1,2547 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_expr.c - Rasqal general expression support
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#ifdef RASQAL_REGEX_PCRE
+#include <pcre.h>
+#endif
+
+#ifdef RASQAL_REGEX_POSIX
+#include <sys/types.h>
+#include <regex.h>
+#endif
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#ifndef STANDALONE
+
+
+/**
+ * rasqal_new_data_graph:
+ * @world: rasqal_world object
+ * @uri: source URI
+ * @name_uri: name of graph (or NULL)
+ * @flags: %RASQAL_DATA_GRAPH_NAMED or %RASQAL_DATA_GRAPH_BACKGROUND
+ * 
+ * Constructor - create a new #rasqal_data_graph.
+ * 
+ * The name_uri is only used when the flags are %RASQAL_DATA_GRAPH_NAMED.
+ * 
+ * Return value: a new #rasqal_data_graph or NULL on failure.
+ **/
+rasqal_data_graph*
+rasqal_new_data_graph(rasqal_world* world, raptor_uri* uri, raptor_uri* name_uri, int flags)
+{
+  rasqal_data_graph* dg = (rasqal_data_graph*)RASQAL_CALLOC(rasqal_data_graph, 1,
+                                                            sizeof(rasqal_data_graph));
+  if(dg) {
+    dg->world = world;
+#ifdef RAPTOR_V2_AVAILABLE
+    dg->uri = raptor_uri_copy_v2(world->raptor_world_ptr, uri);
+    if(name_uri)
+      dg->name_uri = raptor_uri_copy_v2(world->raptor_world_ptr, name_uri);
+#else
+    dg->uri = raptor_uri_copy(uri);
+    if(name_uri)
+      dg->name_uri = raptor_uri_copy(name_uri);
+#endif
+    dg->flags = flags;
+  }
+
+  return dg;
+}
+
+
+/**
+ * rasqal_free_data_graph:
+ * @dg: #rasqal_data_graph object
+ * 
+ * Destructor - destroy a #rasqal_data_graph object.
+ *
+ **/
+void
+rasqal_free_data_graph(rasqal_data_graph* dg)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(dg, rasqal_data_graph);
+
+#ifdef RAPTOR_V2_AVAILABLE  
+  if(dg->uri)
+    raptor_free_uri_v2(dg->world->raptor_world_ptr, dg->uri);
+  if(dg->name_uri)
+    raptor_free_uri_v2(dg->world->raptor_world_ptr, dg->name_uri);
+#else
+  if(dg->uri)
+    raptor_free_uri(dg->uri);
+  if(dg->name_uri)
+    raptor_free_uri(dg->name_uri);
+#endif
+  RASQAL_FREE(rasqal_data_graph, dg);
+}
+
+
+/**
+ * rasqal_data_graph_print:
+ * @dg: #rasqal_data_graph object
+ * @fh: the #FILE* handle to print to
+ *
+ * Print a Rasqal data graph in a debug format.
+ * 
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_data_graph_print(rasqal_data_graph* dg, FILE* fh)
+{
+#ifdef RAPTOR_V2_AVAILABLE
+  if(dg->name_uri)
+    fprintf(fh, "data graph(%s named as %s flags %d)", 
+            raptor_uri_as_string_v2(dg->world->raptor_world_ptr, dg->uri),
+            raptor_uri_as_string_v2(dg->world->raptor_world_ptr, dg->name_uri),
+            dg->flags);
+  else
+    fprintf(fh, "data graph(%s, flags %d)", 
+            raptor_uri_as_string_v2(dg->world->raptor_world_ptr, dg->uri), dg->flags);
+#else
+  if(dg->name_uri)
+    fprintf(fh, "data graph(%s named as %s flags %d)", 
+            raptor_uri_as_string(dg->uri),
+            raptor_uri_as_string(dg->name_uri),
+            dg->flags);
+  else
+    fprintf(fh, "data graph(%s, flags %d)", 
+            raptor_uri_as_string(dg->uri), dg->flags);
+#endif
+}
+
+
+/**
+ * rasqal_new_prefix:
+ * @world: rasqal_world object
+ * @prefix: Short prefix string to stand for URI or NULL.
+ * @uri: Name #raptor_uri.
+ * 
+ * Constructor - create a new #rasqal_prefix.
+ * Takes ownership of prefix and uri.
+ * 
+ * Return value: a new #rasqal_prefix or NULL on failure.
+ **/
+rasqal_prefix*
+rasqal_new_prefix(rasqal_world* world, const unsigned char *prefix, raptor_uri* uri) 
+{
+  rasqal_prefix* p = (rasqal_prefix*)RASQAL_CALLOC(rasqal_prefix, 1,
+                                                   sizeof(rasqal_prefix));
+
+  if(p) {  
+    p->world = world;
+    p->prefix = prefix;
+    p->uri = uri;
+  } else {
+    RASQAL_FREE(cstring, prefix);
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(world->raptor_world_ptr, uri);
+#else
+    raptor_free_uri(uri);
+#endif
+  }
+
+  return p;
+}
+
+
+/**
+ * rasqal_free_prefix:
+ * @p: #rasqal_prefix object.
+ * 
+ * Destructor - destroy a #rasqal_prefix object.
+ **/
+void
+rasqal_free_prefix(rasqal_prefix* p)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(p, rasqal_prefix);
+  
+  if(p->prefix)
+    RASQAL_FREE(cstring, (void*)p->prefix);
+  if(p->uri)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(p->world->raptor_world_ptr, p->uri);
+#else
+    raptor_free_uri(p->uri);
+#endif
+  RASQAL_FREE(rasqal_prefix, p);
+}
+
+
+/**
+ * rasqal_prefix_print:
+ * @p: #rasqal_prefix object.
+ * @fh: The #FILE* handle to print to.
+ *
+ * Print a Rasqal prefix in a debug format.
+ * 
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_prefix_print(rasqal_prefix* p, FILE* fh)
+{
+  fprintf(fh, "prefix(%s as %s)", (p->prefix ? (const char*)p->prefix : "(default)"),
+#ifdef RAPTOR_V2_AVAILABLE
+          raptor_uri_as_string_v2(p->world->raptor_world_ptr, p->uri)
+#else
+          raptor_uri_as_string(p->uri)
+#endif
+          );
+}
+
+
+
+/**
+ * rasqal_new_triple:
+ * @subject: Triple subject.
+ * @predicate: Triple predicate.
+ * @object: Triple object.
+ * 
+ * Constructor - create a new #rasqal_triple triple or triple pattern.
+ * Takes ownership of the literals passed in.
+ * 
+ * The triple origin can be set with rasqal_triple_set_origin().
+ *
+ * Return value: a new #rasqal_triple or NULL on failure.
+ **/
+rasqal_triple*
+rasqal_new_triple(rasqal_literal* subject, rasqal_literal* predicate, rasqal_literal* object)
+{
+  rasqal_triple* t=(rasqal_triple*)RASQAL_CALLOC(rasqal_triple, 1, sizeof(rasqal_triple));
+
+  if(t) {
+    t->subject=subject;
+    t->predicate=predicate;
+    t->object=object;
+  } else {
+    if(subject)
+      rasqal_free_literal(subject);
+    if(predicate)
+      rasqal_free_literal(predicate);
+    if(object)
+      rasqal_free_literal(object);
+  }
+
+  return t;
+}
+
+
+/**
+ * rasqal_new_triple_from_triple:
+ * @t: Triple to copy.
+ * 
+ * Copy constructor - create a new #rasqal_triple from an existing one.
+ * 
+ * Return value: a new #rasqal_triple or NULL on failure.
+ **/
+rasqal_triple*
+rasqal_new_triple_from_triple(rasqal_triple* t)
+{
+  rasqal_triple* newt=(rasqal_triple*)RASQAL_CALLOC(rasqal_triple, 1, sizeof(rasqal_triple));
+
+  if(newt) {
+    newt->subject=rasqal_new_literal_from_literal(t->subject);
+    newt->predicate=rasqal_new_literal_from_literal(t->predicate);
+    newt->object=rasqal_new_literal_from_literal(t->object);
+  }
+
+  return newt;
+}
+
+
+/**
+ * rasqal_free_triple:
+ * @t: #rasqal_triple object.
+ * 
+ * Destructor - destroy a #rasqal_triple object.
+ **/
+void
+rasqal_free_triple(rasqal_triple* t)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(t, rasqal_triple);
+  
+  if(t->subject)
+    rasqal_free_literal(t->subject);
+  if(t->predicate)
+    rasqal_free_literal(t->predicate);
+  if(t->object)
+    rasqal_free_literal(t->object);
+  if(t->origin)
+    rasqal_free_literal(t->origin);
+  RASQAL_FREE(rasqal_triple, t);
+}
+
+
+/**
+ * rasqal_triple_write:
+ * @t: #rasqal_triple object.
+ * @iostr: The #raptor_iostream handle to write to.
+ * 
+ * Write a Rasqal triple to an iostream in a debug format.
+ * 
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_triple_write(rasqal_triple* t, raptor_iostream* iostr)
+{
+  raptor_iostream_write_counted_string(iostr, "triple(", 7);
+  rasqal_literal_write(t->subject, iostr);
+  raptor_iostream_write_counted_string(iostr, ", ", 2);
+  rasqal_literal_write(t->predicate, iostr);
+  raptor_iostream_write_counted_string(iostr, ", ", 2);
+  rasqal_literal_write(t->object, iostr);
+  raptor_iostream_write_byte(iostr, ')');
+  if(t->origin) {
+    raptor_iostream_write_counted_string(iostr, " with origin(", 13);
+    rasqal_literal_write(t->origin, iostr);
+    raptor_iostream_write_byte(iostr, ')');
+  }
+}
+
+
+/**
+ * rasqal_triple_print:
+ * @t: #rasqal_triple object.
+ * @fh: The #FILE* handle to print to.
+ * 
+ * Print a Rasqal triple in a debug format.
+ * 
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_triple_print(rasqal_triple* t, FILE* fh)
+{
+  fputs("triple(", fh);
+  rasqal_literal_print(t->subject, fh);
+  fputs(", ", fh);
+  rasqal_literal_print(t->predicate, fh);
+  fputs(", ", fh);
+  rasqal_literal_print(t->object, fh);
+  fputc(')', fh);
+  if(t->origin) {
+    fputs(" with origin(", fh);
+    rasqal_literal_print(t->origin, fh);
+    fputc(')', fh);
+  }
+}
+
+
+/**
+ * rasqal_triple_set_origin:
+ * @t: The triple object. 
+ * @l: The #rasqal_literal object to set as origin.
+ * 
+ * Set the origin field of a #rasqal_triple.
+ **/
+void
+rasqal_triple_set_origin(rasqal_triple* t, rasqal_literal* l)
+{
+  t->origin=l;
+}
+
+
+/**
+ * rasqal_triple_get_origin:
+ * @t: The triple object. 
+ * 
+ * Get the origin field of a #rasqal_triple.
+ * 
+ * Return value: The triple origin or NULL.
+ **/
+rasqal_literal*
+rasqal_triple_get_origin(rasqal_triple* t)
+{
+  return t->origin;
+}
+
+
+/**
+ * rasqal_new_0op_expression:
+ * @world: rasqal_world object
+ * @op: Expression operator
+ * 
+ * Constructor - create a new 0-operand (constant) expression.
+ *
+ * The operators are:
+ * @RASQAL_EXPR_VARSTAR
+ *
+ * The only operator here is the '*' in COUNT(*) as used by LAQRS.
+ * 
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_0op_expression(rasqal_world* world, rasqal_op op)
+{
+  rasqal_expression* e = (rasqal_expression*)RASQAL_CALLOC(rasqal_expression, 1, sizeof(rasqal_expression));
+  if(e) {
+    e->usage = 1;
+    e->world = world;
+    e->op = op;
+  }
+  return e;
+}
+
+
+/**
+ * rasqal_new_1op_expression:
+ * @world: rasqal_world object
+ * @op: Expression operator
+ * @arg: Operand 1 
+ * 
+ * Constructor - create a new 1-operand expression.
+ * Takes ownership of the operand expression.
+ *
+ * The operators are:
+ * @RASQAL_EXPR_TILDE @RASQAL_EXPR_BANG @RASQAL_EXPR_UMINUS
+ * @RASQAL_EXPR_BOUND @RASQAL_EXPR_STR @RASQAL_EXPR_LANG
+ * @RASQAL_EXPR_LANGMATCHES
+ * @RASQAL_EXPR_DATATYPE @RASQAL_EXPR_ISURI @RASQAL_EXPR_ISBLANK
+ * @RASQAL_EXPR_ISLITERAL @RASQAL_EXPR_ORDER_COND_ASC
+ * @RASQAL_EXPR_ORDER_COND_DESC @RASQAL_EXPR_GROUP_COND_ASC
+ * @RASQAL_EXPR_GROUP_COND_DESC @RASQAL_EXPR_COUNT
+ *
+ * @RASQAL_EXPR_BANG and @RASQAL_EXPR_UMINUS are used by RDQL and
+ * SPARQL.  @RASQAL_EXPR_TILDE by RDQL only.  The rest by SPARQL
+ * only.
+ * 
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_1op_expression(rasqal_world* world, rasqal_op op, rasqal_expression* arg)
+{
+  rasqal_expression* e = NULL;
+
+  if(!arg)
+    goto tidy;
+  
+  e = (rasqal_expression*)RASQAL_CALLOC(rasqal_expression, 1,
+                                        sizeof(rasqal_expression));
+  if(e) {
+    e->usage = 1;
+    e->world = world;
+    e->op = op;
+    e->arg1 = arg; arg = NULL;
+  }
+  
+  tidy:
+  if(arg)
+    rasqal_free_expression(arg);
+
+  return e;
+}
+
+
+/**
+ * rasqal_new_2op_expression:
+ * @world: rasqal_world object
+ * @op: Expression operator
+ * @arg1: Operand 1 
+ * @arg2: Operand 2
+ * 
+ * Constructor - create a new 2-operand expression.
+ * Takes ownership of the operand expressions.
+ * 
+ * The operators are:
+ * @RASQAL_EXPR_AND @RASQAL_EXPR_OR @RASQAL_EXPR_EQ
+ * @RASQAL_EXPR_NEQ @RASQAL_EXPR_LT @RASQAL_EXPR_GT @RASQAL_EXPR_LE
+ * @RASQAL_EXPR_GE @RASQAL_EXPR_PLUS @RASQAL_EXPR_MINUS
+ * @RASQAL_EXPR_STAR @RASQAL_EXPR_SLASH @RASQAL_EXPR_REM
+ * @RASQAL_EXPR_STR_EQ @RASQAL_EXPR_STR_NEQ
+ *
+ * @RASQAL_EXPR_REM @RASQAL_EXPR_STR_EQ and @RASQAL_EXPR_STR_NEQ are
+ * not used by SPARQL. @RASQAL_EXPR_REM is used by RDQL.
+ * 
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_2op_expression(rasqal_world* world,
+                          rasqal_op op,
+                          rasqal_expression* arg1, 
+                          rasqal_expression* arg2)
+{
+  rasqal_expression* e = NULL;
+
+  if(!arg1 || !arg2)
+    goto tidy;
+  
+  e = (rasqal_expression*)RASQAL_CALLOC(rasqal_expression, 1, 
+                                        sizeof(rasqal_expression));
+  if(e) {
+    e->usage = 1;
+    e->world = world;
+    e->op = op;
+    e->arg1 = arg1; arg1 = NULL;
+    e->arg2 = arg2; arg2 = NULL;
+  }
+  
+tidy:
+  if(arg1)
+    rasqal_free_expression(arg1);
+  if(arg2)
+    rasqal_free_expression(arg2);
+
+  return e;
+}
+
+
+/**
+ * rasqal_new_3op_expression:
+ * @world: rasqal_world object
+ * @op: Expression operator
+ * @arg1: Operand 1 
+ * @arg2: Operand 2
+ * @arg3: Operand 3 (may be NULL)
+ * 
+ * Constructor - create a new 3-operand expression.
+ * Takes ownership of the operands.
+ * 
+ * The only operator is:
+ * @RASQAL_EXPR_REGEX
+ *
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_3op_expression(rasqal_world* world,
+                          rasqal_op op,
+                          rasqal_expression* arg1, 
+                          rasqal_expression* arg2,
+                          rasqal_expression* arg3)
+{
+  rasqal_expression* e = NULL;
+
+  if(!arg1 || !arg2) /* arg3 may be NULL */
+    goto tidy;
+
+  e = (rasqal_expression*)RASQAL_CALLOC(rasqal_expression, 1,
+                                        sizeof(rasqal_expression));
+  if(e) {
+    e->usage = 1;
+    e->world = world;
+    e->op = op;
+    e->arg1 = arg1; arg1 = NULL;
+    e->arg2 = arg2; arg2 = NULL;
+    e->arg3 = arg3; arg3 = NULL;
+  }
+
+  tidy:
+  if(arg1)
+    rasqal_free_expression(arg1);
+  if(arg2)
+    rasqal_free_expression(arg2);
+  if(arg3)
+    rasqal_free_expression(arg3);
+
+  return e;
+}
+
+
+/**
+ * rasqal_new_string_op_expression:
+ * @world: rasqal_world object
+ * @op: Expression operator
+ * @arg1: Operand 1 
+ * @literal: Literal operand 2
+ * 
+ * Constructor - create a new expression with one expression and one string operand.
+ * Takes ownership of the operands.
+ *
+ * The operators are:
+ * @RASQAL_EXPR_STR_MATCH (RDQL, SPARQL) and
+ * @RASQAL_EXPR_STR_NMATCH (RDQL)
+ *
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_string_op_expression(rasqal_world* world,
+                                rasqal_op op,
+                                rasqal_expression* arg1,
+                                rasqal_literal* literal)
+{
+  rasqal_expression* e = NULL;
+
+  if(!arg1 || !literal)
+    goto tidy;
+  
+  e = (rasqal_expression*)RASQAL_CALLOC(rasqal_expression, 1,
+                                        sizeof(rasqal_expression));
+  if(e) {
+    e->usage = 1;
+    e->world = world;
+    e->op = op;
+    e->arg1 = arg1; arg1 = NULL;
+    e->literal = literal; literal = NULL;
+  }
+
+  tidy:
+  if(arg1)
+    rasqal_free_expression(arg1);
+  if(literal)
+    rasqal_free_literal(literal);
+
+  return e;
+}
+
+
+/**
+ * rasqal_new_literal_expression:
+ * @world: rasqal_world object
+ * @literal: Literal operand 1
+ * 
+ * Constructor - create a new expression for a #rasqal_literal
+ * Takes ownership of the operand literal.
+ * 
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_literal_expression(rasqal_world* world, rasqal_literal *literal)
+{
+  rasqal_expression* e;
+
+  if(!literal)
+    return NULL;
+  
+  e = (rasqal_expression*)RASQAL_CALLOC(rasqal_expression, 1,
+                                         sizeof(rasqal_expression));
+  if(e) {  
+    e->usage = 1;
+    e->world = world;
+    e->op = RASQAL_EXPR_LITERAL;
+    e->literal = literal;
+  } else {
+    rasqal_free_literal(literal);
+  }
+  return e;
+}
+
+
+/**
+ * rasqal_new_function_expression:
+ * @world: rasqal_world object
+ * @name: function name
+ * @args: sequence of #rasqal_expression function arguments
+ * 
+ * Constructor - create a new expression for a function with expression arguments.
+ * Takes ownership of the function uri and arguments.
+ * 
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_function_expression(rasqal_world* world,
+                               raptor_uri* name,
+                               raptor_sequence* args)
+{
+  rasqal_expression* e = NULL;
+
+  if(!name || !args)
+    goto tidy;
+  
+  e = (rasqal_expression*)RASQAL_CALLOC(rasqal_expression, 1,
+                                        sizeof(rasqal_expression));
+  if(e) {
+    e->usage = 1;
+    e->world = world;
+    e->op = RASQAL_EXPR_FUNCTION;
+    e->name = name; name = NULL;
+    e->args = args; args = NULL;
+  }
+  
+  tidy:
+  if(name)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(world->raptor_world_ptr, name);
+#else
+    raptor_free_uri(name);
+#endif
+  if(args)
+    raptor_free_sequence(args);
+
+  return e;
+}
+
+
+/**
+ * rasqal_new_cast_expression:
+ * @world: rasqal_world object
+ * @name: cast datatype URI
+ * @value: expression value to cast to @datatype type
+ * 
+ * Constructor - create a new expression for casting and expression to a datatype.
+ * Takes ownership of the datatype uri and expression value.
+ * 
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_cast_expression(rasqal_world* world, raptor_uri* name, rasqal_expression *value) 
+{
+  rasqal_expression* e = NULL;
+
+  if(!name || !value)
+    goto tidy;
+  
+  e = (rasqal_expression*)RASQAL_CALLOC(rasqal_expression, 1,
+                                        sizeof(rasqal_expression));
+  if(e) {
+    e->usage = 1;
+    e->world = world;
+    e->op = RASQAL_EXPR_CAST;
+    e->name = name; name = NULL;
+    e->arg1 = value; value = NULL;
+  }
+
+  tidy:
+  if(name)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(world->raptor_world_ptr, name);
+#else
+    raptor_free_uri(name);
+#endif
+  if(value)
+    rasqal_free_expression(value);
+
+  return e;
+}
+
+
+/**
+ * rasqal_expression_clear:
+ * @e: expression
+ * 
+ * Empty an expression of contained content.
+ *
+ * Intended to be used to deallocate resources from a statically
+ * declared #rasqal_expression such as on a stack.
+ **/
+void
+rasqal_expression_clear(rasqal_expression* e)
+{
+  switch(e->op) {
+    case RASQAL_EXPR_AND:
+    case RASQAL_EXPR_OR:
+    case RASQAL_EXPR_EQ:
+    case RASQAL_EXPR_NEQ:
+    case RASQAL_EXPR_LT:
+    case RASQAL_EXPR_GT:
+    case RASQAL_EXPR_LE:
+    case RASQAL_EXPR_GE:
+    case RASQAL_EXPR_PLUS:
+    case RASQAL_EXPR_MINUS:
+    case RASQAL_EXPR_STAR:
+    case RASQAL_EXPR_SLASH:
+    case RASQAL_EXPR_REM:
+    case RASQAL_EXPR_STR_EQ:
+    case RASQAL_EXPR_STR_NEQ:
+    case RASQAL_EXPR_LANGMATCHES:
+    case RASQAL_EXPR_SAMETERM:
+      rasqal_free_expression(e->arg1);
+      rasqal_free_expression(e->arg2);
+      break;
+    case RASQAL_EXPR_REGEX:
+      rasqal_free_expression(e->arg1);
+      rasqal_free_expression(e->arg2);
+      if(e->arg3)
+        rasqal_free_expression(e->arg3);
+      break;
+    case RASQAL_EXPR_TILDE:
+    case RASQAL_EXPR_BANG:
+    case RASQAL_EXPR_UMINUS:
+    case RASQAL_EXPR_BOUND:
+    case RASQAL_EXPR_STR:
+    case RASQAL_EXPR_LANG:
+    case RASQAL_EXPR_DATATYPE:
+    case RASQAL_EXPR_ISURI:
+    case RASQAL_EXPR_ISBLANK:
+    case RASQAL_EXPR_ISLITERAL:
+    case RASQAL_EXPR_ORDER_COND_ASC:
+    case RASQAL_EXPR_ORDER_COND_DESC:
+    case RASQAL_EXPR_GROUP_COND_ASC:
+    case RASQAL_EXPR_GROUP_COND_DESC:
+    case RASQAL_EXPR_COUNT:
+      rasqal_free_expression(e->arg1);
+      break;
+    case RASQAL_EXPR_STR_MATCH:
+    case RASQAL_EXPR_STR_NMATCH:
+      rasqal_free_expression(e->arg1);
+      /* FALLTHROUGH */
+    case RASQAL_EXPR_LITERAL:
+      rasqal_free_literal(e->literal);
+      break;
+    case RASQAL_EXPR_FUNCTION:
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_free_uri_v2(e->world->raptor_world_ptr, e->name);
+#else
+      raptor_free_uri(e->name);
+#endif
+      raptor_free_sequence(e->args);
+      break;
+    case RASQAL_EXPR_CAST:
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_free_uri_v2(e->world->raptor_world_ptr, e->name);
+#else
+      raptor_free_uri(e->name);
+#endif
+      rasqal_free_expression(e->arg1);
+      break;
+
+    case RASQAL_EXPR_VARSTAR:
+      /* constants */
+      break;
+      
+    case RASQAL_EXPR_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown operation %d", e->op);
+  }
+}
+
+
+/**
+ * rasqal_new_expression_from_expression:
+ * @e: #rasqal_expression object to copy
+ *
+ * Copy Constructor - create a new #rasqal_expression object from an existing rasqal_expression object.
+ * 
+ * Return value: a new #rasqal_expression object or NULL on failure
+ **/
+rasqal_expression*
+rasqal_new_expression_from_expression(rasqal_expression* e)
+{
+  if(!e)
+    return NULL;
+  
+  e->usage++;
+  return e;
+}
+
+
+/**
+ * rasqal_free_expression:
+ * @e: #rasqal_expression object
+ * 
+ * Destructor - destroy a #rasqal_expression object.
+ *
+ **/
+void
+rasqal_free_expression(rasqal_expression* e)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(e, rasqal_expression);
+  
+  if(--e->usage)
+    return;
+
+  rasqal_expression_clear(e);
+  RASQAL_FREE(rasqal_expression, e);
+}
+
+
+/**
+ * rasqal_expression_visit:
+ * @e:  #rasqal_expression to visit
+ * @fn: visit function
+ * @user_data: user data to pass to visit function
+ * 
+ * Visit a user function over a #rasqal_expression
+ * 
+ * If the user function @fn returns 0, the visit is truncated.
+ *
+ * Return value: 0 if the visit was truncated.
+ **/
+int
+rasqal_expression_visit(rasqal_expression* e, 
+                        rasqal_expression_visit_fn fn,
+                        void *user_data)
+{
+  int i;
+  int result=0;
+
+  /* This ordering allows fn to potentially edit 'e' in-place */
+  result=fn(user_data, e);
+  if(result)
+    return result;
+
+  switch(e->op) {
+    case RASQAL_EXPR_AND:
+    case RASQAL_EXPR_OR:
+    case RASQAL_EXPR_EQ:
+    case RASQAL_EXPR_NEQ:
+    case RASQAL_EXPR_LT:
+    case RASQAL_EXPR_GT:
+    case RASQAL_EXPR_LE:
+    case RASQAL_EXPR_GE:
+    case RASQAL_EXPR_PLUS:
+    case RASQAL_EXPR_MINUS:
+    case RASQAL_EXPR_STAR:
+    case RASQAL_EXPR_SLASH:
+    case RASQAL_EXPR_REM:
+    case RASQAL_EXPR_STR_EQ:
+    case RASQAL_EXPR_STR_NEQ:
+    case RASQAL_EXPR_LANGMATCHES:
+    case RASQAL_EXPR_SAMETERM:
+      return rasqal_expression_visit(e->arg1, fn, user_data) ||
+             rasqal_expression_visit(e->arg2, fn, user_data);
+      break;
+    case RASQAL_EXPR_REGEX:
+      return rasqal_expression_visit(e->arg1, fn, user_data) ||
+             rasqal_expression_visit(e->arg2, fn, user_data) ||
+             (e->arg3 && rasqal_expression_visit(e->arg3, fn, user_data));
+      break;
+    case RASQAL_EXPR_TILDE:
+    case RASQAL_EXPR_BANG:
+    case RASQAL_EXPR_UMINUS:
+    case RASQAL_EXPR_BOUND:
+    case RASQAL_EXPR_STR:
+    case RASQAL_EXPR_LANG:
+    case RASQAL_EXPR_DATATYPE:
+    case RASQAL_EXPR_ISURI:
+    case RASQAL_EXPR_ISBLANK:
+    case RASQAL_EXPR_ISLITERAL:
+    case RASQAL_EXPR_CAST:
+    case RASQAL_EXPR_ORDER_COND_ASC:
+    case RASQAL_EXPR_ORDER_COND_DESC:
+    case RASQAL_EXPR_GROUP_COND_ASC:
+    case RASQAL_EXPR_GROUP_COND_DESC:
+    case RASQAL_EXPR_COUNT:
+      return rasqal_expression_visit(e->arg1, fn, user_data);
+      break;
+    case RASQAL_EXPR_STR_MATCH:
+    case RASQAL_EXPR_STR_NMATCH:
+      return fn(user_data, e->arg1);
+      break;
+    case RASQAL_EXPR_LITERAL:
+      return 0;
+    case RASQAL_EXPR_FUNCTION:
+      for(i=0; i<raptor_sequence_size(e->args); i++) {
+        rasqal_expression* e2=(rasqal_expression*)raptor_sequence_get_at(e->args, i);
+        if(!rasqal_expression_visit(e2, fn, user_data)) {
+          result=0;
+          break;
+        }
+      }
+      return result;
+      break;
+
+    case RASQAL_EXPR_VARSTAR:
+      /* constants */
+      return 0;
+      break;
+      
+    case RASQAL_EXPR_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown operation %d", e->op);
+      return -1; /* keep some compilers happy */
+  }
+}
+
+
+/* 
+ * rasqal_language_matches:
+ * @lang_tag: language tag such as "en" or "en-US" or "ab-cd-ef"
+ * @lang_range: language range such as "*" (SPARQL) or "en" or "ab-cd"
+ *
+ * INTERNAL - Match a language tag against a language range
+ *
+ * Returns true if @lang_range matches @lang_tag per
+ *   Matching of Language Tags [RFC4647] section 2.1
+ * RFC4647 defines a case-insensitive, hierarchical matching
+ * algorithm which operates on ISO-defined subtags for language and
+ * country codes, and user defined subtags.
+ *
+ * (Note: RFC3066 section 2.5 matching is identical to
+ * RFC4647 section 3.3.1 Basic Filtering )
+ * 
+ * In SPARQL, a language-range of "*" matches any non-empty @lang_tag string.
+ * See http://www.w3.org/TR/2007/WD-rdf-sparql-query-20070326/#func-langMatches
+ *
+ * Return value: non-0 if true
+ */
+static int
+rasqal_language_matches(const unsigned char* lang_tag,
+                        const unsigned char* lang_range) 
+{
+  int b= 0;
+
+  if(!(lang_tag && lang_range && *lang_tag && *lang_range)) {
+    /* One of the arguments is NULL or the empty string */
+    return 0;
+  }
+
+  /* Now have two non-empty arguments */
+
+  /* Simple range string "*" matches anything excluding NULL/empty
+   * lang_tag (checked above)
+   */
+  if(lang_range[0] == '*') {
+    if(!lang_range[1])
+      b = 1;
+    return b;
+  }
+  
+  while (1) {
+    char tag_c   = tolower(*lang_tag++);
+    char range_c = tolower(*lang_range++);
+    if ((!tag_c && !range_c) || (!range_c && tag_c == '-')) {
+      /* EITHER
+       *   The end of both strings (thus everything previous matched
+       *   such as e.g. tag "fr-CA" matching range "fr-ca")
+       * OR
+       *   The end of the range and end of the tag prefix (e.g. tag
+       *   "en-US" matching range "en")
+       * means a match
+       */
+      b = 1;
+      break;
+    } 
+    if (range_c != tag_c) {
+      /* If a difference was found - including one of the
+       * strings being shorter than the other, it means no match
+       * (b is set to 0 above)
+       */
+      break;
+    }
+  }
+
+  return b;
+}
+
+
+/* 
+ * rasqal_expression_evaluate_strmatch:
+ * @world: #rasqal_world
+ * @locator: error locator object
+ * @e: The expression to evaluate.
+ * @flags: Compare flags
+ *
+ * INTERNAL - Evaluate RASQAL_EXPR_STR_MATCH, RASQAL_EXPR_STR_NMATCH and
+ * RASQAL_EXPR_REGEX expressions.
+ *
+ * Return value: A #rasqal_literal value or NULL on failure.
+ */
+static rasqal_literal*
+rasqal_expression_evaluate_strmatch(rasqal_world *world,
+                                    raptor_locator *locator,
+                                    rasqal_expression *e,
+                                    int flags)
+{
+  int b=0;
+  int flag_i=0; /* flags contains i */
+  const unsigned char *p;
+  const unsigned char *match_string;
+  const unsigned char *pattern;
+  const unsigned char *regex_flags;
+  rasqal_literal *l1, *l2, *l3;
+  int error=0;
+  int rc=0;
+#ifdef RASQAL_REGEX_PCRE
+  pcre* re;
+  int options=0;
+  const char *re_error=NULL;
+  int erroffset=0;
+#endif
+#ifdef RASQAL_REGEX_POSIX
+  regex_t reg;
+  int options=REG_EXTENDED | REG_NOSUB;
+#endif
+    
+  l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+  if(!l1)
+    goto failed;
+
+  match_string=rasqal_literal_as_string_flags(l1, flags, &error);
+  if(error || !match_string) {
+    rasqal_free_literal(l1);
+    goto failed;
+  }
+    
+  l3=NULL;
+  regex_flags=NULL;
+  if(e->op == RASQAL_EXPR_REGEX) {
+    l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+    if(!l2) {
+      rasqal_free_literal(l1);
+      goto failed;
+    }
+
+    if(e->arg3) {
+      l3=rasqal_expression_evaluate_v2(world, locator, e->arg3, flags);
+      if(!l3) {
+        rasqal_free_literal(l1);
+        rasqal_free_literal(l2);
+        goto failed;
+      }
+      regex_flags=l3->string;
+    }
+      
+  } else {
+    l2=e->literal;
+    regex_flags=l2->flags;
+  }
+  pattern=l2->string;
+    
+  for(p=regex_flags; p && *p; p++)
+    if(*p == 'i')
+      flag_i++;
+      
+#ifdef RASQAL_REGEX_PCRE
+  if(flag_i)
+    options |= PCRE_CASELESS;
+    
+  re=pcre_compile((const char*)pattern, options, 
+                  &re_error, &erroffset, NULL);
+  if(!re) {
+    rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, locator,
+                            "Regex compile of '%s' failed - %s", pattern, re_error);
+    rc= -1;
+  } else {
+    rc=pcre_exec(re, 
+                 NULL, /* no study */
+                 (const char*)match_string, strlen((const char*)match_string),
+                 0 /* startoffset */,
+                 0 /* options */,
+                 NULL, 0 /* ovector, ovecsize - no matches wanted */
+                 );
+    if(rc >= 0)
+      b=1;
+    else if(rc != PCRE_ERROR_NOMATCH) {
+      rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, locator,
+                              "Regex match failed - returned code %d", rc);
+      rc= -1;
+    } else
+      rc=0;
+  }
+  pcre_free(re);
+  
+#endif
+    
+#ifdef RASQAL_REGEX_POSIX
+  if(flag_i)
+    options |=REG_ICASE;
+    
+  rc=regcomp(&reg, (const char*)pattern, options);
+  if(rc) {
+    rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, locator,
+                            "Regex compile of '%s' failed", pattern);
+    rc= -1;
+  } else {
+    rc=regexec(&reg, (const char*)match_string, 
+               0, NULL, /* nmatch, regmatch_t pmatch[] - no matches wanted */
+               0 /* eflags */
+               );
+    if(!rc)
+      b=1;
+    else if (rc != REG_NOMATCH) {
+      rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, locator,
+                              "Regex match failed - returned code %d", rc);
+      rc= -1;
+    } else
+      rc= 0;
+  }
+  regfree(&reg);
+#endif
+
+#ifdef RASQAL_REGEX_NONE
+  rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_WARNING, locator,
+                          "Regex support missing, cannot compare '%s' to '%s'", match_string, pattern);
+  b=1;
+  rc= -1;
+#endif
+
+  RASQAL_DEBUG5("regex match returned %s for '%s' against '%s' (flags=%s)\n", b ? "true" : "false", match_string, pattern, l2->flags ? (char*)l2->flags : "");
+  
+  if(e->op == RASQAL_EXPR_STR_NMATCH)
+    b=1-b;
+
+  rasqal_free_literal(l1);
+  if(e->op == RASQAL_EXPR_REGEX) {
+    rasqal_free_literal(l2);
+    if(l3)
+      rasqal_free_literal(l3);
+  }
+    
+  if(rc<0)
+    goto failed;
+    
+  return rasqal_new_boolean_literal(world, b);
+
+  failed:
+  return NULL;
+}
+
+
+/**
+ * rasqal_expression_evaluate_v2:
+ * @query: #rasqal_query this expression belongs to
+ * @locator: error locator
+ * @e: The expression to evaluate.
+ * @flags: Flags for rasqal_literal_compare() and RASQAL_COMPARE_NOCASE for string matches.
+ * 
+ * Evaluate a #rasqal_expression tree to give a #rasqal_literal result
+ * or error.
+ * 
+ * Return value: a #rasqal_literal value or NULL on failure.
+ **/
+rasqal_literal*
+rasqal_expression_evaluate_v2(rasqal_world *world, raptor_locator *locator,
+                              rasqal_expression* e, int flags)
+{
+  rasqal_literal* result=NULL;
+
+  rasqal_literal *l1;
+  rasqal_literal *l2;
+  const unsigned char *s;
+
+  /* pack vars from different switch cases in unions to save some stack space */
+  union {
+    struct { int e1; int e2; } errs;
+    struct { int dummy_do_not_mask_e; int free_literal; } flags;
+    int e;
+  } errs;
+  union {
+    struct { int b1; int b2; } bools;
+    int b;
+    int i;
+    raptor_uri *dt_uri;
+    const unsigned char *s;
+    unsigned char *new_s;
+    rasqal_variable *v;
+  } vars;
+
+  errs.e=0;
+
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG2("evaluating expression %p: ", e);
+  rasqal_expression_print(e, stderr);
+  fprintf(stderr, "\n");
+#endif
+  
+  switch(e->op) {
+    case RASQAL_EXPR_AND:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1) {
+        errs.errs.e1=1;
+        vars.bools.b1=0;
+      } else {
+        errs.errs.e1=0;
+        vars.bools.b1=rasqal_literal_as_boolean(l1, &errs.errs.e1);
+        rasqal_free_literal(l1);
+      }
+
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l1) {
+        errs.errs.e2=1;
+        vars.bools.b2=0;
+      } else {
+        errs.errs.e2=0;
+        vars.bools.b2=rasqal_literal_as_boolean(l1, &errs.errs.e2);
+        rasqal_free_literal(l1);
+      }
+
+      /* See http://www.w3.org/TR/2005/WD-rdf-sparql-query-20051123/#truthTable */
+      if(!errs.errs.e1 && !errs.errs.e2) {
+        /* No type error, answer is A && B */
+        vars.b = vars.bools.b1 && vars.bools.b2; /* don't need b1,b2 anymore */
+      } else {
+        if((!vars.bools.b1 && errs.errs.e2) || (errs.errs.e1 && vars.bools.b2))
+          /* F && E => F.   E && F => F. */
+          vars.b=0;
+        else
+          /* Otherwise E */
+          goto failed;
+      }
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+      
+    case RASQAL_EXPR_OR:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1) {
+        errs.errs.e1=1;
+        vars.bools.b1=0;
+      } else {
+        errs.errs.e1=0;
+        vars.bools.b1=rasqal_literal_as_boolean(l1, &errs.errs.e1);
+        rasqal_free_literal(l1);
+      }
+
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l1) {
+        errs.errs.e2=1;
+        vars.bools.b2=0;
+      } else {
+        errs.errs.e2=0;
+        vars.bools.b2=rasqal_literal_as_boolean(l1, &errs.errs.e2);
+        rasqal_free_literal(l1);
+      }
+
+      /* See http://www.w3.org/TR/2005/WD-rdf-sparql-query-20051123/#truthTable */
+      if(!errs.errs.e1 && !errs.errs.e2) {
+        /* No type error, answer is A || B */
+        vars.b = vars.bools.b1 || vars.bools.b2; /* don't need b1,b2 anymore */
+      } else {
+        if((vars.bools.b1 && errs.errs.e2) || (errs.errs.e1 && vars.bools.b2))
+          /* T || E => T.   E || T => T */
+          vars.b=1;
+        else
+          /* Otherwise E */
+          goto failed;
+      }
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_EQ:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=(rasqal_literal_equals_flags(l1, l2, flags, &errs.e) != 0);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_NEQ:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=(rasqal_literal_equals_flags(l1, l2, flags, &errs.e) == 0);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_LT:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=(rasqal_literal_compare(l1, l2, flags, &errs.e) < 0);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_GT:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=(rasqal_literal_compare(l1, l2, flags, &errs.e) > 0);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_LE:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=(rasqal_literal_compare(l1, l2, flags, &errs.e) <= 0);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;        
+
+    case RASQAL_EXPR_GE:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=(rasqal_literal_compare(l1, l2, flags, &errs.e) >= 0);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_UMINUS:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      result=rasqal_literal_negate(l1, &errs.e);
+      rasqal_free_literal(l1);
+      if(errs.e)
+        goto failed;
+      break;
+
+    case RASQAL_EXPR_BOUND:
+      /* Do not use rasqal_expression_evaluate() here since
+       * we need to check the argument is a variable, and
+       * that function will flatten such thing to literals
+       * as early as possible. See (FLATTEN_LITERAL) below
+       */
+      if(!e->arg1 || e->arg1->op != RASQAL_EXPR_LITERAL)
+        goto failed;
+
+      l1=e->arg1->literal;
+      if(!l1 || l1->type != RASQAL_LITERAL_VARIABLE)
+        goto failed;
+
+      vars.v=rasqal_literal_as_variable(l1);
+      if(!vars.v)
+        goto failed;
+
+      result=rasqal_new_boolean_literal(world, (vars.v->value != NULL));
+      break;
+
+    case RASQAL_EXPR_STR:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      /* Note: flags removes RASQAL_COMPARE_XQUERY as this is the
+       * explicit stringify operation
+       */
+      s=rasqal_literal_as_string_flags(l1, (flags & ~RASQAL_COMPARE_XQUERY),
+                                       &errs.e);
+      if(!s || errs.e) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.new_s=(unsigned char *)RASQAL_MALLOC(cstring, strlen((const char*)s)+1);
+      if(!vars.new_s) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+      strcpy((char*)vars.new_s, (const char*)s);
+
+      result=rasqal_new_string_literal(world, vars.new_s, NULL, NULL, NULL);
+      rasqal_free_literal(l1);
+
+      break;
+      
+    case RASQAL_EXPR_LANG:
+      errs.flags.free_literal=1;
+      
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      vars.v=rasqal_literal_as_variable(l1);
+      if(vars.v) {
+        rasqal_free_literal(l1);
+        l1=vars.v->value; /* don't need vars.v after this */
+        errs.flags.free_literal=0;
+        if(!l1)
+          goto failed;
+      }
+
+      if(rasqal_literal_get_rdf_term_type(l1) != RASQAL_LITERAL_STRING) {
+        if(errs.flags.free_literal)
+          rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      if(l1->language) {
+        vars.new_s=(unsigned char*)RASQAL_MALLOC(cstring,
+                                                 strlen(l1->language)+1);
+        if(!vars.new_s) {
+          if(errs.flags.free_literal)
+            rasqal_free_literal(l1);
+          goto failed;
+        }
+        strcpy((char*)vars.new_s, l1->language);
+      } else  {
+        vars.new_s=(unsigned char*)RASQAL_MALLOC(cstring, 1);
+        if(!vars.new_s) {
+          if(errs.flags.free_literal)
+            rasqal_free_literal(l1);
+          goto failed;
+        }
+        *vars.new_s='\0';
+      }
+      result=rasqal_new_string_literal(world, vars.new_s, NULL, NULL, NULL);
+      
+      if(errs.flags.free_literal)
+        rasqal_free_literal(l1);
+
+      break;
+
+    case RASQAL_EXPR_LANGMATCHES:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      s=rasqal_literal_as_string_flags(l1, flags, &errs.e);
+      vars.s=rasqal_literal_as_string_flags(l2, flags, &errs.e);
+
+      if(errs.e)
+        vars.b=0;
+      else
+        vars.b=rasqal_language_matches(s, vars.s); /* don't need s anymore */
+      
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_DATATYPE:
+      errs.flags.free_literal=1;
+      vars.dt_uri=NULL;
+      
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      vars.v=rasqal_literal_as_variable(l1);
+      if(vars.v) {
+        rasqal_free_literal(l1);
+        l1=vars.v->value; /* don't need vars.v after this */
+        errs.flags.free_literal=0;
+        if(!l1)
+          goto failed;
+      }
+
+      if(rasqal_literal_get_rdf_term_type(l1) != RASQAL_LITERAL_STRING) {
+        if(errs.flags.free_literal)
+          rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      if(l1->language) {
+        if(errs.flags.free_literal)
+          rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      /* The datatype of a plain literal is xsd:string */
+      vars.dt_uri=l1->datatype;
+      if(!vars.dt_uri && l1->type == RASQAL_LITERAL_STRING)
+        vars.dt_uri=rasqal_xsd_datatype_type_to_uri(l1->world, l1->type);
+
+      if(!vars.dt_uri) {
+        if(errs.flags.free_literal)
+          rasqal_free_literal(l1);
+        goto failed;
+      }
+      
+#ifdef RAPTOR_V2_AVAILABLE
+      result = rasqal_new_uri_literal(world, raptor_uri_copy_v2(world->raptor_world_ptr, vars.dt_uri));
+#else
+      result = rasqal_new_uri_literal(world, raptor_uri_copy(vars.dt_uri));
+#endif
+
+      if(errs.flags.free_literal)
+        rasqal_free_literal(l1);
+
+      break;
+
+    case RASQAL_EXPR_ISURI:
+      errs.flags.free_literal=1;
+      
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+      
+      vars.v=rasqal_literal_as_variable(l1);
+      if(vars.v) {
+        rasqal_free_literal(l1);
+        l1=vars.v->value; /* don't need vars.v after this */
+        errs.flags.free_literal=0;
+        if(!l1)
+          goto failed;
+      }
+
+      vars.b=(l1->type == RASQAL_LITERAL_URI);
+      
+      if(errs.flags.free_literal)
+        rasqal_free_literal(l1);
+
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_ISBLANK:
+      errs.flags.free_literal=1;
+      
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+      
+      vars.v=rasqal_literal_as_variable(l1);
+      if(vars.v) {
+        rasqal_free_literal(l1);
+        l1=vars.v->value; /* don't need vars.v after this */
+        errs.flags.free_literal=0;
+        if(!l1)
+          goto failed;
+      }
+
+      vars.b=(l1->type == RASQAL_LITERAL_BLANK);
+
+      if(errs.flags.free_literal)
+        rasqal_free_literal(l1);
+
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_ISLITERAL:
+      errs.flags.free_literal=1;
+      
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+      
+      vars.v=rasqal_literal_as_variable(l1);
+      if(vars.v) {
+        rasqal_free_literal(l1);
+        l1=vars.v->value; /* don't need vars.v after this */
+        errs.flags.free_literal=0;
+        if(!l1)
+          goto failed;
+      }
+
+      vars.b=(rasqal_literal_get_rdf_term_type(l1) == RASQAL_LITERAL_STRING);
+
+      if(errs.flags.free_literal)
+        rasqal_free_literal(l1);
+
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+      
+    case RASQAL_EXPR_PLUS:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      result=rasqal_literal_add(l1, l2, &errs.e);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      
+      break;
+        
+    case RASQAL_EXPR_MINUS:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      result=rasqal_literal_subtract(l1, l2, &errs.e);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      
+      break;
+      
+    case RASQAL_EXPR_STAR:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      result=rasqal_literal_multiply(l1, l2, &errs.e);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      
+      break;
+      
+    case RASQAL_EXPR_SLASH:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      result=rasqal_literal_divide(l1, l2, &errs.e);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+      
+      break;
+      
+    case RASQAL_EXPR_REM:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.i=rasqal_literal_as_integer(l2, &errs.errs.e2);
+      /* error if divisor is zero */
+      if(!vars.i)
+        errs.errs.e2=1;
+      else
+        vars.i=rasqal_literal_as_integer(l1, &errs.errs.e1) % vars.i;
+
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.errs.e1 || errs.errs.e2)
+        goto failed;
+
+      result=rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, vars.i);
+      break;
+      
+    case RASQAL_EXPR_STR_EQ:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=(rasqal_literal_compare(l1, l2, flags | RASQAL_COMPARE_NOCASE,
+                                     &errs.e) == 0);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+      
+    case RASQAL_EXPR_STR_NEQ:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=(rasqal_literal_compare(l1, l2, flags | RASQAL_COMPARE_NOCASE, 
+                                     &errs.e) != 0);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_TILDE:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      vars.i= ~ rasqal_literal_as_integer(l1, &errs.e);
+      rasqal_free_literal(l1);
+      if(errs.e)
+        goto failed;
+
+      result=rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, vars.i);
+      break;
+
+    case RASQAL_EXPR_BANG:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      vars.b= ! rasqal_literal_as_boolean(l1, &errs.e);
+      rasqal_free_literal(l1);
+      if(errs.e)
+        goto failed;
+
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+
+    case RASQAL_EXPR_STR_MATCH:
+    case RASQAL_EXPR_STR_NMATCH:
+    case RASQAL_EXPR_REGEX:
+      result=rasqal_expression_evaluate_strmatch(world, locator, e, flags);
+      break;
+
+    case RASQAL_EXPR_LITERAL:
+      /* flatten any literal to a value as soon as possible - this
+       * removes variables from expressions the first time they are seen.
+       * (FLATTEN_LITERAL)
+       */
+      result=rasqal_new_literal_from_literal(rasqal_literal_value(e->literal));
+      break;
+
+    case RASQAL_EXPR_FUNCTION:
+      rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_WARNING, locator,
+                              "No function expressions support at present.  Returning false.");
+      result=rasqal_new_boolean_literal(world, 0);
+      break;
+      
+    case RASQAL_EXPR_CAST:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+
+      result=rasqal_literal_cast(l1, e->name, flags, &errs.e);
+
+      rasqal_free_literal(l1);
+      if(errs.e)
+        goto failed;
+
+      break;
+
+    case RASQAL_EXPR_ORDER_COND_ASC:
+    case RASQAL_EXPR_ORDER_COND_DESC:
+    case RASQAL_EXPR_GROUP_COND_ASC:
+    case RASQAL_EXPR_GROUP_COND_DESC:
+    case RASQAL_EXPR_COUNT:
+      result=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      break;
+
+    case RASQAL_EXPR_VARSTAR:
+      /* constants */
+      break;
+      
+    case RASQAL_EXPR_SAMETERM:
+      l1=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
+      if(!l1)
+        goto failed;
+      
+      l2=rasqal_expression_evaluate_v2(world, locator, e->arg2, flags);
+      if(!l2) {
+        rasqal_free_literal(l1);
+        goto failed;
+      }
+
+      vars.b=rasqal_literal_equals_flags(l1, l2, RASQAL_COMPARE_RDF, &errs.e);
+      rasqal_free_literal(l1);
+      rasqal_free_literal(l2);
+      if(errs.e)
+        goto failed;
+
+      result=rasqal_new_boolean_literal(world, vars.b);
+      break;
+      
+    case RASQAL_EXPR_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown operation %d", e->op);
+  }
+
+  got_result:
+
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG2("result of %p: ", e);
+  rasqal_expression_print(e, stderr);
+  fputs( ": ", stderr);
+  if(result)
+    rasqal_literal_print(result, stderr);
+  else
+    fputs("(NULL)",stderr);
+  fputc('\n', stderr);
+#endif
+  
+  return result;
+
+  failed:
+
+  if(result) {
+    rasqal_free_literal(result);
+    result=NULL;
+  }
+  goto got_result;
+}
+
+
+/**
+ * rasqal_expression_evaluate:
+ * @query: #rasqal_query this expression belongs to
+ * @e: The expression to evaluate.
+ * @flags: Flags for rasqal_literal_compare() and RASQAL_COMPARE_NOCASE for string matches.
+ * 
+ * Evaluate a #rasqal_expression tree to give a #rasqal_literal result
+ * or error.
+ * 
+ * Return value: a #rasqal_literal value or NULL on failure.
+ **/
+rasqal_literal*
+rasqal_expression_evaluate(rasqal_query *query, rasqal_expression* e,
+                           int flags)
+{
+  return rasqal_expression_evaluate_v2(query->world, &query->locator, e, flags);
+}
+
+
+static const char* const rasqal_op_labels[RASQAL_EXPR_LAST+1]={
+  "UNKNOWN",
+  "and",
+  "or",
+  "eq",
+  "neq",
+  "lt",
+  "gt",
+  "le",
+  "ge",
+  "uminus",
+  "plus",
+  "minus",
+  "star",
+  "slash",
+  "rem",
+  "str_eq",
+  "str_ne",
+  "str_match",
+  "str_nmatch",
+  "tilde",
+  "bang",
+  "literal",
+  "function",
+  "bound",
+  "str",
+  "lang",
+  "datatype",
+  "isUri",
+  "isBlank",
+  "isLiteral",
+  "cast",
+  "order asc",
+  "order desc",
+  "langMatches",
+  "regex",
+  "group asc",
+  "group desc",
+  "count",
+  "varstar",
+  "sameTerm"
+};
+
+
+/**
+ * rasqal_expression_write_op:
+ * @e: the #rasqal_expression object
+ * @iostr: the #raptor_iostream to write to
+ * 
+ * Write a rasqal expression operator to an iostream in a debug format.
+ *
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_expression_write_op(rasqal_expression* e, raptor_iostream* iostr)
+{
+  rasqal_op op=e->op;
+  if(op > RASQAL_EXPR_LAST)
+    op=RASQAL_EXPR_UNKNOWN;
+  raptor_iostream_write_string(iostr, rasqal_op_labels[(int)op]);
+}
+
+
+/**
+ * rasqal_expression_print_op:
+ * @e: the #rasqal_expression object
+ * @fh: the #FILE* handle to print to
+ * 
+ * Print a rasqal expression operator in a debug format.
+ *
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_expression_print_op(rasqal_expression* e, FILE* fh)
+{
+  rasqal_op op=e->op;
+  if(op > RASQAL_EXPR_LAST)
+    op=RASQAL_EXPR_UNKNOWN;
+  fputs(rasqal_op_labels[(int)op], fh);
+}
+
+
+/**
+ * rasqal_expression_write:
+ * @e: #rasqal_expression object.
+ * @iostr: The #raptor_iostream to write to.
+ * 
+ * Write a Rasqal expression to an iostream in a debug format.
+ * 
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_expression_write(rasqal_expression* e, raptor_iostream* iostr)
+{
+  int i;
+  
+  raptor_iostream_write_counted_string(iostr, "expr(", 5);
+  switch(e->op) {
+    case RASQAL_EXPR_AND:
+    case RASQAL_EXPR_OR:
+    case RASQAL_EXPR_EQ:
+    case RASQAL_EXPR_NEQ:
+    case RASQAL_EXPR_LT:
+    case RASQAL_EXPR_GT:
+    case RASQAL_EXPR_LE:
+    case RASQAL_EXPR_GE:
+    case RASQAL_EXPR_PLUS:
+    case RASQAL_EXPR_MINUS:
+    case RASQAL_EXPR_STAR:
+    case RASQAL_EXPR_SLASH:
+    case RASQAL_EXPR_REM:
+    case RASQAL_EXPR_STR_EQ:
+    case RASQAL_EXPR_STR_NEQ:
+    case RASQAL_EXPR_LANGMATCHES:
+    case RASQAL_EXPR_REGEX:
+    case RASQAL_EXPR_SAMETERM:
+      raptor_iostream_write_counted_string(iostr, "op ", 3);
+      rasqal_expression_write_op(e, iostr);
+      raptor_iostream_write_byte(iostr, '(');
+      rasqal_expression_write(e->arg1, iostr);
+      raptor_iostream_write_counted_string(iostr, ", ", 2);
+      rasqal_expression_write(e->arg2, iostr);
+      /* There is only one 3-op expression and it's handled here */
+      if(e->op == RASQAL_EXPR_REGEX && e->arg3) {
+        raptor_iostream_write_counted_string(iostr, ", ", 2);
+        rasqal_expression_write(e->arg3, iostr);
+      }
+      raptor_iostream_write_byte(iostr, ')');
+      break;
+    case RASQAL_EXPR_STR_MATCH:
+    case RASQAL_EXPR_STR_NMATCH:
+      raptor_iostream_write_counted_string(iostr, "op ", 3);
+      rasqal_expression_write_op(e, iostr);
+      raptor_iostream_write_byte(iostr, '(');
+      rasqal_expression_write(e->arg1, iostr);
+      raptor_iostream_write_counted_string(iostr, ", ", 2);
+      rasqal_literal_write(e->literal, iostr);
+      raptor_iostream_write_byte(iostr, ')');
+      break;
+    case RASQAL_EXPR_TILDE:
+    case RASQAL_EXPR_BANG:
+    case RASQAL_EXPR_UMINUS:
+    case RASQAL_EXPR_BOUND:
+    case RASQAL_EXPR_STR:
+    case RASQAL_EXPR_LANG:
+    case RASQAL_EXPR_DATATYPE:
+    case RASQAL_EXPR_ISURI:
+    case RASQAL_EXPR_ISBLANK:
+    case RASQAL_EXPR_ISLITERAL:
+    case RASQAL_EXPR_ORDER_COND_ASC:
+    case RASQAL_EXPR_ORDER_COND_DESC:
+    case RASQAL_EXPR_GROUP_COND_ASC:
+    case RASQAL_EXPR_GROUP_COND_DESC:
+    case RASQAL_EXPR_COUNT:
+      raptor_iostream_write_counted_string(iostr, "op ", 3);
+      rasqal_expression_write_op(e, iostr);
+      raptor_iostream_write_byte(iostr, '(');
+      rasqal_expression_write(e->arg1, iostr);
+      raptor_iostream_write_byte(iostr, ')');
+      break;
+
+    case RASQAL_EXPR_LITERAL:
+      rasqal_literal_write(e->literal, iostr);
+      break;
+
+    case RASQAL_EXPR_FUNCTION:
+      raptor_iostream_write_counted_string(iostr, "function(uri=", 13);
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_iostream_write_uri_v2(e->world->raptor_world_ptr, iostr, e->name);
+#else
+      raptor_iostream_write_uri(iostr, e->name);
+#endif
+      raptor_iostream_write_counted_string(iostr, ", args=", 7);
+      for(i=0; i<raptor_sequence_size(e->args); i++) {
+        rasqal_expression* e2;
+        if(i>0)
+          raptor_iostream_write_counted_string(iostr, ", ", 2);
+        e2=(rasqal_expression*)raptor_sequence_get_at(e->args, i);
+        rasqal_expression_write(e2, iostr);
+      }
+      raptor_iostream_write_byte(iostr, ')');
+      break;
+
+    case RASQAL_EXPR_CAST:
+      raptor_iostream_write_counted_string(iostr, "cast(type=", 10);
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_iostream_write_uri_v2(e->world->raptor_world_ptr, iostr, e->name);
+#else
+      raptor_iostream_write_uri(iostr, e->name);
+#endif
+      raptor_iostream_write_counted_string(iostr, ", value=", 8);
+      rasqal_expression_write(e->arg1, iostr);
+      raptor_iostream_write_byte(iostr, ')');
+      break;
+
+    case RASQAL_EXPR_VARSTAR:
+      raptor_iostream_write_counted_string(iostr, "varstar", 7);
+      break;
+      
+    case RASQAL_EXPR_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown operation %d", e->op);
+  }
+  raptor_iostream_write_byte(iostr, ')');
+}
+
+
+/**
+ * rasqal_expression_print:
+ * @e: #rasqal_expression object.
+ * @fh: The #FILE* handle to print to.
+ * 
+ * Print a Rasqal expression in a debug format.
+ * 
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_expression_print(rasqal_expression* e, FILE* fh)
+{
+  fputs("expr(", fh);
+  switch(e->op) {
+    case RASQAL_EXPR_AND:
+    case RASQAL_EXPR_OR:
+    case RASQAL_EXPR_EQ:
+    case RASQAL_EXPR_NEQ:
+    case RASQAL_EXPR_LT:
+    case RASQAL_EXPR_GT:
+    case RASQAL_EXPR_LE:
+    case RASQAL_EXPR_GE:
+    case RASQAL_EXPR_PLUS:
+    case RASQAL_EXPR_MINUS:
+    case RASQAL_EXPR_STAR:
+    case RASQAL_EXPR_SLASH:
+    case RASQAL_EXPR_REM:
+    case RASQAL_EXPR_STR_EQ:
+    case RASQAL_EXPR_STR_NEQ:
+    case RASQAL_EXPR_LANGMATCHES:
+    case RASQAL_EXPR_REGEX:
+    case RASQAL_EXPR_SAMETERM:
+      fputs("op ", fh);
+      rasqal_expression_print_op(e, fh);
+      fputc('(', fh);
+      rasqal_expression_print(e->arg1, fh);
+      fputs(", ", fh);
+      rasqal_expression_print(e->arg2, fh);
+      /* There is only one 3-op expression and it's handled here */
+      if(e->op == RASQAL_EXPR_REGEX && e->arg3) {
+        fputs(", ", fh);
+        rasqal_expression_print(e->arg3, fh);
+      }
+      fputc(')', fh);
+      break;
+    case RASQAL_EXPR_STR_MATCH:
+    case RASQAL_EXPR_STR_NMATCH:
+      fputs("op ", fh);
+      rasqal_expression_print_op(e, fh);
+      fputc('(', fh);
+      rasqal_expression_print(e->arg1, fh);
+      fputs(", ", fh);
+      rasqal_literal_print(e->literal, fh);
+      fputc(')', fh);
+      break;
+    case RASQAL_EXPR_TILDE:
+    case RASQAL_EXPR_BANG:
+    case RASQAL_EXPR_UMINUS:
+    case RASQAL_EXPR_BOUND:
+    case RASQAL_EXPR_STR:
+    case RASQAL_EXPR_LANG:
+    case RASQAL_EXPR_DATATYPE:
+    case RASQAL_EXPR_ISURI:
+    case RASQAL_EXPR_ISBLANK:
+    case RASQAL_EXPR_ISLITERAL:
+    case RASQAL_EXPR_ORDER_COND_ASC:
+    case RASQAL_EXPR_ORDER_COND_DESC:
+    case RASQAL_EXPR_GROUP_COND_ASC:
+    case RASQAL_EXPR_GROUP_COND_DESC:
+    case RASQAL_EXPR_COUNT:
+      fputs("op ", fh);
+      rasqal_expression_print_op(e, fh);
+      fputc('(', fh);
+      rasqal_expression_print(e->arg1, fh);
+      fputc(')', fh);
+      break;
+
+    case RASQAL_EXPR_LITERAL:
+      rasqal_literal_print(e->literal, fh);
+      break;
+
+    case RASQAL_EXPR_FUNCTION:
+      fputs("function(uri=", fh);
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_uri_print_v2(e->world->raptor_world_ptr, e->name, fh);
+#else
+      raptor_uri_print(e->name, fh);
+#endif
+      fputs(", args=", fh);
+      raptor_sequence_print(e->args, fh);
+      fputc(')', fh);
+      break;
+
+    case RASQAL_EXPR_CAST:
+      fputs("cast(type=", fh);
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_uri_print_v2(e->world->raptor_world_ptr, e->name, fh);
+#else
+      raptor_uri_print(e->name, fh);
+#endif
+      fputs(", value=", fh);
+      rasqal_expression_print(e->arg1, fh);
+      fputc(')', fh);
+      break;
+
+    case RASQAL_EXPR_VARSTAR:
+      fputs("varstar", fh);
+      break;
+      
+    case RASQAL_EXPR_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown operation %d", e->op);
+  }
+  fputc(')', fh);
+}
+
+
+/* for use with rasqal_expression_visit and user_data=rasqal_query */
+int
+rasqal_expression_has_qname(void *user_data, rasqal_expression *e)
+{
+  if(e->op == RASQAL_EXPR_LITERAL)
+    return rasqal_literal_has_qname(e->literal);
+
+  return 0;
+}
+
+
+/* for use with rasqal_expression_visit and user_data=rasqal_query */
+int
+rasqal_expression_expand_qname(void *user_data, rasqal_expression *e)
+{
+  if(e->op == RASQAL_EXPR_LITERAL)
+    return rasqal_literal_expand_qname(user_data, e->literal);
+
+  return 0;
+}
+
+
+int
+rasqal_expression_is_constant(rasqal_expression* e) 
+{
+  int i;
+  int result=0;
+  
+  switch(e->op) {
+    case RASQAL_EXPR_AND:
+    case RASQAL_EXPR_OR:
+    case RASQAL_EXPR_EQ:
+    case RASQAL_EXPR_NEQ:
+    case RASQAL_EXPR_LT:
+    case RASQAL_EXPR_GT:
+    case RASQAL_EXPR_LE:
+    case RASQAL_EXPR_GE:
+    case RASQAL_EXPR_PLUS:
+    case RASQAL_EXPR_MINUS:
+    case RASQAL_EXPR_STAR:
+    case RASQAL_EXPR_SLASH:
+    case RASQAL_EXPR_REM:
+    case RASQAL_EXPR_STR_EQ:
+    case RASQAL_EXPR_STR_NEQ:
+    case RASQAL_EXPR_LANGMATCHES:
+    case RASQAL_EXPR_SAMETERM:
+      result=rasqal_expression_is_constant(e->arg1) &&
+             rasqal_expression_is_constant(e->arg2);
+      break;
+    case RASQAL_EXPR_REGEX:
+      result=rasqal_expression_is_constant(e->arg1) &&
+             rasqal_expression_is_constant(e->arg2) &&
+             (e->arg3 && rasqal_expression_is_constant(e->arg3));
+      break;
+    case RASQAL_EXPR_STR_MATCH:
+    case RASQAL_EXPR_STR_NMATCH:
+      result=rasqal_expression_is_constant(e->arg1) &&
+             rasqal_literal_is_constant(e->literal);
+      break;
+    case RASQAL_EXPR_TILDE:
+    case RASQAL_EXPR_BANG:
+    case RASQAL_EXPR_UMINUS:
+    case RASQAL_EXPR_BOUND:
+    case RASQAL_EXPR_STR:
+    case RASQAL_EXPR_LANG:
+    case RASQAL_EXPR_DATATYPE:
+    case RASQAL_EXPR_ISURI:
+    case RASQAL_EXPR_ISBLANK:
+    case RASQAL_EXPR_ISLITERAL:
+    case RASQAL_EXPR_ORDER_COND_ASC:
+    case RASQAL_EXPR_ORDER_COND_DESC:
+    case RASQAL_EXPR_GROUP_COND_ASC:
+    case RASQAL_EXPR_GROUP_COND_DESC:
+    case RASQAL_EXPR_COUNT:
+      result=rasqal_expression_is_constant(e->arg1);
+      break;
+
+    case RASQAL_EXPR_LITERAL:
+      result=rasqal_literal_is_constant(e->literal);
+      break;
+
+    case RASQAL_EXPR_FUNCTION:
+      result=1;
+      for(i=0; i<raptor_sequence_size(e->args); i++) {
+        rasqal_expression* e2=(rasqal_expression*)raptor_sequence_get_at(e->args, i);
+        if(!rasqal_expression_is_constant(e2)) {
+          result=0;
+          break;
+        }
+      }
+      break;
+
+    case RASQAL_EXPR_CAST:
+      result=rasqal_expression_is_constant(e->arg1);
+      break;
+
+    case RASQAL_EXPR_VARSTAR:
+      result=0;
+      break;
+      
+    case RASQAL_EXPR_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown operation %d", e->op);
+  }
+  
+  return result;
+}
+
+
+void
+rasqal_expression_convert_to_literal(rasqal_expression* e, rasqal_literal* l)
+{
+  int usage=e->usage;
+
+  /* update expression 'e' in place */
+  rasqal_expression_clear(e);
+
+  memset(e, 0, sizeof(rasqal_expression));
+  e->usage=usage;
+  e->op=RASQAL_EXPR_LITERAL;
+  e->literal=l;
+}
+
+  
+
+
+/* for use with rasqal_expression_visit and user_data=rasqal_query */
+static int
+rasqal_expression_has_variable(void *user_data, rasqal_expression *e)
+{
+  rasqal_variable* v;
+  const unsigned char* name=((rasqal_variable*)user_data)->name;
+
+  if(e->op != RASQAL_EXPR_LITERAL)
+    return 0;
+  
+  v=rasqal_literal_as_variable(e->literal);
+  if(!v)
+    return 0;
+  
+  if(!strcmp((const char*)v->name, (const char*)name))
+    return 1;
+
+  return 0;
+}
+
+
+int
+rasqal_expression_mentions_variable(rasqal_expression* e, rasqal_variable* v)
+{
+  return rasqal_expression_visit(e, rasqal_expression_has_variable, v);
+}
+
+
+#endif /* not STANDALONE */
+
+
+
+
+#ifdef STANDALONE
+#include <stdio.h>
+
+int main(int argc, char *argv[]);
+
+
+#define assert_match(function, result, string) do { if(strcmp(result, string)) { fprintf(stderr, #function " failed - returned %s, expected %s\n", result, string); exit(1); } } while(0)
+
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program=rasqal_basename(argv[0]);
+  rasqal_literal *lit1, *lit2;
+  rasqal_expression *expr1, *expr2;
+  rasqal_expression* expr;
+  rasqal_literal* result;
+  int error=0;
+  rasqal_world *world;
+
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_world* raptor_world_ptr;
+  raptor_world_ptr = raptor_new_world();
+  if(!raptor_world_ptr || raptor_world_open(raptor_world_ptr))
+    exit(1);
+#else
+  raptor_init();
+#endif
+
+  world = rasqal_new_world();
+#ifdef RAPTOR_V2_AVAILABLE
+  rasqal_world_set_raptor(world, raptor_world_ptr);
+#endif
+  /* no rasqal_world_open() */
+  
+  rasqal_uri_init(world);
+
+  rasqal_xsd_init(world);
+  
+  lit1=rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, 1);
+  expr1=rasqal_new_literal_expression(world, lit1);
+  lit2=rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, 1);
+  expr2=rasqal_new_literal_expression(world, lit2);
+  expr=rasqal_new_2op_expression(world, RASQAL_EXPR_PLUS, expr1, expr2);
+
+  fprintf(stderr, "%s: expression: ", program);
+  rasqal_expression_print(expr, stderr);
+  fputc('\n', stderr);
+
+  result=rasqal_expression_evaluate_v2(world, NULL, expr, 0);
+
+  if(result) {
+    int bresult;
+    
+    fprintf(stderr, "%s: expression result: \n", program);
+    rasqal_literal_print(result, stderr);
+    fputc('\n', stderr);
+    bresult=rasqal_literal_as_boolean(result, &error);
+    if(error) {
+      fprintf(stderr, "%s: boolean expression FAILED\n", program);
+    } else
+      fprintf(stderr, "%s: boolean expression result: %d\n", program, bresult);
+
+
+  } else
+    fprintf(stderr, "%s: expression evaluation FAILED with error\n", program);
+
+  rasqal_free_expression(expr);
+
+  if(result)
+    rasqal_free_literal(result);
+
+  rasqal_xsd_finish(world);
+
+  rasqal_uri_finish(world);
+  
+  RASQAL_FREE(rasqal_world, world);
+
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_free_world(raptor_world_ptr);
+#else
+  raptor_finish();
+#endif
+
+  return error;
+}
+#endif
diff --git a/src/rasqal/rasqal_feature.c b/src/rasqal/rasqal_feature.c
new file mode 100644
index 0000000..acfda69
--- /dev/null
+++ b/src/rasqal/rasqal_feature.c
@@ -0,0 +1,224 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_feature.c - Query system features
+ *
+ * Copyright (C) 2006, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+/* Rasqal includes */
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+static const struct
+{
+  rasqal_feature feature;
+  /* flag bits
+   *  1=query feature
+   *  2=unused
+   *  4=string value (else int)
+   */
+  int flags;
+  const char *name;
+  const char *label;
+} rasqal_features_list [RASQAL_FEATURE_LAST+1]= {
+  { RASQAL_FEATURE_NO_NET, 1,  "noNet", "Deny network requests." }
+};
+
+
+static const char * const rasqal_feature_uri_prefix="http://feature.librdf.org/rasqal-";;
+/* NOTE: this is strlen(rasqal_feature_uri_prefix) */
+#define RASQAL_FEATURE_URI_PREFIX_LEN 33
+
+
+/*
+ * rasqal_features_enumerate_common:
+ * @world: rasqal_world object
+ * @feature: feature enumeration (0+)
+ * @name: pointer to store feature short name (or NULL)
+ * @uri: pointer to store feature URI (or NULL)
+ * @label: pointer to feature label (or NULL)
+ * @flags: flags to match
+ * 
+ * Internal: Get list of rasqal features.
+ *
+ * If @uri is not NULL, a pointer to a new raptor_uri is returned
+ * that must be freed by the caller with raptor_free_uri().
+ *
+ * Return value: 0 on success, <0 on failure, >0 if feature is unknown
+ **/
+static int
+rasqal_features_enumerate_common(rasqal_world* world,
+                                 const rasqal_feature feature,
+                                 const char **name, 
+                                 raptor_uri **uri, const char **label,
+                                 int flags)
+{
+  int i;
+
+  for(i=0; i <= RASQAL_FEATURE_LAST; i++)
+    if(rasqal_features_list[i].feature == feature &&
+       (rasqal_features_list[i].flags & flags)) {
+      if(name)
+        *name=rasqal_features_list[i].name;
+      
+      if(uri) {
+        raptor_uri *base_uri;
+#ifdef RAPTOR_V2_AVAILABLE
+        base_uri = raptor_new_uri_v2(world->raptor_world_ptr, (const unsigned char*)rasqal_feature_uri_prefix);
+        if(!base_uri)
+          return -1;
+        *uri = raptor_new_uri_from_uri_local_name_v2(world->raptor_world_ptr, base_uri,
+                                                     (const unsigned char*)rasqal_features_list[i].name);
+        raptor_free_uri_v2(world->raptor_world_ptr, base_uri);
+#else
+        base_uri = raptor_new_uri((const unsigned char*)rasqal_feature_uri_prefix);
+        if(!base_uri)
+          return -1;
+        *uri = raptor_new_uri_from_uri_local_name(base_uri,
+                                                  (const unsigned char*)rasqal_features_list[i].name);
+        raptor_free_uri(base_uri);
+#endif
+      }
+      if(label)
+        *label=rasqal_features_list[i].label;
+      return 0;
+    }
+
+  return 1;
+}
+
+
+/**
+ * rasqal_features_enumerate:
+ * @world: rasqal_world object
+ * @feature: feature enumeration (0+)
+ * @name: pointer to store feature short name (or NULL)
+ * @uri: pointer to store feature URI (or NULL)
+ * @label: pointer to feature label (or NULL)
+ *
+ * Get list of rasqal features.
+ * 
+ * If uri is not NULL, a pointer to a new raptor_uri is returned
+ * that must be freed by the caller with raptor_free_uri().
+ *
+ * Return value: 0 on success, <0 on failure, >0 if feature is unknown
+ **/
+int
+rasqal_features_enumerate(rasqal_world* world,
+                          const rasqal_feature feature,
+                          const char **name, 
+                          raptor_uri **uri, const char **label)
+{
+  return rasqal_features_enumerate_common(world, feature, name, uri, label, 1);
+}
+
+
+/**
+ * rasqal_feature_value_type
+ * @feature: rasqal query feature
+ *
+ * Get the type of a features.
+ *
+ * The type of the @feature is 0=integer , 1=string.  Other values are
+ * undefined.  Most features are integer values and use
+ * rasqal_query_set_feature rasqal_query_get_feature()
+ *
+ * Return value: the type of the feature or <0 if @feature is unknown
+ */
+int
+rasqal_feature_value_type(const rasqal_feature feature) {
+  if(feature > RASQAL_FEATURE_LAST)
+    return -1;
+  return (rasqal_features_list[feature].flags & 4) ? 1 : 0;
+}
+
+
+/**
+ * rasqal_feature_from_uri:
+ * @world: rasqal_world object
+ * @uri: feature URI
+ *
+ * Turn a feature URI into an feature enum.
+ * 
+ * The allowed feature URIs are available via rasqal_features_enumerate().
+ *
+ * Return value: < 0 if the feature is unknown
+ **/
+rasqal_feature
+rasqal_feature_from_uri(rasqal_world* world, raptor_uri *uri)
+{
+  unsigned char *uri_string;
+  int i;
+  rasqal_feature feature= (rasqal_feature)-1;
+  
+  if(!uri)
+    return feature;
+  
+#ifdef RAPTOR_V2_AVAILABLE
+  uri_string = raptor_uri_as_string_v2(world->raptor_world_ptr, uri);
+#else
+  uri_string = raptor_uri_as_string(uri);
+#endif
+  if(strncmp((const char*)uri_string, rasqal_feature_uri_prefix,
+             RASQAL_FEATURE_URI_PREFIX_LEN))
+    return feature;
+
+  uri_string += RASQAL_FEATURE_URI_PREFIX_LEN;
+
+  for(i=0; i <= RASQAL_FEATURE_LAST; i++)
+    if(!strcmp(rasqal_features_list[i].name, (const char*)uri_string)) {
+      feature=(rasqal_feature)i;
+      break;
+    }
+
+  return feature;
+}
+
+
+/**
+ * rasqal_get_feature_count:
+ *
+ * Get the count of features defined.
+ *
+ * This is prefered to the compile time-only symbol #RASQAL_FEATURE_LAST
+ * and returns a count of the number of features which is
+ * #RASQAL_FEATURE_LAST+1.
+ *
+ * Return value: count of features in the #rasqal_feature enumeration
+ **/
+unsigned int
+rasqal_get_feature_count(void) {
+  return RASQAL_FEATURE_LAST+1;
+}
diff --git a/src/rasqal/rasqal_general.c b/src/rasqal/rasqal_general.c
new file mode 100644
index 0000000..8619509
--- /dev/null
+++ b/src/rasqal/rasqal_general.c
@@ -0,0 +1,1128 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_general.c - Rasqal library startup, shutdown and factories
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+/* prototypes for helper functions */
+static void rasqal_delete_query_language_factories(rasqal_world*);
+
+
+/* statics */
+
+const char * const rasqal_short_copyright_string = "Copyright 2003-2008 David Beckett.  Copyright 2003-2005 University of Bristol";
+
+const char * const rasqal_copyright_string = "Copyright (C) 2003-2008 David Beckett - http://www.dajobe.org/\nCopyright (C) 2003-2005 University of Bristol - http://www.bristol.ac.uk/";;
+
+const char * const rasqal_license_string = "LGPL 2.1 or newer, GPL 2 or newer, Apache 2.0 or newer.\nSee http://librdf.org/rasqal/LICENSE.html for full terms.";
+
+const char * const rasqal_home_url_string = "http://librdf.org/rasqal/";;
+
+/**
+ * rasqal_version_string:
+ *
+ * Library full version as a string.
+ *
+ * See also #rasqal_version_decimal.
+ */
+const char * const rasqal_version_string = VERSION;
+
+/**
+ * rasqal_version_major:
+ *
+ * Library major version number as a decimal integer.
+ */
+const unsigned int rasqal_version_major = RASQAL_VERSION_MAJOR;
+
+/**
+ * rasqal_version_minor:
+ *
+ * Library minor version number as a decimal integer.
+ */
+const unsigned int rasqal_version_minor = RASQAL_VERSION_MINOR;
+
+/**
+ * rasqal_version_release:
+ *
+ * Library release version number as a decimal integer.
+ */
+const unsigned int rasqal_version_release = RASQAL_VERSION_RELEASE;
+
+/**
+ * rasqal_version_decimal:
+ *
+ * Library full version as a decimal integer.
+ *
+ * See also #rasqal_version_string.
+ */
+const unsigned int rasqal_version_decimal = RASQAL_VERSION_DECIMAL;
+
+
+/**
+ * rasqal_new_world:
+ * 
+ * Allocate a new rasqal_world object.
+ *
+ * The rasqal_world is initialized with rasqal_world_open().
+ * Allocation and initialization are decoupled to allow
+ * changing settings on the world object before init.
+ *
+ * Return value: rasqal_world object or NULL on failure
+ **/
+rasqal_world*
+rasqal_new_world(void)
+{
+  return (rasqal_world*)RASQAL_CALLOC(rasqal_world, sizeof(rasqal_world), 1);
+}
+
+
+/**
+ * rasqal_world_open:
+ * 
+ * Initialise the rasqal library.
+ *
+ * Initializes a #rasqal_world object created by rasqal_new_world().
+ * Allocation and initialization are decoupled to allow
+ * changing settings on the world object before init.
+ * These settings include e.g. the raptor library instance set with
+ * rasqal_world_set_raptor().
+ *
+ * The initialized world object is used with subsequent rasqal API calls.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_world_open(rasqal_world *world)
+{
+  int rc;
+
+  if(!world)
+    return -1;
+    
+  if(world->opened)
+    return 0; /* not an error */
+
+#ifdef RAPTOR_V2_AVAILABLE
+  /* Create and init a raptor_world unless one is provided externally with rasqal_world_set_raptor() */
+  if(!world->raptor_world_ptr) {
+    world->raptor_world_ptr = raptor_new_world();
+    if(!world->raptor_world_ptr)
+      return -1;
+    world->raptor_world_allocated_here = 1;
+    rc = raptor_world_open(world->raptor_world_ptr);
+    if(rc)
+      return rc;
+  }
+#else  
+  raptor_init();
+#endif
+
+  rc = rasqal_uri_init(world);
+  if(rc)
+    return rc;
+
+  rc = rasqal_xsd_init(world);
+  if(rc)
+    return rc;
+
+/* FIXME */
+#ifndef RAPTOR_ERROR_HANDLER_MAGIC
+#define RAPTOR_ERROR_HANDLER_MAGIC 0xD00DB1FF
+#endif
+  world->error_handlers.magic=RAPTOR_ERROR_HANDLER_MAGIC;
+
+  /* last one declared is the default - RDQL */
+
+#ifdef RASQAL_QUERY_RDQL
+  rc = rasqal_init_query_language_rdql(world);
+  if(rc)
+    return rc;
+#endif
+
+#ifdef RASQAL_QUERY_LAQRS
+  rc = rasqal_init_query_language_laqrs(world);
+  if(rc)
+    return rc;
+#endif
+
+#ifdef RASQAL_QUERY_SPARQL  
+  rc = rasqal_init_query_language_sparql(world);
+  if(rc)
+    return rc;
+#endif
+
+#ifdef RAPTOR_TRIPLES_SOURCE_RAPTOR
+  rc = rasqal_raptor_init(world);
+  if(rc)
+    return rc;
+#endif
+#ifdef RAPTOR_TRIPLES_SOURCE_REDLAND
+  rc = rasqal_redland_init(world);
+  if(rc)
+    return rc;
+#endif
+
+  rc = rasqal_init_query_results();
+  if(rc)
+    return rc;
+  
+  rc = rasqal_init_result_formats(world);
+  if(rc)
+    return rc;
+
+  world->opened = 1;
+
+  return 0;
+}
+
+
+/**
+ * rasqal_free_world:
+ * @world: rasqal_world object
+ * 
+ * Terminate the rasqal library.
+ *
+ * Destroys a rasqal_world object and all static information.
+ *
+ **/
+void
+rasqal_free_world(rasqal_world* world) 
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(world, rasqal_world);
+  
+  rasqal_finish_result_formats(world);
+  rasqal_finish_query_results();
+
+  rasqal_delete_query_language_factories(world);
+
+#ifdef RAPTOR_TRIPLES_SOURCE_REDLAND
+  rasqal_redland_finish();
+#endif
+
+  rasqal_xsd_finish(world);
+
+  rasqal_uri_finish(world);
+
+#ifdef RAPTOR_V2_AVAILABLE
+  if(world->raptor_world_ptr && world->raptor_world_allocated_here)
+    raptor_free_world(world->raptor_world_ptr);
+#else
+  raptor_finish();
+#endif
+
+  RASQAL_FREE(rasqal_world, world);
+}
+
+
+/**
+ * rasqal_world_set_raptor:
+ * @world: rasqal_world object
+ * @raptor_world_ptr: raptor_world object
+ * 
+ * Set the #raptor_world instance to be used with this #rasqal_world.
+ *
+ * If no raptor_world instance is set with this function,
+ * rasqal_world_open() creates a new instance.
+ *
+ * Ownership of the raptor_world is not taken. If the raptor library
+ * instance is set with this function, rasqal_free_world() will not
+ * free it.
+ *
+ **/
+void
+rasqal_world_set_raptor(rasqal_world* world, raptor_world* raptor_world_ptr)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(world, rasqal_world);
+  world->raptor_world_ptr = raptor_world_ptr;
+}
+
+
+/**
+ * rasqal_world_get_raptor:
+ * @world: rasqal_world object
+ * 
+ * Get the #raptor_world instance used by this #rasqal_world.
+ *
+ * Return value: raptor_world object or NULL on failure (e.g. not initialized)
+ **/
+raptor_world*
+rasqal_world_get_raptor(rasqal_world* world)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
+  return world->raptor_world_ptr;
+}
+
+
+/* helper functions */
+
+/*
+ * rasqal_free_query_language_factory - delete a query language factory
+ */
+static void
+rasqal_free_query_language_factory(rasqal_query_language_factory *factory)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(factory, rasqal_query_language_factory);
+  
+  if(factory) {
+    if(factory->finish_factory)
+      factory->finish_factory(factory);
+
+    if(factory->name)
+      RASQAL_FREE(rasqal_query_language_factory, (void*)factory->name);
+    if(factory->label)
+      RASQAL_FREE(rasqal_query_language_factory, (void*)factory->label);
+    if(factory->alias)
+      RASQAL_FREE(rasqal_query_language_factory, (void*)factory->alias);
+    if(factory->uri_string)
+      RASQAL_FREE(rasqal_query_language_factory, (void*)factory->uri_string);
+
+    RASQAL_FREE(rasqal_query_language_factory, factory);
+  }
+}
+
+
+/*
+ * rasqal_delete_query_language_factories - helper function to delete all the registered query language factories
+ */
+static void
+rasqal_delete_query_language_factories(rasqal_world *world)
+{
+  rasqal_query_language_factory *factory, *next;
+  
+  for(factory=world->query_languages; factory; factory=next) {
+    next=factory->next;
+    rasqal_free_query_language_factory(factory);
+  }
+  world->query_languages=NULL;
+}
+
+
+/* class methods */
+
+/*
+ * rasqal_query_language_register_factory - Register a syntax handled by a query factory
+ * @name: the short syntax name
+ * @label: readable label for syntax
+ * @uri_string: URI string of the syntax (or NULL)
+ * @factory: pointer to function to call to register the factory
+ * 
+ * INTERNAL
+ *
+ * Return value: non-0 on failure
+ **/
+RASQAL_EXTERN_C
+int
+rasqal_query_language_register_factory(rasqal_world *world,
+                                     const char *name, const char *label,
+                                     const char *alias,
+                                     const unsigned char *uri_string,
+                                     void (*factory) (rasqal_query_language_factory*)) 
+{
+  rasqal_query_language_factory *query, *h;
+  char *name_copy, *label_copy, *alias_copy;
+  unsigned char *uri_string_copy;
+  
+#if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
+  RASQAL_DEBUG4("Received registration for syntax %s '%s' with alias '%s'\n", 
+                name, label, (alias ? alias : "none"));
+  RASQAL_DEBUG2("URI %s\n", (uri_string ? (const char*)uri_string : (const char*)"none"));
+#endif
+  
+  query=(rasqal_query_language_factory*)RASQAL_CALLOC(rasqal_query_language_factory, 1,
+                                                    sizeof(rasqal_query_language_factory));
+  if(!query)
+    goto tidy_noquery;
+
+  for(h = world->query_languages; h; h = h->next ) {
+    if(!strcmp(h->name, name) ||
+       (alias && !strcmp(h->name, alias))) {
+      RASQAL_FATAL2("query %s already registered\n", h->name);
+    }
+  }
+  
+  name_copy=(char*)RASQAL_CALLOC(cstring, strlen(name)+1, 1);
+  if(!name_copy)
+    goto tidy;
+  strcpy(name_copy, name);
+  query->name=name_copy;
+        
+  label_copy=(char*)RASQAL_CALLOC(cstring, strlen(label)+1, 1);
+  if(!label_copy)
+    goto tidy;
+  strcpy(label_copy, label);
+  query->label=label_copy;
+
+  if(uri_string) {
+    uri_string_copy=(unsigned char*)RASQAL_CALLOC(cstring, strlen((const char*)uri_string)+1, 1);
+    if(!uri_string_copy)
+      goto tidy;
+    strcpy((char*)uri_string_copy, (const char*)uri_string);
+    query->uri_string=uri_string_copy;
+  }
+        
+  if(alias) {
+    alias_copy=(char*)RASQAL_CALLOC(cstring, strlen(alias)+1, 1);
+    if(!alias_copy)
+      goto tidy;
+    strcpy(alias_copy, alias);
+    query->alias=alias_copy;
+  }
+
+  /* Call the query registration function on the new object */
+  (*factory)(query);
+  
+#if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
+  RASQAL_DEBUG3("%s has context size %d\n", name, (int)query->context_length);
+#endif
+  
+  query->next = world->query_languages;
+  world->query_languages = query;
+
+  return 0;
+
+  tidy:
+  rasqal_free_query_language_factory(query);
+  tidy_noquery:
+  rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_FATAL, NULL,
+                          "Out of memory in rasqal_query_language_register_factory()");
+  return 1;
+}
+
+
+/**
+ * rasqal_get_query_language_factory:
+ * @name: the factory name or NULL for the default factory
+ * @uri: the query syntax URI or NULL
+ *
+ * Get a query factory by name.
+ * 
+ * Return value: the factory object or NULL if there is no such factory
+ **/
+rasqal_query_language_factory*
+rasqal_get_query_language_factory(rasqal_world *world, const char *name,
+                                const unsigned char *uri)
+{
+  rasqal_query_language_factory *factory;
+
+  /* return 1st query if no particular one wanted - why? */
+  if(!name && !uri) {
+    factory=world->query_languages;
+    if(!factory) {
+      RASQAL_DEBUG1("No (default) query_languages registered\n");
+      return NULL;
+    }
+  } else {
+    for(factory=world->query_languages; factory; factory=factory->next) {
+      if((name && !strcmp(factory->name, name)) ||
+         (factory->alias && !strcmp(factory->alias, name)))
+        break;
+      if(uri && !strcmp((const char*)factory->uri_string, (const char*)uri))
+        break;
+    }
+    /* else FACTORY name not found */
+    if(!factory) {
+      RASQAL_DEBUG2("No query language with name %s found\n", name);
+      return NULL;
+    }
+  }
+        
+  return factory;
+}
+
+
+/**
+ * rasqal_languages_enumerate:
+ * @world: rasqal_world object
+ * @counter: index into the list of syntaxes
+ * @name: pointer to store the name of the syntax (or NULL)
+ * @label: pointer to store syntax readable label (or NULL)
+ * @uri_string: pointer to store syntax URI string (or NULL)
+ *
+ * Get information on query languages.
+ * 
+ * Return value: non 0 on failure of if counter is out of range
+ **/
+int
+rasqal_languages_enumerate(rasqal_world *world,
+                           unsigned int counter,
+                           const char **name, const char **label,
+                           const unsigned char **uri_string)
+{
+  unsigned int i;
+  rasqal_query_language_factory *factory=world->query_languages;
+
+  if(!factory)
+    return 1;
+
+  for(i=0; factory && i<=counter ; i++, factory=factory->next) {
+    if(i == counter) {
+      if(name)
+        *name=factory->name;
+      if(label)
+        *label=factory->label;
+      if(uri_string)
+        *uri_string=factory->uri_string;
+      return 0;
+    }
+  }
+        
+  return 1;
+}
+
+
+/**
+ * rasqal_language_name_check:
+ * @world: rasqal_world object
+ * @name: the query language name
+ *
+ * Check name of a query language.
+ *
+ * Return value: non 0 if name is a known query language
+ */
+int
+rasqal_language_name_check(rasqal_world* world, const char *name) {
+  return (rasqal_get_query_language_factory(world, name, NULL) != NULL);
+}
+
+
+static const char* const rasqal_log_level_labels[RAPTOR_LOG_LEVEL_LAST+1]={
+  "none",
+  "fatal error",
+  "error",
+  "warning"
+};
+
+
+/* internal */
+void
+rasqal_log_error_simple(rasqal_world* world, raptor_log_level level,
+                        raptor_locator* locator, const char* message, ...)
+{
+  va_list arguments;
+
+  if(level == RAPTOR_LOG_LEVEL_NONE)
+    return;
+
+  va_start(arguments, message);
+  rasqal_log_error_varargs(world, level, locator, message, arguments);
+  va_end(arguments);
+}
+
+
+void
+rasqal_log_error_varargs(rasqal_world* world, raptor_log_level level,
+                         raptor_locator* locator,
+                         const char* message, va_list arguments)
+{
+  char *buffer;
+  size_t length;
+  raptor_message_handler handler=world->error_handlers.handlers[level].handler;
+  void* handler_data=world->error_handlers.handlers[level].user_data;
+  
+  if(level == RAPTOR_LOG_LEVEL_NONE)
+    return;
+
+  buffer=raptor_vsnprintf(message, arguments);
+  if(!buffer) {
+    if(locator) {
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_print_locator_v2(world->raptor_world_ptr, stderr, locator);
+#else
+      raptor_print_locator(stderr, locator);
+#endif
+      fputc(' ', stderr);
+    }
+    fputs("rasqal ", stderr);
+    fputs(rasqal_log_level_labels[level], stderr);
+    fputs(" - ", stderr);
+    vfprintf(stderr, message, arguments);
+    fputc('\n', stderr);
+    return;
+  }
+
+  length=strlen(buffer);
+  if(buffer[length-1]=='\n')
+    buffer[length-1]='\0';
+  
+  if(handler)
+    /* This is the single place in rasqal that the user error handler
+     * functions are called.
+     */
+    handler(handler_data, locator, buffer);
+  else {
+    if(locator) {
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_print_locator_v2(world->raptor_world_ptr, stderr, locator);
+#else
+      raptor_print_locator(stderr, locator);
+#endif
+      fputc(' ', stderr);
+    }
+    fputs("rasqal ", stderr);
+    fputs(rasqal_log_level_labels[level], stderr);
+    fputs(" - ", stderr);
+    fputs(buffer, stderr);
+    fputc('\n', stderr);
+  }
+
+  RASQAL_FREE(cstring, buffer);
+}
+
+
+/*
+ * rasqal_query_simple_error - Error from a query - Internal
+ *
+ * Matches the raptor_simple_message_handler API but same as
+ * rasqal_query_error 
+ */
+void
+rasqal_query_simple_error(void* user_data, const char *message, ...)
+{
+  rasqal_query* query=(rasqal_query*)user_data;
+
+  va_list arguments;
+
+  va_start(arguments, message);
+
+  query->failed=1;
+  rasqal_log_error_varargs(query->world,
+                           RAPTOR_LOG_LEVEL_ERROR, NULL,
+                           message, arguments);
+  
+  va_end(arguments);
+}
+
+
+/* wrapper */
+const char*
+rasqal_basename(const char *name)
+{
+  char *p;
+  if((p=strrchr(name, '/')))
+    name=p+1;
+  else if((p=strrchr(name, '\\')))
+    name=p+1;
+
+  return name;
+}
+
+
+/**
+ * rasqal_escaped_name_to_utf8_string:
+ * @src: source name string
+ * @len: length of source name string
+ * @dest_lenp: pointer to store result string (or NULL)
+ * @error_handler: error handling function
+ * @error_data: data for error handle
+ *
+ * Get a UTF-8 and/or \u-escaped name as UTF-8.
+ *
+ * If dest_lenp is not NULL, the length of the resulting string is
+ * stored at the pointed size_t.
+ *
+ * Return value: new UTF-8 string or NULL on failure.
+ */
+unsigned char*
+rasqal_escaped_name_to_utf8_string(const unsigned char *src, size_t len,
+                                   size_t *dest_lenp,
+                                   raptor_simple_message_handler error_handler,
+                                   void *error_data)
+{
+  const unsigned char *p=src;
+  size_t ulen=0;
+  unsigned long unichar=0;
+  unsigned char *result;
+  unsigned char *dest;
+  int n;
+  
+  result=(unsigned char*)RASQAL_MALLOC(cstring, len+1);
+  if(!result)
+    return NULL;
+
+  dest=result;
+
+  /* find end of string, fixing backslashed characters on the way */
+  while(len > 0) {
+    unsigned char c=*p;
+
+    if(c > 0x7f) {
+      /* just copy the UTF-8 bytes through */
+      size_t unichar_len=raptor_utf8_to_unicode_char(NULL, (const unsigned char*)p, len+1);
+      if(unichar_len > len) {
+        if(error_handler)
+          error_handler(error_data, "UTF-8 encoding error at character %d (0x%02X) found.", c, c);
+        /* UTF-8 encoding had an error or ended in the middle of a string */
+        RASQAL_FREE(cstring, result);
+        return NULL;
+      }
+      memcpy(dest, p, unichar_len);
+      dest+= unichar_len;
+      p += unichar_len;
+      len -= unichar_len;
+      continue;
+    }
+
+    p++; len--;
+    
+    if(c != '\\') {
+      /* not an escape - store and move on */
+      *dest++=c;
+      continue;
+    }
+
+    if(!len) {
+      RASQAL_FREE(cstring, result);
+      return NULL;
+    }
+
+    c = *p++; len--;
+
+    switch(c) {
+      case '"':
+      case '\\':
+        *dest++=c;
+        break;
+      case 'u':
+      case 'U':
+        ulen=(c == 'u') ? 4 : 8;
+        
+        if(len < ulen) {
+          if(error_handler)
+            error_handler(error_data, "%c over end of line", c);
+          RASQAL_FREE(cstring, result);
+          return 0;
+        }
+        
+        n=sscanf((const char*)p, ((ulen == 4) ? "%04lx" : "%08lx"), &unichar);
+        if(n != 1) {
+          if(error_handler)
+            error_handler(error_data, "Bad %c escape", c);
+          break;
+        }
+        
+        p+=ulen;
+        len-=ulen;
+        
+        if(unichar > 0x10ffff) {
+          if(error_handler)
+            error_handler(error_data, "Illegal Unicode character with code point #x%lX.", unichar);
+          break;
+        }
+          
+        dest+=raptor_unicode_char_to_utf8(unichar, dest);
+        break;
+
+      default:
+        if(error_handler)
+          error_handler(error_data, "Illegal string escape \\%c in \"%s\"", c, src);
+        RASQAL_FREE(cstring, result);
+        return 0;
+    }
+
+  } /* end while */
+
+  
+  /* terminate dest, can be shorter than source */
+  *dest='\0';
+
+  if(dest_lenp)
+    *dest_lenp=dest-result;
+
+  return result;
+}
+
+
+int
+rasqal_uri_init(rasqal_world* world) 
+{
+#ifdef RAPTOR_V2_AVAILABLE
+  world->rdf_namespace_uri = raptor_new_uri_v2(world->raptor_world_ptr, raptor_rdf_namespace_uri);
+#else
+  world->rdf_namespace_uri = raptor_new_uri(raptor_rdf_namespace_uri);
+#endif
+  if(!world->rdf_namespace_uri)
+    goto oom;
+
+#ifdef RAPTOR_V2_AVAILABLE
+  world->rdf_first_uri = raptor_new_uri_from_uri_local_name_v2(world->raptor_world_ptr, world->rdf_namespace_uri, (const unsigned char*)"first");
+  world->rdf_rest_uri = raptor_new_uri_from_uri_local_name_v2(world->raptor_world_ptr, world->rdf_namespace_uri, (const unsigned char*)"rest");
+  world->rdf_nil_uri = raptor_new_uri_from_uri_local_name_v2(world->raptor_world_ptr, world->rdf_namespace_uri, (const unsigned char*)"nil");
+#else
+  world->rdf_first_uri = raptor_new_uri_from_uri_local_name(world->rdf_namespace_uri, (const unsigned char*)"first");
+  world->rdf_rest_uri = raptor_new_uri_from_uri_local_name(world->rdf_namespace_uri, (const unsigned char*)"rest");
+  world->rdf_nil_uri = raptor_new_uri_from_uri_local_name(world->rdf_namespace_uri, (const unsigned char*)"nil");
+#endif
+
+  if(!world->rdf_first_uri || !world->rdf_rest_uri || !world->rdf_nil_uri)
+    goto oom;
+
+  return 0;
+
+  oom:
+  rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_FATAL,
+                          NULL,
+                          "Out of memory");
+  return 1;
+}
+
+
+void
+rasqal_uri_finish(rasqal_world* world) 
+{
+#ifdef RAPTOR_V2_AVAILABLE
+  if(world->rdf_first_uri) {
+    raptor_free_uri_v2(world->raptor_world_ptr, world->rdf_first_uri);
+    world->rdf_first_uri = NULL;
+  }
+  if(world->rdf_rest_uri) {
+    raptor_free_uri_v2(world->raptor_world_ptr, world->rdf_rest_uri);
+    world->rdf_rest_uri = NULL;
+  }
+  if(world->rdf_nil_uri) {
+    raptor_free_uri_v2(world->raptor_world_ptr, world->rdf_nil_uri);
+    world->rdf_nil_uri = NULL;
+  }
+  if(world->rdf_namespace_uri) {
+    raptor_free_uri_v2(world->raptor_world_ptr, world->rdf_namespace_uri);
+    world->rdf_namespace_uri = NULL;
+  }
+#else
+  if(world->rdf_first_uri) {
+    raptor_free_uri(world->rdf_first_uri);
+    world->rdf_first_uri=NULL;
+  }
+  if(world->rdf_rest_uri) {
+    raptor_free_uri(world->rdf_rest_uri);
+    world->rdf_rest_uri=NULL;
+  }
+  if(world->rdf_nil_uri) {
+    raptor_free_uri(world->rdf_nil_uri);
+    world->rdf_nil_uri=NULL;
+  }
+  if(world->rdf_namespace_uri) {
+    raptor_free_uri(world->rdf_namespace_uri);
+    world->rdf_namespace_uri=NULL;
+  }
+#endif
+}
+
+
+/**
+ * rasqal_query_set_default_generate_bnodeid_parameters - Set default bnodeid generation parameters
+ * @rdf_query: #rasqal_query object
+ * @prefix: prefix string
+ * @base: integer base identifier
+ *
+ * Sets the parameters for the default algorithm used to generate
+ * blank node IDs.  The default algorithm uses both @prefix and @base
+ * to generate a new identifier.  The exact identifier generated is
+ * not guaranteed to be a strict concatenation of @prefix and @base
+ * but will use both parts.
+ *
+ * For finer control of the generated identifiers, use
+ * rasqal_set_default_generate_bnodeid_handler()
+ *
+ * If prefix is NULL, the default prefix is used (currently "bnodeid")
+ * If base is less than 1, it is initialised to 1.
+ * 
+ **/
+void
+rasqal_query_set_default_generate_bnodeid_parameters(rasqal_query* rdf_query, 
+                                                     char *prefix, int base)
+{
+  char *prefix_copy=NULL;
+  size_t length=0;
+
+  if(--base<0)
+    base=0;
+
+  if(prefix) {
+    length=strlen(prefix);
+    
+    prefix_copy=(char*)RASQAL_MALLOC(cstring, length+1);
+    if(!prefix_copy)
+      return;
+    strcpy(prefix_copy, prefix);
+  }
+  
+  if(rdf_query->default_generate_bnodeid_handler_prefix)
+    RASQAL_FREE(cstring, rdf_query->default_generate_bnodeid_handler_prefix);
+
+  rdf_query->default_generate_bnodeid_handler_prefix=prefix_copy;
+  rdf_query->default_generate_bnodeid_handler_prefix_length=length;
+  rdf_query->default_generate_bnodeid_handler_base=base;
+}
+
+
+/**
+ * rasqal_query_set_generate_bnodeid_handler:
+ * @query: #rasqal_query query object
+ * @user_data: user data pointer for callback
+ * @handler: generate blank ID callback function
+ *
+ * Set the generate blank node ID handler function for the query.
+ *
+ * Sets the function to generate blank node IDs for the query.
+ * The handler is called with a pointer to the rasqal_query, the
+ * @user_data pointer and a user_bnodeid which is the value of
+ * a user-provided blank node identifier (may be NULL).
+ * It can either be returned directly as the generated value when present or
+ * modified.  The passed in value must be free()d if it is not used.
+ *
+ * If handler is NULL, the default method is used
+ * 
+ **/
+void
+rasqal_query_set_generate_bnodeid_handler(rasqal_query* query,
+                                          void *user_data,
+                                          rasqal_generate_bnodeid_handler handler)
+{
+  query->generate_bnodeid_handler_user_data=user_data;
+  query->generate_bnodeid_handler=handler;
+}
+
+
+static unsigned char*
+rasqal_default_generate_bnodeid_handler(void *user_data,
+                                        unsigned char *user_bnodeid) 
+{
+  rasqal_query *rdf_query=(rasqal_query *)user_data;
+  int id;
+  unsigned char *buffer;
+  int length;
+  int tmpid;
+
+  if(user_bnodeid)
+    return user_bnodeid;
+
+  id=++rdf_query->default_generate_bnodeid_handler_base;
+
+  tmpid=id;
+  length=2; /* min length 1 + \0 */
+  while(tmpid/=10)
+    length++;
+
+  if(rdf_query->default_generate_bnodeid_handler_prefix)
+    length += rdf_query->default_generate_bnodeid_handler_prefix_length;
+  else
+    length += 7; /* bnodeid */
+  
+  buffer=(unsigned char*)RASQAL_MALLOC(cstring, length);
+  if(!buffer)
+    return NULL;
+  if(rdf_query->default_generate_bnodeid_handler_prefix) {
+    strncpy((char*)buffer, rdf_query->default_generate_bnodeid_handler_prefix,
+            rdf_query->default_generate_bnodeid_handler_prefix_length);
+    sprintf((char*)buffer + rdf_query->default_generate_bnodeid_handler_prefix_length,
+            "%d", id);
+  } else 
+    sprintf((char*)buffer, "bnodeid%d", id);
+
+  return buffer;
+}
+
+
+/*
+ * rasqal_query_generate_bnodeid - Default generate id - internal
+ */
+unsigned char*
+rasqal_query_generate_bnodeid(rasqal_query* rdf_query,
+                              unsigned char *user_bnodeid)
+{
+  if(rdf_query->generate_bnodeid_handler)
+    return rdf_query->generate_bnodeid_handler(rdf_query, 
+                                               rdf_query->generate_bnodeid_handler_user_data, user_bnodeid);
+  else
+    return rasqal_default_generate_bnodeid_handler(rdf_query, user_bnodeid);
+}
+
+
+
+
+/**
+ * rasqal_free_memory:
+ * @ptr: memory pointer
+ *
+ * Free memory allocated inside rasqal.
+ * 
+ * Some systems require memory allocated in a library to
+ * be deallocated in that library.  This function allows
+ * memory allocated by rasqal to be freed.
+ *
+ **/
+void
+rasqal_free_memory(void *ptr)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(ptr, memory);
+  
+  RASQAL_FREE(void, ptr);
+}
+
+
+/**
+ * rasqal_alloc_memory:
+ * @size: size of memory to allocate
+ *
+ * Allocate memory inside rasqal.
+ * 
+ * Some systems require memory allocated in a library to
+ * be deallocated in that library.  This function allows
+ * memory to be allocated inside the rasqal shared library
+ * that can be freed inside rasqal either internally or via
+ * rasqal_free_memory().
+ *
+ * Return value: the address of the allocated memory or NULL on failure
+ *
+ **/
+void*
+rasqal_alloc_memory(size_t size)
+{
+  return RASQAL_MALLOC(void, size);
+}
+
+
+/**
+ * rasqal_calloc_memory:
+ * @nmemb: number of members
+ * @size: size of item
+ *
+ * Allocate zeroed array of items inside rasqal.
+ * 
+ * Some systems require memory allocated in a library to
+ * be deallocated in that library.  This function allows
+ * memory to be allocated inside the rasqal shared library
+ * that can be freed inside rasqal either internally or via
+ * rasqal_free_memory().
+ *
+ * Return value: the address of the allocated memory or NULL on failure
+ *
+ **/
+void*
+rasqal_calloc_memory(size_t nmemb, size_t size)
+{
+  return RASQAL_CALLOC(void, nmemb, size);
+}
+
+
+#if defined (RASQAL_DEBUG) && defined(RASQAL_MEMORY_SIGN)
+void*
+rasqal_sign_malloc(size_t size)
+{
+  int *p;
+  
+  size += sizeof(int);
+  
+  p=(int*)malloc(size);
+  *p++ = RASQAL_SIGN_KEY;
+  return p;
+}
+
+void*
+rasqal_sign_calloc(size_t nmemb, size_t size)
+{
+  int *p;
+  
+  /* turn into bytes */
+  size = nmemb*size + sizeof(int);
+  
+  p=(int*)calloc(1, size);
+  *p++ = RASQAL_SIGN_KEY;
+  return p;
+}
+
+void*
+rasqal_sign_realloc(void *ptr, size_t size)
+{
+  int *p;
+
+  if(!ptr)
+    return rasqal_sign_malloc(size);
+  
+  p=(int*)ptr;
+  p--;
+
+  if(*p != RASQAL_SIGN_KEY)
+    RASQAL_FATAL3("memory signature %08X != %08X", *p, RASQAL_SIGN_KEY);
+
+  size += sizeof(int);
+  
+  p=(int*)realloc(p, size);
+  *p++= RASQAL_SIGN_KEY;
+  return p;
+}
+
+void
+rasqal_sign_free(void *ptr)
+{
+  int *p;
+
+  if(!ptr)
+    return;
+  
+  p=(int*)ptr;
+  p--;
+
+  if(*p != RASQAL_SIGN_KEY)
+    RASQAL_FATAL3("memory signature %08X != %08X", *p, RASQAL_SIGN_KEY);
+
+  free(p);
+}
+#endif
+
+
+#if defined (RASQAL_DEBUG) && defined(HAVE_DMALLOC_H) && defined(RASQAL_MEMORY_DEBUG_DMALLOC)
+
+#undef malloc
+void*
+rasqal_system_malloc(size_t size)
+{
+  return malloc(size);
+}
+
+#undef free
+void
+rasqal_system_free(void *ptr)
+{
+  return free(ptr);
+  
+}
+
+#endif
+
diff --git a/src/rasqal/rasqal_graph.c b/src/rasqal/rasqal_graph.c
new file mode 100644
index 0000000..6f7d1aa
--- /dev/null
+++ b/src/rasqal/rasqal_graph.c
@@ -0,0 +1,459 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_graph.c - Rasqal Graph API
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+typedef struct 
+{
+  int usage;
+  rasqal_world *world;
+  raptor_uri *uri;
+  void *user_data;
+} rasqal_graph;
+
+typedef struct 
+{
+  rasqal_world *world;
+  rasqal_graph *graph;
+  void *user_data;
+} rasqal_graph_match;
+
+typedef struct 
+{
+  rasqal_world *world;
+  rasqal_graph *graph;
+  void *user_data;
+} rasqal_graph_bindings;
+
+
+struct rasqal_graph_factory_s
+{
+  int version; /* API version */
+
+  /* One-time initialisation/termination of graph factory (optional) */
+  void* (*init_factory)(rasqal_world* world);
+  void (*terminate_factory)(void *graph_factory_user_data);
+
+  /* Dataset API (required)
+   *
+   * Manage a set of RDF graphs
+   */
+  /* list dataset graphs */
+  raptor_uri* (*dataset_enumerate)(void *graph_factory_user_data, int offset);
+  /* load dataset with a graph via URI */
+  int (*dataset_load)(void *graph_factory_user_data, raptor_uri* uri);
+
+  /* RDF Graph API (required)
+   *
+   * (acts like librdf_model)
+   */
+  void *(*new_graph)(rasqal_world* world, raptor_uri* uri);
+  void (*free_graph)(void *graph_user_data);
+  /* Check for presence of a triple (NOT triple pattern) in a graph (required)
+   * (acts like librdf_model_contains_statement)
+   */
+  int (*graph_triple_present)(void *graph_user_data, rasqal_triple *triple);
+
+  /* Triple pattern matching API (required)
+   *
+   * Find triples matching a triple pattern
+   * (acts like librdf_model_find_statements returning a librdf_stream of
+   * librdf_statement)
+   */
+  void* (*new_graph_match)(rasqal_graph *graph, rasqal_triple *triple);
+  rasqal_triple* (*graph_match_get_triple)(void *match_user_data);
+  void (*free_graph_match)(void *match_user_data);
+
+  /* Graph pattern binding API (optional)
+   * 
+   * Bind variables when triples in the graph match a graph pattern
+   */
+  void* (*new_graph_bindings)(rasqal_graph *graph, rasqal_triple **triples, int triples_count, rasqal_expression *filter);
+  int (*graph_bindings_bind)(void *graph_bindings_user_data);
+  void (*free_graph_bindings)(void *graph_bindings_user_data);
+};
+
+
+/* prototypes */
+int rasqal_init_graph_factory(rasqal_world *world, rasqal_graph_factory *factory);
+void rasqal_free_graph_factory(rasqal_world *world);
+int rasqal_dataset_graph_present(rasqal_world* world, raptor_uri* uri);
+raptor_uri* rasqal_dataset_enumerate(rasqal_world* world, int offset);
+int rasqal_dataset_graph_load(rasqal_world* world, raptor_uri* uri);
+rasqal_graph* rasqal_new_graph(rasqal_world* world, raptor_uri *uri);
+void rasqal_free_graph(rasqal_graph *graph);
+int rasqal_graph_triple_present(rasqal_graph *graph, rasqal_triple *triple);
+rasqal_graph_match* rasqal_new_graph_match(rasqal_graph *graph, rasqal_triple *triple);
+void rasqal_free_graph_match(rasqal_graph_match *match);
+rasqal_triple* rasqal_graph_match_get_triple(rasqal_graph_match *match);
+rasqal_graph_bindings* rasqal_new_graph_bindings(rasqal_graph *graph, rasqal_triple **triples, int triples_count, rasqal_expression *filter);
+void rasqal_free_graph_bindings(rasqal_graph_bindings *graph_bindings);
+int rasqal_graph_bindings_bind(rasqal_graph_bindings *graph_bindings);
+
+
+/**
+ * rasqal_init_graph_factory:
+ * @world: rasqal world
+ * @factory: factory
+ *
+ * Set graph matching factory for rasqal world.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_init_graph_factory(rasqal_world *world,
+                          rasqal_graph_factory *factory)
+{
+  if(world->graph_factory)
+    rasqal_free_graph_factory(world);
+  
+  world->graph_factory = factory;
+
+  if(factory->init_factory) {
+    world->graph_factory_user_data = factory->init_factory(world);
+    return (world->graph_factory_user_data == NULL);
+  }
+
+  return 0;
+}
+
+
+/**
+ * rasqal_free_graph_factory:
+ * @world: rasqal world
+ *
+ * Free any resources attached to the graph factory
+ */
+void
+rasqal_free_graph_factory(rasqal_world *world)
+{
+  rasqal_graph_factory *factory = world->graph_factory;
+
+  if(factory->terminate_factory)
+    factory->terminate_factory(world->graph_factory_user_data);
+}
+
+
+/**
+ * rasqal_dataset_enumerate:
+ * @world: rasqal world
+ * @offset: offset
+ * 
+ * Get the URIs of the graphs in the dataset
+ * 
+ * Return value: URI or NULL if offset is out of rangek
+ **/
+raptor_uri*
+rasqal_dataset_enumerate(rasqal_world* world, int offset)
+{
+  rasqal_graph_factory *factory = world->graph_factory;
+
+  return factory->dataset_enumerate(world->graph_factory_user_data, offset);
+}
+
+
+/**
+ * rasqal_dataset_graph_present:
+ * @world: rasqal world
+ * @uri: graph URI
+ * 
+ * Check if a graph is in the dataset
+ * 
+ * Return value: non-0 if the graph is present
+ **/
+int
+rasqal_dataset_graph_present(rasqal_world* world, raptor_uri* uri)
+{
+  int offset = 0;
+  
+  while(1) {
+    raptor_uri *graph_uri;
+    
+    graph_uri = rasqal_dataset_enumerate(world, offset++);
+    if(!graph_uri)
+      break;
+
+    if(raptor_uri_equals(uri, graph_uri))
+      return 1;
+  }
+  
+  return 0;
+}
+
+
+/**
+ * rasqal_dataset_graph_load:
+ * @world: rasqal world
+ * @uri: graph URI to load
+ * 
+ * Load graph into daaset
+ * 
+ * Return value: graph API object or NULL on failure
+ **/
+int
+rasqal_dataset_graph_load(rasqal_world* world, raptor_uri* uri)
+{
+  rasqal_graph_factory *factory = world->graph_factory;
+
+  return factory->dataset_load(world->graph_factory_user_data, uri);
+}
+
+
+/**
+ * rasqal_new_graph:
+ * @world: rasqal world
+ * @uri: graph URI (or NULL for default graph)
+ * 
+ * Constructor - Create a new graph API for a given URI
+ * 
+ * Returns: graph API object or NULL on failure
+ **/
+rasqal_graph*
+rasqal_new_graph(rasqal_world* world, raptor_uri *uri)
+{
+  rasqal_graph* g;
+  rasqal_graph_factory *factory = world->graph_factory;
+
+  g = (rasqal_graph*)RASQAL_CALLOC(rasqal_graph, sizeof(rasqal_graph), 1);
+  if(!g)
+    return NULL;
+  g->world = world;
+  g->user_data = factory->new_graph(world, uri);
+  if(!g->user_data) {
+    RASQAL_FREE(rasqal_graph, g);
+    return NULL;
+  }
+
+  g->usage = 1;
+  return g;
+}
+
+
+/**
+ * rasqal_free_graph:
+ * @graph: graph API object
+ * 
+ * Destructor - Destroy a graph API object
+ * 
+ **/
+void
+rasqal_free_graph(rasqal_graph *graph)
+{
+  rasqal_graph_factory *factory = graph->world->graph_factory;
+
+  if(graph->usage--)
+    return;
+  
+  if(factory->free_graph)
+    factory->free_graph(graph->user_data);
+  RASQAL_FREE(rasqal_graph, graph);
+}
+
+
+/**
+ * rasqal_new_graph_from_graph:
+ * @graph: graph API object
+ *
+ * Copy constructor
+ *
+ * Return value: new graph object
+ */
+static rasqal_graph*
+rasqal_new_graph_from_graph(rasqal_graph *graph)
+{
+  graph->usage++;
+
+  return graph;
+}
+
+
+/**
+ * rasqal_graph_triple_present:
+ * @graph: graph API object
+ * @triple: triple
+ *
+ * Test if a triple is in a graph
+ *
+ * Return value: non-0 if triple is present
+ */
+int
+rasqal_graph_triple_present(rasqal_graph *graph, rasqal_triple *triple)
+{
+  rasqal_graph_factory *factory = graph->world->graph_factory;
+
+  return factory->graph_triple_present(graph->user_data, triple);
+}
+
+
+/**
+ * rasqal_new_graph_match:
+ * @graph: graph API object
+ * @triple: triple pattern
+ * 
+ * Constructor - create a new triple pattern matcher for a triple pattern
+ * 
+ * Returns: triple pattern matcher or NULL on failure
+ **/
+rasqal_graph_match*
+rasqal_new_graph_match(rasqal_graph *graph, rasqal_triple *triple)
+{
+  rasqal_graph_match* gm;
+  rasqal_graph_factory *factory = graph->world->graph_factory;
+
+  gm = (rasqal_graph_match*)RASQAL_CALLOC(rasqal_graph_match,
+                                          sizeof(rasqal_graph_match), 1);
+  if(!gm)
+    return NULL;
+
+  gm->graph = rasqal_new_graph_from_graph(graph);
+  gm->user_data = factory->new_graph_match(graph, triple);
+  if(!gm->user_data) {
+    RASQAL_FREE(graph_match, gm);
+    return NULL;
+  }
+
+  return gm;
+}
+
+
+/**
+ * rasqal_free_graph_match:
+ * @match: triple pattern matcher object
+ * 
+ * Destructor - Delete a triple pattern matcher
+ **/
+void
+rasqal_free_graph_match(rasqal_graph_match *match)
+{
+  rasqal_graph_factory *factory = match->world->graph_factory;
+
+  rasqal_free_graph(match->graph);
+
+  if(factory->free_graph_match)
+    factory->free_graph_match(match->user_data);
+  RASQAL_FREE(rasqal_graph_match, match);
+}
+
+
+/**
+ * rasqal_graph_match_get_triple:
+ * @match: triple pattern matcher object
+ * 
+ * Get the next triple from a triple pattern matcher
+ * 
+ * Returns: new triple object or NULL when no (more) triples match
+ **/
+rasqal_triple*
+rasqal_graph_match_get_triple(rasqal_graph_match *match)
+{
+  rasqal_graph_factory *factory = match->world->graph_factory;
+
+  return factory->graph_match_get_triple(match->user_data);
+}
+
+
+/**
+ * rasqal_new_graph_bindings:
+ * @graph: graph API object 
+ * @triples: graph pattern as an array of triples of size @triples_count
+ * @triples_count: number of triples in graph pattern
+ * @filter: expression over the resulting bound variables to filter and constrain matches
+ * 
+ * Returns: 
+ **/
+rasqal_graph_bindings*
+rasqal_new_graph_bindings(rasqal_graph *graph,
+                          rasqal_triple **triples,
+                          int triples_count,
+                          rasqal_expression *filter)
+{
+  rasqal_graph_bindings* gb;
+  rasqal_graph_factory *factory = graph->world->graph_factory;
+
+  gb = (rasqal_graph_bindings*)RASQAL_CALLOC(rasqal_graph_bindings,
+                                             sizeof(rasqal_graph_bindings), 1);
+  if(!gb)
+    return NULL;
+  
+  gb->graph = rasqal_new_graph_from_graph(graph);
+  gb->user_data = factory->new_graph_bindings(graph, triples, triples_count,
+                                              filter);
+  if(!gb->user_data) {
+    RASQAL_FREE(graph_bindings, gb);
+    return NULL;
+  }
+
+  return gb;
+}
+
+
+/**
+ * rasqal_free_graph_bindings:
+ * @graph_bindings: graph binding object
+ * 
+ * Destructor - free a graph bindings object
+ **/
+void
+rasqal_free_graph_bindings(rasqal_graph_bindings *graph_bindings)
+{
+  rasqal_graph_factory *factory = graph_bindings->world->graph_factory;
+
+  rasqal_free_graph(graph_bindings->graph);
+
+  if(factory->free_graph_bindings)
+    factory->free_graph_bindings(graph_bindings->user_data);
+  RASQAL_FREE(rasqal_graph_bindings, graph_bindings);
+}
+
+
+/**
+ * rasqal_graph_bindings_bind:
+ * @graph_bindings: graph bindings object
+ *
+ * Match a graph pattern and bind variables to the matches
+ * 
+ * Returns: non-0 on failure
+ **/
+int
+rasqal_graph_bindings_bind(rasqal_graph_bindings *graph_bindings)
+{
+  rasqal_graph_factory *factory = graph_bindings->world->graph_factory;
+
+  return factory->graph_bindings_bind(graph_bindings->user_data);
+}
diff --git a/src/rasqal/rasqal_graph_pattern.c b/src/rasqal/rasqal_graph_pattern.c
new file mode 100644
index 0000000..e4032b5
--- /dev/null
+++ b/src/rasqal/rasqal_graph_pattern.c
@@ -0,0 +1,864 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_graph_pattern.c - Rasqal graph pattern class
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+/*
+ * rasqal_new_graph_pattern:
+ * @query: #rasqal_graph_pattern query object
+ * @op: enum #rasqal_graph_pattern_operator operator
+ *
+ * INTERNAL - Create a new graph pattern object.
+ * 
+ * NOTE: This does not initialise the graph pattern completely
+ * but relies on other operations.  The empty graph pattern
+ * has no triples and no sub-graphs.
+ *
+ * Return value: a new #rasqal_graph_pattern object or NULL on failure
+ **/
+static rasqal_graph_pattern*
+rasqal_new_graph_pattern(rasqal_query* query, 
+                         rasqal_graph_pattern_operator op)
+{
+  rasqal_graph_pattern* gp;
+
+  if(!query)
+    return NULL;
+  
+  gp=(rasqal_graph_pattern*)RASQAL_CALLOC(rasqal_graph_pattern, 1, sizeof(rasqal_graph_pattern));
+  if(!gp)
+    return NULL;
+
+  gp->op = op;
+  
+  gp->query=query;
+  gp->triples= NULL;
+  gp->start_column= -1;
+  gp->end_column= -1;
+  /* This is initialised by rasqal_query_prepare_count_graph_patterns() inside
+   * rasqal_query_prepare()
+   */
+  gp->gp_index= -1;
+
+  return gp;
+}
+
+
+/*
+ * rasqal_new_basic_graph_pattern:
+ * @query: #rasqal_graph_pattern query object
+ * @triples: triples sequence containing the graph pattern
+ * @start_column: first triple in the pattern
+ * @end_column: last triple in the pattern
+ *
+ * INTERNAL - Create a new graph pattern object over triples.
+ * 
+ * Return value: a new #rasqal_graph_pattern object or NULL on failure
+ **/
+rasqal_graph_pattern*
+rasqal_new_basic_graph_pattern(rasqal_query* query,
+                               raptor_sequence *triples,
+                               int start_column, int end_column)
+{
+  rasqal_graph_pattern* gp;
+
+  if(!triples)
+    return NULL;
+  
+  gp=rasqal_new_graph_pattern(query, RASQAL_GRAPH_PATTERN_OPERATOR_BASIC);
+  if(!gp)
+    return NULL;
+
+  gp->triples=triples;
+  gp->start_column=start_column;
+  gp->end_column=end_column;
+
+  return gp;
+}
+
+
+/*
+ * rasqal_new_graph_pattern_from_sequence:
+ * @query: #rasqal_graph_pattern query object
+ * @graph_patterns: sequence containing the graph patterns
+ * @operator: enum #rasqal_graph_pattern_operator such as
+ * RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL
+ *
+ * INTERNAL - Create a new graph pattern from a sequence of graph_patterns.
+ * 
+ * Return value: a new #rasqal_graph_pattern object or NULL on failure
+ **/
+rasqal_graph_pattern*
+rasqal_new_graph_pattern_from_sequence(rasqal_query* query,
+                                       raptor_sequence *graph_patterns, 
+                                       rasqal_graph_pattern_operator op)
+{
+  rasqal_graph_pattern* gp;
+
+  gp=rasqal_new_graph_pattern(query, op);
+  if(!gp) {
+  	if(graph_patterns)
+      raptor_free_sequence(graph_patterns);
+    return NULL;
+  }
+  
+  gp->graph_patterns=graph_patterns;
+  return gp;
+}
+
+
+/*
+ * rasqal_new_filter_graph_pattern:
+ * @query: #rasqal_graph_pattern query object
+ * @expr: expression
+ *
+ * INTERNAL - Create a new graph pattern from a sequence of graph_patterns.
+ * 
+ * Return value: a new #rasqal_graph_pattern object or NULL on failure
+ **/
+rasqal_graph_pattern*
+rasqal_new_filter_graph_pattern(rasqal_query* query,
+                                rasqal_expression* expr)
+{
+  rasqal_graph_pattern* gp;
+
+  gp=rasqal_new_graph_pattern(query, RASQAL_GRAPH_PATTERN_OPERATOR_FILTER);
+  if(!gp) {
+    rasqal_free_expression(expr);
+    return NULL;
+  }
+  
+  if(rasqal_graph_pattern_set_filter_expression(gp, expr)) {
+    rasqal_free_graph_pattern(gp);
+    gp=NULL;
+  }
+
+  return gp;
+}
+
+
+/*
+ * rasqal_free_graph_pattern:
+ * @gp: #rasqal_graph_pattern object
+ *
+ * INTERNAL - Free a graph pattern object.
+ * 
+ **/
+void
+rasqal_free_graph_pattern(rasqal_graph_pattern* gp)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(gp, rasqal_graph_pattern);
+  
+  if(gp->graph_patterns)
+    raptor_free_sequence(gp->graph_patterns);
+  
+  if(gp->filter_expression)
+    rasqal_free_expression(gp->filter_expression);
+
+  if(gp->constraints)
+    raptor_free_sequence(gp->constraints);
+
+  if(gp->origin)
+    rasqal_free_literal(gp->origin);
+
+  RASQAL_FREE(rasqal_graph_pattern, gp);
+}
+
+
+/*
+ * rasqal_graph_pattern_adjust:
+ * @gp: #rasqal_graph_pattern graph pattern
+ * @offset: adjustment
+ *
+ * INTERNAL - Adjust the column in a graph pattern by the offset.
+ * 
+ **/
+void
+rasqal_graph_pattern_adjust(rasqal_graph_pattern* gp, int offset)
+{
+  gp->start_column += offset;
+  gp->end_column += offset;
+}
+
+
+/**
+ * rasqal_graph_pattern_set_filter_expression:
+ * @gp: #rasqal_graph_pattern query object
+ * @expr: #rasqal_expression expr - ownership taken
+ *
+ * Set a filter graph pattern constraint expression
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_graph_pattern_set_filter_expression(rasqal_graph_pattern* gp,
+                                           rasqal_expression* expr)
+{
+  if(gp->filter_expression)
+    rasqal_free_expression(gp->filter_expression);
+  gp->filter_expression = expr;
+  return 0;
+}
+
+
+/**
+ * rasqal_graph_pattern_get_filter_expression:
+ * @gp: #rasqal_graph_pattern query object
+ *
+ * Get a filter graph pattern's constraint expression
+ *
+ * Return value: expression or NULL on failure
+ **/
+rasqal_expression*
+rasqal_graph_pattern_get_filter_expression(rasqal_graph_pattern* gp)
+{
+  return gp->filter_expression;
+}
+
+
+/**
+ * rasqal_graph_pattern_add_constraint:
+ * @gp: #rasqal_graph_pattern query object
+ * @expr: #rasqal_expression expr - ownership taken
+ *
+ * Add a constraint expression to the graph_pattern.
+ *
+ * @deprecated: Use rasqal_graph_pattern_set_filter_expression()
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_graph_pattern_add_constraint(rasqal_graph_pattern* gp,
+                                    rasqal_expression* expr)
+{
+  if(!gp->constraints) {
+    gp->constraints=raptor_new_sequence(NULL, 
+                                        (raptor_sequence_print_handler*)rasqal_expression_print);
+    if(!gp->constraints) {
+      rasqal_free_expression(expr);
+      return 1;
+    }
+  }
+  raptor_sequence_set_at(gp->constraints, 0, expr);
+
+  return rasqal_graph_pattern_set_filter_expression(gp, expr);
+}
+
+
+/**
+ * rasqal_graph_pattern_get_constraint_sequence:
+ * @gp: #rasqal_graph_pattern object
+ *
+ * Get the sequence of constraints expressions in the query.
+ *
+ * @deprecated: always returns a sequence with one expression.
+ * Use rasqal_graph_pattern_get_filter_expression() to return it.
+ *
+ * Return value: NULL
+ **/
+raptor_sequence*
+rasqal_graph_pattern_get_constraint_sequence(rasqal_graph_pattern* gp)
+{
+  return gp->constraints;
+}
+
+
+/**
+ * rasqal_graph_pattern_get_constraint:
+ * @gp: #rasqal_graph_pattern query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a constraint in the sequence of constraint expressions in the query.
+ *
+ * @deprecated: A FILTER graph pattern always has one expression
+ * that can be returned with rasqal_graph_pattern_get_filter_expression()
+ *
+ * Return value: a #rasqal_expression pointer or NULL if out of the sequence range
+ **/
+rasqal_expression*
+rasqal_graph_pattern_get_constraint(rasqal_graph_pattern* gp, int idx)
+{
+  return rasqal_graph_pattern_get_filter_expression(gp);
+}
+
+
+/**
+ * rasqal_graph_pattern_get_operator:
+ * @graph_pattern: #rasqal_graph_pattern graph pattern object
+ *
+ * Get the graph pattern operator .
+ * 
+ * The operator for the given graph pattern. See also
+ * rasqal_graph_pattern_operator_as_string().
+ *
+ * Return value: graph pattern operator
+ **/
+rasqal_graph_pattern_operator
+rasqal_graph_pattern_get_operator(rasqal_graph_pattern* graph_pattern)
+{
+  return graph_pattern->op;
+}
+
+
+static const char* const rasqal_graph_pattern_operator_labels[RASQAL_GRAPH_PATTERN_OPERATOR_LAST+1]={
+  "UNKNOWN",
+  "Basic",
+  "Optional",
+  "Union",
+  "Group",
+  "Graph",
+  "Filter"
+};
+
+
+/**
+ * rasqal_graph_pattern_operator_as_string:
+ * @op: the #rasqal_graph_pattern_operator verb of the query
+ *
+ * Get a string for the query verb.
+ * 
+ * Return value: pointer to a shared string label for the query verb
+ **/
+const char*
+rasqal_graph_pattern_operator_as_string(rasqal_graph_pattern_operator op)
+{
+  if(op <= RASQAL_GRAPH_PATTERN_OPERATOR_UNKNOWN || 
+     op > RASQAL_GRAPH_PATTERN_OPERATOR_LAST)
+    op=RASQAL_GRAPH_PATTERN_OPERATOR_UNKNOWN;
+
+  return rasqal_graph_pattern_operator_labels[(int)op];
+}
+  
+
+#ifdef RASQAL_DEBUG
+#define DO_INDENTING 0
+#else
+#define DO_INDENTING -1
+#endif
+
+#define SPACES_LENGTH 80
+static const char spaces[SPACES_LENGTH+1]="                                                                                ";
+
+static void
+rasqal_graph_pattern_write_indent(raptor_iostream *iostr, int indent) 
+{
+  while(indent > 0) {
+    int sp=(indent > SPACES_LENGTH) ? SPACES_LENGTH : indent;
+    raptor_iostream_write_bytes(iostr, spaces, sizeof(char), sp);
+    indent -= sp;
+  }
+}
+
+
+static void
+rasqal_graph_pattern_write_plurals(raptor_iostream *iostr,
+                                   const char* label, int value)
+{
+  raptor_iostream_write_decimal(iostr, value);
+  raptor_iostream_write_byte(iostr, ' ');
+  raptor_iostream_write_string(iostr, label);
+  if(value != 1)
+    raptor_iostream_write_byte(iostr, 's');
+}
+
+
+/**
+ * rasqal_graph_pattern_print_indent:
+ * @gp: the #rasqal_graph_pattern object
+ * @iostr: the iostream to write to
+ * @indent: the current indent level, <0 for no indenting
+ *
+ * INTERNAL - Print a #rasqal_graph_pattern in a debug format with indenting
+ * 
+ **/
+static int
+rasqal_graph_pattern_write_internal(rasqal_graph_pattern* gp,
+                                    raptor_iostream* iostr, int indent)
+{
+  int pending_nl=0;
+  
+  raptor_iostream_write_counted_string(iostr, "graph pattern", 13);
+  if(gp->gp_index >= 0) {
+    raptor_iostream_write_byte(iostr, '[');
+    raptor_iostream_write_decimal(iostr, gp->gp_index);
+    raptor_iostream_write_byte(iostr, ']');
+  }
+  raptor_iostream_write_byte(iostr, ' ');
+  raptor_iostream_write_string(iostr, 
+                               rasqal_graph_pattern_operator_as_string(gp->op));
+  raptor_iostream_write_byte(iostr, '(');
+
+  if(indent >= 0)
+    indent+= 2;
+
+  if(gp->triples) {
+    int size=gp->end_column - gp->start_column +1;
+    int i;
+    raptor_iostream_write_counted_string(iostr, "over ", 5);
+    rasqal_graph_pattern_write_plurals(iostr, "triple", size);
+    raptor_iostream_write_byte(iostr, '[');
+
+    if(indent >= 0) {
+      raptor_iostream_write_byte(iostr, '\n');
+      indent+= 2;
+      rasqal_graph_pattern_write_indent(iostr, indent);
+    }
+    
+    for(i=gp->start_column; i <= gp->end_column; i++) {
+      rasqal_triple *t=(rasqal_triple*)raptor_sequence_get_at(gp->triples, i);
+      if(i > gp->start_column) {
+        raptor_iostream_write_counted_string(iostr, " ,", 2);
+
+        if(indent >= 0) {
+          raptor_iostream_write_byte(iostr, '\n');
+          rasqal_graph_pattern_write_indent(iostr, indent);
+        }
+      }
+      rasqal_triple_write(t, iostr);
+    }
+    if(indent >= 0) {
+      raptor_iostream_write_byte(iostr, '\n');
+      indent-= 2;
+      rasqal_graph_pattern_write_indent(iostr, indent);
+    }
+    raptor_iostream_write_byte(iostr, ']');
+
+    pending_nl=1;
+  }
+
+  if(gp->origin) {
+    if(pending_nl) {
+      raptor_iostream_write_counted_string(iostr, " ,", 2);
+
+      if(indent >= 0) {
+        raptor_iostream_write_byte(iostr, '\n');
+        rasqal_graph_pattern_write_indent(iostr, indent);
+      }
+    }
+
+    raptor_iostream_write_counted_string(iostr, "origin ", 7);
+
+    rasqal_literal_write(gp->origin, iostr);
+
+    pending_nl=1;
+  }
+
+  if(gp->graph_patterns) {
+    int size=raptor_sequence_size(gp->graph_patterns);
+    int i;
+
+    if(pending_nl) {
+      raptor_iostream_write_counted_string(iostr, " ,", 2);
+      if(indent >= 0) {
+        raptor_iostream_write_byte(iostr, '\n');
+        rasqal_graph_pattern_write_indent(iostr, indent);
+      }
+    }
+    
+    raptor_iostream_write_counted_string(iostr, "over ", 5);
+    rasqal_graph_pattern_write_plurals(iostr, "graph pattern", size);
+    raptor_iostream_write_byte(iostr, '[');
+
+    if(indent >= 0) {
+      raptor_iostream_write_byte(iostr, '\n');
+      indent+= 2;
+      rasqal_graph_pattern_write_indent(iostr, indent);
+    }
+    
+    for(i=0; i< size; i++) {
+      rasqal_graph_pattern* sgp;
+      sgp=(rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+      if(i) {
+        raptor_iostream_write_counted_string(iostr, " ,", 2);
+        if(indent >= 0) {
+          raptor_iostream_write_byte(iostr, '\n');
+          rasqal_graph_pattern_write_indent(iostr, indent);
+        }
+      }
+      if(sgp)
+        rasqal_graph_pattern_write_internal(sgp, iostr, indent);
+      else
+        raptor_iostream_write_counted_string(iostr, "(empty)", 7);
+    }
+    if(indent >= 0) {
+      raptor_iostream_write_byte(iostr, '\n');
+      indent-= 2;
+      rasqal_graph_pattern_write_indent(iostr, indent);
+    }
+    raptor_iostream_write_byte(iostr, ']');
+
+    pending_nl=1;
+  }
+
+  if(gp->filter_expression) {
+    if(pending_nl) {
+      raptor_iostream_write_counted_string(iostr, " ,", 2);
+
+      if(indent >= 0) {
+        raptor_iostream_write_byte(iostr, '\n');
+        rasqal_graph_pattern_write_indent(iostr, indent);
+      }
+    }
+    
+    if(gp->triples || gp->graph_patterns)
+      raptor_iostream_write_counted_string(iostr, "with ", 5);
+  
+    if(indent >= 0) {
+      raptor_iostream_write_byte(iostr, '\n');
+      indent+= 2;
+      rasqal_graph_pattern_write_indent(iostr, indent);
+    }
+
+    rasqal_expression_write(gp->filter_expression, iostr);
+    if(indent >= 0)
+      indent-= 2;
+    
+    pending_nl=1;
+  }
+
+  if(indent >= 0)
+    indent-= 2;
+
+  if(pending_nl) {
+    if(indent >= 0) {
+      raptor_iostream_write_byte(iostr, '\n');
+      rasqal_graph_pattern_write_indent(iostr, indent);
+    }
+  }
+  
+  raptor_iostream_write_byte(iostr, ')');
+
+  return 0;
+}
+
+
+/**
+ * rasqal_graph_pattern_print:
+ * @gp: the #rasqal_graph_pattern object
+ * @fh: the #FILE* handle to print to
+ *
+ * Print a #rasqal_graph_pattern in a debug format.
+ * 
+ * The print debug format may change in any release.
+ * 
+ **/
+void
+rasqal_graph_pattern_print(rasqal_graph_pattern* gp, FILE* fh)
+{
+  raptor_iostream* iostr;
+  iostr=raptor_new_iostream_to_file_handle(fh);
+  rasqal_graph_pattern_write_internal(gp, iostr, DO_INDENTING);
+  raptor_free_iostream(iostr);
+}
+
+
+/**
+ * rasqal_graph_pattern_visit:
+ * @query: #rasqal_query to operate on
+ * @gp: #rasqal_graph_pattern graph pattern
+ * @fn: pointer to function to apply that takes user data and graph pattern parameters
+ * @user_data: user data for applied function 
+ * 
+ * Visit a user function over a #rasqal_graph_pattern
+ *
+ * If the user function @fn returns 0, the visit is truncated.
+ *
+ * Return value: 0 if the visit was truncated.
+ **/
+int
+rasqal_graph_pattern_visit(rasqal_query *query,
+                           rasqal_graph_pattern* gp,
+                           rasqal_graph_pattern_visit_fn fn,
+                           void *user_data)
+{
+  raptor_sequence *seq;
+  int result;
+  
+  result=fn(query, gp, user_data);
+  if(result)
+    return result;
+  
+  seq=rasqal_graph_pattern_get_sub_graph_pattern_sequence(gp);
+  if(seq && raptor_sequence_size(seq) > 0) {
+    int gp_index=0;
+    while(1) {
+      rasqal_graph_pattern* sgp;
+      sgp=rasqal_graph_pattern_get_sub_graph_pattern(gp, gp_index);
+      if(!sgp)
+        break;
+      
+      result=rasqal_graph_pattern_visit(query, sgp, fn, user_data);
+      if(result)
+        return result;
+      gp_index++;
+    }
+  }
+
+  return 0;
+}
+
+
+/**
+ * rasqal_graph_pattern_get_index:
+ * @gp: #rasqal_graph_pattern graph pattern
+ * 
+ * Get the graph pattern absolute index in the array of graph patterns.
+ * 
+ * The graph pattern index is assigned when rasqal_query_prepare() is
+ * run on a query containing a graph pattern.
+ *
+ * Return value: index or <0 if no index has been assigned yet
+ **/
+int
+rasqal_graph_pattern_get_index(rasqal_graph_pattern* gp)
+{
+  return gp->gp_index;
+}
+
+
+/**
+ * rasqal_graph_pattern_add_sub_graph_pattern:
+ * @graph_pattern: graph pattern to add to
+ * @sub_graph_pattern: graph pattern to add inside
+ *
+ * Add a sub graph pattern to a graph pattern.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_graph_pattern_add_sub_graph_pattern(rasqal_graph_pattern* graph_pattern,
+                                           rasqal_graph_pattern* sub_graph_pattern)
+{
+  if(!graph_pattern->graph_patterns) {
+    graph_pattern->graph_patterns=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print);
+    if(!graph_pattern->graph_patterns) {
+      if(sub_graph_pattern)
+        rasqal_free_graph_pattern(sub_graph_pattern);
+      return 1;
+    }
+  }
+  return raptor_sequence_push(graph_pattern->graph_patterns, sub_graph_pattern);
+}
+
+
+/**
+ * rasqal_graph_pattern_get_triple:
+ * @graph_pattern: #rasqal_graph_pattern graph pattern object
+ * @idx: index into the sequence of triples in the graph pattern
+ *
+ * Get a triple inside a graph pattern.
+ * 
+ * Return value: #rasqal_triple or NULL if out of range
+ **/
+rasqal_triple*
+rasqal_graph_pattern_get_triple(rasqal_graph_pattern* graph_pattern, int idx)
+{
+  if(!graph_pattern->triples)
+    return NULL;
+
+  idx += graph_pattern->start_column;
+
+  if(idx > graph_pattern->end_column)
+    return NULL;
+  
+  return (rasqal_triple*)raptor_sequence_get_at(graph_pattern->triples, idx);
+}
+
+
+/**
+ * rasqal_graph_pattern_get_sub_graph_pattern_sequence:
+ * @graph_pattern: #rasqal_graph_pattern graph pattern object
+ *
+ * Get the sequence of graph patterns inside a graph pattern .
+ * 
+ * Return value:  a #raptor_sequence of #rasqal_graph_pattern pointers.
+ **/
+raptor_sequence*
+rasqal_graph_pattern_get_sub_graph_pattern_sequence(rasqal_graph_pattern* graph_pattern)
+{
+  return graph_pattern->graph_patterns;
+}
+
+
+/**
+ * rasqal_graph_pattern_get_sub_graph_pattern:
+ * @graph_pattern: #rasqal_graph_pattern graph pattern object
+ * @idx: index into the sequence of sub graph_patterns in the graph pattern
+ *
+ * Get a sub-graph pattern inside a graph pattern.
+ * 
+ * Return value: #rasqal_graph_pattern or NULL if out of range
+ **/
+rasqal_graph_pattern*
+rasqal_graph_pattern_get_sub_graph_pattern(rasqal_graph_pattern* graph_pattern, int idx)
+{
+  if(!graph_pattern->graph_patterns)
+    return NULL;
+
+  return (rasqal_graph_pattern*)raptor_sequence_get_at(graph_pattern->graph_patterns, idx);
+}
+
+
+/*
+ * rasqal_graph_pattern_set_origin:
+ * @graph_pattern: #rasqal_graph_pattern graph pattern object
+ * @origin: #rasqal_literal variable or URI
+ *
+ * INTERNAL - Set the graph pattern triple origin.
+ * 
+ * All triples in this graph pattern or contained graph patterns are set
+ * to have the given origin.
+ **/
+void
+rasqal_graph_pattern_set_origin(rasqal_graph_pattern* graph_pattern,
+                                rasqal_literal *origin)
+{
+  raptor_sequence* s;
+  
+  s=graph_pattern->triples;
+  if(s) {
+    int i;
+
+    /* Flag all the triples in this graph pattern with origin */
+    for(i= graph_pattern->start_column; i <= graph_pattern->end_column; i++) {
+      rasqal_triple *t=(rasqal_triple*)raptor_sequence_get_at(s, i);
+      rasqal_triple_set_origin(t, rasqal_new_literal_from_literal(origin));
+    }
+  }
+
+  s=graph_pattern->graph_patterns;
+  if(s) {
+    int i;
+
+    /* Flag all the triples in sub-graph patterns with origin */
+    for(i=0; i < raptor_sequence_size(s); i++) {
+      rasqal_graph_pattern *gp=(rasqal_graph_pattern*)raptor_sequence_get_at(s, i);
+      rasqal_graph_pattern_set_origin(gp, origin);
+    }
+  }
+
+}
+
+
+/**
+ * rasqal_new_basic_graph_pattern_from_formula:
+ * @query: #rasqal_graph_pattern query object
+ * @formula: triples sequence containing the graph pattern
+ * @op: enum #rasqal_graph_pattern_operator operator
+ *
+ * INTERNAL - Create a new graph pattern object over a formula. This function
+ * frees the formula passed in.
+ * 
+ * Return value: a new #rasqal_graph_pattern object or NULL on failure
+ **/
+rasqal_graph_pattern*
+rasqal_new_basic_graph_pattern_from_formula(rasqal_query* query,
+                                            rasqal_formula* formula)
+{
+  rasqal_graph_pattern* gp;
+  raptor_sequence *triples=query->triples;
+  raptor_sequence *formula_triples=formula->triples;
+  int offset=raptor_sequence_size(triples);
+  int triple_pattern_size=0;
+
+  if(formula_triples) {
+    /* Move formula triples to end of main triples sequence */
+    triple_pattern_size=raptor_sequence_size(formula_triples);
+    if(raptor_sequence_join(triples, formula_triples)) {
+      rasqal_free_formula(formula);
+      return NULL;
+    }
+  }
+
+  rasqal_free_formula(formula);
+
+  gp=rasqal_new_basic_graph_pattern(query, triples, 
+                                    offset, 
+                                    offset+triple_pattern_size-1);
+  return gp;
+}
+
+
+/**
+ * rasqal_new_2_group_graph_pattern:
+ * @query: query object
+ * @first_gp: first graph pattern
+ * @second_gp: second graph pattern
+ *
+ * INTERNAL - Make a new group graph pattern from two graph patterns
+ * of which either or both may be NULL, in which case a group
+ * of 0 graph patterns is created.
+ *
+ * @first_gp and @second_gp if given, become owned by the new graph
+ * pattern.
+ *
+ * Return value: new group graph pattern or NULL on failure
+ */
+rasqal_graph_pattern*
+rasqal_new_2_group_graph_pattern(rasqal_query* query,
+                                 rasqal_graph_pattern* first_gp,
+                                 rasqal_graph_pattern* second_gp)
+{
+  raptor_sequence *seq;
+
+  seq=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print);
+  if(!seq) {
+    if(first_gp)
+      rasqal_free_graph_pattern(first_gp);
+    if(second_gp)
+      rasqal_free_graph_pattern(second_gp);
+    return NULL;
+  }
+
+  if(first_gp && raptor_sequence_push(seq, first_gp)) {
+    raptor_free_sequence(seq);
+    if(second_gp)
+      rasqal_free_graph_pattern(second_gp);
+    return NULL;
+  }
+  if(second_gp && raptor_sequence_push(seq, second_gp)) {
+    raptor_free_sequence(seq);
+    return NULL;
+  }
+
+  return rasqal_new_graph_pattern_from_sequence(query, seq,
+                                                RASQAL_GRAPH_PATTERN_OPERATOR_GROUP);
+}
diff --git a/src/rasqal/rasqal_internal.h b/src/rasqal/rasqal_internal.h
new file mode 100644
index 0000000..f0e7a14
--- /dev/null
+++ b/src/rasqal/rasqal_internal.h
@@ -0,0 +1,1200 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_internal.h - Rasqal RDF Query library internals
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+
+#ifndef RASQAL_INTERNAL_H
+#define RASQAL_INTERNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#define RASQAL_EXTERN_C extern "C"
+#else
+#define RASQAL_EXTERN_C
+#endif
+
+#ifdef RASQAL_INTERNAL
+
+/* for the memory allocation functions */
+#if defined(HAVE_DMALLOC_H) && defined(RASQAL_MEMORY_DEBUG_DMALLOC)
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#undef HAVE_STDLIB_H
+#endif
+#include <dmalloc.h>
+#endif
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#define RASQAL_PRINTF_FORMAT(string_index, first_to_check_index) \
+  __attribute__((__format__(__printf__, string_index, first_to_check_index)))
+#else
+#define RASQAL_PRINTF_FORMAT(string_index, first_to_check_index)
+#endif
+
+/* Can be over-ridden or undefined in a config.h file or -Ddefine */
+#ifndef RASQAL_INLINE
+#define RASQAL_INLINE inline
+#endif
+
+#ifdef LIBRDF_DEBUG
+#define RASQAL_DEBUG 1
+#endif
+
+#if defined(RASQAL_MEMORY_SIGN)
+#define RASQAL_SIGN_KEY 0x08A59A10
+void* rasqal_sign_malloc(size_t size);
+void* rasqal_sign_calloc(size_t nmemb, size_t size);
+void* rasqal_sign_realloc(void *ptr, size_t size);
+void rasqal_sign_free(void *ptr);
+  
+#define RASQAL_MALLOC(type, size)   rasqal_sign_malloc(size)
+#define RASQAL_CALLOC(type, nmemb, size) rasqal_sign_calloc(nmemb, size)
+#define RASQAL_REALLOC(type, ptr, size) rasqal_sign_realloc(ptr, size)
+#define RASQAL_FREE(type, ptr)   rasqal_sign_free(ptr)
+
+#else
+#define RASQAL_MALLOC(type, size) malloc(size)
+#define RASQAL_CALLOC(type, size, count) calloc(size, count)
+#define RASQAL_FREE(type, ptr)   free((void*)ptr)
+
+#endif
+
+#ifdef RASQAL_DEBUG
+/* Debugging messages */
+#define RASQAL_DEBUG1(msg) do {fprintf(stderr, "%s:%d:%s: " msg, __FILE__, __LINE__, __func__); } while(0)
+#define RASQAL_DEBUG2(msg, arg1) do {fprintf(stderr, "%s:%d:%s: " msg, __FILE__, __LINE__, __func__, arg1);} while(0)
+#define RASQAL_DEBUG3(msg, arg1, arg2) do {fprintf(stderr, "%s:%d:%s: " msg, __FILE__, __LINE__, __func__, arg1, arg2);} while(0)
+#define RASQAL_DEBUG4(msg, arg1, arg2, arg3) do {fprintf(stderr, "%s:%d:%s: " msg, __FILE__, __LINE__, __func__, arg1, arg2, arg3);} while(0)
+#define RASQAL_DEBUG5(msg, arg1, arg2, arg3, arg4) do {fprintf(stderr, "%s:%d:%s: " msg, __FILE__, __LINE__, __func__, arg1, arg2, arg3, arg4);} while(0)
+#define RASQAL_DEBUG6(msg, arg1, arg2, arg3, arg4, arg5) do {fprintf(stderr, "%s:%d:%s: " msg, __FILE__, __LINE__, __func__, arg1, arg2, arg3, arg4, arg5);} while(0)
+
+#if defined(HAVE_DMALLOC_H) && defined(RASQAL_MEMORY_DEBUG_DMALLOC)
+void* rasqal_system_malloc(size_t size);
+void rasqal_system_free(void *ptr);
+#define SYSTEM_MALLOC(size)   rasqal_system_malloc(size)
+#define SYSTEM_FREE(ptr)   rasqal_system_free(ptr)
+#else
+#define SYSTEM_MALLOC(size)   malloc(size)
+#define SYSTEM_FREE(ptr)   free(ptr)
+#endif
+
+#ifndef RASQAL_ASSERT_DIE
+#define RASQAL_ASSERT_DIE abort();
+#endif
+
+#else
+/* DEBUGGING TURNED OFF */
+
+/* No debugging messages */
+#define RASQAL_DEBUG1(msg)
+#define RASQAL_DEBUG2(msg, arg1)
+#define RASQAL_DEBUG3(msg, arg1, arg2)
+#define RASQAL_DEBUG4(msg, arg1, arg2, arg3)
+#define RASQAL_DEBUG5(msg, arg1, arg2, arg3, arg4)
+#define RASQAL_DEBUG6(msg, arg1, arg2, arg3, arg4, arg5)
+
+#define SYSTEM_MALLOC(size)   malloc(size)
+#define SYSTEM_FREE(ptr)   free(ptr)
+
+#ifndef RASQAL_ASSERT_DIE
+#define RASQAL_ASSERT_DIE
+#endif
+
+#endif
+
+
+#ifdef RASQAL_DISABLE_ASSERT_MESSAGES
+#define RASQAL_ASSERT_REPORT(line)
+#else
+#define RASQAL_ASSERT_REPORT(msg) fprintf(stderr, "%s:%d: (%s) assertion failed: " msg "\n", __FILE__, __LINE__, __func__);
+#endif
+
+
+#ifdef RASQAL_DISABLE_ASSERT
+
+#define RASQAL_ASSERT(condition, msg) 
+#define RASQAL_ASSERT_RETURN(condition, msg, ret) 
+#define RASQAL_ASSERT_OBJECT_POINTER_RETURN(pointer, type) do { \
+  if(!pointer) \
+    return; \
+} while(0)
+#define RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(pointer, type, ret)
+
+#else
+
+#define RASQAL_ASSERT(condition, msg) do { \
+  if(condition) { \
+    RASQAL_ASSERT_REPORT(msg) \
+    RASQAL_ASSERT_DIE \
+  } \
+} while(0)
+
+#define RASQAL_ASSERT_RETURN(condition, msg, ret) do { \
+  if(condition) { \
+    RASQAL_ASSERT_REPORT(msg) \
+    RASQAL_ASSERT_DIE \
+    return ret; \
+  } \
+} while(0)
+
+#define RASQAL_ASSERT_OBJECT_POINTER_RETURN(pointer, type) do { \
+  if(!pointer) { \
+    RASQAL_ASSERT_REPORT("object pointer of type " #type " is NULL.") \
+    RASQAL_ASSERT_DIE \
+    return; \
+  } \
+} while(0)
+
+#define RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(pointer, type, ret) do { \
+  if(!pointer) { \
+    RASQAL_ASSERT_REPORT("object pointer of type " #type " is NULL.") \
+    RASQAL_ASSERT_DIE \
+    return ret; \
+  } \
+} while(0)
+
+#endif
+
+
+/* Fatal errors - always happen */
+#define RASQAL_FATAL1(msg) do {fprintf(stderr, "%s:%d:%s: fatal error: " msg, __FILE__, __LINE__ , __func__); abort();} while(0)
+#define RASQAL_FATAL2(msg,arg) do {fprintf(stderr, "%s:%d:%s: fatal error: " msg, __FILE__, __LINE__ , __func__, arg); abort();} while(0)
+#define RASQAL_FATAL3(msg,arg1,arg2) do {fprintf(stderr, "%s:%d:%s: fatal error: " msg, __FILE__, __LINE__ , __func__, arg1, arg2); abort();} while(0)
+
+#ifndef NO_STATIC_DATA
+#define RASQAL_DEPRECATED_MESSAGE(msg) do {static int warning_given=0; if(!warning_given++) fprintf(stderr, "Function %s is deprecated - " msg,  __func__); } while(0)
+#define RASQAL_DEPRECATED_WARNING(rq, msg) do {static int warning_given=0; if(!warning_given++) rasqal_query_warning(rq, msg); } while(0)
+#else
+#define RASQAL_DEPRECATED_MESSAGE(msg) do { fprintf(stderr, "Function %s is deprecated - " msg,  __func__); } while(0)
+#define RASQAL_DEPRECATED_WARNING(rq, msg) do { rasqal_query_warning(rq, msg); } while(0)
+#endif
+
+
+typedef struct rasqal_query_execution_factory_s rasqal_query_execution_factory;
+typedef struct rasqal_query_language_factory_s rasqal_query_language_factory;
+typedef struct rasqal_variables_table_s rasqal_variables_table;
+
+
+/*
+ * Graph Pattern
+ */
+struct rasqal_graph_pattern_s {
+  rasqal_query* query;
+
+  /* operator for this graph pattern's contents */
+  rasqal_graph_pattern_operator op;
+  
+  raptor_sequence* triples;          /* ... rasqal_triple*         */
+  raptor_sequence* graph_patterns;   /* ... rasqal_graph_pattern*  */
+
+  int start_column;
+  int end_column;
+
+  /* used to support DEPRECATED functions
+   * rasqal_graph_pattern_get_constraint_sequence() and
+   * rasqal_graph_pattern_get_constraint()  */
+  raptor_sequence *constraints; /* ... rasqal_expression*          */
+
+  /* the FILTER graph pattern expression */
+  rasqal_expression* filter_expression;
+
+  /* index of the graph pattern in the query (0.. query->graph_pattern_count-1) */
+  int gp_index;
+
+  /* Graph literal */
+  rasqal_literal *origin;
+};
+
+rasqal_graph_pattern* rasqal_new_basic_graph_pattern(rasqal_query* query, raptor_sequence* triples, int start_column, int end_column);
+rasqal_graph_pattern* rasqal_new_graph_pattern_from_sequence(rasqal_query* query, raptor_sequence* graph_patterns, rasqal_graph_pattern_operator op);
+rasqal_graph_pattern* rasqal_new_filter_graph_pattern(rasqal_query* query, rasqal_expression* expr);
+void rasqal_free_graph_pattern(rasqal_graph_pattern* gp);
+void rasqal_graph_pattern_adjust(rasqal_graph_pattern* gp, int offset);
+void rasqal_graph_pattern_set_origin(rasqal_graph_pattern* graph_pattern, rasqal_literal* origin);
+
+
+/*
+ * A query in some query language
+ */
+struct rasqal_query_s {
+  rasqal_world* world; /* world object */
+
+  int usage; /* reference count - 1 for itself, plus for query_results */
+  
+  unsigned char* query_string;
+  int query_string_length; /* length including NULs */
+
+  raptor_namespace_stack* namespaces;
+
+  /* query graph pattern, containing the sequence of graph_patterns below */
+  rasqal_graph_pattern* query_graph_pattern;
+  
+  /* the query verb - in SPARQL terms: SELECT, CONSTRUCT, DESCRIBE or ASK */
+  rasqal_query_verb verb;
+  
+  /* sequences of ... */
+  raptor_sequence* selects;     /* ... rasqal_variable* names only */
+  raptor_sequence* data_graphs; /* ... rasqal_data_graph*          */
+  /* NOTE: Cannot assume that triples are in any of 
+   * graph pattern use / query execution / document order 
+   */
+  raptor_sequence* triples;     /* ... rasqal_triple*              */
+  raptor_sequence* prefixes;    /* ... rasqal_prefix*              */
+  raptor_sequence* constructs;  /* ... rasqal_triple*       SPARQL */
+  raptor_sequence* optional_triples; /* ... rasqal_triple*  SPARQL */
+  raptor_sequence* describes;   /* ... rasqal_literal* (var or URIs) SPARQL */
+
+  /* DISTINCT mode:
+   * 0 if not given
+   * 1 if DISTINCT: ensure solutions are unique
+   * 2 if SPARQL REDUCED: permit elimination of some non-unique solutions 
+   * otherwise undefined
+   */
+  int distinct;
+
+  /* result limit LIMIT (>=0) or <0 if not given */
+  int limit;
+
+  /* result offset OFFSET (>=0) or <0 if not given */
+  int offset;
+
+  /* non-0 if '*' was seen after a verb (the appropriate list such as selects or constructs will be NULL) */
+  int wildcard;
+
+  int prepared;
+
+  rasqal_variables_table* vars_table;
+
+  /* The number of selected variables: these are always the first
+   * in the variables table and are the ones returend to the user.
+   */
+  int select_variables_count;
+
+  /* array of size (number of total variables)
+   * pointing to triple column where a variable[offset] is declared
+   */
+  int* variables_declared_in;
+
+  /* can be filled with error location information */
+  raptor_locator locator;
+
+  /* base URI of this query for resolving relative URIs in queries */
+  raptor_uri* base_uri;
+
+  /* non 0 if query had fatal error in parsing and cannot be executed */
+  int failed;
+
+  /* stuff for our user */
+  void* user_data;
+
+  int default_generate_bnodeid_handler_base;
+  char *default_generate_bnodeid_handler_prefix;
+  size_t default_generate_bnodeid_handler_prefix_length;
+
+  void *generate_bnodeid_handler_user_data;
+  rasqal_generate_bnodeid_handler generate_bnodeid_handler;
+
+
+  /* query engine specific stuff */
+  void* context;
+
+  struct rasqal_query_language_factory_s* factory;
+
+  rasqal_triples_source_factory* triples_source_factory;
+
+  /* sequence of query results made from this query */
+  raptor_sequence* results;
+
+  /* incrementing counter for declaring prefixes in order of appearance */
+  int prefix_depth;
+
+  /* sequence of order condition expressions */
+  raptor_sequence* order_conditions_sequence;
+
+  /* sequence of group by condition expressions */
+  raptor_sequence* group_conditions_sequence;
+
+  /* INTERNAL rasqal_literal_compare / rasqal_expression_evaluate flags */
+  int compare_flags;
+
+  /* Number of graph patterns in this query */
+  int graph_pattern_count;
+  
+  /* Graph pattern shared pointers by gp index (after prepare) */
+  raptor_sequence* graph_patterns_sequence;
+
+  /* Features */
+  int features[RASQAL_FEATURE_LAST+1];
+
+  /* Name of requested query results syntax.  If present, this
+   * is the name used for constructing a rasqal_query_formatter
+   * from the results.
+   */
+  const char* query_results_formatter_name;
+
+  /* EXPLAIN was given */
+  int explain;
+
+  /* generated counter - increments at every generation */
+  int genid_counter;
+
+  /* INTERNAL lexer internal data */
+  void* lexer_user_data;
+
+  /* INTERNAL for now: non-0 to store results otherwise lazy eval results */
+  int store_results;
+};
+
+
+/*
+ * A query language factory for a query language.
+ *
+ * This structure is about turning a query syntax string into a
+ * #rasqal_query structure.  It does not deal with execution of the
+ * query in any manner.
+ */
+struct rasqal_query_language_factory_s {
+  struct rasqal_query_language_factory_s* next;
+
+  /* query language name */
+  const char* name;
+
+  /* query language readable label */
+  const char* label;
+
+  /* query language alternate name */
+  const char* alias;
+
+  /* query language MIME type (or NULL) */
+  const char* mime_type;
+
+  /* query language URI (or NULL) */
+  const unsigned char* uri_string;
+  
+  /* the rest of this structure is populated by the
+     query-language-specific register function */
+  size_t context_length;
+  
+  /* create a new query */
+  int (*init)(rasqal_query* rq, const char *name);
+  
+  /* destroy a query */
+  void (*terminate)(rasqal_query* rq);
+  
+  /* prepare a query */
+  int (*prepare)(rasqal_query* rq);
+  
+  /* finish the query language factory */
+  void (*finish_factory)(rasqal_query_language_factory* factory);
+
+  /* Write a string to an iostream in escaped form suitable for the query */
+  int (*iostream_write_escaped_counted_string)(rasqal_query* rq, raptor_iostream* iostr, const unsigned char* string, size_t len);
+};
+
+
+typedef struct rasqal_rowsource_s rasqal_rowsource;
+
+/*
+ * A row of values from a query result, usually generated by a rowsource
+ */
+typedef struct {
+  /* reference count */
+  int usage;
+
+  /* Rowsource this row is associated with (or NULL if none) */
+  rasqal_rowsource* rowsource;
+
+  /* current row number in the sequence of rows*/
+  int offset;
+
+  /* values for each variable in the query sequence of values */
+  int size;
+  rasqal_literal** values;
+
+  /* literal values for ORDER BY expressions evaluated for this row */
+  /* number of expressions (can be 0) */
+  int order_size;
+  rasqal_literal** order_values;
+} rasqal_row;
+
+
+typedef struct rasqal_map_s rasqal_map;
+
+/**
+ * rasqal_query_results_type:
+ * @RASQAL_QUERY_RESULTS_BINDINGS: variable binding
+ * @RASQAL_QUERY_RESULTS_BOOLEAN: a single boolean
+ * @RASQAL_QUERY_RESULTS_GRAPH: an RDF graph
+ * @RASQAL_QUERY_RESULTS_SYNTAX: a syntax
+ *
+ * Query result type.
+ */
+
+typedef enum {
+  RASQAL_QUERY_RESULTS_BINDINGS,
+  RASQAL_QUERY_RESULTS_BOOLEAN,
+  RASQAL_QUERY_RESULTS_GRAPH,
+  RASQAL_QUERY_RESULTS_SYNTAX
+} rasqal_query_results_type;
+
+
+/* rasqal_rowsource_empty.c */
+rasqal_rowsource* rasqal_new_empty_rowsource(rasqal_world *world, rasqal_query* query);
+
+/* rasqal_rowsource_engine.c */
+rasqal_rowsource* rasqal_new_execution_rowsource(rasqal_query_results* query_results);
+
+/* rasqal_rowsource_filter.c */
+rasqal_rowsource* rasqal_new_filter_rowsource(rasqal_world *world, rasqal_query *query, rasqal_rowsource* rs, rasqal_expression* expr);
+
+/* rasqal_rowsource_join.c */
+rasqal_rowsource* rasqal_new_join_rowsource(rasqal_world *world, rasqal_query* query, rasqal_rowsource* left, rasqal_rowsource* right, int join_type, rasqal_expression *expr);
+
+/* rasqal_rowsource_project.c */
+rasqal_rowsource* rasqal_new_project_rowsource(rasqal_world *world, rasqal_query *query, rasqal_rowsource* rowsource, raptor_sequence* projection_variables);
+
+/* rasqal_rowsource_rowsequence.c */
+rasqal_rowsource* rasqal_new_rowsequence_rowsource(rasqal_world *world, rasqal_query* query, rasqal_variables_table* vt, raptor_sequence* row, raptor_sequence* vars_seq);
+
+/* rasqal_rowsource_sort.c */
+rasqal_rowsource* rasqal_new_sort_rowsource(rasqal_world *world, rasqal_query *query, rasqal_rowsource *rowsource, raptor_sequence *seq);
+
+/* rasqal_rowsource_triples.c */
+rasqal_rowsource* rasqal_new_triples_rowsource(rasqal_world *world, rasqal_query* query, rasqal_triples_source* triples_source, raptor_sequence* triples, int start_column, int end_column, int *declared_in);
+
+/* rasqal_rowsource_union.c */
+rasqal_rowsource* rasqal_new_union_rowsource(rasqal_world *world, rasqal_query* query, rasqal_rowsource* left, rasqal_rowsource* right);
+
+
+/**
+ * rasqal_rowsource_init_func:
+ * @context: stream context data
+ *
+ * Handler function for #rasqal_rowsource initialising.
+ *
+ * Return value: non-0 on failure.
+ */
+typedef int (*rasqal_rowsource_init_func) (rasqal_rowsource* rowsource, void *user_data);
+
+/**
+ * rasqal_rowsource_finish_func:
+ * @user_data: user data
+ *
+ * Handler function for #rasqal_rowsource terminating.
+ *
+ * Return value: non-0 on failure
+ */
+typedef int (*rasqal_rowsource_finish_func) (rasqal_rowsource* rowsource, void *user_data);
+
+/**
+ * rasqal_rowsource_ensure_variables_func
+ * @rowsource: #rasqal_rowsource
+ * @user_data: user data
+ *
+ * Handler function for ensuring rowsource variables fields are initialised
+ *
+ * Return value: non-0 on failure
+ */
+typedef int (*rasqal_rowsource_ensure_variables_func) (rasqal_rowsource* rowsource, void *user_data);
+
+/**
+ * rasqal_rowsource_read_row_func
+ * @user_data: user data
+ *
+ * Handler function for returning the next result row
+ *
+ * Return value: a query result row or NULL if exhausted
+ */
+typedef rasqal_row* (*rasqal_rowsource_read_row_func) (rasqal_rowsource* rowsource, void *user_data);
+
+
+/**
+ * rasqal_rowsource_read_all_rows_func
+ * @user_data: user data
+ *
+ * Handler function for returning all rows as a sequence
+ *
+ * Return value: a sequence of result rows (which may be size 0) or NULL if exhausted
+ */
+typedef raptor_sequence* (*rasqal_rowsource_read_all_rows_func) (rasqal_rowsource* rowsource, void *user_data);
+
+
+/**
+ * rasqal_rowsource_reset_func
+ * @user_data: user data
+ *
+ * Handler function for resetting a rowsource to generate the same set of rows
+ *
+ * Return value: non-0 on failure
+ */
+typedef int (*rasqal_rowsource_reset_func) (rasqal_rowsource* rowsource, void *user_data);
+
+
+/**
+ * rasqal_rowsource_set_preserve_func
+ * @user_data: user data
+ * @preserve: flag
+ *
+ * Handler function for setting preserve binding states on a rowsource
+ *
+ * Return value: non-0 on failure
+ */
+typedef int (*rasqal_rowsource_set_preserve_func) (rasqal_rowsource* rowsource, void *user_data, int preserve);
+
+
+/**
+ * rasqal_rowsource_get_inner_rowsource_func
+ * @user_data: user data
+ * @offset: offset
+ *
+ * Handler function for getting an inner rowsource at an offset
+ *
+ * Return value: rowsource object or NULL if offset out of range
+ */
+typedef rasqal_rowsource* (*rasqal_rowsource_get_inner_rowsource_func) (rasqal_rowsource* rowsource, void *user_data, int offset);
+
+
+/**
+ * rasqal_rowsource_handler:
+ * @version: API version - 1
+ * @name: rowsource name for debugging
+ * @init:  initialisation handler - optional, called at most once (V1)
+ * @finish: finishing handler - optional, called at most once (V1)
+ * @ensure_variables: update variables handler- optional, called at most once (V1)
+ * @read_row: read row handler - this or @read_all_rows required (V1)
+ * @read_all_rows: read all rows handler - this or @read_row required (V1)
+ * @reset: reset rowsource to starting state handler - optional (V1)
+ * @set_preserve: set preserve flag handler - optional (V1)
+ * @get_inner_rowsource: get inner rowsource handler - optional if has no inner rowsources (V1)
+ *
+ * Row Source implementation factory handler structure.
+ * 
+ */
+typedef struct {
+  int version;
+  const char* name;
+  /* API V1 methods */
+  rasqal_rowsource_init_func                 init;
+  rasqal_rowsource_finish_func               finish;
+  rasqal_rowsource_ensure_variables_func     ensure_variables;
+  rasqal_rowsource_read_row_func             read_row;
+  rasqal_rowsource_read_all_rows_func        read_all_rows;
+  rasqal_rowsource_reset_func                reset;
+  rasqal_rowsource_set_preserve_func         set_preserve;
+  rasqal_rowsource_get_inner_rowsource_func  get_inner_rowsource;
+} rasqal_rowsource_handler;
+
+
+/**
+ * rasqal_rowsource:
+ * @world: rasqal world
+ * @query: query that this may be associated with (or NULL)
+ * @flags: flags - none currently defined.
+ * @user_data: rowsource handler data
+ * @handler: rowsource handler pointer
+ * @finished: non-0 if rowsource has been exhausted
+ * @count:  number of rows returned
+ * @updated_variables: non-0 if ensure_variables factory method has been called to get the variables_sequence updated
+ * @vars_table: variables table where variables used in this row are declared/owned
+ * @variables_sequence: variables declared in this row from @vars_table
+ * @size: number of variables in @variables_sequence
+ * @rows_sequence: stored sequence of rows for use by rasqal_rowsource_read_row() (or NULL)
+ * @offset: size of @rows_sequence
+ *
+ * Rasqal Row Source class providing a sequence of rows of values similar to a SQL table.
+ *
+ * The table has @size columns which are #rasqal_variable names that
+ * are declared in the associated variables table.
+ * @variables_sequence contains the ordered projection of the
+ * variables for the columns for this row sequence, from the full set
+ * of variables in @vars_table.
+ * 
+ * Each row has @size #rasqal_literal values for the variables or
+ * NULL if unset.
+ *
+ * Row sources are constructed indirectly via an @handler passed
+ * to the rasqal_new_rowsource_from_handler() constructor.
+ *
+ * The main methods are rasqal_rowsource_read_row() to read one row
+ * and rasqal_rowsource_read_all_rows() to get all rows as a
+ * sequence, draining the row source.
+ * rasqal_rowsource_get_rows_count() returns the current number of
+ * rows that have been read which is only useful in the read one row
+ * case.
+ * 
+ * The variables associated with a rowsource can be read by
+ * rasqal_rowsource_get_variable_by_offset() and
+ * rasqal_rowsource_get_variable_offset_by_name() which all are
+ * offsets into @variables_sequence but refer to variables owned by
+ * the full internal variables table @vars_table
+ *
+ * The @rows_sequence and @offset variables are used by the
+ * rasqal_rowsource_read_row() function when operating over a handler
+ * that will only return a full sequence: handler->read_all_rows is NULL.
+ */
+struct rasqal_rowsource_s
+{
+  rasqal_world* world;
+
+  rasqal_query* query;
+  
+  int flags;
+  
+  void *user_data;
+
+  const rasqal_rowsource_handler* handler;
+
+  int finished;
+
+  int count;
+
+  int updated_variables;
+
+  rasqal_variables_table* vars_table;
+
+  raptor_sequence* variables_sequence;
+  
+  int size;
+
+  raptor_sequence* rows_sequence;
+
+  int offset;
+};
+
+/* rasqal_rowsource.c */
+rasqal_rowsource* rasqal_new_rowsource_from_handler(rasqal_world *world, rasqal_query* query, void* user_data, const rasqal_rowsource_handler *handler, rasqal_variables_table* vars_table, int flags);
+void rasqal_free_rowsource(rasqal_rowsource *rowsource);
+
+rasqal_row* rasqal_rowsource_read_row(rasqal_rowsource *rowsource);
+int rasqal_rowsource_get_rows_count(rasqal_rowsource *rowsource);
+raptor_sequence* rasqal_rowsource_read_all_rows(rasqal_rowsource *rowsource);
+int rasqal_rowsource_get_size(rasqal_rowsource *rowsource);
+int rasqal_rowsource_add_variable(rasqal_rowsource *rowsource, rasqal_variable* v);
+rasqal_variable* rasqal_rowsource_get_variable_by_offset(rasqal_rowsource *rowsource, int offset);
+int rasqal_rowsource_get_variable_offset_by_name(rasqal_rowsource *rowsource, const unsigned char* name);
+void rasqal_rowsource_copy_variables(rasqal_rowsource *dest_rowsource, rasqal_rowsource *src_rowsource);
+void rasqal_rowsource_print_row_sequence(rasqal_rowsource* rowsource,raptor_sequence* seq, FILE* fh);
+int rasqal_rowsource_reset(rasqal_rowsource* rowsource);
+int rasqal_rowsource_set_preserve(rasqal_rowsource* rowsource, int preserve);
+rasqal_rowsource* rasqal_rowsource_get_inner_rowsource(rasqal_rowsource* rowsource, int offset);
+int rasqal_rowsource_write(rasqal_rowsource *rowsource,  raptor_iostream *iostr);
+void rasqal_rowsource_print(rasqal_rowsource* rs, FILE* fh);
+int rasqal_rowsource_ensure_variables(rasqal_rowsource *rowsource);
+
+typedef int (*rasqal_query_results_formatter_func)(raptor_iostream *iostr, rasqal_query_results* results, raptor_uri *base_uri);
+
+typedef rasqal_rowsource* (*rasqal_query_results_get_rowsource_func)(rasqal_world*, rasqal_variables_table* vars_table, raptor_iostream *iostr, raptor_uri *base_uri);
+
+
+typedef struct {
+  /* query results format name */
+  const char* name;
+
+  /* query results format name */
+  const char* label;
+
+  /* query results format URI (or NULL) */
+  const unsigned char* uri_string;
+
+  /* format writer: READ from results, WRITE syntax (using base URI) to iostr */
+  rasqal_query_results_formatter_func writer;
+
+  /* format reader: READ syntax from iostr using base URI, WRITE to results */
+  rasqal_query_results_formatter_func reader;
+
+  /* format get rowsource: get a rowsource that will return a sequence of rows from an iostram */
+  rasqal_query_results_get_rowsource_func get_rowsource;
+
+  /* MIME Type of the format */
+  const char* mime_type;
+} rasqal_query_results_format_factory;
+
+
+/*
+ * A query results formatter for some query_results
+ */
+struct rasqal_query_results_formatter_s {
+  rasqal_query_results_format_factory* factory;
+
+  const char *mime_type;
+};
+
+typedef struct {
+  raptor_sequence *triples;
+  rasqal_literal *value;
+} rasqal_formula;
+
+
+/* rasqal_datetime.c */
+int rasqal_xsd_datetime_check(const unsigned char* string);
+
+
+/* rasqal_general.c */
+char* rasqal_vsnprintf(const char* message, va_list arguments);
+
+int rasqal_query_language_register_factory(rasqal_world*, const char* name, const char* label, const char* alias, const unsigned char* uri_string, void (*factory) (rasqal_query_language_factory*));
+rasqal_query_language_factory* rasqal_get_query_language_factory (rasqal_world*, const char* name, const unsigned char* uri);
+void rasqal_log_error_simple(rasqal_world* world, raptor_log_level level, raptor_locator* locator, const char* message, ...) RASQAL_PRINTF_FORMAT(4, 5);
+void rasqal_log_error_varargs(rasqal_world* world, raptor_log_level level, raptor_locator* locator, const char* message, va_list arguments) RASQAL_PRINTF_FORMAT(4, 0);
+void rasqal_log_error(raptor_log_level level, raptor_message_handler handler, void* handler_data, raptor_locator* locator, const char* message);
+void rasqal_query_simple_error(void* query, const char *message, ...) RASQAL_PRINTF_FORMAT(2, 3);
+
+const char* rasqal_basename(const char* name);
+
+
+/* rasqal_graph_pattern.c */
+unsigned char* rasqal_escaped_name_to_utf8_string(const unsigned char* src, size_t len, size_t* dest_lenp, raptor_simple_message_handler error_handler, void* error_data);
+unsigned char* rasqal_query_generate_bnodeid(rasqal_query* rdf_query, unsigned char *user_bnodeid);
+
+rasqal_graph_pattern* rasqal_new_basic_graph_pattern_from_formula(rasqal_query* query, rasqal_formula* formula);
+rasqal_graph_pattern* rasqal_new_2_group_graph_pattern(rasqal_query* query, rasqal_graph_pattern* first_gp, rasqal_graph_pattern* second_gp);
+
+/* rdql_parser.y */
+int rasqal_init_query_language_rdql(rasqal_world*);
+
+/* sparql_parser.y */
+int rasqal_init_query_language_sparql(rasqal_world*);
+int rasqal_init_query_language_laqrs(rasqal_world*);
+
+/* rasqal_query_transform.c */
+int rasqal_query_expand_triple_qnames(rasqal_query* rq);
+int rasqal_sequence_has_qname(raptor_sequence* seq);
+int rasqal_query_constraints_has_qname(rasqal_query* gp);
+int rasqal_query_expand_graph_pattern_constraints_qnames(rasqal_query* rq, rasqal_graph_pattern* gp);
+int rasqal_query_expand_query_constraints_qnames(rasqal_query* rq);
+int rasqal_query_build_anonymous_variables(rasqal_query* rq);
+int rasqal_query_expand_wildcards(rasqal_query* rq);
+int rasqal_query_remove_duplicate_select_vars(rasqal_query* rq);
+int rasqal_query_prepare_common(rasqal_query *query);
+int rasqal_query_merge_graph_patterns(rasqal_query* query, rasqal_graph_pattern* gp, void* data);
+int rasqal_graph_patterns_join(rasqal_graph_pattern *dest_gp, rasqal_graph_pattern *src_gp);
+int rasqal_graph_pattern_move_constraints(rasqal_graph_pattern* dest_gp, rasqal_graph_pattern* src_gp);
+int* rasqal_query_triples_build_declared_in(rasqal_query* query, int size, int start_column, int end_column);
+
+/* rasqal_expr.c */
+rasqal_literal* rasqal_new_string_literal_node(rasqal_world*, const unsigned char *string, const char *language, raptor_uri *datatype);
+int rasqal_literal_as_boolean(rasqal_literal* literal, int* error);
+int rasqal_literal_as_integer(rasqal_literal* l, int* error);
+double rasqal_literal_as_floating(rasqal_literal* l, int* error);
+raptor_uri* rasqal_literal_as_uri(rasqal_literal* l);
+int rasqal_literal_string_to_native(rasqal_literal *l, raptor_simple_message_handler error_handler, void *error_data, int flags);
+int rasqal_literal_has_qname(rasqal_literal* l);
+int rasqal_literal_expand_qname(void* user_data, rasqal_literal* l);
+int rasqal_literal_is_constant(rasqal_literal* l);
+int rasqal_expression_has_qname(void* user_data, rasqal_expression* e);
+int rasqal_expression_expand_qname(void* user_data, rasqal_expression* e);
+int rasqal_literal_ebv(rasqal_literal* l);
+int rasqal_expression_is_constant(rasqal_expression* e);
+void rasqal_expression_clear(rasqal_expression* e);
+void rasqal_expression_convert_to_literal(rasqal_expression* e, rasqal_literal* l);
+int rasqal_expression_mentions_variable(rasqal_expression* e, rasqal_variable* v);
+void rasqal_triple_write(rasqal_triple* t, raptor_iostream* iostr);
+void rasqal_variable_write(rasqal_variable* v, raptor_iostream* iostr);
+
+
+/* strcasecmp.c */
+#ifdef HAVE_STRCASECMP
+#  define rasqal_strcasecmp strcasecmp
+#  define rasqal_strncasecmp strncasecmp
+#else
+#  ifdef HAVE_STRICMP
+#    define rasqal_strcasecmp stricmp
+#    define rasqal_strncasecmp strnicmp
+#   else
+int rasqal_strcasecmp(const char* s1, const char* s2);
+int rasqal_strncasecmp(const char* s1, const char* s2, size_t n);
+#  endif
+#endif
+
+/* rasqal_raptor.c */
+int rasqal_raptor_init(rasqal_world*);
+
+#ifdef RAPTOR_TRIPLES_SOURCE_REDLAND
+/* rasqal_redland.c */
+int rasqal_redland_init(rasqal_world*);
+void rasqal_redland_finish(void);
+#endif  
+
+
+/* rasqal_general.c */
+int rasqal_uri_init(rasqal_world*);
+void rasqal_uri_finish(rasqal_world*);
+
+/* rasqal_literal.c */
+rasqal_formula* rasqal_new_formula(void);
+void rasqal_free_formula(rasqal_formula* formula);
+void rasqal_formula_print(rasqal_formula* formula, FILE *stream);
+rasqal_formula* rasqal_formula_join(rasqal_formula* first_formula, rasqal_formula* second_formula);
+
+/* The following should be public eventually in rasqal.h or raptor.h or ...? */
+
+typedef int (rasqal_compare_fn)(void* user_data, const void *a, const void *b);
+typedef void (rasqal_compare_free_user_data_fn)(const void *data);
+typedef void (rasqal_kv_free_fn)(const void *key, const void *value);
+
+
+#define RASQAL_XSD_BOOLEAN_TRUE (const unsigned char*)"true"
+#define RASQAL_XSD_BOOLEAN_FALSE (const unsigned char*)"false"
+
+rasqal_literal* rasqal_literal_cast(rasqal_literal* l, raptor_uri* datatype, int flags,  int* error_p);
+rasqal_literal* rasqal_new_numeric_literal(rasqal_world*, rasqal_literal_type type, double d);
+int rasqal_literal_is_numeric(rasqal_literal* literal);
+rasqal_literal* rasqal_literal_add(rasqal_literal* l1, rasqal_literal* l2, int *error);
+rasqal_literal* rasqal_literal_subtract(rasqal_literal* l1, rasqal_literal* l2, int *error);
+rasqal_literal* rasqal_literal_multiply(rasqal_literal* l1, rasqal_literal* l2, int *error);
+rasqal_literal* rasqal_literal_divide(rasqal_literal* l1, rasqal_literal* l2, int *error);
+rasqal_literal* rasqal_literal_negate(rasqal_literal* l, int *error_p);
+int rasqal_literal_equals_flags(rasqal_literal* l1, rasqal_literal* l2, int flags, int* error);
+rasqal_literal_type rasqal_literal_get_rdf_term_type(rasqal_literal* l);
+void rasqal_literal_write_type(rasqal_literal* l, raptor_iostream* iostr);
+void rasqal_literal_write(rasqal_literal* l, raptor_iostream* iostr);
+void rasqal_expression_write_op(rasqal_expression* e, raptor_iostream* iostr);
+void rasqal_expression_write(rasqal_expression* e, raptor_iostream* iostr);
+
+/* rasqal_map.c */
+typedef void (*rasqal_map_visit_fn)(void *key, void *value, void *user_data);
+
+rasqal_map* rasqal_new_map(rasqal_compare_fn* compare_fn, void* compare_user_data, rasqal_compare_free_user_data_fn* free_compare_user_data, rasqal_kv_free_fn* free_fn, raptor_sequence_print_handler* print_key_fn, raptor_sequence_print_handler* print_value_fn, int flags);
+void rasqal_free_map(rasqal_map *map);
+int rasqal_map_add_kv(rasqal_map* map, void* key, void *value);
+void rasqal_map_visit(rasqal_map* map, rasqal_map_visit_fn fn, void *user_data);
+void rasqal_map_print(rasqal_map* map, FILE* fh);
+
+/* rasqal_query.c */
+rasqal_query_results* rasqal_query_execute_with_engine(rasqal_query* query, const rasqal_query_execution_factory* engine);
+void rasqal_query_remove_query_result(rasqal_query* query, rasqal_query_results* query_results);
+int rasqal_query_declare_prefix(rasqal_query* rq, rasqal_prefix* prefix);
+int rasqal_query_declare_prefixes(rasqal_query* rq);
+unsigned char* rasqal_query_get_genid(rasqal_query* query, const unsigned char* base, int counter);
+void rasqal_query_set_base_uri(rasqal_query* rq, raptor_uri* base_uri);
+void rasqal_query_set_store_results(rasqal_query* query, int store_results);
+rasqal_variable* rasqal_query_get_variable_by_offset(rasqal_query* query, int idx);
+const rasqal_query_execution_factory* rasqal_query_get_engine_by_name(const char* name);
+
+/* rasqal_query_results.c */
+int rasqal_init_query_results(void);
+void rasqal_finish_query_results(void);
+rasqal_query_results* rasqal_new_query_results(rasqal_world* world, rasqal_query* query, rasqal_query_results_type type, rasqal_variables_table* vars_table);
+rasqal_query_results* rasqal_query_results_execute_with_engine(rasqal_query* query, const rasqal_query_execution_factory* factory);
+void rasqal_query_results_add_row(rasqal_query_results* query_results, rasqal_row* row);
+int rasqal_query_results_check_limit_offset(rasqal_query_results* query_results);
+void rasqal_query_results_remove_query_reference(rasqal_query_results* query_results);
+rasqal_variables_table* rasqal_query_results_get_variables_table(rasqal_query_results* query_results);
+
+/* rasqal_result_formats.c */
+int rasqal_query_results_format_register_factory(rasqal_world*, const char *name, const char *label, const unsigned char* uri_string, rasqal_query_results_formatter_func writer, rasqal_query_results_formatter_func reader, rasqal_query_results_get_rowsource_func get_rowsource, const char *mime_type);
+int rasqal_init_result_formats(rasqal_world*);
+void rasqal_finish_result_formats(rasqal_world*);
+
+/* rasqal_result_format_sparql_xml.c */
+int rasqal_init_result_format_sparql_xml(rasqal_world*);
+
+/* rasqal_row.c */
+rasqal_row* rasqal_new_row(rasqal_rowsource* rowsource);
+rasqal_row* rasqal_new_row_for_size(int size);
+rasqal_row* rasqal_new_row_from_row(rasqal_row* row);
+void rasqal_free_row(rasqal_row* row);
+void rasqal_row_print(rasqal_row* row, FILE* fh);
+void rasqal_row_set_value_at(rasqal_row* row, int offset, rasqal_literal* value);
+raptor_sequence* rasqal_new_row_sequence(rasqal_world* world, rasqal_variables_table* vt, const char* const row_data[], int vars_count, raptor_sequence** vars_seq_p);
+int rasqal_row_to_nodes(rasqal_row* row);
+void rasqal_row_set_values_from_variables_table(rasqal_row* row, rasqal_variables_table* vars_table);
+int rasqal_row_set_order_size(rasqal_row *row, int order_size);
+int rasqal_row_expand_size(rasqal_row *row, int size);
+
+/* rasqal_triples_source.c */
+rasqal_triples_source* rasqal_new_triples_source(rasqal_query* query);
+int rasqal_reset_triple_meta(rasqal_triple_meta* m);
+void rasqal_free_triples_source(rasqal_triples_source *rts);
+int rasqal_triples_source_triple_present(rasqal_triples_source *rts, rasqal_triple *t);
+rasqal_triples_match* rasqal_new_triples_match(rasqal_query* query, rasqal_triples_source* triples_source, rasqal_triple_meta *m, rasqal_triple *t);
+int rasqal_triples_match_bind_match(struct rasqal_triples_match_s* rtm, rasqal_variable *bindings[4],rasqal_triple_parts parts);
+void rasqal_triples_match_next_match(struct rasqal_triples_match_s* rtm);
+int rasqal_triples_match_is_end(struct rasqal_triples_match_s* rtm);
+
+/* rasqal_xsd_datatypes.c */
+int rasqal_xsd_init(rasqal_world*);
+void rasqal_xsd_finish(rasqal_world*);
+rasqal_literal_type rasqal_xsd_datatype_uri_to_type(rasqal_world*, raptor_uri* uri);
+raptor_uri* rasqal_xsd_datatype_type_to_uri(rasqal_world*, rasqal_literal_type type);
+int rasqal_xsd_datatype_check(rasqal_literal_type native_type, const unsigned char* string, int flags);
+const char* rasqal_xsd_datatype_label(rasqal_literal_type native_type);
+int rasqal_xsd_is_datatype_uri(rasqal_world*, raptor_uri* uri);
+const unsigned char* rasqal_xsd_datetime_string_to_canonical(const unsigned char* datetime_string);
+rasqal_literal_type rasqal_xsd_datatype_uri_parent_type(rasqal_world* world, raptor_uri* uri);
+int rasqal_xsd_datatype_is_numeric(rasqal_literal_type type);
+unsigned char* rasqal_xsd_format_double(double d, size_t *len_p);
+
+
+typedef struct rasqal_graph_factory_s rasqal_graph_factory;
+
+/* rasqal_world structure */
+struct rasqal_world_s {
+  /* opened flag */
+  int opened;
+  
+  /* raptor_world object */
+  raptor_world *raptor_world_ptr;
+
+  /* should rasqal free the raptor_world */
+  int raptor_world_allocated_here;
+
+  /* error handlers structure */
+  raptor_error_handlers error_handlers;
+
+  /* linked list of query languages */
+  rasqal_query_language_factory *query_languages;
+
+  /* registered query results formats */
+  raptor_sequence *query_results_formats;
+
+  /* rasqal_uri rdf uris */
+  raptor_uri *rdf_namespace_uri;
+  raptor_uri *rdf_first_uri;
+  raptor_uri *rdf_rest_uri;
+  raptor_uri *rdf_nil_uri;
+
+  /* triples source factory */
+  rasqal_triples_source_factory triples_source_factory;
+
+  /* rasqal_xsd_datatypes */
+  raptor_uri *xsd_namespace_uri;
+  raptor_uri **xsd_datatype_uris;
+
+  /* graph factory */
+  rasqal_graph_factory *graph_factory;
+  void *graph_factory_user_data;
+};
+
+
+/*
+ * Rasqal Algebra
+ *
+ * Based on http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
+ */
+
+typedef enum {
+  RASQAL_ALGEBRA_OPERATOR_UNKNOWN  = 0,
+  RASQAL_ALGEBRA_OPERATOR_BGP      = 1,
+  RASQAL_ALGEBRA_OPERATOR_FILTER   = 2,
+  RASQAL_ALGEBRA_OPERATOR_JOIN     = 3,
+  RASQAL_ALGEBRA_OPERATOR_DIFF     = 4,
+  RASQAL_ALGEBRA_OPERATOR_LEFTJOIN = 5,
+  RASQAL_ALGEBRA_OPERATOR_UNION    = 6,
+  RASQAL_ALGEBRA_OPERATOR_TOLIST   = 7,
+  RASQAL_ALGEBRA_OPERATOR_ORDERBY  = 8,
+  RASQAL_ALGEBRA_OPERATOR_PROJECT  = 9,
+  RASQAL_ALGEBRA_OPERATOR_DISTINCT = 10,
+  RASQAL_ALGEBRA_OPERATOR_REDUCED  = 11,
+  RASQAL_ALGEBRA_OPERATOR_SLICE    = 12,
+
+  RASQAL_ALGEBRA_OPERATOR_LAST=RASQAL_ALGEBRA_OPERATOR_SLICE
+} rasqal_algebra_node_operator;
+
+
+/*
+ * Algebra Node
+ */
+struct rasqal_algebra_node_s {
+  rasqal_query* query;
+
+  /* operator for this algebra_node's contents */
+  rasqal_algebra_node_operator op;
+
+  /* type BGP (otherwise NULL and start_column and end_column are -1) */
+  raptor_sequence* triples;
+  int start_column;
+  int end_column;
+  
+  /* types JOIN, DIFF, LEFTJOIN, UNION, ORDERBY: node1 and node2 ALWAYS present
+   * types FILTER, TOLIST: node1 ALWAYS present, node2 ALWAYS NULL
+   * type PROJECT: node1 always present
+   * (otherwise NULL)
+   */
+  rasqal_algebra_node *node1;
+  rasqal_algebra_node *node2;
+
+  /* types FILTER, LEFTJOIN
+   * (otherwise NULL) 
+   */
+  rasqal_expression* expr;
+
+  /* types ORDERBY always present
+   * (otherwise NULL)
+   */
+  raptor_sequence* seq;
+
+  /* types PROJECT, DISTINCT, REDUCED
+   * FIXME: sequence of solution mappings */
+
+  /* types PROJECT, SLICE */
+  raptor_sequence* vars_seq;
+
+  /* type SLICE: start and length */
+  unsigned int start;
+  unsigned int length;
+};
+
+/**
+ * rasqal_algebra_node_visit_fn:
+ * @query: #rasqal_query containing the graph pattern
+ * @gp: current algebra_node
+ * @user_data: user data passed in
+ *
+ * User function to visit an algebra_node and operate on it with
+ * rasqal_algebra_node_visit() or rasqal_query_algebra_node_visit()
+ *
+ * Return value: 0 to truncate the visit
+ */
+typedef int (*rasqal_algebra_node_visit_fn)(rasqal_query* query, rasqal_algebra_node* node, void *user_data);
+
+/* rasqal_algebra.c */
+rasqal_algebra_node* rasqal_new_filter_algebra_node(rasqal_query* query, rasqal_expression* expr, rasqal_algebra_node* node);
+rasqal_algebra_node* rasqal_new_empty_algebra_node(rasqal_query* query);
+rasqal_algebra_node* rasqal_new_triples_algebra_node(rasqal_query* query, raptor_sequence* triples, int start_column, int end_column);
+rasqal_algebra_node* rasqal_new_2op_algebra_node(rasqal_query* query, rasqal_algebra_node_operator op, rasqal_algebra_node* node1, rasqal_algebra_node* node2);
+rasqal_algebra_node* rasqal_new_leftjoin_algebra_node(rasqal_query* query, rasqal_algebra_node* node1, rasqal_algebra_node* node2, rasqal_expression* expr);
+rasqal_algebra_node* rasqal_new_orderby_algebra_node(rasqal_query* query, rasqal_algebra_node* node, raptor_sequence* seq);
+rasqal_algebra_node* rasqal_new_project_algebra_node(rasqal_query* query, rasqal_algebra_node* node1, raptor_sequence* vars_seq);
+void rasqal_free_algebra_node(rasqal_algebra_node* node);
+rasqal_algebra_node_operator rasqal_algebra_node_get_operator(rasqal_algebra_node* node);
+const char* rasqal_algebra_node_operator_as_string(rasqal_algebra_node_operator op);
+int rasqal_algebra_algebra_node_write(rasqal_algebra_node *node, raptor_iostream* iostr);
+void rasqal_algebra_node_print(rasqal_algebra_node* node, FILE* fh);
+int rasqal_algebra_node_visit(rasqal_query *query, rasqal_algebra_node* node, rasqal_algebra_node_visit_fn fn, void *user_data);
+rasqal_algebra_node* rasqal_algebra_query_to_algebra(rasqal_query* query);
+int rasqal_algebra_node_is_empty(rasqal_algebra_node* node);
+
+/* rasqal_variable.c */
+rasqal_variables_table* rasqal_new_variables_table(rasqal_world* world);
+rasqal_variables_table* rasqal_new_variables_table_from_variables_table(rasqal_variables_table* vt);
+void rasqal_free_variables_table(rasqal_variables_table* vt);
+rasqal_variable* rasqal_variables_table_add(rasqal_variables_table* vt, rasqal_variable_type type, const unsigned char *name, rasqal_literal *value);
+rasqal_variable* rasqal_variables_table_get(rasqal_variables_table* vt, int idx);
+rasqal_variable* rasqal_variables_table_get_by_name(rasqal_variables_table* vt, const unsigned char *name);
+rasqal_literal* rasqal_variables_table_get_value(rasqal_variables_table* vt, int idx);
+int rasqal_variables_table_has(rasqal_variables_table* vt, const unsigned char *name);
+int rasqal_variables_table_set(rasqal_variables_table* vt, const unsigned char *name, rasqal_literal* value);
+int rasqal_variables_table_get_named_variables_count(rasqal_variables_table* vt);
+int rasqal_variables_table_get_anonymous_variables_count(rasqal_variables_table* vt);
+int rasqal_variables_table_get_total_variables_count(rasqal_variables_table* vt);
+raptor_sequence* rasqal_variables_table_get_named_variables_sequence(rasqal_variables_table* vt);
+raptor_sequence* rasqal_variables_table_get_anonymous_variables_sequence(rasqal_variables_table* vt);
+const unsigned char** rasqal_variables_table_get_names(rasqal_variables_table* vt);
+
+
+/**
+ * @RASQAL_ENGINE_OK:
+ * @RASQAL_ENGINE_FAILED:
+ * @RASQAL_ENGINE_FINISHED:
+ *
+ * Execution engine errors.
+ *
+ */
+typedef enum {
+  RASQAL_ENGINE_OK,
+  RASQAL_ENGINE_FAILED,
+  RASQAL_ENGINE_FINISHED
+} rasqal_engine_error;
+
+
+/*
+ * A query execution engine factory
+ *
+ * This structure is about executing the query recorded in
+ * #rasqal_query structure into results accessed via #rasqal_query_results
+ */
+struct rasqal_query_execution_factory_s {
+  /* execution engine name */
+  const char* name;
+
+  /* size of execution engine private data */
+  size_t execution_data_size;
+  
+  /*
+   * @ex_data: execution data
+   * @query: query to execute
+   * @query_results: query results
+   * @flags: execution flags.  1: execute and store results
+   * @error_p: execution error (OUT variable)
+   *
+   * Initialise a new execution
+   *
+   * Return value: non-0 on failure
+   */
+  int (*execute_init)(void* ex_data, rasqal_query* query, rasqal_query_results* query_results, int flags, rasqal_engine_error *error_p);
+
+  /**
+   * @ex_data: execution data
+   * @error_p: execution error (OUT variable)
+   *
+   * Get all bindings result rows (returning a new raptor_sequence object holding new objects.
+   *
+   * Will not be called if query results is NULL, finished or failed.
+   */
+  raptor_sequence* (*get_all_rows)(void* ex_data, rasqal_engine_error *error_p);
+
+  /*
+   * @ex_data: execution object
+   * @error_p: execution error (OUT variable)
+   *
+   * Get current bindings result row (returning a new object) 
+   *
+   * Will not be called if query results is NULL, finished or failed.
+   */
+  rasqal_row* (*get_row)(void* ex_data, rasqal_engine_error *error_p);
+
+  /* finish (free) execution */
+  int (*execute_finish)(void* ex_data, rasqal_engine_error *error_p);
+  
+  /* finish the query execution factory */
+  void (*finish_factory)(rasqal_query_execution_factory* factory);
+
+};
+
+
+/* rasqal_engine.c */
+
+/* Original Rasqal 0.9.16 query engine executing over graph patterns */
+extern const rasqal_query_execution_factory rasqal_query_engine_1;
+
+/* rasqal_engine_sort.c */
+rasqal_map* rasqal_engine_new_rowsort_map(int is_distinct, int compare_flags, raptor_sequence* order_conditions_sequence);
+int rasqal_engine_rowsort_map_add_row(rasqal_map* map, rasqal_row* row);
+raptor_sequence* rasqal_engine_rowsort_map_to_sequence(rasqal_map* map, raptor_sequence* seq);
+int rasqal_engine_rowsort_calculate_order_values(rasqal_query* query, rasqal_row* row);
+
+/* rasqal_engine_algebra.c */
+
+/* New query engine based on executing over query algebra */
+extern const rasqal_query_execution_factory rasqal_query_engine_algebra;
+  
+/* end of RASQAL_INTERNAL */
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/rasqal/rasqal_literal.c b/src/rasqal/rasqal_literal.c
new file mode 100644
index 0000000..874b23e
--- /dev/null
+++ b/src/rasqal/rasqal_literal.c
@@ -0,0 +1,3198 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_literal.c - Rasqal literals
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+/* for isnan() */
+#include <math.h>
+
+#ifdef RASQAL_REGEX_PCRE
+#include <pcre.h>
+#endif
+
+#ifdef RASQAL_REGEX_POSIX
+#include <sys/types.h>
+#include <regex.h>
+#endif
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+/* prototypes */
+static rasqal_literal_type rasqal_literal_promote_numerics(rasqal_literal* l1, rasqal_literal* l2, int flags);
+static int rasqal_literal_set_typed_value(rasqal_literal* l, rasqal_literal_type type, const unsigned char* string, raptor_simple_message_handler error_handler, void *error_data, int flags);
+
+
+/**
+ * rasqal_new_integer_literal:
+ * @world: rasqal world object
+ * @type: Type of literal such as RASQAL_LITERAL_INTEGER or RASQAL_LITERAL_BOOLEAN
+ * @integer: int value
+ *
+ * Constructor - Create a new Rasqal integer literal.
+ * 
+ * The integer decimal number is turned into a rasqal integer literal
+ * and given a datatype of xsd:integer
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_integer_literal(rasqal_world* world, rasqal_literal_type type, int integer)
+{
+  raptor_uri* dt_uri;
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+    l->type=type;
+    l->value.integer=integer;
+    l->string=(unsigned char*)RASQAL_MALLOC(cstring, 30); /* FIXME */
+    if(!l->string) {
+      rasqal_free_literal(l);
+      return NULL;
+    }
+    sprintf((char*)l->string, "%d", integer);
+    l->string_len=strlen((const char*)l->string);
+    dt_uri=rasqal_xsd_datatype_type_to_uri(world, l->type);
+    if(!dt_uri) {
+      rasqal_free_literal(l);
+      return NULL;
+    }
+#ifdef RAPTOR_V2_AVAILABLE
+    l->datatype = raptor_uri_copy_v2(world->raptor_world_ptr, dt_uri);
+#else
+    l->datatype = raptor_uri_copy(dt_uri);
+#endif
+    if(type == RASQAL_LITERAL_INTEGER)
+      l->parent_type=RASQAL_LITERAL_DECIMAL;
+  }
+  return l;
+}
+
+
+/**
+ * rasqal_new_typed_literal:
+ * @world: rasqal world object
+ * @type: Type of literal such as RASQAL_LITERAL_INTEGER or RASQAL_LITERAL_BOOLEAN
+ * @string: lexical form - ownership not taken
+ *
+ * Constructor - Create a new Rasqal integer literal from a string
+ * 
+ * The integer decimal number is turned into a rasqal integer literal
+ * and given a datatype of xsd:integer
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_typed_literal(rasqal_world* world, rasqal_literal_type type, const unsigned char* string)
+{
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1,
+                                                   sizeof(rasqal_literal));
+  if(!l)
+    return NULL;
+
+  l->usage=1;
+  l->world=world;
+  l->type=type;
+  if(rasqal_literal_set_typed_value(l, type, string, NULL, NULL, 0)) {
+    rasqal_free_literal(l);
+    l=NULL;
+  }
+
+  return l;
+}
+
+
+/**
+ * rasqal_new_double_literal:
+ * @world: rasqal world object
+ * @d: double literal
+ *
+ * Constructor - Create a new Rasqal double literal.
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_double_literal(rasqal_world*world, double d)
+{
+  raptor_uri* dt_uri;
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+    l->type=RASQAL_LITERAL_DOUBLE;
+    l->value.floating=d;
+    l->string=rasqal_xsd_format_double(d, (size_t*)&l->string_len);
+    if(!l->string) {
+      rasqal_free_literal(l);
+      return NULL;
+    }
+    dt_uri=rasqal_xsd_datatype_type_to_uri(world, l->type);
+    if(!dt_uri) {
+      rasqal_free_literal(l);
+      return NULL;
+    }
+#ifdef RAPTOR_V2_AVAILABLE
+    l->datatype = raptor_uri_copy_v2(world->raptor_world_ptr, dt_uri);
+#else
+    l->datatype = raptor_uri_copy(dt_uri);
+#endif
+  }
+  return l;
+}
+
+
+/**
+ * rasqal_new_float_literal:
+ * @world: rasqal world object
+ * @f:  float literal
+ * 
+ * Constructor - Create a new Rasqal float literal.
+ *
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_float_literal(rasqal_world *world, float f)
+{
+  raptor_uri* dt_uri;
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+    l->type=RASQAL_LITERAL_FLOAT;
+    l->value.floating=(double)f;
+    l->string=(unsigned char*)RASQAL_MALLOC(cstring, 30); /* FIXME */
+    if(!l->string) {
+      rasqal_free_literal(l);
+      return NULL;
+    }
+    sprintf((char*)l->string, "%1g", f);
+    l->string_len=strlen((const char*)l->string);
+    dt_uri=rasqal_xsd_datatype_type_to_uri(world, l->type);
+    if(!dt_uri) {
+      rasqal_free_literal(l);
+      return NULL;
+    }
+#ifdef RAPTOR_V2_AVAILABLE
+    l->datatype = raptor_uri_copy_v2(world->raptor_world_ptr, dt_uri);
+#else
+    l->datatype = raptor_uri_copy(dt_uri);
+#endif
+  }
+  return l;
+}
+
+
+/**
+ * rasqal_new_uri_literal:
+ * @world: rasqal world object
+ * @uri: #raptor_uri uri
+ *
+ * Constructor - Create a new Rasqal URI literal from a raptor URI.
+ *
+ * The uri is an input parameter and is stored in the literal, not copied.
+ * The uri is freed also on failure.
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_uri_literal(rasqal_world* world, raptor_uri *uri)
+{
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+    l->type=RASQAL_LITERAL_URI;
+    l->value.uri=uri;
+  } else {
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(world->raptor_world_ptr, uri);
+#else
+    raptor_free_uri(uri);
+#endif
+  }
+  return l;
+}
+
+
+/**
+ * rasqal_new_pattern_literal:
+ * @world: rasqal world object
+ * @pattern: regex pattern
+ * @flags: regex flags
+ *
+ * Constructor - Create a new Rasqal pattern literal.
+ *
+ * The pattern and flags are input parameters and are stored in the
+ * literal, not copied. They are freed also on failure.
+ * The set of flags recognised depends on the regex library and the query
+ * language.
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_pattern_literal(rasqal_world* world,
+                           const unsigned char *pattern, 
+                           const char *flags)
+{
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+    l->type=RASQAL_LITERAL_PATTERN;
+    l->string=pattern;
+    l->string_len=strlen((const char*)pattern);
+    l->flags=(const unsigned char*)flags;
+  } else {
+    if(flags)
+      RASQAL_FREE(cstring, (void*)flags);
+    RASQAL_FREE(cstring, (void*)pattern);
+  }
+  return l;
+}
+
+
+/**
+ * rasqal_new_decimal_literal:
+ * @world: rasqal world object
+ * @string: decimal literal
+ *
+ * Constructor - Create a new Rasqal decimal literal.
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_decimal_literal(rasqal_world* world, const unsigned char *string)
+{
+  return rasqal_new_decimal_literal_from_decimal(world, string, NULL);
+}
+
+
+/**
+ * rasqal_new_decimal_literal_from_decimal:
+ * @world: rasqal world object
+ * @string: decimal literal string
+ * @decimal: rasqal XSD Decimal
+ *
+ * Constructor - Create a new Rasqal decimal literal.
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_decimal_literal_from_decimal(rasqal_world* world,
+                                        const unsigned char *string,
+                                        rasqal_xsd_decimal* decimal)
+{
+  rasqal_literal* l;
+  raptor_uri *dt_uri;
+
+  l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(!l)
+    return NULL;
+  
+  l->usage=1;
+  l->world=world;
+  l->type=RASQAL_LITERAL_DECIMAL;
+  if(string) {
+    if(rasqal_literal_set_typed_value(l, l->type, string, NULL, NULL, 0)) {
+      rasqal_free_literal(l);
+      l=NULL;
+    }
+  } else if(decimal) {
+    dt_uri=rasqal_xsd_datatype_type_to_uri(world, l->type);
+    if(!dt_uri) {
+      rasqal_free_literal(l);
+      l=NULL;
+    } else {
+#ifdef RAPTOR_V2_AVAILABLE
+      l->datatype = raptor_uri_copy_v2(world->raptor_world_ptr, dt_uri);
+#else
+      l->datatype = raptor_uri_copy(dt_uri);
+#endif
+      l->value.decimal=decimal;
+      /* string is owned by l->value.decimal */
+      l->string=(unsigned char*)rasqal_xsd_decimal_as_counted_string(l->value.decimal,
+                                                                     (size_t*)&l->string_len);
+      if(!l->string) {
+        rasqal_free_literal(l);
+        l=NULL;
+      }
+    }
+  } else {
+    /* no string or decimal was given */
+    rasqal_free_literal(l);
+    l=NULL;
+  }
+  
+  return l;
+}
+
+
+/**
+ * rasqal_new_numeric_literal:
+ * @world: rasqal world object
+ * @type: datatype
+ * @double: double
+ *
+ * INTERNAL - Make a numeric datatype from a double  
+ *
+ * Return value: new literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_numeric_literal(rasqal_world* world, rasqal_literal_type type, double d)
+{
+  char buffer[30];
+  
+  switch(type) {
+    case RASQAL_LITERAL_INTEGER:
+      return rasqal_new_integer_literal(world, type, (int)d);
+      break;
+
+    case RASQAL_LITERAL_DOUBLE:
+      return rasqal_new_double_literal(world, d);
+      break;
+
+    case RASQAL_LITERAL_FLOAT:
+      return rasqal_new_float_literal(world, d);
+      break;
+
+    case RASQAL_LITERAL_DECIMAL:
+      sprintf(buffer, "%g", d);
+      return rasqal_new_decimal_literal(world, (unsigned char*)buffer);
+      break;
+
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DATETIME:
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_VARIABLE:
+      RASQAL_FATAL2("Unexpected numeric type %d\n", type);
+  }
+
+  return NULL;
+}
+
+
+/*
+ * rasqal_literal_set_typed_value:
+ * @l: literal
+ * @type: type
+ * @string: string or NULL to use existing literal string
+ * @error_handler: error handling function
+ * @error_data: data for error handle
+ * @flags: non-0 to ignore type errors
+ *
+ * INTERNAL - Set a literal typed value
+ *
+ * Return value: non-0 on failure
+ **/
+static int
+rasqal_literal_set_typed_value(rasqal_literal* l, rasqal_literal_type type,
+                               const unsigned char* string,
+                               raptor_simple_message_handler error_handler,
+                               void *error_data, int flags)
+{  
+  char *eptr;
+  raptor_uri* dt_uri;
+  int i;
+  double d;
+  const unsigned char *new_string;
+  int valid;
+
+  valid=rasqal_xsd_datatype_check(type, string ? string : l->string, flags);
+  if(!valid) {
+    if(!flags) {
+      if(error_handler)
+        error_handler(error_data, "Illegal type %s string '%s'",
+                      rasqal_xsd_datatype_label(type), string ? string : l->string);
+      return 1;
+    }
+    return 0;
+  }
+
+  if(l->language) {
+    RASQAL_FREE(cstring, (void*)l->language);
+    l->language=NULL;
+  }
+  l->type=type;
+
+  if(string) {
+    if(l->string)
+      RASQAL_FREE(cstring, (void*)l->string);
+    l->string_len=strlen((const char*)string);
+    l->string=(unsigned char*)RASQAL_MALLOC(cstring, l->string_len+1);
+    if(!l->string)
+      return 1;
+    strncpy((char*)l->string, (const char*)string, l->string_len+1);
+  }
+
+  dt_uri=rasqal_xsd_datatype_type_to_uri(l->world, l->type);
+  if(!dt_uri)
+    return 1;
+
+#ifdef RAPTOR_V2_AVAILABLE
+  if(l->datatype)
+    raptor_free_uri_v2(l->world->raptor_world_ptr, l->datatype);
+  l->datatype = raptor_uri_copy_v2(l->world->raptor_world_ptr, dt_uri);
+#else
+  if(l->datatype)
+    raptor_free_uri(l->datatype);
+  l->datatype = raptor_uri_copy(dt_uri);
+#endif
+
+  if(type == RASQAL_LITERAL_INTEGER)
+    l->parent_type=RASQAL_LITERAL_DECIMAL;
+
+  switch(type) {
+    case RASQAL_LITERAL_INTEGER:
+      eptr=NULL;
+      i=(int)strtol((const char*)l->string, &eptr, 10);
+      if(*eptr)
+        return 1;
+
+      l->value.integer=i;
+      l->parent_type=RASQAL_LITERAL_DECIMAL;
+      break;
+
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+      d=0.0;
+      (void)sscanf((char*)l->string, "%lf", &d);
+      l->value.floating=d;
+      break;
+
+    case RASQAL_LITERAL_DECIMAL:
+      l->value.decimal=rasqal_new_xsd_decimal();
+      if(!l->value.decimal) {
+        RASQAL_FREE(cstring, (void*)l->string);
+        return 1;
+      }
+      if(rasqal_xsd_decimal_set_string(l->value.decimal,
+                                       (const char*)l->string)) {
+        RASQAL_FREE(cstring, (void*)l->string);
+        return 1;
+      }
+      RASQAL_FREE(cstring, (void*)l->string);
+      /* string is owned by l->value.decimal */
+      l->string=(unsigned char*)rasqal_xsd_decimal_as_counted_string(l->value.decimal,
+                                                                     (size_t*)&l->string_len);
+      if(!l->string)
+        return 1;
+      break;
+
+    case RASQAL_LITERAL_BOOLEAN:
+      i=0;
+      if(!strcmp((const char*)l->string, "true") || 
+         !strcmp((const char*)l->string, "TRUE") ||
+         !strcmp((const char*)l->string, "1"))
+        i=1;
+      
+      /* Free passed in string */
+      RASQAL_FREE(cstring, (void*)l->string);
+      /* and replace with a static string */
+      l->string=i ? RASQAL_XSD_BOOLEAN_TRUE : RASQAL_XSD_BOOLEAN_FALSE;
+      l->string_len=(i ? 4 : 5);
+      
+      l->value.integer=i;
+      break;
+
+  case RASQAL_LITERAL_STRING:
+    /* No change - kept as a string */
+    break;
+
+  case RASQAL_LITERAL_DATETIME:
+    new_string=rasqal_xsd_datetime_string_to_canonical(l->string);
+    if(new_string) {
+      RASQAL_DEBUG3("converted xsd:dateTime \"%s\" to canonical form \"%s\"\n", l->string, new_string);
+      RASQAL_FREE(cstring, l->string);
+      l->string=new_string;
+      l->string_len=strlen((const char*)l->string);
+      break; /* success */
+    }
+    RASQAL_DEBUG2("rasqal_xsd_datetime_string_to_canonical(\"%s\") failed\n", l->string);
+    return 1; /* error */
+
+  case RASQAL_LITERAL_UNKNOWN:
+  case RASQAL_LITERAL_BLANK:
+  case RASQAL_LITERAL_URI:
+  case RASQAL_LITERAL_PATTERN:
+  case RASQAL_LITERAL_QNAME:
+  case RASQAL_LITERAL_VARIABLE:
+    RASQAL_FATAL2("Unexpected native type %d\n", type);
+    break;
+    
+  default:
+    RASQAL_FATAL2("Unknown native type %d\n", type);
+  }
+
+  return 0;
+}
+
+
+
+/*
+ * rasqal_literal_string_to_native:
+ * @l: #rasqal_literal to operate on inline
+ * @error_handler: error handling function
+ * @error_data: data for error handle
+ * @flags: flags for literal checking.  non-0 to ignore type errors
+ *
+ * INTERNAL Upgrade a datatyped literal string to an internal typed literal
+ *
+ * At present this promotes datatyped literals
+ * xsd:integer to RASQAL_LITERAL_INTEGER
+ * xsd:double to RASQAL_LITERAL_DOUBLE
+ * xsd:float to RASQAL_LITERAL_FLOAT
+ * xsd:boolean to RASQAL_LITERAL_BOOLEAN
+ * xsd:decimal to RASQAL_LITERAL_DECIMAL
+ * xsd:dateTime to RASQAL_LITERAL_DATETIME
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_literal_string_to_native(rasqal_literal *l,
+                                raptor_simple_message_handler error_handler,
+                                void *error_data, int flags)
+{
+  rasqal_literal_type native_type=RASQAL_LITERAL_UNKNOWN;
+  int rc=0;
+  
+  /* RDF literal with no datatype (plain literal) */
+  if(!l->datatype)
+    return 0;
+  
+  native_type=rasqal_xsd_datatype_uri_to_type(l->world, l->datatype);
+
+  /* If not a native type return ok but do not change literal */
+  if(native_type == RASQAL_LITERAL_UNKNOWN)
+    return 0;
+  /* xsd:string but nothing need be done */
+  if(native_type == RASQAL_LITERAL_STRING)
+    return 0;
+
+  rc=rasqal_literal_set_typed_value(l, native_type, NULL /* existing string */,
+                                    error_handler, error_data, flags);
+  return rc;
+}
+
+
+/*
+ * rasqal_new_string_literal_common:
+ * @world: rasqal world object
+ * @string: UTF-8 string lexical form
+ * @language: RDF language (xml:lang) (or NULL)
+ * @datatype: datatype URI (or NULL for plain literal)
+ * @datatype_qname: datatype qname string (or NULL for plain literal)
+ * @flags: flags - 1 to do native type promotion
+ *
+ * INTERNAL Constructor - Create a new Rasqal string literal.
+ * 
+ * All parameters are input parameters and if present are stored in
+ * the literal, not copied. They are freed also on failure.
+ * 
+ * The datatype and datatype_qname parameters are alternatives; the
+ * qname is a datatype that cannot be resolved till later since the
+ * prefixes have not yet been declared or checked.
+ * 
+ * If the string literal is datatyped and of certain types recognised
+ * it may be converted to a different literal type by 
+ * rasqal_literal_string_to_native() only if @flags is 1.
+ *
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+static rasqal_literal*
+rasqal_new_string_literal_common(rasqal_world* world,
+                                 const unsigned char *string,
+                                 const char *language,
+                                 raptor_uri *datatype, 
+                                 const unsigned char *datatype_qname,
+                                 int flags)
+{
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+
+    if(datatype && language) {
+      /* RDF typed literal but this is not allowed so delete language */
+      RASQAL_FREE(cstring, (void*)language);
+      language=NULL;
+    }
+
+    l->type=RASQAL_LITERAL_STRING;
+    l->string=string;
+    l->string_len=strlen((const char*)string);
+    l->language=language;
+    l->datatype=datatype;
+    l->flags=datatype_qname;
+
+    if(datatype)
+      /* This is either RASQAL_LITERAL_DECIMAL or ...INTEGER or ...UNKNOWN */
+      l->parent_type=rasqal_xsd_datatype_uri_parent_type(world, datatype);
+
+    if((flags == 1) && rasqal_literal_string_to_native(l, NULL, NULL, 1)) {
+      rasqal_free_literal(l);
+      l=NULL;
+    }
+  } else {
+    if(language)
+      RASQAL_FREE(cstring, (void*)language);
+    if(datatype)
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_free_uri_v2(world->raptor_world_ptr, datatype);
+#else
+      raptor_free_uri(datatype);
+#endif
+    if(datatype_qname)
+      RASQAL_FREE(cstring, (void*)datatype_qname);
+    RASQAL_FREE(cstring, (void*)string);
+  }
+    
+  return l;
+}
+
+
+/**
+ * rasqal_new_string_literal:
+ * @world: rasqal world object
+ * @string: UTF-8 string lexical form
+ * @language: RDF language (xml:lang) (or NULL)
+ * @datatype: datatype URI (or NULL for plain literal)
+ * @datatype_qname: datatype qname string (or NULL for plain literal)
+ *
+ * Constructor - Create a new Rasqal string literal.
+ * 
+ * All parameters are input parameters and if present are stored in
+ * the literal, not copied. They are freed also on failure.
+ * 
+ * The datatype and datatype_qname parameters are alternatives; the
+ * qname is a datatype that cannot be resolved till later since the
+ * prefixes have not yet been declared or checked.
+ * 
+ * If the string literal is datatyped and of certain types recognised
+ * it may be converted to a different literal type by
+ * rasqal_literal_string_to_native()
+ *
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_string_literal(rasqal_world* world,
+                          const unsigned char *string,
+                          const char *language,
+                          raptor_uri *datatype, 
+                          const unsigned char *datatype_qname)
+{
+  return rasqal_new_string_literal_common(world, string, language, datatype, 
+                                          datatype_qname, 1);
+}
+
+rasqal_literal*
+rasqal_new_string_literal_node(rasqal_world* world, const unsigned char *string,
+                               const char *language, raptor_uri *datatype)
+{
+  return rasqal_new_string_literal_common(world, string, language, datatype, NULL, 0);
+}
+
+
+/**
+ * rasqal_new_simple_literal:
+ * @world: rasqal world object
+ * @type: RASQAL_LITERAL_BLANK or RASQAL_LITERAL_BLANK_QNAME
+ * @string: the UTF-8 string value to store
+ *
+ * Constructor - Create a new Rasqal simple literal.
+ * 
+ * The string is an input parameter and is stored in the
+ * literal, not copied. It is freed also on failure.
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_simple_literal(rasqal_world* world,
+                          rasqal_literal_type type, 
+                          const unsigned char *string)
+{
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+    l->type=type;
+    l->string=string;
+    l->string_len=strlen((const char*)string);
+  } else {
+    RASQAL_FREE(cstring, (void*)string);
+  }
+  return l;
+}
+
+
+/**
+ * rasqal_new_boolean_literal:
+ * @world: rasqal world object
+ * @value: non-0 for true, 0 for false
+ *
+ * Constructor - Create a new Rasqal boolean literal.
+ *
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_boolean_literal(rasqal_world* world, int value)
+{
+  raptor_uri* dt_uri;
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+    l->type=RASQAL_LITERAL_BOOLEAN;
+    l->value.integer=value;
+    l->string=value ? RASQAL_XSD_BOOLEAN_TRUE : RASQAL_XSD_BOOLEAN_FALSE;
+    l->string_len=(value ? 4 : 5);
+    dt_uri=rasqal_xsd_datatype_type_to_uri(world, l->type);
+    if(!dt_uri) {
+      rasqal_free_literal(l);
+      return NULL;
+    }
+#ifdef RAPTOR_V2_AVAILABLE
+    l->datatype = raptor_uri_copy_v2(world->raptor_world_ptr, dt_uri);
+#else
+    l->datatype = raptor_uri_copy(dt_uri);
+#endif
+  }
+  return l;
+}
+
+
+/**
+ * rasqal_new_variable_literal:
+ * @world: rasqal_world object
+ * @variable: #rasqal_variable to use
+ *
+ * Constructor - Create a new Rasqal variable literal.
+ * 
+ * variable is an input parameter and stored in the literal, not copied.
+ * 
+ * Return value: New #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_new_variable_literal(rasqal_world* world, rasqal_variable *variable)
+{
+  rasqal_literal* l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+  if(l) {
+    l->usage=1;
+    l->world=world;
+    l->type=RASQAL_LITERAL_VARIABLE;
+    l->value.variable=variable;
+  }
+
+  /* Do not rasqal_free_variable(variable) on error since
+   * all variables are shared and owned by rasqal_query
+   * variables_sequence */
+
+  return l;
+}
+
+
+/**
+ * rasqal_new_literal_from_literal:
+ * @l: #rasqal_literal object to copy
+ *
+ * Copy Constructor - create a new rasqal_literal object from an existing rasqal_literal object.
+ * 
+ * Return value: a new #rasqal_literal object or NULL
+ **/
+rasqal_literal*
+rasqal_new_literal_from_literal(rasqal_literal* l)
+{
+  if(!l)
+    return NULL;
+  
+  l->usage++;
+  return l;
+}
+
+
+/**
+ * rasqal_free_literal:
+ * @l: #rasqal_literal object
+ *
+ * Destructor - destroy an rasqal_literal object.
+ * 
+ **/
+void
+rasqal_free_literal(rasqal_literal* l)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(l, rasqal_literal);
+  
+  if(--l->usage)
+    return;
+  
+  switch(l->type) {
+    case RASQAL_LITERAL_URI:
+      if(l->value.uri)
+#ifdef RAPTOR_V2_AVAILABLE
+        raptor_free_uri_v2(l->world->raptor_world_ptr, l->value.uri);
+#else
+        raptor_free_uri(l->value.uri);
+#endif
+      break;
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_INTEGER: 
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DATETIME:
+      if(l->string)
+        RASQAL_FREE(cstring, (void*)l->string);
+      if(l->language)
+        RASQAL_FREE(cstring, (void*)l->language);
+      if(l->datatype)
+#ifdef RAPTOR_V2_AVAILABLE
+        raptor_free_uri_v2(l->world->raptor_world_ptr, l->datatype);
+#else
+        raptor_free_uri(l->datatype);
+#endif
+      if(l->type == RASQAL_LITERAL_STRING ||
+         l->type == RASQAL_LITERAL_PATTERN) {
+        if(l->flags)
+          RASQAL_FREE(cstring, (void*)l->flags);
+      }
+      break;
+    case RASQAL_LITERAL_DECIMAL:
+      /* l->string is owned by l->value.decimal - do not free it */
+      if(l->datatype)
+#ifdef RAPTOR_V2_AVAILABLE
+        raptor_free_uri_v2(l->world->raptor_world_ptr, l->datatype);
+#else
+        raptor_free_uri(l->datatype);
+#endif
+      if(l->value.decimal)
+        rasqal_free_xsd_decimal(l->value.decimal);
+      break;
+
+    case RASQAL_LITERAL_BOOLEAN:
+      /* static l->string for boolean, does not need freeing */
+      if(l->datatype)
+#ifdef RAPTOR_V2_AVAILABLE
+        raptor_free_uri_v2(l->world->raptor_world_ptr, l->datatype);
+#else
+        raptor_free_uri(l->datatype);
+#endif
+      break;
+
+    case RASQAL_LITERAL_VARIABLE:
+      /* It is correct that this is not called here
+       * since all variables are shared and owned by
+       * the rasqal_query sequence variables_sequence */
+
+      /* rasqal_free_variable(l->value.variable); */
+      break;
+
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown literal type %d", l->type);
+  }
+  RASQAL_FREE(rasqal_literal, l);
+}
+
+
+/* 
+ * The order here must match that of rasqal_literal_type
+ * in rasqal.h and is significant as rasqal_literal_compare
+ * uses it for type comparisons with the RASQAL_COMPARE_XQUERY
+ * flag.
+ */
+static const char* const rasqal_literal_type_labels[RASQAL_LITERAL_LAST+1]={
+  "UNKNOWN",
+  "blank",
+  "uri",
+  "string",
+  "boolean",
+  "integer",
+  "double",
+  "float",
+  "decimal",
+  "datetime",
+  "pattern",
+  "qname",
+  "variable"
+};
+
+
+/**
+ * rasqal_literal_write_type:
+ * @l: the #rasqal_literal object
+ * @iostr: the #raptor_iostream handle to print to
+ * 
+ * Write a string form for a rasqal literal type to an iostream
+ *
+ **/
+void
+rasqal_literal_write_type(rasqal_literal* l, raptor_iostream* iostr)
+{
+  rasqal_literal_type type;
+
+  if(!l) {
+    raptor_iostream_write_counted_string(iostr, "null", 4);
+    return;
+  }
+  
+  type=l->type;
+  if(type > RASQAL_LITERAL_LAST)
+    type=RASQAL_LITERAL_UNKNOWN;
+  raptor_iostream_write_string(iostr, rasqal_literal_type_labels[(int)type]);
+}
+
+
+/**
+ * rasqal_literal_print_type:
+ * @l: the #rasqal_literal object
+ * @fh: the #FILE* handle to print to
+ * 
+ * Print a string form for a rasqal literal type.
+ *
+ **/
+void
+rasqal_literal_print_type(rasqal_literal* l, FILE* fh)
+{
+  rasqal_literal_type type;
+
+  if(!l) {
+    fputs("null", fh);
+    return;
+  }
+  
+  type=l->type;
+  if(type > RASQAL_LITERAL_LAST)
+    type=RASQAL_LITERAL_UNKNOWN;
+  fputs(rasqal_literal_type_labels[(int)type], fh);
+}
+
+
+/**
+ * rasqal_literal_write:
+ * @l: the #rasqal_literal object
+ * @iostr: the #raptor_iostream handle to write to
+ *
+ * Write a Rasqal literal to an iostream in a debug format.
+ * 
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_literal_write(rasqal_literal* l, raptor_iostream* iostr)
+{
+  const unsigned char*str;
+  size_t len;
+  
+  if(!l) {
+    raptor_iostream_write_counted_string(iostr, "null", 4);
+    return;
+  }
+
+  if(l->type != RASQAL_LITERAL_VARIABLE)
+    rasqal_literal_write_type(l, iostr);
+
+  switch(l->type) {
+    case RASQAL_LITERAL_URI:
+      raptor_iostream_write_byte(iostr, '<');
+#ifdef RAPTOR_V2_AVAILABLE
+      str = raptor_uri_as_counted_string_v2(l->world->raptor_world_ptr, l->value.uri, &len);
+#else
+      str = raptor_uri_as_counted_string(l->value.uri, &len);
+#endif
+      raptor_iostream_write_string_ntriples(iostr, str, len, '>');
+      raptor_iostream_write_byte(iostr, '>');
+      break;
+    case RASQAL_LITERAL_BLANK:
+      raptor_iostream_write_byte(iostr, ' ');
+      raptor_iostream_write_counted_string(iostr, l->string, l->string_len);
+      break;
+    case RASQAL_LITERAL_PATTERN:
+      raptor_iostream_write_byte(iostr, '/');
+      raptor_iostream_write_counted_string(iostr, l->string, l->string_len);
+      raptor_iostream_write_byte(iostr, '/');
+      if(l->flags)
+        raptor_iostream_write_string(iostr, l->flags);
+      break;
+    case RASQAL_LITERAL_STRING:
+      raptor_iostream_write_counted_string(iostr, "(\"", 2);
+      raptor_iostream_write_string_ntriples(iostr, l->string, l->string_len, '"');
+      raptor_iostream_write_byte(iostr, '"');
+      if(l->language) {
+        raptor_iostream_write_byte(iostr, '@');
+        raptor_iostream_write_string(iostr, l->language);
+      }
+      if(l->datatype) {
+        raptor_iostream_write_counted_string(iostr, "^^<", 3);
+#ifdef RAPTOR_V2_AVAILABLE
+        str = raptor_uri_as_counted_string_v2(l->world->raptor_world_ptr, l->datatype, &len);
+#else
+        str = raptor_uri_as_counted_string(l->datatype, &len);
+#endif
+        raptor_iostream_write_string_ntriples(iostr, str, len, '>');
+        raptor_iostream_write_byte(iostr, '>');
+      }
+      raptor_iostream_write_byte(iostr, ')');
+      break;
+    case RASQAL_LITERAL_VARIABLE:
+      rasqal_variable_write(l->value.variable, iostr);
+      break;
+
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DECIMAL:
+    case RASQAL_LITERAL_DATETIME:
+      raptor_iostream_write_byte(iostr, '(');
+      raptor_iostream_write_counted_string(iostr, l->string, l->string_len);
+      raptor_iostream_write_byte(iostr, ')');
+      break;
+
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown literal type %d", l->type);
+  }
+}
+
+
+
+/**
+ * rasqal_literal_print:
+ * @l: the #rasqal_literal object
+ * @fh: the #FILE* handle to print to
+ *
+ * Print a Rasqal literal in a debug format.
+ * 
+ * The print debug format may change in any release.
+ **/
+void
+rasqal_literal_print(rasqal_literal* l, FILE* fh)
+{
+  if(!l) {
+    fputs("null", fh);
+    return;
+  }
+
+  if(l->type != RASQAL_LITERAL_VARIABLE)
+    rasqal_literal_print_type(l, fh);
+
+  switch(l->type) {
+    case RASQAL_LITERAL_URI:
+      fputc('<', fh);
+      raptor_print_ntriples_string(fh,
+#ifdef RAPTOR_V2_AVAILABLE
+                                   raptor_uri_as_string_v2(l->world->raptor_world_ptr, l->value.uri),
+#else
+                                   raptor_uri_as_string(l->value.uri),
+#endif
+                                   '>');
+      fputc('>', fh);
+      break;
+    case RASQAL_LITERAL_BLANK:
+      fprintf(fh, " %s", l->string);
+      break;
+    case RASQAL_LITERAL_PATTERN:
+      fprintf(fh, "/%s/%s", l->string, l->flags ? (const char*)l->flags : "");
+      break;
+    case RASQAL_LITERAL_STRING:
+      fputs("(\"", fh);
+      raptor_print_ntriples_string(fh, l->string, '"');
+      fputc('"', fh);
+      if(l->language)
+        fprintf(fh, "@%s", l->language);
+      if(l->datatype) {
+        fputs("^^<", fh);
+        raptor_print_ntriples_string(fh,
+#ifdef RAPTOR_V2_AVAILABLE
+                                     raptor_uri_as_string_v2(l->world->raptor_world_ptr, l->datatype),
+#else
+                                     raptor_uri_as_string(l->datatype),
+#endif
+                                     '>');
+        fputc('>', fh);
+      }
+      fputc(')', fh);
+      break;
+    case RASQAL_LITERAL_VARIABLE:
+      rasqal_variable_print(l->value.variable, fh);
+      break;
+
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DECIMAL:
+    case RASQAL_LITERAL_DATETIME:
+      fputc('(', fh);
+      fwrite(l->string, 1, l->string_len, fh);
+      fputc(')', fh);
+      break;
+
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown literal type %d", l->type);
+  }
+}
+
+
+
+/*
+ * rasqal_literal_as_boolean:
+ * @l: #rasqal_literal object
+ * @error: pointer to error flag
+ * 
+ * INTERNAL: Return a literal as a boolean value
+ *
+ * SPARQL Effective Boolean Value (EBV) rules:
+ *  - If the argument is a typed literal with a datatype of xsd:boolean, the
+ *    EBV is the value of that argument.
+ *  - If the argument is a plain literal or a typed literal with a datatype of
+ *    xsd:string, the EBV is false if the operand value has zero length;
+ *    otherwise the EBV is true.
+ *  - If the argument is a numeric type or a typed literal with a datatype
+ *    derived from a numeric type, the EBV is false if the operand value is NaN
+ *    or is numerically equal to zero; otherwise the EBV is true.
+ *  - All other arguments, including unbound arguments, produce a type error.
+ *
+ * Return value: non-0 if true
+ **/
+int
+rasqal_literal_as_boolean(rasqal_literal* l, int *error)
+{
+  if(!l)
+    return 0;
+  
+  switch(l->type) {
+    case RASQAL_LITERAL_STRING:
+      if(l->datatype) {
+        if(
+#ifdef RAPTOR_V2_AVAILABLE
+           raptor_uri_equals_v2(l->world->raptor_world_ptr, l->datatype, 
+                             rasqal_xsd_datatype_type_to_uri(l->world, RASQAL_LITERAL_STRING))
+#else
+           raptor_uri_equals(l->datatype, 
+                             rasqal_xsd_datatype_type_to_uri(l->world, RASQAL_LITERAL_STRING))
+#endif
+           )
+        {
+          /* typed literal with xsd:string datatype -> true if non-empty */
+          return l->string && *l->string;
+        }
+        /* typed literal with other datatype -> type error */
+        *error = 1;
+        return 0;
+      }
+      /* plain literal -> true if non-empty */
+      return l->string && *l->string;
+
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_DECIMAL:
+    case RASQAL_LITERAL_DATETIME:
+      *error = 1;
+      return 0;
+      break;
+
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+      return l->value.integer != 0;
+      break;
+
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+      return l->value.floating != 0.0 && !isnan(l->value.floating);
+      break;
+
+    case RASQAL_LITERAL_VARIABLE:
+      return rasqal_literal_as_boolean(l->value.variable->value, error);
+      break;
+
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown literal type %d", l->type);
+      return 0; /* keep some compilers happy */
+  }
+}
+
+
+/*
+ * rasqal_literal_as_integer - INTERNAL Return a literal as an integer value
+ * @l: #rasqal_literal object
+ * @error: pointer to error flag
+ * 
+ * Integers, booleans, double and float literals natural are turned into
+ * integers. If string values are the lexical form of an integer, that is
+ * returned.  Otherwise the error flag is set.
+ * 
+ * Return value: integer value
+ **/
+int
+rasqal_literal_as_integer(rasqal_literal* l, int *error)
+{
+  if(!l)
+    return 0;
+  
+  switch(l->type) {
+    case RASQAL_LITERAL_INTEGER:
+      return l->value.integer;
+      break;
+
+    case RASQAL_LITERAL_BOOLEAN:
+      return l->value.integer != 0;
+      break;
+
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+      return (int)l->value.floating;
+      break;
+
+    case RASQAL_LITERAL_DECIMAL:
+      return (int)rasqal_xsd_decimal_get_double(l->value.decimal);
+      break;
+
+    case RASQAL_LITERAL_STRING:
+      {
+        char *eptr;
+        double  d;
+        int v;
+
+        eptr=NULL;
+        v=(int)strtol((const char*)l->string, &eptr, 10);
+        if((unsigned char*)eptr != l->string && *eptr=='\0')
+          return v;
+
+        eptr=NULL;
+        d=strtod((const char*)l->string, &eptr);
+        if((unsigned char*)eptr != l->string && *eptr=='\0')
+          return (int)d;
+      }
+      if(error)
+        *error=1;
+      return 0;
+      break;
+
+    case RASQAL_LITERAL_VARIABLE:
+      return rasqal_literal_as_integer(l->value.variable->value, error);
+      break;
+
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_DATETIME:
+      if(error)
+        *error=1;
+      return 0;
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown literal type %d", l->type);
+      return 0; /* keep some compilers happy */
+  }
+}
+
+
+/*
+ * rasqal_literal_as_floating - INTERNAL Return a literal as a floating value
+ * @l: #rasqal_literal object
+ * @error: pointer to error flag
+ * 
+ * Integers, booleans, double and float literals natural are turned into
+ * integers. If string values are the lexical form of an floating, that is
+ * returned.  Otherwise the error flag is set.
+ * 
+ * Return value: floating value
+ **/
+double
+rasqal_literal_as_floating(rasqal_literal* l, int *error)
+{
+  if(!l)
+    return 0;
+  
+  switch(l->type) {
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+      return (double)l->value.integer;
+      break;
+
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+      return l->value.floating;
+      break;
+
+    case RASQAL_LITERAL_DECIMAL:
+      return rasqal_xsd_decimal_get_double(l->value.decimal);
+      break;
+
+    case RASQAL_LITERAL_STRING:
+      {
+        char *eptr=NULL;
+        double  d=strtod((const char*)l->string, &eptr);
+        if((unsigned char*)eptr != l->string && *eptr=='\0')
+          return d;
+      }
+      if(error)
+        *error=1;
+      return 0.0;
+      break;
+
+    case RASQAL_LITERAL_VARIABLE:
+      return rasqal_literal_as_integer(l->value.variable->value, error);
+      break;
+
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_DATETIME:
+      if(error)
+        *error=1;
+      return 0.0;
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown literal type %d", l->type);
+      return 0.0; /* keep some compilers happy */
+  }
+}
+
+
+/*
+ * rasqal_literal_as_uri - INTERNAL Return a literal as a raptor_uri*
+ * @l: #rasqal_literal object
+ * 
+ * Return value: raptor_uri* value or NULL on failure
+ **/
+raptor_uri*
+rasqal_literal_as_uri(rasqal_literal* l)
+{
+  if(!l)
+    return NULL;
+  
+  if(l->type==RASQAL_LITERAL_URI)
+    return l->value.uri;
+
+  if(l->type==RASQAL_LITERAL_VARIABLE)
+    return rasqal_literal_as_uri(l->value.variable->value);
+
+  RASQAL_FATAL2("Literal type %d has no URI value", l->type);
+
+  return NULL;
+}
+
+
+/**
+ * rasqal_literal_as_string_flags:
+ * @l: #rasqal_literal object
+ * @flags: comparison flags
+ * @error: pointer to error
+ *
+ * Return the string format of a literal according to flags.
+ * 
+ * flag bits affects conversion:
+ *   RASQAL_COMPARE_XQUERY: use XQuery conversion rules
+ * 
+ * If @error is not NULL, *error is set to non-0 on error
+ *
+ * Return value: pointer to a shared string format of the literal.
+ **/
+const unsigned char*
+rasqal_literal_as_string_flags(rasqal_literal* l, int flags, int *error)
+{
+  if(!l)
+    return NULL;
+  
+  switch(l->type) {
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DECIMAL:
+    case RASQAL_LITERAL_DATETIME:
+      return l->string;
+
+    case RASQAL_LITERAL_URI:
+      if(flags & RASQAL_COMPARE_XQUERY) {
+        if(error)
+          *error=1;
+        return NULL;
+      }
+#ifdef RAPTOR_V2_AVAILABLE
+      return raptor_uri_as_string_v2(l->world->raptor_world_ptr, l->value.uri);
+#else
+      return raptor_uri_as_string(l->value.uri);
+#endif
+
+    case RASQAL_LITERAL_VARIABLE:
+      return rasqal_literal_as_string_flags(l->value.variable->value, flags,
+                                            error);
+
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown literal type %d", l->type);
+      return NULL; /* keep some compilers happy */
+  }
+}
+
+
+/**
+ * rasqal_literal_as_string:
+ * @l: #rasqal_literal object
+ *
+ * Return the string format of a literal.
+ * 
+ * Return value: pointer to a shared string format of the literal.
+ **/
+const unsigned char*
+rasqal_literal_as_string(rasqal_literal* l)
+{
+  return rasqal_literal_as_string_flags(l, 0, NULL);
+}
+
+/**
+ * rasqal_literal_as_variable:
+ * @l: #rasqal_literal object
+ *
+ * Get the variable inside a literal.
+ * 
+ * Return value: the #rasqal_variable or NULL if the literal is not a variable
+ **/
+rasqal_variable*
+rasqal_literal_as_variable(rasqal_literal* l)
+{
+  return (l->type == RASQAL_LITERAL_VARIABLE) ? l->value.variable : NULL;
+}
+
+
+/**
+ * rasqal_literal_promote_numerics:
+ * @l1: first literal
+ * @l2: second literal
+ * @flags: promotion flags
+ *
+ * INTERNAL - Calculate the type to promote a pair of literals to
+ *
+ * Numeric type promotion
+ * http://www.w3.org/TR/xpath20/#dt-type-promotion
+ *
+ * [[xs:decimal (or any type derived by restriction from xs:decimal,
+ * including xs:integer) can be promoted to either of the types
+ * xs:float or xs:double.]]
+ *
+ * For here that means xs:integer to xs:double and xs:decimal to xs:double
+ *
+ * Return value: promote type or RASQAL_LITERAL_UNKNOWN
+ */
+static rasqal_literal_type
+rasqal_literal_promote_numerics(rasqal_literal* l1, rasqal_literal* l2,
+                                 int flags)
+{
+  rasqal_literal_type type1=l1->type;
+  rasqal_literal_type type2=l2->type;
+
+  /* No promotion needed */
+  if(type1 == type2)
+    return type1;
+
+  /* No parents - no promotion possible */
+  if(l1->parent_type == RASQAL_LITERAL_UNKNOWN &&
+     l2->parent_type == RASQAL_LITERAL_UNKNOWN)
+    return l1->parent_type;
+  
+  /* First promotion is to xsd:integer */
+  if(l1->parent_type == RASQAL_LITERAL_INTEGER &&
+     type2 == RASQAL_LITERAL_INTEGER)
+    return type2;
+
+  if(l2->parent_type == RASQAL_LITERAL_INTEGER &&
+     type1 == RASQAL_LITERAL_INTEGER)
+    return type1;
+
+  if(l1->parent_type == RASQAL_LITERAL_INTEGER)
+    type1=RASQAL_LITERAL_INTEGER;
+  if(l2->parent_type == RASQAL_LITERAL_INTEGER)
+    type2=RASQAL_LITERAL_INTEGER;
+
+  if(type1 == type2)
+    return type1;
+  
+  /* Second promotion is to xsd:decimal */
+  if(type1 == RASQAL_LITERAL_INTEGER)
+    type1=RASQAL_LITERAL_DECIMAL;
+  if(type2 == RASQAL_LITERAL_INTEGER)
+    type2=RASQAL_LITERAL_DECIMAL;
+
+  if(type1 == type2)
+    return type1;
+
+  /* Third/Fourth promotions are either to xsd:float or xsd:double */
+  if(type1 == RASQAL_LITERAL_FLOAT || type2 == RASQAL_LITERAL_FLOAT)
+    return RASQAL_LITERAL_FLOAT;
+
+  if(type1 == RASQAL_LITERAL_DOUBLE || type2 == RASQAL_LITERAL_DOUBLE)
+    return RASQAL_LITERAL_DOUBLE;
+
+  /* failed! */
+  return RASQAL_LITERAL_UNKNOWN;
+}
+
+
+/**
+ * rasqal_literal_get_rdf_term_type:
+ * @l: literal
+ *
+ * INTERNAL - Get the RDF term type of a literal
+ *
+ * Return value: type or RASQAL_LITERAL_UNKNOWN if cannot be an RDF term
+ */
+rasqal_literal_type
+rasqal_literal_get_rdf_term_type(rasqal_literal* l)
+{
+  rasqal_literal_type type;
+  type=(l->parent_type != RASQAL_LITERAL_UNKNOWN) ? l->parent_type : l->type;
+ 
+  /* squash literal datatypes into one type: RDF Literal */
+  if(type >= RASQAL_LITERAL_FIRST_XSD &&
+     type <= RASQAL_LITERAL_LAST_XSD)
+    type = RASQAL_LITERAL_STRING;
+  
+  if(type != RASQAL_LITERAL_URI &&
+     type != RASQAL_LITERAL_STRING &&
+     type != RASQAL_LITERAL_BLANK)
+    type=RASQAL_LITERAL_UNKNOWN;
+
+  return type;
+}
+
+
+static rasqal_literal*
+rasqal_new_literal_from_promotion(rasqal_literal* lit,
+                                  rasqal_literal_type type)
+{
+  rasqal_literal* new_lit=NULL;
+  int errori=0;
+  double d;
+  int i;
+  unsigned char *new_s=NULL;
+  const unsigned char* s;
+  size_t len;
+  
+  if(lit->type == type)
+    return rasqal_new_literal_from_literal(lit);
+
+  RASQAL_DEBUG3("promoting literal type %s to type %s\n", 
+                rasqal_literal_type_labels[lit->type],
+                rasqal_literal_type_labels[type]);
+
+  /* May not promote to non-numerics */
+  if(!rasqal_xsd_datatype_is_numeric(type)) {
+    RASQAL_DEBUG2("NOT promoting to non-numeric type %s\n", 
+                  rasqal_literal_type_labels[lit->type]);
+
+    if(type == RASQAL_LITERAL_STRING) {
+      s=rasqal_literal_as_string(lit);
+      len=strlen((const char*)s);
+      new_s=(unsigned char*)RASQAL_MALLOC(sstring, len+1);
+      if(new_s) {
+        strncpy((char*)new_s, (const char*)s, len+1);
+        return rasqal_new_string_literal(lit->world, new_s, NULL, NULL, NULL);
+      } else
+        return NULL;
+    }
+    return NULL;
+  }
+    
+  switch(type) {
+    case RASQAL_LITERAL_DECIMAL:
+      new_lit=rasqal_new_decimal_literal(lit->world, rasqal_literal_as_string(lit));
+      break;
+      
+    case RASQAL_LITERAL_DOUBLE:
+      d=rasqal_literal_as_floating(lit, &errori);
+      /* failure always means no match */
+      if(errori)
+        new_lit=NULL;
+      else
+        new_lit=rasqal_new_double_literal(lit->world, d);
+      break;
+      
+    case RASQAL_LITERAL_FLOAT:
+      d=rasqal_literal_as_floating(lit, &errori);
+      /* failure always means no match */
+      if(errori)
+        new_lit=NULL;
+      else
+        new_lit=rasqal_new_float_literal(lit->world, d);
+      break;
+      
+
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+      i=rasqal_literal_as_integer(lit, &errori);
+      /* failure always means no match */
+      if(errori)
+        new_lit=NULL;
+      else
+        new_lit=rasqal_new_integer_literal(lit->world, type, i);
+      break;
+    
+    case RASQAL_LITERAL_STRING:
+      s=rasqal_literal_as_string(lit);
+      len=strlen((const char*)s);
+      new_s=(unsigned char*)RASQAL_MALLOC(sstring, len+1);
+      if(new_s) {
+        strncpy((char*)new_s, (const char*)s, len+1);
+        new_lit=rasqal_new_string_literal(lit->world, new_s, NULL, NULL, NULL);
+      }
+      break;
+
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_DATETIME:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_VARIABLE:
+    default:
+      errori=1;
+      new_lit=NULL;
+  }
+
+#ifdef RASQAL_DEBUG
+  if(new_lit)
+    RASQAL_DEBUG4("promoted literal type %s to type %s, with value '%s'\n", 
+                  rasqal_literal_type_labels[new_lit->type],
+                  rasqal_literal_type_labels[type],
+                  rasqal_literal_as_string(new_lit));
+  else
+    RASQAL_DEBUG3("failed to promote literal type %s to type %s\n", 
+                  rasqal_literal_type_labels[lit->type],
+                  rasqal_literal_type_labels[type]);
+#endif
+
+  return new_lit;
+}  
+
+
+static int
+rasqal_literal_string_compare(rasqal_literal* l1, rasqal_literal* l2,
+                              int flags, int* error)
+{
+  if(l1->type != RASQAL_LITERAL_STRING ||
+     l2->type != RASQAL_LITERAL_STRING) {
+    if(error)
+      *error=0;
+    return 0;
+  }
+    
+  if(l1->language || l2->language) {
+    /* if either is null, the comparison fails */
+    if(!l1->language || !l2->language)
+      return 1;
+    if(rasqal_strcasecmp(l1->language, l2->language))
+      return 1;
+  }
+  
+  if(l1->datatype || l2->datatype) {
+    int result;
+    
+    /* there is no ordering between typed and plain literals:       
+       if either is NULL, do not compare but return an error
+       (also implies inequality) */
+    if(!l1->datatype || !l2->datatype) {
+      if(error)
+        *error=1;
+      return 0;
+    }
+#ifdef RAPTOR_V2_AVAILABLE
+    result = raptor_uri_compare_v2(l1->world->raptor_world_ptr, l1->datatype, l2->datatype);
+#else
+    result = raptor_uri_compare(l1->datatype, l2->datatype);
+#endif
+
+    if(result)
+      return result;
+  }
+  
+  if(flags & RASQAL_COMPARE_NOCASE)
+    return rasqal_strcasecmp((const char*)l1->string, (const char*)l2->string);
+  else
+    return strcmp((const char*)l1->string, (const char*)l2->string);
+}
+
+
+static rasqal_literal_type
+rasqal_literal_rdql_promote_calculate(rasqal_literal* l1, rasqal_literal* l2)
+{    
+  int seen_string=0;
+  int seen_int=0;
+  int seen_double=0;
+  int seen_boolean=0;
+  int i;
+  rasqal_literal *lits[2];
+  rasqal_literal_type type=RASQAL_LITERAL_UNKNOWN;
+
+  lits[0]=l1;
+  lits[1]=l2;
+
+  for(i=0; i<2; i++) {
+    switch(lits[i]->type) {
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_DECIMAL:
+      break;
+      
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_DATETIME:
+      seen_string++;
+      break;
+      
+    case RASQAL_LITERAL_BOOLEAN:
+      seen_boolean=1;
+      break;
+      
+    case RASQAL_LITERAL_INTEGER:
+      seen_int++;
+      break;
+      
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+      seen_double++;
+      break;
+      
+    case RASQAL_LITERAL_VARIABLE:
+      /* this case was dealt with elsewhere */
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Unknown literal type %d", lits[i]->type);
+    }
+  }
+
+  
+  if(lits[0]->type != lits[1]->type) {
+    type=seen_string ? RASQAL_LITERAL_STRING : RASQAL_LITERAL_INTEGER;
+    if((seen_int & seen_double) || (seen_int & seen_string))
+      type=RASQAL_LITERAL_DOUBLE;
+    if(seen_boolean & seen_string)
+      type=RASQAL_LITERAL_STRING;
+  } else
+    type=lits[0]->type;
+  
+  return type;
+}
+
+
+
+/**
+ * rasqal_literal_compare:
+ * @l1: #rasqal_literal first literal
+ * @l2: #rasqal_literal second literal
+ * @flags: comparison flags
+ * @error: pointer to error
+ *
+ * Compare two literals with type promotion.
+ * 
+ * The two literals are compared across their range.  If the types
+ * are not the same, they are promoted.  If one is a double or float, the
+ * other is promoted to double, otherwise for integers, otherwise
+ * to strings (all literals have a string value).
+ *
+ * The comparison returned is as for strcmp, first before second
+ * returns <0.  equal returns 0, and first after second returns >0.
+ * For URIs, the string value is used for the comparsion.
+ *
+ * flag bits affects comparisons:
+ *   RASQAL_COMPARE_NOCASE: use case independent string comparisons
+ *   RASQAL_COMPARE_XQUERY: use XQuery comparison and type promotion rules
+ *   RASQAL_COMPARE_RDF: use RDF term comparison
+ *   RASQAL_COMPARE_URI: allow comparison of URIs (typically for SPARQL ORDER)
+ * 
+ * If @error is not NULL, *error is set to non-0 on error
+ *
+ * Return value: <0, 0, or >0 as described above.
+ **/
+int
+rasqal_literal_compare(rasqal_literal* l1, rasqal_literal* l2, int flags,
+                       int *error)
+{
+  rasqal_literal *lits[2];
+  rasqal_literal* new_lits[2]; /* after promotions */
+  rasqal_literal_type type; /* target promotion type */
+  int i;
+  int result=0;
+  double d=0;
+  int promotion=0;
+  
+  if(error)
+    *error=0;
+
+  lits[0]=rasqal_literal_value(l1);
+  lits[1]=rasqal_literal_value(l2);
+
+  /* null literals */
+  if(!lits[0] || !lits[1]) {
+    /* if either is not NULL, the comparison fails */
+    if(lits[0] || lits[1]) {
+      if(error)
+        *error=1;
+    }
+    return 0;
+  }
+
+  new_lits[0]=NULL;
+  new_lits[1]=NULL;
+
+  RASQAL_DEBUG3("literal 0 type %s.  literal 1 type %s\n", 
+                rasqal_literal_type_labels[lits[0]->type],
+                rasqal_literal_type_labels[lits[1]->type]);
+  
+  if(flags & RASQAL_COMPARE_RDF) {
+    /* no promotion but compare as RDF terms; like rasqal_literal_as_node() */
+    rasqal_literal_type type0=rasqal_literal_get_rdf_term_type(lits[0]);
+    rasqal_literal_type type1=rasqal_literal_get_rdf_term_type(lits[1]);
+    int type_diff;
+    
+    if(type0 == RASQAL_LITERAL_UNKNOWN || type1 == RASQAL_LITERAL_UNKNOWN)
+      return 1;
+    type_diff=type0 - type1;
+    if(type_diff != 0) {
+      RASQAL_DEBUG2("RDF term literal returning type difference %d\n",
+                    type_diff);
+      return type_diff;
+    }
+    type=type1;
+  } else if(flags & RASQAL_COMPARE_XQUERY) { 
+    /* SPARQL / XQuery promotion rules */
+    rasqal_literal_type type0=lits[0]->type;
+    rasqal_literal_type type1=lits[1]->type;
+
+    RASQAL_DEBUG3("xquery literal compare types %s vs %s\n",
+                rasqal_literal_type_labels[type0],
+                rasqal_literal_type_labels[type1]);
+
+    type=rasqal_literal_promote_numerics(lits[0], lits[1], flags);
+    if(type == RASQAL_LITERAL_UNKNOWN) {
+      int type_diff;
+
+      /* no promotion but compare as RDF terms; like rasqal_literal_as_node() */
+      type0=rasqal_literal_get_rdf_term_type(lits[0]);
+      type1=rasqal_literal_get_rdf_term_type(lits[1]);
+      
+      if(type0 == RASQAL_LITERAL_UNKNOWN || type1 == RASQAL_LITERAL_UNKNOWN)
+        return 1;
+      type_diff=type0 - type1;
+      if(type_diff != 0) {
+        RASQAL_DEBUG2("RDF term literal returning type difference %d\n",
+                      type_diff);
+        return type_diff;
+      }
+      if(error)
+        *error=1;
+      return 0;
+    }
+    promotion=1;
+  } else {
+    /* RDQL promotion rules */
+    type=rasqal_literal_rdql_promote_calculate(lits[0], lits[1]);
+    promotion=1;
+  }
+
+#ifdef RASQAL_DEBUG
+  if(promotion)
+    RASQAL_DEBUG2("promoting to type %s\n", rasqal_literal_type_labels[type]);
+#endif
+
+  /* do promotions */
+  for(i=0; i<2; i++) {
+    if(promotion) {
+      new_lits[i]=rasqal_new_literal_from_promotion(lits[i], type);
+      if(!new_lits[i]) {
+        if(error)
+          *error=1;
+        goto done;
+      }
+    } else {
+      new_lits[i]=lits[i];
+    }
+  }
+
+
+  switch(type) {
+    case RASQAL_LITERAL_URI:
+      if(flags & RASQAL_COMPARE_URI)
+#ifdef RAPTOR_V2_AVAILABLE
+        result = raptor_uri_compare_v2(l1->world->raptor_world_ptr,
+                                       new_lits[0]->value.uri,
+                                       new_lits[1]->value.uri);
+#else
+        result = raptor_uri_compare(new_lits[0]->value.uri,
+                                    new_lits[1]->value.uri);
+#endif
+      else {
+        if(error)
+          *error=1;
+        return 0;
+      }
+      break;
+
+    case RASQAL_LITERAL_STRING:
+      result=rasqal_literal_string_compare(new_lits[0], new_lits[1],
+                                           flags, error);
+      if(*error)
+        result=1;
+      break;
+      
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_DATETIME:
+      if(flags & RASQAL_COMPARE_NOCASE)
+        result=rasqal_strcasecmp((const char*)new_lits[0]->string,
+                                 (const char*)new_lits[1]->string);
+      else
+        result=strcmp((const char*)new_lits[0]->string,
+                      (const char*)new_lits[1]->string);
+      break;
+
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+      result=new_lits[0]->value.integer - new_lits[1]->value.integer;
+      break;
+
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+      d=new_lits[0]->value.floating - new_lits[1]->value.floating;
+      result=(d > 0.0) ? 1: (d < 0.0) ? -1 : 0;
+      break;
+      
+    case RASQAL_LITERAL_DECIMAL:
+      result=rasqal_xsd_decimal_compare(new_lits[0]->value.decimal,
+                                        new_lits[1]->value.decimal);
+      break;
+
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_VARIABLE:
+    default:
+      RASQAL_FATAL2("Literal type %d cannot be compared", type);
+      result=0; /* keep some compilers happy */
+  }
+
+  done:
+  if(promotion) {
+    for(i=0; i<2; i++) {
+      if(new_lits[i])
+        rasqal_free_literal(new_lits[i]);
+    }
+  }
+  
+  return result;
+}
+
+
+/**
+ * rasqal_literal_string_equals:
+ * @l1: #rasqal_literal first literal
+ * @l2: #rasqal_literal second literal
+ * @error: pointer to error
+ *
+ * INTERNAL - Compare two typed literals
+ *
+ * Return value: non-0 if equal
+ */
+static int
+rasqal_literal_string_equals(rasqal_literal* l1, rasqal_literal* l2,
+                             int* error)
+{
+  int result=1;
+  raptor_uri* dt1=l1->datatype;
+  raptor_uri* dt2=l2->datatype;
+  raptor_uri* xsd_string_uri=rasqal_xsd_datatype_type_to_uri(l1->world, RASQAL_LITERAL_STRING);
+
+  if(l1->language || l2->language) {
+    /* if either is NULL, the comparison fails */
+    if(!l1->language || !l2->language)
+      return 0;
+    if(rasqal_strcasecmp(l1->language,l2->language))
+      return 0;
+  }
+
+  /* Treat typed literal "xx"^^xsd:string as plain literal "xx" 
+   * for purposes of equality.
+   */
+#ifdef RAPTOR_V2_AVAILABLE
+  if(dt1 && raptor_uri_equals_v2(l1->world->raptor_world_ptr, dt1, xsd_string_uri))
+    dt1 = NULL;
+  if(dt2 && raptor_uri_equals_v2(l1->world->raptor_world_ptr, dt2, xsd_string_uri))
+    dt2 = NULL;
+#else
+  if(dt1 && raptor_uri_equals(dt1, xsd_string_uri))
+    dt1 = NULL;
+  if(dt2 && raptor_uri_equals(dt2, xsd_string_uri))
+    dt2 = NULL;
+#endif
+
+  if(dt1 || dt2) {
+    /* if either is NULL - type error */
+    if(!dt1 || !dt2) {
+      if(error)
+        *error=1;
+      return 0;
+    }
+    /* if different - type error */
+    if(
+#ifdef RAPTOR_V2_AVAILABLE
+       !raptor_uri_equals_v2(l1->world->raptor_world_ptr, dt1, dt2)
+#else
+       !raptor_uri_equals(dt1, dt2)
+#endif
+       )
+    {
+      if(error)
+        *error=1;
+      return 0;
+    }
+    /* at this point the datatypes (URIs) are the same */
+    
+    /* If literals were both typed literals */
+    if(l1->type == RASQAL_LITERAL_STRING && l2->type == RASQAL_LITERAL_STRING) {
+      if(l1->string_len != l2->string_len) {
+        /* not-equal if lengths are different - cheap to compare this first */
+        return 0;
+      } else {
+        /* user-defined datatype - can only check for lexical identity */
+        result=!strcmp((const char*)l1->string, (const char*)l2->string);
+        if(!result) {
+          /* different strings but cannot tell if they are equal */
+          if(error)
+            *error=1;
+          return 0;
+        }
+      }
+    }
+  }
+
+  /* Finally check the lexical forms */
+
+  /* not-equal if lengths are different - cheaper to try this first */
+  if(l1->string_len != l2->string_len)
+    return 0;
+
+  result=!strcmp((const char*)l1->string, (const char*)l2->string);
+
+  return result;
+}
+
+
+/**
+ * rasqal_literal_equals:
+ * @l1: #rasqal_literal literal
+ * @l2: #rasqal_literal data literal
+ *
+ * Compare two literals with no type promotion.
+ * 
+ * If the l2 data literal value is a boolean, it will match
+ * the string "true" or "false" in the first literal l1.
+ *
+ * Return value: non-0 if equal
+ **/
+int
+rasqal_literal_equals(rasqal_literal* l1, rasqal_literal* l2)
+{
+  return rasqal_literal_equals_flags(l1, l2, 0, NULL);
+}
+
+
+/**
+ * rasqal_literal_equals_flags:
+ * @l1: #rasqal_literal literal
+ * @l2: #rasqal_literal data literal
+ * @flags: comparison flags
+ * @error: type error
+ *
+ * Compare two literals with optional type promotion.
+ * 
+ * flag bits affects equality:
+ *   RASQAL_COMPARE_XQUERY: use XQuery comparison and type promotion rules
+ *   RASQAL_COMPARE_RDF: use RDF term equality
+ *
+ * Return value: non-0 if equal
+ **/
+int
+rasqal_literal_equals_flags(rasqal_literal* l1, rasqal_literal* l2,
+                            int flags, int* error)
+{
+  rasqal_literal_type type;
+  rasqal_literal* l1_p=NULL;
+  rasqal_literal* l2_p=NULL;
+  int result=0;
+  int promotion=0;
+  
+  /* null literals */
+  if(!l1 || !l2) {
+    /* if either is not null, the comparison fails */
+    return (l1 || l2);
+  }
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG1(" ");
+  rasqal_literal_print(l1, stderr);
+  fputs( " to ", stderr);
+  rasqal_literal_print(l2, stderr);
+  fprintf(stderr, " with flags %d\n", flags);
+#endif
+
+  if(flags & RASQAL_COMPARE_RDF) {
+    /* no promotion but compare as RDF terms; like rasqal_literal_as_node() */
+    rasqal_literal_type type1=rasqal_literal_get_rdf_term_type(l1);
+    rasqal_literal_type type2=rasqal_literal_get_rdf_term_type(l2);
+
+    if(type1 == RASQAL_LITERAL_UNKNOWN || type2 == RASQAL_LITERAL_UNKNOWN ||
+       type1 != type2)
+      goto tidy;
+
+    type=type1;
+  } else if(flags & RASQAL_COMPARE_XQUERY) { 
+    /* SPARQL / XSD promotion rules */
+    if(l1->type != l2->type) {
+      type=rasqal_literal_promote_numerics(l1, l2, flags);
+      if(type == RASQAL_LITERAL_UNKNOWN) {
+        /* Cannot numeric promote - try RDF equality */
+        rasqal_literal_type type1=rasqal_literal_get_rdf_term_type(l1);
+        rasqal_literal_type type2=rasqal_literal_get_rdf_term_type(l2);
+        
+        if(type1 == RASQAL_LITERAL_UNKNOWN || type2 == RASQAL_LITERAL_UNKNOWN ||
+           type1 != type2)
+          goto tidy;
+
+        type=type1;
+      } else
+        promotion=1;
+#if RASQAL_DEBUG > 1
+      RASQAL_DEBUG4("xquery promoted literals types (%s, %s) to type %s\n", 
+                    rasqal_literal_type_labels[l1->type],
+                    rasqal_literal_type_labels[l2->type],
+                    rasqal_literal_type_labels[type]);
+#endif
+    } else
+      type=l1->type;
+  } else {
+    /* RDQL rules: compare as values with no promotion */
+    if(l1->type != l2->type) {
+      /* booleans can be compared to strings */
+      if(l2->type == RASQAL_LITERAL_BOOLEAN &&
+         l1->type == RASQAL_LITERAL_STRING)
+        result=!strcmp((const char*)l1->string, (const char*)l2->string);
+      goto tidy;
+    }
+    type=l1->type;
+  }
+
+  if(promotion) {
+    l1_p=rasqal_new_literal_from_promotion(l1, type);
+    if(l1_p)
+      l2_p=rasqal_new_literal_from_promotion(l2, type);
+    if(!l1_p || !l2_p) {
+      result=1;
+      goto tidy;
+    }
+  } else {
+    l1_p=l1;
+    l2_p=l2;
+  }
+  
+  switch(type) {
+    case RASQAL_LITERAL_URI:
+#ifdef RAPTOR_V2_AVAILABLE
+      result = raptor_uri_equals_v2(l1->world->raptor_world_ptr, l1_p->value.uri, l2_p->value.uri);
+#else
+      result = raptor_uri_equals(l1_p->value.uri, l2_p->value.uri);
+#endif
+      break;
+
+    case RASQAL_LITERAL_STRING:
+      result=rasqal_literal_string_equals(l1, l2, error);
+      break;
+
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_DATETIME:
+      /* FIXME this should be xsd:dateTime equality */
+      if(l1_p->string_len != l2_p->string_len)
+        /* not-equal if lengths are different - cheap to compare this first */
+        result=0;
+      else
+        result=!strcmp((const char*)l1_p->string, (const char*)l2_p->string);
+      break;
+      
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+      result=l1_p->value.integer == l2_p->value.integer;
+      break;
+
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+      result=l1_p->value.floating == l2_p->value.floating;
+      break;
+
+    case RASQAL_LITERAL_DECIMAL:
+      result=rasqal_xsd_decimal_equals(l1_p->value.decimal,
+                                       l2_p->value.decimal);
+      break;
+
+    case RASQAL_LITERAL_VARIABLE:
+      /* both are variables */
+      result=rasqal_literal_equals(l1_p->value.variable->value,
+                                   l2_p->value.variable->value);
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    default:
+      RASQAL_FATAL2("Literal type %d cannot be equaled", type);
+      result=0; /* keep some compilers happy */
+  }
+
+  tidy:
+  if(promotion) {
+    if(l1_p)
+      rasqal_free_literal(l1_p);
+    if(l2_p)
+      rasqal_free_literal(l2_p);
+  }
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("equals result %d\n", result);
+#endif
+
+  return result;
+}
+
+
+/*
+ * rasqal_literal_expand_qname - INTERNAL Expand any qname in a literal into a URI
+ * @user_data: #rasqal_query cast as void for use with raptor_sequence_foreach
+ * @l: #rasqal_literal literal
+ * 
+ * Expands any QName inside the literal using prefixes that are
+ * declared in the query that may not have been present when the
+ * literal was first declared.  Intended to be used standalone
+ * as well as with raptor_sequence_foreach which takes a function
+ * signature that this function matches.
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_literal_expand_qname(void *user_data, rasqal_literal *l)
+{
+  rasqal_query *rq=(rasqal_query *)user_data;
+
+  if(l->type == RASQAL_LITERAL_QNAME) {
+    /* expand a literal qname */
+    raptor_uri *uri=raptor_qname_string_to_uri(rq->namespaces,
+                                               l->string, l->string_len,
+                                               (raptor_simple_message_handler)rasqal_query_simple_error, rq);
+    if(!uri)
+      return 1;
+    RASQAL_FREE(cstring, (void*)l->string);
+    l->string=NULL;
+    l->type=RASQAL_LITERAL_URI;
+    l->value.uri=uri;
+  } else if (l->type == RASQAL_LITERAL_STRING) {
+    raptor_uri *uri;
+    
+    if(l->flags) {
+      /* expand a literal string datatype qname */
+      uri=raptor_qname_string_to_uri(rq->namespaces,
+                                     l->flags, 
+                                     strlen((const char*)l->flags),
+                                     (raptor_simple_message_handler)rasqal_query_simple_error, rq);
+      if(!uri)
+        return 1;
+      l->datatype=uri;
+      RASQAL_FREE(cstring, (void*)l->flags);
+      l->flags=NULL;
+
+      if(l->language && uri) {
+        RASQAL_FREE(cstring, (void*)l->language);
+        l->language=NULL;
+      }
+
+      if(rasqal_literal_string_to_native(l, (raptor_simple_message_handler)rasqal_query_simple_error, rq, 0)) {
+        rasqal_free_literal(l);
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+
+/*
+ * rasqal_literal_has_qname - INTERNAL Check if literal has a qname part
+ * @l: #rasqal_literal literal
+ * 
+ * Checks if any part ofthe literal has an unexpanded QName.
+ * 
+ * Return value: non-0 if a QName is present
+ **/
+int
+rasqal_literal_has_qname(rasqal_literal *l) {
+  return (l->type == RASQAL_LITERAL_QNAME) ||
+         (l->type == RASQAL_LITERAL_STRING && (l->flags));
+}
+
+
+/**
+ * rasqal_literal_as_node:
+ * @l: #rasqal_literal object
+ *
+ * Turn a literal into a new RDF string, URI or blank literal.
+ * 
+ * Return value: the new #rasqal_literal or NULL on failure
+ **/
+rasqal_literal*
+rasqal_literal_as_node(rasqal_literal* l)
+{
+  raptor_uri* dt_uri;
+  rasqal_literal* new_l=NULL;
+  
+  reswitch:
+  if(!l)
+    return NULL;
+  switch(l->type) {
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BLANK:
+      new_l=rasqal_new_literal_from_literal(l);
+      break;
+      
+    case RASQAL_LITERAL_VARIABLE:
+      l=l->value.variable->value;
+      goto reswitch;
+
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DECIMAL:
+    case RASQAL_LITERAL_DATETIME:
+      new_l=(rasqal_literal*)RASQAL_CALLOC(rasqal_literal, 1, sizeof(rasqal_literal));
+      if(new_l) {
+        new_l->usage=1;
+        new_l->world=l->world;
+        new_l->type=RASQAL_LITERAL_STRING;
+        new_l->string_len=l->string_len;
+        new_l->string=(unsigned char*)RASQAL_MALLOC(cstring, l->string_len+1);
+        if(!new_l->string) {
+          rasqal_free_literal(new_l);
+          return NULL; 
+        }
+        strncpy((char*)new_l->string, (const char*)l->string, l->string_len+1);
+        dt_uri=rasqal_xsd_datatype_type_to_uri(l->world, l->type);
+        if(!dt_uri) {
+          rasqal_free_literal(new_l);
+          return NULL;
+        }
+#ifdef RAPTOR_V2_AVAILABLE
+        new_l->datatype = raptor_uri_copy_v2(l->world->raptor_world_ptr, dt_uri);
+#else
+        new_l->datatype = raptor_uri_copy(dt_uri);
+#endif
+        new_l->flags=NULL;
+      }
+      break;
+      
+    case RASQAL_LITERAL_QNAME:
+      /* QNames should be gone by the time expression eval happens */
+
+    case RASQAL_LITERAL_PATTERN:
+      /* FALLTHROUGH */
+
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Literal type %d has no node value", l->type);
+  }
+  
+  return new_l;
+}
+
+
+/*
+ * rasqal_literal_ebv - INTERNAL Get the rasqal_literal effective boolean value
+ * @l: #rasqal_literal literal
+ * 
+ * Return value: non-0 if EBV is true, else false
+ **/
+int
+rasqal_literal_ebv(rasqal_literal* l) 
+{
+  rasqal_variable* v;
+  /* Result is true unless... */
+  int b=1;
+  
+  v=rasqal_literal_as_variable(l);
+  if(v) {
+    if(v->value == NULL) {
+      /* ... The operand is unbound */
+      b=0;
+      goto done;
+    }
+    l=v->value;
+  }
+  
+  if(l->type == RASQAL_LITERAL_BOOLEAN && !l->value.integer) {
+    /* ... The operand is an xs:boolean with a FALSE value. */
+    b=0;
+  } else if(l->type == RASQAL_LITERAL_STRING && 
+            !l->datatype && !l->string_len) {
+    /* ... The operand is a 0-length untyped RDF literal or xs:string. */
+    b=0;
+  } else if((l->type == RASQAL_LITERAL_INTEGER && !l->value.integer) ||
+            ((l->type == RASQAL_LITERAL_DOUBLE || 
+              l->type == RASQAL_LITERAL_FLOAT) &&
+             !l->value.floating)
+            ) {
+    /* ... The operand is any numeric type with a value of 0. */
+    b=0;
+  } else if(l->type == RASQAL_LITERAL_DECIMAL &&
+            rasqal_xsd_decimal_is_zero(l->value.decimal)) {
+    /* ... The operand is any numeric type with a value of 0 (decimal) */
+    b=0;
+  } else if((l->type == RASQAL_LITERAL_DOUBLE || 
+             l->type == RASQAL_LITERAL_FLOAT) &&
+            isnan(l->value.floating)
+            ) {
+    /* ... The operand is an xs:double or xs:float with a value of NaN */
+    b=0;
+  }
+  
+  done:
+  return b;
+}
+
+
+/*
+ * rasqal_literal_is_constant - INTERNAL Check if a literal is a constant
+ * @l: #rasqal_literal literal
+ * 
+ * Return value: non-0 if literal is a constant
+ **/
+int
+rasqal_literal_is_constant(rasqal_literal* l)
+{
+  switch(l->type) {
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_INTEGER:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DECIMAL:
+    case RASQAL_LITERAL_DATETIME:
+      return 1;
+
+    case RASQAL_LITERAL_VARIABLE:
+      return 0;
+
+    case RASQAL_LITERAL_UNKNOWN:
+    default:
+      RASQAL_FATAL2("Literal type %d cannot be checked for constant", l->type);
+      return 0; /* keep some compilers happy */
+  }
+}
+
+
+rasqal_formula*
+rasqal_new_formula(void) 
+{
+  return (rasqal_formula*)RASQAL_CALLOC(rasqal_formula, 1, sizeof(rasqal_formula));
+}
+
+void
+rasqal_free_formula(rasqal_formula* formula)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(formula, rasqal_formula);
+  
+  if(formula->triples)
+    raptor_free_sequence(formula->triples);
+  if(formula->value)
+    rasqal_free_literal(formula->value);
+  RASQAL_FREE(rasqal_formula, formula);
+}
+  
+
+void
+rasqal_formula_print(rasqal_formula* formula, FILE *stream)
+{
+  fputs("formula(triples=", stream);
+  if(formula->triples)
+    raptor_sequence_print(formula->triples, stream);
+  else
+    fputs("[]", stream);
+  fputs(", value=", stream);
+  if(formula->value)
+    rasqal_literal_print(formula->value, stream);
+  else
+    fputs("NULL", stream);
+  fputc(')', stream);
+}
+
+
+rasqal_formula*
+rasqal_formula_join(rasqal_formula* first_formula, 
+                    rasqal_formula* second_formula)
+{
+  if(!first_formula && !second_formula)
+    return NULL;
+
+  if(!first_formula)
+    return second_formula;
+  
+  if(!second_formula)
+    return first_formula;
+  
+  if(first_formula->triples || second_formula->triples) {
+    if(!first_formula->triples) {
+      first_formula->triples=second_formula->triples;
+      second_formula->triples=NULL;
+    } else if(second_formula->triples)
+      if(raptor_sequence_join(first_formula->triples, second_formula->triples)) {
+        rasqal_free_formula(first_formula);
+        first_formula=NULL;
+      }
+  }
+  rasqal_free_formula(second_formula);
+
+  return first_formula;
+}
+
+
+/**
+ * rasqal_literal_datatype:
+ * @l: #rasqal_literal object
+ *
+ * Get the datatype URI of a literal
+ *
+ * Return value: shared pointer to #raptor_uri of datatype or NULL on failure or no value
+ */
+raptor_uri*
+rasqal_literal_datatype(rasqal_literal* l)
+{
+  if(!l)
+    return NULL;
+  
+  if(l->type != RASQAL_LITERAL_VARIABLE)
+    return l->datatype;
+  return rasqal_literal_datatype(l->value.variable->value);
+}
+
+
+rasqal_literal*
+rasqal_literal_cast(rasqal_literal* l, raptor_uri* to_datatype, int flags, 
+                    int* error_p)
+{
+  raptor_uri* from_datatype=NULL;
+  const unsigned char *string=NULL;
+  unsigned char *new_string;
+  rasqal_literal* result=NULL;
+  rasqal_literal_type from_native_type;
+  rasqal_literal_type to_native_type;
+
+  l=rasqal_literal_value(l);
+  if(!l)
+    return NULL;
+
+  from_datatype=l->datatype;
+  from_native_type=l->type;
+
+  to_native_type=rasqal_xsd_datatype_uri_to_type(l->world, to_datatype);
+
+  if(from_native_type == to_native_type) {
+    /* cast to same type is always allowed */
+    return rasqal_new_literal_from_literal(l);
+
+  } else {
+    /* switch on FROM type to check YES/NO conversions and get the string */
+    switch(from_native_type) {
+      /* string */
+      case RASQAL_LITERAL_STRING:
+        string=l->string;
+        break;
+
+      /* XSD datatypes: RASQAL_LITERAL_FIRST_XSD to RASQAL_LITERAL_LAST_XSD */
+      case RASQAL_LITERAL_BOOLEAN:
+      case RASQAL_LITERAL_INTEGER:
+      case RASQAL_LITERAL_DOUBLE:
+      case RASQAL_LITERAL_FLOAT:
+      case RASQAL_LITERAL_DECIMAL:
+        /* XSD (boolean, integer, decimal, double, float) may NOT be
+         * cast to dateTime */
+        if(to_native_type == RASQAL_LITERAL_DATETIME) {
+          *error_p=1;
+          break;
+        }
+        string=l->string;
+        break;
+
+      case RASQAL_LITERAL_DATETIME:
+        string=l->string;
+        break;
+
+      /* SPARQL casts - FIXME */
+      case RASQAL_LITERAL_BLANK:
+      case RASQAL_LITERAL_PATTERN:
+      case RASQAL_LITERAL_QNAME:
+        string=l->string;
+        break;
+
+      case RASQAL_LITERAL_URI:
+        /* URI (IRI) May ONLY be cast to a string */
+        if(to_native_type != RASQAL_LITERAL_STRING) {
+          *error_p=1;
+          break;
+        }
+
+#ifdef RAPTOR_V2_AVAILABLE
+        string = raptor_uri_as_string_v2(l->world->raptor_world_ptr, l->value.uri);
+#else
+        string = raptor_uri_as_string(l->value.uri);
+#endif
+        break;
+
+      case RASQAL_LITERAL_VARIABLE:
+        /* fallthrough since rasqal_literal_value() handled this above */
+      case RASQAL_LITERAL_UNKNOWN:
+      default:
+        RASQAL_FATAL2("Literal type %d cannot be cast", l->type);
+        return NULL; /* keep some compilers happy */
+    }
+
+    if(to_native_type == RASQAL_LITERAL_DATETIME) {
+      /* XSD dateTime may ONLY be cast from string (cast from dateTime
+       * is checked above)
+       */
+      if(from_native_type != RASQAL_LITERAL_STRING) {
+        *error_p=1;
+      }
+    }
+
+    if(*error_p)
+      return NULL;
+
+  }
+  
+
+  /* switch on the TO type to check MAYBE conversions */
+
+#ifdef RAPTOR_V2_AVAILABLE
+  RASQAL_DEBUG4("CAST from \"%s\" type %s to type %s\n",
+                string, 
+                from_datatype ? (const char*)raptor_uri_as_string_v2(l->world->raptor_world_ptr, from_datatype) : "(NONE)",
+                raptor_uri_as_string_v2(l->world->raptor_world_ptr, to_datatype));
+#else
+  RASQAL_DEBUG4("CAST from \"%s\" type %s to type %s\n",
+                string, 
+                from_datatype ? (const char*)raptor_uri_as_string(from_datatype) : "(NONE)",
+                raptor_uri_as_string(to_datatype));
+#endif
+  
+  if(!rasqal_xsd_datatype_check(to_native_type, string, flags)) {
+    *error_p=1;
+    RASQAL_DEBUG3("Illegal cast to type %s string '%s'",
+                  rasqal_xsd_datatype_label(to_native_type), string);
+    return NULL;
+  }
+
+  new_string=(unsigned char*)RASQAL_MALLOC(string, 
+                                           strlen((const char*)string)+1);
+  if(!new_string) {
+    *error_p=1;
+    return NULL;
+  }
+  strcpy((char*)new_string, (const char*)string);
+#ifdef RAPTOR_V2_AVAILABLE
+  to_datatype = raptor_uri_copy_v2(l->world->raptor_world_ptr, to_datatype);
+#else
+  to_datatype = raptor_uri_copy(to_datatype);  
+#endif
+  
+  result=rasqal_new_string_literal(l->world, new_string, NULL, to_datatype, NULL);
+  if(!result)
+    *error_p=1;
+  return result;
+}
+
+
+/**
+ * rasqal_literal_value:
+ * @l: #rasqal_literal object
+ *
+ * Get the literal value looking up any variables needed
+ *
+ * Return value: literal value or NULL if has no value
+ */
+rasqal_literal*
+rasqal_literal_value(rasqal_literal* l)
+{
+  while(l) {
+    if(l->type != RASQAL_LITERAL_VARIABLE)
+      break;
+
+    l=l->value.variable->value;
+  }
+  
+  return l;
+}
+
+
+int
+rasqal_literal_is_numeric(rasqal_literal* literal)
+{
+  return (rasqal_xsd_datatype_is_numeric(literal->type) ||
+          rasqal_xsd_datatype_is_numeric(literal->parent_type));
+}
+
+
+rasqal_literal*
+rasqal_literal_add(rasqal_literal* l1, rasqal_literal* l2, int *error_p)
+{
+  int i;
+  double d;
+  rasqal_xsd_decimal* dec;
+  int error=0;
+  rasqal_literal_type type;
+  rasqal_literal* l1_p=NULL;
+  rasqal_literal* l2_p=NULL;
+  int flags=0;
+  rasqal_literal* result=NULL;
+  
+  type=rasqal_literal_promote_numerics(l1, l2, flags);
+  switch(type) {
+    case RASQAL_LITERAL_INTEGER:
+      i=rasqal_literal_as_integer(l1, &error);
+      if(error)
+        break;
+      i=i + rasqal_literal_as_integer(l2, &error);
+      if(error)
+        break;
+
+      result=rasqal_new_integer_literal(l1->world, RASQAL_LITERAL_INTEGER, i);
+      break;
+      
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DOUBLE:
+      d=rasqal_literal_as_floating(l1, &error);
+      if(error)
+        break;
+      d=d + rasqal_literal_as_floating(l2, &error);
+      if(error)
+        break;
+
+      result=rasqal_new_numeric_literal(l1->world, type, d);
+      break;
+      
+    case RASQAL_LITERAL_DECIMAL:
+      l1_p=rasqal_new_literal_from_promotion(l1, type);
+      if(l1_p)
+        l2_p=rasqal_new_literal_from_promotion(l2, type);
+      if(l1_p && l2_p) {
+        dec=rasqal_new_xsd_decimal();
+        if(rasqal_xsd_decimal_add(dec, l1_p->value.decimal,
+                                  l2_p->value.decimal)) {
+          error=1;
+          rasqal_free_xsd_decimal(dec);
+        } else
+          result=rasqal_new_decimal_literal_from_decimal(l1->world, NULL, dec);
+      }
+      break;
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DATETIME:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_VARIABLE:
+    default:
+      error=1;
+      break;
+  }
+
+  if(error) {
+    if(error_p)
+      *error_p=1;
+  }
+  
+  if(l1_p)
+    rasqal_free_literal(l1_p);
+  if(l2_p)
+    rasqal_free_literal(l2_p);
+
+  return result;
+}
+
+
+rasqal_literal*
+rasqal_literal_subtract(rasqal_literal* l1, rasqal_literal* l2, int *error_p)
+{
+  int i;
+  double d;
+  rasqal_xsd_decimal* dec;
+  int error=0;
+  rasqal_literal_type type;
+  rasqal_literal* l1_p=NULL;
+  rasqal_literal* l2_p=NULL;
+  int flags=0;
+  rasqal_literal* result=NULL;
+  
+  type=rasqal_literal_promote_numerics(l1, l2, flags);
+  switch(type) {
+    case RASQAL_LITERAL_INTEGER:
+      i=rasqal_literal_as_integer(l1, &error);
+      if(error)
+        break;
+      i=i - rasqal_literal_as_integer(l2, &error);
+      if(error)
+        break;
+
+      result=rasqal_new_integer_literal(l1->world, RASQAL_LITERAL_INTEGER, i);
+      break;
+      
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DOUBLE:
+      d=rasqal_literal_as_floating(l1, &error);
+      if(error)
+        break;
+      d=d - rasqal_literal_as_floating(l2, &error);
+      if(error)
+        break;
+
+      result=rasqal_new_numeric_literal(l1->world, type, d);
+      break;
+      
+    case RASQAL_LITERAL_DECIMAL:
+      l1_p=rasqal_new_literal_from_promotion(l1, type);
+      if(l1_p)
+        l2_p=rasqal_new_literal_from_promotion(l2, type);
+      if(l1_p && l2_p) {
+        dec=rasqal_new_xsd_decimal();
+        if(rasqal_xsd_decimal_subtract(dec, l1_p->value.decimal,
+                                       l2_p->value.decimal)) {
+          error=1;
+          rasqal_free_xsd_decimal(dec);
+        } else
+          result=rasqal_new_decimal_literal_from_decimal(l1->world, NULL, dec);
+      }
+      break;
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DATETIME:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_VARIABLE:
+    default:
+      error=1;
+      break;
+  }
+
+  if(error) {
+    if(error_p)
+      *error_p=1;
+  }
+  
+  if(l1_p)
+    rasqal_free_literal(l1_p);
+  if(l2_p)
+    rasqal_free_literal(l2_p);
+
+  return result;
+}
+
+
+rasqal_literal*
+rasqal_literal_multiply(rasqal_literal* l1, rasqal_literal* l2, int *error_p)
+{
+  int i;
+  double d;
+  rasqal_xsd_decimal* dec;
+  int error=0;
+  rasqal_literal_type type;
+  rasqal_literal* l1_p=NULL;
+  rasqal_literal* l2_p=NULL;
+  int flags=0;
+  rasqal_literal* result=NULL;
+  
+  type=rasqal_literal_promote_numerics(l1, l2, flags);
+  switch(type) {
+    case RASQAL_LITERAL_INTEGER:
+      i=rasqal_literal_as_integer(l1, &error);
+      if(error)
+        break;
+      i=i * rasqal_literal_as_integer(l2, &error);
+      if(error)
+        break;
+
+      result=rasqal_new_integer_literal(l1->world, RASQAL_LITERAL_INTEGER, i);
+      break;
+      
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DOUBLE:
+      d=rasqal_literal_as_floating(l1, &error);
+      if(error)
+        break;
+      d=d * rasqal_literal_as_floating(l2, &error);
+      if(error)
+        break;
+
+      result=rasqal_new_numeric_literal(l1->world, type, d);
+      break;
+      
+    case RASQAL_LITERAL_DECIMAL:
+      l1_p=rasqal_new_literal_from_promotion(l1, type);
+      if(l1_p)
+        l2_p=rasqal_new_literal_from_promotion(l2, type);
+      if(l1_p && l2_p) {
+        dec=rasqal_new_xsd_decimal();
+        if(rasqal_xsd_decimal_multiply(dec, l1_p->value.decimal,
+                                       l2_p->value.decimal)) {
+          error=1;
+          rasqal_free_xsd_decimal(dec);
+        } else
+          result=rasqal_new_decimal_literal_from_decimal(l1->world, NULL, dec);
+      }
+      break;
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DATETIME:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_VARIABLE:
+    default:
+      error=1;
+      break;
+  }
+
+  if(error) {
+    if(error_p)
+      *error_p=1;
+  }
+  
+  if(l1_p)
+    rasqal_free_literal(l1_p);
+  if(l2_p)
+    rasqal_free_literal(l2_p);
+
+  return result;
+}
+
+
+rasqal_literal*
+rasqal_literal_divide(rasqal_literal* l1, rasqal_literal* l2, int *error_p)
+{
+  int i1, i2;
+  double d1, d2;
+  rasqal_xsd_decimal* dec;
+  int error=0;
+  rasqal_literal_type type;
+  rasqal_literal* l1_p=NULL;
+  rasqal_literal* l2_p=NULL;
+  int flags=0;
+  rasqal_literal* result=NULL;
+  
+  type=rasqal_literal_promote_numerics(l1, l2, flags);
+  switch(type) {
+    case RASQAL_LITERAL_INTEGER:
+      i2=rasqal_literal_as_integer(l2, &error);
+      if(!i2)
+        error=1;
+      if(error)
+        break;
+      i1=rasqal_literal_as_integer(l1, &error);
+      if(error)
+        break;
+      i1=i1 / i2;
+      if(error)
+        break;
+
+      result=rasqal_new_integer_literal(l1->world, RASQAL_LITERAL_INTEGER, i1);
+      break;
+      
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DOUBLE:
+      d2=rasqal_literal_as_floating(l2, &error);
+      if(!d2)
+        error=1;
+      if(error)
+        break;
+      d1=rasqal_literal_as_floating(l1, &error);
+      if(error)
+        break;
+      d1=d1 / d2;
+      if(error)
+        break;
+
+      result=rasqal_new_numeric_literal(l1->world, type, d1);
+      break;
+      
+    case RASQAL_LITERAL_DECIMAL:
+      l1_p=rasqal_new_literal_from_promotion(l1, type);
+      if(l1_p)
+        l2_p=rasqal_new_literal_from_promotion(l2, type);
+      if(l1_p && l2_p) {
+        dec=rasqal_new_xsd_decimal();
+        if(rasqal_xsd_decimal_add(dec, l1_p->value.decimal,
+                                  l2_p->value.decimal)) {
+          error=1;
+          rasqal_free_xsd_decimal(dec);
+        } else
+          result=rasqal_new_decimal_literal_from_decimal(l1->world, NULL, dec);
+      }
+      break;
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DATETIME:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_VARIABLE:
+    default:
+      error=1;
+      break;
+  }
+
+  if(error) {
+    if(error_p)
+      *error_p=1;
+  }
+  
+  if(l1_p)
+    rasqal_free_literal(l1_p);
+  if(l2_p)
+    rasqal_free_literal(l2_p);
+
+  return result;
+}
+
+
+rasqal_literal*
+rasqal_literal_negate(rasqal_literal* l, int *error_p)
+{
+  int i;
+  double d;
+  rasqal_xsd_decimal* dec;
+  int error=0;
+  rasqal_literal* result=NULL;
+  
+  switch(l->type) {
+    case RASQAL_LITERAL_INTEGER:
+      i=rasqal_literal_as_integer(l, &error);
+      if(error)
+        break;
+      i= -i;
+      result=rasqal_new_integer_literal(l->world, RASQAL_LITERAL_INTEGER, i);
+      break;
+      
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DOUBLE:
+      d=rasqal_literal_as_floating(l, &error);
+      if(!d)
+        error=1;
+      d= -d;
+      result=rasqal_new_numeric_literal(l->world, l->type, d);
+      break;
+      
+    case RASQAL_LITERAL_DECIMAL:
+      dec=rasqal_new_xsd_decimal();
+      if(rasqal_xsd_decimal_negate(dec, l->value.decimal)) {
+        error=1;
+        rasqal_free_xsd_decimal(dec);
+      } else
+        result=rasqal_new_decimal_literal_from_decimal(l->world, NULL, dec);
+      break;
+      
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_BLANK:
+    case RASQAL_LITERAL_URI:
+    case RASQAL_LITERAL_STRING:
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DATETIME:
+    case RASQAL_LITERAL_PATTERN:
+    case RASQAL_LITERAL_QNAME:
+    case RASQAL_LITERAL_VARIABLE:
+    default:
+      error=1;
+      break;
+  }
+
+  if(error) {
+    if(error_p)
+      *error_p=1;
+  }
+  
+  return result;
+}
diff --git a/src/rasqal/rasqal_map.c b/src/rasqal/rasqal_map.c
new file mode 100644
index 0000000..80dfa87
--- /dev/null
+++ b/src/rasqal/rasqal_map.c
@@ -0,0 +1,319 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_map.c - Rasqal simple Key:Value Map with duplicates allowed
+ *
+ * Copyright (C) 2005-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2005-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+struct rasqal_map_node_s
+{
+  struct rasqal_map_s* map;
+  struct rasqal_map_node_s* prev;
+  struct rasqal_map_node_s* next;
+  void* key;
+  void* value;
+};
+
+struct rasqal_map_s {
+  struct rasqal_map_node_s* root;
+  rasqal_compare_fn* compare;
+  void *compare_user_data;
+  rasqal_compare_free_user_data_fn* free_compare_data;
+  rasqal_kv_free_fn* free;
+  raptor_sequence_print_handler* print_key;
+  raptor_sequence_print_handler* print_value;
+  int allow_duplicates;
+};
+
+typedef struct rasqal_map_node_s rasqal_map_node;
+
+
+static rasqal_map_node*
+rasqal_new_map_node(rasqal_map* map, void *key, void *value)
+{
+  rasqal_map_node *node;
+  node=(rasqal_map_node*)RASQAL_CALLOC(rasqal_map_node, 1, sizeof(rasqal_map_node));
+  if(!node)
+    return NULL;
+  node->map=map;
+  node->key=key;
+  node->value=value;
+  return node;
+}
+
+
+static void
+rasqal_free_map_node(rasqal_map_node *node, rasqal_kv_free_fn* free_fn) 
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(node, rasqal_map_node);
+  
+  if(node->prev)
+    rasqal_free_map_node(node->prev, free_fn);
+  if(node->next)
+    rasqal_free_map_node(node->next, free_fn);
+
+  free_fn(node->key, node->value);
+
+  RASQAL_FREE(rasqal_map_node, node);
+}
+
+
+/**
+ * rasqal_new_map:
+ * @compare_fn: comparison function for keys
+ * @compare_user_data: user data pointer for @compare_fn
+ * @free_compare_data_fn: function to free @compare_user_data once done
+ * @free_fn: free function for (key, value) pair
+ * @print_key_fn: print a key function (or NULL)
+ * @print_value_fn: print a value function (or NULL)
+ * @flags: non-0 to allow duplicates
+ *
+ * Constructor - Create a (key:value) map.
+ * 
+ * Return value: a new #rasqal_map or NULL on failure
+ **/
+rasqal_map*
+rasqal_new_map(rasqal_compare_fn* compare_fn,
+               void *compare_user_data,
+               rasqal_compare_free_user_data_fn* free_compare_data_fn,
+               rasqal_kv_free_fn* free_fn,
+               raptor_sequence_print_handler* print_key_fn,
+               raptor_sequence_print_handler* print_value_fn,
+               int flags)
+{
+  rasqal_map *map;
+  map = (rasqal_map*)RASQAL_CALLOC(rasqal_map, 1, sizeof(rasqal_map));
+  if(!map) {
+    if(free_compare_data_fn)
+      free_compare_data_fn(compare_user_data);
+    return NULL;
+  }
+
+  map->compare = compare_fn;
+  map->compare_user_data = compare_user_data;
+  map->free_compare_data = free_compare_data_fn;
+  map->free = free_fn;
+  map->print_key = print_key_fn;
+  map->print_value = print_value_fn;
+  map->allow_duplicates = flags;
+  
+  return map;
+}
+
+
+/**
+ * rasqal_free_map:
+ * @map: the #rasqal_map to free
+ *
+ * Destructor - Destroy a (key:value) map.
+ * 
+ **/
+void
+rasqal_free_map(rasqal_map *map)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(map, rasqal_map);
+  
+  if(map->root)
+    rasqal_free_map_node(map->root, map->free);
+
+  if(map->free_compare_data)
+    map->free_compare_data(map->compare_user_data);
+
+  RASQAL_FREE(rasqal_map, map);
+}
+
+
+static int
+rasqal_map_node_add_kv(rasqal_map_node* node, void *key, void *value) 
+{
+  rasqal_map *map = node->map;
+  int result;
+
+  result = map->compare(map->compare_user_data, &key, &node->key);
+  if(result < 0) {
+    if(node->prev)
+      return rasqal_map_node_add_kv(node->prev, key, value);
+    node->prev = rasqal_new_map_node(map, key, value);
+    return node->prev ? 0 : -1;
+  } else if(!result) {
+    if(!node->map->allow_duplicates) {
+      /* duplicate and not allowed */
+      return 1;
+    }
+    /* duplicate, fall through  */
+  } 
+
+  /* result > 0 */
+  if(node->next)
+    return rasqal_map_node_add_kv(node->next, key, value);
+
+  node->next = rasqal_new_map_node(map, key, value);
+  return node->next ? 0 : -1;
+}
+
+
+/**
+ * rasqal_map_add_kv:
+ * @map: #rasqal_map adding to
+ * @key: key data
+ * @value: value data (or NULL)
+ *
+ * Add a (key, value) pair to the map.
+ * 
+ * Return value: non-0 on failure including adding a duplicate.
+ **/
+int
+rasqal_map_add_kv(rasqal_map* map, void* key, void *value)
+{
+  if(!map->root) {
+    map->root=rasqal_new_map_node(map, key, value);
+    return map->root ? 0 : -1;
+  }
+  
+  return rasqal_map_node_add_kv(map->root, key, value);
+}
+
+
+#define SPACES_LENGTH 80
+static const char rasqal_map_node_spaces[SPACES_LENGTH+1]="                                                                                ";
+
+
+static void
+rasqal_map_node_write_indent(FILE *fh, int indent) 
+{
+  while(indent > 0) {
+    int sp=(indent > SPACES_LENGTH) ? SPACES_LENGTH : indent;
+    (void)fwrite(rasqal_map_node_spaces, sizeof(char), sp, fh);
+    indent -= sp;
+  }
+}
+
+  
+
+static void
+rasqal_map_node_visit(rasqal_map_node* node, 
+                      rasqal_map_visit_fn fn, void *user_data)
+{
+  if(node->prev)
+    rasqal_map_node_visit(node->prev, fn, user_data);
+  fn(node->key, node->value, user_data);
+  if(node->next)
+    rasqal_map_node_visit(node->next, fn, user_data);
+}
+
+
+/**
+ * rasqal_map_visit:
+ * @map: the #rasqal_map to visit
+ * @fn: user function to call with key, value and @user_data
+ * @user_data: user data to pass to visit function
+ *
+ * Walk all entries in a (key:value) map.
+ * 
+ **/
+void
+rasqal_map_visit(rasqal_map* map, rasqal_map_visit_fn fn, void *user_data)
+{
+  if(map->root)
+    rasqal_map_node_visit(map->root, fn, user_data);
+}
+
+
+struct print_info 
+{
+  rasqal_map* map;
+  FILE *fh;
+  int indent;
+};
+  
+
+static void 
+rasqal_map_node_print_visit(void *key, void *value, void *user_data)
+{
+  struct print_info* pi=(struct print_info*)user_data;
+  FILE* fh;
+  int indent;
+  
+  fh=pi->fh;
+  indent=pi->indent;
+
+  rasqal_map_node_write_indent(fh, indent);
+  fputs("{key: ", fh);
+  if(!key)
+    fputs("NULL", fh);
+  else if(pi->map->print_key)
+    pi->map->print_key(key, fh);
+  else
+    fprintf(fh, "%p", key);
+
+  fputs(", value: ", fh);
+
+  if(!value)
+    fputs("NULL", fh);
+  else if(pi->map->print_value)
+    pi->map->print_value(value, fh);
+  else
+    fprintf(fh, "%p", value);
+
+  fputs("}\n", fh);
+}
+
+
+/**
+ * rasqal_map_print:
+ * @map: #rasqal_map to print
+ * @fh: FILE handle to write to.
+ *
+ * Print a (key:value) map in a debug format.
+ * 
+ **/
+void
+rasqal_map_print(rasqal_map* map, FILE* fh)
+{
+  fprintf(fh, "map duplicates=%s {\n", map->allow_duplicates ? "yes" : "no");
+  if(map->root) {
+    struct print_info pi;
+    pi.map=map;
+    pi.fh=fh;
+    pi.indent=2;
+    rasqal_map_visit(map, rasqal_map_node_print_visit, &pi);
+  }
+  
+  fputs("}\n", fh);
+}
diff --git a/src/rasqal/rasqal_query.c b/src/rasqal/rasqal_query.c
new file mode 100644
index 0000000..65f1ad6
--- /dev/null
+++ b/src/rasqal/rasqal_query.c
@@ -0,0 +1,2382 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_query.c - Rasqal RDF Query
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+/**
+ *
+ * Query Class Internals
+ *
+ * This is the main Rasqal class for constructing RDF graph queries
+ * from a syntax or by API, preparing them for execution with a query
+ * execution and executing them to return a result set.
+ *
+ * Queries are constructed from a syntax in some query language
+ * syntax and build an RDF query API structure based on triple
+ * patterns, filter expressions, graph patterns above them operating
+ * over a set of graphs.
+ *
+ * This class does not deal with manipulating result sets which are
+ * handled by the #rasqal_query_results and methods on it although
+ * rasqal_query_execute() does return a newly constructed result
+ * object.
+ *
+ * It also does not deal with executing a query which is handled by
+ * #rasqal_query_execution_factory instances that have their own
+ * simpler API.
+ *
+ */
+
+#define DEBUG_FH stderr
+
+#if 0
+#undef RASQAL_NO_GP_MERGE
+#else
+#define RASQAL_NO_GP_MERGE 1
+#endif
+
+
+static int rasqal_query_add_query_result(rasqal_query* query, rasqal_query_results* query_results);
+static int rasqal_query_write_sparql_20060406(raptor_iostream *iostr, rasqal_query* query, raptor_uri *base_uri);
+
+
+/**
+ * rasqal_new_query:
+ * @world: rasqal_world object
+ * @name: the query language name (or NULL)
+ * @uri: #raptor_uri language uri (or NULL)
+ *
+ * Constructor - create a new rasqal_query object.
+ *
+ * A query language can be named or identified by a URI, either
+ * of which is optional.  The default query language will be used
+ * if both are NULL.  rasqal_languages_enumerate returns
+ * information on the known names, labels and URIs.
+ *
+ * Return value: a new #rasqal_query object or NULL on failure
+ */
+rasqal_query*
+rasqal_new_query(rasqal_world *world, const char *name,
+                 const unsigned char *uri)
+{
+  rasqal_query_language_factory* factory;
+  rasqal_query* query;
+#ifndef RAPTOR_V2_AVAILABLE
+  const raptor_uri_handler *uri_handler;
+  void *uri_context;
+#endif
+
+  factory = rasqal_get_query_language_factory(world, name, uri);
+  if(!factory)
+    return NULL;
+
+  query = (rasqal_query*)RASQAL_CALLOC(rasqal_query, 1, sizeof(rasqal_query));
+  if(!query)
+    return NULL;
+  
+  /* set usage first to 1 so we can clean up with rasqal_free_query() on error */
+  query->usage = 1;
+
+  query->world = world;
+  
+  query->factory = factory;
+
+  query->limit = -1;
+  query->offset = -1;
+
+  query->genid_counter = 1;
+
+  query->context = (char*)RASQAL_CALLOC(rasqal_query_context, 1,
+                                        factory->context_length);
+  if(!query->context)
+    goto tidy;
+  
+#ifdef RAPTOR_V2_AVAILABLE
+  query->namespaces = raptor_new_namespaces_v2(world->raptor_world_ptr,
+                                               (raptor_simple_message_handler)rasqal_query_simple_error,
+                                               query,
+                                               0);
+#else
+  raptor_uri_get_handler(&uri_handler, &uri_context);
+  query->namespaces = raptor_new_namespaces(uri_handler, uri_context,
+                                            (raptor_simple_message_handler)rasqal_query_simple_error,
+                                            query,
+                                            0);
+#endif
+  if(!query->namespaces)
+    goto tidy;
+
+  query->vars_table = rasqal_new_variables_table(query->world);
+  if(!query->vars_table)
+    goto tidy;
+
+  query->triples = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print);
+  if(!query->triples)
+    goto tidy;
+  
+  query->prefixes = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_prefix, (raptor_sequence_print_handler*)rasqal_prefix_print);
+  if(!query->prefixes)
+    goto tidy;
+
+  query->data_graphs = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_data_graph, (raptor_sequence_print_handler*)rasqal_data_graph_print);
+  if(!query->data_graphs)
+    goto tidy;
+
+  query->results = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_query_results_remove_query_reference, NULL);
+  if(!query->results)
+    goto tidy;
+
+  if(factory->init(query, name))
+    goto tidy;
+  
+  return query;
+
+  tidy:
+  rasqal_free_query(query);
+  return NULL;
+}
+
+
+
+/**
+ * rasqal_free_query:
+ * @query: #rasqal_query object
+ * 
+ * Destructor - destroy a #rasqal_query object.
+ **/
+void
+rasqal_free_query(rasqal_query* query) 
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(query, rasqal_query);
+  
+  if(--query->usage)
+    return;
+  
+  if(query->factory)
+    query->factory->terminate(query);
+
+  if(query->context)
+    RASQAL_FREE(rasqal_query_context, query->context);
+
+  if(query->namespaces)
+    raptor_free_namespaces(query->namespaces);
+
+  if(query->base_uri)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(query->world->raptor_world_ptr, query->base_uri);
+#else
+    raptor_free_uri(query->base_uri);
+#endif
+
+  if(query->query_string)
+    RASQAL_FREE(cstring, query->query_string);
+
+  if(query->data_graphs)
+    raptor_free_sequence(query->data_graphs);
+  if(query->selects)
+    raptor_free_sequence(query->selects);
+  if(query->describes)
+    raptor_free_sequence(query->describes);
+
+  if(query->triples)
+    raptor_free_sequence(query->triples);
+  if(query->optional_triples)
+    raptor_free_sequence(query->optional_triples);
+  if(query->constructs)
+    raptor_free_sequence(query->constructs);
+  if(query->prefixes)
+    raptor_free_sequence(query->prefixes);
+  if(query->results)
+    raptor_free_sequence(query->results);
+
+  if(query->variables_declared_in)
+    RASQAL_FREE(intarray, query->variables_declared_in);
+
+  if(query->query_graph_pattern)
+    rasqal_free_graph_pattern(query->query_graph_pattern);
+
+  if(query->order_conditions_sequence)
+    raptor_free_sequence(query->order_conditions_sequence);
+
+  if(query->group_conditions_sequence)
+    raptor_free_sequence(query->group_conditions_sequence);
+
+  if(query->graph_patterns_sequence)
+    raptor_free_sequence(query->graph_patterns_sequence);
+
+  if(query->query_results_formatter_name)
+    RASQAL_FREE(cstring, query->query_results_formatter_name);
+
+  /* Do this last since most everything above could refer to a variable */
+  if(query->vars_table)
+    rasqal_free_variables_table(query->vars_table);
+  RASQAL_FREE(rasqal_query, query);
+}
+
+
+/* Methods */
+
+/**
+ * rasqal_query_get_name:
+ * @query: #rasqal_query query object
+ *
+ * Get a short name for the query language.
+ *
+ * Return value: shared string label value
+ **/
+const char*
+rasqal_query_get_name(rasqal_query* query)
+{
+  return query->factory->name;
+}
+
+
+/**
+ * rasqal_query_get_label:
+ * @query: #rasqal_query query object
+ *
+ * Get a readable label for the query language.
+ *
+ * Return value: shared string label value
+ **/
+const char*
+rasqal_query_get_label(rasqal_query* query)
+{
+  return query->factory->label;
+}
+
+
+/**
+ * rasqal_query_set_fatal_error_handler:
+ * @query: the query
+ * @user_data: user data to pass to function
+ * @handler: pointer to the function
+ *
+ * Set the query error handling function.
+ * 
+ * The function will receive callbacks when the query fails.
+ * 
+ **/
+void
+rasqal_query_set_fatal_error_handler(rasqal_query* query, void *user_data,
+                                     raptor_message_handler handler)
+{
+  raptor_error_handlers* error_handlers;
+  if(!query || !query->world)
+    return;
+
+  error_handlers = &query->world->error_handlers;
+  
+  error_handlers->handlers[RAPTOR_LOG_LEVEL_FATAL].user_data = user_data;
+  error_handlers->handlers[RAPTOR_LOG_LEVEL_FATAL].handler = handler;
+}
+
+
+/**
+ * rasqal_query_set_error_handler:
+ * @query: the query
+ * @user_data: user data to pass to function
+ * @handler: pointer to the function
+ *
+ * Set the query error handling function.
+ * 
+ * The function will receive callbacks when the query fails.
+ * 
+ **/
+void
+rasqal_query_set_error_handler(rasqal_query* query, void *user_data,
+                               raptor_message_handler handler)
+{
+  raptor_error_handlers* error_handlers;
+  if(!query || !query->world)
+    return;
+
+  error_handlers = &query->world->error_handlers;
+  
+  error_handlers->handlers[RAPTOR_LOG_LEVEL_ERROR].user_data = user_data;
+  error_handlers->handlers[RAPTOR_LOG_LEVEL_ERROR].handler = handler;
+}
+
+
+/**
+ * rasqal_query_set_warning_handler:
+ * @query: the query
+ * @user_data: user data to pass to function
+ * @handler: pointer to the function
+ *
+ * Set the query warning handling function.
+ * 
+ * The function will receive callbacks when the query gives a warning.
+ * 
+ **/
+void
+rasqal_query_set_warning_handler(rasqal_query* query, void *user_data,
+                                 raptor_message_handler handler)
+{
+  raptor_error_handlers* error_handlers;
+  if(!query || !query->world)
+    return;
+
+  error_handlers = &query->world->error_handlers;
+  
+  error_handlers->handlers[RAPTOR_LOG_LEVEL_WARNING].user_data = user_data;
+  error_handlers->handlers[RAPTOR_LOG_LEVEL_WARNING].handler  =handler;
+}
+
+
+/**
+ * rasqal_query_set_feature:
+ * @query: #rasqal_query query object
+ * @feature: feature to set from enumerated #rasqal_feature values
+ * @value: integer feature value
+ *
+ * Set various query features.
+ * 
+ * The allowed features are available via rasqal_features_enumerate().
+ *
+ * Return value: non 0 on failure or if the feature is unknown
+ **/
+int
+rasqal_query_set_feature(rasqal_query* query, rasqal_feature feature, int value)
+{
+  switch(feature) {
+    case RASQAL_FEATURE_NO_NET:
+      query->features[(int)feature] = value;
+      break;
+      
+    default:
+      break;
+  }
+
+  return 0;
+}
+
+
+/**
+ * rasqal_query_set_feature_string:
+ * @query: #rasqal_query query object
+ * @feature: feature to set from enumerated #rasqal_feature values
+ * @value: feature value
+ *
+ * Set query features with string values.
+ * 
+ * The allowed features are available via rasqal_features_enumerate().
+ * If the feature type is integer, the value is interpreted as an integer.
+ *
+ * Return value: non 0 on failure or if the feature is unknown
+ **/
+int
+rasqal_query_set_feature_string(rasqal_query *query, 
+                                rasqal_feature feature, 
+                                const unsigned char *value)
+{
+  int value_is_string = (rasqal_feature_value_type(feature) == 1);
+  if(!value_is_string)
+    return rasqal_query_set_feature(query, feature, atoi((const char*)value));
+
+  return -1;
+}
+
+
+/**
+ * rasqal_query_get_feature:
+ * @query: #rasqal_query query object
+ * @feature: feature to get value
+ *
+ * Get various query features.
+ * 
+ * The allowed features are available via rasqal_features_enumerate().
+ *
+ * Note: no feature value is negative
+ *
+ * Return value: feature value or < 0 for an illegal feature
+ **/
+int
+rasqal_query_get_feature(rasqal_query *query, rasqal_feature feature)
+{
+  int result= -1;
+  
+  switch(feature) {
+    case RASQAL_FEATURE_NO_NET:
+      result = (query->features[(int)feature] != 0);
+      break;
+
+    default:
+      break;
+  }
+  
+  return result;
+}
+
+
+/**
+ * rasqal_query_get_feature_string:
+ * @query: #rasqal_query query object
+ * @feature: feature to get value
+ *
+ * Get query features with string values.
+ * 
+ * The allowed features are available via rasqal_features_enumerate().
+ * If a string is returned, it must be freed by the caller.
+ *
+ * Return value: feature value or NULL for an illegal feature or no value
+ **/
+const unsigned char *
+rasqal_query_get_feature_string(rasqal_query *query, 
+                                rasqal_feature feature)
+{
+  int value_is_string = (rasqal_feature_value_type(feature) == 1);
+  if(!value_is_string)
+    return NULL;
+  
+  return NULL;
+}
+
+
+/**
+ * rasqal_query_get_distinct:
+ * @query: #rasqal_query query object
+ *
+ * Get the query distinct mode
+ *
+ * See rasqal_query_set_distinct() for the distinct modes.
+ *
+ * Return value: non-0 if the results should be distinct
+ **/
+int
+rasqal_query_get_distinct(rasqal_query* query)
+{
+  return query->distinct;
+}
+
+
+/**
+ * rasqal_query_set_distinct:
+ * @query: #rasqal_query query object
+ * @distinct_mode: distinct mode
+ *
+ * Set the query distinct results mode.
+ *
+ * The allowed @distinct_mode values are:
+ * 0 if not given
+ * 1 if DISTINCT: ensure solutions are unique
+ * 2 if SPARQL REDUCED: permit elimination of some non-unique solutions 
+ *
+ **/
+void
+rasqal_query_set_distinct(rasqal_query* query, int distinct_mode)
+{
+  if(distinct_mode >= 0 && distinct_mode <= 2)
+    query->distinct= distinct_mode;
+  else
+    query->distinct= 0;
+}
+
+
+/**
+ * rasqal_query_get_explain:
+ * @query: #rasqal_query query object
+ *
+ * Get the query explain results flag.
+ *
+ * Return value: non-0 if the results should be explain
+ **/
+int
+rasqal_query_get_explain(rasqal_query* query)
+{
+  return query->explain;
+}
+
+
+/**
+ * rasqal_query_set_explain:
+ * @query: #rasqal_query query object
+ * @is_explain: non-0 if explain
+ *
+ * Set the query explain results flag.
+ *
+ **/
+void
+rasqal_query_set_explain(rasqal_query* query, int is_explain)
+{
+  query->explain= (is_explain != 0) ? 1 : 0;
+}
+
+
+/**
+ * rasqal_query_get_limit:
+ * @query: #rasqal_query query object
+ *
+ * Get the query-specified limit on results.
+ *
+ * This is the limit given in the query on the number of results allowed.
+ *
+ * Return value: integer >=0 if a limit is given, otherwise <0
+ **/
+int
+rasqal_query_get_limit(rasqal_query* query)
+{
+  return query->limit;
+}
+
+
+/**
+ * rasqal_query_set_limit:
+ * @query: #rasqal_query query object
+ * @limit: the limit on results, >=0 to set a limit, <0 to have no limit
+ *
+ * Set the query-specified limit on results.
+ *
+ * This is the limit given in the query on the number of results allowed.
+ **/
+void
+rasqal_query_set_limit(rasqal_query* query, int limit)
+{
+  query->limit = limit;
+}
+
+
+/**
+ * rasqal_query_get_offset:
+ * @query: #rasqal_query query object
+ *
+ * Get the query-specified offset on results.
+ *
+ * This is the offset given in the query on the number of results allowed.
+ *
+ * Return value: integer >=0 if a offset is given, otherwise <0
+ **/
+int
+rasqal_query_get_offset(rasqal_query* query)
+{
+  return query->offset;
+}
+
+
+/**
+ * rasqal_query_set_offset:
+ * @query: #rasqal_query query object
+ * @offset: offset for results, >=0 to set an offset, <0 to have no offset
+ *
+ * Set the query-specified offset on results.
+ *
+ * This is the offset given in the query on the number of results allowed.
+ **/
+void
+rasqal_query_set_offset(rasqal_query* query, int offset)
+{
+  query->offset = offset;
+}
+
+
+/**
+ * rasqal_query_add_data_graph:
+ * @query: #rasqal_query query object
+ * @uri: #raptor_uri source uri for retrieval
+ * @name_uri: #raptor_uri name uri (or NULL)
+ * @flags: RASQAL_DATA_GRAPH_NAMED or RASQAL_DATA_GRAPH_BACKGROUND
+ *
+ * Add a data graph to the query.
+ *
+ * named_uri must be given if flags RASQAL_DATA_GRAPH_NAMED is set.
+ * It is the name of the graph and also used as the base URI
+ * when resolving any relative URIs for the graph in uri.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_add_data_graph(rasqal_query* query, 
+                            raptor_uri* uri, raptor_uri* name_uri,
+                            int flags)
+{
+  rasqal_data_graph *dg;
+
+  if((flags & RASQAL_DATA_GRAPH_NAMED) && !name_uri)
+    return 1;
+  
+  dg = rasqal_new_data_graph(query->world, uri, name_uri, flags);
+  if(!dg)
+    return 1;
+  if(raptor_sequence_push(query->data_graphs, (void*)dg))
+    return 1;
+  return 0;
+}
+
+
+/**
+ * rasqal_query_get_data_graph_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of data_graph URIs.
+ *
+ * Return value: a #raptor_sequence of #raptor_uri pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_data_graph_sequence(rasqal_query* query)
+{
+  return query->data_graphs;
+}
+
+
+/**
+ * rasqal_query_get_data_graph:
+ * @query: #rasqal_query query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a rasqal_data_graph* in the sequence of data_graphs.
+ *
+ * Return value: a #rasqal_data_graph pointer or NULL if out of the sequence range
+ **/
+rasqal_data_graph*
+rasqal_query_get_data_graph(rasqal_query* query, int idx)
+{
+  if(!query->data_graphs)
+    return NULL;
+  
+  return (rasqal_data_graph*)raptor_sequence_get_at(query->data_graphs, idx);
+}
+
+
+/**
+ * rasqal_query_dataset_contains_named_graph:
+ * @query: #rasqal_query query object
+ * @graph_uri: query URI
+ *
+ * Test if the query dataset contains a named graph
+ *
+ * Return value: non-0 if the dataset contains a named graph
+ */
+int
+rasqal_query_dataset_contains_named_graph(rasqal_query* query,
+                                          raptor_uri *graph_uri)
+{
+  rasqal_data_graph *dg;
+  int idx;
+  int found = 0;
+  
+  for(idx = 0; (dg = rasqal_query_get_data_graph(query, idx)); idx++) {
+    if(dg->name_uri &&
+#ifdef RAPTOR_V2_AVAILABLE
+       raptor_uri_equals_v2(query->world->raptor_world_ptr, dg->name_uri, graph_uri)
+#else
+       raptor_uri_equals(dg->name_uri, graph_uri)
+#endif
+       )
+    {
+      /* graph_uri is a graph name in the dataset */
+      found = 1;
+      break;
+    }
+  }
+  return found;
+}
+
+
+/**
+ * rasqal_query_add_variable:
+ * @query: #rasqal_query query object
+ * @var: #rasqal_variable variable
+ *
+ * Add a binding variable to the query.
+ *
+ * See also rasqal_query_set_variable which assigns or removes a value to
+ * a previously added variable in the query.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_add_variable(rasqal_query* query, rasqal_variable* var)
+{
+  if(!query->selects) {
+    query->selects = raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_variable_print);
+    if(!query->selects)
+      return 1;
+  }
+
+  return raptor_sequence_push(query->selects, (void*)var);
+}
+
+
+/**
+ * rasqal_query_get_bound_variable_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of variables to bind in the query.
+ *
+ * This returns the sequence of variables that are explicitly chosen
+ * via SELECT in RDQL, SPARQL.  Or all variables mentioned with SELECT *
+ *
+ * Return value: a #raptor_sequence of #rasqal_variable pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_bound_variable_sequence(rasqal_query* query)
+{
+  return query->selects;
+}
+
+
+/**
+ * rasqal_query_get_anonymous_variable_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of anonymous variables mentioned in the query.
+ *
+ * Return value: a #raptor_sequence of #rasqal_variable pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_anonymous_variable_sequence(rasqal_query* query)
+{
+  return rasqal_variables_table_get_anonymous_variables_sequence(query->vars_table);
+}
+
+
+/**
+ * rasqal_query_get_all_variable_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of all variables mentioned in the query.
+ *
+ * Return value: a #raptor_sequence of #rasqal_variable pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_all_variable_sequence(rasqal_query* query)
+{
+  return rasqal_variables_table_get_named_variables_sequence(query->vars_table);
+}
+
+
+/**
+ * rasqal_query_get_variable:
+ * @query: #rasqal_query query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a variable in the sequence of variables to bind.
+ *
+ * Return value: a #rasqal_variable pointer or NULL if out of the sequence range
+ **/
+rasqal_variable*
+rasqal_query_get_variable(rasqal_query* query, int idx)
+{
+  if(!query->selects || idx < 0 || idx > query->select_variables_count)
+    return NULL;
+  
+  return rasqal_variables_table_get(query->vars_table, idx);
+}
+
+
+/**
+ * rasqal_query_has_variable:
+ * @query: #rasqal_query query object
+ * @name: variable name
+ *
+ * Find if the named variable is in the sequence of variables to bind.
+ *
+ * Return value: non-0 if the variable name was found.
+ **/
+int
+rasqal_query_has_variable(rasqal_query* query, const unsigned char *name)
+{
+  return rasqal_variables_table_has(query->vars_table, name);
+}
+
+
+/**
+ * rasqal_query_set_variable:
+ * @query: #rasqal_query query object
+ * @name: #rasqal_variable variable
+ * @value: #rasqal_literal value to set or NULL
+ *
+ * Add a binding variable to the query.
+ *
+ * See also rasqal_query_add_variable which adds a new binding variable
+ * and must be called before this method is invoked.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_set_variable(rasqal_query* query, const unsigned char *name,
+                          rasqal_literal* value)
+{
+  int i;
+
+  if(!query->selects)
+    return 1;
+  
+  for(i = 0; i< raptor_sequence_size(query->selects); i++) {
+    rasqal_variable* v;
+    v = (rasqal_variable*)raptor_sequence_get_at(query->selects, i);
+    if(!strcmp((const char*)v->name, (const char*)name)) {
+      if(v->value)
+        rasqal_free_literal(v->value);
+      v->value = value;
+      return 0;
+    }
+  }
+  return 1;
+}
+
+
+/**
+ * rasqal_query_get_triple_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of matching triples in the query.
+ *
+ * Return value: a #raptor_sequence of #rasqal_triple pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_triple_sequence(rasqal_query* query)
+{
+  return query->triples;
+}
+
+
+/**
+ * rasqal_query_get_triple:
+ * @query: #rasqal_query query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a triple in the sequence of matching triples in the query.
+ *
+ * Return value: a #rasqal_triple pointer or NULL if out of the sequence range
+ **/
+rasqal_triple*
+rasqal_query_get_triple(rasqal_query* query, int idx)
+{
+  if(!query->triples)
+    return NULL;
+  
+  return (rasqal_triple*)raptor_sequence_get_at(query->triples, idx);
+}
+
+
+int
+rasqal_query_declare_prefix(rasqal_query *rq, rasqal_prefix *p)
+{
+  if(p->declared)
+    return 0;
+
+  if(raptor_namespaces_start_namespace_full(rq->namespaces, 
+                                            p->prefix, 
+#ifdef RAPTOR_V2_AVAILABLE
+                                            raptor_uri_as_string_v2(rq->world->raptor_world_ptr, p->uri),
+#else
+                                            raptor_uri_as_string(p->uri),
+#endif
+                                            rq->prefix_depth))
+    return 1;
+  p->declared = 1;
+  rq->prefix_depth++;
+  return 0;
+}
+
+
+static int
+rasqal_query_undeclare_prefix(rasqal_query *rq, rasqal_prefix *prefix)
+{
+  if(!prefix->declared) {
+    prefix->declared = 1;
+    return 0;
+  }
+  
+  raptor_namespaces_end_for_depth(rq->namespaces, prefix->depth);
+  return 0;
+}
+
+
+int
+rasqal_query_declare_prefixes(rasqal_query *rq) 
+{
+  int i;
+  
+  if(!rq->prefixes)
+    return 0;
+  
+  for(i = 0; i< raptor_sequence_size(rq->prefixes); i++) {
+    rasqal_prefix* p = (rasqal_prefix*)raptor_sequence_get_at(rq->prefixes, i);
+    if(rasqal_query_declare_prefix(rq, p))
+      return 1;
+  }
+
+  return 0;
+}
+
+
+/**
+ * rasqal_query_add_prefix:
+ * @query: #rasqal_query query object
+ * @prefix: #rasqal_prefix namespace prefix, URI
+ *
+ * Add a namespace prefix to the query.
+ *
+ * If the prefix has already been used, the old URI will be overridden.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_add_prefix(rasqal_query* query, rasqal_prefix* prefix)
+{
+  if(!query->prefixes) {
+    query->prefixes = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_prefix, (raptor_sequence_print_handler*)rasqal_prefix_print);
+    if(!query->prefixes)
+      return 1;
+  } else {
+    int i;
+    for(i = 0; i< raptor_sequence_size(query->prefixes); i++) {
+      rasqal_prefix* p;
+      p = (rasqal_prefix*)raptor_sequence_get_at(query->prefixes, i);
+      if(strcmp((const char*)p->prefix, (const char*)prefix->prefix)) {
+        rasqal_query_undeclare_prefix(query, p);
+        break;
+      }
+    }
+  }
+
+  return raptor_sequence_push(query->prefixes, (void*)prefix);
+}
+
+
+/**
+ * rasqal_query_get_prefix_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of namespace prefixes in the query.
+ *
+ * Return value: a #raptor_sequence of #rasqal_prefix pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_prefix_sequence(rasqal_query* query)
+{
+  return query->prefixes;
+}
+
+
+/**
+ * rasqal_query_get_prefix:
+ * @query: #rasqal_query query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a prefix in the sequence of namespsace prefixes in the query.
+ *
+ * Return value: a #rasqal_prefix pointer or NULL if out of the sequence range
+ **/
+rasqal_prefix*
+rasqal_query_get_prefix(rasqal_query* query, int idx)
+{
+  if(!query->prefixes)
+    return NULL;
+
+  return (rasqal_prefix*)raptor_sequence_get_at(query->prefixes, idx);
+}
+
+
+/**
+ * rasqal_query_get_query_graph_pattern:
+ * @query: #rasqal_query query object
+ *
+ * Get the top query graph pattern.
+ *
+ * Return value: a #rasqal_graph_pattern of the top query graph pattern
+ **/
+rasqal_graph_pattern*
+rasqal_query_get_query_graph_pattern(rasqal_query* query)
+{
+  return query->query_graph_pattern;
+}
+
+
+/**
+ * rasqal_query_get_graph_pattern_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of graph_patterns expressions inside the top query graph pattern.
+ *
+ * Return value: a #raptor_sequence of #rasqal_graph_pattern pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_graph_pattern_sequence(rasqal_query* query)
+{
+  return rasqal_graph_pattern_get_sub_graph_pattern_sequence(query->query_graph_pattern);
+}
+
+
+/**
+ * rasqal_query_get_graph_pattern:
+ * @query: #rasqal_query query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a graph_pattern in the sequence of graph_pattern expressions in the top query graph pattern.
+ *
+ * Return value: a #rasqal_graph_pattern pointer or NULL if out of the sequence range
+ **/
+rasqal_graph_pattern*
+rasqal_query_get_graph_pattern(rasqal_query* query, int idx)
+{
+  return rasqal_graph_pattern_get_sub_graph_pattern(query->query_graph_pattern, idx);
+}
+
+
+/**
+ * rasqal_query_get_construct_triples_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of triples for a construct.
+ *
+ * Return value: a #raptor_sequence of #rasqal_triple pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_construct_triples_sequence(rasqal_query* query)
+{
+  return query->constructs;
+}
+
+
+/**
+ * rasqal_query_get_construct_triple:
+ * @query: #rasqal_query query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a triple in the sequence of construct triples.
+ *
+ * Return value: a #rasqal_triple pointer or NULL if out of the sequence range
+ **/
+rasqal_triple*
+rasqal_query_get_construct_triple(rasqal_query* query, int idx)
+{
+  if(!query->constructs)
+    return NULL;
+
+  return (rasqal_triple*)raptor_sequence_get_at(query->constructs, idx);
+}
+
+
+
+/**
+ * rasqal_query_prepare:
+ * @query: the #rasqal_query object
+ * @query_string: the query string (or NULL)
+ * @base_uri: base URI of query string (optional)
+ *
+ * Prepare a query - typically parse it.
+ * 
+ * Some query languages may require a base URI to resolve any
+ * relative URIs in the query string.  If this is not given,
+ * the current directory in the filesystem is used as the base URI.
+ *
+ * The query string may be NULL in which case it is not parsed
+ * and the query parts may be created by API calls such as
+ * rasqal_query_add_source etc.
+ *
+ * Return value: non-0 on failure.
+ **/
+int
+rasqal_query_prepare(rasqal_query* query,
+                     const unsigned char *query_string,
+                     raptor_uri *base_uri)
+{
+  int rc = 0;
+  
+  if(query->failed)
+    return 1;
+
+  if(query->prepared)
+    return 0;
+  query->prepared = 1;
+
+  if(query_string) {
+    /* flex lexers require two NULs at the end of the lexed buffer.
+     * Add them here instead of parser to allow resource cleanup on error.
+     *  
+     * flex manual:
+     *
+     * Function: YY_BUFFER_STATE yy_scan_buffer (char *base, yy_size_t size)
+     * which scans in place the buffer starting at `base', consisting of
+     * `size' bytes, the last two bytes of which _must_ be
+     * `YY_END_OF_BUFFER_CHAR' (ASCII NUL).  These last two bytes are not
+     * scanned; thus, scanning consists of `base[0]' through
+     * `base[size-2]', inclusive.
+     */
+    int len = strlen((const char*)query_string)+3; /* +3 for " \0\0" */
+    unsigned char *query_string_copy = (unsigned char*)RASQAL_MALLOC(cstring, len);
+    if(!query_string_copy) {
+      query->failed = 1;
+      return 1;
+    }
+    strcpy((char*)query_string_copy, (const char*)query_string);
+    query_string_copy[len-3] = ' ';
+    query_string_copy[len-2] = query_string_copy[len-1] = '\0';
+    query->query_string = query_string_copy;
+    query->query_string_length = len;
+  }
+
+  if(base_uri)
+#ifdef RAPTOR_V2_AVAILABLE
+    base_uri = raptor_uri_copy_v2(query->world->raptor_world_ptr, base_uri);
+#else
+    base_uri = raptor_uri_copy(base_uri);
+#endif
+  else {
+    unsigned char *uri_string = raptor_uri_filename_to_uri_string("");
+#ifdef RAPTOR_V2_AVAILABLE
+    base_uri = raptor_new_uri_v2(query->world->raptor_world_ptr, uri_string);
+#else
+    base_uri = raptor_new_uri(uri_string);
+#endif
+    if(uri_string)
+      raptor_free_memory(uri_string);
+  }
+
+  rasqal_query_set_base_uri(query, base_uri);
+  query->locator.line = query->locator.column = query->locator.byte = -1;
+
+  rc = query->factory->prepare(query);
+  if(rc) {
+    query->failed = 1;
+    rc = 1;
+  } else if(rasqal_query_prepare_common(query)) {
+    query->failed = 1;
+    rc = 1;
+  }
+
+  return rc;
+}
+
+
+/**
+ * rasqal_query_get_engine_by_name:
+ * @name: query engine name
+ *
+ * INTERNAL - Get a query engine by name
+ *
+ * If @name is NULL or the name is unknown, the default factory is returned
+ *
+ * return value: pointer to factory
+ **/
+const rasqal_query_execution_factory* 
+rasqal_query_get_engine_by_name(const char* name)
+{
+  const rasqal_query_execution_factory* engine = &rasqal_query_engine_1;
+
+#ifdef RASQAL_DEBUG
+  if(1) {
+    char* n = getenv("RASQAL_DEBUG_ENGINE");
+    if(n)
+      name = n;
+  }
+#endif
+
+  if(name) {
+    if(!strcmp(name, "1") || !strcmp(name, "original"))
+      engine = &rasqal_query_engine_1;
+    else if(!strcmp(name, "2") || !strcmp(name, "algebra"))
+      engine = &rasqal_query_engine_algebra;
+  }
+
+  return engine;
+}
+
+
+/**
+ * rasqal_query_execute_with_engine:
+ * @query: the #rasqal_query object
+ * @engine: execution engine factory
+ *
+ * INTERNAL - Excecute a query with a given factory and return results.
+ *
+ * return value: a #rasqal_query_results structure or NULL on failure.
+ **/
+rasqal_query_results*
+rasqal_query_execute_with_engine(rasqal_query* query,
+                                 const rasqal_query_execution_factory* engine)
+{
+  rasqal_query_results *query_results = NULL;
+  
+  if(query->failed)
+    return NULL;
+
+  if(!engine)
+    engine = rasqal_query_get_engine_by_name(NULL);
+
+  query_results = rasqal_query_results_execute_with_engine(query, engine);
+  if(query_results && rasqal_query_add_query_result(query, query_results)) {
+    rasqal_free_query_results(query_results);
+    query_results = NULL;      
+  }
+
+  return query_results;
+}
+
+
+/**
+ * rasqal_query_execute:
+ * @query: the #rasqal_query object
+ *
+ * Excute a query - run and return results.
+ *
+ * return value: a #rasqal_query_results structure or NULL on failure.
+ **/
+rasqal_query_results*
+rasqal_query_execute(rasqal_query* query)
+{
+  return rasqal_query_execute_with_engine(query, NULL);
+}
+
+
+static const char* const rasqal_query_verb_labels[RASQAL_QUERY_VERB_LAST+1] = {
+  "Unknown",
+  "SELECT",
+  "CONSTRUCT",
+  "DESCRIBE",
+  "ASK",
+  "DELETE",
+  "INSERT"
+};
+
+/* Utility methods */
+
+/**
+ * rasqal_query_verb_as_string:
+ * @verb: the #rasqal_query_verb verb of the query
+ *
+ * Get a string for the query verb.
+ * 
+ * Return value: pointer to a shared string label for the query verb
+ **/
+const char*
+rasqal_query_verb_as_string(rasqal_query_verb verb)
+{
+  if(verb <= RASQAL_QUERY_VERB_UNKNOWN || 
+     verb > RASQAL_QUERY_VERB_LAST)
+    verb = RASQAL_QUERY_VERB_UNKNOWN;
+
+  return rasqal_query_verb_labels[(int)verb];
+}
+  
+
+/**
+ * rasqal_query_print:
+ * @query: the #rasqal_query object
+ * @fh: the #FILE* handle to print to.
+ *
+ * Print a query in a debug format.
+ * 
+ **/
+void
+rasqal_query_print(rasqal_query* query, FILE *fh)
+{
+  rasqal_variables_table* vars_table = query->vars_table;
+  raptor_sequence* seq;
+
+  fprintf(fh, "query verb: %s\n", rasqal_query_verb_as_string(query->verb));
+  
+  if(query->distinct)
+    fprintf(fh, "query results distinct mode: %s\n",
+            (query->distinct == 1 ? "distinct" : "reduced"));
+  if(query->explain)
+    fputs("query results explain: yes\n", fh);
+  if(query->limit >= 0)
+    fprintf(fh, "query results limit: %d\n", query->limit);
+  if(query->offset >= 0)
+    fprintf(fh, "query results offset: %d\n", query->offset);
+
+  fputs("data graphs: ", fh);
+  if(query->data_graphs)
+    raptor_sequence_print(query->data_graphs, fh);
+  seq = rasqal_variables_table_get_named_variables_sequence(vars_table);
+  if(seq) {
+    fputs("\nnamed variables: ", fh); 
+    raptor_sequence_print(seq, fh);
+  }
+  seq = rasqal_variables_table_get_anonymous_variables_sequence(vars_table);
+  if(seq) {
+    fputs("\nanonymous variables: ", fh); 
+    raptor_sequence_print(seq, fh);
+  }
+  if(query->selects) {
+    fputs("\nbound variables: ", fh); 
+    raptor_sequence_print(query->selects, fh);
+  }
+  if(query->describes) {
+    fputs("\ndescribes: ", fh);
+    raptor_sequence_print(query->describes, fh);
+  }
+  if(query->triples) {
+    fputs("\ntriples: ", fh);
+    raptor_sequence_print(query->triples, fh);
+  }
+  if(query->optional_triples) {
+    fputs("\noptional triples: ", fh);
+    raptor_sequence_print(query->optional_triples, fh);
+  }
+  if(query->constructs) {
+    fputs("\nconstructs: ", fh);
+    raptor_sequence_print(query->constructs, fh);
+  }
+  if(query->prefixes) {
+    fputs("\nprefixes: ", fh);
+    raptor_sequence_print(query->prefixes, fh);
+  }
+  if(query->query_graph_pattern) {
+    fputs("\nquery graph pattern: ", fh);
+    rasqal_graph_pattern_print(query->query_graph_pattern, fh);
+  }
+  if(query->order_conditions_sequence) {
+    fputs("\nquery order conditions: ", fh);
+    raptor_sequence_print(query->order_conditions_sequence, fh);
+  }
+  if(query->group_conditions_sequence) {
+    fputs("\nquery group conditions: ", fh);
+    raptor_sequence_print(query->group_conditions_sequence, fh);
+  }
+  fputc('\n', fh);
+}
+
+
+static int
+rasqal_query_add_query_result(rasqal_query* query,
+                              rasqal_query_results* query_results) 
+{
+  /* add reference to ensure query lives as long as this runs */
+
+  /* query->results sequence has rasqal_query_results_remove_query_reference()
+     as the free handler which calls rasqal_free_query() decrementing
+     query->usage */
+  
+  query->usage++;
+
+  return raptor_sequence_push(query->results, query_results);
+}
+
+
+
+void
+rasqal_query_remove_query_result(rasqal_query* query,
+                                 rasqal_query_results* query_results) 
+{
+  int i;
+  int size;
+  
+  size = raptor_sequence_size(query->results);
+  for(i = 0 ; i < size; i++) {
+    rasqal_query_results *result;
+    result = (rasqal_query_results*)raptor_sequence_get_at(query->results, i);
+
+    if(result == query_results) {
+      raptor_sequence_set_at(query->results, i, NULL);
+      break;
+    }
+  }
+}
+
+
+
+/**
+ * rasqal_query_get_user_data:
+ * @query: #rasqal_query
+ *
+ * Get query user data.
+ * 
+ * Return value: user data as set by rasqal_query_set_user_data
+ **/
+void*
+rasqal_query_get_user_data(rasqal_query* query)
+{
+  return query->user_data;
+}
+
+
+/**
+ * rasqal_query_set_user_data:
+ * @query: #rasqal_query
+ * @user_data: some user data to associate with the query
+ *
+ * Set the query user data.
+ *
+ **/
+void
+rasqal_query_set_user_data(rasqal_query* query, void *user_data)
+{
+  query->user_data = user_data;
+}
+
+
+/**
+ * rasqal_query_get_verb:
+ * @query: #rasqal_query
+ *
+ * Get the query verb.
+ *
+ * Return value: the operating verb of the query of type rasqal_query_verb
+ **/
+rasqal_query_verb
+rasqal_query_get_verb(rasqal_query* query)
+{
+  return query->verb;
+}
+
+
+/**
+ * rasqal_query_get_wildcard:
+ * @query: #rasqal_query
+ *
+ * Get the query verb is wildcard flag.
+ *
+ * Return value: non-0 if the query verb was a wildcard (such as SELECT *)
+ **/
+int
+rasqal_query_get_wildcard(rasqal_query* query)
+{
+  return query->wildcard;
+}
+
+
+/**
+ * rasqal_query_get_order_conditions_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of query ordering conditions.
+ *
+ * Return value: a #raptor_sequence of #rasqal_expression pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_order_conditions_sequence(rasqal_query* query)
+{
+  return query->order_conditions_sequence;
+}
+
+
+/**
+ * rasqal_query_get_order_condition:
+ * @query: #rasqal_query query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a query ordering expression in the sequence of query ordering conditions.
+ *
+ * Return value: a #rasqal_expression pointer or NULL if out of the sequence range
+ **/
+rasqal_expression*
+rasqal_query_get_order_condition(rasqal_query* query, int idx)
+{
+  if(!query->order_conditions_sequence)
+    return NULL;
+  
+  return (rasqal_expression*)raptor_sequence_get_at(query->order_conditions_sequence, idx);
+}
+
+
+/**
+ * rasqal_query_get_group_conditions_sequence:
+ * @query: #rasqal_query query object
+ *
+ * Get the sequence of query grouping conditions.
+ *
+ * Return value: a #raptor_sequence of #rasqal_expression pointers.
+ **/
+raptor_sequence*
+rasqal_query_get_group_conditions_sequence(rasqal_query* query)
+{
+  return query->group_conditions_sequence;
+}
+
+
+/**
+ * rasqal_query_get_group_condition:
+ * @query: #rasqal_query query object
+ * @idx: index into the sequence (0 or larger)
+ *
+ * Get a query grouping expression in the sequence of query grouping conditions.
+ *
+ * Return value: a #rasqal_expression pointer or NULL if out of the sequence range
+ **/
+rasqal_expression*
+rasqal_query_get_group_condition(rasqal_query* query, int idx)
+{
+  if(!query->group_conditions_sequence)
+    return NULL;
+  
+  return (rasqal_expression*)raptor_sequence_get_at(query->group_conditions_sequence, idx);
+}
+
+
+/**
+ * rasqal_query_graph_pattern_visit:
+ * @query: query
+ * @visit_fn: user function to operate on
+ * @data: user data to pass to function
+ * 
+ * Visit all graph patterns in a query with a user function @visit_fn.
+ *
+ * See also rasqal_graph_pattern_visit().
+ **/
+void
+rasqal_query_graph_pattern_visit(rasqal_query* query, 
+                                 rasqal_graph_pattern_visit_fn visit_fn, 
+                                 void* data)
+{
+  rasqal_graph_pattern* gp = rasqal_query_get_query_graph_pattern(query);
+  if(!gp)
+    return;
+
+  rasqal_graph_pattern_visit(query, gp, visit_fn, data);
+}
+
+
+
+typedef struct 
+{
+  rasqal_world* world;
+  raptor_uri* type_uri;
+  raptor_uri* base_uri;
+  raptor_namespace_stack *nstack;
+} sparql_writer_context;
+
+static void rasqal_query_write_sparql_expression(sparql_writer_context *wc, raptor_iostream* iostr, rasqal_expression* e);
+
+
+static void
+rasqal_query_write_sparql_variable(sparql_writer_context *wc,
+                                   raptor_iostream* iostr, rasqal_variable* v)
+{
+  if(v->expression) {
+    rasqal_query_write_sparql_expression(wc, iostr, v->expression);
+    raptor_iostream_write_counted_string(iostr, " AS ", 4);
+  }
+  if(v->type == RASQAL_VARIABLE_TYPE_ANONYMOUS)
+    raptor_iostream_write_counted_string(iostr, "_:", 2);
+  else if(!v->expression)
+    raptor_iostream_write_byte(iostr, '?');
+  raptor_iostream_write_string(iostr, v->name);
+}
+
+
+static void
+rasqal_query_write_sparql_uri(sparql_writer_context *wc,
+                              raptor_iostream* iostr, raptor_uri* uri)
+{
+  size_t len;
+  unsigned char* string;
+  raptor_qname* qname;
+
+  qname = raptor_namespaces_qname_from_uri(wc->nstack, uri, 10);
+  if(qname) {
+    const raptor_namespace* nspace = raptor_qname_get_namespace(qname);
+    if(!raptor_namespace_get_prefix(nspace))
+      raptor_iostream_write_byte(iostr, ':');
+    raptor_iostream_write_qname(iostr, qname);
+    raptor_free_qname(qname);
+    return;
+  }
+  
+#ifdef RAPTOR_V2_AVAILABLE
+  if(wc->base_uri)
+    string = raptor_uri_to_relative_counted_uri_string_v2(wc->world->raptor_world_ptr, wc->base_uri, uri, &len);
+  else
+    string = raptor_uri_as_counted_string_v2(wc->world->raptor_world_ptr, uri, &len);
+#else
+  if(wc->base_uri)
+    string = raptor_uri_to_relative_counted_uri_string(wc->base_uri, uri, &len);
+  else
+    string = raptor_uri_as_counted_string(uri, &len);
+#endif
+
+  raptor_iostream_write_byte(iostr, '<');
+  raptor_iostream_write_string_ntriples(iostr, string, len, '>');
+  raptor_iostream_write_byte(iostr, '>');
+
+  if(wc->base_uri)
+    raptor_free_memory(string);
+}
+
+
+static void
+rasqal_query_write_sparql_literal(sparql_writer_context *wc,
+                                  raptor_iostream* iostr, rasqal_literal* l)
+{
+  if(!l) {
+    raptor_iostream_write_counted_string(iostr, "null", 4);
+    return;
+  }
+
+  switch(l->type) {
+    case RASQAL_LITERAL_URI:
+      rasqal_query_write_sparql_uri(wc, iostr, l->value.uri);
+      break;
+    case RASQAL_LITERAL_BLANK:
+      raptor_iostream_write_counted_string(iostr, "_:", 2);
+      raptor_iostream_write_string(iostr, l->string);
+      break;
+    case RASQAL_LITERAL_STRING:
+      raptor_iostream_write_byte(iostr, '"');
+      raptor_iostream_write_string_ntriples(iostr, l->string, l->string_len, '"');
+      raptor_iostream_write_byte(iostr, '"');
+      if(l->language) {
+        raptor_iostream_write_byte(iostr, '@');
+        raptor_iostream_write_string(iostr, l->language);
+      }
+      if(l->datatype) {
+        raptor_iostream_write_counted_string(iostr, "^^", 2);
+        rasqal_query_write_sparql_uri(wc, iostr, l->datatype);
+      }
+      break;
+    case RASQAL_LITERAL_QNAME:
+      raptor_iostream_write_counted_string(iostr, "QNAME(", 6);
+      raptor_iostream_write_counted_string(iostr, l->string, l->string_len);
+      raptor_iostream_write_byte(iostr, ')');
+      break;
+    case RASQAL_LITERAL_INTEGER:
+      raptor_iostream_write_decimal(iostr, l->value.integer);
+      break;
+    case RASQAL_LITERAL_BOOLEAN:
+    case RASQAL_LITERAL_DOUBLE:
+    case RASQAL_LITERAL_FLOAT:
+    case RASQAL_LITERAL_DECIMAL:
+      raptor_iostream_write_counted_string(iostr, l->string, l->string_len);
+      break;
+    case RASQAL_LITERAL_VARIABLE:
+      rasqal_query_write_sparql_variable(wc, iostr, l->value.variable);
+      break;
+    case RASQAL_LITERAL_DATETIME:
+      raptor_iostream_write_byte(iostr, '"');
+      raptor_iostream_write_string_ntriples(iostr, l->string, l->string_len, '"');
+      raptor_iostream_write_counted_string(iostr, "\"^^", 3);
+      rasqal_query_write_sparql_uri(wc, iostr,
+                                    rasqal_xsd_datatype_type_to_uri(l->world, l->type));
+      break;
+
+    case RASQAL_LITERAL_UNKNOWN:
+    case RASQAL_LITERAL_PATTERN:
+    default:
+      RASQAL_FATAL2("Literal type %d cannot be written as a SPARQL literal", l->type);
+  }
+}
+
+
+static void
+rasqal_query_write_sparql_triple(sparql_writer_context *wc,
+                                 raptor_iostream* iostr, rasqal_triple* triple)
+{
+  rasqal_query_write_sparql_literal(wc, iostr, triple->subject);
+  raptor_iostream_write_byte(iostr, ' ');
+  if(triple->predicate->type == RASQAL_LITERAL_URI &&
+#ifdef RAPTOR_V2_AVAILABLE
+     raptor_uri_equals_v2(wc->world->raptor_world_ptr, triple->predicate->value.uri, wc->type_uri)
+#else
+     raptor_uri_equals(triple->predicate->value.uri, wc->type_uri)
+#endif
+     )
+    raptor_iostream_write_byte(iostr, 'a');
+  else
+    rasqal_query_write_sparql_literal(wc, iostr, triple->predicate);
+  raptor_iostream_write_byte(iostr, ' ');
+  rasqal_query_write_sparql_literal(wc, iostr, triple->object);
+  raptor_iostream_write_counted_string(iostr, " .", 2);
+}
+
+
+#define SPACES_LENGTH 80
+static const char spaces[SPACES_LENGTH+1] = "                                                                                ";
+
+static void
+rasqal_query_write_indent(raptor_iostream* iostr, int indent) 
+{
+  while(indent > 0) {
+    int sp = (indent > SPACES_LENGTH) ? SPACES_LENGTH : indent;
+    raptor_iostream_write_bytes(iostr, spaces, sizeof(char), sp);
+    indent -= sp;
+  }
+}
+
+  
+
+static const char* const rasqal_sparql_op_labels[RASQAL_EXPR_LAST+1] = {
+  NULL, /* UNKNOWN */
+  "&&",
+  "||",
+  "=",
+  "!=",
+  "<",
+  ">",
+  "<=",
+  ">=",
+  "-",
+  "+",
+  "-",
+  "*",
+  "/",
+  NULL, /* REM */
+  NULL, /* STR EQ */
+  NULL, /* STR NEQ */
+  NULL, /* STR_MATCH */
+  NULL, /* STR_NMATCH */
+  NULL, /* TILDE */
+  "!",
+  NULL, /* LITERAL */
+  NULL, /* FUNCTION */
+  "BOUND",
+  "STR",
+  "LANG",
+  "DATATYPE",
+  "isIRI",
+  "isBLANK",
+  "isLITERAL",
+  NULL, /* CAST */
+  "ASC",   /* ORDER BY ASC */
+  "DESC",  /* ORDER BY DESC */
+  "LANGMATCHES",
+  "REGEX",
+  "ASC",   /* GROUP BY ASC */
+  "DESC",  /* GROUP BY DESC */
+  "COUNT",
+  NULL, /* VARSTAR */
+  "sameTerm"
+};
+
+
+
+static void
+rasqal_query_write_sparql_expression_op(sparql_writer_context *wc,
+                                        raptor_iostream* iostr,
+                                        rasqal_expression* e)
+{
+  rasqal_op op = e->op;
+  const char* string;
+  if(op > RASQAL_EXPR_LAST)
+    op = RASQAL_EXPR_UNKNOWN;
+  string = rasqal_sparql_op_labels[(int)op];
+  
+  if(string)
+    raptor_iostream_write_string(iostr, string);
+  else
+    raptor_iostream_write_string(iostr, "NONE");
+}
+
+
+static void
+rasqal_query_write_sparql_expression(sparql_writer_context *wc,
+                                     raptor_iostream* iostr, 
+                                     rasqal_expression* e)
+{
+  int i;
+  int count;
+
+  switch(e->op) {
+    case RASQAL_EXPR_AND:
+    case RASQAL_EXPR_OR:
+    case RASQAL_EXPR_EQ:
+    case RASQAL_EXPR_NEQ:
+    case RASQAL_EXPR_LT:
+    case RASQAL_EXPR_GT:
+    case RASQAL_EXPR_LE:
+    case RASQAL_EXPR_GE:
+    case RASQAL_EXPR_PLUS:
+    case RASQAL_EXPR_MINUS:
+    case RASQAL_EXPR_STAR:
+    case RASQAL_EXPR_SLASH:
+    case RASQAL_EXPR_REM:
+    case RASQAL_EXPR_STR_EQ:
+    case RASQAL_EXPR_STR_NEQ:
+      raptor_iostream_write_counted_string(iostr, "( ", 2);
+      rasqal_query_write_sparql_expression(wc, iostr, e->arg1);
+      raptor_iostream_write_byte(iostr, ' ');
+      rasqal_query_write_sparql_expression_op(wc, iostr, e);
+      raptor_iostream_write_byte(iostr, ' ');
+      rasqal_query_write_sparql_expression(wc, iostr, e->arg2);
+      raptor_iostream_write_counted_string(iostr, " )", 2);
+      break;
+
+    case RASQAL_EXPR_BOUND:
+    case RASQAL_EXPR_STR:
+    case RASQAL_EXPR_LANG:
+    case RASQAL_EXPR_DATATYPE:
+    case RASQAL_EXPR_ISURI:
+    case RASQAL_EXPR_ISBLANK:
+    case RASQAL_EXPR_ISLITERAL:
+    case RASQAL_EXPR_ORDER_COND_ASC:
+    case RASQAL_EXPR_ORDER_COND_DESC:
+    case RASQAL_EXPR_GROUP_COND_ASC:
+    case RASQAL_EXPR_GROUP_COND_DESC:
+    case RASQAL_EXPR_COUNT:
+    case RASQAL_EXPR_SAMETERM:
+      rasqal_query_write_sparql_expression_op(wc, iostr, e);
+      raptor_iostream_write_counted_string(iostr, "( ", 2);
+      rasqal_query_write_sparql_expression(wc, iostr, e->arg1);
+      raptor_iostream_write_counted_string(iostr, " )", 2);
+      break;
+      
+    case RASQAL_EXPR_LANGMATCHES:
+    case RASQAL_EXPR_REGEX:
+      rasqal_query_write_sparql_expression_op(wc, iostr, e);
+      raptor_iostream_write_counted_string(iostr, "( ", 2);
+      rasqal_query_write_sparql_expression(wc, iostr, e->arg1);
+      raptor_iostream_write_counted_string(iostr, ", ", 2);
+      rasqal_query_write_sparql_expression(wc, iostr, e->arg2);
+      if(e->op == RASQAL_EXPR_REGEX && e->arg3) {
+        raptor_iostream_write_counted_string(iostr, ", ", 2);
+        rasqal_query_write_sparql_expression(wc, iostr, e->arg3);
+      }
+      raptor_iostream_write_counted_string(iostr, " )", 2);
+      break;
+
+    case RASQAL_EXPR_TILDE:
+    case RASQAL_EXPR_BANG:
+    case RASQAL_EXPR_UMINUS:
+      rasqal_query_write_sparql_expression_op(wc, iostr, e);
+      raptor_iostream_write_counted_string(iostr, "( ", 2);
+      rasqal_query_write_sparql_expression(wc, iostr, e->arg1);
+      raptor_iostream_write_counted_string(iostr, " )", 2);
+      break;
+
+    case RASQAL_EXPR_LITERAL:
+      rasqal_query_write_sparql_literal(wc, iostr, e->literal);
+      break;
+
+    case RASQAL_EXPR_FUNCTION:
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_iostream_write_uri_v2(e->world->raptor_world_ptr, iostr, e->name);
+#else
+      raptor_iostream_write_uri(iostr, e->name);
+#endif
+      raptor_iostream_write_counted_string(iostr, "( ", 2);
+      count = raptor_sequence_size(e->args);
+      for(i = 0; i < count ; i++) {
+        rasqal_expression* arg;
+        arg = (rasqal_expression*)raptor_sequence_get_at(e->args, i);
+        if(i > 0)
+          raptor_iostream_write_counted_string(iostr, " ,", 2);
+        rasqal_query_write_sparql_expression(wc, iostr, arg);
+      }
+      raptor_iostream_write_counted_string(iostr, " )", 2);
+      break;
+
+    case RASQAL_EXPR_CAST:
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_iostream_write_uri_v2(e->world->raptor_world_ptr, iostr, e->name);
+#else
+      raptor_iostream_write_uri(iostr, e->name);
+#endif
+      raptor_iostream_write_counted_string(iostr, "( ", 2);
+      rasqal_query_write_sparql_expression(wc, iostr, e->arg1);
+      raptor_iostream_write_counted_string(iostr, " )", 2);
+      break;
+
+    case RASQAL_EXPR_VARSTAR:
+      raptor_iostream_write_byte(iostr, '*');
+      break;
+      
+    case RASQAL_EXPR_UNKNOWN:
+    case RASQAL_EXPR_STR_MATCH:
+    case RASQAL_EXPR_STR_NMATCH:
+    default:
+      RASQAL_FATAL2("Expression op %d cannot be written as a SPARQL expresson", e->op);
+  }
+}
+
+
+static void
+rasqal_query_write_sparql_graph_pattern(sparql_writer_context *wc,
+                                        raptor_iostream* iostr,
+                                        rasqal_graph_pattern *gp, 
+                                        int gp_index, int indent)
+{
+  int triple_index = 0;
+  rasqal_graph_pattern_operator op;
+  raptor_sequence *seq;
+  int filters_count = 0;
+  
+  op = rasqal_graph_pattern_get_operator(gp);
+  
+  if(op == RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL ||
+     op == RASQAL_GRAPH_PATTERN_OPERATOR_GRAPH) {
+    /* prefix verbs */
+    if(op == RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL) 
+      raptor_iostream_write_counted_string(iostr, "OPTIONAL ", 9);
+    else {
+      rasqal_graph_pattern* sgp;
+      rasqal_triple* t;
+      sgp = rasqal_graph_pattern_get_sub_graph_pattern(gp, 0);
+      t = rasqal_graph_pattern_get_triple(sgp, 0);
+
+      raptor_iostream_write_counted_string(iostr, "GRAPH ", 6);
+      rasqal_query_write_sparql_literal(wc, iostr, t->origin);
+      raptor_iostream_write_byte(iostr, ' ');
+    }
+  }
+  raptor_iostream_write_counted_string(iostr, "{\n", 2);
+
+  indent+= 2;
+
+  /* look for triples */
+  while(1) {
+    rasqal_triple* t = rasqal_graph_pattern_get_triple(gp, triple_index);
+    if(!t)
+      break;
+    
+    rasqal_query_write_indent(iostr, indent);
+    rasqal_query_write_sparql_triple(wc, iostr, t);
+    raptor_iostream_write_byte(iostr, '\n');
+
+    triple_index++;
+  }
+
+
+  /* look for sub-graph patterns */
+  seq = rasqal_graph_pattern_get_sub_graph_pattern_sequence(gp);
+  if(seq && raptor_sequence_size(seq) > 0) {
+    for(gp_index = 0; 1; gp_index++) {
+      rasqal_graph_pattern* sgp = rasqal_graph_pattern_get_sub_graph_pattern(gp, gp_index);
+      if(!sgp)
+        break;
+
+      if(sgp->op == RASQAL_GRAPH_PATTERN_OPERATOR_FILTER) {
+        filters_count++;
+        continue;
+      }
+      
+      if(!gp_index)
+        rasqal_query_write_indent(iostr, indent);
+      else {
+        if(op == RASQAL_GRAPH_PATTERN_OPERATOR_UNION)
+          /* infix verb */
+          raptor_iostream_write_counted_string(iostr, " UNION ", 7);
+        else {
+          /* must be prefix verb */
+          raptor_iostream_write_byte(iostr, '\n');
+          rasqal_query_write_indent(iostr, indent);
+        }
+      }
+      
+      rasqal_query_write_sparql_graph_pattern(wc, iostr, sgp, gp_index, indent);
+    }
+    raptor_iostream_write_byte(iostr, '\n');
+  }
+  
+
+  /* look for constraints */
+  if(filters_count > 0) {
+    for(gp_index = 0; 1; gp_index++) {
+      rasqal_graph_pattern* sgp;
+      rasqal_expression* expr;
+
+      sgp = rasqal_graph_pattern_get_sub_graph_pattern(gp, gp_index);
+      if(!sgp)
+        break;
+      
+      if(sgp->op != RASQAL_GRAPH_PATTERN_OPERATOR_FILTER)
+        continue;
+
+      expr = rasqal_graph_pattern_get_filter_expression(sgp);
+
+      rasqal_query_write_indent(iostr, indent);
+      raptor_iostream_write_counted_string(iostr, "FILTER( ", 8);
+      rasqal_query_write_sparql_expression(wc, iostr, expr);
+      raptor_iostream_write_counted_string(iostr, " )\n", 3);
+    }
+  }
+  
+
+  indent -= 2;
+  
+  rasqal_query_write_indent(iostr, indent);
+  raptor_iostream_write_byte(iostr, '}');
+}
+
+
+    
+static int
+rasqal_query_write_sparql_20060406(raptor_iostream *iostr, 
+                                   rasqal_query* query, raptor_uri *base_uri)
+{
+  int i;
+  raptor_sequence *var_seq = NULL;
+  sparql_writer_context wc;
+#ifndef RAPTOR_V2_AVAILABLE
+  const raptor_uri_handler *uri_handler;
+  void *uri_context;
+#endif
+
+  wc.world = query->world;
+  wc.base_uri = NULL;
+
+#ifdef RAPTOR_V2_AVAILABLE
+  wc.type_uri = raptor_new_uri_for_rdf_concept_v2(query->world->raptor_world_ptr, "type");
+  wc.nstack = raptor_new_namespaces_v2(query->world->raptor_world_ptr,
+                                       (raptor_simple_message_handler)rasqal_query_simple_error,
+                                       query,
+                                       1);
+#else
+  wc.type_uri = raptor_new_uri_for_rdf_concept("type");
+  raptor_uri_get_handler(&uri_handler, &uri_context);
+  wc.nstack = raptor_new_namespaces(uri_handler, uri_context,
+                                    (raptor_simple_message_handler)rasqal_query_simple_error,
+                                    query,
+                                    1);
+#endif
+
+  if(base_uri) {
+    raptor_iostream_write_counted_string(iostr, "BASE ", 5);
+    rasqal_query_write_sparql_uri(&wc, iostr, base_uri);
+    raptor_iostream_write_byte(iostr, '\n');
+
+    /* from now on all URIs are relative to this */
+#ifdef RAPTOR_V2_AVAILABLE
+    wc.base_uri = raptor_uri_copy_v2(query->world->raptor_world_ptr, base_uri);
+#else
+    wc.base_uri = raptor_uri_copy(base_uri);
+#endif
+  }
+  
+  
+  for(i = 0; 1 ; i++) {
+    raptor_namespace *nspace;
+    rasqal_prefix* p = rasqal_query_get_prefix(query, i);
+    if(!p)
+      break;
+    
+    raptor_iostream_write_counted_string(iostr, "PREFIX ", 7);
+    if(p->prefix)
+      raptor_iostream_write_string(iostr, p->prefix);
+    raptor_iostream_write_counted_string(iostr,": ", 2);
+    rasqal_query_write_sparql_uri(&wc, iostr, p->uri);
+    raptor_iostream_write_byte(iostr, '\n');
+
+    /* Use this constructor so we copy a URI directly */
+    nspace = raptor_new_namespace_from_uri(wc.nstack, p->prefix, p->uri, i);
+    raptor_namespaces_start_namespace(wc.nstack, nspace);
+  }
+
+  if(query->explain)
+    raptor_iostream_write_counted_string(iostr, "EXPLAIN ", 8);
+
+  if(query->verb != RASQAL_QUERY_VERB_CONSTRUCT)
+    raptor_iostream_write_string(iostr,
+                                 rasqal_query_verb_as_string(query->verb));
+
+  if(query->distinct) {
+    if(query->distinct == 1)
+      raptor_iostream_write_counted_string(iostr, " DISTINCT", 9);
+    else
+      raptor_iostream_write_counted_string(iostr, " REDUCED", 8);
+  }
+
+  if(query->verb == RASQAL_QUERY_VERB_DESCRIBE)
+    var_seq = query->describes;
+  else if(query->verb == RASQAL_QUERY_VERB_SELECT)
+    var_seq = query->selects;
+  
+  if(var_seq && query->wildcard)
+    raptor_iostream_write_counted_string(iostr, " *", 2);
+  else if(var_seq) {
+    int count = raptor_sequence_size(var_seq);
+    for(i = 0; i < count; i++) {
+      rasqal_variable* v = (rasqal_variable*)raptor_sequence_get_at(var_seq, i);
+      raptor_iostream_write_byte(iostr, ' ');
+      rasqal_query_write_sparql_variable(&wc, iostr, v);
+    }
+  }
+  raptor_iostream_write_byte(iostr, '\n');
+
+  if(query->data_graphs) {
+    for(i = 0; 1; i++) {
+      rasqal_data_graph* dg = rasqal_query_get_data_graph(query, i);
+      if(!dg)
+        break;
+      
+      if(dg->flags & RASQAL_DATA_GRAPH_NAMED)
+        continue;
+      
+      raptor_iostream_write_counted_string(iostr, "FROM ", 5);
+      rasqal_query_write_sparql_uri(&wc, iostr, dg->uri);
+      raptor_iostream_write_counted_string(iostr, "\n", 1);
+    }
+    
+    for(i = 0; 1; i++) {
+      rasqal_data_graph* dg = rasqal_query_get_data_graph(query, i);
+      if(!dg)
+        break;
+
+      if(!(dg->flags & RASQAL_DATA_GRAPH_NAMED))
+        continue;
+      
+      raptor_iostream_write_counted_string(iostr, "FROM NAMED ", 11);
+      rasqal_query_write_sparql_uri(&wc, iostr, dg->name_uri);
+      raptor_iostream_write_byte(iostr, '\n');
+    }
+    
+  }
+
+  if(query->constructs) {
+    raptor_iostream_write_string(iostr, "CONSTRUCT {\n");
+    for(i = 0; 1; i++) {
+      rasqal_triple* t = rasqal_query_get_construct_triple(query, i);
+      if(!t)
+        break;
+
+      raptor_iostream_write_counted_string(iostr, "  ", 2);
+      rasqal_query_write_sparql_triple(&wc, iostr, t);
+      raptor_iostream_write_byte(iostr, '\n');
+    }
+    raptor_iostream_write_counted_string(iostr, "}\n", 2);
+  }
+  if(query->query_graph_pattern) {
+    raptor_iostream_write_counted_string(iostr, "WHERE ", 6);
+    rasqal_query_write_sparql_graph_pattern(&wc, iostr,
+                                            query->query_graph_pattern, 
+                                            -1, 0);
+    raptor_iostream_write_byte(iostr, '\n');
+  }
+
+  if(query->group_conditions_sequence) {
+    raptor_iostream_write_counted_string(iostr, "GROUP BY ", 9);
+    for(i = 0; 1; i++) {
+      rasqal_expression* expr = rasqal_query_get_group_condition(query, i);
+      if(!expr)
+        break;
+
+      if(i > 0)
+        raptor_iostream_write_byte(iostr, ' ');
+      rasqal_query_write_sparql_expression(&wc, iostr, expr);
+    }
+    raptor_iostream_write_byte(iostr, '\n');
+  }
+
+  if(query->order_conditions_sequence) {
+    raptor_iostream_write_counted_string(iostr, "ORDER BY ", 9);
+    for(i = 0; 1; i++) {
+      rasqal_expression* expr = rasqal_query_get_order_condition(query, i);
+      if(!expr)
+        break;
+
+      if(i > 0)
+        raptor_iostream_write_byte(iostr, ' ');
+      rasqal_query_write_sparql_expression(&wc, iostr, expr);
+    }
+    raptor_iostream_write_byte(iostr, '\n');
+  }
+
+  if(query->limit >= 0 || query->offset >= 0) {
+    if(query->limit >= 0) {
+      raptor_iostream_write_counted_string(iostr, "LIMIT ", 7);
+      raptor_iostream_write_decimal(iostr, query->limit);
+    }
+    if(query->offset >= 0) {
+      if(query->limit)
+        raptor_iostream_write_byte(iostr, ' ');
+      raptor_iostream_write_counted_string(iostr, "OFFSET ", 8);
+      raptor_iostream_write_decimal(iostr, query->offset);
+    }
+    raptor_iostream_write_byte(iostr, '\n');
+  }
+
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_free_uri_v2(query->world->raptor_world_ptr, wc.type_uri);
+  if(wc.base_uri)
+    raptor_free_uri_v2(query->world->raptor_world_ptr, wc.base_uri);
+#else
+  raptor_free_uri(wc.type_uri);
+  if(wc.base_uri)
+    raptor_free_uri(wc.base_uri);
+#endif
+  raptor_free_namespaces(wc.nstack);
+
+  return 0;
+}
+
+
+/**
+ * rasqal_query_write:
+ * @iostr: #raptor_iostream to write the query to
+ * @query: #rasqal_query pointer.
+ * @format_uri: #raptor_uri describing the format to write (or NULL for default)
+ * @base_uri: #raptor_uri base URI of the output format
+ *
+ * Write a query to an iostream in a specified format.
+ * 
+ * The supported URIs for the format_uri are:
+ *
+ * Default: SPARQL Query Language 2006-04-06
+ * http://www.w3.org/TR/2006/CR-rdf-sparql-query-20060406/
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_write(raptor_iostream* iostr, rasqal_query* query,
+                   raptor_uri* format_uri, raptor_uri* base_uri)
+{
+  const char *format_uri_str = NULL;
+
+  if(format_uri)
+#ifdef RAPTOR_V2_AVAILABLE
+    format_uri_str = (const char*)raptor_uri_as_string_v2(query->world->raptor_world_ptr,
+                                                          format_uri);
+#else
+    format_uri_str = (const char*)raptor_uri_as_string(format_uri);
+#endif
+
+  if(!format_uri ||
+     !strcmp(format_uri_str,
+             "http://www.w3.org/TR/rdf-sparql-query/";) ||
+     !strcmp(format_uri_str,
+             "http://www.w3.org/TR/2006/WD-rdf-sparql-query-20060220/";) ||
+     !strcmp(format_uri_str,
+             "http://www.w3.org/TR/2006/CR-rdf-sparql-query-20060406/";))
+    return rasqal_query_write_sparql_20060406(iostr, query, base_uri);
+
+  return 1;
+}
+
+
+/**
+ * rasqal_query_iostream_write_escaped_counted_string:
+ * @query: #rasqal_query object
+ * @iostr: #raptor_iostream to write the escaped string to
+ * @string: string to escape
+ * @len: Length of string to escape
+ * 
+ * Write a string to an iostream in escaped form suitable for the query string.
+ * 
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_iostream_write_escaped_counted_string(rasqal_query* query,
+                                                   raptor_iostream* iostr,
+                                                   const unsigned char* string,
+                                                   size_t len)
+{
+  if(query->factory->iostream_write_escaped_counted_string)
+    return query->factory->iostream_write_escaped_counted_string(query, iostr, 
+                                                                 string, len);
+  else
+    return 1;
+}
+
+
+/**
+ * rasqal_query_escape_counted_string:
+ * @query: #rasqal_query object
+ * @string: string to escape
+ * @len: Length of string to escape
+ * @output_len_p: Pointer to store length of output string (or NULL)
+ * 
+ * Convert a string into an escaped form suitable for the query string.
+ * 
+ * The returned string must be freed by the caller with
+ * rasqal_free_memory()
+ *
+ * Return value: the escaped string or NULL on failure.
+ **/
+unsigned char*
+rasqal_query_escape_counted_string(rasqal_query* query,
+                                   const unsigned char* string, 
+                                   size_t len,
+                                   size_t* output_len_p)
+{
+  raptor_iostream* iostr;
+  void* output_string = NULL;
+  int rc;
+  
+  iostr = raptor_new_iostream_to_string(&output_string, output_len_p,
+                                        rasqal_alloc_memory);
+  if(!iostr)
+    return NULL;
+  rc = rasqal_query_iostream_write_escaped_counted_string(query, iostr,
+                                                          string, len);
+  raptor_free_iostream(iostr);
+  if(rc && output_string) {
+    rasqal_free_memory(output_string);
+    output_string = NULL;
+  }
+  
+  return (unsigned char *)output_string;
+}
+
+
+unsigned char*
+rasqal_query_get_genid(rasqal_query* query, const unsigned char* base, 
+                       int counter)
+{
+  int tmpcounter;
+  int length;
+  unsigned char *buffer;
+
+  /* This is read-only and thread safe */
+  if(counter < 0)
+    counter= query->genid_counter++;
+  
+  length = strlen((const char*)base)+2;  /* base + (int) + "\0" */
+  tmpcounter = counter;
+  while(tmpcounter /= 10)
+    length++;
+  
+  buffer = (unsigned char*)RASQAL_MALLOC(cstring, length);
+  if(!buffer)
+    return NULL;
+
+  sprintf((char*)buffer, "%s%d", base, counter);
+  return buffer;
+}
+
+
+void
+rasqal_query_set_base_uri(rasqal_query* query, raptor_uri* base_uri)
+{
+  if(query->base_uri)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(query->world->raptor_world_ptr, query->base_uri);
+#else
+    raptor_free_uri(query->base_uri);
+#endif
+  query->base_uri = base_uri;
+  query->locator.uri = base_uri;
+}
+
+
+void
+rasqal_query_set_store_results(rasqal_query* query, int store_results)
+{
+  query->store_results = store_results;
+}
+
+
+rasqal_variable* 
+rasqal_query_get_variable_by_offset(rasqal_query* query, int idx)
+{
+  return rasqal_variables_table_get(query->vars_table, idx);
+}
diff --git a/src/rasqal/rasqal_query_results.c b/src/rasqal/rasqal_query_results.c
new file mode 100644
index 0000000..dde892d
--- /dev/null
+++ b/src/rasqal/rasqal_query_results.c
@@ -0,0 +1,1425 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_query_results.c - Rasqal RDF Query Results
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+/**
+ *
+ * Query Results Class Internals
+ *
+ * This class provides the abstraction for query results in different
+ * forms.  The forms can be either a sequence of variable bindings,
+ * set of RDF triples, boolean value or a syntax.
+ *
+ * Query results can be created as a result of a #rasqal_query
+ * execution using rasqal_query_execute() or as an independent result
+ * set constructed from a query results syntax such as the SPARQL XML
+ * results format via the #rasqal_query_results_formatter class.
+ *
+ * The query results constructor rasqal_new_query_results() takes
+ * a world to use, an optional query, the type of result as well
+ * as a variable table to operate on.  If the query is given, then
+ * that is used to handle limit, offset and triple construction,
+ * otherwise the result set is standalone and not associated with
+ * a query.
+ *
+ * The variables table is used for the variables that will appear in
+ * the result rows in the result set.  The query results module does
+ * not own any variable information, all API calls are delegated to
+ * the variables table.
+ * 
+ * If the rasqal_new_query_results_from_query_execution() is used to
+ * make a query results from a query structure via executing the
+ * query, it initialises a execution engine via the
+ * #rasqal_query_execution_factory 'execute_init' factory method.
+ * This method also determines whether the entire results need to be
+ * (or a requested to be) obtained in one go, and if so, they are
+ * done during construction.
+ *
+ * The user API to getting query results is primarily to get variable
+ * bindings - a sequence of variable:value (also called #rasqal_row
+ * internally), RDF triples, a boolean value or a syntax.  
+ *
+ * The variable bindings are generated from the execution engine by
+ * retrieving #rasqal_row either one-by-one using the get_row method
+ * or getting the entire result at once with the get_all_rows method.
+ *
+ * In the case of getting the entire result the rows are stored as a
+ * sqeuence inside the #rasqal_query_results and returned one-by-one
+ * from there, respecting any limit and offset.
+ *
+ * The RDF triples and boolean value results are generated from the
+ * variable bindings (#rasqal_row) inside this class.  The underlying
+ * execution engine only knows about rows.
+ *
+ * The class also handles several other results-specific methods such
+ * as getting variable binding names, values by name, counts of
+ * number of results, writing a query results as a syntax (in a
+ * simple fashion), read a query results from a syntax.
+ */
+
+static int rasqal_query_results_execute_and_store_results(rasqal_query_results* query_results);
+static void rasqal_query_results_update_bindings(rasqal_query_results* query_results);
+
+
+/*
+ * A query result for some query
+ */
+struct rasqal_query_results_s {
+  rasqal_world* world;
+
+  /* type of query result (bindings, boolean, graph or syntax) */
+  rasqal_query_results_type type;
+  
+  /* non-0 if have read all (variable binding) results */
+  int finished;
+
+  /* non-0 if query has been executed */
+  int executed;
+
+  /* non 0 if query had fatal error and cannot return results */
+  int failed;
+
+  /* query that this was executed over */
+  rasqal_query* query;
+
+  /* how many (variable bindings) results found so far */
+  int result_count;
+
+  /* execution data for execution engine. owned by this object */
+  void* execution_data;
+
+  /* current row of results */
+  rasqal_row* row;
+
+  /* boolean ASK result >0 true, 0 false or -1 uninitialised */
+  int ask_result;
+
+  /* boolean: non-0 to store query results rather than lazy eval */
+  int store_results;
+
+  /* current triple in the sequence of triples 'constructs' or -1 */
+  int current_triple_result;
+
+  /* constructed triple result - shared and updated for each triple */
+  raptor_statement result_triple;
+
+  /* triple used to store references to literals for triple subject,
+   * predicate, object.  never returned or used otherwise.
+   */
+  rasqal_triple* triple;
+  
+  /* sequence of stored results */
+  raptor_sequence* results_sequence;
+
+  /* size of result row fields:
+   * row->results, row->values
+   */
+  int size;
+
+  /* Execution engine used here */
+  const rasqal_query_execution_factory* execution_factory;
+
+  /* Variables table for variables in result rows */
+  rasqal_variables_table* vars_table;
+};
+    
+
+int
+rasqal_init_query_results(void)
+{
+  return 0;
+}
+
+
+void
+rasqal_finish_query_results(void)
+{
+}
+
+
+/**
+ * rasqal_new_query_results:
+ * @world: rasqal world object
+ * @query: query object (or NULL)
+ * @type: query results (expected) type
+ * @vars_table: variables table
+ * 
+ * INTERNAL -  create a query result set
+ *
+ * The @query may be NULL for result set objects that are standalone
+ * and not attached to any particular query
+ *
+ * Return value: a new query result object or NULL on failure
+ **/
+rasqal_query_results*  
+rasqal_new_query_results(rasqal_world* world,
+                         rasqal_query* query,
+                         rasqal_query_results_type type,
+                         rasqal_variables_table* vars_table)
+{
+  rasqal_query_results* query_results;
+    
+  query_results = (rasqal_query_results*)RASQAL_CALLOC(rasqal_query_results, 1, sizeof(rasqal_query_results));
+  if(!query_results)
+    return NULL;
+  
+  query_results->world = world;
+  query_results->type = type;
+  query_results->finished = 0;
+  query_results->executed = 0;
+  query_results->failed = 0;
+  query_results->query = query;
+  query_results->result_count = 0;
+  query_results->execution_data = NULL;
+  query_results->row = NULL;
+  query_results->ask_result = -1; 
+  query_results->store_results = 0; 
+  query_results->current_triple_result = -1;
+  /* query_results->result_triple is static */
+  query_results->triple = NULL;
+  query_results->results_sequence = NULL;
+  query_results->size = 0;
+  query_results->vars_table = rasqal_new_variables_table_from_variables_table(vars_table);
+
+  return query_results;
+}
+
+
+/**
+ * rasqal_query_results_execute_with_engine:
+ * @query: the #rasqal_query object
+ * @engine: execution factory
+ *
+ * INTERNAL - Create a new query results set executing a prepared query with the given execution engine
+ *
+ * return value: a #rasqal_query_results structure or NULL on failure.
+ **/
+rasqal_query_results*
+rasqal_query_results_execute_with_engine(rasqal_query* query,
+                                         const rasqal_query_execution_factory* engine)
+{
+  rasqal_query_results *query_results = NULL;
+  int rc = 0;
+  size_t ex_data_size;
+  rasqal_query_results_type type = RASQAL_QUERY_RESULTS_BINDINGS;
+
+  if(!query)
+    return NULL;
+  
+  if(query->failed)
+    return NULL;
+
+  if(query->query_results_formatter_name)
+    type = RASQAL_QUERY_RESULTS_SYNTAX;
+  else
+    switch(query->verb) {
+      case RASQAL_QUERY_VERB_SELECT:
+        type = RASQAL_QUERY_RESULTS_BINDINGS;
+        break;
+      case RASQAL_QUERY_VERB_ASK:
+        type = RASQAL_QUERY_RESULTS_BOOLEAN;
+        break;
+      case RASQAL_QUERY_VERB_CONSTRUCT:
+      case RASQAL_QUERY_VERB_DESCRIBE:
+        type = RASQAL_QUERY_RESULTS_GRAPH;
+        break;
+        
+      case RASQAL_QUERY_VERB_UNKNOWN:
+      case RASQAL_QUERY_VERB_DELETE:
+      case RASQAL_QUERY_VERB_INSERT:
+      default:
+        return NULL;
+    }
+  
+  query_results = rasqal_new_query_results(query->world, query, type,
+                                           query->vars_table);
+  if(!query_results)
+    return NULL;
+
+  query_results->execution_factory = engine;
+  
+  /* set executed flag early to enable cleanup on error */
+  query_results->executed = 1;
+
+  query_results->store_results = (query->store_results || 
+                                  query->order_conditions_sequence ||
+                                  query->distinct);
+  
+  ex_data_size = query_results->execution_factory->execution_data_size;
+  if(ex_data_size > 0) {
+    query_results->execution_data = RASQAL_CALLOC(data, 1, ex_data_size);
+    if(!query_results->execution_data) {
+      rasqal_free_query_results(query_results);
+      return NULL;
+    }
+  } else
+    query_results->execution_data = NULL;
+
+  if(query_results->execution_factory->execute_init) {
+    rasqal_engine_error execution_error = RASQAL_ENGINE_OK;
+    int execution_flags = 0;
+    if(query_results->store_results)
+      execution_flags |= 1;
+
+    rc = query_results->execution_factory->execute_init(query_results->execution_data, query, query_results, execution_flags, &execution_error);
+    if(execution_error != RASQAL_ENGINE_OK) {
+      query_results->failed = 1;
+      rasqal_free_query_results(query_results);
+      return NULL;
+    }
+  }
+
+  /* Choose either to execute all now and store OR do it on demand (lazy) */
+  if(query_results->store_results)
+    rc = rasqal_query_results_execute_and_store_results(query_results);
+
+  return query_results;
+}
+
+
+/**
+ * rasqal_free_query_results:
+ * @query_results: #rasqal_query_results object
+ *
+ * Destructor - destroy a rasqal_query_results.
+ *
+ **/
+void
+rasqal_free_query_results(rasqal_query_results* query_results)
+{
+  rasqal_query* query;
+
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(query_results, rasqal_query_result);
+
+  query = query_results->query;
+
+  if(query_results->executed) {
+    if(query_results->execution_factory->execute_finish) {
+      rasqal_engine_error execution_error = RASQAL_ENGINE_OK;
+
+      query_results->execution_factory->execute_finish(query_results->execution_data, &execution_error);
+      /* ignoring failure of execute_finish */
+    }
+  }
+
+  if(query_results->execution_data)
+    RASQAL_FREE(rasqal_engine_execution_data, query_results->execution_data);
+
+  if(query_results->row)
+    rasqal_free_row(query_results->row);
+
+  if(query_results->results_sequence)
+    raptor_free_sequence(query_results->results_sequence);
+
+  if(query_results->triple)
+    rasqal_free_triple(query_results->triple);
+
+  if(query_results->vars_table)
+    rasqal_free_variables_table(query_results->vars_table);
+
+  if(query)
+    rasqal_query_remove_query_result(query, query_results);
+
+  RASQAL_FREE(rasqal_query_results, query_results);
+}
+
+
+/**
+ * rasqal_query_results_get_query:
+ * @query_results: #rasqal_query_results object
+ *
+ * Get thq query associated with this query result
+ * 
+ * Return value: shared pointer to query object
+ **/
+rasqal_query*
+rasqal_query_results_get_query(rasqal_query_results* query_results)
+{
+  return query_results->query;
+}
+
+
+/**
+ * rasqal_query_results_is_bindings:
+ * @query_results: #rasqal_query_results object
+ *
+ * Test if rasqal_query_results is variable bindings format.
+ * 
+ * Return value: non-0 if true
+ **/
+int
+rasqal_query_results_is_bindings(rasqal_query_results* query_results)
+{
+  return (query_results->type == RASQAL_QUERY_RESULTS_BINDINGS);
+}
+
+
+/**
+ * rasqal_query_results_is_boolean:
+ * @query_results: #rasqal_query_results object
+ *
+ * Test if rasqal_query_results is boolean format.
+ * 
+ * Return value: non-0 if true
+ **/
+int
+rasqal_query_results_is_boolean(rasqal_query_results* query_results)
+{
+  return (query_results->type == RASQAL_QUERY_RESULTS_BOOLEAN);
+}
+ 
+
+/**
+ * rasqal_query_results_is_graph:
+ * @query_results: #rasqal_query_results object
+ *
+ * Test if rasqal_query_results is RDF graph format.
+ * 
+ * Return value: non-0 if true
+ **/
+int
+rasqal_query_results_is_graph(rasqal_query_results* query_results)
+{
+  return (query_results->type == RASQAL_QUERY_RESULTS_GRAPH);
+}
+
+
+/**
+ * rasqal_query_results_is_syntax:
+ * @query_results: #rasqal_query_results object
+ *
+ * Test if the rasqal_query_results is a syntax.
+ *
+ * Many of the query results may be formatted as a syntax using the
+ * #rasqal_query_formatter class however this function returns true
+ * if a syntax result was specifically requested.
+ * 
+ * Return value: non-0 if true
+ **/
+int
+rasqal_query_results_is_syntax(rasqal_query_results* query_results)
+{
+  return (query_results->type == RASQAL_QUERY_RESULTS_SYNTAX);
+}
+
+
+/**
+ * rasqal_query_results_check_limit_offset:
+ * @query_results: query results object
+ *
+ * INTERNAL - Check the query result count is in the limit and offset range if any.
+ *
+ * Return value: before range -1, in range 0, after range 1
+ */
+int
+rasqal_query_results_check_limit_offset(rasqal_query_results* query_results)
+{
+  rasqal_query* query = query_results->query;
+  int limit;
+
+  if(!query)
+    return 0;
+
+  limit = query->limit;
+
+  /* Ensure ASK queries never do more than one result */
+  if(query->verb == RASQAL_QUERY_VERB_ASK)
+    limit = 1;
+
+  if(query->offset > 0) {
+    /* offset */
+    if(query_results->result_count <= query->offset)
+      return -1;
+    
+    if(limit >= 0) {
+      /* offset and limit */
+      if(query_results->result_count > (query->offset + limit)) {
+        query_results->finished = 1;
+      }
+    }
+    
+  } else if(limit >= 0) {
+    /* limit */
+    if(query_results->result_count > limit) {
+      query_results->finished = 1;
+    }
+  }
+
+  return query_results->finished;
+}
+
+
+/**
+ * rasqal_query_results_get_row_from_saved:
+ * @query_results: Query results to execute
+ *
+ * INTERNAL - Get next result row from a stored query result sequence
+ *
+ * Return value: result row or NULL if finished or failed
+ */
+static rasqal_row*
+rasqal_query_results_get_row_from_saved(rasqal_query_results* query_results)
+{
+  rasqal_query* query = query_results->query;
+  int size;
+  rasqal_row* row = NULL;
+  
+  size = raptor_sequence_size(query_results->results_sequence);
+  
+  while(1) {
+    if(query_results->result_count >= size) {
+      query_results->finished = 1;
+      break;
+    }
+    
+    query_results->result_count++;
+    
+    /* finished if beyond result range */
+    if(rasqal_query_results_check_limit_offset(query_results) > 0) {
+      query_results->result_count--;
+      break;
+    }
+    
+    /* continue if before start of result range */
+    if(rasqal_query_results_check_limit_offset(query_results) < 0)
+      continue;
+    
+    /* else got result or finished */
+    row = (rasqal_row*)raptor_sequence_delete_at(query_results->results_sequence,
+                                                 query_results->result_count-1);
+    
+    if(row) {
+      /* stored results may not be canonicalized yet - do it lazily */
+      rasqal_row_to_nodes(row);
+
+      if(query && query->constructs)
+        rasqal_query_results_update_bindings(query_results);
+    }
+    break;
+  }
+  
+  return row;
+}
+
+
+/**
+ * rasqal_query_results_ensure_have_row_internal:
+ * @query_results: #rasqal_query_results query_results
+ *
+ * INTERNAL - Ensure there is a row in the query results by getting it from the generator/stored list
+ *
+ * If one already is held, nothing is done.  It is assumed
+ * that @query_results is not NULL and the query is neither finished
+ * nor failed.
+ *
+ * Return value: non-0 if failed or results exhausted
+ **/
+static int
+rasqal_query_results_ensure_have_row_internal(rasqal_query_results* query_results)
+{
+  /* already have row */
+  if(query_results->row)
+    return 0;
+  
+  if(query_results->results_sequence) {
+    query_results->row = rasqal_query_results_get_row_from_saved(query_results);
+  } else if(query_results->execution_factory &&
+            query_results->execution_factory->get_row) {
+    rasqal_engine_error execution_error = RASQAL_ENGINE_OK;
+
+    query_results->row = query_results->execution_factory->get_row(query_results->execution_data, &execution_error);
+    if(execution_error == RASQAL_ENGINE_FAILED)
+      query_results->failed = 1;
+    else if(execution_error == RASQAL_ENGINE_OK)
+      query_results->result_count++;
+  }
+  
+  if(query_results->row) {
+    rasqal_row_to_nodes(query_results->row);
+    query_results->size = query_results->row->size;
+  } else
+    query_results->finished = 1;
+
+  return (query_results->row == NULL);
+}
+
+
+/**
+ * rasqal_query_results_get_current_row:
+ * @query_results: query results object
+ *
+ * INTERNAL - Get the current query result as a row of values
+ *
+ * The returned row is shared and owned by query_results
+ *
+ * Return value: result row or NULL on failure
+ */
+static rasqal_row*
+rasqal_query_results_get_current_row(rasqal_query_results* query_results)
+{
+  if(!query_results || query_results->failed || query_results->finished)
+    return NULL;
+  
+  if(!rasqal_query_results_is_bindings(query_results))
+    return NULL;
+
+  /* ensure we have a row */
+  rasqal_query_results_ensure_have_row_internal(query_results);
+
+  return query_results->row;
+}
+
+
+/**
+ * rasqal_query_results_get_count:
+ * @query_results: #rasqal_query_results query_results
+ *
+ * Get number of bindings so far.
+ * 
+ * Return value: number of bindings found so far or < 0 on failure
+ **/
+int
+rasqal_query_results_get_count(rasqal_query_results* query_results)
+{
+  rasqal_query* query;
+
+  if(!query_results || query_results->failed)
+    return -1;
+
+  if(!rasqal_query_results_is_bindings(query_results))
+    return -1;
+  
+  query = query_results->query;
+  if(query && query->offset > 0)
+    return query_results->result_count - query->offset;
+  return query_results->result_count;
+}
+
+
+/**
+ * rasqal_query_results_next:
+ * @query_results: #rasqal_query_results query_results
+ *
+ * Move to the next result.
+ * 
+ * Return value: non-0 if failed or results exhausted
+ **/
+int
+rasqal_query_results_next(rasqal_query_results* query_results)
+{
+  if(!query_results || query_results->failed || query_results->finished)
+    return 1;
+  
+  if(!rasqal_query_results_is_bindings(query_results))
+    return 1;
+
+  /* Remove any current row */
+  if(query_results->row) {
+    rasqal_free_row(query_results->row);
+    query_results->row = NULL;
+  }
+
+  /* Now try to get a new one */
+  return rasqal_query_results_ensure_have_row_internal(query_results);
+}
+
+
+/**
+ * rasqal_query_results_finished:
+ * @query_results: #rasqal_query_results query_results
+ *
+ * Find out if binding results are exhausted.
+ * 
+ * Return value: non-0 if results are finished or query failed
+ **/
+int
+rasqal_query_results_finished(rasqal_query_results* query_results)
+{
+  if(!query_results || query_results->failed || query_results->finished)
+    return 1;
+  
+  if(!rasqal_query_results_is_bindings(query_results))
+    return 1;
+
+  /* need to have at least tried to get a row once */
+  if(!query_results->failed && !query_results->finished)
+    rasqal_query_results_ensure_have_row_internal(query_results);
+  
+  return (query_results->failed || query_results->finished);
+}
+
+
+/**
+ * rasqal_query_results_get_bindings:
+ * @query_results: #rasqal_query_results query_results
+ * @names: pointer to an array of binding names (or NULL)
+ * @values: pointer to an array of binding value #rasqal_literal (or NULL)
+ *
+ * Get all binding names, values for current result.
+ * 
+ * If names is not NULL, it is set to the address of a shared array
+ * of names of the bindings (an output parameter).  These names
+ * are shared and must not be freed by the caller
+ *
+ * If values is not NULL, it is set to the address of a shared array
+ * of #rasqal_literal* binding values.  These values are shaerd
+ * and must not be freed by the caller.
+ * 
+ * Return value: non-0 if the assignment failed
+ **/
+int
+rasqal_query_results_get_bindings(rasqal_query_results* query_results,
+                                  const unsigned char ***names, 
+                                  rasqal_literal ***values)
+{
+  if(!query_results)
+    return 1;
+  
+  if(!rasqal_query_results_is_bindings(query_results))
+    return 1;
+  
+  if(names)
+    *names = rasqal_variables_table_get_names(query_results->vars_table);
+  
+  if(values) {
+    rasqal_row* row;
+
+    row = rasqal_query_results_get_current_row(query_results);
+    if(row)
+      *values = row->values;
+    else
+      query_results->finished = 1;
+  }
+    
+  return 0;
+}
+
+
+/**
+ * rasqal_query_results_get_binding_value:
+ * @query_results: #rasqal_query_results query_results
+ * @offset: offset of binding name into array of known names
+ *
+ * Get one binding value for the current result.
+ * 
+ * Return value: a pointer to a shared #rasqal_literal binding value or NULL on failure
+ **/
+rasqal_literal*
+rasqal_query_results_get_binding_value(rasqal_query_results* query_results, 
+                                       int offset)
+{
+  rasqal_row* row;
+  
+  if(!query_results)
+    return NULL;
+  
+  if(!rasqal_query_results_is_bindings(query_results))
+    return NULL;
+  
+  if(offset < 0 || offset > query_results->size-1)
+    return NULL;
+
+  row = rasqal_query_results_get_current_row(query_results);
+  if(row)
+    return row->values[offset];
+
+  query_results->finished = 1;
+  return NULL;
+}
+
+
+/**
+ * rasqal_query_results_get_binding_name:
+ * @query_results: #rasqal_query_results query_results
+ * @offset: offset of binding name into array of known names
+ *
+ * Get binding name for the current result.
+ * 
+ * Return value: a pointer to a shared copy of the binding name or NULL on failure
+ **/
+const unsigned char*
+rasqal_query_results_get_binding_name(rasqal_query_results* query_results, 
+                                      int offset)
+{
+  rasqal_variable* v;
+
+  if(!query_results)
+    return NULL;
+  
+  if(!rasqal_query_results_is_bindings(query_results)) 
+    return NULL;
+  
+  v = rasqal_variables_table_get(query_results->vars_table, offset);
+  if(!v)
+    return NULL;
+  
+  return v->name;
+}
+
+
+/**
+ * rasqal_query_results_get_binding_value_by_name:
+ * @query_results: #rasqal_query_results query_results
+ * @name: variable name
+ *
+ * Get one binding value for a given name in the current result.
+ * 
+ * Return value: a pointer to a shared #rasqal_literal binding value or NULL on failure
+ **/
+rasqal_literal*
+rasqal_query_results_get_binding_value_by_name(rasqal_query_results* query_results,
+                                               const unsigned char *name)
+{
+  rasqal_row* row;
+  rasqal_variable* v;
+
+  if(!query_results)
+    return NULL;
+  
+  if(!rasqal_query_results_is_bindings(query_results))
+    return NULL;
+  
+  row = rasqal_query_results_get_current_row(query_results);
+  if(!row)
+    return NULL;
+  
+  v = rasqal_variables_table_get_by_name(query_results->vars_table, name);
+  if(!v)
+    return NULL;
+
+  return row->values[v->offset];
+}
+
+
+/**
+ * rasqal_query_results_get_bindings_count:
+ * @query_results: #rasqal_query_results query_results
+ *
+ * Get the number of bound variables in the result.
+ * 
+ * Return value: <0 if failed or results exhausted
+ **/
+int
+rasqal_query_results_get_bindings_count(rasqal_query_results* query_results)
+{
+  if(!query_results || query_results->failed)
+    return -1;
+  
+  if(!rasqal_query_results_is_bindings(query_results))
+    return -1;
+  
+  return query_results->size;
+}
+
+
+static unsigned char*
+rasqal_prefix_id(int prefix_id, unsigned char *string)
+{
+  int tmpid = prefix_id;
+  unsigned char* buffer;
+  size_t length = strlen((const char*)string)+4;  /* "r" +... + "_" +... \0 */
+
+  while(tmpid /= 10)
+    length++;
+  
+  buffer = (unsigned char*)RASQAL_MALLOC(cstring, length);
+  if(!buffer)
+    return NULL;
+  
+  sprintf((char*)buffer, "r%d_%s", prefix_id, string);
+  
+  return buffer;
+}
+
+
+/**
+ * rasqal_query_results_get_triple:
+ * @query_results: #rasqal_query_results query_results
+ *
+ * Get the current triple in the result.
+ *
+ * The return value is a shared #raptor_statement.
+ * 
+ * Return value: #raptor_statement or NULL if failed or results exhausted
+ **/
+raptor_statement*
+rasqal_query_results_get_triple(rasqal_query_results* query_results)
+{
+  rasqal_query* query;
+  int rc;
+  rasqal_triple *t;
+  rasqal_literal *s, *p, *o;
+  raptor_statement *rs = NULL;
+  unsigned char *nodeid;
+  int skipped;
+  
+ if(!query_results || query_results->failed || query_results->finished)
+    return NULL;
+  
+  if(!rasqal_query_results_is_graph(query_results))
+    return NULL;
+  
+  query = query_results->query;
+  if(!query)
+    return NULL;
+  
+  if(query->verb == RASQAL_QUERY_VERB_DESCRIBE)
+    return NULL;
+
+ 
+  /* ensure we have a row to work on */
+  if(rasqal_query_results_ensure_have_row_internal(query_results))
+    return NULL;
+
+  skipped = 0;
+  while(1) {
+    if(skipped) {
+      rc = rasqal_query_results_next(query_results);
+      if(rc) {
+        rs = NULL;
+        break;
+      }
+      query_results->current_triple_result = -1;
+    }
+    
+    if(query_results->current_triple_result < 0)
+      query_results->current_triple_result = 0;
+
+    t = (rasqal_triple*)raptor_sequence_get_at(query->constructs,
+                                               query_results->current_triple_result);
+
+    rs = &query_results->result_triple;
+
+    s = rasqal_literal_as_node(t->subject);
+    if(!s) {
+      rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_WARNING,
+                              &query->locator,
+                              "Triple with unbound subject skipped");
+      skipped = 1;
+      continue;
+    }
+    switch(s->type) {
+      case RASQAL_LITERAL_URI:
+        rs->subject = s->value.uri;
+        rs->subject_type = RAPTOR_IDENTIFIER_TYPE_RESOURCE;
+        break;
+
+      case RASQAL_LITERAL_BLANK:
+        nodeid = rasqal_prefix_id(query_results->result_count,
+                                  (unsigned char*)s->string);
+        rasqal_free_literal(s);
+        if(!nodeid) {
+          rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_FATAL,
+                                  &query->locator,
+                                  "Could not prefix subject blank identifier");
+          return NULL;
+        }
+        s = rasqal_new_simple_literal(query_results->world, RASQAL_LITERAL_BLANK,
+                                      nodeid);
+        if(!s) {
+          rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_FATAL,
+                                  &query->locator,
+                                  "Could not create a new subject blank literal");
+          return NULL;
+        }
+        rs->subject = nodeid;
+        rs->subject_type = RAPTOR_IDENTIFIER_TYPE_ANONYMOUS;
+        break;
+
+      case RASQAL_LITERAL_QNAME:
+      case RASQAL_LITERAL_PATTERN:
+      case RASQAL_LITERAL_BOOLEAN:
+      case RASQAL_LITERAL_INTEGER:
+      case RASQAL_LITERAL_DOUBLE:
+      case RASQAL_LITERAL_FLOAT:
+      case RASQAL_LITERAL_VARIABLE:
+      case RASQAL_LITERAL_DECIMAL:
+      case RASQAL_LITERAL_DATETIME:
+        /* QNames should be gone by the time expression eval happens
+         * Everything else is removed by rasqal_literal_as_node() above. 
+         */
+
+      case RASQAL_LITERAL_STRING:
+        /* string [literal] subjects are not RDF */
+
+      case RASQAL_LITERAL_UNKNOWN:
+      default:
+        /* case RASQAL_LITERAL_STRING: */
+        rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_WARNING,
+                                &query->locator,
+                                "Triple with non-URI/blank node subject skipped");
+        skipped = 1;
+        break;
+    }
+    if(skipped) {
+      if(s)
+        rasqal_free_literal(s);
+      continue;
+    }
+    
+
+    p = rasqal_literal_as_node(t->predicate);
+    if(!p) {
+      rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_WARNING,
+                              &query->locator,
+                              "Triple with unbound predicate skipped");
+      rasqal_free_literal(s);
+      skipped = 1;
+      continue;
+    }
+    switch(p->type) {
+      case RASQAL_LITERAL_URI:
+        rs->predicate = p->value.uri;
+        rs->predicate_type = RAPTOR_IDENTIFIER_TYPE_RESOURCE;
+        break;
+
+      case RASQAL_LITERAL_QNAME:
+      case RASQAL_LITERAL_PATTERN:
+      case RASQAL_LITERAL_BOOLEAN:
+      case RASQAL_LITERAL_INTEGER:
+      case RASQAL_LITERAL_DOUBLE:
+      case RASQAL_LITERAL_FLOAT:
+      case RASQAL_LITERAL_VARIABLE:
+      case RASQAL_LITERAL_DECIMAL:
+      case RASQAL_LITERAL_DATETIME:
+        /* QNames should be gone by the time expression eval happens
+         * Everything else is removed by rasqal_literal_as_node() above. 
+         */
+
+      case RASQAL_LITERAL_BLANK:
+      case RASQAL_LITERAL_STRING:
+        /* blank node or string [literal] predicates are not RDF */
+
+      case RASQAL_LITERAL_UNKNOWN:
+      default:
+        rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_WARNING,
+                                &query->locator,
+                                "Triple with non-URI predicate skipped");
+        skipped = 1;
+        break;
+    }
+    if(skipped) {
+      rasqal_free_literal(s);
+      if(p)
+        rasqal_free_literal(p);
+      continue;
+    }
+
+    o = rasqal_literal_as_node(t->object);
+    if(!o) {
+      rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_WARNING,
+                              &query->locator,
+                              "Triple with unbound object skipped");
+      rasqal_free_literal(s);
+      rasqal_free_literal(p);
+      skipped = 1;
+      continue;
+    }
+    switch(o->type) {
+      case RASQAL_LITERAL_URI:
+        rs->object = o->value.uri;
+        rs->object_type = RAPTOR_IDENTIFIER_TYPE_RESOURCE;
+        break;
+
+      case RASQAL_LITERAL_BLANK:
+        nodeid = rasqal_prefix_id(query_results->result_count,
+                                  (unsigned char*)o->string);
+        rasqal_free_literal(o);
+        if(!nodeid) {
+          rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_FATAL,
+                                  &query->locator,
+                                  "Could not prefix blank identifier");
+          rasqal_free_literal(s);
+          rasqal_free_literal(p);
+          return NULL;
+        }
+        o = rasqal_new_simple_literal(query_results->world, RASQAL_LITERAL_BLANK,
+                                      nodeid);
+        if(!o) {
+          rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_FATAL,
+                                  &query->locator,
+                                  "Could not create a new subject blank literal");
+          rasqal_free_literal(s);
+          rasqal_free_literal(p);
+          return NULL;
+        }
+        rs->object = nodeid;
+        rs->object_type = RAPTOR_IDENTIFIER_TYPE_ANONYMOUS;
+        break;
+
+      case RASQAL_LITERAL_STRING:
+        rs->object = o->string;
+        rs->object_literal_language = (const unsigned char*)o->language;
+        rs->object_literal_datatype = o->datatype;
+        rs->object_type = RAPTOR_IDENTIFIER_TYPE_LITERAL;
+        break;
+
+      case RASQAL_LITERAL_QNAME:
+      case RASQAL_LITERAL_PATTERN:
+      case RASQAL_LITERAL_BOOLEAN:
+      case RASQAL_LITERAL_INTEGER:
+      case RASQAL_LITERAL_DOUBLE:
+      case RASQAL_LITERAL_FLOAT:
+      case RASQAL_LITERAL_VARIABLE:
+      case RASQAL_LITERAL_DECIMAL:
+      case RASQAL_LITERAL_DATETIME:
+        /* QNames should be gone by the time expression eval happens
+         * Everything else is removed by rasqal_literal_as_node() above. 
+         */
+
+      case RASQAL_LITERAL_UNKNOWN:
+      default:
+        rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_WARNING,
+                                &query->locator,
+                                "Triple with unknown object skipped");
+        skipped = 1;
+        break;
+    }
+    if(skipped) {
+      rasqal_free_literal(s);
+      rasqal_free_literal(p);
+      if(o)
+        rasqal_free_literal(o);
+      continue;
+    }
+    
+    /* dispose previous triple if any */
+    if(query_results->triple) {
+      rasqal_free_triple(query_results->triple);
+      query_results->triple = NULL;
+    }
+
+    /* for saving s, p, o for later disposal */
+    query_results->triple = rasqal_new_triple(s, p, o);
+
+    /* got triple, return it */
+    break;
+  }
+  
+  return rs;
+}
+
+
+/**
+ * rasqal_query_results_next_triple:
+ * @query_results: #rasqal_query_results query_results
+ *
+ * Move to the next triple result.
+ * 
+ * Return value: non-0 if failed or results exhausted
+ **/
+int
+rasqal_query_results_next_triple(rasqal_query_results* query_results)
+{
+  rasqal_query* query;
+  int rc = 0;
+  
+  if(!query_results || query_results->failed || query_results->finished)
+    return 1;
+  
+  if(!rasqal_query_results_is_graph(query_results))
+    return 1;
+  
+  query = query_results->query;
+  if(!query)
+    return 1;
+
+  if(query->verb == RASQAL_QUERY_VERB_DESCRIBE)
+    return 1;
+  
+  if(query_results->triple) {
+    rasqal_free_triple(query_results->triple);
+    query_results->triple = NULL;
+  }
+
+  if(++query_results->current_triple_result >= raptor_sequence_size(query->constructs)) {
+    /* Remove any current row */
+    if(query_results->row) {
+      rasqal_free_row(query_results->row);
+      query_results->row = NULL;
+    }
+    
+    /* Now try to get a new one */
+    if(rasqal_query_results_ensure_have_row_internal(query_results))
+      return 1;
+    
+    query_results->current_triple_result = -1;
+  }
+
+  return rc;
+}
+
+
+/**
+ * rasqal_query_results_get_boolean:
+ * @query_results: #rasqal_query_results query_results
+ *
+ * Get boolean query result.
+ *
+ * The return value is only meaningful if this is a boolean
+ * query result - see rasqal_query_results_is_boolean()
+ *
+ * Return value: boolean query result - >0 is true, 0 is false, <0 on error
+ */
+int
+rasqal_query_results_get_boolean(rasqal_query_results* query_results)
+{
+  if(!query_results || query_results->failed)
+    return -1;
+  
+  if(!rasqal_query_results_is_boolean(query_results))
+    return -1;
+  
+  if(query_results->ask_result >= 0)
+    return query_results->ask_result;
+
+  query_results->ask_result= (query_results->result_count > 0) ? 1 : 0;
+  query_results->finished= 1;
+  
+  return query_results->ask_result;
+}
+
+
+/**
+ * rasqal_query_results_write:
+ * @iostr: #raptor_iostream to write the query to
+ * @results: #rasqal_query_results query results format
+ * @format_uri: #raptor_uri describing the format to write (or NULL for default)
+ * @base_uri: #raptor_uri base URI of the output format
+ *
+ * Write the query results to an iostream in a format.
+ * 
+ * This uses the #rasqal_query_results_formatter class
+ * and the rasqal_query_results_formatter_write() method
+ * to perform the formatting. See
+ * rasqal_query_results_formats_enumerate() 
+ * for obtaining the supported format URIs at run time.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_results_write(raptor_iostream *iostr,
+                           rasqal_query_results* results,
+                           raptor_uri *format_uri,
+                           raptor_uri *base_uri)
+{
+  rasqal_query_results_formatter *formatter;
+  int status;
+  
+  if(!results || results->failed)
+    return 1;
+
+  formatter = rasqal_new_query_results_formatter(results->world, NULL,
+                                                 format_uri);
+  if(!formatter)
+    return 1;
+
+  status = rasqal_query_results_formatter_write(iostr, formatter,
+                                                results, base_uri);
+
+  rasqal_free_query_results_formatter(formatter);
+  return status;
+}
+
+
+/**
+ * rasqal_query_results_read:
+ * @iostr: #raptor_iostream to read the query from
+ * @results: #rasqal_query_results query results format
+ * @format_uri: #raptor_uri describing the format to read (or NULL for default)
+ * @base_uri: #raptor_uri base URI of the input format
+ *
+ * Read the query results from an iostream in a format.
+ * 
+ * This uses the #rasqal_query_results_formatter class
+ * and the rasqal_query_results_formatter_read() method
+ * to perform the formatting. See
+ * rasqal_query_results_formats_enumerate() 
+ * for obtaining the supported format URIs at run time.
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_results_read(raptor_iostream *iostr,
+                          rasqal_query_results* results,
+                          raptor_uri *format_uri,
+                          raptor_uri *base_uri)
+{
+  rasqal_query_results_formatter *formatter;
+  int status;
+  
+  if(!results || results->failed)
+    return 1;
+
+  formatter = rasqal_new_query_results_formatter(results->world, NULL,
+                                                 format_uri);
+  if(!formatter)
+    return 1;
+
+  status = rasqal_query_results_formatter_read(results->world, iostr, formatter,
+                                               results, base_uri);
+
+  rasqal_free_query_results_formatter(formatter);
+  return status;
+}
+
+
+/**
+ * rasqal_query_results_add_row:
+ * @query_results: query results object
+ * @row: query result row
+ *
+ * INTERNAL - Add a query result row to the sequence of result rows
+ */
+void
+rasqal_query_results_add_row(rasqal_query_results* query_results,
+                             rasqal_row* row)
+{
+  if(!query_results->results_sequence) {
+    query_results->results_sequence = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_row, (raptor_sequence_print_handler*)rasqal_row_print);
+    query_results->result_count = 1;
+  }
+
+  row->offset = query_results->result_count-1;
+  raptor_sequence_push(query_results->results_sequence, row);
+}
+
+
+/**
+ * rasqal_query_results_execute_and_store_results:
+ * @query_results: query results object
+ *
+ * INTERNAL - Store all query result (rows) immediately
+ *
+ * Return value: non-0 on finished or failure
+ */
+static int
+rasqal_query_results_execute_and_store_results(rasqal_query_results* query_results)
+{
+  rasqal_query* query;
+  raptor_sequence* seq = NULL;
+
+  query = query_results->query;
+
+  if(query_results->results_sequence)
+     raptor_free_sequence(query_results->results_sequence);
+
+  if(query_results->execution_factory->get_all_rows) {
+    rasqal_engine_error execution_error = RASQAL_ENGINE_OK;
+
+    seq = query_results->execution_factory->get_all_rows(query_results->execution_data, &execution_error);
+    if(execution_error == RASQAL_ENGINE_FAILED)
+      query_results->failed = 1;
+  }
+
+  query_results->results_sequence = seq;
+
+  if(!seq) {
+    query_results->finished = 1;
+  } else {
+    int size;
+
+    size = raptor_sequence_size(seq);
+    query_results->finished = (size == 0);
+    
+    if(query && !query->limit)
+      query_results->finished = 1;
+    
+    if(!query_results->finished) {
+      /* Reset to first result, index-1 into sequence of results */
+      query_results->result_count = 0;
+      
+      /* skip past any OFFSET */
+      if(query && query->offset > 0) {
+        query_results->result_count += query->offset;
+        if(query_results->result_count >= size)
+          query_results->finished = 1;
+      }
+      
+    }
+    
+    if(query_results->finished)
+      query_results->result_count = 0;
+    else {
+      if(query && query->constructs)
+        rasqal_query_results_update_bindings(query_results);
+    }
+  }
+
+  return query_results->finished;
+}
+
+
+static void
+rasqal_query_results_update_bindings(rasqal_query_results* query_results)
+{
+  int i;
+  int size;
+
+  /* bind the construct variables again if running through a sequence */
+  size = rasqal_variables_table_get_named_variables_count(query_results->vars_table);
+  for(i = 0; i< size; i++) {
+    rasqal_variable* v;
+    rasqal_literal* value;
+    v = rasqal_variables_table_get(query_results->vars_table, i);
+    value = rasqal_query_results_get_binding_value(query_results, i);
+    rasqal_variable_set_value(v, rasqal_new_literal_from_literal(value));
+  }
+}
+
+
+void
+rasqal_query_results_remove_query_reference(rasqal_query_results* query_results)
+{
+  rasqal_query* query = query_results->query;
+  query_results->query = NULL;
+
+  rasqal_free_query(query);
+}
+
+
+rasqal_variables_table*
+rasqal_query_results_get_variables_table(rasqal_query_results* query_results)
+{
+  return query_results->vars_table;
+}
+
diff --git a/src/rasqal/rasqal_query_transform.c b/src/rasqal/rasqal_query_transform.c
new file mode 100644
index 0000000..afaf7e0
--- /dev/null
+++ b/src/rasqal/rasqal_query_transform.c
@@ -0,0 +1,1320 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_query_transform.c - Rasqal query transformations
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#if 0
+#undef RASQAL_DEBUG
+#define RASQAL_DEBUG 2
+#endif
+
+#define DEBUG_FH stderr
+
+
+int
+rasqal_query_expand_triple_qnames(rasqal_query* rq)
+{
+  int i;
+
+  if(!rq->triples)
+    return 0;
+  
+  /* expand qnames in triples */
+  for(i = 0; i< raptor_sequence_size(rq->triples); i++) {
+    rasqal_triple* t = (rasqal_triple*)raptor_sequence_get_at(rq->triples, i);
+    if(rasqal_literal_expand_qname(rq, t->subject) ||
+       rasqal_literal_expand_qname(rq, t->predicate) ||
+       rasqal_literal_expand_qname(rq, t->object))
+      return 1;
+  }
+
+  return 0;
+}
+
+
+int
+rasqal_sequence_has_qname(raptor_sequence *seq)
+{
+  int i;
+
+  if(!seq)
+    return 0;
+  
+  /* expand qnames in triples */
+  for(i = 0; i< raptor_sequence_size(seq); i++) {
+    rasqal_triple* t = (rasqal_triple*)raptor_sequence_get_at(seq, i);
+    if(rasqal_literal_has_qname(t->subject) ||
+       rasqal_literal_has_qname(t->predicate) ||
+       rasqal_literal_has_qname(t->object))
+      return 1;
+  }
+
+  return 0;
+}
+
+
+static int
+rasqal_graph_pattern_constraints_has_qname(rasqal_graph_pattern* gp) 
+{
+  int i;
+  
+  /* check for qnames in sub graph patterns */
+  if(gp->graph_patterns) {
+    /* check for constraint qnames in rasqal_graph_patterns */
+    for(i = 0; i < raptor_sequence_size(gp->graph_patterns); i++) {
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+      if(rasqal_graph_pattern_constraints_has_qname(sgp))
+        return 1;
+    }
+  }
+
+  if(!gp->filter_expression)
+    return 0;
+  
+  /* check for qnames in constraint expressions */
+  if(rasqal_expression_visit(gp->filter_expression,
+                             rasqal_expression_has_qname, gp))
+    return 1;
+
+  return 0;
+}
+
+
+int
+rasqal_query_constraints_has_qname(rasqal_query* rq) 
+{
+  if(!rq->query_graph_pattern)
+    return 0;
+  
+  return rasqal_graph_pattern_constraints_has_qname(rq->query_graph_pattern);
+}
+
+
+int
+rasqal_query_expand_graph_pattern_constraints_qnames(rasqal_query *rq,
+                                                     rasqal_graph_pattern* gp)
+{
+  int i;
+  
+  /* expand qnames in sub graph patterns */
+  if(gp->graph_patterns) {
+    /* check for constraint qnames in rasqal_graph_patterns */
+    for(i = 0; i < raptor_sequence_size(gp->graph_patterns); i++) {
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+      if(rasqal_query_expand_graph_pattern_constraints_qnames(rq, sgp))
+        return 1;
+    }
+  }
+
+  if(!gp->filter_expression)
+    return 0;
+  
+  /* expand qnames in constraint expressions */
+  if(rasqal_expression_visit(gp->filter_expression,
+                             rasqal_expression_expand_qname, rq))
+    return 1;
+
+  return 0;
+}
+
+
+int
+rasqal_query_expand_query_constraints_qnames(rasqal_query *rq) 
+{
+  return rasqal_query_expand_graph_pattern_constraints_qnames(rq, 
+                                                              rq->query_graph_pattern);
+}
+
+
+static int
+rasqal_query_convert_blank_node_to_anonymous_variable(rasqal_query *rq,
+                                                       rasqal_literal *l)
+{
+  rasqal_variable* v;
+  
+  v = rasqal_new_variable_typed(rq, 
+                                RASQAL_VARIABLE_TYPE_ANONYMOUS,
+                                (unsigned char*)l->string, NULL);
+  /* rasqal_new_variable_typed took ownership of the l->string name.
+   * Set to NULL to prevent double delete. */
+  l->string = NULL;
+  
+  if(!v)
+    return 1; /* error */
+
+  /* Convert the blank node literal into a variable literal */
+  l->type = RASQAL_LITERAL_VARIABLE;
+  l->value.variable = v;
+
+  return 0; /* success */
+}
+
+
+/**
+ * rasqal_query_build_anonymous_variables:
+ * @rq: query
+ *
+ * INTERNAL - Turn triple blank node parts into anonymous variables
+ *
+ * These are the blank nodes such as (Turtle/SPARQL):
+ *   _:name or [] or [ prop value ] or ( collection of things )
+ *
+ * Return value: non-0 on failure
+ */
+int
+rasqal_query_build_anonymous_variables(rasqal_query* rq)
+{
+  int i;
+  int rc = 1;
+  raptor_sequence *s = rq->triples;
+  
+  for(i = 0; i < raptor_sequence_size(s); i++) {
+    rasqal_triple* t = (rasqal_triple*)raptor_sequence_get_at(s, i);
+    if(t->subject->type == RASQAL_LITERAL_BLANK &&
+       rasqal_query_convert_blank_node_to_anonymous_variable(rq, t->subject))
+      goto done;
+    if(t->predicate->type == RASQAL_LITERAL_BLANK &&
+       rasqal_query_convert_blank_node_to_anonymous_variable(rq, t->predicate))
+      goto done;
+    if(t->object->type == RASQAL_LITERAL_BLANK &&
+       rasqal_query_convert_blank_node_to_anonymous_variable(rq, t->object))
+      goto done;
+  }
+
+  rc = 0;
+
+  done:
+  return rc;
+}
+
+
+/**
+ * rasqal_query_expand_wildcards:
+ * @rq: query
+ *
+ * INTERNAL - expand RDQL/SPARQL SELECT * to a full list of select variables
+ *
+ * Return value: non-0 on failure
+ */
+int
+rasqal_query_expand_wildcards(rasqal_query* rq)
+{
+  int i;
+  int size;
+  
+  if(rq->verb != RASQAL_QUERY_VERB_SELECT || !rq->wildcard)
+    return 0;
+  
+  /* If 'SELECT *' was given, make the selects be a list of all variables */
+  rq->selects = raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_variable_print);
+  if(!rq->selects)
+    return 1;
+  
+  size = rasqal_variables_table_get_named_variables_count(rq->vars_table);
+  for(i = 0; i < size; i++) {
+    rasqal_variable* v = rasqal_variables_table_get(rq->vars_table, i);
+    if(raptor_sequence_push(rq->selects, v))
+      return 1;
+  }
+
+  rq->select_variables_count = size;
+
+  return 0;
+}
+
+
+/**
+ * rasqal_query_remove_duplicate_select_vars:
+ * @rq: query
+ *
+ * INTERNAL - remove duplicate variables in SELECT sequence and warn
+ *
+ * The order of the select variables is preserved.
+ *
+ * Return value: non-0 on failure
+ */
+int
+rasqal_query_remove_duplicate_select_vars(rasqal_query* rq)
+{
+  int i;
+  int modified = 0;
+  int size;
+  raptor_sequence* seq = rq->selects;
+  raptor_sequence* new_seq;
+  
+  if(!seq)
+    return 1;
+
+  size = raptor_sequence_size(seq);
+  if(!size)
+    return 0;
+  
+  new_seq = raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_variable_print);
+  if(!new_seq)
+    return 1;
+  
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG1("bound variables before deduping: "); 
+  raptor_sequence_print(rq->selects, DEBUG_FH);
+  fputs("\n", DEBUG_FH); 
+#endif
+
+  for(i = 0; i < size; i++) {
+    int j;
+    rasqal_variable *v;
+    int warned = 0;
+    
+    v = (rasqal_variable*)raptor_sequence_get_at(seq, i);
+    if(!v)
+      continue;
+
+    for(j = 0; j < i; j++) {
+      rasqal_variable *v2;
+      v2 = (rasqal_variable*)raptor_sequence_get_at(seq, j);
+      
+      if(v == v2) {
+        if(!warned) {
+          rasqal_log_error_simple(rq->world, RAPTOR_LOG_LEVEL_WARNING,
+                                  &rq->locator,
+                                  "Variable %s duplicated in SELECT.", 
+                                  v->name);
+          warned = 1;
+        }
+      }
+    }
+    if(!warned) {
+      raptor_sequence_push(new_seq, v);
+      modified = 1;
+    }
+  }
+  
+  if(modified) {
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG1("bound variables after deduping: "); 
+    raptor_sequence_print(new_seq, DEBUG_FH);
+    fputs("\n", DEBUG_FH); 
+#endif
+    raptor_free_sequence(rq->selects);
+    rq->selects = new_seq;
+    rq->select_variables_count = raptor_sequence_size(rq->selects);
+  } else
+    raptor_free_sequence(new_seq);
+
+  return 0;
+}
+
+
+/**
+ * rasqal_query_triples_build_declared_in_internal:
+ * @query: the #rasqal_query to find the variables in
+ * @declared_in: array to write declared_in
+ * @start_column: first column in triples array
+ * @end_column: last column in triples array
+ *
+ * INTERNAL - Mark where variables are first declared in a sequence of triples
+ * 
+ **/
+static void
+rasqal_query_triples_build_declared_in_internal(rasqal_query* query,
+                                                int *declared_in,
+                                                int start_column,
+                                                int end_column)
+{
+  int col;
+  
+  for(col = start_column; col <= end_column; col++) {
+    rasqal_triple *t;
+    rasqal_variable *v;
+    
+    t = (rasqal_triple*)raptor_sequence_get_at(query->triples, col);
+
+    if((v = rasqal_literal_as_variable(t->subject))) {
+      if(declared_in[v->offset] < 0)
+        declared_in[v->offset] = col;
+    }
+    if((v = rasqal_literal_as_variable(t->predicate))) {
+      if(declared_in[v->offset] < 0)
+        declared_in[v->offset] = col;
+    }
+    if((v = rasqal_literal_as_variable(t->object))) {
+      if(declared_in[v->offset] < 0)
+        declared_in[v->offset] = col;
+    }
+    if(t->origin) {
+      if((v = rasqal_literal_as_variable(t->origin))) {
+        if(declared_in[v->offset] < 0)
+          declared_in[v->offset] = col;
+      }
+    }
+
+  }
+}
+
+
+/**
+ * rasqal_query_triples_build_declared_in:
+ * @query: the #rasqal_query to find the variables in
+ * @size:
+ * @start_column: first column in triples array
+ * @end_column: last column in triples array
+ *
+ * INTERNAL - Mark where variables are first declared in a graph_pattern tree walk
+ * 
+ **/
+int*
+rasqal_query_triples_build_declared_in(rasqal_query* query,
+                                       int size,
+                                       int start_column,
+                                       int end_column)
+{
+  int i;
+  int *declared_in;
+  
+  declared_in = (int*)RASQAL_CALLOC(intarray, size+1, sizeof(int));
+  if(!declared_in)
+    return NULL;
+
+  for(i = 0; i < size; i++)
+    declared_in[i] = -1;
+
+  rasqal_query_triples_build_declared_in_internal(query, declared_in,
+                                                  start_column,
+                                                  end_column);
+  return declared_in;
+}
+
+
+/**
+ * rasqal_query_graph_pattern_build_declared_in:
+ * @query: the #rasqal_query to find the variables in
+ * @declared_in: array to write declared_in
+ * @gp: graph pattern to use
+ *
+ * INTERNAL - Mark where variables are first declared in a graph_pattern tree walk
+ * 
+ **/
+static int
+rasqal_query_graph_pattern_build_declared_in(rasqal_query* query,
+                                             int *declared_in,
+                                             rasqal_graph_pattern *gp)
+{
+  if(gp->graph_patterns) {
+    int i;
+
+    for(i = 0; i < raptor_sequence_size(gp->graph_patterns); i++) {
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+      if(rasqal_query_graph_pattern_build_declared_in(query, declared_in, sgp))
+        return 1;
+    }
+  }
+
+  if(!gp->triples)
+    return 0;
+
+  rasqal_query_triples_build_declared_in_internal(query, declared_in,
+                                                  gp->start_column,
+                                                  gp->end_column);
+  return 0;
+}
+
+
+/**
+ * rasqal_query_build_declared_in:
+ * @query: the #rasqal_query to find the variables in
+ *
+ * INTERNAL - Record the triple columns where variables are first declared in a query
+ *
+ * Constructs an array indexed by variable offset of columns where
+ * the variable is first declared.  The order used is a tree walk of
+ * the graph patterns.  Later mentions of the variable are not marked.
+ *
+ * Return value: non-0 on failure
+ **/
+static int
+rasqal_query_build_declared_in(rasqal_query* query)
+{
+  int i;
+  int size;
+
+  size = rasqal_variables_table_get_total_variables_count(query->vars_table);
+  
+  query->variables_declared_in = (int*)RASQAL_CALLOC(intarray, size+1, sizeof(int));
+  if(!query->variables_declared_in)
+    return 1;
+
+  for(i = 0; i < size; i++)
+    query->variables_declared_in[i] = -1;
+
+  return rasqal_query_graph_pattern_build_declared_in(query,
+                                                      query->variables_declared_in,
+                                                      query->query_graph_pattern);
+}
+
+
+/**
+ * rasqal_query_check_unused_variables:
+ * @query: the #rasqal_query to check
+ * @declared_in: array of columns where variables are declared as created by rasqal_query_build_declared_in()
+ *
+ * INTERNAL - warn for variables that are selected but not mentioned in a triple
+ *
+ * Return value: non-0 on failure
+ */
+static int
+rasqal_query_check_unused_variables(rasqal_query* query, int *declared_in)
+{
+  int i;
+  int size;
+  
+  /* check declared in only for named variables since only they can
+   * appear in SELECT $vars 
+   */
+  size = rasqal_variables_table_get_named_variables_count(query->vars_table);
+  for(i = 0; i < size; i++) {
+    int column = declared_in[i];
+    rasqal_variable *v;
+
+    v = rasqal_variables_table_get(query->vars_table, i);
+    if(column >= 0) {
+#if RASQAL_DEBUG > 1
+      RASQAL_DEBUG4("Variable %s (%d) was declared in column %d\n",
+                    v->name, i, column);
+#endif
+    } else if(!v->expression)
+      rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_WARNING,
+                              &query->locator,
+                              "Variable %s was selected but is unused in the query.", 
+                              v->name);
+  }
+
+  return 0;
+}
+
+
+/**
+ * rasqal_query_merge_triple_patterns:
+ * @query: query (not used here)
+ * @gp: current graph pattern
+ * @data: visit data (not used here)
+ *
+ * INTERNAL - Join triple patterns in adjacent basic graph patterns into
+ * single basic graph pattern.
+ *
+ * For group graph pattern move all triples
+ *  from { { a } { b } { c }  D... } 
+ *  to { a b c  D... }
+ *  if the types of a, b, c are all BASIC GPs (just triples)
+ *   D... is anything else
+ * 
+ */
+static int
+rasqal_query_merge_triple_patterns(rasqal_query* query,
+                                   rasqal_graph_pattern* gp,
+                                   void* data)
+{
+  int* modified = (int*)data;
+  int checking;
+  int offset;
+
+#if RASQAL_DEBUG > 1
+  printf("rasqal_query_merge_triple_patterns: Checking graph pattern #%d:\n  ", gp->gp_index);
+  rasqal_graph_pattern_print(gp, stdout);
+  fputs("\n", stdout);
+  RASQAL_DEBUG3("Columns %d to %d\n", gp->start_column, gp->end_column);
+#endif
+    
+  if(!gp->graph_patterns) {
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG2("Ending graph patterns %d - no sub-graph patterns\n", gp->gp_index);
+#endif
+    return 0;
+  }
+
+  if(gp->op != RASQAL_GRAPH_PATTERN_OPERATOR_GROUP) {
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG3("Ending graph patterns %d - operator %s\n", gp->gp_index,
+                  rasqal_graph_pattern_operator_as_string(gp->op));
+#endif
+    return 0;
+  }
+
+
+  checking = 1;
+  offset = 0;
+  while(checking) {
+    int bgp_count;
+    rasqal_graph_pattern *dest_bgp;
+    raptor_sequence *seq;
+    int i, j;
+    int first = 0, last = 0;
+    int size = raptor_sequence_size(gp->graph_patterns);
+    
+    /* find first basic graph pattern starting at offset */
+    for(i= offset; i < size; i++) {
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+
+      if(sgp->op == RASQAL_GRAPH_PATTERN_OPERATOR_BASIC) {
+        first = i;
+        break;
+      }
+    }
+    
+    /* None found */
+    if(i >= size)
+      break;
+
+    /* Next time, start after this BGP */
+    offset = i+1;
+    
+    /* count basic graph patterns */
+    bgp_count = 0;
+    dest_bgp = NULL; /* destination graph pattern */
+    for(j = i; j < size; j++) {
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, j);
+
+      if(sgp->op == RASQAL_GRAPH_PATTERN_OPERATOR_BASIC) {
+        bgp_count++;
+        if(!dest_bgp)
+          dest_bgp = sgp;
+        last = j;
+      } else
+        break;
+    }
+
+
+  #if RASQAL_DEBUG > 1
+    RASQAL_DEBUG3("Found sequence of %d basic sub-graph patterns in %d\n", bgp_count, gp->gp_index);
+  #endif
+    if(bgp_count < 2)
+      continue;
+
+  #if RASQAL_DEBUG > 1
+    RASQAL_DEBUG3("OK to merge %d basic sub-graph patterns of %d\n", bgp_count, gp->gp_index);
+
+    RASQAL_DEBUG3("Initial columns %d to %d\n", gp->start_column, gp->end_column);
+  #endif
+    seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print);
+    if(!seq)
+      return 1;
+    for(i = 0; raptor_sequence_size(gp->graph_patterns) > 0; i++) {
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_unshift(gp->graph_patterns);
+      if(i >= first && i <= last) {
+        if(sgp != dest_bgp) {
+          if(rasqal_graph_patterns_join(dest_bgp, sgp)) {
+            RASQAL_DEBUG1("Cannot join graph patterns\n");
+            *modified = -1; /* error flag */
+          }
+          rasqal_free_graph_pattern(sgp);
+        } else
+          raptor_sequence_push(seq, sgp);
+      } else
+        raptor_sequence_push(seq, sgp);
+    }
+    raptor_free_sequence(gp->graph_patterns);
+    gp->graph_patterns = seq;
+
+    if(!*modified)
+      *modified = 1;
+
+  } /* end while checking */
+  
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG3("Ending columns %d to %d\n", gp->start_column, gp->end_column);
+
+  RASQAL_DEBUG2("Ending graph pattern #%d\n  ", gp->gp_index);
+  rasqal_graph_pattern_print(gp, stdout);
+  fputs("\n\n", stdout);
+#endif
+
+  return 0;
+}
+
+
+/**
+ * rasqal_graph_pattern_move_constraints:
+ * @dest_gp: destination graph pattern
+ * @src_gp: src graph pattern
+ *
+ * INTERNAL - copy all constraints from @src_gp graph pattern to @src_gp graph pattern
+ *
+ * Return value: non-0 on error
+ */
+int
+rasqal_graph_pattern_move_constraints(rasqal_graph_pattern* dest_gp, 
+                                      rasqal_graph_pattern* src_gp)
+{
+  int rc = 0;
+  rasqal_expression* e;
+  
+  if(!src_gp->filter_expression)
+    return 0; /* no constraints is not an error */
+  
+  e = rasqal_new_expression_from_expression(src_gp->filter_expression);
+  rc = rasqal_graph_pattern_set_filter_expression(dest_gp, e);
+
+  return rc;
+}
+
+
+/**
+ * rasqal_query_remove_empty_group_graph_patterns:
+ * @query: query (not used here)
+ * @gp: current graph pattern
+ * @data: visit data (not used here)
+ *
+ * INTERNAL - Remove empty group graph patterns
+ *
+ * Return value: non-0 on failure
+ */
+static int
+rasqal_query_remove_empty_group_graph_patterns(rasqal_query* query,
+                                               rasqal_graph_pattern* gp,
+                                               void* data)
+{
+  int i;
+  int saw_empty_gp = 0;
+  raptor_sequence *seq;
+  int* modified = (int*)data;
+  
+  if(!gp->graph_patterns)
+    return 0;
+
+#if RASQAL_DEBUG > 1
+  printf("rasqal_query_remove_empty_group_graph_patterns: Checking graph pattern #%d:\n  ", gp->gp_index);
+  rasqal_graph_pattern_print(gp, stdout);
+  fputs("\n", stdout);
+#endif
+
+  for(i = 0; i < raptor_sequence_size(gp->graph_patterns); i++) {
+    rasqal_graph_pattern *sgp;
+    sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+    if(sgp->graph_patterns && !raptor_sequence_size(sgp->graph_patterns)) {
+      /* One is enough to know we need to rewrite */
+      saw_empty_gp = 1;
+      break;
+    }
+  }
+
+  if(!saw_empty_gp) {
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG2("Ending graph patterns %d - saw no empty groups\n", gp->gp_index);
+#endif
+    return 0;
+  }
+  
+  
+  seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print);
+  if(!seq) {
+    RASQAL_DEBUG1("Cannot create new gp sequence\n");
+    *modified = -1;
+    return 1;
+  }
+  while(raptor_sequence_size(gp->graph_patterns) > 0) {
+    rasqal_graph_pattern *sgp;
+    sgp = (rasqal_graph_pattern*)raptor_sequence_unshift(gp->graph_patterns);
+    if(sgp->graph_patterns && !raptor_sequence_size(sgp->graph_patterns)) {
+      rasqal_graph_pattern_move_constraints(gp, sgp);
+      rasqal_free_graph_pattern(sgp);
+      continue;
+    }
+    raptor_sequence_push(seq, sgp);
+  }
+  raptor_free_sequence(gp->graph_patterns);
+  gp->graph_patterns = seq;
+
+  if(!*modified)
+    *modified = 1;
+  
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("Ending graph pattern #%d\n  ", gp->gp_index);
+  rasqal_graph_pattern_print(gp, stdout);
+  fputs("\n\n", stdout);
+#endif
+
+  return 0;
+}
+
+
+/**
+ * rasqal_query_merge_graph_patterns:
+ * @query: query (not used here)
+ * @gp: current graph pattern
+ * @data: pointer to int modified flag
+ *
+ * INTERNAL - Merge graph patterns where possible
+ *
+ * When size = 1 (never for UNION)
+ * GROUP { A } -> A
+ * OPTIONAL { A } -> OPTIONAL { A }
+ *
+ * When size > 1
+ * GROUP { BASIC{2,} } -> merge-BASIC
+ * OPTIONAL { BASIC{2,} } -> OPTIONAL { merge-BASIC }
+ *
+ * Never merged: UNION
+ */
+int
+rasqal_query_merge_graph_patterns(rasqal_query* query,
+                                  rasqal_graph_pattern* gp,
+                                  void* data)
+{
+  rasqal_graph_pattern_operator op;
+  int merge_gp_ok = 0;
+  int all_gp_op_same = 0;
+  int i;
+  int size;
+  int* modified = (int*)data;
+  
+#if RASQAL_DEBUG > 1
+  printf("rasqal_query_merge_graph_patterns: Checking graph pattern #%d:\n  ",
+         gp->gp_index);
+  rasqal_graph_pattern_print(gp, stdout);
+  fputs("\n", stdout);
+  RASQAL_DEBUG3("Columns %d to %d\n", gp->start_column, gp->end_column);
+#endif
+
+  if(!gp->graph_patterns) {
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG3("Ending graph pattern #%d - operator %s: no sub-graph patterns\n", gp->gp_index,
+                  rasqal_graph_pattern_operator_as_string(gp->op));
+#endif
+    return 0;
+  }
+
+  if(gp->op != RASQAL_GRAPH_PATTERN_OPERATOR_GROUP) {
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG3("Ending graph patterns %d - operator %s: not GROUP\n", gp->gp_index,
+                  rasqal_graph_pattern_operator_as_string(gp->op));
+#endif
+    return 0;
+  }
+
+  size = raptor_sequence_size(gp->graph_patterns);
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG3("Doing %d sub-graph patterns of %d\n", size, gp->gp_index);
+#endif
+  op = RASQAL_GRAPH_PATTERN_OPERATOR_UNKNOWN;
+  all_gp_op_same = 1;
+  for(i = 0; i < size; i++) {
+    rasqal_graph_pattern *sgp;
+    sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+    if(op == RASQAL_GRAPH_PATTERN_OPERATOR_UNKNOWN) {
+      op = sgp->op;
+    } else {
+      if(op != sgp->op) {
+#if RASQAL_DEBUG > 1
+        RASQAL_DEBUG4("Sub-graph pattern #%d is %s different from first %s, cannot merge\n", 
+                      i, rasqal_graph_pattern_operator_as_string(sgp->op), 
+                      rasqal_graph_pattern_operator_as_string(op));
+#endif
+        all_gp_op_same = 0;
+      }
+    }
+  }
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("Sub-graph patterns of %d done\n", gp->gp_index);
+#endif
+  
+  if(!all_gp_op_same) {
+    merge_gp_ok = 0;
+    goto merge_check_done;
+  }
+
+  if(size == 1) {
+    merge_gp_ok = 1;
+    goto merge_check_done;
+  }
+
+
+  /* if size > 1 check if ALL sub-graph patterns are basic graph
+   * patterns and either:
+   *   1) a single triple
+   *   2) a single constraint
+   */
+  for(i = 0; i < size; i++) {
+    rasqal_graph_pattern *sgp;
+    sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+    
+    if(sgp->op != RASQAL_GRAPH_PATTERN_OPERATOR_BASIC) {
+#if RASQAL_DEBUG > 1
+      RASQAL_DEBUG3("Found %s sub-graph pattern #%d\n",
+                    rasqal_graph_pattern_operator_as_string(sgp->op), 
+                    sgp->gp_index);
+#endif
+      merge_gp_ok = 0;
+      break;
+    }
+    
+    /* not ok if there are >1 triples */
+    if(sgp->triples && (sgp->end_column-sgp->start_column+1) > 1) {
+#if RASQAL_DEBUG > 1
+      RASQAL_DEBUG2("Found >1 triples in sub-graph pattern #%d\n", sgp->gp_index);
+#endif
+      merge_gp_ok = 0;
+      break;
+    }
+    
+    /* not ok if there are triples and constraints */
+    if(sgp->triples && sgp->filter_expression) {
+#if RASQAL_DEBUG > 1
+      RASQAL_DEBUG2("Found triples and constraints in sub-graph pattern #%d\n", sgp->gp_index);
+#endif
+      merge_gp_ok = 0;
+      break;
+    }
+    
+    /* was at least 1 OK sub graph-pattern */
+    merge_gp_ok = 1;
+  }
+
+  merge_check_done:
+  
+  if(merge_gp_ok) {
+    raptor_sequence *seq;
+    
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG2("OK to merge sub-graph patterns of %d\n", gp->gp_index);
+
+    RASQAL_DEBUG3("Initial columns %d to %d\n", gp->start_column, gp->end_column);
+#endif
+
+    /* Pretend dest is an empty basic graph pattern */
+    seq = gp->graph_patterns;
+    gp->graph_patterns = NULL;
+    gp->op = op;
+    
+    while(raptor_sequence_size(seq) > 0) {
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_unshift(seq);
+
+      /* fake this so that the join happens */
+      sgp->op = gp->op;
+      if(rasqal_graph_patterns_join(gp, sgp)) {
+        RASQAL_DEBUG1("Cannot join graph patterns\n");
+        *modified = -1; /* error flag */
+      }
+      rasqal_free_graph_pattern(sgp);
+    }
+
+    /* If result is 'basic' but contains graph patterns, turn it into a group */
+    if(gp->graph_patterns && gp->op == RASQAL_GRAPH_PATTERN_OPERATOR_BASIC)
+      gp->op = RASQAL_GRAPH_PATTERN_OPERATOR_GROUP;
+
+    /* Delete any evidence of sub graph patterns */
+    raptor_free_sequence(seq);
+
+    if(!*modified)
+      *modified = 1;
+    
+  } else {
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG2("NOT OK to merge sub-graph patterns of %d\n", gp->gp_index);
+#endif
+  }
+
+#if RASQAL_DEBUG > 1
+  if(merge_gp_ok) {
+    RASQAL_DEBUG2("Ending graph pattern #%d\n  ", gp->gp_index);
+    rasqal_graph_pattern_print(gp, stdout);
+    fputs("\n\n", stdout);
+  }
+#endif
+
+  return 0;
+}
+
+
+struct folding_state {
+  rasqal_query* query;
+  int changes;
+  int failed;
+};
+  
+
+static int
+rasqal_expression_foreach_fold(void *user_data, rasqal_expression *e)
+{
+  struct folding_state *st = (struct folding_state*)user_data;
+  rasqal_query* query;  
+  rasqal_literal* l;
+
+  /* skip if already a  literal or this expression tree is not constant */
+  if(e->op == RASQAL_EXPR_LITERAL || !rasqal_expression_is_constant(e))
+    return 0;
+  
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG2("folding expression %p: ", e);
+  rasqal_expression_print(e, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n");
+#endif
+  
+  query = st->query;
+  l = rasqal_expression_evaluate_v2(query->world, &query->locator,
+                                    e, query->compare_flags);
+  if(!l) {
+    st->failed++;
+    return 1;
+  }
+
+  /* In-situ conversion of 'e' to a literal expression */
+  rasqal_expression_convert_to_literal(e, l);
+  
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG1("folded expression now: ");
+  rasqal_expression_print(e, DEBUG_FH);
+  fputc('\n', DEBUG_FH);
+#endif
+
+  /* change made */
+  st->changes++;
+  
+  return 0;
+}
+
+
+static int
+rasqal_query_expression_fold(rasqal_query* rq, rasqal_expression* e)
+{
+  struct folding_state st;
+
+  st.query = rq;
+  while(1) {
+    st.changes = 0;
+    st.failed = 0;
+    rasqal_expression_visit(e, rasqal_expression_foreach_fold, 
+                            (void*)&st);
+    if(!st.changes || st.failed)
+      break;
+  }
+
+  return st.failed;
+}
+
+
+static int
+rasqal_graph_pattern_fold_expressions(rasqal_query* rq,
+                                      rasqal_graph_pattern* gp)
+{
+  if(!gp)
+    return 1;
+  
+  /* fold expressions in sub graph patterns */
+  if(gp->graph_patterns) {
+    int i;
+    
+    for(i = 0; i < raptor_sequence_size(gp->graph_patterns); i++) {
+      rasqal_graph_pattern *sgp;
+      sgp = (rasqal_graph_pattern*)raptor_sequence_get_at(gp->graph_patterns, i);
+      if(rasqal_graph_pattern_fold_expressions(rq, sgp))
+        return 1;
+    }
+  }
+
+  if(gp->filter_expression)
+    return rasqal_query_expression_fold(rq, gp->filter_expression);
+
+  return 0;
+}
+
+
+static int
+rasqal_query_fold_expressions(rasqal_query* rq)
+{
+  rasqal_graph_pattern *gp = rq->query_graph_pattern;
+  int order_size;
+
+  if(gp)
+    rasqal_graph_pattern_fold_expressions(rq, gp);
+
+  if(!rq->order_conditions_sequence)
+    return 0;
+  
+  order_size = raptor_sequence_size(rq->order_conditions_sequence);
+  if(order_size) {
+    int i;
+    
+    for(i = 0; i < order_size; i++) {
+      rasqal_expression* e;
+      e = (rasqal_expression*)raptor_sequence_get_at(rq->order_conditions_sequence, i);
+      rasqal_query_expression_fold(rq, e);
+    }
+  }
+
+  return 0;
+}
+
+
+static int
+rasqal_query_prepare_count_graph_patterns(rasqal_query* query,
+                                          rasqal_graph_pattern* gp,
+                                          void* data)
+{
+  raptor_sequence* seq = (raptor_sequence*)data;
+
+  if(raptor_sequence_push(seq, gp)) {
+    query->failed = 1;
+    rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_FATAL,
+                            NULL,
+                            "Out of memory in rasqal_query_prepare_count_graph_patterns()");
+    return 1;
+  }
+  gp->gp_index = (query->graph_pattern_count++);
+  return 0;
+}
+
+
+/**
+ * rasqal_query_prepare_common:
+ * @query: query
+ *
+ * INTERNAL - initialise the remainder of the query structures
+ *
+ * Does not do any execution prepration - this is once-only stuff.
+ *
+ * NOTE: The caller is responsible for ensuring this is called at
+ * most once.  This is currently enforced by rasqal_query_prepare()
+ * using the query->prepared flag when it calls the query factory
+ * prepare method which does the query string parsing and ends by
+ * calling this function.
+ *
+ * Return value: non-0 on failure
+ */
+int
+rasqal_query_prepare_common(rasqal_query *query)
+{
+  int rc = 1;
+
+  if(!query->triples)
+    goto done;
+  
+  /* turn SELECT $a, $a into SELECT $a - editing query->selects */
+  if(query->selects) {
+    if(rasqal_query_remove_duplicate_select_vars(query))
+      goto done;
+  }
+
+  if(query->query_graph_pattern) {
+    /* This query prepare processing requires a query graph pattern.
+     * Not the case for a legal query like 'DESCRIBE <uri>'
+     */
+
+    /* create query->variables_declared_in to find triples where a variable
+     * is first used and look for variables selected that are not used
+     * in the execution order (graph pattern tree walk order).
+     *
+     * The query->variables_declared_in array is used in
+     * rasqal_engine_graph_pattern_init() when trying to figure out
+     * which parts of a triple pattern need to bind to a variable:
+     * only the first reference to it.
+     */
+    if(rasqal_query_build_declared_in(query))
+      goto done;
+
+    /* warn if any of the selected named variables are not in a triple */
+    if(rasqal_query_check_unused_variables(query, query->variables_declared_in))
+      goto done;
+  }
+
+  rasqal_query_fold_expressions(query);
+
+  if(query->query_graph_pattern) {
+#ifndef RASQAL_NO_GP_MERGE
+    int modified;
+    
+#if RASQAL_DEBUG > 1
+    fputs("Initial query graph pattern:\n  ", DEBUG_FH);
+    rasqal_graph_pattern_print(query->query_graph_pattern, DEBUG_FH);
+    fputs("\n", DEBUG_FH);
+#endif
+
+    do {
+      modified = 0;
+      
+      rasqal_query_graph_pattern_visit(query, 
+                                       rasqal_query_merge_triple_patterns,
+                                       &modified);
+      
+#if RASQAL_DEBUG > 1
+      fprintf(DEBUG_FH, "modified=%d after merge triples, query graph pattern now:\n  ", modified);
+      rasqal_graph_pattern_print(query->query_graph_pattern, DEBUG_FH);
+      fputs("\n", DEBUG_FH);
+#endif
+
+      rasqal_query_graph_pattern_visit(query,
+                                       rasqal_query_remove_empty_group_graph_patterns,
+                                       &modified);
+      
+#if RASQAL_DEBUG > 1
+      fprintf(DEBUG_FH, "modified=%d after remove empty groups, query graph pattern now:\n  ", modified);
+      rasqal_graph_pattern_print(query->query_graph_pattern, DEBUG_FH);
+      fputs("\n", DEBUG_FH);
+#endif
+
+      rasqal_query_graph_pattern_visit(query, 
+                                       rasqal_query_merge_graph_patterns,
+                                       &modified);
+
+#if RASQAL_DEBUG > 1
+      fprintf(DEBUG_FH, "modified=%d  after merge graph patterns, query graph pattern now:\n  ", modified);
+      rasqal_graph_pattern_print(query->query_graph_pattern, DEBUG_FH);
+      fputs("\n", DEBUG_FH);
+#endif
+
+    } while(modified>0);
+
+    rc = modified; /* error if modified<0, success if modified==0 */
+    if(rc)
+      goto done;
+
+#endif /* !RASQAL_NO_GP_MERGE */
+
+    /* Label all graph patterns with an index 0.. for use in discovering
+     * the size of the graph pattern execution data array
+     */
+    query->graph_pattern_count = 0;
+
+    /* This sequence stores shared pointers to the graph patterns it
+     * finds, indexed by the gp_index
+     */
+    query->graph_patterns_sequence = raptor_new_sequence(NULL, NULL);
+    if(!query->graph_patterns_sequence)
+      return 1;
+
+    rasqal_query_graph_pattern_visit(query, 
+                                     rasqal_query_prepare_count_graph_patterns,
+                                     query->graph_patterns_sequence);
+  }
+
+
+  rc = 0;
+
+  done:
+  return rc;
+}
+
+
+/**
+ * rasqal_graph_patterns_join:
+ * @dest_gp: destination graph pattern
+ * @src_gp: src graph pattern
+ *
+ * INTERNAL - merge @src_gp graph pattern into @dest_gp graph pattern
+ *
+ * Return value: non-0 on error
+ */
+int
+rasqal_graph_patterns_join(rasqal_graph_pattern *dest_gp,
+                           rasqal_graph_pattern *src_gp)
+{
+  int rc;
+
+  if(!src_gp || !dest_gp)
+    return 0;
+
+  if(src_gp->op != dest_gp->op) {
+    RASQAL_DEBUG3("Source operator %s != Destination operator %s, ending\n",
+                  rasqal_graph_pattern_operator_as_string(src_gp->op),
+                  rasqal_graph_pattern_operator_as_string(dest_gp->op));
+    return 1;
+  }
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("Joining graph pattern #%d\n  ", src_gp->gp_index);
+  rasqal_graph_pattern_print(src_gp, DEBUG_FH);
+  fprintf(DEBUG_FH, "\nto graph pattern #%d\n  ", dest_gp->gp_index);
+  rasqal_graph_pattern_print(dest_gp, DEBUG_FH);
+  fprintf(DEBUG_FH, "\nboth of operator %s\n",
+          rasqal_graph_pattern_operator_as_string(src_gp->op));
+#endif
+    
+
+  if(src_gp->graph_patterns) {
+    if(!dest_gp->graph_patterns) {
+      dest_gp->graph_patterns = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern,
+                                                    (raptor_sequence_print_handler*)rasqal_graph_pattern_print);
+      if(!dest_gp->graph_patterns)
+        return -1;
+    }
+
+    raptor_sequence_join(dest_gp->graph_patterns, src_gp->graph_patterns);
+  }
+
+  if(src_gp->triples) {
+    int start_c = src_gp->start_column;
+    int end_c = src_gp->end_column;
+    
+    /* if this is our first triple, save a free/alloc */
+    dest_gp->triples = src_gp->triples;
+    src_gp->triples = NULL;
+    
+    if((dest_gp->start_column < 0) || start_c < dest_gp->start_column)
+      dest_gp->start_column = start_c;
+    if((dest_gp->end_column < 0) || end_c > dest_gp->end_column)
+      dest_gp->end_column = end_c;
+    
+#if RASQAL_DEBUG > 1
+    RASQAL_DEBUG3("Moved triples from columns %d to %d\n", start_c, end_c);
+    RASQAL_DEBUG3("Columns now %d to %d\n", dest_gp->start_column, dest_gp->end_column);
+#endif
+  }
+
+  rc = rasqal_graph_pattern_move_constraints(dest_gp, src_gp);
+
+  if(src_gp->origin) {
+    dest_gp->origin = src_gp->origin;
+    src_gp->origin = NULL;
+  }
+
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("Result graph pattern #%d\n  ", dest_gp->gp_index);
+  rasqal_graph_pattern_print(dest_gp, stdout);
+  fputs("\n", stdout);
+#endif
+
+  return rc;
+}
diff --git a/src/rasqal/rasqal_raptor.c b/src/rasqal/rasqal_raptor.c
new file mode 100644
index 0000000..26d6fef
--- /dev/null
+++ b/src/rasqal/rasqal_raptor.c
@@ -0,0 +1,816 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_raptor.c - Rasqal triple store implementation with raptor
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+struct rasqal_raptor_triple_s {
+  struct rasqal_raptor_triple_s *next;
+  rasqal_triple *triple;
+};
+
+typedef struct rasqal_raptor_triple_s rasqal_raptor_triple;
+
+typedef struct {
+  rasqal_query* query;
+
+  rasqal_raptor_triple *head;
+  rasqal_raptor_triple *tail;
+
+  /* index used while reading triples into the two arrays below.
+   * This is used to connect a triple to the URI literal of the source
+   */
+  int source_index;
+
+  /* size of the two arrays below */
+  int sources_count;
+  
+  /* shared pointers into query->data_graph uris */
+  raptor_uri* source_uri;
+
+  /* array of URI literals (allocated here) */
+  rasqal_literal **source_literals;
+
+  /* genid base for mapping user bnodes */
+  unsigned char* mapped_id_base;
+  /* length of above string */
+  int mapped_id_base_len;
+} rasqal_raptor_triples_source_user_data;
+
+
+/* prototypes */
+static int rasqal_raptor_init_triples_match(rasqal_triples_match* rtm, rasqal_triples_source *rts, void *user_data, rasqal_triple_meta *m, rasqal_triple *t);
+static int rasqal_raptor_triple_present(rasqal_triples_source *rts, void *user_data, rasqal_triple *t);
+static void rasqal_raptor_free_triples_source(void *user_data);
+
+
+static raptor_uri* 
+ordinal_as_uri(rasqal_world* world, int ordinal) 
+{
+  int t = ordinal;
+  size_t len; 
+  unsigned char *buffer;
+  raptor_uri* uri;
+  
+  len = raptor_rdf_namespace_uri_len + 1 + 1; /* 1 for min-length, 1 for '_' */
+  while(t /= 10)
+    len++;
+  buffer = (unsigned char*)RASQAL_MALLOC(cstring, len + 1);
+  if(!buffer)
+    return NULL;
+  
+  sprintf((char*)buffer, "%s_%d", raptor_rdf_namespace_uri, ordinal);
+#ifdef RAPTOR_V2_AVAILABLE
+  uri = raptor_new_uri_v2(world->raptor_world_ptr, buffer);
+#else
+  uri = raptor_new_uri(buffer);
+#endif
+  RASQAL_FREE(cstring, buffer);
+
+  return uri;
+}
+
+  
+static rasqal_triple*
+raptor_statement_as_rasqal_triple(rasqal_world* world,
+                                  const raptor_statement *statement)
+{
+  rasqal_literal *s, *p, *o;
+
+  if(statement->subject_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) {
+    unsigned char *new_blank;
+    size_t blank_len;
+
+    blank_len = strlen((char*)statement->subject);
+    new_blank = (unsigned char*)RASQAL_MALLOC(cstring, blank_len + 1);
+    strncpy((char*)new_blank, (const char*)statement->subject, blank_len + 1);
+    s = rasqal_new_simple_literal(world, RASQAL_LITERAL_BLANK, new_blank);
+  } else if(statement->subject_type == RAPTOR_IDENTIFIER_TYPE_ORDINAL) {
+    raptor_uri* uri;
+
+    uri = ordinal_as_uri(world, *((int*)statement->subject));
+    if(!uri)
+      return NULL;
+    s = rasqal_new_uri_literal(world, uri);
+  } else {
+    raptor_uri *uri;
+
+#ifdef RAPTOR_V2_AVAILABLE
+    uri = raptor_uri_copy_v2(world->raptor_world_ptr,
+                             (raptor_uri*)statement->subject);
+#else
+    uri = raptor_uri_copy((raptor_uri*)statement->subject);
+#endif
+    s = rasqal_new_uri_literal(world, uri);
+  }
+
+  if(statement->predicate_type == RAPTOR_IDENTIFIER_TYPE_ORDINAL) {
+    raptor_uri* uri = ordinal_as_uri(world, *((int*)statement->predicate));
+
+    if(!uri)
+      return NULL;
+    p = rasqal_new_uri_literal(world, uri);
+  } else {
+    raptor_uri *uri;
+
+#ifdef RAPTOR_V2_AVAILABLE
+    uri = raptor_uri_copy_v2(world->raptor_world_ptr,
+                             (raptor_uri*)statement->predicate);
+#else
+    uri = raptor_uri_copy((raptor_uri*)statement->predicate);
+#endif
+    p = rasqal_new_uri_literal(world, uri);
+  }
+  
+  if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_LITERAL || 
+     statement->object_type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
+    unsigned char *string;
+    char *language = NULL;
+    raptor_uri *uri = NULL;
+    size_t literal_len;
+
+    literal_len = strlen((char*)statement->object);
+    string = (unsigned char*)RASQAL_MALLOC(cstring, literal_len + 1);
+    strncpy((char*)string, (const char*)statement->object, literal_len + 1);
+
+    if(statement->object_literal_language) {
+      size_t language_len;
+      language_len = strlen((const char*)statement->object_literal_language);
+      language = (char*)RASQAL_MALLOC(cstring, language_len + 1);
+      strncpy(language, (const char*)statement->object_literal_language,
+              language_len + 1);
+    }
+
+    if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
+      const unsigned char* dt_uri_string;
+
+      dt_uri_string = (const unsigned char*)raptor_xml_literal_datatype_uri_string;
+#ifdef RAPTOR_V2_AVAILABLE
+      uri = raptor_new_uri_v2(world->raptor_world_ptr, dt_uri_string);
+#else
+      uri = raptor_new_uri(dt_uri_string);
+#endif
+    } else if(statement->object_literal_datatype) {
+      raptor_uri *dt_uri = (raptor_uri*)statement->object_literal_datatype;
+
+#ifdef RAPTOR_V2_AVAILABLE
+      uri = raptor_uri_copy_v2(world->raptor_world_ptr, dt_uri);
+#else
+      uri = raptor_uri_copy(dt_uri);
+#endif
+    }
+    o = rasqal_new_string_literal(world, string, language, uri, NULL);
+  } else if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_ANONYMOUS) {
+    char *blank = (char*)statement->object;
+    unsigned char *new_blank;
+    size_t blank_len;
+
+    blank_len = strlen(blank);
+    new_blank = (unsigned char*)RASQAL_MALLOC(cstring, blank_len + 1);
+    strncpy((char*)new_blank, (const char*)blank, blank_len + 1);
+    o = rasqal_new_simple_literal(world, RASQAL_LITERAL_BLANK, new_blank);
+  } else if(statement->object_type == RAPTOR_IDENTIFIER_TYPE_ORDINAL) {
+    raptor_uri* uri = ordinal_as_uri(world, *((int*)statement->object));
+
+    if(!uri)
+      return NULL;
+    o = rasqal_new_uri_literal(world, uri);
+  } else {
+    raptor_uri *uri;
+
+#ifdef RAPTOR_V2_AVAILABLE
+    uri = raptor_uri_copy_v2(world->raptor_world_ptr,
+                             (raptor_uri*)statement->object);
+#else
+    uri = raptor_uri_copy((raptor_uri*)statement->object);
+#endif
+    o = rasqal_new_uri_literal(world, uri);
+  }
+
+  return rasqal_new_triple(s, p, o);
+}
+
+
+
+static void
+rasqal_raptor_statement_handler(void *user_data, 
+                                const raptor_statement *statement) 
+{
+  rasqal_raptor_triples_source_user_data* rtsc;
+  rasqal_raptor_triple *triple;
+  
+  rtsc = (rasqal_raptor_triples_source_user_data*)user_data;
+
+  triple = (rasqal_raptor_triple*)RASQAL_MALLOC(rasqal_raptor_triple,
+                                                sizeof(rasqal_raptor_triple));
+  triple->next = NULL;
+  triple->triple = raptor_statement_as_rasqal_triple(rtsc->query->world,
+                                                     statement);
+
+  /* this origin URI literal is shared amongst the triples and
+   * freed only in rasqal_raptor_free_triples_source
+   */
+  rasqal_triple_set_origin(triple->triple, 
+                           rtsc->source_literals[rtsc->source_index]);
+
+  if(rtsc->tail)
+    rtsc->tail->next = triple;
+  else
+    rtsc->head = triple;
+
+  rtsc->tail = triple;
+}
+
+
+static void
+rasqal_raptor_error_handler(void *user_data, 
+                            raptor_locator* locator, const char *message)
+{
+  rasqal_query* query = (rasqal_query*)user_data;
+  int locator_len;
+
+  query->failed = 1;
+
+  if(locator &&
+#ifdef RAPTOR_V2_AVAILABLE
+     (locator_len = raptor_format_locator_v2(query->world->raptor_world_ptr,
+                                             NULL, 0, locator)) > 0
+#else
+     (locator_len = raptor_format_locator(NULL, 0, locator)) > 0
+#endif
+    ) {
+    char *buffer = (char*)RASQAL_MALLOC(cstring, locator_len + 1);
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_format_locator_v2(query->world->raptor_world_ptr, buffer,
+                             locator_len, locator);
+#else
+    raptor_format_locator(buffer, locator_len, locator);
+#endif
+
+    rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                            &query->locator,
+                            "Failed to parse %s - %s", buffer, message);
+    RASQAL_FREE(cstring, buffer);
+  } else
+    rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                            &query->locator,
+                            "Failed to parse - %s", message);
+}
+
+
+static unsigned char*
+rasqal_raptor_generate_id_handler(void *user_data,
+                                  raptor_genid_type type,
+                                  unsigned char *user_bnodeid) 
+{
+  rasqal_raptor_triples_source_user_data* rtsc;
+
+  rtsc = (rasqal_raptor_triples_source_user_data*)user_data;
+
+  if(user_bnodeid) {
+    unsigned char *mapped_id;
+    size_t user_bnodeid_len = strlen((const char*)user_bnodeid);
+    
+    mapped_id = (unsigned char*)RASQAL_MALLOC(cstring, 
+                                              rtsc->mapped_id_base_len + 1 + 
+                                              user_bnodeid_len + 1);
+    strncpy((char*)mapped_id, (const char*)rtsc->mapped_id_base, 
+            rtsc->mapped_id_base_len);
+    mapped_id[rtsc->mapped_id_base_len] = '_';
+    strncpy((char*)(mapped_id+rtsc->mapped_id_base_len + 1),
+            (const char*)user_bnodeid, user_bnodeid_len + 1);
+
+    raptor_free_memory(user_bnodeid);
+    return mapped_id;
+  }
+  
+  return rasqal_query_get_genid(rtsc->query, (const unsigned char*)"genid", -1);
+}
+
+
+static int
+rasqal_raptor_new_triples_source(rasqal_query* rdf_query,
+                                 void *factory_user_data,
+                                 void *user_data,
+                                 rasqal_triples_source *rts)
+{
+  rasqal_raptor_triples_source_user_data* rtsc;
+  raptor_parser *parser;
+  int i;
+
+  rtsc = (rasqal_raptor_triples_source_user_data*)user_data;
+
+  if(!rdf_query->data_graphs)
+    return -1;  /* no data */
+
+  rts->init_triples_match = rasqal_raptor_init_triples_match;
+  rts->triple_present = rasqal_raptor_triple_present;
+  rts->free_triples_source = rasqal_raptor_free_triples_source;
+
+  rtsc->sources_count = raptor_sequence_size(rdf_query->data_graphs);
+  /* no default triple source possible */
+  if(!rtsc->sources_count)
+    return -1;  /* no data */
+
+  rtsc->source_literals = (rasqal_literal**)RASQAL_CALLOC(rasqal_literal_ptr,
+                                                          rtsc->sources_count,
+                                                          sizeof(rasqal_literal*));
+
+  rtsc->query = rdf_query;
+
+  for(i = 0; i < rtsc->sources_count; i++) {
+    rasqal_data_graph *dg;
+    raptor_uri* uri;
+    raptor_uri* name_uri;
+
+    dg = (rasqal_data_graph*)raptor_sequence_get_at(rdf_query->data_graphs, i);
+    uri = dg->uri;
+    name_uri = dg->name_uri;
+
+    rtsc->source_index = i;
+#ifdef RAPTOR_V2_AVAILABLE
+    rtsc->source_uri = raptor_uri_copy_v2(rdf_query->world->raptor_world_ptr,
+                                          uri);
+#else
+    rtsc->source_uri = raptor_uri_copy(uri);
+#endif
+    if(name_uri)
+      rtsc->source_literals[i] = rasqal_new_uri_literal(rdf_query->world, 
+#ifdef RAPTOR_V2_AVAILABLE
+                                                        raptor_uri_copy_v2(rdf_query->world->raptor_world_ptr, name_uri)
+#else
+                                                        raptor_uri_copy(name_uri)
+#endif
+                                                        );
+    rtsc->mapped_id_base = rasqal_query_get_genid(rdf_query,
+                                                  (const unsigned char*)"graphid",
+                                                  i);
+    rtsc->mapped_id_base_len = strlen((const char*)rtsc->mapped_id_base);
+
+#ifdef RAPTOR_V2_AVAILABLE
+    parser = raptor_new_parser_v2(rdf_query->world->raptor_world_ptr, "guess");
+#else
+    parser = raptor_new_parser("guess");
+#endif
+    raptor_set_statement_handler(parser, rtsc, rasqal_raptor_statement_handler);
+    raptor_set_error_handler(parser, rdf_query, rasqal_raptor_error_handler);
+    raptor_set_generate_id_handler(parser, rtsc,
+                                   rasqal_raptor_generate_id_handler);
+
+#ifdef RAPTOR_FEATURE_NO_NET
+    if(rdf_query->features[RASQAL_FEATURE_NO_NET])
+      raptor_set_feature(parser, RAPTOR_FEATURE_NO_NET,
+                         rdf_query->features[RASQAL_FEATURE_NO_NET]);
+#endif
+
+    raptor_parse_uri(parser, uri, dg->name_uri);
+    raptor_free_parser(parser);
+
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(rdf_query->world->raptor_world_ptr, rtsc->source_uri);
+#else
+    raptor_free_uri(rtsc->source_uri);
+#endif
+
+    /* This is freed in rasqal_raptor_free_triples_source() */
+    /* rasqal_free_literal(rtsc->source_literal); */
+    RASQAL_FREE(cstring, rtsc->mapped_id_base);
+    
+    if(rdf_query->failed) {
+      rasqal_raptor_free_triples_source(user_data);
+      break;
+    }
+  }
+
+  return rdf_query->failed;
+}
+
+
+/**
+ * rasqal_raptor_triple_match:
+ * @world: rasqal_world object
+ * @triple: #rasqal_triple to match against
+ * @match: #rasqal_triple with wildcards
+ * @parts; parts of the triple to match
+ * .
+ * 
+ * Match a rasqal_triple against a rasqal_triple with NULL
+ * signifying wildcard fields in the rasqal_triple.
+ * 
+ * Return value: non-0 on match
+ **/
+static int
+rasqal_raptor_triple_match(rasqal_world* world,
+                           rasqal_triple *triple,
+                           rasqal_triple *match,
+                           rasqal_triple_parts parts)
+{
+  int rc = 0;
+  
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG1("\ntriple ");
+  rasqal_triple_print(triple, stderr);
+  fputs("\nmatch  ", stderr);
+  rasqal_triple_print(match, stderr);
+  fputs("\n", stderr);
+#endif
+
+  if(match->subject && (parts & RASQAL_TRIPLE_SUBJECT)) {
+    if(!rasqal_literal_equals_flags(triple->subject, match->subject,
+                                    RASQAL_COMPARE_RDF, NULL))
+      goto done;
+  }
+
+  if(match->predicate && (parts & RASQAL_TRIPLE_PREDICATE)) {
+    if(!rasqal_literal_equals_flags(triple->predicate, match->predicate,
+                                    RASQAL_COMPARE_RDF, NULL))
+      goto done;
+  }
+
+  if(match->object && (parts & RASQAL_TRIPLE_OBJECT)) {
+    if(!rasqal_literal_equals_flags(triple->object, match->object,
+                                    RASQAL_COMPARE_RDF, NULL))
+      goto done;
+  }
+
+  if(parts & RASQAL_TRIPLE_ORIGIN) {
+    /* Binding a graph */
+    
+    /* If expecting a graph and triple has none then no match */
+    if(!triple->origin)
+      goto done;
+      
+    if(match->origin) {
+      if(match->origin->type == RASQAL_LITERAL_URI ) {
+        raptor_uri* triple_uri = triple->origin->value.uri;
+        raptor_uri* match_uri = match->origin->value.uri;
+#ifdef RAPTOR_V2_AVAILABLE
+        if(!raptor_uri_equals_v2(world->raptor_world_ptr, triple_uri, match_uri))
+          goto done;
+#else
+        if(!raptor_uri_equals(triple_uri, match_uri))
+          goto done;
+#endif
+      }
+    }
+    
+  } else {
+    /* Not binding a graph */
+    
+    /* If triple has a GRAPH and there is none in the triple pattern, no match */
+    if(triple->origin)
+      goto done;
+  }
+  
+  rc = 1;
+  done:
+  
+#if RASQAL_DEBUG > 1
+  RASQAL_DEBUG2("result: %s\n", (rc ? "match" : "no match"));
+#endif
+
+  return rc;
+}
+
+
+/* non-0 if present */
+static int
+rasqal_raptor_triple_present(rasqal_triples_source *rts, void *user_data, 
+                             rasqal_triple *t) 
+{
+  rasqal_raptor_triples_source_user_data* rtsc;
+  rasqal_raptor_triple *triple;
+  rasqal_triple_parts parts = RASQAL_TRIPLE_SPO;
+  
+  rtsc = (rasqal_raptor_triples_source_user_data*)user_data;
+
+  if(t->origin)
+    parts = (rasqal_triple_parts)(parts | RASQAL_TRIPLE_GRAPH);
+
+  for(triple = rtsc->head; triple; triple = triple->next) {
+    if(rasqal_raptor_triple_match(rtsc->query->world, triple->triple, t, parts))
+      return 1;
+  }
+
+  return 0;
+}
+
+
+
+static void
+rasqal_raptor_free_triples_source(void *user_data)
+{
+  rasqal_raptor_triples_source_user_data* rtsc;
+  rasqal_raptor_triple *cur;
+  int i;
+
+  rtsc = (rasqal_raptor_triples_source_user_data*)user_data;
+  cur = rtsc->head;
+  while(cur) {
+    rasqal_raptor_triple *next = cur->next;
+    rasqal_triple_set_origin(cur->triple, NULL); /* shared URI literal */
+    rasqal_free_triple(cur->triple);
+    RASQAL_FREE(rasqal_raptor_triple, cur);
+    cur = next;
+  }
+
+  for(i = 0; i < rtsc->sources_count; i++) {
+    if(rtsc->source_literals[i])
+      rasqal_free_literal(rtsc->source_literals[i]);
+  }
+  RASQAL_FREE(raptor_literal_ptr, rtsc->source_literals);
+}
+
+
+
+static void
+rasqal_raptor_register_triples_source_factory(rasqal_triples_source_factory *factory) 
+{
+  factory->user_data_size = sizeof(rasqal_raptor_triples_source_user_data);
+  factory->new_triples_source = rasqal_raptor_new_triples_source;
+}
+
+
+typedef struct {
+  rasqal_raptor_triple *cur;
+  rasqal_raptor_triples_source_user_data* source_context;
+  rasqal_triple match;
+
+  /* parts of the triple above to match: always (S,P,O) sometimes C */
+  rasqal_triple_parts parts;
+} rasqal_raptor_triples_match_context;
+
+
+static rasqal_triple_parts
+rasqal_raptor_bind_match(struct rasqal_triples_match_s* rtm,
+                         void *user_data,
+                         rasqal_variable* bindings[4],
+                         rasqal_triple_parts parts)
+{
+  rasqal_raptor_triples_match_context* rtmc;
+  int error = 0;
+  rasqal_triple_parts result = (rasqal_triple_parts)0;
+  
+  rtmc = (rasqal_raptor_triples_match_context*)rtm->user_data;
+
+#ifdef RASQAL_DEBUG
+  if(rtmc->cur) {
+    RASQAL_DEBUG1("  matched statement ");
+    rasqal_triple_print(rtmc->cur->triple, stderr);
+    fputc('\n', stderr);
+  } else
+    RASQAL_FATAL1("  matched NO statement - BUG\n");
+#endif
+
+  /* set variable values from the fields of statement */
+
+  if(bindings[0] && (parts & RASQAL_TRIPLE_SUBJECT)) {
+    rasqal_literal *l = rtmc->cur->triple->subject;
+    RASQAL_DEBUG1("binding subject to variable\n");
+    rasqal_variable_set_value(bindings[0], rasqal_new_literal_from_literal(l));
+    result = RASQAL_TRIPLE_SUBJECT;
+  }
+
+  if(bindings[1] && (parts & RASQAL_TRIPLE_PREDICATE)) {
+    if(bindings[0] == bindings[1]) {
+      if(!rasqal_literal_equals_flags(rtmc->cur->triple->subject,
+                                      rtmc->cur->triple->predicate,
+                                      RASQAL_COMPARE_RDF, &error))
+        return (rasqal_triple_parts)0;
+      if(error)
+        return (rasqal_triple_parts)0;
+      
+      RASQAL_DEBUG1("subject and predicate values match\n");
+    } else {
+      rasqal_literal *l = rtmc->cur->triple->predicate;
+      RASQAL_DEBUG1("binding predicate to variable\n");
+      rasqal_variable_set_value(bindings[1], rasqal_new_literal_from_literal(l));
+      result = (rasqal_triple_parts)(result | RASQAL_TRIPLE_PREDICATE);
+    }
+  }
+
+  if(bindings[2] && (parts & RASQAL_TRIPLE_OBJECT)) {
+    int bind = 1;
+    
+    if(bindings[0] == bindings[2]) {
+      if(!rasqal_literal_equals_flags(rtmc->cur->triple->subject,
+                                      rtmc->cur->triple->object,
+                                      RASQAL_COMPARE_RDF, &error))
+        return (rasqal_triple_parts)0;
+      if(error)
+        return (rasqal_triple_parts)0;
+
+      bind = 0;
+      RASQAL_DEBUG1("subject and object values match\n");
+    }
+    if(bindings[1] == bindings[2] &&
+       !(bindings[0] == bindings[1]) /* don't do this check if ?x ?x ?x */
+       ) {
+      if(!rasqal_literal_equals_flags(rtmc->cur->triple->predicate,
+                                      rtmc->cur->triple->object,
+                                      RASQAL_COMPARE_RDF, &error))
+        return (rasqal_triple_parts)0;
+      if(error)
+        return (rasqal_triple_parts)0;
+
+      bind = 0;
+      RASQAL_DEBUG1("predicate and object values match\n");
+    }
+    
+    if(bind) {
+      rasqal_literal *l = rtmc->cur->triple->object;
+      RASQAL_DEBUG1("binding object to variable\n");
+      rasqal_variable_set_value(bindings[2], rasqal_new_literal_from_literal(l));
+      result = (rasqal_triple_parts)(result | RASQAL_TRIPLE_OBJECT);
+    }
+  }
+
+  if(bindings[3] && (parts & RASQAL_TRIPLE_ORIGIN)) {
+    rasqal_literal *l;
+    l = rasqal_new_literal_from_literal(rtmc->cur->triple->origin);
+    RASQAL_DEBUG1("binding origin to variable\n");
+    rasqal_variable_set_value(bindings[3], l);
+    result = (rasqal_triple_parts)(result | RASQAL_TRIPLE_ORIGIN);
+  }
+
+  return result;
+}
+
+
+
+static void
+rasqal_raptor_next_match(struct rasqal_triples_match_s* rtm, void *user_data)
+{
+  rasqal_raptor_triples_match_context* rtmc;
+
+  rtmc = (rasqal_raptor_triples_match_context*)rtm->user_data;
+
+  while(rtmc->cur) {
+    rtmc->cur = rtmc->cur->next;
+    if(rtmc->cur &&
+       rasqal_raptor_triple_match(rtm->world, rtmc->cur->triple, &rtmc->match,
+                                  rtmc->parts))
+      break;
+  }
+}
+
+static int
+rasqal_raptor_is_end(struct rasqal_triples_match_s* rtm, void *user_data)
+{
+  rasqal_raptor_triples_match_context* rtmc;
+
+  rtmc = (rasqal_raptor_triples_match_context*)rtm->user_data;
+
+  return !rtmc || rtmc->cur == NULL;
+}
+
+
+static void
+rasqal_raptor_finish_triples_match(struct rasqal_triples_match_s* rtm,
+                                   void *user_data)
+{
+  rasqal_raptor_triples_match_context* rtmc;
+
+  rtmc = (rasqal_raptor_triples_match_context*)rtm->user_data;
+
+  if(rtmc->match.subject)
+    rasqal_free_literal(rtmc->match.subject);
+
+  if(rtmc->match.predicate)
+    rasqal_free_literal(rtmc->match.predicate);
+
+  if(rtmc->match.object)
+    rasqal_free_literal(rtmc->match.object);
+
+  if(rtmc->match.origin)
+    rasqal_free_literal(rtmc->match.origin);
+
+  RASQAL_FREE(rasqal_raptor_triples_match_context, rtmc);
+}
+
+
+static int
+rasqal_raptor_init_triples_match(rasqal_triples_match* rtm,
+                                 rasqal_triples_source *rts, void *user_data,
+                                 rasqal_triple_meta *m, rasqal_triple *t)
+{
+  rasqal_raptor_triples_source_user_data* rtsc;
+  rasqal_raptor_triples_match_context* rtmc;
+  rasqal_variable* var;
+
+  rtsc = (rasqal_raptor_triples_source_user_data*)user_data;
+
+  rtm->bind_match = rasqal_raptor_bind_match;
+  rtm->next_match = rasqal_raptor_next_match;
+  rtm->is_end = rasqal_raptor_is_end;
+  rtm->finish = rasqal_raptor_finish_triples_match;
+
+  rtmc = (rasqal_raptor_triples_match_context*)RASQAL_CALLOC(rasqal_raptor_triples_match_context, 1, sizeof(rasqal_raptor_triples_match_context));
+  if(!rtmc)
+    return -1;
+
+  rtm->user_data = rtmc;
+
+  rtmc->source_context = rtsc;
+  rtmc->cur = rtsc->head;
+  
+  /* at least one of the triple terms is a variable and we need to
+   * do a triplesMatching() over the list of stored raptor_statements
+   */
+
+  if((var = rasqal_literal_as_variable(t->subject))) {
+    if(var->value)
+      rtmc->match.subject = rasqal_new_literal_from_literal(var->value);
+  } else
+    rtmc->match.subject = rasqal_new_literal_from_literal(t->subject);
+
+  m->bindings[0] = var;
+  
+
+  if((var = rasqal_literal_as_variable(t->predicate))) {
+    if(var->value)
+      rtmc->match.predicate = rasqal_new_literal_from_literal(var->value);
+  } else
+    rtmc->match.predicate = rasqal_new_literal_from_literal(t->predicate);
+
+  m->bindings[1] = var;
+  
+
+  if((var = rasqal_literal_as_variable(t->object))) {
+    if(var->value)
+      rtmc->match.object = rasqal_new_literal_from_literal(var->value);
+  } else
+    rtmc->match.object = rasqal_new_literal_from_literal(t->object);
+
+  m->bindings[2] = var;
+  
+  rtmc->parts = RASQAL_TRIPLE_SPO;
+
+  if(t->origin) {
+    if((var = rasqal_literal_as_variable(t->origin))) {
+      if(var->value)
+        rtmc->match.origin = rasqal_new_literal_from_literal(var->value);
+    } else
+      rtmc->match.origin = rasqal_new_literal_from_literal(t->origin);
+    m->bindings[3] = var;
+    rtmc->parts = (rasqal_triple_parts)(rtmc->parts | RASQAL_TRIPLE_GRAPH);
+  }
+  
+
+  while(rtmc->cur) {
+    if(rasqal_raptor_triple_match(rtm->world, rtmc->cur->triple, &rtmc->match,
+                                  rtmc->parts))
+      break;
+    rtmc->cur = rtmc->cur->next;
+  }
+  
+    
+  RASQAL_DEBUG1("rasqal_init_triples_match done\n");
+
+  return 0;
+}
+
+
+int
+rasqal_raptor_init(rasqal_world* world)
+{
+  rasqal_set_triples_source_factory(world, rasqal_raptor_register_triples_source_factory, (void*)NULL);
+  return 0;
+}
diff --git a/src/rasqal/rasqal_redland.c b/src/rasqal/rasqal_redland.c
new file mode 100644
index 0000000..6a10cc3
--- /dev/null
+++ b/src/rasqal/rasqal_redland.c
@@ -0,0 +1,474 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_redland.c - Rasqal redland interface
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include <redland.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#define LIBRDF_MALLOC(type, size) malloc(size)
+#define LIBRDF_CALLOC(type, size, count) calloc(size, count)
+#define LIBRDF_FREE(type, ptr)   free((void*)ptr)
+
+#ifdef RASQAL_DEBUG
+#define LIBRDF_DEBUG1(msg) do {fprintf(stderr, "%s:%d:%s: " msg, __FILE__, __LINE__, __func__); } while(0)
+#define LIBRDF_DEBUG2(msg, arg1) do {fprintf(stderr, "%s:%d:%s: " msg, __FILE__, __LINE__, __func__, arg1);} while(0)
+#else
+#define LIBRDF_DEBUG1(msg)
+#define LIBRDF_DEBUG2(msg, arg1)
+#endif
+
+
+
+static librdf_node*
+rasqal_literal_to_redland_node(librdf_world *world, rasqal_literal* l) {
+  if(l->type == RASQAL_LITERAL_URI)
+    return librdf_new_node_from_uri(world, (librdf_uri*)l->value.uri);
+  else if (l->type == RASQAL_LITERAL_STRING ||
+           l->type == RASQAL_LITERAL_INTEGER ||
+           l->type == RASQAL_LITERAL_DOUBLE ||
+           l->type == RASQAL_LITERAL_BOOLEAN)
+    return librdf_new_node_from_typed_literal(world, l->string, 
+                                              l->language, 
+                                              (librdf_uri*)l->datatype);
+  else if (l->type == RASQAL_LITERAL_BLANK)
+    return librdf_new_node_from_blank_identifier(world, l->string);
+  else
+    RASQAL_FATAL1("Literal type %d cannot be converted to a librdf_node", l->type);
+
+  return NULL;
+}
+
+
+static rasqal_literal*
+redland_node_to_rasqal_literal(rasqal_world *world, librdf_node *node) {
+  rasqal_literal* l;
+  
+  if(librdf_node_is_resource(node)) {
+    raptor_uri* uri=(raptor_uri*)librdf_new_uri_from_uri(librdf_node_get_uri(node));
+    l=rasqal_new_uri_literal(world, uri);
+  } else if(librdf_node_is_literal(node)) {
+    char *string;
+    librdf_uri *uri;
+    char *new_string;
+    char *new_language=NULL;
+    raptor_uri *new_datatype=NULL;
+    size_t len;
+    string=(char*)librdf_node_get_literal_value_as_counted_string(node, &len);
+    new_string=LIBRDF_MALLOC(cstring, len+1);
+    strcpy(new_string, (const char*)string);
+    string=librdf_node_get_literal_value_language(node);
+    if(string) {
+      new_language=LIBRDF_MALLOC(cstring, strlen(string)+1);
+      strcpy(new_language, (const char*)string);
+    }
+    uri=librdf_node_get_literal_value_datatype_uri(node);
+    if(uri)
+      new_datatype=(raptor_uri*)librdf_new_uri_from_uri(uri);
+    l=rasqal_new_string_literal(world, (unsigned char*)new_string, new_language, new_datatype, NULL);
+  } else {
+    char *blank=(char*)librdf_node_get_blank_identifier(node);
+    char *new_blank=LIBRDF_MALLOC(cstring, strlen(blank)+1);
+    strcpy(new_blank, (const char*)blank);
+    l=rasqal_new_simple_literal(world, RASQAL_LITERAL_BLANK, (unsigned char*)new_blank);
+  }
+
+  return l;
+}
+
+
+typedef struct {
+  librdf_world *world;
+  librdf_model *model;
+  librdf_storage *storage;
+
+  /* index used while reading triples into the array below.
+   * This is used to connect a triple to the URI of the source
+   */
+  int source_index;
+
+  /* size of the two arrays below */
+  int sources_count;
+  
+  /* array of source URIs */
+  librdf_uri **source_uris;
+} rasqal_redland_triples_source_user_data;
+
+/* prototypes */
+static int rasqal_redland_init_triples_match(rasqal_triples_match* rtm, rasqal_triples_source *rts, void *user_data, rasqal_triple_meta *m, rasqal_triple *t);
+static int rasqal_redland_triple_present(rasqal_triples_source *rts, void *user_data, rasqal_triple *t);
+static void rasqal_redland_free_triples_source(void *user_data);
+
+static int
+rasqal_redland_new_triples_source(rasqal_query* rdf_query,
+                                  void *factory_user_data,
+                                  void *user_data,
+                                  rasqal_triples_source *rts) {
+  librdf_world *world=(librdf_world*)factory_user_data;
+  rasqal_redland_triples_source_user_data* rtsc=(rasqal_redland_triples_source_user_data*)user_data;
+  librdf_parser *parser;
+  const char *parser_name;
+  int i;
+  
+  if(!rdf_query->data_graphs)
+    return -1; /* no data */
+
+  rtsc->sources_count=raptor_sequence_size(rdf_query->data_graphs);
+  /* no default triple source possible */
+  if(!rtsc->sources_count)
+    return -1;  /* no data */
+
+  rtsc->world=world;
+
+  /* FIXME error checking */
+  rtsc->storage = librdf_new_storage(world, NULL, NULL, "contexts='yes'");
+  rtsc->model = librdf_new_model(world, rtsc->storage, NULL);
+
+  rts->init_triples_match=rasqal_redland_init_triples_match;
+  rts->triple_present=rasqal_redland_triple_present;
+  rts->free_triples_source=rasqal_redland_free_triples_source;
+
+  rtsc->source_uris=(librdf_uri**)RASQAL_CALLOC(librdf_uri_ptr, rtsc->sources_count, sizeof(librdf_uri*));
+
+  for(i=0; i< rtsc->sources_count; i++) {
+    rasqal_data_graph *dg=(rasqal_data_graph*)raptor_sequence_get_at(rdf_query->data_graphs, i);
+    librdf_stream *stream;
+    librdf_node *node;
+    
+    rtsc->source_index=i;
+    rtsc->source_uris[i]=librdf_new_uri(world, raptor_uri_as_string(dg->uri));
+
+    parser_name=raptor_guess_parser_name(NULL, NULL, NULL, 0,
+                                         raptor_uri_as_string(dg->uri));
+    parser=librdf_new_parser(world, parser_name, NULL, NULL);
+    stream=librdf_parser_parse_as_stream(parser, (librdf_uri*)dg->uri,
+                                         (librdf_uri*)dg->name_uri);
+    node=librdf_new_node_from_uri(world, (librdf_uri*)rtsc->source_uris[i]);
+    librdf_model_context_add_statements(rtsc->model, node, stream);
+    librdf_free_stream(stream);
+    librdf_free_node(node);
+    librdf_free_parser(parser);
+  }
+
+  return 0;
+}
+
+
+static int
+rasqal_redland_triple_present(rasqal_triples_source *rts, void *user_data, 
+                              rasqal_triple *t) 
+{
+  rasqal_redland_triples_source_user_data* rtsc=(rasqal_redland_triples_source_user_data*)user_data;
+  librdf_node* nodes[3];
+  librdf_statement *s;
+  int rc;
+  
+  /* ASSUMPTION: all the parts of the triple are not variables */
+  /* FIXME: and no error checks */
+  nodes[0]=rasqal_literal_to_redland_node(rtsc->world, t->subject);
+  nodes[1]=rasqal_literal_to_redland_node(rtsc->world, t->predicate);
+  nodes[2]=rasqal_literal_to_redland_node(rtsc->world, t->object);
+
+  s=librdf_new_statement_from_nodes(rtsc->world, nodes[0], nodes[1], nodes[2]);
+  
+  rc=librdf_model_contains_statement(rtsc->model, s);
+  librdf_free_statement(s);
+  return rc;
+}
+
+
+
+static void
+rasqal_redland_free_triples_source(void *user_data) {
+  rasqal_redland_triples_source_user_data* rtsc=(rasqal_redland_triples_source_user_data*)user_data;
+  int i;
+  
+  for(i=0; i< rtsc->sources_count; i++) {
+    librdf_free_uri(rtsc->source_uris[i]);
+  }
+  RASQAL_FREE(librdf_uri_ptr, rtsc->source_uris);
+  
+  librdf_free_model(rtsc->model);
+  librdf_free_storage(rtsc->storage);
+}
+
+
+static void
+rasqal_redland_register_triples_source_factory(rasqal_triples_source_factory *factory) 
+{
+  factory->user_data_size=sizeof(rasqal_redland_triples_source_user_data);
+  factory->new_triples_source=rasqal_redland_new_triples_source;
+}
+
+
+typedef struct {
+  librdf_node* nodes[3];
+  librdf_node* origin;
+  /* query statement, made from the nodes above (even when exact) */
+  librdf_statement *qstatement;
+  librdf_stream *stream;
+} rasqal_redland_triples_match_context;
+
+
+static rasqal_triple_parts
+rasqal_redland_bind_match(struct rasqal_triples_match_s* rtm,
+                          void *user_data,
+                          rasqal_variable* bindings[4],
+                          rasqal_triple_parts parts) {
+  rasqal_redland_triples_match_context* rtmc=(rasqal_redland_triples_match_context*)rtm->user_data;
+  rasqal_literal* l;
+  rasqal_triple_parts result=(rasqal_triple_parts)0;
+  librdf_statement* statement;
+
+  statement= librdf_stream_get_object(rtmc->stream);
+  if(!statement)
+    return result;
+  
+#ifdef RASQAL_DEBUG
+  LIBRDF_DEBUG1("  matched statement ");
+  librdf_statement_print(statement, stderr);
+  fputc('\n', stderr);
+#endif
+
+  /* set 1 or 2 variable values from the fields of statement */
+
+  if(bindings[0] && (parts & RASQAL_TRIPLE_SUBJECT)) {
+    LIBRDF_DEBUG1("binding subject to variable\n");
+    l=redland_node_to_rasqal_literal(rtm->world, librdf_statement_get_subject(statement));
+    rasqal_variable_set_value(bindings[0], rasqal_literal_as_node(l));
+    rasqal_free_literal(l);
+    result= RASQAL_TRIPLE_SUBJECT;
+  }
+
+  if(bindings[1] && (parts & RASQAL_TRIPLE_PREDICATE)) {
+    if(bindings[0] == bindings[1]) {
+      if(!librdf_node_equals(librdf_statement_get_subject(statement),
+                             librdf_statement_get_predicate(statement)))
+        return (rasqal_triple_parts)0;
+      LIBRDF_DEBUG1("subject and predicate values match\n");
+    } else {
+      LIBRDF_DEBUG1("binding predicate to variable\n");
+      l=redland_node_to_rasqal_literal(rtm->world, librdf_statement_get_predicate(statement));
+      rasqal_variable_set_value(bindings[1], rasqal_literal_as_node(l));
+      rasqal_free_literal(l);
+      result= (rasqal_triple_parts)(result | RASQAL_TRIPLE_PREDICATE);
+    }
+  }
+
+  if(bindings[2] && (parts & RASQAL_TRIPLE_OBJECT)) {
+    int bind=1;
+    
+    if(bindings[0] == bindings[2]) {
+      if(!librdf_node_equals(librdf_statement_get_subject(statement),
+                             librdf_statement_get_object(statement)))
+        return (rasqal_triple_parts)0;
+      bind=0;
+      LIBRDF_DEBUG1("subject and object values match\n");
+    }
+    if(bindings[1] == bindings[2] &&
+       !(bindings[0] == bindings[1]) /* don't do this check if ?x ?x ?x */
+       ) {
+      if(!librdf_node_equals(librdf_statement_get_predicate(statement),
+                             librdf_statement_get_object(statement)))
+        return (rasqal_triple_parts)0;
+      bind=0;
+      LIBRDF_DEBUG1("predicate and object values match\n");
+    }
+    
+    if(bind) {
+      LIBRDF_DEBUG1("binding object to variable\n");
+      l=redland_node_to_rasqal_literal(rtm->world, librdf_statement_get_object(statement));
+      rasqal_variable_set_value(bindings[2], rasqal_literal_as_node(l));
+      rasqal_free_literal(l);
+      result= (rasqal_triple_parts)(result | RASQAL_TRIPLE_OBJECT);
+    }
+  }
+
+  if(bindings[3] && (parts & RASQAL_TRIPLE_ORIGIN)) {
+    l=redland_node_to_rasqal_literal(rtm->world, (librdf_node*)librdf_stream_get_context(rtmc->stream));
+    RASQAL_DEBUG1("binding origin to variable\n");
+    rasqal_variable_set_value(bindings[3], rasqal_literal_as_node(l));
+    rasqal_free_literal(l);
+    result= (rasqal_triple_parts)(result | RASQAL_TRIPLE_ORIGIN);
+  }
+
+  return result;
+}
+
+
+static void
+rasqal_redland_next_match(struct rasqal_triples_match_s* rtm,
+                          void *user_data)
+{
+  rasqal_redland_triples_match_context* rtmc=(rasqal_redland_triples_match_context*)rtm->user_data;
+
+  librdf_stream_next(rtmc->stream);
+}
+
+static int
+rasqal_redland_is_end(struct rasqal_triples_match_s* rtm,
+                      void *user_data)
+{
+  rasqal_redland_triples_match_context* rtmc=(rasqal_redland_triples_match_context*)rtm->user_data;
+
+  return librdf_stream_end(rtmc->stream);
+}
+
+
+static void
+rasqal_redland_finish_triples_match(struct rasqal_triples_match_s* rtm,
+                                    void *user_data) {
+  rasqal_redland_triples_match_context* rtmc=(rasqal_redland_triples_match_context*)rtm->user_data;
+
+  if(rtmc->stream) {
+    librdf_free_stream(rtmc->stream);
+    rtmc->stream=NULL;
+  }
+  librdf_free_statement(rtmc->qstatement);
+  LIBRDF_FREE(rasqal_redland_triples_match_context, rtmc);
+}
+
+
+static int
+rasqal_redland_init_triples_match(rasqal_triples_match* rtm,
+                                  rasqal_triples_source *rts, void *user_data,
+                                  rasqal_triple_meta *m, rasqal_triple *t) {
+  rasqal_redland_triples_source_user_data* rtsc=(rasqal_redland_triples_source_user_data*)user_data;
+  rasqal_redland_triples_match_context* rtmc;
+  rasqal_variable* var;
+
+  rtm->bind_match=rasqal_redland_bind_match;
+  rtm->next_match=rasqal_redland_next_match;
+  rtm->is_end=rasqal_redland_is_end;
+  rtm->finish=rasqal_redland_finish_triples_match;
+
+  rtmc=(rasqal_redland_triples_match_context*)LIBRDF_CALLOC(rasqal_redland_triples_match_context, 1, sizeof(rasqal_redland_triples_match_context));
+
+  rtm->user_data=rtmc;
+
+
+  /* at least one of the triple terms is a variable and we need to
+   * do a triplesMatching() aka librdf_model_find_statements
+   *
+   * redland find_statements will do the right thing and internally
+   * pick the most efficient, indexed way to get the answer.
+   */
+
+  if((var=rasqal_literal_as_variable(t->subject))) {
+    if(var->value)
+      rtmc->nodes[0]=rasqal_literal_to_redland_node(rtsc->world, var->value);
+    else
+      rtmc->nodes[0]=NULL;
+  } else
+    rtmc->nodes[0]=rasqal_literal_to_redland_node(rtsc->world, t->subject);
+
+  m->bindings[0]=var;
+  
+
+  if((var=rasqal_literal_as_variable(t->predicate))) {
+    if(var->value)
+      rtmc->nodes[1]=rasqal_literal_to_redland_node(rtsc->world, var->value);
+    else
+      rtmc->nodes[1]=NULL;
+  } else
+    rtmc->nodes[1]=rasqal_literal_to_redland_node(rtsc->world, t->predicate);
+
+  m->bindings[1]=var;
+  
+
+  if((var=rasqal_literal_as_variable(t->object))) {
+    if(var->value)
+      rtmc->nodes[2]=rasqal_literal_to_redland_node(rtsc->world, var->value);
+    else
+      rtmc->nodes[2]=NULL;
+  } else
+    rtmc->nodes[2]=rasqal_literal_to_redland_node(rtsc->world, t->object);
+
+  m->bindings[2]=var;
+  
+
+  if(t->origin) {
+    if((var=rasqal_literal_as_variable(t->origin))) {
+      if(var->value)
+        rtmc->origin=rasqal_literal_to_redland_node(rtsc->world, var->value);
+    } else
+      rtmc->origin=rasqal_literal_to_redland_node(rtsc->world, t->origin);
+    m->bindings[3]=var;
+  }
+
+
+  rtmc->qstatement=librdf_new_statement_from_nodes(rtsc->world, 
+                                                   rtmc->nodes[0],
+                                                   rtmc->nodes[1], 
+                                                   rtmc->nodes[2]);
+  if(!rtmc->qstatement)
+    return 1;
+
+#ifdef RASQAL_DEBUG
+  LIBRDF_DEBUG1("query statement: ");
+  librdf_statement_print(rtmc->qstatement, stderr);
+  fputc('\n', stderr);
+#endif
+  
+  rtmc->stream=librdf_model_find_statements(rtsc->model, rtmc->qstatement);
+
+  LIBRDF_DEBUG1("rasqal_init_triples_match done\n");
+
+  return 0;
+}
+
+static librdf_world* Rasqal_Redland_World=NULL;
+
+int
+rasqal_redland_init(rasqal_world* world) {
+  Rasqal_Redland_World=librdf_new_world();
+  if(!Rasqal_Redland_World)
+    return 1;
+  librdf_world_open(Rasqal_Redland_World);
+  rasqal_set_triples_source_factory(world, rasqal_redland_register_triples_source_factory, Rasqal_Redland_World);
+  return 0;
+}
+
+void
+rasqal_redland_finish() {
+  librdf_free_world(Rasqal_Redland_World);
+  Rasqal_Redland_World=NULL;
+}
+
diff --git a/src/rasqal/rasqal_result_formats.c b/src/rasqal/rasqal_result_formats.c
new file mode 100644
index 0000000..c8435f5
--- /dev/null
+++ b/src/rasqal/rasqal_result_formats.c
@@ -0,0 +1,676 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_result_formats.c - Rasqal RDF Query Result Formats
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+static int rasqal_query_results_write_json1(raptor_iostream *iostr, rasqal_query_results* results, raptor_uri *base_uri);
+
+
+int
+rasqal_query_results_format_register_factory(rasqal_world* world,
+                                             const char *name,
+                                             const char *label,
+                                             const unsigned char* uri_string,
+                                             rasqal_query_results_formatter_func writer,
+                                             rasqal_query_results_formatter_func reader,
+                                             rasqal_query_results_get_rowsource_func get_rowsource,
+                                             const char *mime_type)
+{
+  rasqal_query_results_format_factory* factory;
+
+  factory=(rasqal_query_results_format_factory*)RASQAL_CALLOC(query_results_format_factory, 
+                                                              1, sizeof(rasqal_query_results_format_factory));
+
+  if(!factory) {
+    rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_FATAL, NULL,
+                            "Out of memory in rasqal_query_results_format_register_factory()");
+    return 1;
+  }
+  factory->name=name;
+  factory->label=label;
+  factory->uri_string=uri_string;
+  factory->writer=writer;
+  factory->reader=reader;
+  factory->get_rowsource=get_rowsource;
+  factory->mime_type=mime_type;
+
+  return raptor_sequence_push(world->query_results_formats, factory);
+}
+
+
+
+static
+void rasqal_free_query_results_format_factory(rasqal_query_results_format_factory* factory) 
+{
+  RASQAL_FREE(query_results_format_factory, factory);
+}
+
+
+int
+rasqal_init_result_formats(rasqal_world* world)
+{
+  rasqal_query_results_formatter_func writer_fn=NULL;
+  rasqal_query_results_formatter_func reader_fn=NULL;
+  rasqal_query_results_get_rowsource_func get_rowsource_fn=NULL;
+  int rc=0;
+  
+  world->query_results_formats=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_query_results_format_factory, NULL);
+  if(!world->query_results_formats)
+    return 1;
+
+  rc+= rasqal_init_result_format_sparql_xml(world) != 0;
+
+  /*
+   * SPARQL Query Results in JSON (http://json.org/) draft
+   * Defined in http://www.w3.org/2001/sw/DataAccess/json-sparql/
+   * Version: 1.6 $ of $Date: 2006/04/05 15:55:17
+   */
+  writer_fn=&rasqal_query_results_write_json1;
+  reader_fn=NULL;
+  get_rowsource_fn=NULL;
+  rc+= rasqal_query_results_format_register_factory(world,
+                                                    "json",
+                                                    "JSON",
+                                                    (unsigned char*)"http://www.w3.org/2001/sw/DataAccess/json-sparql/";,
+                                                    writer_fn, reader_fn, get_rowsource_fn,
+                                                    "text/json")
+                                                    != 0;
+  rc+= rasqal_query_results_format_register_factory(world,
+                                                    NULL,
+                                                    NULL,
+                                                    (unsigned char*)"http://www.mindswap.org/%7Ekendall/sparql-results-json/";,
+                                                    writer_fn, reader_fn, get_rowsource_fn,
+                                                    "text/json")
+                                                    != 0;
+
+  return rc;
+}
+
+
+void
+rasqal_finish_result_formats(rasqal_world* world)
+{
+  if(world->query_results_formats) {
+    raptor_free_sequence(world->query_results_formats);
+    world->query_results_formats = NULL;
+  }
+}
+
+
+/**
+ * rasqal_query_results_formats_enumerate:
+ * @world: rasqal_world object
+ * @counter: index into the list of query result syntaxes
+ * @name: pointer to store the name of the query result syntax (or NULL)
+ * @label: pointer to store query result syntax readable label (or NULL)
+ * @uri_string: pointer to store query result syntax URI string (or NULL)
+ * @mime_type: pointer to store query result syntax mime type string (or NULL)
+ * @flags: pointer to store query result syntax flags (or NULL)
+ *
+ * Get information on query result syntaxes.
+ * 
+ * The current list of format names/URI is given below however
+ * the results of this function will always return the latest.
+ *
+ * SPARQL XML Results 2007-06-14 (default format when @counter is 0)
+ * name '<literal>xml</literal>' with
+ * URIs http://www.w3.org/TR/2006/WD-rdf-sparql-XMLres-20070614/ or
+ * http://www.w3.org/2005/sparql-results#
+ *
+ * JSON name '<literal>json</literal>' and
+ * URI http://www.w3.org/2001/sw/DataAccess/json-sparql/
+ *
+ * All returned strings are shared and must be copied if needed to be
+ * used dynamically.
+ * 
+ * Return value: non 0 on failure of if counter is out of range
+ **/
+int
+rasqal_query_results_formats_enumerate(rasqal_world* world,
+                                       unsigned int counter,
+                                       const char **name,
+                                       const char **label,
+                                       const unsigned char **uri_string,
+                                       const char **mime_type,
+                                       int *flags)
+
+
+
+{
+  rasqal_query_results_format_factory *factory;
+  int i;
+  unsigned int real_counter;
+  
+  real_counter=0;
+  for(i=0; 1; i++) {
+    factory=(rasqal_query_results_format_factory*)raptor_sequence_get_at(world->query_results_formats, i);
+    if(!factory)
+      break;
+
+    if(factory->name) {
+      if(real_counter == counter)
+        break;
+      real_counter++;
+    }
+  }
+
+  if(!factory)
+    return 1;
+
+  if(name)
+    *name=factory->name;
+  if(label)
+    *label=factory->label;
+  if(uri_string)
+    *uri_string=factory->uri_string;
+  if(mime_type)
+    *mime_type=factory->mime_type;
+  if(flags) {
+    *flags=0;
+    if(factory->reader)
+      *flags |= RASQAL_QUERY_RESULTS_FORMAT_FLAG_READER;
+    if(factory->writer)
+      *flags |= RASQAL_QUERY_RESULTS_FORMAT_FLAG_WRITER;
+  }
+  
+  return 0;
+}
+
+
+static rasqal_query_results_format_factory*
+rasqal_get_query_results_formatter_factory(rasqal_world* world,
+                                           const char *name, raptor_uri* uri,
+                                           const char *mime_type)
+{
+  int i;
+  rasqal_query_results_format_factory* factory=NULL;
+  
+  for(i=0; 1; i++) {
+    factory=(rasqal_query_results_format_factory*)raptor_sequence_get_at(world->query_results_formats,
+                                                                         i);
+    if(!factory)
+      break;
+
+    if(!name && !uri)
+      /* the default is the first registered format */
+      break;
+    
+    if(name && factory->name &&
+       !strcmp(factory->name, (const char*)name))
+      return factory;
+
+
+    if(uri && factory->uri_string &&
+       !strcmp(
+#ifdef RAPTOR_V2_AVAILABLE
+               (const char*)raptor_uri_as_string_v2(world->raptor_world_ptr, uri),
+#else
+               (const char*)raptor_uri_as_string(uri),
+#endif
+               (const char*)factory->uri_string))
+      break;
+
+
+    if(mime_type && factory->mime_type &&
+       !strcmp(factory->mime_type, (const char*)mime_type))
+      return factory;
+  }
+  
+  return factory;
+}
+
+
+/**
+ * rasqal_query_results_formats_check:
+ * @world: rasqal_world object
+ * @name: the query results format name (or NULL)
+ * @uri: #raptor_uri query results format uri (or NULL)
+ * @mime_type: mime type name
+ * 
+ * Check if a query results formatter exists for the requested format.
+ * 
+ * Return value: non-0 if a formatter exists.
+ **/
+int
+rasqal_query_results_formats_check(rasqal_world* world,
+                                   const char *name, raptor_uri* uri,
+                                   const char *mime_type)
+{
+  return (rasqal_get_query_results_formatter_factory(world, name, uri, mime_type) 
+          != NULL);
+}
+
+
+/**
+ * rasqal_new_query_results_formatter:
+ * @world: rasqal_world object
+ * @name: the query results format name (or NULL)
+ * @format_uri: #raptor_uri query results format uri (or NULL)
+ *
+ * Constructor - create a new rasqal_query_results_formatter object by identified format.
+ *
+ * A query results format can be named or identified by a URI, both
+ * of which are optional.  The default query results format will be used
+ * if both are NULL.  rasqal_query_results_formats_enumerate() returns
+ * information on the known query results names, labels and URIs.
+ *
+ * Return value: a new #rasqal_query_results_formatter object or NULL on failure
+ */
+rasqal_query_results_formatter*
+rasqal_new_query_results_formatter(rasqal_world* world, const char *name, raptor_uri* format_uri)
+{
+  rasqal_query_results_format_factory* factory;
+  rasqal_query_results_formatter* formatter;
+
+  factory=rasqal_get_query_results_formatter_factory(world, name, format_uri, NULL);
+  if(!factory)
+    return NULL;
+
+  formatter=(rasqal_query_results_formatter*)RASQAL_CALLOC(rasqal_query_results_formatter, 1, sizeof(rasqal_query_results_formatter));
+  if(!formatter)
+    return NULL;
+
+  formatter->factory=factory;
+
+  formatter->mime_type=factory->mime_type;
+  
+  return formatter;
+}
+
+
+/**
+ * rasqal_new_query_results_formatter_by_mime_type:
+ * @world: rasqal_world object
+ * @mime_type: mime type name
+ *
+ * Constructor - create a new rasqal_query_results_formatter object by mime type.
+ *
+ * A query results format generates a syntax with a mime type which
+ * may be requested with this constructor.
+ *
+ * Note that there may be several formatters that generate the same
+ * MIME Type (such as SPARQL XML results format drafts) and in thot
+ * case the rasqal_new_query_results_formatter() constructor allows
+ * selecting of a specific one by name or URI.
+ *
+ * Return value: a new #rasqal_query_results_formatter object or NULL on failure
+ */
+rasqal_query_results_formatter*
+rasqal_new_query_results_formatter_by_mime_type(rasqal_world* world, const char *mime_type)
+{
+  rasqal_query_results_format_factory* factory;
+  rasqal_query_results_formatter* formatter;
+
+  if(!mime_type)
+    return NULL;
+
+  factory=rasqal_get_query_results_formatter_factory(world, NULL, NULL, mime_type);
+  if(!factory)
+    return NULL;
+
+  formatter=(rasqal_query_results_formatter*)RASQAL_CALLOC(rasqal_query_results_formatter, 1, sizeof(rasqal_query_results_formatter));
+  if(!formatter)
+    return NULL;
+
+  formatter->factory=factory;
+
+  formatter->mime_type=factory->mime_type;
+  
+  return formatter;
+}
+
+
+/**
+ * rasqal_free_query_results_formatter:
+ * @formatter: #rasqal_query_results_formatter object
+ * 
+ * Destructor - destroy a #rasqal_query_results_formatter object.
+ **/
+void
+rasqal_free_query_results_formatter(rasqal_query_results_formatter* formatter) 
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(formatter, rasqal_query_results_formatter);
+
+  RASQAL_FREE(rasqal_query_results_formatter, formatter);
+}
+
+
+static void
+rasqal_iostream_write_json_boolean(raptor_iostream* iostr, 
+                                   const char* name, int json_bool)
+{
+  raptor_iostream_write_byte(iostr, '\"');
+  raptor_iostream_write_string(iostr, name);
+  raptor_iostream_write_counted_string(iostr, "\" : ",4);
+
+  if(json_bool)
+    raptor_iostream_write_counted_string(iostr, "true", 4);
+  else
+    raptor_iostream_write_counted_string(iostr, "false", 5);
+
+}
+
+
+/*
+ * rasqal_query_results_write_json1:
+ * @iostr: #raptor_iostream to write the query to
+ * @results: #rasqal_query_results query results format
+ * @base_uri: #raptor_uri base URI of the output format
+ *
+ * Write a JSON version of the query results format to an
+ * iostream in a format - INTERNAL.
+ * 
+ * If the writing succeeds, the query results will be exhausted.
+ * 
+ * Return value: non-0 on failure
+ **/
+static int
+rasqal_query_results_write_json1(raptor_iostream *iostr,
+                                 rasqal_query_results* results,
+                                 raptor_uri *base_uri)
+{
+  rasqal_query* query = rasqal_query_results_get_query(results);
+  int i;
+  int row_comma;
+  int column_comma=0;
+  
+  if(!rasqal_query_results_is_bindings(results) &&
+     !rasqal_query_results_is_boolean(results)) {
+    rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                            &query->locator,
+                            "Can only write JSON format for variable binding and boolean results");
+    return 1;
+  }
+  
+  
+  raptor_iostream_write_counted_string(iostr, "{\n", 2);
+  
+  /* Header */
+  raptor_iostream_write_counted_string(iostr, "  \"head\": {\n", 12);
+  
+  if(rasqal_query_results_is_bindings(results)) {
+    raptor_iostream_write_counted_string(iostr, "    \"vars\": [ ", 14);
+    for(i=0; 1; i++) {
+      const unsigned char *name;
+      
+      name=rasqal_query_results_get_binding_name(results, i);
+      if(!name)
+        break;
+      
+      /*     'x', */
+      if(i > 0)
+        raptor_iostream_write_counted_string(iostr, ", ", 2);
+      raptor_iostream_write_byte(iostr, '\"');
+      raptor_iostream_write_string(iostr, name);
+      raptor_iostream_write_byte(iostr, '\"');
+    }
+    raptor_iostream_write_counted_string(iostr, " ]\n", 3);
+  }
+
+  /* FIXME - could add link inside 'head': */
+    
+  /*   End Header */
+  raptor_iostream_write_counted_string(iostr, "  },\n", 5);
+
+
+  /* Boolean Results */
+  if(rasqal_query_results_is_boolean(results)) {
+    raptor_iostream_write_counted_string(iostr, "  ", 2);
+    rasqal_iostream_write_json_boolean(iostr, "boolean", 
+                                       rasqal_query_results_get_boolean(results));
+    goto results3done;
+  }
+
+  /* Variable Binding Results */
+  raptor_iostream_write_counted_string(iostr, "  \"results\": {\n", 15);
+
+  raptor_iostream_write_counted_string(iostr, "    ", 4);
+  rasqal_iostream_write_json_boolean(iostr, "ordered", 
+                                     (rasqal_query_get_order_condition(query, 0) != NULL));
+  raptor_iostream_write_counted_string(iostr, ",\n", 2);
+
+  raptor_iostream_write_counted_string(iostr, "    ", 4);
+  rasqal_iostream_write_json_boolean(iostr, "distinct", 
+                                     rasqal_query_get_distinct(query));
+  raptor_iostream_write_counted_string(iostr, ",\n", 2);
+
+  raptor_iostream_write_counted_string(iostr, "    \"bindings\" : [\n", 19);
+
+  row_comma=0;
+  while(!rasqal_query_results_finished(results)) {
+    if(row_comma)
+      raptor_iostream_write_counted_string(iostr, ",\n", 2);
+
+    /* Result row */
+    raptor_iostream_write_counted_string(iostr, "      {\n", 8);
+
+    column_comma=0;
+    for(i=0; i<rasqal_query_results_get_bindings_count(results); i++) {
+      const unsigned char *name=rasqal_query_results_get_binding_name(results, i);
+      rasqal_literal *l=rasqal_query_results_get_binding_value(results, i);
+
+      if(column_comma)
+        raptor_iostream_write_counted_string(iostr, ",\n", 2);
+
+      /*       <binding> */
+      raptor_iostream_write_counted_string(iostr, "        \"", 9);
+      raptor_iostream_write_string(iostr, name);
+      raptor_iostream_write_counted_string(iostr, "\" : { ", 6);
+
+      if(!l) {
+        raptor_iostream_write_string(iostr, "\"type\": \"unbound\", \"value\": null");
+      } else switch(l->type) {
+        const unsigned char* str;
+        size_t len;
+        
+        case RASQAL_LITERAL_URI:
+          raptor_iostream_write_string(iostr, "\"type\": \"uri\", \"value\": \"");
+#ifdef RAPTOR_V2_AVAILABLE
+          str = (const unsigned char*)raptor_uri_as_counted_string_v2(l->world->raptor_world_ptr, l->value.uri, &len);
+#else
+          str = (const unsigned char*)raptor_uri_as_counted_string(l->value.uri, &len);
+#endif
+          raptor_iostream_write_string_ntriples(iostr, str, len, '"');
+          raptor_iostream_write_byte(iostr, '"');
+          break;
+
+        case RASQAL_LITERAL_BLANK:
+          raptor_iostream_write_string(iostr, "\"type\": \"bnode\", \"value\": \"");
+          raptor_iostream_write_string_ntriples(iostr, (const unsigned char*)l->string, 
+                                                l->string_len, '"');
+          raptor_iostream_write_byte(iostr, '"');
+          break;
+
+        case RASQAL_LITERAL_STRING:
+          raptor_iostream_write_string(iostr, "\"type\": \"literal\", \"value\": \"");
+          raptor_iostream_write_string_ntriples(iostr, (const unsigned char*)l->string,
+                                                l->string_len, '"');
+          raptor_iostream_write_byte(iostr, '"');
+
+          if(l->language) {
+            raptor_iostream_write_string(iostr, ",\n      \"xml:lang\" : \"");
+            raptor_iostream_write_string(iostr, (const unsigned char*)l->language);
+            raptor_iostream_write_byte(iostr, '"');
+          }
+          
+          if(l->datatype) {
+            raptor_iostream_write_string(iostr, ",\n      \"datatype\" : \"");
+#ifdef RAPTOR_V2_AVAILABLE
+            str = (const unsigned char*)raptor_uri_as_counted_string_v2(l->world->raptor_world_ptr, l->datatype, &len);
+#else
+            str = (const unsigned char*)raptor_uri_as_counted_string(l->datatype, &len);
+#endif
+            raptor_iostream_write_string_ntriples(iostr, str, len, '"');
+            raptor_iostream_write_byte(iostr, '"');
+          }
+          
+          break;
+
+        case RASQAL_LITERAL_PATTERN:
+        case RASQAL_LITERAL_QNAME:
+        case RASQAL_LITERAL_INTEGER:
+        case RASQAL_LITERAL_BOOLEAN:
+        case RASQAL_LITERAL_DOUBLE:
+        case RASQAL_LITERAL_FLOAT:
+        case RASQAL_LITERAL_VARIABLE:
+        case RASQAL_LITERAL_DECIMAL:
+        case RASQAL_LITERAL_DATETIME:
+
+        case RASQAL_LITERAL_UNKNOWN:
+        default:
+          rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                                  &query->locator,
+                                  "Cannot turn literal type %d into XML", 
+                                  l->type);
+      }
+
+      /* End Binding */
+      raptor_iostream_write_counted_string(iostr, " }", 2);
+      column_comma=1;
+    }
+
+    /* End Result Row */
+    raptor_iostream_write_counted_string(iostr, "\n      }", 8);
+    row_comma=1;
+    
+    rasqal_query_results_next(results);
+  }
+
+  raptor_iostream_write_counted_string(iostr, "\n    ]\n  }", 10);
+
+  results3done:
+  
+  /* end sparql */
+  raptor_iostream_write_counted_string(iostr, "\n}\n", 3);
+
+  return 0;
+}
+
+
+/**
+ * rasqal_query_results_formatter_get_mime_type:
+ * @formatter: #rasqal_query_results_formatter object
+ * 
+ * Get the mime type of the syntax being formatted.
+ * 
+ * Return value: a shared mime type string
+ **/
+const char*
+rasqal_query_results_formatter_get_mime_type(rasqal_query_results_formatter *formatter)
+{
+  return formatter->mime_type;
+}
+
+
+/**
+ * rasqal_query_results_formatter_write:
+ * @iostr: #raptor_iostream to write the query to
+ * @formatter: #rasqal_query_results_formatter object
+ * @results: #rasqal_query_results query results format
+ * @base_uri: #raptor_uri base URI of the output format
+ *
+ * Write the query results using the given formatter to an iostream
+ * 
+ * See rasqal_query_results_formats_enumerate() to get the
+ * list of syntax URIs and their description. 
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_results_formatter_write(raptor_iostream *iostr,
+                                     rasqal_query_results_formatter* formatter,
+                                     rasqal_query_results* results,
+                                     raptor_uri *base_uri)
+{
+  if(!formatter->factory->writer)
+     return 1;
+  return formatter->factory->writer(iostr, results, base_uri);
+}
+
+
+/**
+ * rasqal_query_results_formatter_read:
+ * @world: rasqal world object
+ * @iostr: #raptor_iostream to read the query from
+ * @formatter: #rasqal_query_results_formatter object
+ * @results: #rasqal_query_results query results format
+ * @base_uri: #raptor_uri base URI of the input format
+ *
+ * Read the query results using the given formatter from an iostream
+ * 
+ * See rasqal_query_results_formats_enumerate() to get the
+ * list of syntax URIs and their description. 
+ *
+ * Return value: non-0 on failure
+ **/
+int
+rasqal_query_results_formatter_read(rasqal_world *world,
+                                    raptor_iostream *iostr,
+                                    rasqal_query_results_formatter* formatter,
+                                    rasqal_query_results* results,
+                                    raptor_uri *base_uri)
+{
+  rasqal_rowsource* rowsource=NULL;
+  
+  if(formatter->factory->reader)
+    return formatter->factory->reader(iostr, results, base_uri);
+
+  if(!formatter->factory->get_rowsource)
+    return 1;
+  
+  rowsource=formatter->factory->get_rowsource(world, 
+                                              rasqal_query_results_get_variables_table(results),
+                                              iostr, base_uri);
+  if(!rowsource)
+    return 1;
+
+  while(1) {
+    rasqal_row* row=rasqal_rowsource_read_row(rowsource);
+    if(!row)
+      break;
+    rasqal_query_results_add_row(results, row);
+  }
+
+  if(rowsource)
+    rasqal_free_rowsource(rowsource);
+  
+  return 0;
+}
diff --git a/src/rasqal/rasqal_row.c b/src/rasqal/rasqal_row.c
new file mode 100644
index 0000000..24b7ce0
--- /dev/null
+++ b/src/rasqal/rasqal_row.c
@@ -0,0 +1,509 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_row.c - Rasqal Query Result Row
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+
+
+static rasqal_row*
+rasqal_new_row_common(int size, int order_size)
+{
+  rasqal_row* row;
+  
+  row = (rasqal_row*)RASQAL_CALLOC(rasqal_row, 1, sizeof(rasqal_row));
+  if(!row)
+    return NULL;
+
+  row->usage = 1;
+  row->size = size;
+  row->order_size = order_size;
+  
+  row->values = (rasqal_literal**)RASQAL_CALLOC(array, row->size,
+                                                sizeof(rasqal_literal*));
+  if(!row->values) {
+    rasqal_free_row(row);
+    return NULL;
+  }
+
+  if(row->order_size > 0) {
+    row->order_values = (rasqal_literal**)RASQAL_CALLOC(array,  row->order_size,
+                                                        sizeof(rasqal_literal*));
+    if(!row->order_values) {
+      rasqal_free_row(row);
+      return NULL;
+    }
+  }
+  
+  return row;
+}
+
+
+/**
+ * rasqal_new_row:
+ * @rowsource: rowsource
+ *
+ * INTERNAL - Create a new query result row at an offset into the result sequence.
+ *
+ * Return value: a new query result row or NULL on failure
+ */
+rasqal_row*
+rasqal_new_row(rasqal_rowsource* rowsource)
+{
+  int size;
+  int order_size = -1;
+  rasqal_row* row;
+  
+  size = rasqal_rowsource_get_size(rowsource);
+
+  row = rasqal_new_row_common(size, order_size);
+  if(row)
+    row->rowsource = rowsource;
+
+  return row;
+}
+
+
+/**
+ * rasqal_new_row_for_size:
+ * @size: width of row
+ *
+ * INTERNAL - Create a new query result row of a given size
+ *
+ * Return value: a new query result row or NULL on failure
+ */
+rasqal_row*
+rasqal_new_row_for_size(int size)
+{
+  int order_size = 0;
+
+  return rasqal_new_row_common(size, order_size);
+}
+
+
+/**
+ * rasqal_new_row_from_row:
+ * @row: query result row
+ * 
+ * INTERNAL - Copy a query result row.
+ *
+ * Return value: a copy of the query result row or NULL
+ */
+rasqal_row*
+rasqal_new_row_from_row(rasqal_row* row)
+{
+  row->usage++;
+  return row;
+}
+
+
+/**
+ * rasqal_free_row:
+ * @row: query result row
+ * 
+ * INTERNAL - Free a query result row object.
+ */
+void 
+rasqal_free_row(rasqal_row* row)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(row, rasqal_row);
+
+  if(--row->usage)
+    return;
+  
+  if(row->values) {
+    int i; 
+    for(i = 0; i < row->size; i++) {
+      if(row->values[i])
+        rasqal_free_literal(row->values[i]);
+    }
+    RASQAL_FREE(array, row->values);
+  }
+  if(row->order_values) {
+    int i; 
+    for(i = 0; i < row->order_size; i++) {
+      if(row->order_values[i])
+        rasqal_free_literal(row->order_values[i]);
+    }
+    RASQAL_FREE(array, row->order_values);
+  }
+
+  RASQAL_FREE(rasqal_row, row);
+}
+
+
+/**
+ * rasqal_row_print:
+ * @row: query result row
+ * @fp: FILE* handle
+ *
+ * INTERNAL - Print a query result row.
+ */
+void 
+rasqal_row_print(rasqal_row* row, FILE* fh)
+{
+  rasqal_rowsource* rowsource = row->rowsource;
+  int i;
+  
+  fputs("result[", fh);
+  for(i = 0; i < row->size; i++) {
+    /* Do not use rasqal_query_results_get_binding_name(row->results, i); 
+     * as it does not work for a construct result
+     */
+    const unsigned char *name = NULL;
+    rasqal_literal *value;
+
+    if(rowsource) {
+      rasqal_variable* v;
+      v = rasqal_rowsource_get_variable_by_offset(rowsource, i);
+      if(v)
+        name = v->name;
+    }
+    
+    value = row->values[i];
+    if(i > 0)
+      fputs(", ", fh);
+    if(name)
+      fprintf(fh, "%s=", name);
+
+    if(value)
+      rasqal_literal_print(value, fh);
+    else
+      fputs("NULL", fh);
+  }
+
+  if(row->order_size > 0) {
+    fputs(" with ordering values [", fh);
+
+    for(i = 0; i < row->order_size; i++) {
+      rasqal_literal *value = row->order_values[i];
+      
+      if(i > 0)
+        fputs(", ", fh);
+      if(value)
+        rasqal_literal_print(value, fh);
+      else
+        fputs("NULL", fh);
+    }
+    fputs("]", fh);
+
+  }
+
+  fprintf(fh, " offset %d]", row->offset);
+}
+
+
+/**
+ * rasqal_row_set_value_at:
+ * @row: query result row
+ * @offset: offset into row (column number)
+ * @value: literal value to set
+ *
+ * INTERNAL - Set the value of a variable in a query result row
+ */
+void
+rasqal_row_set_value_at(rasqal_row* row, int offset, rasqal_literal* value)
+{
+  row->values[offset] = value;
+}
+
+
+/**
+ * rasqal_new_row_sequence:
+ * @world: world object ot use
+ * @vt: variables table to use to declare variables
+ * @row_data: row data
+ * @vars_count: number of variables in row
+ * @vars_seq_p: OUT parameter - pointer to place to store sequence of variables (or NULL)
+ *
+ * INTERNAL - Make a sequence of #rasqal_row* objects
+ * with variables defined into the @vt table and values in the sequence
+ *
+ * The @row_data parameter is an array of strings forming a table of
+ * width (vars_count * 2).
+ * The first row is a list of variable names at offset 0.
+ * The remaining rows are values where offset 0 is a literal and
+ * offset 1 is a URI string.
+ * The last row is indicated by offset 0 = NULL and offset 1 = NULL
+ *
+ * Return value: sequence of rows or NULL on failure
+ */
+raptor_sequence*
+rasqal_new_row_sequence(rasqal_world* world,
+                        rasqal_variables_table* vt,
+                        const char* const row_data[],
+                        int vars_count,
+                        raptor_sequence** vars_seq_p)
+{
+  raptor_sequence *seq = NULL;
+  raptor_sequence *vars_seq = NULL;
+  int row_i;
+  int column_i;
+  int failed = 0;
+  
+#define GET_CELL(row, column, offset) \
+  row_data[((((row)*vars_count)+(column))<<1)+(offset)]
+
+  seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_row,
+                            (raptor_sequence_print_handler*)rasqal_row_print);
+  if(!seq)
+    return NULL;
+
+  if(vars_seq_p) {
+    vars_seq = raptor_new_sequence(NULL,
+                                   (raptor_sequence_print_handler*)rasqal_variable_print);
+    if(!vars_seq) {
+      raptor_free_sequence(seq);
+      return NULL;
+    }
+  }
+  
+  /* row 0 is variables */
+  row_i = 0;
+
+  for(column_i = 0; column_i < vars_count; column_i++) {
+    const char * var_name = GET_CELL(row_i, column_i, 0);
+    size_t var_name_len = strlen(var_name);
+    const unsigned char* name;
+    rasqal_variable* v;
+    
+    name = (unsigned char*)RASQAL_MALLOC(cstring, var_name_len+1);
+    if(!name) {
+      failed = 1;
+      goto tidy;
+    }
+
+    strncpy((char*)name, var_name, var_name_len+1);
+    v = rasqal_variables_table_add(vt, RASQAL_VARIABLE_TYPE_NORMAL, name, NULL);
+    if(!v) {
+      failed = 1;
+      goto tidy;
+    }
+
+    if(vars_seq)
+      raptor_sequence_push(vars_seq, v);
+  }
+
+  for(row_i = 1;
+      GET_CELL(row_i, 0, 0) || GET_CELL(row_i, 0, 1);
+      row_i++) {
+    rasqal_row* row;
+    
+    row = rasqal_new_row_for_size(vars_count);
+    if(!row) {
+      raptor_free_sequence(seq); seq = NULL;
+      goto tidy;
+    }
+
+    for(column_i = 0; column_i < vars_count; column_i++) {
+      rasqal_literal* l = NULL;
+
+      if(GET_CELL(row_i, column_i, 0)) {
+        /* string literal */
+        const char* str = GET_CELL(row_i, column_i, 0);
+        size_t str_len = strlen(str);
+        unsigned char *val;
+        val = (unsigned char*)RASQAL_MALLOC(cstring, str_len+1);
+        if(val) {
+          strncpy((char*)val, str, str_len+1);
+          l = rasqal_new_string_literal_node(world, val, NULL, NULL);
+        } else 
+          failed = 1;
+      } else if(GET_CELL(row_i, column_i, 1)) {
+        /* URI */
+        const unsigned char* str;
+        raptor_uri* u;
+        str = (const unsigned char*)GET_CELL(row_i, column_i, 1);
+#ifdef RAPTOR_V2_AVAILABLE
+        u = raptor_new_uri_v2(world->raptor_world_ptr, str);
+#else
+        u = raptor_new_uri(str);
+#endif
+        if(u)
+          l = rasqal_new_uri_literal(world, u);
+        else
+          failed = 1;
+      } /* else invalid and l=NULL so fails */
+
+      if(!l) {
+        rasqal_free_row(row);
+        failed = 1;
+        goto tidy;
+      }
+      rasqal_row_set_value_at(row, column_i, l);
+    }
+
+    raptor_sequence_push(seq, row);
+  }
+
+  tidy:
+  if(failed) {
+    if(seq) {
+      raptor_free_sequence(seq);
+      seq = NULL;
+    }
+    if(vars_seq) {
+      raptor_free_sequence(vars_seq);
+      vars_seq = NULL;
+    }
+  } else {
+    if(vars_seq) {
+      if(vars_seq_p)
+        *vars_seq_p = vars_seq;
+      else
+        raptor_free_sequence(vars_seq);
+    }
+  }
+  
+  return seq;
+}
+
+
+/**
+ * rasqal_row_to_nodes:
+ * @row: Result row
+ *
+ * INTERNAL - Turn the given result row literals into RDF strings, URIs or blank literals.
+ * 
+ * Return value: non-0 on failure
+ */
+int
+rasqal_row_to_nodes(rasqal_row* row)
+{
+  int i;
+
+  if(!row)
+    return 1;
+  
+  for(i = 0; i < row->size; i++) {
+    if(row->values[i]) {
+      rasqal_literal* new_l;
+      new_l = rasqal_literal_as_node(row->values[i]);
+      if(!new_l)
+        return -1;
+      rasqal_free_literal(row->values[i]);
+      row->values[i] = new_l;
+    }
+  }
+  
+  return 0;
+}
+
+
+/**
+ * rasqal_row_set_values_from_variables_table:
+ * @row: Result row
+ * @vars_table: Variables table
+ *
+ * INTERNAL - Set the values of all variables in the row from the given variables table
+ * 
+ */
+void
+rasqal_row_set_values_from_variables_table(rasqal_row* row,
+                                           rasqal_variables_table* vars_table)
+{
+  int i;
+  
+  for(i = 0; i < row->size; i++) {
+    rasqal_literal *l;
+    l = rasqal_variables_table_get_value(vars_table, i);
+    if(row->values[i])
+      rasqal_free_literal(row->values[i]);
+    row->values[i] = rasqal_new_literal_from_literal(l);
+  }
+}
+
+
+/**
+ * rasqal_row_set_order_size:
+ * @row: Result row
+ * @order_size: number of order conditions
+ *
+ * INTERNAL - Initialise the row with space to handle @order_size order conditions being evaluated
+ *
+ * Return value: non-0 on failure 
+ */
+int
+rasqal_row_set_order_size(rasqal_row *row, int order_size)
+{
+  row->order_size = order_size;
+  if(row->order_size > 0) {
+    row->order_values = (rasqal_literal**)RASQAL_CALLOC(array,  row->order_size,
+                                                        sizeof(rasqal_literal*));
+    if(!row->order_values) {
+      row->order_size = -1;
+      return 1;
+    }
+  }
+  
+  return 0;
+}
+
+
+/**
+ * rasqal_row_expand_size:
+ * @row: Result row
+ * @size: number of variables
+ *
+ * INTERNAL - Expand the row to be able to handle @size variables
+ *
+ * Return value: non-0 on failure 
+ */
+int
+rasqal_row_expand_size(rasqal_row *row, int size)
+{
+  rasqal_literal** nvalues;
+
+  /* do not allow row size to contract & lose data */
+  if(row->size > size)
+    return 1;
+  
+  nvalues = (rasqal_literal**)RASQAL_CALLOC(array, size,
+                                            sizeof(rasqal_literal*));
+  if(!nvalues)
+    return 1;
+  memcpy(nvalues, row->values, sizeof(rasqal_literal*) * row->size);
+  RASQAL_FREE(array, row->values);
+  row->values = nvalues;
+  
+  row->size = size;
+  return 0;
+}
+
diff --git a/src/rasqal/rasqal_rowsource.c b/src/rasqal/rasqal_rowsource.c
new file mode 100644
index 0000000..e36716f
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource.c
@@ -0,0 +1,712 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource.c - Rasqal query rowsource (row generator) class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#ifndef STANDALONE
+
+
+/**
+ * rasqal_new_rowsource_from_handler:
+ * @query: query object
+ * @user_data: pointer to context information to pass in to calls
+ * @handler: pointer to handler methods
+ * @vars_table: variables table to use for rows
+ * @flags: 0 (none defined so far)
+ *
+ * Create a new rowsource over a user-defined handler.
+ *
+ * Return value: new #rasqal_rowsource object or NULL on failure
+ **/
+rasqal_rowsource*
+rasqal_new_rowsource_from_handler(rasqal_world* world,
+                                  rasqal_query* query,
+                                  void *user_data,
+                                  const rasqal_rowsource_handler *handler,
+                                  rasqal_variables_table* vars_table,
+                                  int flags)
+{
+  rasqal_rowsource* rowsource;
+
+  if(!handler)
+    return NULL;
+
+  if(handler->version < 1 || handler->version > 1)
+    return NULL;
+
+  rowsource = (rasqal_rowsource*)RASQAL_CALLOC(rasqal_rowsource, 1,
+                                               sizeof(rasqal_rowsource));
+  if(!rowsource) {
+    if(handler->finish)
+      handler->finish(NULL, user_data);
+    return NULL;
+  }
+
+  rowsource->world = world;
+  rowsource->query = query;
+  rowsource->user_data = (void*)user_data;
+  rowsource->handler = handler;
+  rowsource->flags = flags;
+
+  rowsource->size= -1;
+
+  if(vars_table)
+    rowsource->vars_table = rasqal_new_variables_table_from_variables_table(vars_table);
+  else
+    rowsource->vars_table = NULL;
+
+  /* no free method here - the variables are owned by rowsource->vars_table */
+  rowsource->variables_sequence = raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_variable_print);
+  if(!rowsource->variables_sequence) {
+    rasqal_free_rowsource(rowsource);
+    return NULL;
+  }
+  
+  if(rowsource->handler->init && 
+     rowsource->handler->init(rowsource, rowsource->user_data)) {
+    RASQAL_DEBUG2("rowsource %s init failed\n", rowsource->handler->name);
+    rasqal_free_rowsource(rowsource);
+    return NULL;
+  }
+  return rowsource;
+}
+
+
+/**
+ * rasqal_free_rowsource:
+ * @rowsource: rowsource object
+ *
+ * Destructor - destroy an rowsource.
+ **/
+void
+rasqal_free_rowsource(rasqal_rowsource *rowsource)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(rowsource, rasqal_rowsource);
+
+  if(rowsource->handler->finish)
+    rowsource->handler->finish(rowsource, rowsource->user_data);
+
+  if(rowsource->vars_table)
+    rasqal_free_variables_table(rowsource->vars_table);
+
+  if(rowsource->variables_sequence)
+    raptor_free_sequence(rowsource->variables_sequence);
+
+  if(rowsource->rows_sequence)
+    raptor_free_sequence(rowsource->rows_sequence);
+
+  RASQAL_FREE(rasqal_rowsource, rowsource);
+}
+
+
+
+/**
+ * rasqal_rowsource_add_variable:
+ * @rowsource: rasqal rowsource
+ * @v: variable
+ *
+ * Add a variable to the rowsource if the variable is not already present
+ *
+ * Return value: variable offset or < 0 on failure
+ **/
+int
+rasqal_rowsource_add_variable(rasqal_rowsource *rowsource, rasqal_variable* v)
+{
+  int offset;
+  
+  offset = rasqal_rowsource_get_variable_offset_by_name(rowsource, v->name);
+  if(offset >= 0)
+    return offset;
+
+  if(raptor_sequence_push(rowsource->variables_sequence, v))
+    return -1;
+
+  if(rowsource->size < 0)
+    rowsource->size = 0;
+
+  offset = rowsource->size;
+  
+  rowsource->size++;
+
+  return offset;
+}
+
+
+/**
+ * rasqal_rowsource_ensure_variables:
+ * @rowsource: rasqal rowsource
+ *
+ * INTERNAL - Ensure that the variables in the rowsource are defined
+ *
+ * Return value: non-0 on failure
+ */
+int
+rasqal_rowsource_ensure_variables(rasqal_rowsource *rowsource)
+{
+  int rc = 0;
+  
+  if(rowsource->updated_variables)
+    return 0;
+
+  rowsource->updated_variables++;
+  
+  if(rowsource->handler->ensure_variables)
+    rc = rowsource->handler->ensure_variables(rowsource, rowsource->user_data);
+
+  return rc;
+}
+
+
+/**
+ * rasqal_rowsource_read_row:
+ * @rowsource: rasqal rowsource
+ *
+ * Read a query result row from the rowsource.
+ *
+ * If a row is returned, it is owned by the caller.
+ *
+ * Return value: row or NULL when no more rows are available
+ **/
+rasqal_row*
+rasqal_rowsource_read_row(rasqal_rowsource *rowsource)
+{
+  rasqal_row* row = NULL;
+  
+  if(rowsource->finished)
+    return NULL;
+
+  rasqal_rowsource_ensure_variables(rowsource);
+
+  if(rowsource->handler->read_row)
+    row = rowsource->handler->read_row(rowsource, rowsource->user_data);
+  else {
+    if(!rowsource->rows_sequence) {
+      rowsource->rows_sequence = rasqal_rowsource_read_all_rows(rowsource);
+      rowsource->offset = 0;
+    }
+
+    if(rowsource->rows_sequence)
+      /* remove and return row from sequence at offset */
+      row = (rasqal_row*)raptor_sequence_delete_at(rowsource->rows_sequence,
+                                                   rowsource->offset++);
+  }
+  
+  if(!row)
+    rowsource->finished = 1;
+  else
+    rowsource->count++;
+
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG1("read row : ");
+  if(row)
+    rasqal_row_print(row, stderr);
+  else
+    fputs("NONE", stderr);
+  fputs("\n", stderr);
+#endif
+
+  return row;
+}
+
+
+/**
+ * rasqal_rowsource_get_row_count:
+ * @rowsource: rasqal rowsource
+ *
+ * Get number of rows seen from a rowsource.
+ *
+ * Return value: row count
+ **/
+int
+rasqal_rowsource_get_rows_count(rasqal_rowsource *rowsource)
+{
+  return rowsource->count;
+}
+
+
+/**
+ * rasqal_rowsource_read_all_rows:
+ * @rowsource: rasqal rowsource
+ *
+ * Read all rows from a rowsource
+ *
+ * After calling this, the rowsource will be empty of rows and finished
+ * and if a sequence is returned, it is owned by the caller.
+ *
+ * Return value: new sequence of all rows (may be size 0) or NULL on failure
+ **/
+raptor_sequence*
+rasqal_rowsource_read_all_rows(rasqal_rowsource *rowsource)
+{
+  raptor_sequence* seq;
+
+  rasqal_rowsource_ensure_variables(rowsource);
+
+  if(rowsource->handler->read_all_rows) {
+    seq = rowsource->handler->read_all_rows(rowsource, rowsource->user_data);
+    if(!seq)
+      seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_row,
+                                (raptor_sequence_print_handler*)rasqal_row_print);
+    return seq;
+  }
+  
+  seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_row,
+                            (raptor_sequence_print_handler*)rasqal_row_print);
+  if(!seq)
+    return NULL;
+  
+  while(1) {
+    rasqal_row* row = rasqal_rowsource_read_row(rowsource);
+    if(!row)
+      break;
+    raptor_sequence_push(seq, row);
+  }
+  
+  return seq;
+}
+
+
+/**
+ * rasqal_rowsource_get_size:
+ * @rowsource: rasqal rowsource
+ *
+ * Get rowsource row width
+ **/
+int
+rasqal_rowsource_get_size(rasqal_rowsource *rowsource)
+{
+  rasqal_rowsource_ensure_variables(rowsource);
+
+  return rowsource->size;
+}
+
+
+/**
+ * rasqal_rowsource_get_variable_by_offset:
+ * @rowsource: rasqal rowsource
+ * @offset: integer offset into array of variables
+ *
+ * Get the variable associated with the given offset
+ *
+ * Return value: pointer to shared #rasqal_variable or NULL if out of range
+ **/
+rasqal_variable*
+rasqal_rowsource_get_variable_by_offset(rasqal_rowsource *rowsource, int offset)
+{
+  rasqal_rowsource_ensure_variables(rowsource);
+
+  if(!rowsource->variables_sequence)
+    return NULL;
+  
+  return (rasqal_variable*)raptor_sequence_get_at(rowsource->variables_sequence,
+                                                  offset);
+}
+
+
+/**
+ * rasqal_rowsource_get_variable_offset_by_name:
+ * @rowsource: rasqal rowsource
+ * @name: variable name
+ *
+ * Get the offset of a variable into the list of variables
+ *
+ * Return value: offset or <0 if not present
+ **/
+int
+rasqal_rowsource_get_variable_offset_by_name(rasqal_rowsource *rowsource,
+                                             const unsigned char* name)
+{
+  int offset= -1;
+  int i;
+  
+  rasqal_rowsource_ensure_variables(rowsource);
+
+  if(!rowsource->variables_sequence)
+    return -1;
+  
+  for(i=0; i < raptor_sequence_size(rowsource->variables_sequence); i++) {
+    rasqal_variable* v;
+    v = (rasqal_variable*)raptor_sequence_get_at(rowsource->variables_sequence, i);
+    if(!strcmp((const char*)v->name, (const char*)name)) {
+      offset = i;
+      break;
+    }
+  }
+
+  return offset;
+}
+
+
+/**
+ * rasqal_rowsource_copy_variables:
+ * @dest_rowsource: destination rowsource to copy into
+ * @src_rowsource: source rowsource to copy from
+ *
+ * INTERNAL - Copy a variables projection from one rowsource to another
+ *
+ * This adds new variables from @src_rowsource to the
+ * @dest_rowsource, it does not add duplicates.
+ **/
+void
+rasqal_rowsource_copy_variables(rasqal_rowsource *dest_rowsource,
+                                rasqal_rowsource *src_rowsource)
+{
+  int i;
+  
+  for(i = 0; i < src_rowsource->size; i++) {
+    rasqal_variable* v;
+    v = rasqal_rowsource_get_variable_by_offset(src_rowsource, i);
+    rasqal_rowsource_add_variable(dest_rowsource, v);
+  }
+}
+
+
+static void 
+rasqal_rowsource_print_header(rasqal_rowsource* rowsource, FILE* fh)
+{
+  int i;
+  
+  fputs("variables: ", fh);
+  for(i = 0; i < rowsource->size; i++) {
+    rasqal_variable* v;
+    const unsigned char *name = NULL;
+
+    v = rasqal_rowsource_get_variable_by_offset(rowsource, i);
+    if(v)
+      name = v->name;
+    if(i > 0)
+      fputs(", ", fh);
+    if(name)
+      fputs((const char*)name, fh);
+    else
+      fputs("NULL", fh);
+  }
+  fputs("\n", fh);
+}
+
+
+/**
+ * rasqal_rowsource_print_row_sequence:
+ * @rowsource: rowsource associated with rows
+ * @seq: query result sequence of #rasqal_row
+ * @fp: FILE* handle to print to
+ *
+ * INTERNAL - Print a result set header with row values from a sequence
+ */
+void 
+rasqal_rowsource_print_row_sequence(rasqal_rowsource* rowsource,
+                                    raptor_sequence* seq,
+                                    FILE* fh)
+{
+  int size = raptor_sequence_size(seq);
+  int i;
+
+  rasqal_rowsource_print_header(rowsource, fh);
+  
+  for(i = 0; i < size; i++) {
+    rasqal_row *row = (rasqal_row*)raptor_sequence_get_at(seq, i);
+    rasqal_row_print(row, fh);
+    fputs("\n", fh);
+  }
+}
+
+
+/**
+ * rasqal_rowsource_reset:
+ * @rowsource: rasqal rowsource
+ *
+ * INTERNAL - Reset a rowsource to regenerate the same set of rows
+ *
+ * Return value: query or NULL
+ **/
+int
+rasqal_rowsource_reset(rasqal_rowsource* rowsource)
+{
+  rowsource->finished = 0;
+  rowsource->count = 0;
+
+  if(rowsource->handler->reset)
+    return rowsource->handler->reset(rowsource, rowsource->user_data);
+
+  return 0;
+}
+
+
+int
+rasqal_rowsource_set_preserve(rasqal_rowsource* rowsource, int preserve)
+{
+  if(rowsource->handler->set_preserve)
+    return rowsource->handler->set_preserve(rowsource,
+                                            rowsource->user_data, preserve);
+
+  return 0;
+}
+
+
+rasqal_rowsource*
+rasqal_rowsource_get_inner_rowsource(rasqal_rowsource* rowsource, int offset)
+{
+  if(rowsource->handler->get_inner_rowsource)
+    return rowsource->handler->get_inner_rowsource(rowsource,
+                                                   rowsource->user_data,
+                                                   offset);
+  return NULL;
+}
+
+
+#define SPACES_LENGTH 80
+static const char spaces[SPACES_LENGTH+1] = "                                                                                ";
+
+static void
+rasqal_rowsource_write_indent(raptor_iostream *iostr, int indent) 
+{
+  while(indent > 0) {
+    int sp = (indent > SPACES_LENGTH) ? SPACES_LENGTH : indent;
+    raptor_iostream_write_bytes(iostr, spaces, sizeof(char), sp);
+    indent -= sp;
+  }
+}
+
+
+static int
+rasqal_rowsource_write_internal(rasqal_rowsource *rowsource, 
+                                raptor_iostream* iostr, int indent)
+{
+  const char* rs_name = rowsource->handler->name;
+  int arg_count = 0;
+  int indent_delta;
+  int offset;
+  rasqal_rowsource* inner_rowsource;
+  
+  indent_delta = strlen(rs_name);
+
+  raptor_iostream_write_counted_string(iostr, rs_name, indent_delta);
+  raptor_iostream_write_counted_string(iostr, "(\n", 2);
+  indent_delta++;
+  
+  indent += indent_delta;
+  rasqal_rowsource_write_indent(iostr, indent);
+
+
+  for(offset = 0;
+      (inner_rowsource = rasqal_rowsource_get_inner_rowsource(rowsource, offset));
+      offset++) {
+      if(arg_count) {
+        raptor_iostream_write_counted_string(iostr, " ,\n", 3);
+        rasqal_rowsource_write_indent(iostr, indent);
+      }
+      rasqal_rowsource_write_internal(inner_rowsource, iostr, indent);
+      arg_count++;
+  }
+
+  raptor_iostream_write_byte(iostr, '\n');
+  indent-= indent_delta;
+
+  rasqal_rowsource_write_indent(iostr, indent);
+  raptor_iostream_write_byte(iostr, ')');
+
+  return 0;
+}
+
+
+int
+rasqal_rowsource_write(rasqal_rowsource *rowsource, raptor_iostream *iostr)
+{
+  return rasqal_rowsource_write_internal(rowsource, iostr, 0);
+}
+  
+
+/**
+ * rasqal_rowsource_print:
+ * @rs: the #rasqal_rowsource object
+ * @fh: the #FILE* handle to print to
+ *
+ * Print a #rasqal_rowsource in a debug format.
+ * 
+ * The print debug format may change in any release.
+ * 
+ **/
+void
+rasqal_rowsource_print(rasqal_rowsource *rowsource, FILE* fh)
+{
+  raptor_iostream *iostr;
+
+  iostr = raptor_new_iostream_to_file_handle(fh);
+  rasqal_rowsource_write(rowsource, iostr);
+  raptor_free_iostream(iostr);
+}
+
+
+#endif
+
+
+
+#ifdef STANDALONE
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+
+#define IN_FILENAME "in.bin"
+#define OUT_BYTES_COUNT 14
+
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program = rasqal_basename(argv[0]);
+#define TEST_ITEMS_COUNT 9
+  int i;
+
+  for(i = 0; i < 4; i++) {
+    rasqal_rowsource *rowsource;
+    size_t count;
+
+    /* for _from_file */
+    FILE *handle = NULL;
+    /* for _from_string */
+    void *string;
+    size_t string_len;
+
+    switch(i) {
+      case 0:
+#ifdef RASQAL_DEBUG
+        fprintf(stderr, "%s: Creating rowsource from afilename '%s'\n",
+                program, OUT_FILENAME);
+#endif
+        rowsource = rasqal_new_rowsource_from_filename((const char*)IN_FILENAME);
+        if(!rowsource) {
+          fprintf(stderr, "%s: Failed to create rowsource to filename '%s'\n",
+                  program, OUT_FILENAME);
+          exit(1);
+        }
+        break;
+
+      case 1:
+#ifdef RASQAL_DEBUG
+        fprintf(stderr, "%s: Creating rowsource from file handle\n", program);
+#endif
+        handle = fopen((const char*)OUT_FILENAME, "wb");
+        rowsource = rasqal_new_rowsource_from_file_handle(handle);
+        if(!rowsource) {
+          fprintf(stderr, "%s: Failed to create rowsource from a file handle\n", program);
+          exit(1);
+        }
+        break;
+
+      case 2:
+#ifdef RASQAL_DEBUG
+        fprintf(stderr, "%s: Creating rowsource from a string\n", program);
+#endif
+        rowsource = rasqal_new_rowsource_from_string(&string, &string_len, NULL);
+        if(!rowsource) {
+          fprintf(stderr, "%s: Failed to create rowsource from a string\n", program);
+          exit(1);
+        }
+        break;
+
+      case 3:
+#ifdef RASQAL_DEBUG
+        fprintf(stderr, "%s: Creating rowsource from a sink\n", program);
+#endif
+        rowsource = rasqal_new_rowsource_from_sink();
+        if(!rowsource) {
+          fprintf(stderr, "%s: Failed to create rowsource from a sink\n", program);
+          exit(1);
+        }
+        break;
+
+      default:
+        fprintf(stderr, "%s: Unknown test case %d init\n", program, i);
+        exit(1);
+    }
+    
+
+    count = rasqal_rowsource_get_rows_count(rowsource);
+    if(count != OUT_BYTES_COUNT) {
+      fprintf(stderr, "%s: I/O stream wrote %d bytes, expected %d\n", program,
+              (int)count, (int)OUT_BYTES_COUNT);
+      return 1;
+    }
+    
+#ifdef RASQAL_DEBUG
+    fprintf(stderr, "%s: Freeing rowsource\n", program);
+#endif
+    rasqal_free_rowsource(rowsource);
+
+    switch(i) {
+      case 0:
+        remove(OUT_FILENAME);
+        break;
+
+      case 1:
+        fclose(handle);
+        remove(OUT_FILENAME);
+        break;
+
+      case 2:
+        if(!string) {
+          fprintf(stderr, "%s: I/O stream failed to create a string\n", program);
+          return 1;
+        }
+        if(string_len != count) {
+          fprintf(stderr, "%s: I/O stream created a string length %d, expected %d\n", program, (int)string_len, (int)count);
+          return 1;
+        }
+        rasqal_free_memory(string);
+        break;
+
+      case 3:
+        break;
+
+      default:
+        fprintf(stderr, "%s: Unknown test case %d tidy\n", program, i);
+        exit(1);
+    }
+    
+  }
+  
+  /* keep gcc -Wall happy */
+  return(0);
+}
+
+#endif
diff --git a/src/rasqal/rasqal_rowsource_empty.c b/src/rasqal/rasqal_rowsource_empty.c
new file mode 100644
index 0000000..e9c4c14
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource_empty.c
@@ -0,0 +1,194 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource_empty.c - Rasqal empty rowsource class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#ifndef STANDALONE
+
+typedef struct 
+{
+  void* undefined;
+} rasqal_empty_rowsource_context;
+
+
+static int
+rasqal_empty_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_empty_rowsource_context* con;
+  con = (rasqal_empty_rowsource_context*)user_data;
+  RASQAL_FREE(rasqal_empty_rowsource_context, con);
+
+  return 0;
+}
+
+static rasqal_row*
+rasqal_empty_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data)
+{
+  /* rasqal_empty_rowsource_context* con;
+  con = (rasqal_empty_rowsource_context*)user_data; */
+  return NULL;
+}
+
+static raptor_sequence*
+rasqal_empty_rowsource_read_all_rows(rasqal_rowsource* rowsource,
+                                     void *user_data)
+{
+  /* rasqal_empty_rowsource_context* con;
+  con = (rasqal_empty_rowsource_context*)user_data; */
+  return NULL;
+}
+
+static const rasqal_rowsource_handler rasqal_empty_rowsource_handler = {
+  /* .version = */ 1,
+  "empty",
+  /* .init = */ NULL,
+  /* .finish = */ rasqal_empty_rowsource_finish,
+  /* .ensure_variables = */ NULL,
+  /* .read_row = */ rasqal_empty_rowsource_read_row,
+  /* .read_all_rows = */ rasqal_empty_rowsource_read_all_rows,
+  /* .reset = */ NULL,
+  /* .set_preserve = */ NULL,
+  /* .get_inner_rowsource = */ NULL
+};
+
+
+rasqal_rowsource*
+rasqal_new_empty_rowsource(rasqal_world *world, rasqal_query* query)
+{
+  rasqal_empty_rowsource_context* con;
+  int flags = 0;
+
+  if(!world || !query)
+    return NULL;
+  
+  con = (rasqal_empty_rowsource_context*)RASQAL_CALLOC(rasqal_empty_rowsource_context, 1, sizeof(rasqal_empty_rowsource_context));
+  if(!con)
+    return NULL;
+
+  return rasqal_new_rowsource_from_handler(world, query,
+                                           con,
+                                           &rasqal_empty_rowsource_handler,
+                                           query->vars_table,
+                                           flags);
+}
+
+
+#endif
+
+
+
+#ifdef STANDALONE
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program = rasqal_basename(argv[0]);
+  rasqal_rowsource *rowsource = NULL;
+  rasqal_world* world = NULL;
+  rasqal_query* query = NULL;
+  rasqal_row* row = NULL;
+  int count;
+  raptor_sequence* seq = NULL;
+  int failures = 0;
+
+  world = rasqal_new_world();
+  if(!world || rasqal_world_open(world)) {
+    fprintf(stderr, "%s: rasqal_world init failed\n", program);
+    return(1);
+  }
+  
+  query = rasqal_new_query(world, "sparql", NULL);
+  
+  rowsource = rasqal_new_empty_rowsource(world, query);
+  if(!rowsource) {
+    fprintf(stderr, "%s: failed to create empty rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+
+  row = rasqal_rowsource_read_row(rowsource);
+  if(row) {
+    fprintf(stderr, "%s: read_row returned a row for a empty stream\n",
+            program);
+    failures++;
+    goto tidy;
+  }
+  
+  count = rasqal_rowsource_get_rows_count(rowsource);
+  if(count) {
+    fprintf(stderr, "%s: read_rows returned a row count for a empty stream\n",
+            program);
+    failures++;
+    goto tidy;
+  }
+  
+  seq = rasqal_rowsource_read_all_rows(rowsource);
+  if(!seq) {
+    fprintf(stderr, "%s: read_rows returned a NULL seq for a empty stream\n",
+            program);
+    failures++;
+    goto tidy;
+  }
+  if(raptor_sequence_size(seq) != 0) {
+    fprintf(stderr, "%s: read_rows returned a non-empty seq for a empty stream\n",
+            program);
+    failures++;
+    goto tidy;
+  }
+
+
+  tidy:
+  if(seq)
+    raptor_free_sequence(seq);
+  if(rowsource)
+    rasqal_free_rowsource(rowsource);
+  if(query)
+    rasqal_free_query(query);
+  if(world)
+    rasqal_free_world(world);
+
+  return failures;
+}
+
+#endif
diff --git a/src/rasqal/rasqal_rowsource_filter.c b/src/rasqal/rasqal_rowsource_filter.c
new file mode 100644
index 0000000..77b7ad6
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource_filter.c
@@ -0,0 +1,241 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource_filter.c - Rasqal filter rowsource class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#define DEBUG_FH stderr
+
+
+typedef struct 
+{
+  /* inner rowsource to filter */
+  rasqal_rowsource *rowsource;
+
+  /* FILTER expression */
+  rasqal_expression* expr;
+
+  /* offset into results for current row */
+  int offset;
+  
+} rasqal_filter_rowsource_context;
+
+
+static int
+rasqal_filter_rowsource_init(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_filter_rowsource_context *con;
+
+  con = (rasqal_filter_rowsource_context*)user_data;
+  
+  return 0;
+}
+
+
+static int
+rasqal_filter_rowsource_ensure_variables(rasqal_rowsource* rowsource,
+                                         void *user_data)
+{
+  rasqal_filter_rowsource_context* con;
+  
+  con = (rasqal_filter_rowsource_context*)user_data; 
+
+  rasqal_rowsource_ensure_variables(con->rowsource);
+
+  rowsource->size = 0;
+  rasqal_rowsource_copy_variables(rowsource, con->rowsource);
+  
+  return 0;
+}
+
+
+static int
+rasqal_filter_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_filter_rowsource_context *con;
+  con = (rasqal_filter_rowsource_context*)user_data;
+
+  if(con->rowsource)
+    rasqal_free_rowsource(con->rowsource);
+  
+  RASQAL_FREE(rasqal_filter_rowsource_context, con);
+
+  return 0;
+}
+
+
+static rasqal_row*
+rasqal_filter_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_query *query = rowsource->query;
+  rasqal_filter_rowsource_context *con;
+  rasqal_row *row = NULL;
+  
+  con = (rasqal_filter_rowsource_context*)user_data;
+
+  while(1) {
+    rasqal_literal* result;
+    int bresult = 1;
+
+    row = rasqal_rowsource_read_row(con->rowsource);
+    if(!row)
+      break;
+
+    result = rasqal_expression_evaluate_v2(rowsource->world, &query->locator,
+                                           con->expr, query->compare_flags);
+#ifdef RASQAL_DEBUG
+    RASQAL_DEBUG1("filter expression result:\n");
+    if(!result)
+      fputs("type error", DEBUG_FH);
+    else
+      rasqal_literal_print(result, DEBUG_FH);
+    fputc('\n', DEBUG_FH);
+#endif
+    if(!result) {
+      bresult = 0;
+    } else {
+      int error = 0;
+      bresult = rasqal_literal_as_boolean(result, &error);
+      if(error)
+        RASQAL_DEBUG1("filter boolean expression returned error\n");
+#ifdef RASQAL_DEBUG
+      else
+        RASQAL_DEBUG2("filter boolean expression result: %d\n", bresult);
+#endif
+      rasqal_free_literal(result);
+    }
+    if(bresult)
+      /* Constraint succeeded so end */
+      break;
+
+    rasqal_free_row(row); row = NULL;
+  }
+
+  if(row) {
+    int i;
+    
+    for(i = 0; i < row->size; i++) {
+      rasqal_literal *l;
+      l = rasqal_variables_table_get_value(query->vars_table, i);
+      if(row->values[i])
+        rasqal_free_literal(row->values[i]);
+      row->values[i] = rasqal_new_literal_from_literal(l);
+    }
+
+    row->offset = con->offset++;
+  }
+  
+  return row;
+}
+
+
+static int
+rasqal_filter_rowsource_reset(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_filter_rowsource_context *con;
+  con = (rasqal_filter_rowsource_context*)user_data;
+
+  return rasqal_rowsource_reset(con->rowsource);
+}
+
+
+static int
+rasqal_filter_rowsource_set_preserve(rasqal_rowsource* rowsource,
+                                     void *user_data, int preserve)
+{
+  rasqal_filter_rowsource_context *con;
+  con = (rasqal_filter_rowsource_context*)user_data;
+
+  return rasqal_rowsource_set_preserve(con->rowsource, preserve);
+}
+
+
+static rasqal_rowsource*
+rasqal_filter_rowsource_get_inner_rowsource(rasqal_rowsource* rowsource,
+                                            void *user_data, int offset)
+{
+  rasqal_filter_rowsource_context *con;
+  con = (rasqal_filter_rowsource_context*)user_data;
+
+  if(offset == 0)
+    return con->rowsource;
+  return NULL;
+}
+
+
+static const rasqal_rowsource_handler rasqal_filter_rowsource_handler = {
+  /* .version =          */ 1,
+  "filter",
+  /* .init =             */ rasqal_filter_rowsource_init,
+  /* .finish =           */ rasqal_filter_rowsource_finish,
+  /* .ensure_variables = */ rasqal_filter_rowsource_ensure_variables,
+  /* .read_row =         */ rasqal_filter_rowsource_read_row,
+  /* .read_all_rows =    */ NULL,
+  /* .reset =            */ rasqal_filter_rowsource_reset,
+  /* .set_preserve =     */ rasqal_filter_rowsource_set_preserve,
+  /* .get_inner_rowsource = */ rasqal_filter_rowsource_get_inner_rowsource
+};
+
+
+rasqal_rowsource*
+rasqal_new_filter_rowsource(rasqal_world *world,
+                            rasqal_query *query,
+                            rasqal_rowsource* rowsource,
+                            rasqal_expression* expr)
+{
+  rasqal_filter_rowsource_context *con;
+  int flags = 0;
+  
+  if(!world || !query || !rowsource || !expr)
+    return NULL;
+  
+  con = (rasqal_filter_rowsource_context*)RASQAL_CALLOC(rasqal_filter_rowsource_context, 1, sizeof(rasqal_filter_rowsource_context));
+  if(!con)
+    return NULL;
+
+  con->rowsource = rowsource;
+  con->expr = expr;
+
+  return rasqal_new_rowsource_from_handler(world, query,
+                                           con,
+                                           &rasqal_filter_rowsource_handler,
+                                           query->vars_table,
+                                           flags);
+}
diff --git a/src/rasqal/rasqal_rowsource_join.c b/src/rasqal/rasqal_rowsource_join.c
new file mode 100644
index 0000000..7e63399
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource_join.c
@@ -0,0 +1,677 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource_join.c - Rasqal join rowsource class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#define DEBUG_FH stderr
+
+#ifndef STANDALONE
+
+#define INIT_RIGHT  (0)
+#define READ_RIGHT (1)
+#define FINISHED   (2)
+
+typedef struct 
+{
+  rasqal_rowsource* left;
+
+  rasqal_rowsource* right;
+
+  /* current left row */
+  rasqal_row *left_row;
+  
+  /* array to map right variables into output rows */
+  int* right_map;
+
+  /* 0 = reading from left rs, 1 = reading from right rs, 2 = finished */
+  int state;
+
+  int failed;
+
+  /* row offset for read_row() */
+  int offset;
+
+  /* join type: 0 = left outer join */
+  int join_type;
+  
+  /* join expression */
+  rasqal_expression *expr;
+} rasqal_join_rowsource_context;
+
+
+static int
+rasqal_join_rowsource_init(rasqal_rowsource* rowsource, void *user_data) 
+{
+  rasqal_join_rowsource_context* con;
+  con = (rasqal_join_rowsource_context*)user_data;
+
+  con->failed = 0;
+
+  con->left_row  = rasqal_rowsource_read_row(con->left);
+  if(!con->left_row) {
+    con->state = FINISHED;
+    return 1;
+  }
+
+  con->state = INIT_RIGHT;
+
+  if(con->expr && rasqal_expression_is_constant(con->expr)) {
+    rasqal_query *query = rowsource->query;
+    rasqal_literal* result;
+    int bresult;
+    
+    result = rasqal_expression_evaluate_v2(rowsource->world, &query->locator,
+                                           con->expr, query->compare_flags);
+
+#ifdef RASQAL_DEBUG
+    RASQAL_DEBUG1("join expression condition is constant: ");
+    if(!result)
+      fputs("type error", DEBUG_FH);
+    else
+      rasqal_literal_print(result, DEBUG_FH);
+    fputc('\n', DEBUG_FH);
+#endif
+    if(!result) {
+      bresult = 0;
+    } else {
+      int error = 0;
+      bresult = rasqal_literal_as_boolean(result, &error);
+      if(error)
+        RASQAL_DEBUG1("join boolean expression returned error\n");
+#ifdef RASQAL_DEBUG
+      else
+        RASQAL_DEBUG2("join boolean expression result: %d\n", bresult);
+#endif
+      rasqal_free_literal(result);
+    }
+
+    /* free expression always */
+    rasqal_free_expression(con->expr); con->expr = NULL;
+
+    if(!bresult) {
+      /* Constraint is always false so row source is finished */
+      con->state = 2;
+    }
+    /* otherwise always true so no need to evaluate on each row
+     * and deleting con->expr will handle that
+     */
+
+  }
+
+  rasqal_rowsource_set_preserve(con->left, 1);
+  rasqal_rowsource_set_preserve(con->right, 1);
+  
+  return 0;
+}
+
+
+static int
+rasqal_join_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_join_rowsource_context* con;
+  con = (rasqal_join_rowsource_context*)user_data;
+  if(con->left)
+    rasqal_free_rowsource(con->left);
+  
+  if(con->right)
+    rasqal_free_rowsource(con->right);
+  
+  if(con->right_map)
+    RASQAL_FREE(int, con->right_map);
+  
+  if(con->expr)
+    rasqal_free_expression(con->expr);
+  
+  RASQAL_FREE(rasqal_join_rowsource_context, con);
+
+  return 0;
+}
+
+
+static int
+rasqal_join_rowsource_ensure_variables(rasqal_rowsource* rowsource,
+                                        void *user_data)
+{
+  rasqal_join_rowsource_context* con;
+  int map_size;
+  int i;
+  
+  con = (rasqal_join_rowsource_context*)user_data;
+
+  if(rasqal_rowsource_ensure_variables(con->left))
+    return 1;
+
+  if(rasqal_rowsource_ensure_variables(con->right))
+    return 1;
+
+  map_size = rasqal_rowsource_get_size(con->right);
+  con->right_map = (int*)RASQAL_MALLOC(int, sizeof(int) * map_size);
+  if(!con->right_map)
+    return 1;
+
+  rowsource->size = 0;
+
+  /* copy in variables from left rowsource */
+  rasqal_rowsource_copy_variables(rowsource, con->left);
+  
+  /* add any new variables not already seen from right rowsource */
+  for(i = 0; i < map_size; i++) {
+    rasqal_variable* v;
+    int offset;
+    
+    v = rasqal_rowsource_get_variable_by_offset(con->right, i);
+    if(!v)
+      break;
+    offset = rasqal_rowsource_add_variable(rowsource, v);
+    if(offset < 0)
+      return 1;
+
+    con->right_map[i] = offset;
+  }
+
+  return 0;
+}
+
+
+static rasqal_row*
+rasqal_join_rowsource_build_merged_row(rasqal_rowsource* rowsource,
+                                       rasqal_join_rowsource_context* con,
+                                       rasqal_row *right_row)
+{
+  rasqal_row *row;
+  int i;
+
+  row = rasqal_new_row_for_size(rowsource->size);
+  if(!row)
+    return NULL;
+
+  row->rowsource = rowsource;
+  row->offset = row->offset;
+
+#ifdef RASQAL_DEBUG
+  RASQAL_DEBUG1("merge\n  left row   : ");
+  rasqal_row_print(con->left_row, stderr);
+  fputs("\n  right row  : ", stderr);
+  if(right_row)
+    rasqal_row_print(right_row, stderr);
+  else
+    fputs("NONE", stderr);
+  fputs("\n", stderr);
+#endif
+
+  for(i = 0; i < con->left_row->size; i++) {
+    rasqal_literal *l = con->left_row->values[i];
+    row->values[i] = rasqal_new_literal_from_literal(l);
+  }
+
+  if(right_row) {
+    for(i = 0; i < right_row->size; i++) {
+      rasqal_literal *l = right_row->values[i];
+      int dest_i = con->right_map[i];
+      if(!row->values[dest_i])
+        row->values[dest_i] = rasqal_new_literal_from_literal(l);
+    }
+
+    rasqal_free_row(right_row);
+  }
+  
+#ifdef RASQAL_DEBUG
+  fputs("  result row : ", stderr);
+  if(row)
+    rasqal_row_print(row, stderr);
+  else
+    fputs("NONE", stderr);
+  fputs("\n", stderr);
+#endif
+
+  return row;
+}
+
+
+static rasqal_row*
+rasqal_join_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_join_rowsource_context* con;
+  rasqal_row* row = NULL;
+  rasqal_query *query = rowsource->query;
+
+  con = (rasqal_join_rowsource_context*)user_data;
+
+  if(con->failed || con->state == FINISHED)
+    return NULL;
+
+  while(1) {
+    rasqal_row *right_row;
+    rasqal_literal *result;
+    int bresult;
+    
+    if(con->state == INIT_RIGHT) {
+      if(!con->left_row) {
+        con->state = FINISHED;
+        return NULL;
+      }
+
+      rasqal_rowsource_reset(con->right);
+      right_row  = rasqal_rowsource_read_row(con->right);
+      row = rasqal_join_rowsource_build_merged_row(rowsource, con, right_row);
+      if(right_row) {
+        con->state = READ_RIGHT;
+      } else {
+        /* con->state = INIT_RIGHT; */
+        if(row)
+          con->left_row = rasqal_rowsource_read_row(con->left);
+      }
+      if(row)
+        goto have_row;
+    }
+
+    /* else state is READ_RIGHT */
+
+    right_row = rasqal_rowsource_read_row(con->right);
+    if(!right_row) {
+      /* right table done, restart left, continue looping */
+      con->state = INIT_RIGHT;
+      con->left_row = rasqal_rowsource_read_row(con->left);
+      continue;
+    }
+
+    /* con->state = READ_RIGHT; */
+    row = rasqal_join_rowsource_build_merged_row(rowsource, con, right_row);
+
+    have_row:
+    if(!con->expr)
+      break;
+
+    result = rasqal_expression_evaluate_v2(rowsource->world, &query->locator,
+                                           con->expr, query->compare_flags);
+#ifdef RASQAL_DEBUG
+    RASQAL_DEBUG1("join expression result:\n");
+    if(!result)
+      fputs("type error", DEBUG_FH);
+    else
+      rasqal_literal_print(result, DEBUG_FH);
+    fputc('\n', DEBUG_FH);
+#endif
+    if(!result) {
+      bresult = 0;
+    } else {
+      int error = 0;
+      bresult = rasqal_literal_as_boolean(result, &error);
+      if(error)
+        RASQAL_DEBUG1("filter boolean expression returned error\n");
+#ifdef RASQAL_DEBUG
+      else
+        RASQAL_DEBUG2("filter boolean expression result: %d\n", bresult);
+#endif
+      rasqal_free_literal(result);
+    }
+    if(bresult)
+      /* Constraint succeeded so return row */
+      break;
+
+    rasqal_free_row(row); row = NULL;
+  }
+
+  if(row) {
+    row->rowsource = rowsource;
+    row->offset = con->offset++;
+  }
+  
+  return row;
+}
+
+
+static int
+rasqal_join_rowsource_reset(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_join_rowsource_context* con;
+  int rc;
+  
+  con = (rasqal_join_rowsource_context*)user_data;
+
+  con->state = INIT_RIGHT;
+  con->failed = 0;
+  
+  rc = rasqal_rowsource_reset(con->left);
+  if(rc)
+    return rc;
+
+  return rasqal_rowsource_reset(con->right);
+}
+
+
+static int
+rasqal_join_rowsource_set_preserve(rasqal_rowsource* rowsource,
+                                   void *user_data, int preserve)
+{
+  rasqal_join_rowsource_context *con;
+  int rc;
+
+  con = (rasqal_join_rowsource_context*)user_data;
+
+  rc = rasqal_rowsource_set_preserve(con->left, preserve);
+  if(rc)
+    return rc;
+
+  return rasqal_rowsource_set_preserve(con->right, preserve);
+}
+
+
+static rasqal_rowsource*
+rasqal_join_rowsource_get_inner_rowsource(rasqal_rowsource* rowsource,
+                                          void *user_data, int offset)
+{
+  rasqal_join_rowsource_context *con;
+  con = (rasqal_join_rowsource_context*)user_data;
+
+  if(offset == 1)
+    return con->left;
+  else if(offset == 2)
+    return con->right;
+  else
+    return NULL;
+}
+
+
+static const rasqal_rowsource_handler rasqal_join_rowsource_handler = {
+  /* .version = */ 1,
+  "join",
+  /* .init = */ rasqal_join_rowsource_init,
+  /* .finish = */ rasqal_join_rowsource_finish,
+  /* .ensure_variables = */ rasqal_join_rowsource_ensure_variables,
+  /* .read_row = */ rasqal_join_rowsource_read_row,
+  /* .read_all_rows = */ NULL,
+  /* .reset = */ rasqal_join_rowsource_reset,
+  /* .set_preserve = */ rasqal_join_rowsource_set_preserve,
+  /* .get_inner_rowsource = */ rasqal_join_rowsource_get_inner_rowsource
+};
+
+
+/**
+ * rasqal_new_join_rowsource:
+ * @world: query world
+ * @query: query results object
+ * @left: left (first) rowsource
+ * @right: right (second) rowsource
+ * @join_type: 0 = left outer join
+ * @expr: join expression to filter result rows
+ *
+ * INTERNAL - create a new JOIN over two rowsources
+ *
+ * This uses the number of variables in @vt to set the rowsource size
+ * (order size is always 0) and then checks that all the rows in the
+ * sequence are the same.  If not, construction fails and NULL is
+ * returned.
+ *
+ * Return value: new rowsource or NULL on failure
+ */
+rasqal_rowsource*
+rasqal_new_join_rowsource(rasqal_world *world,
+                          rasqal_query* query,
+                          rasqal_rowsource* left,
+                          rasqal_rowsource* right,
+                          int join_type,
+                          rasqal_expression *expr)
+{
+  rasqal_join_rowsource_context* con;
+  int flags = 0;
+
+  if(!world || !query || !left || !right)
+    return NULL;
+
+  /* only left outer join now */
+  if(join_type != 0)
+    return NULL;
+  
+  con = (rasqal_join_rowsource_context*)RASQAL_CALLOC(rasqal_join_rowsource_context, 1, sizeof(rasqal_join_rowsource_context));
+  if(!con)
+    return NULL;
+
+  con->left = left;
+  con->right = right;
+  con->join_type = join_type;
+  con->expr = expr;
+  
+  return rasqal_new_rowsource_from_handler(world, query,
+                                           con,
+                                           &rasqal_join_rowsource_handler,
+                                           query->vars_table,
+                                           flags);
+}
+
+
+#endif
+
+
+
+#ifdef STANDALONE
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+
+const char* const join_1_data_2x3_rows[] =
+{
+  /* 2 variable names and 3 rows */
+  "a",   NULL, "b",   NULL,
+  /* row 1 data */
+  "foo", NULL, "bar", NULL,
+  /* row 2 data */
+  "baz", NULL, "fez", NULL,
+  /* row 3 data */
+  "bob", NULL, "sue", NULL,
+  /* end of data */
+  NULL, NULL
+};
+  
+
+const char* const join_2_data_3x4_rows[] =
+{
+  /* 3 variable names and 4 rows */
+  "b",     NULL, "c",      NULL, "d",      NULL,
+  /* row 1 data */
+  "red",   NULL, "orange", NULL, "yellow", NULL,
+  /* row 2 data */
+  "blue",  NULL, "indigo", NULL, "violet", NULL,
+  /* row 3 data */
+  "black", NULL, "silver", NULL, "gold",   NULL,
+  /* row 4 data */
+  "green", NULL, "tope",   NULL, "bronze", NULL,
+  /* end of data */
+  NULL, NULL
+};
+
+
+#define EXPECTED_ROWS_COUNT (3 * 4)
+
+/* there is one duplicate variable 'b' */
+#define EXPECTED_COLUMNS_COUNT (2 + 3 - 1)
+const char* const join_result_vars[] = { "a" , "b" , "c", "d" };
+
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program = rasqal_basename(argv[0]);
+  rasqal_rowsource *rowsource = NULL;
+  rasqal_rowsource *left_rs = NULL;
+  rasqal_rowsource *right_rs = NULL;
+  rasqal_world* world = NULL;
+  rasqal_query* query = NULL;
+  int count;
+  raptor_sequence* seq = NULL;
+  int failures = 0;
+  int vars_count;
+  rasqal_variables_table* vt;
+  int size;
+  int expected_count = EXPECTED_ROWS_COUNT;
+  int expected_size = EXPECTED_COLUMNS_COUNT;
+  int i;
+  raptor_sequence* vars_seq = NULL;
+  
+  world = rasqal_new_world(); rasqal_world_open(world);
+  
+  query = rasqal_new_query(world, "sparql", NULL);
+  
+  vt = query->vars_table;
+
+  /* 2 variables and 3 rows */
+  vars_count = 2;
+  seq = rasqal_new_row_sequence(world, vt, join_1_data_2x3_rows, vars_count,
+                                &vars_seq);
+  if(!seq) {
+    fprintf(stderr,
+            "%s: failed to create left sequence of %d vars\n", program,
+            vars_count);
+    failures++;
+    goto tidy;
+  }
+
+  left_rs = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq);
+  if(!left_rs) {
+    fprintf(stderr, "%s: failed to create left rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+  /* vars_seq and seq are now owned by left_rs */
+  vars_seq = seq = NULL;
+  
+  /* 3 variables and 4 rows */
+  vars_count = 3;
+  seq = rasqal_new_row_sequence(world, vt, join_2_data_3x4_rows, vars_count,
+                                &vars_seq);
+  if(!seq) {
+    fprintf(stderr,
+            "%s: failed to create right sequence of %d rows\n", program,
+            vars_count);
+    failures++;
+    goto tidy;
+  }
+
+  right_rs = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq);
+  if(!right_rs) {
+    fprintf(stderr, "%s: failed to create right rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+  /* vars_seq and seq are now owned by right_rs */
+  vars_seq = seq = NULL;
+
+  rowsource = rasqal_new_join_rowsource(world, query, left_rs, right_rs, 0, NULL);
+  if(!rowsource) {
+    fprintf(stderr, "%s: failed to create join rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+  /* left_rs and right_rs are now owned by rowsource */
+  left_rs = right_rs = NULL;
+
+  seq = rasqal_rowsource_read_all_rows(rowsource);
+  if(!seq) {
+    fprintf(stderr,
+            "%s: read_rows returned a NULL seq for a join rowsource\n",
+            program);
+    failures++;
+    goto tidy;
+  }
+  count = raptor_sequence_size(seq);
+  if(count != expected_count) {
+    fprintf(stderr,
+            "%s: read_rows returned %d rows for a join rowsource, expected %d\n",
+            program, count, expected_count);
+    failures++;
+    goto tidy;
+  }
+  
+  size = rasqal_rowsource_get_size(rowsource);
+  if(size != expected_size) {
+    fprintf(stderr,
+            "%s: read_rows returned %d columns (variables) for a join rowsource, expected %d\n",
+            program, size, expected_size);
+    failures++;
+    goto tidy;
+  }
+  for(i = 0; i < expected_size; i++) {
+    rasqal_variable* v;
+    const char* name = NULL;
+    const char *expected_name = join_result_vars[i];
+    
+    v = rasqal_rowsource_get_variable_by_offset(rowsource, i);
+    if(!v) {
+      fprintf(stderr,
+            "%s: read_rows had NULL column (variable) #%d expected %s\n",
+              program, i, expected_name);
+      failures++;
+      goto tidy;
+    }
+    name = (const char*)v->name;
+    if(strcmp(name, expected_name)) {
+      fprintf(stderr,
+            "%s: read_rows returned column (variable) #%d %s but expected %s\n",
+              program, i, name, expected_name);
+      failures++;
+      goto tidy;
+    }
+  }
+  
+  
+#ifdef RASQAL_DEBUG
+  rasqal_rowsource_print_row_sequence(rowsource, seq, DEBUG_FH);
+#endif
+
+  tidy:
+  if(seq)
+    raptor_free_sequence(seq);
+  if(left_rs)
+    rasqal_free_rowsource(left_rs);
+  if(right_rs)
+    rasqal_free_rowsource(right_rs);
+  if(rowsource)
+    rasqal_free_rowsource(rowsource);
+  if(query)
+    rasqal_free_query(query);
+  if(world)
+    rasqal_free_world(world);
+
+  return failures;
+}
+
+#endif
diff --git a/src/rasqal/rasqal_rowsource_project.c b/src/rasqal/rasqal_rowsource_project.c
new file mode 100644
index 0000000..639a767
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource_project.c
@@ -0,0 +1,410 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource_project.c - Rasqal variables projection rowsource class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#define DEBUG_FH stderr
+
+
+#ifndef STANDALONE
+
+typedef struct 
+{
+  /* inner rowsource to project */
+  rasqal_rowsource *rowsource;
+
+  /* variable names to project input rows to */
+  raptor_sequence* projection_variables;
+
+  /* variables projection array: [output row var index]=input row var index */
+  int* projection;
+
+} rasqal_project_rowsource_context;
+
+
+static int
+rasqal_project_rowsource_init(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_project_rowsource_context *con;
+
+  con = (rasqal_project_rowsource_context*)user_data;
+  
+  return 0;
+}
+
+
+static int
+rasqal_project_rowsource_ensure_variables(rasqal_rowsource* rowsource,
+                                         void *user_data)
+{
+  rasqal_project_rowsource_context* con;
+  int size;
+  int i;
+  
+  con = (rasqal_project_rowsource_context*)user_data; 
+
+  rasqal_rowsource_ensure_variables(con->rowsource);
+
+  rowsource->size = 0;
+
+  size = raptor_sequence_size(con->projection_variables);
+
+  con->projection = (int*)RASQAL_MALLOC(array, sizeof(int*) * size);
+  if(!con->projection)
+    return 1;
+  
+  for(i = 0; i <= size; i++) {
+    rasqal_variable* v;
+    int offset;
+    
+    v = (rasqal_variable*)raptor_sequence_get_at(con->projection_variables, i);
+    if(!v)
+      break;
+    offset = rasqal_rowsource_get_variable_offset_by_name(con->rowsource, 
+                                                          v->name);
+#ifdef RASQAL_DEBUG
+    if(offset < 0)
+      RASQAL_DEBUG2("Variable %s is in projection but not in input rowsource\n",
+                    v->name);
+#endif
+
+    rasqal_rowsource_add_variable(rowsource, v);
+    con->projection[i] = offset;
+  }
+
+  return 0;
+}
+
+
+static int
+rasqal_project_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_project_rowsource_context *con;
+  con = (rasqal_project_rowsource_context*)user_data;
+
+  if(con->rowsource)
+    rasqal_free_rowsource(con->rowsource);
+  
+  if(con->projection)
+    RASQAL_FREE(int, con->projection);
+  
+  RASQAL_FREE(rasqal_project_rowsource_context, con);
+
+  return 0;
+}
+
+
+static rasqal_row*
+rasqal_project_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_project_rowsource_context *con;
+  rasqal_row *row = NULL;
+  
+  con = (rasqal_project_rowsource_context*)user_data;
+
+  row = rasqal_rowsource_read_row(con->rowsource);
+  if(row) {
+    rasqal_row* nrow;
+    int i;
+    
+    nrow = rasqal_new_row_for_size(rowsource->size);
+    if(!nrow) {
+      rasqal_free_row(row);
+      row = NULL;
+    } else {
+      nrow->rowsource = rowsource;
+      nrow->offset = row->offset;
+      
+      for(i = 0; i < rowsource->size; i++) {
+        int offset = con->projection[i];
+        if(offset >= 0)
+          nrow->values[i] = rasqal_new_literal_from_literal(row->values[offset]);
+      }
+      rasqal_free_row(row);
+      row = nrow;
+    }
+  }
+  
+  return row;
+}
+
+
+static int
+rasqal_project_rowsource_reset(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_project_rowsource_context *con;
+  con = (rasqal_project_rowsource_context*)user_data;
+
+  return rasqal_rowsource_reset(con->rowsource);
+}
+
+
+static int
+rasqal_project_rowsource_set_preserve(rasqal_rowsource* rowsource,
+                                      void *user_data, int preserve)
+{
+  rasqal_project_rowsource_context *con;
+  con = (rasqal_project_rowsource_context*)user_data;
+
+  return rasqal_rowsource_set_preserve(con->rowsource, preserve);
+}
+
+
+static rasqal_rowsource*
+rasqal_project_rowsource_get_inner_rowsource(rasqal_rowsource* rowsource,
+                                             void *user_data, int offset)
+{
+  rasqal_project_rowsource_context *con;
+  con = (rasqal_project_rowsource_context*)user_data;
+
+  if(offset == 0)
+    return con->rowsource;
+  return NULL;
+}
+
+
+static const rasqal_rowsource_handler rasqal_project_rowsource_handler = {
+  /* .version =          */ 1,
+  "project",
+  /* .init =             */ rasqal_project_rowsource_init,
+  /* .finish =           */ rasqal_project_rowsource_finish,
+  /* .ensure_variables = */ rasqal_project_rowsource_ensure_variables,
+  /* .read_row =         */ rasqal_project_rowsource_read_row,
+  /* .read_all_rows =    */ NULL,
+  /* .reset =            */ rasqal_project_rowsource_reset,
+  /* .set_preserve =     */ rasqal_project_rowsource_set_preserve,
+  /* .get_inner_rowsource = */ rasqal_project_rowsource_get_inner_rowsource
+};
+
+
+rasqal_rowsource*
+rasqal_new_project_rowsource(rasqal_world *world,
+                             rasqal_query *query,
+                             rasqal_rowsource* rowsource,
+                             raptor_sequence* projection_variables)
+{
+  rasqal_project_rowsource_context *con;
+  int flags = 0;
+  
+  if(!world || !query || !rowsource || !projection_variables)
+    return NULL;
+  
+  con = (rasqal_project_rowsource_context*)RASQAL_CALLOC(rasqal_project_rowsource_context, 1, sizeof(rasqal_project_rowsource_context));
+  if(!con)
+    return NULL;
+
+  con->rowsource = rowsource;
+  con->projection_variables = projection_variables;
+
+  return rasqal_new_rowsource_from_handler(world, query,
+                                           con,
+                                           &rasqal_project_rowsource_handler,
+                                           query->vars_table,
+                                           flags);
+}
+
+
+
+
+#endif
+
+
+
+#ifdef STANDALONE
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+
+const char* const project_1_data_4x2_rows[] =
+{
+  /* 4 variable names and 2 rows */
+  "a",   NULL, "b",   NULL, "c",   NULL, "d",   NULL,
+  /* row 1 data */
+  "foo", NULL, "bar", NULL, "baz", NULL, "fez", NULL,
+  /* row 2 data */
+  "bob", NULL, "sue", NULL, "kit", NULL, "kat", NULL,
+  /* end of data */
+  NULL, NULL
+};
+  
+const char* const project_1_var_names[] = { "c", "b" };
+
+#define EXPECTED_ROWS_COUNT 2
+#define EXPECTED_COLUMNS_COUNT 2
+
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program = rasqal_basename(argv[0]);
+  rasqal_rowsource *rowsource = NULL;
+  rasqal_rowsource *input_rs = NULL;
+  rasqal_world* world = NULL;
+  rasqal_query* query = NULL;
+  int count;
+  raptor_sequence* seq = NULL;
+  int failures = 0;
+  int vars_count;
+  rasqal_variables_table* vt;
+  int size;
+  int expected_count = EXPECTED_ROWS_COUNT;
+  int expected_size = EXPECTED_COLUMNS_COUNT;
+  int i;
+  raptor_sequence* vars_seq = NULL;
+  raptor_sequence* projection_seq = NULL;
+  
+  world = rasqal_new_world(); rasqal_world_open(world);
+  
+  query = rasqal_new_query(world, "sparql", NULL);
+  
+  vt = query->vars_table;
+
+  /* 4 variables and 2 rows */
+  vars_count = 4;
+  seq = rasqal_new_row_sequence(world, vt, project_1_data_4x2_rows, vars_count,
+                                &vars_seq);
+  if(!seq) {
+    fprintf(stderr,
+            "%s: failed to create left sequence of %d vars\n", program,
+            vars_count);
+    failures++;
+    goto tidy;
+  }
+
+  input_rs = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq);
+  if(!input_rs) {
+    fprintf(stderr, "%s: failed to create left rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+  /* vars_seq and seq are now owned by input_rs */
+  vars_seq = seq = NULL;
+  
+  projection_seq = raptor_new_sequence(NULL, NULL);
+  for(i = 0 ; i < EXPECTED_COLUMNS_COUNT; i++) {
+    rasqal_variable* v;
+    unsigned const char* name=(unsigned const char*)project_1_var_names[i];
+    v = rasqal_variables_table_get_by_name(vt, name);
+    if(v)
+      raptor_sequence_push(projection_seq, v);
+  }
+
+  rowsource = rasqal_new_project_rowsource(world, query, input_rs, projection_seq);
+  if(!rowsource) {
+    fprintf(stderr, "%s: failed to create project rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+  /* input_rs and right_rs are now owned by rowsource */
+  input_rs = NULL;
+
+  seq = rasqal_rowsource_read_all_rows(rowsource);
+  if(!seq) {
+    fprintf(stderr,
+            "%s: read_rows returned a NULL seq for a project rowsource\n",
+            program);
+    failures++;
+    goto tidy;
+  }
+  count = raptor_sequence_size(seq);
+  if(count != expected_count) {
+    fprintf(stderr,
+            "%s: read_rows returned %d rows for a project rowsource, expected %d\n",
+            program, count, expected_count);
+    failures++;
+    goto tidy;
+  }
+  
+  size = rasqal_rowsource_get_size(rowsource);
+  if(size != expected_size) {
+    fprintf(stderr,
+            "%s: read_rows returned %d columns (variables) for a project rowsource, expected %d\n",
+            program, size, expected_size);
+    failures++;
+    goto tidy;
+  }
+  for(i = 0; i < expected_size; i++) {
+    rasqal_variable* v;
+    const char* name = NULL;
+    const char *expected_name = project_1_var_names[i];
+    
+    v = rasqal_rowsource_get_variable_by_offset(rowsource, i);
+    if(!v) {
+      fprintf(stderr,
+            "%s: read_rows had NULL column (variable) #%d expected %s\n",
+              program, i, expected_name);
+      failures++;
+      goto tidy;
+    }
+    name = (const char*)v->name;
+    if(strcmp(name, expected_name)) {
+      fprintf(stderr,
+            "%s: read_rows returned column (variable) #%d %s but expected %s\n",
+              program, i, name, expected_name);
+      failures++;
+      goto tidy;
+    }
+  }
+  
+#ifdef RASQAL_DEBUG
+  fprintf(DEBUG_FH, "result of projection:\n");
+  rasqal_rowsource_print_row_sequence(rowsource, seq, DEBUG_FH);
+#endif
+
+  tidy:
+  if(seq)
+    raptor_free_sequence(seq);
+  if(projection_seq)
+    raptor_free_sequence(projection_seq);
+  if(input_rs)
+    rasqal_free_rowsource(input_rs);
+  if(rowsource)
+    rasqal_free_rowsource(rowsource);
+  if(query)
+    rasqal_free_query(query);
+  if(world)
+    rasqal_free_world(world);
+
+  return failures;
+}
+
+#endif
diff --git a/src/rasqal/rasqal_rowsource_rowsequence.c b/src/rasqal/rasqal_rowsource_rowsequence.c
new file mode 100644
index 0000000..b738d0c
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource_rowsequence.c
@@ -0,0 +1,464 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource_rowsequence.c - Rasqal rowsequence rowsource class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#ifndef STANDALONE
+
+typedef struct 
+{
+  raptor_sequence* seq;
+
+  /* variables for this rowsource */
+  raptor_sequence* vars_seq;
+  
+  /* index into seq or <0 when finished */
+  int offset;
+
+  int failed;
+} rasqal_rowsequence_rowsource_context;
+
+
+static int
+rasqal_rowsequence_rowsource_init(rasqal_rowsource* rowsource, void *user_data) 
+{
+  rasqal_rowsequence_rowsource_context* con;
+  int rows_count;
+  int i;
+  
+  con = (rasqal_rowsequence_rowsource_context*)user_data;
+  con->offset = 0;
+
+  con->failed = 0;
+  
+  /* adjust offset of every row */
+  rows_count = raptor_sequence_size(con->seq);
+  for(i = 0; i < rows_count; i++) {
+    rasqal_row* row;
+    row = (rasqal_row*)raptor_sequence_get_at(con->seq, i);
+    
+    row->rowsource = rowsource;
+    row->offset = i;
+    
+  }
+
+  return 0;
+}
+
+
+static int
+rasqal_rowsequence_rowsource_finish(rasqal_rowsource* rowsource,
+                                    void *user_data)
+{
+  rasqal_rowsequence_rowsource_context* con;
+
+  con = (rasqal_rowsequence_rowsource_context*)user_data;
+  if(con->seq)
+    raptor_free_sequence(con->seq);
+  
+  RASQAL_FREE(rasqal_rowsequence_rowsource_context, con);
+
+  return 0;
+}
+
+
+static int
+rasqal_rowsequence_rowsource_ensure_variables(rasqal_rowsource* rowsource,
+                                              void *user_data)
+{
+  rasqal_rowsequence_rowsource_context* con;
+  int i;
+  
+  con = (rasqal_rowsequence_rowsource_context*)user_data;
+
+  rowsource->size = 0;
+  for(i = 0; i < raptor_sequence_size(con->vars_seq); i++) {
+    rasqal_variable* v;
+    v = (rasqal_variable*)raptor_sequence_get_at(con->vars_seq, i);
+    rasqal_rowsource_add_variable(rowsource, v);
+  }
+  
+  raptor_free_sequence(con->vars_seq);
+  con->vars_seq = NULL;
+  
+  return 0;
+}
+
+
+static rasqal_row*
+rasqal_rowsequence_rowsource_read_row(rasqal_rowsource* rowsource,
+                                      void *user_data)
+{
+  rasqal_rowsequence_rowsource_context* con;
+  rasqal_row* row = NULL;
+  
+  con = (rasqal_rowsequence_rowsource_context*)user_data;
+  if(con->failed || con->offset < 0)
+    return NULL;
+
+  row = (rasqal_row*)raptor_sequence_get_at(con->seq, con->offset);
+  if(!row) {
+    /* finished */
+    con->offset = -1;
+  } else {
+    row = rasqal_new_row_from_row(row);
+    con->offset++;
+  }
+
+  return row;
+}
+
+
+static raptor_sequence*
+rasqal_rowsequence_rowsource_read_all_rows(rasqal_rowsource* rowsource,
+                                           void *user_data)
+{
+  rasqal_rowsequence_rowsource_context* con;
+  raptor_sequence* seq;
+  
+  con = (rasqal_rowsequence_rowsource_context*)user_data;
+  if(con->offset < 0)
+    return NULL;
+
+  seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_row,
+                            (raptor_sequence_print_handler*)rasqal_row_print);
+  if(seq) {
+    int i;
+    int size = raptor_sequence_size(con->seq);
+    for(i = 0; i < size; i++) {
+      rasqal_row *row = (rasqal_row*)raptor_sequence_get_at(con->seq, i);
+      raptor_sequence_push(seq, rasqal_new_row_from_row(row));
+    }
+  }
+  
+  return seq;
+}
+
+
+static int
+rasqal_rowsequence_rowsource_reset(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_rowsequence_rowsource_context* con;
+
+  con = (rasqal_rowsequence_rowsource_context*)user_data;
+
+  con->offset = 0;
+
+  return 0;
+}
+
+
+static const rasqal_rowsource_handler rasqal_rowsequence_rowsource_handler = {
+  /* .version = */ 1,
+  "rowsequence",
+  /* .init = */ rasqal_rowsequence_rowsource_init,
+  /* .finish = */ rasqal_rowsequence_rowsource_finish,
+  /* .ensure_variables = */ rasqal_rowsequence_rowsource_ensure_variables,
+  /* .read_row = */ rasqal_rowsequence_rowsource_read_row,
+  /* .read_all_rows = */ rasqal_rowsequence_rowsource_read_all_rows,
+  /* .reset = */ rasqal_rowsequence_rowsource_reset,
+  /* .set_preserve = */ NULL,
+  /* .get_inner_rowsource = */ NULL
+};
+
+
+/**
+ * rasqal_new_rowsequence_rowsource:
+ * @world: world object
+ * @query: query object
+ * @vt: variables table
+ * @seq: sequence of rasqal_row*
+ * @vars_seq: sequence of variables for this row
+ *
+ * INTERNAL - create a new rowsource over a sequence of rows
+ *
+ * This uses the number of variables in @vt to set the rowsource size
+ * (order size is always 0) and then checks that all the rows in the
+ * sequence are the same.  If not, construction fails and NULL is
+ * returned.
+ *
+ * Return value: new rowsource or NULL on failure
+ */
+rasqal_rowsource*
+rasqal_new_rowsequence_rowsource(rasqal_world *world,
+                                 rasqal_query* query, 
+                                 rasqal_variables_table* vt,
+                                 raptor_sequence* seq,
+                                 raptor_sequence* vars_seq)
+{
+  rasqal_rowsequence_rowsource_context* con;
+  int flags = 0;
+  
+  if(!world || !query || !vt || !seq || !vars_seq)
+    return NULL;
+
+  if(!raptor_sequence_size(seq) || !raptor_sequence_size(vars_seq))
+    return NULL;
+  
+  con = (rasqal_rowsequence_rowsource_context*)RASQAL_CALLOC(rasqal_rowsequence_rowsource_context, 1, sizeof(rasqal_rowsequence_rowsource_context));
+  if(!con)
+    return NULL;
+
+  con->seq = seq;
+  con->vars_seq = vars_seq;
+
+  return rasqal_new_rowsource_from_handler(world, query,
+                                           con,
+                                           &rasqal_rowsequence_rowsource_handler,
+                                           vt,
+                                           flags);
+}
+
+
+#endif
+
+
+
+#ifdef STANDALONE
+
+
+const char* const test_1_rows[] =
+{
+  /* 2 variable names */
+  "a",   NULL, "b",   NULL,
+  /* row 1 data */
+  "foo", NULL, "bar", NULL,
+  /* end of data */
+  NULL, NULL
+};
+  
+
+const char* const test_3_rows[] =
+{
+  /* 4 variable names */
+  "c1",    NULL, "c2",     NULL, "c3",     NULL, "c4",       NULL,
+  /* row 1 data */
+  "red",   NULL, "orange", NULL, "yellow", NULL, "green",    NULL,
+  /* row 2 data */
+  "blue",  NULL, "indigo", NULL, "violet", NULL, "white",    NULL,
+  /* row 3 data */
+  "black", NULL, "silver", NULL, "gold",   NULL, "platinum", NULL,
+  /* end of data */
+  NULL, NULL
+};
+  
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program = rasqal_basename(argv[0]);
+  rasqal_rowsource *rowsource = NULL;
+  raptor_sequence *seq = NULL;
+  rasqal_world* world = NULL;
+  rasqal_query* query = NULL;
+  rasqal_row* row = NULL;
+  int count;
+  int failures = 0;
+  rasqal_variables_table* vt;
+  int rows_count;
+  int i;
+  raptor_sequence* vars_seq = NULL;
+  
+  world = rasqal_new_world();
+  if(!world || rasqal_world_open(world)) {
+    fprintf(stderr, "%s: rasqal_world init failed\n", program);
+    return(1);
+  }
+  
+  query = rasqal_new_query(world, "sparql", NULL);
+  
+  /* test 1-row rowsource (2 variables) */
+  rows_count = 1;
+  
+#ifdef RASQAL_DEBUG  
+  RASQAL_DEBUG2("Testing %d-row rowsource\n", rows_count);
+#endif
+
+  vt = rasqal_new_variables_table(world);
+
+  /* add 2 variables to table and 1 row sequence */
+  seq = rasqal_new_row_sequence(world, vt, test_1_rows, 2, &vars_seq);
+  if(!seq) {
+    fprintf(stderr, "%s: failed to create sequence of %d rows\n", program,
+            rows_count);
+    failures++;
+    goto tidy;
+  }
+
+  rowsource = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq);
+  if(!rowsource) {
+    fprintf(stderr, "%s: failed to create %d-row sequence rowsource\n",
+            program, rows_count);
+    failures++;
+    goto tidy;
+  }
+  /* vars_seq and seq are now owned by rowsource */
+  vars_seq = seq = NULL;
+
+  row = rasqal_rowsource_read_row(rowsource);
+  if(!row) {
+    fprintf(stderr,
+            "%s: read_row returned no row for a %d-row sequence rowsource\n",
+            program, rows_count);
+    failures++;
+    goto tidy;
+  }
+
+#ifdef RASQAL_DEBUG  
+  RASQAL_DEBUG1("Result Row:\n  ");
+  rasqal_row_print(row, stderr);
+  fputc('\n', stderr);
+#endif
+
+  rasqal_free_row(row); row = NULL;
+
+  count = rasqal_rowsource_get_rows_count(rowsource);
+  if(count != rows_count) {
+    fprintf(stderr,
+            "%s: read_rows returned count %d instead of %d for a %d-row sequence rowsource\n",
+            program, count, rows_count, rows_count);
+    failures++;
+    goto tidy;
+  }
+
+  row = rasqal_rowsource_read_row(rowsource);
+  if(row) {
+    fprintf(stderr,
+            "%s: read_row returned > %d rows for a %d-row sequence rowsource\n",
+            program, rows_count, rows_count);
+    failures++;
+    goto tidy;
+  }
+  
+
+  rasqal_free_rowsource(rowsource); rowsource = NULL;
+  rasqal_free_variables_table(vt); vt = NULL;
+
+  /* test 3-row rowsource */
+  rows_count = 3;
+
+#ifdef RASQAL_DEBUG  
+  RASQAL_DEBUG2("Testing %d-row rowsource\n", rows_count);
+#endif
+
+  vt = rasqal_new_variables_table(world);
+
+  /* add 4 variables to table and 3 row sequence */
+  seq = rasqal_new_row_sequence(world, vt, test_3_rows, 4, &vars_seq);
+  if(!seq) {
+    fprintf(stderr, "%s: failed to create sequence of %d rows\n",
+            program, rows_count);
+    failures++;
+    goto tidy;
+  }
+
+  rowsource = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq);
+  if(!rowsource) {
+    fprintf(stderr, "%s: failed to create %d-row sequence rowsource\n",
+            program, rows_count);
+    failures++;
+    goto tidy;
+  }
+  /* vars_seq and seq are now owned by rowsource */
+  vars_seq = seq = NULL;
+
+  for(i = 0; i < rows_count; i++) {
+    row = rasqal_rowsource_read_row(rowsource);
+    if(!row) {
+      fprintf(stderr,
+              "%s: read_row returned no row for row %d in a %d-row sequence rowsource\n",
+              program, i, rows_count);
+      failures++;
+      goto tidy;
+    }
+
+  #ifdef RASQAL_DEBUG  
+    RASQAL_DEBUG1("Result Row:\n  ");
+    rasqal_row_print(row, stderr);
+    fputc('\n', stderr);
+  #endif
+
+    rasqal_free_row(row); row = NULL;
+  }
+  
+  count = rasqal_rowsource_get_rows_count(rowsource);
+  if(count != rows_count) {
+    fprintf(stderr,
+            "%s: read_rows returned count %d instead of %d for a %d-row sequence rowsource\n",
+            program, count, rows_count, rows_count);
+    failures++;
+    goto tidy;
+  }
+
+  row = rasqal_rowsource_read_row(rowsource);
+  if(row) {
+    fprintf(stderr,
+            "%s: read_row returned >%d rows for a %d-row sequence rowsource\n",
+            program, rows_count, rows_count);
+    failures++;
+    goto tidy;
+  }
+  
+  rasqal_free_rowsource(rowsource); rowsource = NULL;
+  rasqal_free_variables_table(vt); vt = NULL;
+
+
+  tidy:
+  if(row)
+    rasqal_free_row(row);
+  if(seq)
+    raptor_free_sequence(seq);
+  if(rowsource)
+    rasqal_free_rowsource(rowsource);
+  if(vt)
+    rasqal_free_variables_table(vt);
+  if(query)
+    rasqal_free_query(query);
+  if(world)
+    rasqal_free_world(world);
+
+  return failures;
+}
+
+#endif
diff --git a/src/rasqal/rasqal_rowsource_sort.c b/src/rasqal/rasqal_rowsource_sort.c
new file mode 100644
index 0000000..9a9e4cd
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource_sort.c
@@ -0,0 +1,260 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource_source.c - Rasqal source rowsource class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#define DEBUG_FH stderr
+
+
+typedef struct 
+{
+  /* inner rowsource to sort */
+  rasqal_rowsource *rowsource;
+
+  /* map for sorting */
+  rasqal_map* map;
+
+  /* sequence of order conditions #rasqal_expression */
+  raptor_sequence* seq;
+
+  /* number of order conditions in query->order_conditions_sequence */
+  int order_size;
+} rasqal_sort_rowsource_context;
+
+
+static int
+rasqal_sort_rowsource_init(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_query *query = rowsource->query;
+  rasqal_sort_rowsource_context *con;
+
+  con = (rasqal_sort_rowsource_context*)user_data;
+  
+  if(query->order_conditions_sequence)
+    con->order_size = raptor_sequence_size(query->order_conditions_sequence);
+  else {
+    RASQAL_DEBUG1("No order conditions for sort rowsource - passing through");
+    con->order_size = -1;
+  }
+  
+  con->map = NULL;
+
+  if(con->order_size > 0 ) {
+    /* make a row:NULL map in order to sort or do distinct */
+    con->map = rasqal_engine_new_rowsort_map(query->distinct,
+                                             query->compare_flags,
+                                             query->order_conditions_sequence);
+    if(!con->map)
+      return 1;
+  }
+  
+  con->seq = NULL;
+
+  return 0;
+}
+
+
+static int
+rasqal_sort_rowsource_process(rasqal_rowsource* rowsource,
+                              rasqal_sort_rowsource_context* con)
+{
+  int offset = 0;
+
+  /* already processed */
+  if(con->seq)
+    return 0;
+  
+  con->seq = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_row, 
+                                 (raptor_sequence_print_handler*)rasqal_row_print);
+  if(!con->seq)
+    return 1;
+  
+  while(1) {
+    rasqal_row* row;
+
+    row = rasqal_rowsource_read_row(con->rowsource);
+    if(!row)
+      break;
+
+    rasqal_row_set_order_size(row, con->order_size);
+
+    rasqal_engine_rowsort_calculate_order_values(rowsource->query, row);
+
+    row->offset = offset;
+
+    /* after this, row is owned by map */
+    if(!rasqal_engine_rowsort_map_add_row(con->map, row))
+      offset++;
+  }
+  
+#ifdef RASQAL_DEBUG
+  if(con->map) {
+    fputs("resulting ", DEBUG_FH);
+    rasqal_map_print(con->map, DEBUG_FH);
+    fputs("\n", DEBUG_FH);
+  }
+#endif
+  
+  /* do sort/distinct: walk map in order, adding rows to sequence */
+  rasqal_engine_rowsort_map_to_sequence(con->map, con->seq);
+  rasqal_free_map(con->map); con->map = NULL;
+
+  return 0;
+}
+
+
+static int
+rasqal_sort_rowsource_ensure_variables(rasqal_rowsource* rowsource,
+                                       void *user_data)
+{
+  rasqal_sort_rowsource_context* con;
+  con = (rasqal_sort_rowsource_context*)user_data; 
+
+  rasqal_rowsource_ensure_variables(con->rowsource);
+
+  rowsource->size = 0;
+  rasqal_rowsource_copy_variables(rowsource, con->rowsource);
+  
+  return 0;
+}
+
+
+static int
+rasqal_sort_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_sort_rowsource_context *con;
+  con = (rasqal_sort_rowsource_context*)user_data;
+
+  if(con->rowsource)
+    rasqal_free_rowsource(con->rowsource);
+  
+  if(con->map)
+    rasqal_free_map(con->map);
+
+  if(con->seq)
+    raptor_free_sequence(con->seq);
+
+  RASQAL_FREE(rasqal_sort_rowsource_context, con);
+
+  return 0;
+}
+
+
+static raptor_sequence*
+rasqal_sort_rowsource_read_all_rows(rasqal_rowsource* rowsource,
+                                    void *user_data)
+{
+  rasqal_sort_rowsource_context *con;
+  raptor_sequence *seq = NULL;
+  
+  con = (rasqal_sort_rowsource_context*)user_data;
+
+  /* if there were no ordering conditions, pass it all on to inner rowsource */
+  if(con->order_size <= 0)
+    return rasqal_rowsource_read_all_rows(con->rowsource);
+
+
+  /* need to sort */
+  if(rasqal_sort_rowsource_process(rowsource, con))
+    return NULL;
+
+  if(con->seq) {
+    /* pass ownership of seq back to caller */
+    seq = con->seq;
+    con->seq = NULL;
+  }
+  
+  return seq;
+}
+
+
+static rasqal_rowsource*
+rasqal_sort_rowsource_get_inner_rowsource(rasqal_rowsource* rowsource,
+                                          void *user_data, int offset)
+{
+  rasqal_sort_rowsource_context *con;
+  con = (rasqal_sort_rowsource_context*)user_data;
+
+  if(offset == 0)
+    return con->rowsource;
+  return NULL;
+}
+
+
+static const rasqal_rowsource_handler rasqal_sort_rowsource_handler = {
+  /* .version =          */ 1,
+  "sort",
+  /* .init =             */ rasqal_sort_rowsource_init,
+  /* .finish =           */ rasqal_sort_rowsource_finish,
+  /* .ensure_variables = */ rasqal_sort_rowsource_ensure_variables,
+  /* .read_row =         */ NULL,
+  /* .read_all_rows =    */ rasqal_sort_rowsource_read_all_rows,
+  /* .reset =            */ NULL,
+  /* .set_preserve =     */ NULL,
+  /* .get_inner_rowsource = */ rasqal_sort_rowsource_get_inner_rowsource
+};
+
+
+rasqal_rowsource*
+rasqal_new_sort_rowsource(rasqal_world *world,
+                          rasqal_query *query,
+                          rasqal_rowsource *rowsource,
+                          raptor_sequence *seq)
+{
+  rasqal_sort_rowsource_context *con;
+  int flags = 0;
+
+  if(!world || !query || !rowsource || !seq)
+    return NULL;
+  
+  con = (rasqal_sort_rowsource_context*)RASQAL_CALLOC(rasqal_sort_rowsource_context, 1, sizeof(rasqal_sort_rowsource_context));
+  if(!con)
+    return NULL;
+
+  con->rowsource = rowsource;
+  con->seq = seq;
+
+  return rasqal_new_rowsource_from_handler(world, query,
+                                           con,
+                                           &rasqal_sort_rowsource_handler,
+                                           query->vars_table,
+                                           flags);
+}
diff --git a/src/rasqal/rasqal_rowsource_triples.c b/src/rasqal/rasqal_rowsource_triples.c
new file mode 100644
index 0000000..ac24692
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource_triples.c
@@ -0,0 +1,720 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource_triples.c - Rasqal triple pattern rowsource class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#ifndef STANDALONE
+
+typedef struct 
+{
+  /* source of triple pattern matches */
+  rasqal_triples_source* triples_source;
+
+  /* sequence of triple SHARED with query */
+  raptor_sequence* triples;
+
+  /* current column being iterated */
+  int column;
+
+  /* first triple pattern in sequence to use */
+  int start_column;
+
+  /* last triple pattern in sequence to use */
+  int end_column;
+
+  /* number of triple patterns in the sequence
+     ( = end_column - start_column + 1) */
+  int triples_count;
+  
+  /* An array of items, one per triple pattern in the sequence */
+  rasqal_triple_meta* triple_meta;
+
+  /* offset into results for current row */
+  int offset;
+  
+  /* number of variables used in variables table  */
+  int size;
+  
+  /* declared in array index[index into vars table] = column */
+  int *declared_in;
+
+  /* preserve bindings when all rows are finished - for optional mostly */
+  int preserve_on_all_finished;
+} rasqal_triples_rowsource_context;
+
+
+static int
+rasqal_triples_rowsource_init(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_triples_rowsource_context *con;
+  int column;
+  int *declared_in = NULL;
+  int rc = 0;
+  int size;
+  int i;
+  
+  con = (rasqal_triples_rowsource_context*)user_data;
+
+  size = rasqal_variables_table_get_named_variables_count(rowsource->vars_table);
+  declared_in = con->declared_in;
+  
+  /* Construct the ordered projection of the variables set by these triples */
+  con->size = 0;
+  for(i = 0; i < size; i++) {
+    column = declared_in[i];
+    if(column >= con->start_column && column <= con->end_column) {
+      rasqal_variable *v;
+      v = rasqal_variables_table_get(rowsource->vars_table, i);
+      raptor_sequence_push(rowsource->variables_sequence, v);
+      con->size++;
+    }
+  }
+
+  con->column = con->start_column;
+
+  for(column = con->start_column; column <= con->end_column; column++) {
+    rasqal_triple_meta *m;
+    rasqal_triple *t;
+    rasqal_variable* v;
+
+    m = &con->triple_meta[column - con->start_column];
+    if(!m) {
+      rc = 1;
+      break;
+    }
+
+    m->parts = (rasqal_triple_parts)0;
+
+    t = (rasqal_triple*)raptor_sequence_get_at(con->triples, column);
+    
+    if((v = rasqal_literal_as_variable(t->subject)) &&
+       declared_in[v->offset] == column)
+      m->parts = (rasqal_triple_parts)(m->parts | RASQAL_TRIPLE_SUBJECT);
+    
+    if((v = rasqal_literal_as_variable(t->predicate)) &&
+       declared_in[v->offset] == column)
+      m->parts = (rasqal_triple_parts)(m->parts | RASQAL_TRIPLE_PREDICATE);
+    
+    if((v = rasqal_literal_as_variable(t->object)) &&
+       declared_in[v->offset] == column)
+      m->parts = (rasqal_triple_parts)(m->parts | RASQAL_TRIPLE_OBJECT);
+
+    if(t->origin &&
+       (v = rasqal_literal_as_variable(t->origin)) &&
+       declared_in[v->offset] == column)
+      m->parts = (rasqal_triple_parts)(m->parts | RASQAL_TRIPLE_ORIGIN);
+
+    RASQAL_DEBUG3("triple pattern column %d has parts %d\n", column, m->parts);
+
+    /* exact if there are no variables in the triple parts */
+    m->is_exact = 1;
+    if(rasqal_literal_as_variable(t->predicate) ||
+       rasqal_literal_as_variable(t->subject) ||
+       rasqal_literal_as_variable(t->object))
+      m->is_exact = 0;
+
+  }
+  
+  return rc;
+}
+
+
+static int
+rasqal_triples_rowsource_ensure_variables(rasqal_rowsource* rowsource,
+                                          void *user_data)
+{
+  rasqal_triples_rowsource_context* con;
+  con = (rasqal_triples_rowsource_context*)user_data; 
+
+  rowsource->size = con->size;
+  
+  return 0;
+}
+
+
+static int
+rasqal_triples_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_triples_rowsource_context *con;
+  int i;
+  
+  con = (rasqal_triples_rowsource_context*)user_data;
+
+  for(i = con->start_column; i <= con->end_column; i++) {
+    rasqal_triple_meta *m;
+    m = &con->triple_meta[i - con->start_column];
+    rasqal_reset_triple_meta(m);
+  }
+  
+  if(con->triple_meta)
+    RASQAL_FREE(rasqal_triple_meta, con->triple_meta);
+
+  RASQAL_FREE(rasqal_triples_rowsource_context, con);
+
+  return 0;
+}
+
+
+static rasqal_engine_error
+rasqal_triples_rowsource_get_next_row(rasqal_rowsource* rowsource, 
+                                      rasqal_triples_rowsource_context *con)
+{
+  rasqal_query *query = rowsource->query;
+  rasqal_engine_error error = RASQAL_ENGINE_OK;
+  
+  while(con->column >= con->start_column) {
+    rasqal_triple_meta *m;
+    rasqal_triple *t;
+
+    m = &con->triple_meta[con->column - con->start_column];
+    t = (rasqal_triple*)raptor_sequence_get_at(con->triples, con->column);
+
+    error = RASQAL_ENGINE_OK;
+
+    if(!m) {
+      /* error recovery - no match */
+      con->column--;
+      error = RASQAL_ENGINE_FAILED;
+      goto done;
+    }
+    
+    if(m->executed) {
+      RASQAL_DEBUG2("triples match already executed in column %d\n",
+                    con->column);
+      con->column--;
+      continue;
+    }
+      
+    if(m->is_exact) {
+      /* exact triple match wanted */
+
+      if(!rasqal_triples_source_triple_present(con->triples_source, t)) {
+        /* failed */
+        RASQAL_DEBUG2("exact match failed for column %d\n", con->column);
+        con->column--;
+      }
+#ifdef RASQAL_DEBUG
+      else
+        RASQAL_DEBUG2("exact match OK for column %d\n", con->column);
+#endif
+
+      RASQAL_DEBUG2("end of exact triples match for column %d\n", con->column);
+      m->executed = 1;
+      
+    } else {
+      /* triple pattern match wanted */
+      int parts;
+
+      if(!m->triples_match) {
+        /* Column has no triples match so create a new query */
+        m->triples_match = rasqal_new_triples_match(query,
+                                                    con->triples_source,
+                                                    m, t);
+        if(!m->triples_match) {
+          rasqal_log_error_simple(rowsource->world, RAPTOR_LOG_LEVEL_ERROR,
+                                  &query->locator,
+                                  "Failed to make a triple match for column%d",
+                                  con->column);
+          /* failed to match */
+          con->column--;
+          error = RASQAL_ENGINE_FAILED;
+          goto done;
+        }
+        RASQAL_DEBUG2("made new triples match for column %d\n", con->column);
+      }
+
+
+      if(rasqal_triples_match_is_end(m->triples_match)) {
+        RASQAL_DEBUG2("end of pattern triples match for column %d\n",
+                      con->column);
+        m->executed = 1;
+
+        if(con->preserve_on_all_finished && 
+           con->column == con->end_column) {
+          int is_finished = 1;
+          int i;
+          
+          RASQAL_DEBUG1("CHECKING ALL TRIPLE PATTERNS FINISHED\n");
+
+          for(i = con->start_column; i < con->end_column; i++) {
+            rasqal_triple_meta *m2;
+            m2 = &con->triple_meta[con->column - con->start_column];
+            if(!rasqal_triples_match_is_end(m2->triples_match)) {
+              is_finished = 0;
+              break;
+            }
+          }
+          if(is_finished) {
+            RASQAL_DEBUG1("end of all pattern triples matches\n");
+            con->column--;
+            error = RASQAL_ENGINE_FINISHED;
+            goto done;
+          }
+        }
+
+        rasqal_reset_triple_meta(m);
+
+        con->column--;
+        continue;
+      }
+
+      if(m->parts) {
+        parts = rasqal_triples_match_bind_match(m->triples_match, m->bindings,
+                                                m->parts);
+        RASQAL_DEBUG3("bind_match for column %d returned parts %d\n",
+                      con->column, parts);
+        if(!parts)
+          error = RASQAL_ENGINE_FINISHED;
+      } else {
+        RASQAL_DEBUG2("Nothing to bind_match for column %d\n", con->column);
+      }
+
+      rasqal_triples_match_next_match(m->triples_match);
+      if(error == RASQAL_ENGINE_FINISHED)
+        continue;
+
+    }
+    
+    if(con->column == con->end_column) {
+      /* Done all conjunctions */ 
+      
+      /* exact match, so column must have ended */
+      if(m->is_exact)
+        con->column--;
+
+      /* return with result */
+      error = RASQAL_ENGINE_OK;
+      goto done;
+    } else if(con->column >= con->start_column)
+      con->column++;
+
+  }
+
+  if(con->column < con->start_column)
+    error = RASQAL_ENGINE_FINISHED;
+  
+  done:
+  return error;
+}
+
+
+static rasqal_row*
+rasqal_triples_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_triples_rowsource_context *con;
+  int i;
+  rasqal_row* row = NULL;
+  rasqal_engine_error error = RASQAL_ENGINE_OK;
+  
+  con = (rasqal_triples_rowsource_context*)user_data;
+
+  error = rasqal_triples_rowsource_get_next_row(rowsource, con);
+  RASQAL_DEBUG2("rasqal_triples_rowsource_get_next_row() returned %d\n", error);
+
+  if(error != RASQAL_ENGINE_OK)
+    goto done;
+
+#ifdef RASQAL_DEBUG
+  if(1) {
+    int values_returned = 0;
+    /* Count actual bound values */
+    for(i = 0; i < con->size; i++) {
+      rasqal_variable* v;
+      v = rasqal_rowsource_get_variable_by_offset(rowsource, i);
+      if(v->value)
+        values_returned++;
+    }
+    RASQAL_DEBUG2("Solution binds %d values\n", values_returned);
+  }
+#endif
+
+  row = rasqal_new_row(rowsource);
+  if(!row) {
+    error = RASQAL_ENGINE_FAILED;
+    goto done;
+  }
+
+  for(i = 0; i < row->size; i++) {
+    rasqal_variable* v;
+    v = rasqal_rowsource_get_variable_by_offset(rowsource, i);
+    if(row->values[i])
+      rasqal_free_literal(row->values[i]);
+    row->values[i] = rasqal_new_literal_from_literal(v->value);
+  }
+
+  row->offset = con->offset++;
+
+  done:
+  if(error != RASQAL_ENGINE_OK) {
+    if(row) {
+      rasqal_free_row(row);
+      row = NULL;
+    }
+  }
+
+  return row;
+}
+
+
+static raptor_sequence*
+rasqal_triples_rowsource_read_all_rows(rasqal_rowsource* rowsource,
+                                       void *user_data)
+{
+  rasqal_triples_rowsource_context *con;
+  raptor_sequence *seq = NULL;
+  
+  con = (rasqal_triples_rowsource_context*)user_data;
+
+  return seq;
+}
+
+
+static int
+rasqal_triples_rowsource_reset(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_triples_rowsource_context *con;
+  int column;
+  
+  con = (rasqal_triples_rowsource_context*)user_data;
+
+  con->column = con->start_column;
+  for(column = con->start_column; column <= con->end_column; column++) {
+    rasqal_triple_meta *m;
+    
+    m = &con->triple_meta[column - con->start_column];
+    rasqal_reset_triple_meta(m);
+  }
+
+  return 0;
+}
+
+
+static int
+rasqal_triples_rowsource_set_preserve(rasqal_rowsource* rowsource,
+                                      void *user_data, int preserve)
+{
+  rasqal_triples_rowsource_context *con;
+
+  con = (rasqal_triples_rowsource_context*)user_data;
+  con->preserve_on_all_finished = preserve;
+
+  return 0;
+}
+
+
+static const rasqal_rowsource_handler rasqal_triples_rowsource_handler = {
+  /* .version = */ 1,
+  "triple pattern",
+  /* .init = */ rasqal_triples_rowsource_init,
+  /* .finish = */ rasqal_triples_rowsource_finish,
+  /* .ensure_variables = */ rasqal_triples_rowsource_ensure_variables,
+  /* .read_row = */ rasqal_triples_rowsource_read_row,
+  /* .read_all_rows = */ rasqal_triples_rowsource_read_all_rows,
+  /* .reset = */ rasqal_triples_rowsource_reset,
+  /* .set_preserve = */ rasqal_triples_rowsource_set_preserve,
+  /* .get_inner_rowsource = */ NULL
+};
+
+
+rasqal_rowsource*
+rasqal_new_triples_rowsource(rasqal_world *world,
+                             rasqal_query *query,
+                             rasqal_triples_source* triples_source,
+                             raptor_sequence* triples,
+                             int start_column, int end_column,
+                             int *declared_in)
+{
+  rasqal_triples_rowsource_context *con;
+  int flags = 0;
+
+  if(!world || !query || !triples_source || !triples)
+    return NULL;
+  
+  con = (rasqal_triples_rowsource_context*)RASQAL_CALLOC(rasqal_triples_rowsource_context, 1, sizeof(rasqal_triples_rowsource_context));
+  if(!con)
+    return NULL;
+
+  con->triples_source = triples_source;
+  con->triples = triples;
+  con->start_column = start_column;
+  con->end_column = end_column;
+  con->column = -1;
+  con->declared_in = declared_in;
+
+  con->triples_count = con->end_column - con->start_column + 1;
+
+  con->triple_meta = (rasqal_triple_meta*)RASQAL_CALLOC(rasqal_triple_meta,
+                                                        con->triples_count,
+                                                        sizeof(rasqal_triple_meta));
+  if(!con->triple_meta) {
+    rasqal_triples_rowsource_finish(NULL, con);
+    return NULL;
+  }
+
+  return rasqal_new_rowsource_from_handler(world, query,
+                                           con,
+                                           &rasqal_triples_rowsource_handler,
+                                           query->vars_table,
+                                           flags);
+}
+
+
+#endif
+
+
+
+#ifdef STANDALONE
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+#define QUERY_LANGUAGE "sparql"
+#define QUERY_FORMAT "\
+SELECT ?s ?p ?o \
+FROM <%s> \
+WHERE { ?s ?p ?o }\
+"
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program = rasqal_basename(argv[0]);
+  rasqal_rowsource *rowsource = NULL;
+  rasqal_world *world;
+  rasqal_query *query;
+  const char *query_language_name = QUERY_LANGUAGE;
+  const char *query_format = QUERY_FORMAT;
+  unsigned char *query_string;
+  int failures = 0;
+  int start_column;
+  int end_column;
+  int rc;
+  raptor_sequence* triples;
+  rasqal_triples_source* triples_source;
+  raptor_uri *base_uri = NULL;
+  unsigned char *data_string = NULL;
+  unsigned char *uri_string = NULL;
+  /* <http://example.org#subject> <http://example.org#predicate> "object" . */
+#define SUBJECT_URI_STRING (const unsigned char*)"http://example.org#subject";
+#define PREDICATE_URI_STRING (const unsigned char*)"http://example.org#predicate";
+#define OBJECT_STRING "object"
+  raptor_uri* s_uri = NULL;
+  raptor_uri* p_uri = NULL;
+  int size;
+  int *declared_in;
+  
+  if(argc != 2) {
+    fprintf(stderr, "USAGE: %s data-filename\n", program);
+    return(1);
+  }
+    
+  world = rasqal_new_world();
+  if(!world || rasqal_world_open(world)) {
+    fprintf(stderr, "%s: rasqal_world init failed\n", program);
+    return(1);
+  }
+  
+  query = rasqal_new_query(world, "sparql", NULL);
+  
+  data_string = raptor_uri_filename_to_uri_string(argv[1]);
+  query_string = (unsigned char*)RASQAL_MALLOC(cstring, strlen((const char*)data_string)+strlen(query_format)+1);
+  sprintf((char*)query_string, query_format, data_string);
+  raptor_free_memory(data_string);
+  
+  uri_string = raptor_uri_filename_to_uri_string("");
+#ifdef RAPTOR_V2_AVAILABLE
+  base_uri = raptor_new_uri_v2(world->raptor_world_ptr, uri_string);  
+#else
+  base_uri = raptor_new_uri(uri_string);  
+#endif
+  raptor_free_memory(uri_string);
+
+  query = rasqal_new_query(world, query_language_name, NULL);
+  if(!query) {
+    fprintf(stderr, "%s: creating query in language %s FAILED\n", program,
+            query_language_name);
+    failures++;
+    goto tidy;
+  }
+
+  printf("%s: preparing %s query\n", program, query_language_name);
+  rc = rasqal_query_prepare(query, query_string, base_uri);
+  if(rc) {
+    fprintf(stderr, "%s: failed to prepare query '%s'\n", program,
+            query_string);
+    failures++;
+    goto tidy;
+  }
+  
+  RASQAL_FREE(cstring, query_string);
+  query_string = NULL;
+
+  triples = rasqal_query_get_triple_sequence(query);
+  start_column = 0;
+  end_column = 0;
+
+  triples_source = rasqal_new_triples_source(query);
+  
+  size = rasqal_variables_table_get_named_variables_count(query->vars_table);
+  declared_in = rasqal_query_triples_build_declared_in(query, size,
+                                                       start_column,
+                                                       end_column);
+  if(!declared_in) {
+    fprintf(stderr, "%s: failed to create declared_in\n", program);
+    failures++;
+    goto tidy;
+  }
+
+  rowsource = rasqal_new_triples_rowsource(world, query, triples_source,
+                                           triples, start_column, end_column,
+                                           declared_in);
+  if(!rowsource) {
+    fprintf(stderr, "%s: failed to create triples rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+
+  while(1) {
+    rasqal_row* row;
+    rasqal_literal *s;
+    rasqal_literal *p;
+    rasqal_literal *o;
+
+    row = rasqal_rowsource_read_row(rowsource);
+    if(!row)
+      break;
+    
+  #ifdef RASQAL_DEBUG  
+    RASQAL_DEBUG1("Result Row:\n  ");
+    rasqal_row_print(row, stderr);
+    fputc('\n', stderr);
+  #endif
+
+#ifdef RAPTOR_V2_AVAILABLE
+    s_uri = raptor_new_uri_v2(world->raptor_world_ptr, SUBJECT_URI_STRING);
+    p_uri = raptor_new_uri_v2(world->raptor_world_ptr, PREDICATE_URI_STRING);
+#else
+    s_uri = raptor_new_uri(SUBJECT_URI_STRING);
+    p_uri = raptor_new_uri(PREDICATE_URI_STRING);
+#endif
+    
+    s = row->values[0];
+    if(!s ||
+       (s && s->type != RASQAL_LITERAL_URI) ||
+#ifdef RAPTOR_V2_AVAILABLE
+       !raptor_uri_equals_v2(world->raptor_world_ptr, s->value.uri, s_uri)
+#else
+       !raptor_uri_equals(s->value.uri, s_uri)
+#endif
+       ) {
+      fprintf(stderr, "%s: 's' is bound to %s not URI %s\n", program,
+              rasqal_literal_as_string(s),
+#ifdef RAPTOR_V2_AVAILABLE
+              raptor_uri_as_string_v2(world->raptor_world_ptr, s_uri)
+#else
+              raptor_uri_as_string(s_uri)
+#endif
+              );
+      failures++;
+    }
+    p = row->values[1];
+    if(!p ||
+       (p && p->type != RASQAL_LITERAL_URI) ||
+#ifdef RAPTOR_V2_AVAILABLE
+       !raptor_uri_equals_v2(world->raptor_world_ptr, p->value.uri, p_uri)
+#else       
+       !raptor_uri_equals(p->value.uri, p_uri)
+#endif
+       ) {
+      fprintf(stderr, "%s: 'p' is bound to %s not URI %s\n", program,
+              rasqal_literal_as_string(p),
+#ifdef RAPTOR_V2_AVAILABLE
+              raptor_uri_as_string_v2(world->raptor_world_ptr, p_uri)
+#else
+              raptor_uri_as_string(p_uri)
+#endif
+              );
+      failures++;
+    }
+    o = row->values[2];
+    if(!o ||
+       (o && o->type != RASQAL_LITERAL_STRING) ||
+       strcmp((const char*)o->string, OBJECT_STRING)) {
+      fprintf(stderr, "%s: 'o' is bound to %s not string '%s'\n", program,
+              rasqal_literal_as_string(o), OBJECT_STRING);
+      failures++;
+    }
+
+    rasqal_free_row(row);
+    if(failures)
+      break;
+  }
+
+  tidy:
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_free_uri_v2(world->raptor_world_ptr, base_uri);
+  if(s_uri)
+    raptor_free_uri_v2(world->raptor_world_ptr, s_uri);
+  if(p_uri)
+    raptor_free_uri_v2(world->raptor_world_ptr, p_uri);
+#else
+  raptor_free_uri(base_uri);
+  if(s_uri)
+    raptor_free_uri(s_uri);
+  if(p_uri)
+    raptor_free_uri(p_uri);
+#endif
+
+  if(declared_in)
+    RASQAL_FREE(intarray, declared_in);
+  if(triples_source)
+    rasqal_free_triples_source(triples_source);
+  if(rowsource)
+    rasqal_free_rowsource(rowsource);
+  if(query)
+    rasqal_free_query(query);
+  if(world)
+    rasqal_free_world(world);
+
+  return failures;
+}
+
+#endif
diff --git a/src/rasqal/rasqal_rowsource_union.c b/src/rasqal/rasqal_rowsource_union.c
new file mode 100644
index 0000000..a1c3370
--- /dev/null
+++ b/src/rasqal/rasqal_rowsource_union.c
@@ -0,0 +1,579 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_rowsource_union.c - Rasqal union rowsource class
+ *
+ * Copyright (C) 2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <raptor.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#define DEBUG_FH stderr
+
+#ifndef STANDALONE
+
+typedef struct 
+{
+  rasqal_rowsource* left;
+
+  rasqal_rowsource* right;
+
+  /* array of size (number of variables in @right) with this row offset value */
+  int* right_map;
+
+  /* 0 = reading from left rs, 1 = reading from right rs, 2 = finished */
+  int state;
+
+  int failed;
+
+  /* row offset for read_row() */
+  int offset;
+} rasqal_union_rowsource_context;
+
+
+static int
+rasqal_union_rowsource_init(rasqal_rowsource* rowsource, void *user_data) 
+{
+  rasqal_union_rowsource_context* con;
+  con = (rasqal_union_rowsource_context*)user_data;
+  con->state = 0;
+
+  con->failed = 0;
+  
+  return 0;
+}
+
+
+static int
+rasqal_union_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_union_rowsource_context* con;
+  con = (rasqal_union_rowsource_context*)user_data;
+  if(con->left)
+    rasqal_free_rowsource(con->left);
+  
+  if(con->right)
+    rasqal_free_rowsource(con->right);
+  
+  if(con->right_map)
+    RASQAL_FREE(int, con->right_map);
+  
+  RASQAL_FREE(rasqal_union_rowsource_context, con);
+
+  return 0;
+}
+
+
+static int
+rasqal_union_rowsource_ensure_variables(rasqal_rowsource* rowsource,
+                                        void *user_data)
+{
+  rasqal_union_rowsource_context* con;
+  int map_size;
+  int i;
+  
+  con = (rasqal_union_rowsource_context*)user_data;
+
+  if(rasqal_rowsource_ensure_variables(con->left))
+    return 1;
+
+  if(rasqal_rowsource_ensure_variables(con->right))
+    return 1;
+
+  map_size = rasqal_rowsource_get_size(con->right);
+  con->right_map = (int*)RASQAL_MALLOC(int, sizeof(int) * map_size);
+  if(!con->right_map)
+    return 1;
+
+  rowsource->size = 0;
+
+  /* copy in variables from left rowsource */
+  rasqal_rowsource_copy_variables(rowsource, con->left);
+  
+  /* add any new variables not already seen from right rowsource */
+  for(i = 0; i < map_size; i++) {
+    rasqal_variable* v;
+    int offset;
+    
+    v = rasqal_rowsource_get_variable_by_offset(con->right, i);
+    if(!v)
+      break;
+    offset = rasqal_rowsource_add_variable(rowsource, v);
+    if(offset < 0)
+      return 1;
+
+    con->right_map[i] = offset;
+  }
+
+  return 0;
+}
+
+
+static void
+rasqal_union_rowsource_adjust_right_row(rasqal_union_rowsource_context* con,
+                                        rasqal_row *row)
+{
+  rasqal_rowsource *rowsource = con->right;
+  int i;
+  
+  for(i = rowsource->size - 1; i >= 0; i--) {
+    int offset = con->right_map[i];
+    row->values[offset] = row->values[i];
+    row->values[i] = NULL;
+  }
+}
+
+
+static rasqal_row*
+rasqal_union_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_union_rowsource_context* con;
+  rasqal_row* row = NULL;
+
+  con = (rasqal_union_rowsource_context*)user_data;
+  
+  if(con->failed || con->state > 1)
+    return NULL;
+
+  if(con->state == 0) {
+    row = rasqal_rowsource_read_row(con->left);
+    if(!row)
+      con->state = 1;
+    else {
+      /* otherwise: rows from left are correct order but wrong size */
+      if(rasqal_row_expand_size(row, rowsource->size))
+        return NULL;
+    }
+  }
+  if(!row && con->state == 1) {
+    row = rasqal_rowsource_read_row(con->right);
+    if(!row)
+      /* finished */
+      con->state = 2;
+    else {
+      if(rasqal_row_expand_size(row, rowsource->size))
+        return NULL;
+      /* transform row from right to match new projection */
+      rasqal_union_rowsource_adjust_right_row(con, row);
+    }
+  }
+
+  if(row) {
+    row->rowsource = rowsource;
+    row->offset = con->offset++;
+  }
+  
+  return row;
+}
+
+
+static raptor_sequence*
+rasqal_union_rowsource_read_all_rows(rasqal_rowsource* rowsource,
+                                     void *user_data)
+{
+  rasqal_union_rowsource_context* con;
+  raptor_sequence* seq1 = NULL;
+  raptor_sequence* seq2 = NULL;
+  int left_size;
+  int right_size;
+  int i;
+  
+  con = (rasqal_union_rowsource_context*)user_data;
+
+  if(con->failed)
+    return NULL;
+  
+  seq1 = rasqal_rowsource_read_all_rows(con->left);
+  if(!seq1) {
+    con->failed = 1;
+    return NULL;
+  }
+
+  seq2 = rasqal_rowsource_read_all_rows(con->right);
+  if(!seq2) {
+    con->failed = 1;
+    raptor_free_sequence(seq1);
+    return NULL;
+  }
+
+#ifdef RASQAL_DEBUG
+  fprintf(DEBUG_FH, "left rowsource (%d vars):\n",
+          rasqal_rowsource_get_size(con->left));
+  rasqal_rowsource_print_row_sequence(con->left, seq1, DEBUG_FH);
+
+  fprintf(DEBUG_FH, "right rowsource (%d vars):\n",
+          rasqal_rowsource_get_size(con->right));
+  rasqal_rowsource_print_row_sequence(con->right, seq2, DEBUG_FH);
+#endif
+
+  /* transform rows from left to match new projection */
+  left_size = raptor_sequence_size(seq1);
+  for(i = 0; i < left_size; i++) {
+    rasqal_row *row = (rasqal_row*)raptor_sequence_get_at(seq1, i);
+    /* rows from left are correct order but wrong size */
+    rasqal_row_expand_size(row, rowsource->size);
+    row->rowsource = rowsource;
+  }
+  /* transform rows from right to match new projection */
+  right_size = raptor_sequence_size(seq2);
+  for(i = 0; i < right_size; i++) {
+    rasqal_row *row = (rasqal_row*)raptor_sequence_get_at(seq2, i);
+    /* rows from right need resizing and adjusting by offset */
+    rasqal_row_expand_size(row, rowsource->size);
+    rasqal_union_rowsource_adjust_right_row(con, row);
+    row->offset += left_size;
+    row->rowsource = rowsource;
+  }
+
+  if(raptor_sequence_join(seq1, seq2)) {
+    raptor_free_sequence(seq1);
+    seq1 = NULL;
+  }
+  raptor_free_sequence(seq2);
+  
+  con->state = 2;
+  return seq1;
+}
+
+
+static int
+rasqal_union_rowsource_reset(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_union_rowsource_context* con;
+  int rc;
+  
+  con = (rasqal_union_rowsource_context*)user_data;
+
+  con->state = 0;
+  con->failed = 0;
+
+  rc = rasqal_rowsource_reset(con->left);
+  if(rc)
+    return rc;
+
+  return rasqal_rowsource_reset(con->right);
+}
+
+
+static int
+rasqal_union_rowsource_set_preserve(rasqal_rowsource* rowsource,
+                                    void *user_data, int preserve)
+{
+  rasqal_union_rowsource_context* con;
+  int rc;
+  
+  con = (rasqal_union_rowsource_context*)user_data;
+
+  con->state = 0;
+  con->failed = 0;
+
+  rc = rasqal_rowsource_set_preserve(con->left, preserve);
+  if(rc)
+    return rc;
+
+  return rasqal_rowsource_set_preserve(con->right, preserve);
+}
+
+
+static rasqal_rowsource*
+rasqal_union_rowsource_get_inner_rowsource(rasqal_rowsource* rowsource,
+                                           void *user_data, int offset)
+{
+  rasqal_union_rowsource_context *con;
+  con = (rasqal_union_rowsource_context*)user_data;
+
+  if(offset == 1)
+    return con->left;
+  else if(offset == 2)
+    return con->right;
+  else
+    return NULL;
+}
+
+
+static const rasqal_rowsource_handler rasqal_union_rowsource_handler = {
+  /* .version = */ 1,
+  "union",
+  /* .init = */ rasqal_union_rowsource_init,
+  /* .finish = */ rasqal_union_rowsource_finish,
+  /* .ensure_variables = */ rasqal_union_rowsource_ensure_variables,
+  /* .read_row = */ rasqal_union_rowsource_read_row,
+  /* .read_all_rows = */ rasqal_union_rowsource_read_all_rows,
+  /* .reset = */ rasqal_union_rowsource_reset,
+  /* .set_preserve = */ rasqal_union_rowsource_set_preserve,
+  /* .get_inner_rowsource = */ rasqal_union_rowsource_get_inner_rowsource
+};
+
+
+/**
+ * rasqal_new_union_rowsource:
+ * @world: world object
+ * @query: query object
+ * @left: left (first) rowsource
+ * @right: right (second) rowsource
+ *
+ * INTERNAL - create a new UNION over two rowsources
+ *
+ * This uses the number of variables in @vt to set the rowsource size
+ * (order size is always 0) and then checks that all the rows in the
+ * sequence are the same.  If not, construction fails and NULL is
+ * returned.
+ *
+ * Return value: new rowsource or NULL on failure
+ */
+rasqal_rowsource*
+rasqal_new_union_rowsource(rasqal_world *world,
+                           rasqal_query* query,
+                           rasqal_rowsource* left,
+                           rasqal_rowsource* right)
+{
+  rasqal_union_rowsource_context* con;
+  int flags = 0;
+
+  if(!world || !query || !left || !right)
+    return NULL;
+  
+  con = (rasqal_union_rowsource_context*)RASQAL_CALLOC(rasqal_union_rowsource_context, 1, sizeof(rasqal_union_rowsource_context));
+  if(!con)
+    return NULL;
+
+  con->left = left;
+  con->right = right;
+  
+  return rasqal_new_rowsource_from_handler(world, query,
+                                           con,
+                                           &rasqal_union_rowsource_handler,
+                                           query->vars_table,
+                                           flags);
+}
+
+
+#endif
+
+
+
+#ifdef STANDALONE
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+
+const char* const union_1_data_2x3_rows[] =
+{
+  /* 2 variable names and 3 rows */
+  "a",   NULL, "b",   NULL,
+  /* row 1 data */
+  "foo", NULL, "bar", NULL,
+  /* row 2 data */
+  "baz", NULL, "fez", NULL,
+  /* row 3 data */
+  "bob", NULL, "sue", NULL,
+  /* end of data */
+  NULL, NULL
+};
+  
+
+const char* const union_2_data_3x4_rows[] =
+{
+  /* 3 variable names and 4 rows */
+  "b",     NULL, "c",      NULL, "d",      NULL,
+  /* row 1 data */
+  "red",   NULL, "orange", NULL, "yellow", NULL,
+  /* row 2 data */
+  "blue",  NULL, "indigo", NULL, "violet", NULL,
+  /* row 3 data */
+  "black", NULL, "silver", NULL, "gold",   NULL,
+  /* row 4 data */
+  "green", NULL, "tope",   NULL, "bronze", NULL,
+  /* end of data */
+  NULL, NULL
+};
+
+
+#define EXPECTED_ROWS_COUNT (3 + 4)
+
+/* there is one duplicate variable 'b' */
+#define EXPECTED_COLUMNS_COUNT (2 + 3 - 1)
+const char* const union_result_vars[] = { "a" , "b" , "c", "d" };
+
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program = rasqal_basename(argv[0]);
+  rasqal_rowsource *rowsource = NULL;
+  rasqal_rowsource *left_rs = NULL;
+  rasqal_rowsource *right_rs = NULL;
+  rasqal_world* world = NULL;
+  rasqal_query* query = NULL;
+  int count;
+  raptor_sequence* seq = NULL;
+  int failures = 0;
+  int vars_count;
+  rasqal_variables_table* vt;
+  int size;
+  int expected_count = EXPECTED_ROWS_COUNT;
+  int expected_size = EXPECTED_COLUMNS_COUNT;
+  int i;
+  raptor_sequence* vars_seq = NULL;
+  
+  world = rasqal_new_world(); rasqal_world_open(world);
+  
+  query = rasqal_new_query(world, "sparql", NULL);
+  
+  vt = query->vars_table;
+
+  /* 2 variables and 3 rows */
+  vars_count = 2;
+  seq = rasqal_new_row_sequence(world, vt, union_1_data_2x3_rows, vars_count,
+                                &vars_seq);
+  if(!seq) {
+    fprintf(stderr,
+            "%s: failed to create left sequence of %d vars\n", program,
+            vars_count);
+    failures++;
+    goto tidy;
+  }
+
+  left_rs = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq);
+  if(!left_rs) {
+    fprintf(stderr, "%s: failed to create left rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+  /* vars_seq and seq are now owned by left_rs */
+  vars_seq = seq = NULL;
+  
+  /* 3 variables and 4 rows */
+  vars_count = 3;
+  seq = rasqal_new_row_sequence(world, vt, union_2_data_3x4_rows, vars_count,
+                                &vars_seq);
+  if(!seq) {
+    fprintf(stderr,
+            "%s: failed to create right sequence of %d rows\n", program,
+            vars_count);
+    failures++;
+    goto tidy;
+  }
+
+  right_rs = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq);
+  if(!right_rs) {
+    fprintf(stderr, "%s: failed to create right rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+  /* vars_seq and seq are now owned by right_rs */
+  vars_seq = seq = NULL;
+
+  rowsource = rasqal_new_union_rowsource(world, query, left_rs, right_rs);
+  if(!rowsource) {
+    fprintf(stderr, "%s: failed to create union rowsource\n", program);
+    failures++;
+    goto tidy;
+  }
+  /* left_rs and right_rs are now owned by rowsource */
+  left_rs = right_rs = NULL;
+
+  seq = rasqal_rowsource_read_all_rows(rowsource);
+  if(!seq) {
+    fprintf(stderr,
+            "%s: read_rows returned a NULL seq for a union rowsource\n",
+            program);
+    failures++;
+    goto tidy;
+  }
+  count = raptor_sequence_size(seq);
+  if(count != expected_count) {
+    fprintf(stderr,
+            "%s: read_rows returned %d rows for a union rowsource, expected %d\n",
+            program, count, expected_count);
+    failures++;
+    goto tidy;
+  }
+  
+  size = rasqal_rowsource_get_size(rowsource);
+  if(size != expected_size) {
+    fprintf(stderr,
+            "%s: read_rows returned %d columns (variables) for a union rowsource, expected %d\n",
+            program, size, expected_size);
+    failures++;
+    goto tidy;
+  }
+  for(i = 0; i < expected_size; i++) {
+    rasqal_variable* v;
+    const char* name = NULL;
+    const char *expected_name = union_result_vars[i];
+    
+    v = rasqal_rowsource_get_variable_by_offset(rowsource, i);
+    if(!v) {
+      fprintf(stderr,
+            "%s: read_rows had NULL column (variable) #%d expected %s\n",
+              program, i, expected_name);
+      failures++;
+      goto tidy;
+    }
+    name = (const char*)v->name;
+    if(strcmp(name, expected_name)) {
+      fprintf(stderr,
+            "%s: read_rows returned column (variable) #%d %s but expected %s\n",
+              program, i, name, expected_name);
+      failures++;
+      goto tidy;
+    }
+  }
+  
+#ifdef RASQAL_DEBUG
+  rasqal_rowsource_print_row_sequence(rowsource, seq, DEBUG_FH);
+#endif
+
+  tidy:
+  if(seq)
+    raptor_free_sequence(seq);
+  if(left_rs)
+    rasqal_free_rowsource(left_rs);
+  if(right_rs)
+    rasqal_free_rowsource(right_rs);
+  if(rowsource)
+    rasqal_free_rowsource(rowsource);
+  if(query)
+    rasqal_free_query(query);
+  if(world)
+    rasqal_free_world(world);
+
+  return failures;
+}
+
+#endif
diff --git a/src/rasqal/rasqal_skiplist.c b/src/rasqal/rasqal_skiplist.c
new file mode 100644
index 0000000..a261ca2
--- /dev/null
+++ b/src/rasqal/rasqal_skiplist.c
@@ -0,0 +1,604 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_skiplist.c - Skip list
+ *
+ * Copyright (C) 2005-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2005-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#ifndef HAVE_SRANDOMDEV
+/* for time() as a random seed */
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#endif
+
+/* Rasqal includes */
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+typedef struct rasqal_skiplist_node_s rasqal_skiplist_node;
+
+struct rasqal_skiplist_s {
+  /* list header */
+  rasqal_skiplist_node* head;
+
+  /* current level of list */
+  int level;
+
+  /* number of entries in list */
+  int size;
+
+  /* flags from bitor of enum rasqal_skiplist_flags values */
+  int flags;
+
+  /* random bits management for choosing level */
+  unsigned int random_bits;
+  unsigned int random_bits_left;
+
+  /* item comparison function returning for A<B: <0, A=B: 0, A>B: >0 */
+  rasqal_compare_fn* compare_fn;
+
+  /* item free item (key, value pair) function */
+  rasqal_kv_free_fn* free_fn;
+
+  /* print (key,value) functions */
+  raptor_sequence_print_handler* print_key_fn;
+  raptor_sequence_print_handler* print_value_fn;
+};
+
+
+/* levels range from (0 .. RASQAL_SKIPLIST_MAX_LEVEL) */
+#define RASQAL_SKIPLIST_MAX_LEVEL 15
+
+#define RASQAL_SKIPLIST_NIL NULL
+
+#define BITS_IN_RANDOM 31
+
+
+struct rasqal_skiplist_node_s {
+  void* key;
+  void* value;
+  /* skip list forward array.
+   * Note: This MUST remain at the end of the struct as it is variable size 
+   */
+  struct rasqal_skiplist_node_s* forward[1];
+};
+
+
+static int rasqal_skiplist_get_random_level(rasqal_skiplist *list);
+static void rasqal_skiplist_node_print(rasqal_skiplist* list, rasqal_skiplist_node* node, FILE *fh);
+
+
+#ifndef STANDALONE_NOTYET
+
+
+void
+rasqal_skiplist_init_with_seed(unsigned long seed) 
+{
+  srandom(seed);
+}
+
+
+void
+rasqal_skiplist_init(void)
+{
+#ifdef HAVE_SRANDOMDEV
+  srandomdev();
+#else
+  srandom((unsigned long)time(NULL));
+#endif
+}
+
+
+void
+rasqal_skiplist_finish(void)
+{
+  /* NOP */
+}
+
+
+/**
+ * rasqal_new_skiplist:
+ * @compare_fn: function to compare two keys
+ * @free_fn: function to delete a (key, value) item pair (or NULL)
+ * @print_key_fn: function to print a key function
+ * @print_value_fn: function to print a key function
+ * @flags: set to RASQAL_SKIPLIST_FLAG_DUPLICATES to allow duplicates
+ *
+ * Constructor - Create a new Rasqal skiplist.
+ *
+ * Return value: a new #rasqal_skiplist or NULL on failure.
+ */
+rasqal_skiplist*
+rasqal_new_skiplist(rasqal_compare_fn* compare_fn,
+                    rasqal_kv_free_fn* free_fn,
+                    raptor_sequence_print_handler* print_key_fn,
+                    raptor_sequence_print_handler* print_value_fn,
+                    int flags)
+{
+  int i;
+  rasqal_skiplist* list;
+  
+  list=(rasqal_skiplist*)RASQAL_CALLOC(rasqal_skiplist, 1, sizeof(rasqal_skiplist));
+  if(!list)
+    return NULL;
+  
+  list->compare_fn=compare_fn;
+  list->print_key_fn=print_key_fn;
+  list->print_value_fn=print_value_fn;
+  
+  list->head=(rasqal_skiplist_node*)RASQAL_MALLOC(rasqal_skiplist_node,
+                                                  sizeof(rasqal_skiplist_node) + RASQAL_SKIPLIST_MAX_LEVEL*sizeof(rasqal_skiplist_node* ));
+  if(!list->head) {
+    RASQAL_FREE(rasqal_skiplist, list);
+    return NULL;
+  }
+
+  for(i = 0; i <= RASQAL_SKIPLIST_MAX_LEVEL; i++)
+    list->head->forward[i] = RASQAL_SKIPLIST_NIL;
+  list->level = 0;
+
+  list->size = 0;
+
+  list->random_bits=random();
+  list->random_bits_left= BITS_IN_RANDOM;
+
+  list->flags=flags;
+
+  return list;
+}
+
+
+static void
+rasqal_free_skiplist_node(rasqal_skiplist* list, rasqal_skiplist_node* node)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(list, rasqal_skiplist);
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(node, rasqal_skiplist_node);
+
+  if(list->free_fn)
+    list->free_fn(node->key, node->value);
+  RASQAL_FREE(rasqal_skiplist_node, node);
+}
+
+
+/**
+ * rasqal_free_skiplist - Destructor - Destroy a Rasqal skiplist object
+ * @list: #rasqal_skiplist object
+ *
+ */
+void
+rasqal_free_skiplist(rasqal_skiplist* list)
+{
+  rasqal_skiplist_node* node;
+
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(list, rasqal_skiplist);
+
+  node=list->head;
+  for(node = node->forward[0]; node != RASQAL_SKIPLIST_NIL; ) {
+    rasqal_skiplist_node* next = node->forward[0];
+    rasqal_free_skiplist_node(list, node);
+    node=next;
+  }
+
+  if(list->head) 
+    rasqal_free_skiplist_node(list, list->head);
+
+  RASQAL_FREE(rasqal_skiplist, list);
+}
+
+
+static int
+rasqal_skiplist_get_random_level(rasqal_skiplist *list)
+{
+  int level = 0;
+  int b;
+  do {
+    b = list->random_bits & 3;
+    if(!b) 
+      level++;
+    list->random_bits>>=2;
+    if(!--list->random_bits_left) {
+      list->random_bits = random();
+      list->random_bits_left = BITS_IN_RANDOM >>1;
+    };
+  } while (!b);
+
+  return (level > RASQAL_SKIPLIST_MAX_LEVEL ? RASQAL_SKIPLIST_MAX_LEVEL : level);
+};
+
+
+/**
+ * rasqal_skiplist_insert - Add a (key, value) pair to a skiplist
+ * @list: #rasqal_skiplist object
+ * @key: pointer to key
+ * @value: pointer to value
+ * 
+ * If duplicates are not allowed, adding a duplicate (key, value)
+ * pair will fail.
+ *
+ * Return value: non-0 on failure
+ */
+int
+rasqal_skiplist_insert(rasqal_skiplist* list, 
+                       void* key, void* value)
+{
+  int i;
+  int new_level;
+  rasqal_skiplist_node* update[RASQAL_SKIPLIST_MAX_LEVEL+1];
+  rasqal_skiplist_node* node;
+  
+  node=list->head;
+  for(i = list->level; i>=0; i--) {
+    while(node->forward[i] != RASQAL_SKIPLIST_NIL &&
+          list->compare_fn(node->forward[i]->key, key) < 0)
+      node=node->forward[i];
+    update[i] = node;
+  }
+  node=node->forward[0];
+
+  if(!(list->flags & RASQAL_SKIPLIST_FLAG_DUPLICATES)) {
+    if(node != RASQAL_SKIPLIST_NIL && !list->compare_fn(node->key, key)) 
+      /* found duplicate key and they are not allowed */
+      return 1;
+  }
+  
+  new_level = rasqal_skiplist_get_random_level(list);
+  
+  if(new_level > list->level) {
+    for(i = list->level + 1; i <= new_level; i++)
+      update[i] = list->head;
+    list->level = new_level;
+  }
+  
+  node=(rasqal_skiplist_node*)RASQAL_MALLOC(rasqal_skiplist_node, 
+                                            sizeof(rasqal_skiplist_node) + 
+                                            new_level * sizeof(rasqal_skiplist_node*));
+  if(!node)
+    return 1;
+  node->key = key;
+  node->value = value;
+  
+  for(i = 0; i <= new_level; i++) {
+    node->forward[i] = update[i]->forward[i];
+    update[i]->forward[i] = node;
+  }
+
+  list->size++;
+
+  return 0;
+}
+
+
+/**
+ * rasqal_skiplist_delete - Delete a (key, value) pair from a skiplist
+ * @list: #rasqal_skiplist object
+ * @key: pointer to key
+ * @value: pointer to value
+ * 
+ * Return value: non-0 on failure
+ */
+int
+rasqal_skiplist_delete(rasqal_skiplist* list, void* key)
+{
+  int i;
+  rasqal_skiplist_node* update[RASQAL_SKIPLIST_MAX_LEVEL+1];
+  rasqal_skiplist_node* node;
+
+  node=list->head;
+  for(i = list->level; i>=0; i--) {
+    while(node->forward[i] != RASQAL_SKIPLIST_NIL &&
+          list->compare_fn(node->forward[i]->key, key) < 0)
+      node=node->forward[i];
+    update[i] = node;
+  }
+  node=node->forward[0];
+
+  if(node == RASQAL_SKIPLIST_NIL || list->compare_fn(node->key, key))
+    /* failed to find key */
+    return 1;
+  
+  for(i = 0; i <= list->level; i++) {
+    if(update[i]->forward[i] != node) 
+      break;
+    update[i]->forward[i] = node->forward[i];
+  }
+  
+  rasqal_free_skiplist_node(list, node);
+  
+  while((list->level > 0) && 
+        (list->head->forward[list->level] == RASQAL_SKIPLIST_NIL))
+    list->level--;
+  
+  list->size--;
+
+  return 0;
+}
+
+
+/**
+ * rasqal_skiplist_find - Find a value in a skiplist for a given key
+ * @list: #rasqal_skiplist object
+ * @key: pointer to key
+ * 
+ * Return value: value pointer or NULL if not found
+ */
+void*
+rasqal_skiplist_find(rasqal_skiplist* list, void* key)
+{
+  int i;
+  rasqal_skiplist_node* node=list->head;
+  
+  for(i = list->level; i>=0; i--) {
+    while(node->forward[i] != RASQAL_SKIPLIST_NIL &&
+          list->compare_fn(node->forward[i]->key, key) < 0)
+      node=node->forward[i];
+  }
+
+  node=node->forward[0];
+  if(node != RASQAL_SKIPLIST_NIL && !list->compare_fn(node->key, key)) {
+    return node->value;
+  }
+
+  /* failed to find key */
+  return NULL;
+}
+
+
+static void
+rasqal_skiplist_node_print(rasqal_skiplist* list,
+                           rasqal_skiplist_node* node, FILE *fh)
+{
+  fputs("{", fh);
+  if(!node->key)
+    fputs("NULL", fh);
+  else if(list->print_key_fn)
+    list->print_key_fn(node->key, fh);
+  else
+    fprintf(fh, "key %p", node->key);
+
+  fputs(" : ", fh);
+
+  if(!node->value)
+    fputs("NULL", fh);
+  else if(list->print_value_fn)
+    list->print_value_fn(node->value, fh);
+  else
+    fprintf(fh, "data %p", node->value);
+
+  fputs("}", fh);
+}
+
+
+/**
+ * rasqal_skiplist_print - Print a Rasqal skiplist in a debug format
+ * @list: the #rasqal_skiplist object
+ * @fh: the #FILE* handle to print to
+ * 
+ * The print debug format may change in any release.
+ * 
+ */
+void
+rasqal_skiplist_print(rasqal_skiplist* list, FILE* fh)
+{
+  rasqal_skiplist_node* node;
+  int first=1;
+  
+  fprintf(fh, "skiplist(size=%d, duplicates=%s) [[ ", list->size,
+          (list->flags & RASQAL_SKIPLIST_FLAG_DUPLICATES) ? "yes" : "no");
+  node=list->head;
+  for(node = node->forward[0]; node != RASQAL_SKIPLIST_NIL; ) {
+    if(!first)
+      fputs(", ", fh);
+    rasqal_skiplist_node_print(list, node, fh);
+    first=0;
+    node=node->forward[0];
+  }
+  
+  fputs(" ]]", fh);
+}
+
+
+void
+rasqal_skiplist_dump(rasqal_skiplist* list, FILE *fh)
+{
+  rasqal_skiplist_node* node;
+  int i;
+  int first=1;
+  
+  fprintf(fh, "skiplist(size=%d, duplicates=%s) [[ ", list->size,
+          (list->flags & RASQAL_SKIPLIST_FLAG_DUPLICATES) ? "yes" : "no");
+  node=list->head;
+  for(i = list->level; i>=0; i--) {
+    int count=0;
+    while(node->forward[i] != RASQAL_SKIPLIST_NIL) {
+      count++;
+      node=node->forward[i];
+    }
+    if(!first)
+      fputs(", ", fh);
+    fprintf(fh, "L%d: %d node%s", i, count, ((count == 1) ? "" : "s"));
+    first=0;
+  }
+  fputs(" ]]", fh);
+}
+
+
+/**
+ * rasqal_skiplist_get_size - Get the number of items in a skiplist
+ * @list: #rasqal_skiplist object
+ * 
+ * Return value: the number of items in the skiplist (0 or more)
+ */
+unsigned int
+rasqal_skiplist_get_size(rasqal_skiplist* list)
+{
+  return list->size;
+}
+
+
+#endif
+
+
+
+#ifdef STANDALONE
+
+static int
+rasqal_skiplist_int_compare(const void *a, const void *b)
+{
+  int* int_a=(int*)a;
+  int* int_b=(int*)b;
+  
+  return *int_a - *int_b;
+}
+
+static void
+rasqal_skiplist_int_print(void *int_p, FILE *fh)
+{
+  fprintf(fh,"%d", *(int*)int_p);
+}
+
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+#define DEFAULT_TEST_SIZE 100
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program=rasqal_basename(argv[0]);
+  int size;
+  int* keys;
+  int* values;
+  rasqal_skiplist* list;
+  int i;
+  int result_size;
+
+  rasqal_skiplist_init_with_seed(1234567890);
+    
+  if(argc < 1 || argc > 2) {
+    fprintf(stderr, "%s: USAGE: %s [<size>]\n", program, program);
+    exit(1);
+  }
+  
+  if(argc == 2)
+    size = atoi(argv[1]);
+  else
+    size = DEFAULT_TEST_SIZE;
+  
+  list=rasqal_new_skiplist(rasqal_skiplist_int_compare,
+                           NULL,
+                           rasqal_skiplist_int_print,
+                           rasqal_skiplist_int_print,
+                           0);
+  if(!list) {
+    fprintf(stderr, "%s: Creating new skiplist failed\n", program);
+    exit(1);
+  }
+  
+  keys = (int*)RASQAL_CALLOC(intarray, size, sizeof(int));
+  values = (int*)RASQAL_CALLOC(intarray, size, sizeof(int));
+  if(!keys || !values) {
+    fprintf(stderr, "%s: Out of memory\n", program);
+    exit(1);
+  }
+  
+  for(i = 0; i < size; i++) {
+    keys[i]   = random();
+    values[i] = i;
+  }
+  fprintf(stdout, "%s: Testing with %d random-keyed items\n", program, size);
+  
+  for(i = 0; i < size; i++) {
+    if(rasqal_skiplist_insert(list, &keys[i], &values[i])) {
+      fprintf(stderr, "%s: insert failed for %d:%d ", program,
+              keys[i], values[i]);
+      fputs("\n", stderr);
+    }
+  }
+
+  if(rasqal_skiplist_get_size(list) != size) {
+    fprintf(stderr, "%s: skiplist has %d items, expected %d\n", program,
+            rasqal_skiplist_get_size(list), size);
+    exit(1);
+  }
+  
+  for(i=0; i < size; i++) {
+    int* result=(int*)rasqal_skiplist_find(list, &keys[i]);
+    if(!result) {
+      fprintf(stderr, "%s: find failed to find key %d\n",
+              program, keys[i]);
+      exit(1);
+    }
+  }
+  
+  result_size=size;
+  for(i=0; i < size; i++) {
+    if(rasqal_skiplist_delete(list, &keys[i])) {
+      fprintf(stderr, "%s: delete failed with key '%d'\n",
+              program, keys[i]);
+      exit(1);
+    }
+
+    result_size--;
+    
+    if(rasqal_skiplist_get_size(list) != result_size) {
+      fprintf(stderr, "%s: after deleting, skiplist has %d items, expected %d\n", 
+              program, rasqal_skiplist_get_size(list), result_size);
+      exit(1);
+    }
+  }
+
+  rasqal_free_skiplist(list);
+
+  RASQAL_FREE(intarray, values);
+  RASQAL_FREE(intarray, keys);
+
+  rasqal_skiplist_finish();
+  
+  /* keep gcc -Wall happy */
+  return 0;
+}
+
+#endif
diff --git a/src/rasqal/rasqal_sparql_xml.c b/src/rasqal/rasqal_sparql_xml.c
new file mode 100644
index 0000000..0b050c6
--- /dev/null
+++ b/src/rasqal/rasqal_sparql_xml.c
@@ -0,0 +1,1067 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_sparql_xml.c - SPARQL Results XML Format
+ *
+ * Copyright (C) 2007-2008, David Beckett http://www.dajobe.org/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+
+#include <raptor.h>
+
+/* Rasqal includes */
+#include <rasqal.h>
+#include <rasqal_internal.h>
+
+
+static int rasqal_query_results_write_sparql_xml(raptor_iostream *iostr, rasqal_query_results* results, raptor_uri *base_uri);
+static rasqal_rowsource* rasqal_query_results_get_rowsource_sparql_xml(rasqal_world *world, rasqal_variables_table* vars_table, raptor_iostream *iostr, raptor_uri *base_uri);
+
+
+#if RASQAL_DEBUG > 1
+#define TRACE_XML 1
+#else
+#undef TRACE_XML
+#endif
+
+
+#ifndef FILE_READ_BUF_SIZE
+#ifdef BUFSIZ
+#define FILE_READ_BUF_SIZE BUFSIZ
+#else
+#define FILE_READ_BUF_SIZE 1024
+#endif
+#endif
+
+
+
+/*
+ * rasqal_query_results_write_sparql_xml:
+ * @iostr: #raptor_iostream to write the query results to
+ * @results: #rasqal_query_results query results input
+ * @base_uri: #raptor_uri base URI of the output format
+ *
+ * Write the fourth version of the SPARQL XML query results format to an
+ * iostream in a format - INTERNAL.
+ * 
+ * If the writing succeeds, the query results will be exhausted.
+ * 
+ * Return value: non-0 on failure
+ **/
+static int
+rasqal_query_results_write_sparql_xml(raptor_iostream *iostr,
+                                      rasqal_query_results* results,
+                                      raptor_uri *base_uri)
+{
+  int rc=1;
+  rasqal_query* query = rasqal_query_results_get_query(results);
+#ifndef RAPTOR_V2_AVAILABLE
+  const raptor_uri_handler *uri_handler;
+  void *uri_context;
+#endif
+  raptor_xml_writer* xml_writer=NULL;
+  raptor_namespace *res_ns=NULL;
+  raptor_namespace_stack *nstack=NULL;
+  raptor_xml_element *sparql_element=NULL;
+  raptor_xml_element *results_element=NULL;
+  raptor_xml_element *result_element=NULL;
+  raptor_xml_element *element1=NULL;
+  raptor_xml_element *binding_element=NULL;
+  raptor_xml_element *variable_element=NULL;
+  raptor_qname **attrs=NULL;
+  int i;
+
+  if(!rasqal_query_results_is_bindings(results) &&
+     !rasqal_query_results_is_boolean(results)) {
+    rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                            &query->locator,
+                            "Can only write XML format v3 for variable binding and boolean results");
+    return 1;
+  }
+  
+
+#ifdef RAPTOR_V2_AVAILABLE  
+  nstack = raptor_new_namespaces_v2(query->world->raptor_world_ptr,
+                                    (raptor_simple_message_handler)rasqal_query_simple_error, query,
+                                    1);
+
+#else
+  raptor_uri_get_handler(&uri_handler, &uri_context);
+  nstack = raptor_new_namespaces(uri_handler, uri_context,
+                                 (raptor_simple_message_handler)rasqal_query_simple_error, query,
+                                 1);
+#endif
+  if(!nstack)
+    return 1;
+
+#ifdef RAPTOR_V2_AVAILABLE
+  xml_writer = raptor_new_xml_writer_v2(query->world->raptor_world_ptr,
+                                        nstack,
+                                        iostr,
+                                        (raptor_simple_message_handler)rasqal_query_simple_error, query,
+                                        1);
+#else
+  xml_writer = raptor_new_xml_writer(nstack,
+                                     uri_handler, uri_context,
+                                     iostr,
+                                     (raptor_simple_message_handler)rasqal_query_simple_error, query,
+                                     1);
+#endif
+  if(!xml_writer)
+    goto tidy;
+
+  res_ns=raptor_new_namespace(nstack,
+                              NULL,
+                              (const unsigned char*)"http://www.w3.org/2005/sparql-results#";,
+                              0);
+  if(!res_ns)
+    goto tidy;
+
+  sparql_element=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                  (const unsigned char*)"sparql",
+                                                                  NULL, base_uri);
+  if(!sparql_element)
+    goto tidy;
+
+  if(rasqal_query_results_is_bindings(results)) {
+    /* FIXME - consider when to write the XSD.  Need the XSD URI too. */
+#if 0
+    raptor_namespace* xsi_ns;
+    xsi_ns=raptor_new_namespace(nstack,
+                                (const unsigned char*)"xsi",
+                                (const unsigned char*)"http://www.w3.org/2001/XMLSchema-instance";,
+                                0);
+    raptor_xml_element_declare_namespace(sparql_element, xsi_ns);
+    
+    attrs=(raptor_qname **)raptor_alloc_memory(sizeof(raptor_qname*));
+    attrs[0]=raptor_new_qname_from_namespace_local_name(xsi_ns,
+                                                        (const unsigned char*)"schemaLocation",  
+                                                        (const unsigned char*)"http://www.w3.org/2001/sw/DataAccess/rf1/result2.xsd";);
+    raptor_xml_element_set_attributes(sparql_element, attrs, 1);
+#endif
+  }
+  
+  raptor_xml_writer_start_element(xml_writer, sparql_element);
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+
+  /*   <head> */
+  element1=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                            (const unsigned char*)"head",
+                                                            NULL, base_uri);
+  if(!element1)
+    goto tidy;
+
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"  ", 2);
+  raptor_xml_writer_start_element(xml_writer, element1);
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+  
+  if(rasqal_query_results_is_bindings(results)) {
+    for(i=0; 1; i++) {
+      const unsigned char *name;
+      name=rasqal_query_results_get_binding_name(results, i);
+      if(!name)
+        break;
+      
+      /*     <variable name="x"/> */
+      variable_element=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                        (const unsigned char*)"variable",
+                                                                        NULL, base_uri);
+      if(!variable_element)
+        goto tidy;
+      
+      attrs=(raptor_qname **)raptor_alloc_memory(sizeof(raptor_qname*));
+      if(!attrs)
+        goto tidy;
+#ifdef RAPTOR_V2_AVAILABLE
+      attrs[0] = raptor_new_qname_from_namespace_local_name_v2(query->world->raptor_world_ptr,
+                                                               res_ns, 
+                                                               (const unsigned char*)"name",
+                                                               (const unsigned char*)name); /* attribute value */
+#else
+      attrs[0] = raptor_new_qname_from_namespace_local_name(res_ns, 
+                                                            (const unsigned char*)"name",
+                                                            (const unsigned char*)name); /* attribute value */
+#endif
+      if(!attrs[0]) {
+        raptor_free_memory((void*)attrs);
+        goto tidy;
+      }
+
+      raptor_xml_element_set_attributes(variable_element, attrs, 1);
+      
+      raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"    ", 4);
+      raptor_xml_writer_empty_element(xml_writer, variable_element);
+      raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+      
+      raptor_free_xml_element(variable_element);
+      variable_element=NULL;
+    }
+  }
+
+  /* FIXME - could add <link> inside <head> */
+
+    
+  /*   </head> */
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"  ", 2);
+  raptor_xml_writer_end_element(xml_writer, element1);
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+  
+  raptor_free_xml_element(element1);
+  element1=NULL;
+
+
+  /* Boolean Results */
+  if(rasqal_query_results_is_boolean(results)) {
+    result_element=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                    (const unsigned char*)"boolean",
+                                                                    NULL, base_uri);
+    if(!result_element)
+      goto tidy;
+
+    raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"  ", 2);
+    raptor_xml_writer_start_element(xml_writer, result_element);
+    if(rasqal_query_results_get_boolean(results))
+      raptor_xml_writer_raw(xml_writer, RASQAL_XSD_BOOLEAN_TRUE);
+    else
+      raptor_xml_writer_raw(xml_writer, RASQAL_XSD_BOOLEAN_FALSE);
+    raptor_xml_writer_end_element(xml_writer, result_element);
+    raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+
+    goto results3done;
+  }
+
+
+  /* Variable Binding Results */
+
+  /*   <results> */
+  results_element=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                   (const unsigned char*)"results",
+                                                                   NULL, base_uri);
+  if(!results_element)
+    goto tidy;
+
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"  ", 2);
+  raptor_xml_writer_start_element(xml_writer, results_element);
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+
+
+  /* declare result element for later multiple use */
+  result_element=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                  (const unsigned char*)"result",
+                                                                  NULL, base_uri);
+  if(!result_element)
+    goto tidy;
+
+  while(!rasqal_query_results_finished(results)) {
+    /*     <result> */
+    raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"    ", 4);
+    raptor_xml_writer_start_element(xml_writer, result_element);
+    raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+
+    for(i=0; i<rasqal_query_results_get_bindings_count(results); i++) {
+      const unsigned char *name=rasqal_query_results_get_binding_name(results, i);
+      rasqal_literal *l=rasqal_query_results_get_binding_value(results, i);
+
+      /*       <binding> */
+      binding_element=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                       (const unsigned char*)"binding",
+                                                                       NULL, base_uri);
+      if(!binding_element)
+        goto tidy;
+
+      attrs=(raptor_qname **)raptor_alloc_memory(sizeof(raptor_qname*));
+      if(!attrs)
+        goto tidy;
+#ifdef RAPTOR_V2_AVAILABLE
+      attrs[0] = raptor_new_qname_from_namespace_local_name_v2(query->world->raptor_world_ptr,
+                                                               res_ns, 
+                                                               (const unsigned char*)"name",
+                                                               name);
+
+#else
+      attrs[0] = raptor_new_qname_from_namespace_local_name(res_ns, 
+                                                            (const unsigned char*)"name",
+                                                            name);
+#endif
+      if(!attrs[0]) {
+        raptor_free_memory((void*)attrs);
+        goto tidy;
+      }
+
+      raptor_xml_element_set_attributes(binding_element, attrs, 1);
+      
+
+      raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"      ", 6);
+      raptor_xml_writer_start_element(xml_writer, binding_element);
+
+      if(!l) {
+        element1=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                  (const unsigned char*)"unbound",
+                                                                  NULL, base_uri);
+        if(!element1)
+          goto tidy;
+        raptor_xml_writer_empty_element(xml_writer, element1);
+
+      } else switch(l->type) {
+        case RASQAL_LITERAL_URI:
+          element1=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                    (const unsigned char*)"uri",
+                                                                    NULL, base_uri);
+          if(!element1)
+            goto tidy;
+          
+          raptor_xml_writer_start_element(xml_writer, element1);
+#ifdef RAPTOR_V2_AVAILABLE
+          raptor_xml_writer_cdata(xml_writer, (const unsigned char*)raptor_uri_as_string_v2(query->world->raptor_world_ptr, l->value.uri));
+#else
+          raptor_xml_writer_cdata(xml_writer, (const unsigned char*)raptor_uri_as_string(l->value.uri));
+#endif
+          raptor_xml_writer_end_element(xml_writer, element1);
+
+          break;
+
+        case RASQAL_LITERAL_BLANK:
+          element1=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                    (const unsigned char*)"bnode",
+                                                                    NULL, base_uri);
+          if(!element1)
+            goto tidy;
+          
+          raptor_xml_writer_start_element(xml_writer, element1);
+          raptor_xml_writer_cdata(xml_writer, (const unsigned char*)l->string);
+          raptor_xml_writer_end_element(xml_writer, element1);
+          break;
+
+        case RASQAL_LITERAL_STRING:
+          element1=raptor_new_xml_element_from_namespace_local_name(res_ns,
+                                                                    (const unsigned char*)"literal",
+                                                                    NULL, base_uri);
+          if(!element1)
+            goto tidy;
+
+          if(l->language || l->datatype) {
+            attrs=(raptor_qname **)raptor_alloc_memory(sizeof(raptor_qname*));
+            if(!attrs)
+              goto tidy;
+
+            if(l->language)
+              attrs[0]=raptor_new_qname(nstack,
+                                        (const unsigned char*)"xml:lang",
+                                        (const unsigned char*)l->language,
+                                        (raptor_simple_message_handler)rasqal_query_simple_error, query);
+            else
+#ifdef RAPTOR_V2_AVAILABLE
+              attrs[0] = raptor_new_qname_from_namespace_local_name_v2(query->world->raptor_world_ptr,
+                                                                       res_ns, 
+                                                                       (const unsigned char*)"datatype",
+                                                                       (const unsigned char*)raptor_uri_as_string_v2(query->world->raptor_world_ptr,
+                                                                                                                     l->datatype));
+#else
+              attrs[0] = raptor_new_qname_from_namespace_local_name(res_ns, 
+                                                                    (const unsigned char*)"datatype",
+                                                                    (const unsigned char*)raptor_uri_as_string(l->datatype));
+#endif
+            if(!attrs[0]) {
+              raptor_free_memory((void*)attrs);
+              goto tidy;
+            }
+
+            raptor_xml_element_set_attributes(element1, attrs, 1);
+          }
+
+
+          raptor_xml_writer_start_element(xml_writer, element1);
+
+
+          raptor_xml_writer_cdata_counted(xml_writer,
+                                          (const unsigned char*)l->string, 
+                                          l->string_len);
+
+          raptor_xml_writer_end_element(xml_writer, element1);
+          
+          break;
+        case RASQAL_LITERAL_PATTERN:
+        case RASQAL_LITERAL_QNAME:
+        case RASQAL_LITERAL_INTEGER:
+        case RASQAL_LITERAL_BOOLEAN:
+        case RASQAL_LITERAL_DOUBLE:
+        case RASQAL_LITERAL_FLOAT:
+        case RASQAL_LITERAL_VARIABLE:
+        case RASQAL_LITERAL_DECIMAL:
+        case RASQAL_LITERAL_DATETIME:
+
+        case RASQAL_LITERAL_UNKNOWN:
+        default:
+          rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                                  &query->locator,
+                                  "Cannot turn literal type %d into XML", 
+                                  l->type);
+          goto tidy;
+        }
+
+      if(element1) {
+        raptor_free_xml_element(element1);
+        element1=NULL;
+      }
+
+      /*       </binding> */
+      raptor_xml_writer_end_element(xml_writer, binding_element);
+      raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+      
+      raptor_free_xml_element(binding_element);
+      binding_element=NULL;
+    }
+
+    raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"    ", 4);
+    raptor_xml_writer_end_element(xml_writer, result_element);
+    raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+    
+    rasqal_query_results_next(results);
+  }
+
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"  ", 2);
+  raptor_xml_writer_end_element(xml_writer, results_element);
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+
+  results3done:
+
+  rc=0;
+
+  raptor_xml_writer_end_element(xml_writer, sparql_element);
+  raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
+
+  tidy:
+  if(element1)
+    raptor_free_xml_element(element1);
+  if(variable_element)
+    raptor_free_xml_element(variable_element);
+  if(binding_element)
+    raptor_free_xml_element(binding_element);
+  if(result_element)
+    raptor_free_xml_element(result_element);
+  if(results_element)
+    raptor_free_xml_element(results_element);
+  if(sparql_element)
+    raptor_free_xml_element(sparql_element);
+  if(res_ns)
+    raptor_free_namespace(res_ns);
+  if(xml_writer)
+    raptor_free_xml_writer(xml_writer);
+  if(nstack)
+    raptor_free_namespaces(nstack);
+
+  return rc;
+}
+
+
+const char* const sparql_xml_element_names[]=
+{
+  "!",
+  /* In rough order they appear */
+  "sparql",
+  "head",
+  "binding",
+  "variable",
+  "results",
+  "result",
+  "bnode",
+  "literal",
+  "uri",
+  NULL
+};
+  
+
+typedef enum
+{
+  STATE_unknown,
+  /* In same order as above */
+  STATE_sparql,
+  STATE_head,
+  STATE_binding,
+  STATE_variable,
+  STATE_results,
+  STATE_result,
+  STATE_bnode,
+  STATE_literal,
+  STATE_uri,
+  STATE_first = STATE_sparql,
+  STATE_last = STATE_uri
+} rasqal_sparql_xml_read_state;
+  
+
+typedef struct 
+{
+  rasqal_world* world;
+  rasqal_rowsource* rowsource;
+  
+  int failed;
+#ifdef TRACE_XML
+  int trace;
+#endif
+
+  /* Input fields */
+  raptor_uri* base_uri;
+  raptor_iostream* iostr;
+
+  /* SAX2 fields */
+  raptor_sax2* sax2;
+  raptor_locator locator;
+  int depth; /* element depth */
+  raptor_error_handlers error_handlers; /* SAX2 error handler */
+
+  /* SPARQL XML Results parsing */
+  rasqal_sparql_xml_read_state state; /* state */
+  /* state-based fields for turning XML into rasqal literals, rows */
+  const char* name;  /* variable name (from binding/@name) */
+  size_t name_length;
+  char* value; /* URI string, literal string or blank node ID */
+  size_t value_len;
+  const char* datatype; /* literal datatype URI string from literal/@datatype */
+  const char* language; /* literal language from literal/@xml:lang */
+  rasqal_row* row; /* current result row */
+  int offset; /* current result row number */
+  int result_offset; /* current <result> column number */
+  unsigned char buffer[FILE_READ_BUF_SIZE]; /* iostream read buffer */
+
+  /* Output fields */
+  raptor_sequence* results_sequence; /* saved result rows */
+
+  /* Variables table allocated for variables in the result set */
+  rasqal_variables_table* vars_table;
+  int variables_count;
+} rasqal_rowsource_sparql_xml_context;
+  
+
+#ifdef TRACE_XML
+static void
+pad(FILE* fh, int depth)
+{
+  int i;
+  for(i=0; i< depth; i++)
+    fputs("  ", fh);
+}
+#endif
+
+static void
+rasqal_sparql_xml_sax2_start_element_handler(void *user_data,
+                                             raptor_xml_element *xml_element)
+{
+  rasqal_rowsource_sparql_xml_context* con;
+  int i;
+  raptor_qname* name;
+  rasqal_sparql_xml_read_state state=STATE_unknown;
+  int attr_count;
+
+  con=(rasqal_rowsource_sparql_xml_context*)user_data;
+
+  name=raptor_xml_element_get_name(xml_element);
+
+  for(i=STATE_first; i <= STATE_last; i++) {
+    if(!strcmp((const char*)raptor_qname_get_local_name(name),
+               sparql_xml_element_names[i])) {
+      state=(rasqal_sparql_xml_read_state)i;
+      con->state=state;
+    }
+  }
+
+  if(state == STATE_unknown) {
+    fprintf(stderr, "UNKNOWN element %s\n", raptor_qname_get_local_name(name));
+    con->failed++;
+  }
+
+#ifdef TRACE_XML
+  if(con->trace) {
+    pad(stderr, con->depth);
+    fprintf(stderr, "Element %s (%d)\n", raptor_qname_get_local_name(name),
+            state);
+  }
+#endif
+  
+  attr_count=raptor_xml_element_get_attributes_count(xml_element);
+  con->name=NULL;
+  con->datatype=NULL;
+  con->language=NULL;
+  
+  if(attr_count > 0) {
+    raptor_qname** attrs=raptor_xml_element_get_attributes(xml_element);
+    for(i=0; i < attr_count; i++) {
+#ifdef TRACE_XML
+      if(con->trace) {
+        pad(stderr, con->depth+1);
+        fprintf(stderr, "Attribute %s='%s'\n",
+                raptor_qname_get_local_name(attrs[i]),
+                raptor_qname_get_value(attrs[i]));
+      }
+#endif
+      if(!strcmp((const char*)raptor_qname_get_local_name(attrs[i]),
+                 "name"))
+        con->name=(const char*)raptor_qname_get_counted_value(attrs[i],
+                                                             &con->name_length);
+      else if(!strcmp((const char*)raptor_qname_get_local_name(attrs[i]),
+                      "datatype"))
+        con->datatype=(const char*)raptor_qname_get_value(attrs[i]);
+    }
+  }
+  if(raptor_xml_element_get_language(xml_element)) {
+    con->language=(const char*)raptor_xml_element_get_language(xml_element);
+#ifdef TRACE_XML
+    if(con->trace) {
+      pad(stderr, con->depth+1);
+      fprintf(stderr, "xml:lang '%s'\n", con->language);
+    }
+#endif
+  }
+
+  switch(state) {
+    case STATE_variable:
+      if(1) {
+        unsigned char* var_name;
+        rasqal_variable *v;
+        
+        var_name = (unsigned char*)RASQAL_MALLOC(cstring, con->name_length+1);
+        strncpy((char*)var_name, con->name, con->name_length+1);
+
+        v = rasqal_variables_table_add(con->vars_table,
+                                       RASQAL_VARIABLE_TYPE_NORMAL,
+                                       var_name, NULL);
+        if(v)
+          rasqal_rowsource_add_variable(con->rowsource, v);
+      }
+      break;
+      
+    case STATE_result:
+      if(1) {
+        con->row=rasqal_new_row(con->rowsource);
+        RASQAL_DEBUG2("Made new row %d\n", con->offset);
+        con->offset++;
+      }
+      break;
+      
+    case STATE_binding:
+      con->result_offset = rasqal_rowsource_get_variable_offset_by_name(con->rowsource, (const unsigned char*)con->name);
+      break;
+      
+    case STATE_sparql:
+    case STATE_head:
+    case STATE_results:
+    case STATE_literal:
+    case STATE_bnode:
+    case STATE_uri:
+    case STATE_unknown:
+    default:
+      break;
+  }
+  
+  con->depth++;
+}
+
+
+static void
+rasqal_sparql_xml_sax2_characters_handler(void *user_data,
+                                          raptor_xml_element* xml_element,
+                                          const unsigned char *s, int len)
+{
+  rasqal_rowsource_sparql_xml_context* con;
+  con=(rasqal_rowsource_sparql_xml_context*)user_data;
+
+#ifdef TRACE_XML
+  if(con->trace) {
+    pad(stderr, con->depth);
+    fputs("Text '", stderr);
+    fwrite(s, sizeof(char), len, stderr);
+    fprintf(stderr, "' (%d bytes)\n", len);
+  }
+#endif
+
+  if(con->state == STATE_literal ||
+     con->state == STATE_uri ||
+     con->state == STATE_bnode) {
+    con->value_len=len;
+    con->value=(char*)RASQAL_MALLOC(cstring, len+1);
+    memcpy(con->value, s, len);
+    con->value[len]='\0';
+  }
+}
+
+
+static void
+rasqal_sparql_xml_sax2_end_element_handler(void *user_data,
+                                           raptor_xml_element* xml_element)
+{
+  rasqal_rowsource_sparql_xml_context* con;
+  raptor_qname* name;
+  int i;
+  rasqal_sparql_xml_read_state state=STATE_unknown;
+  
+  con=(rasqal_rowsource_sparql_xml_context*)user_data;
+
+  name=raptor_xml_element_get_name(xml_element);
+
+  for(i=STATE_first; i <= STATE_last; i++) {
+    if(!strcmp((const char*)raptor_qname_get_local_name(name),
+               sparql_xml_element_names[i])) {
+      state=(rasqal_sparql_xml_read_state)i;
+      con->state=state;
+    }
+  }
+
+  if(state == STATE_unknown) {
+    fprintf(stderr, "UNKNOWN element %s\n", raptor_qname_get_local_name(name));
+    con->failed++;
+  }
+
+  con->depth--;
+#ifdef TRACE_XML
+  if(con->trace) {
+    pad(stderr, con->depth);
+    fprintf(stderr, "End Element %s (%d)\n", raptor_qname_get_local_name(name),
+            con->state);
+  }
+#endif
+
+  switch(con->state) {
+    case STATE_head:
+      /* Only now is the full number of variables known */
+      con->variables_count = rasqal_variables_table_get_named_variables_count(con->vars_table);
+      con->rowsource->size = con->variables_count;
+      break;
+      
+    case STATE_literal:
+      if(1) {
+        rasqal_literal* l;
+        unsigned char* lvalue;
+        raptor_uri* datatype_uri=NULL;
+        char* language_str=NULL;
+
+        lvalue=(unsigned char*)RASQAL_MALLOC(cstring, con->value_len+1);
+        strncpy((char*)lvalue, con->value, con->value_len+1);
+        if(con->datatype)
+#ifdef RAPTOR_V2_AVAILABLE
+          datatype_uri = raptor_new_uri_v2(con->world->raptor_world_ptr, (const unsigned char*)con->datatype);
+#else
+          datatype_uri = raptor_new_uri((const unsigned char*)con->datatype);
+#endif
+        if(con->language) {
+          language_str=(char*)RASQAL_MALLOC(cstring, strlen(con->language)+1);
+          strcpy(language_str, con->language);
+        }
+        l=rasqal_new_string_literal_node(con->world, lvalue, language_str, datatype_uri);
+        rasqal_row_set_value_at(con->row, con->result_offset, l);
+        RASQAL_DEBUG3("Saving row result %d string value at offset %d\n",
+                      con->offset, con->result_offset);
+      }
+      break;
+      
+    case STATE_bnode:
+      if(1) {
+        rasqal_literal* l;
+        unsigned char* lvalue;
+        lvalue=(unsigned char*)RASQAL_MALLOC(cstring, con->value_len+1);
+        strncpy((char*)lvalue, con->value, con->value_len+1);
+        l=rasqal_new_simple_literal(con->world, RASQAL_LITERAL_BLANK, lvalue);
+        rasqal_row_set_value_at(con->row, con->result_offset, l);
+        RASQAL_DEBUG3("Saving row result %d bnode value at offset %d\n",
+                      con->offset, con->result_offset);
+      }
+      break;
+      
+    case STATE_uri:
+      if(1) {
+        raptor_uri* uri;
+        rasqal_literal* l;
+#ifdef RAPTOR_V2_AVAILABLE
+        uri = raptor_new_uri_v2(con->world->raptor_world_ptr, (const unsigned char*)con->value);
+#else
+        uri = raptor_new_uri((const unsigned char*)con->value);
+#endif
+        l = rasqal_new_uri_literal(con->world, uri);
+        rasqal_row_set_value_at(con->row, con->result_offset, l);
+        RASQAL_DEBUG3("Saving row result %d uri value at offset %d\n",
+                      con->offset, con->result_offset);
+      }
+      break;
+      
+    case STATE_result:
+      if(con->row) {
+        RASQAL_DEBUG2("Saving row result %d\n", con->offset);
+        raptor_sequence_push(con->results_sequence, con->row);
+      }
+      con->row=NULL;
+      break;
+
+    case STATE_unknown:
+    case STATE_sparql:
+    case STATE_variable:
+    case STATE_results:
+    case STATE_binding:
+    default:
+      break;
+  }
+
+  if(con->value) {
+    RASQAL_FREE(cstring, con->value);
+    con->value=NULL;
+  }
+}
+
+
+/* Local handlers for turning sparql XML read from an iostream into rows */
+
+static int
+rasqal_rowsource_sparql_xml_init(rasqal_rowsource* rowsource, void *user_data) 
+{
+  rasqal_rowsource_sparql_xml_context* con;
+
+  con=(rasqal_rowsource_sparql_xml_context*)user_data;
+
+  con->rowsource=rowsource;
+  con->state=STATE_unknown;
+
+#ifdef TRACE_XML
+  con->trace=1;
+#endif
+  con->depth=0;
+
+  raptor_sax2_parse_start(con->sax2, con->base_uri);
+
+  return 0;
+}
+
+static int
+rasqal_rowsource_sparql_xml_finish(rasqal_rowsource* rowsource, void *user_data)
+{
+  rasqal_rowsource_sparql_xml_context* con;
+
+  con=(rasqal_rowsource_sparql_xml_context*)user_data;
+
+  if(con->base_uri)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(con->world->raptor_world_ptr, con->base_uri);
+#else
+    raptor_free_uri(con->base_uri);
+#endif
+
+  if(con->sax2)
+    raptor_free_sax2(con->sax2);
+
+  if(con->results_sequence)
+    raptor_free_sequence(con->results_sequence);
+
+  if(con->vars_table)
+    rasqal_free_variables_table(con->vars_table);
+
+  RASQAL_FREE(rasqal_rowsource_sparql_xml_context, con);
+
+  return 0;
+}
+
+
+static void
+rasqal_rowsource_sparql_xml_process(rasqal_rowsource_sparql_xml_context* con)
+{
+  if(raptor_sequence_size(con->results_sequence) && con->variables_count > 0)
+    return;
+
+  /* do some parsing - need some results */
+  while(!raptor_iostream_read_eof(con->iostr)) {
+    size_t read_len;
+    
+    read_len=raptor_iostream_read_bytes(con->iostr, (char*)con->buffer,
+                                        1, FILE_READ_BUF_SIZE);
+    if(read_len > 0) {
+      RASQAL_DEBUG2("processing %d bytes\n", (int)read_len);
+      raptor_sax2_parse_chunk(con->sax2, con->buffer, read_len, 0);
+      con->locator.byte += read_len;
+    }
+    
+    if(read_len < FILE_READ_BUF_SIZE) {
+      /* finished */
+      raptor_sax2_parse_chunk(con->sax2, NULL, 0, 1);
+      break;
+    }
+    
+    /* end with variables sequence done AND at least one row */
+    if(con->variables_count > 0 &&
+       raptor_sequence_size(con->results_sequence) > 0)
+      break;
+  }
+  
+}
+
+
+static int
+rasqal_rowsource_sparql_xml_ensure_variables(rasqal_rowsource* rowsource,
+                                             void *user_data)
+{
+  rasqal_rowsource_sparql_xml_context* con;
+
+  con = (rasqal_rowsource_sparql_xml_context*)user_data;
+
+  rasqal_rowsource_sparql_xml_process(con);
+
+  return con->failed;
+}
+
+
+static rasqal_row*
+rasqal_rowsource_sparql_xml_read_row(rasqal_rowsource* rowsource,
+                                     void *user_data)
+{
+  rasqal_rowsource_sparql_xml_context* con;
+  rasqal_row* row=NULL;
+
+  con=(rasqal_rowsource_sparql_xml_context*)user_data;
+
+  rasqal_rowsource_sparql_xml_process(con);
+  
+  if(!con->failed && raptor_sequence_size(con->results_sequence) > 0) {
+    RASQAL_DEBUG1("getting row from stored sequence\n");
+    row=(rasqal_row*)raptor_sequence_unshift(con->results_sequence);
+  }
+
+  return row;
+}
+
+
+static const rasqal_rowsource_handler rasqal_rowsource_sparql_xml_handler={
+  /* .version = */ 1,
+  "SPARQL XML",
+  /* .init = */ rasqal_rowsource_sparql_xml_init,
+  /* .finish = */ rasqal_rowsource_sparql_xml_finish,
+  /* .ensure_variables = */ rasqal_rowsource_sparql_xml_ensure_variables,
+  /* .read_row = */ rasqal_rowsource_sparql_xml_read_row,
+  /* .read_all_rows = */ NULL,
+  /* .get_query = */ NULL
+};
+
+
+
+/*
+ * rasqal_query_results_getrowsource_sparql_xml:
+ * @world: rasqal world object
+ * @iostr: #raptor_iostream to read the query results from
+ * @base_uri: #raptor_uri base URI of the input format
+ *
+ * Read the fourth version of the SPARQL XML query results format from an
+ * iostream in a format returning a rwosurce - INTERNAL.
+ * 
+ * Return value: a new rasqal_rowsource or NULL on failure
+ **/
+static rasqal_rowsource*
+rasqal_query_results_get_rowsource_sparql_xml(rasqal_world *world,
+                                              rasqal_variables_table* vars_table,
+                                              raptor_iostream *iostr,
+                                              raptor_uri *base_uri)
+{
+  rasqal_rowsource_sparql_xml_context* con;
+  
+  con=(rasqal_rowsource_sparql_xml_context*)RASQAL_CALLOC(rasqal_rowsource_sparql_xml_context, 1, sizeof(rasqal_rowsource_sparql_xml_context));
+  if(!con)
+    return NULL;
+
+  con->world=world;
+#ifdef RAPTOR_V2_AVAILABLE
+  con->base_uri = base_uri ? raptor_uri_copy_v2(world->raptor_world_ptr, base_uri) : NULL;
+#else
+  con->base_uri = base_uri ? raptor_uri_copy(base_uri) : NULL;
+#endif
+  con->iostr=iostr;
+
+  con->locator.uri=base_uri;
+
+  con->error_handlers.locator=&con->locator;
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_error_handlers_init_v2(world->raptor_world_ptr, &con->error_handlers);
+#else
+  raptor_error_handlers_init(&con->error_handlers);
+#endif
+  
+  con->sax2=raptor_new_sax2(con, &con->error_handlers);
+  if(!con->sax2)
+    return NULL;
+  
+  raptor_sax2_set_start_element_handler(con->sax2,
+                                        rasqal_sparql_xml_sax2_start_element_handler);
+  raptor_sax2_set_characters_handler(con->sax2,
+                                     rasqal_sparql_xml_sax2_characters_handler);
+  raptor_sax2_set_characters_handler(con->sax2,
+                                     (raptor_sax2_characters_handler)rasqal_sparql_xml_sax2_characters_handler);
+
+  raptor_sax2_set_end_element_handler(con->sax2,
+                                      rasqal_sparql_xml_sax2_end_element_handler);
+
+  con->results_sequence=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_row, (raptor_sequence_print_handler*)rasqal_row_print);
+
+  con->vars_table = rasqal_new_variables_table_from_variables_table(vars_table);
+  
+  return rasqal_new_rowsource_from_handler(world, NULL,
+                                           con,
+                                           &rasqal_rowsource_sparql_xml_handler,
+                                           con->vars_table,
+                                           0);
+}
+
+
+
+int
+rasqal_init_result_format_sparql_xml(rasqal_world* world)
+{
+  rasqal_query_results_formatter_func writer_fn=NULL;
+  rasqal_query_results_formatter_func reader_fn=NULL;
+  rasqal_query_results_get_rowsource_func get_rowsource_fn=NULL;
+  int rc=0;
+
+  /*
+   * SPARQL XML Results 2007-06-14
+   * http://www.w3.org/TR/2006/WD-rdf-sparql-XMLres-20070614/
+   */
+  writer_fn=&rasqal_query_results_write_sparql_xml;
+  reader_fn=NULL,
+  get_rowsource_fn=&rasqal_query_results_get_rowsource_sparql_xml;
+  rc+= rasqal_query_results_format_register_factory(world,
+                                                    "xml",
+                                                    "SPARQL Query Results Format 2007-06-14",
+                                                    (unsigned char*)"http://www.w3.org/2005/sparql-results#";,
+                                                    writer_fn, reader_fn, get_rowsource_fn,
+                                                    "application/sparql-results+xml")
+                                                    != 0;
+  rc+= rasqal_query_results_format_register_factory(world,
+                                                    NULL,
+                                                    NULL,
+                                                    (unsigned char*)"http://www.w3.org/TR/2006/WD-rdf-sparql-XMLres-20070614/";,
+                                                    writer_fn, reader_fn, get_rowsource_fn,
+                                                    "application/sparql-results+xml")
+                                                    != 0;
+  return rc;
+}
+
diff --git a/src/rasqal/rasqal_triples_source.c b/src/rasqal/rasqal_triples_source.c
new file mode 100644
index 0000000..02750c2
--- /dev/null
+++ b/src/rasqal/rasqal_triples_source.c
@@ -0,0 +1,236 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_triples_source.c - Rasqal triples source matching TP against triples
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+/**
+ * rasqal_set_triples_source_factory:
+ * @world: rasqal_world object
+ * @register_fn: registration function
+ * @user_data: user data for registration
+ *
+ * Register the factory to return triple sources.
+ * 
+ * Registers the factory that returns triples sources.  Note that
+ * there is only one of these per runtime. 
+ *
+ * The rasqal_triples_source_factory factory method new_triples_source is
+ * called with the user data for some query and rasqal_triples_source.
+ *
+ **/
+RASQAL_EXTERN_C
+void
+rasqal_set_triples_source_factory(rasqal_world* world, void (*register_fn)(rasqal_triples_source_factory *factory), void* user_data)
+{
+  world->triples_source_factory.user_data=user_data;
+  register_fn(&world->triples_source_factory);
+}
+
+
+/**
+ * rasqal_new_triples_source:
+ * @query: query
+ *
+ * INTERNAL - Create a new triples source
+ *
+ * Return value: a new triples source or NULL on failure
+ */
+rasqal_triples_source*
+rasqal_new_triples_source(rasqal_query* query)
+{
+  rasqal_triples_source_factory* rtsf = &query->world->triples_source_factory;
+  rasqal_triples_source* rts;
+  int rc=0;
+  
+  rts = (rasqal_triples_source*)RASQAL_CALLOC(rasqal_triples_source, 1,
+                                              sizeof(rasqal_triples_source));
+  if(!rts)
+    return NULL;
+
+  rts->user_data = RASQAL_CALLOC(user_data, 1, rtsf->user_data_size);
+  if(!rts->user_data) {
+    RASQAL_FREE(rasqal_triples_source, rts);
+    return NULL;
+  }
+  rts->query = query;
+
+  rc = rtsf->new_triples_source(query, rtsf->user_data, rts->user_data, rts);
+  if(rc) {
+    if(rc > 0) {
+      rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                              &query->locator,
+                              "Failed to make triples source.");
+    } else {
+      rasqal_log_error_simple(query->world, RAPTOR_LOG_LEVEL_ERROR,
+                              &query->locator,
+                              "No data to query.");
+    }
+    RASQAL_FREE(user_data, rts->user_data);
+    RASQAL_FREE(rasqal_triples_source, rts);
+    return NULL;
+  }
+  
+  return rts;
+}
+
+
+void
+rasqal_free_triples_source(rasqal_triples_source *rts)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(rts, rasqal_triples_source);
+  
+  if(rts->user_data) {
+    rts->free_triples_source(rts->user_data);
+    RASQAL_FREE(user_data, rts->user_data);
+    rts->user_data=NULL;
+  }
+  
+  RASQAL_FREE(rasqal_triples_source, rts);
+}
+
+
+int
+rasqal_triples_source_triple_present(rasqal_triples_source *rts,
+                                     rasqal_triple *t)
+{
+  return rts->triple_present(rts, rts->user_data, t);
+}
+
+
+static void
+rasqal_free_triples_match(rasqal_triples_match* rtm)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(rtm, rasqal_triples_match);
+  
+  rtm->finish(rtm, rtm->user_data);
+  RASQAL_FREE(rasqal_triples_match, rtm);
+}
+
+
+rasqal_triples_match*
+rasqal_new_triples_match(rasqal_query* query,
+                         rasqal_triples_source* triples_source,
+                         rasqal_triple_meta *m, rasqal_triple *t)
+{
+  rasqal_triples_match* rtm;
+
+  if(!triples_source)
+    return NULL;
+
+  rtm = (rasqal_triples_match *)RASQAL_CALLOC(rasqal_triples_match, 1,
+                                              sizeof(rasqal_triples_match));
+  if(rtm) {
+    rtm->world = query->world;
+    if(triples_source->init_triples_match(rtm, triples_source,
+                                          triples_source->user_data,
+                                          m, t)) {
+      rasqal_free_triples_match(rtm);
+      rtm = NULL;
+    }
+  }
+
+  return rtm;
+}
+
+
+/* methods */
+int
+rasqal_triples_match_bind_match(struct rasqal_triples_match_s* rtm, 
+                                rasqal_variable *bindings[4],
+                                rasqal_triple_parts parts)
+{
+  return rtm->bind_match(rtm, rtm->user_data, bindings, parts);
+}
+
+
+void
+rasqal_triples_match_next_match(struct rasqal_triples_match_s* rtm)
+{
+  rtm->next_match(rtm, rtm->user_data);
+}
+
+
+int
+rasqal_triples_match_is_end(struct rasqal_triples_match_s* rtm)
+{
+  return rtm->is_end(rtm, rtm->user_data);
+}
+
+
+/**
+ * rasqal_reset_triple_meta:
+ * @m: Triple pattern metadata
+ * 
+ * INTERNAL - reset the metadata associated with a triple pattern
+ * 
+ * Return value: number of parts of the triple that were reset (0..4)
+ **/
+int
+rasqal_reset_triple_meta(rasqal_triple_meta* m)
+{
+  int resets=0;
+  
+  if(m->triples_match) {
+    rasqal_free_triples_match(m->triples_match);
+    m->triples_match=NULL;
+  }
+
+  if(m->bindings[0] && (m->parts & RASQAL_TRIPLE_SUBJECT)) {
+    rasqal_variable_set_value(m->bindings[0],  NULL);
+    resets++;
+  }
+  if(m->bindings[1] && (m->parts & RASQAL_TRIPLE_PREDICATE)) {
+    rasqal_variable_set_value(m->bindings[1],  NULL);
+    resets++;
+  }
+  if(m->bindings[2] && (m->parts & RASQAL_TRIPLE_OBJECT)) {
+    rasqal_variable_set_value(m->bindings[2],  NULL);
+    resets++;
+  }
+  if(m->bindings[3] && (m->parts & RASQAL_TRIPLE_ORIGIN)) {
+    rasqal_variable_set_value(m->bindings[3],  NULL);
+    resets++;
+  }
+
+  m->executed=0;
+  
+  return resets;
+}
diff --git a/src/rasqal/rasqal_variable.c b/src/rasqal/rasqal_variable.c
new file mode 100644
index 0000000..7b1e5f7
--- /dev/null
+++ b/src/rasqal/rasqal_variable.c
@@ -0,0 +1,688 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rasqal_variable.c - Rasqal variable support
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#ifdef RASQAL_REGEX_PCRE
+#include <pcre.h>
+#endif
+
+#ifdef RASQAL_REGEX_POSIX
+#include <sys/types.h>
+#include <regex.h>
+#endif
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+
+#ifndef STANDALONE
+
+
+/**
+ * rasqal_new_variable_typed:
+ * @rq: #rasqal_query to associate the variable with
+ * @type: variable type defined by enumeration rasqal_variable_type
+ * @name: variable name
+ * @value: variable #rasqal_literal value (or NULL)
+ *
+ * Constructor - Create a new typed Rasqal variable.
+ * 
+ * The variable must be associated with a query, since variable
+ * names are only significant with a single query.
+ * 
+ * The @name and @value become owned by the rasqal_variable structure
+ *
+ * Return value: a new #rasqal_variable or NULL on failure.
+ **/
+rasqal_variable*
+rasqal_new_variable_typed(rasqal_query* rq,
+                          rasqal_variable_type type, 
+                          unsigned char *name, rasqal_literal *value)
+{
+  return rasqal_variables_table_add(rq->vars_table, type, name, value);
+}
+
+
+/**
+ * rasqal_new_variable:
+ * @rq: #rasqal_query to associate the variable with
+ * @name: variable name
+ * @value: variable #rasqal_literal value (or NULL)
+ *
+ * Constructor - Create a new Rasqal normal variable.
+ * 
+ * The variable must be associated with a query, since variable
+ * names are only significant with a single query.
+ *
+ * This creates a regular variable that can be returned of type
+ * RASQAL_VARIABLE_TYPE_NORMAL.  Use rasqal_new_variable_typed
+ * to create other variables.
+ * 
+ * The @name and @value become owned by the rasqal_variable structure
+ *
+ * Return value: a new #rasqal_variable or NULL on failure.
+ **/
+rasqal_variable*
+rasqal_new_variable(rasqal_query* rq,
+                    unsigned char *name, rasqal_literal *value) 
+{
+  return rasqal_variables_table_add(rq->vars_table, RASQAL_VARIABLE_TYPE_NORMAL,
+                                    name, value);
+}
+
+
+/**
+ * rasqal_new_variable_from_variable:
+ * @v: #rasqal_variable to copy
+ *
+ * Copy Constructor - Create a new Rasqal variable from an existing one
+ *
+ * This does a deep copy of all variable fields
+ *
+ * Return value: a new #rasqal_variable or NULL on failure.
+ **/
+rasqal_variable*
+rasqal_new_variable_from_variable(rasqal_variable* v)
+{
+  rasqal_variable* new_v;
+  size_t name_len;
+  unsigned char *new_name;
+
+  new_v = (rasqal_variable*)RASQAL_CALLOC(rasqal_variable, 1,
+                                          sizeof(rasqal_variable));
+  if(!new_v)
+    return NULL;
+  
+  name_len = strlen((const char*)v->name);
+  new_name = (unsigned char*)RASQAL_MALLOC(cstring, name_len+1);
+  if(!new_name) {
+    RASQAL_FREE(rasqal_variable, new_v);
+    return NULL;
+  }
+  memcpy(new_name, v->name, name_len+1);
+  
+  new_v->name= new_name;
+  new_v->value= rasqal_new_literal_from_literal(v->value);
+  new_v->offset= v->offset;
+  new_v->type= v->type;
+  new_v->expression= rasqal_new_expression_from_expression(v->expression);
+
+  return new_v;
+}
+
+/**
+ * rasqal_free_variable:
+ * @v: #rasqal_variable object
+ *
+ * Destructor - Destroy a Rasqal variable object.
+ *
+ **/
+void
+rasqal_free_variable(rasqal_variable* v)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(v, rasqal_variable);
+  
+  if(v->name)
+    RASQAL_FREE(cstring, (void*)v->name);
+  if(v->value)
+    rasqal_free_literal(v->value);
+  if(v->expression)
+    rasqal_free_expression(v->expression);
+  RASQAL_FREE(rasqal_variable, v);
+}
+
+
+/**
+ * rasqal_variable_write:
+ * @v: the #rasqal_variable object
+ * @iostr: the #raptor_iostream handle to write to
+ *
+ * Write a Rasqal variable to an iostream in a debug format.
+ * 
+ * The write debug format may change in any release.
+ * 
+ **/
+void
+rasqal_variable_write(rasqal_variable* v, raptor_iostream* iostr)
+{
+  if(v->type == RASQAL_VARIABLE_TYPE_ANONYMOUS)
+    raptor_iostream_write_counted_string(iostr, "anon-variable(", 14);
+  else
+    raptor_iostream_write_counted_string(iostr, "variable(", 9);
+  raptor_iostream_write_string(iostr, v->name);
+  if(v->expression) {
+    raptor_iostream_write_byte(iostr, '=');
+    rasqal_expression_write(v->expression, iostr);
+  }
+  if(v->value) {
+    raptor_iostream_write_byte(iostr, '=');
+    rasqal_literal_write(v->value, iostr);
+  }
+  raptor_iostream_write_byte(iostr, ')');
+}
+
+
+/**
+ * rasqal_variable_print:
+ * @v: the #rasqal_variable object
+ * @fh: the #FILE* handle to print to
+ *
+ * Print a Rasqal variable in a debug format.
+ * 
+ * The print debug format may change in any release.
+ * 
+ **/
+void
+rasqal_variable_print(rasqal_variable* v, FILE* fh)
+{
+  if(v->type == RASQAL_VARIABLE_TYPE_ANONYMOUS)
+    fprintf(fh, "anon-variable(%s", v->name);
+  else
+    fprintf(fh, "variable(%s", v->name);
+  if(v->expression) {
+    fputc('=', fh);
+    rasqal_expression_print(v->expression, fh);
+  }
+  if(v->value) {
+    fputc('=', fh);
+    rasqal_literal_print(v->value, fh);
+  }
+  fputc(')', fh);
+}
+
+
+/**
+ * rasqal_variable_set_value:
+ * @v: the #rasqal_variable object
+ * @l: the #rasqal_literal value to set (or NULL)
+ *
+ * Set the value of a Rasqal variable.
+ * 
+ * The variable value is an input parameter and is copied in, not shared.
+ * If the variable value is NULL, any existing value is deleted.
+ * 
+ **/
+void
+rasqal_variable_set_value(rasqal_variable* v, rasqal_literal* l)
+{
+  if(v->value)
+    rasqal_free_literal(v->value);
+  v->value = l;
+
+#ifdef RASQAL_DEBUG
+  if(!v->name)
+    RASQAL_FATAL1("variable has no name");
+  RASQAL_DEBUG2("setting variable %s to value ", v->name);
+  if(v->value)
+    rasqal_literal_print(v->value, stderr);
+  else
+    fputs("(NULL)", stderr);
+  fputc('\n', stderr);
+#endif
+}
+
+
+
+/*
+ * A table of variables with optional binding values
+ *
+ * variables are named or anonymous (cannot be selected).
+ */
+struct rasqal_variables_table_s {
+  rasqal_world* world;
+
+  /* usage/reference count */
+  int usage;
+  
+  /* The variables of size @variables_count + @anon_variables_count
+   * shared pointers into @variables_sequence and @anon_variables_sequence
+   */
+  rasqal_variable** variables;
+
+  /* Named variables (owner) */
+  raptor_sequence* variables_sequence;
+  int variables_count;
+
+  /* Anonymous variables (owner) */
+  raptor_sequence* anon_variables_sequence;
+  int anon_variables_count;
+
+  /* array of variable names.  The array is allocated here but the
+   * pointers are into the #variables_sequence above.  It is only
+   * allocated if rasqal_variables_table_get_names() is called
+   * on demand, otherwise is NULL.
+   */
+  const unsigned char** variable_names;
+};
+
+
+
+rasqal_variables_table*
+rasqal_new_variables_table(rasqal_world* world)
+{
+  rasqal_variables_table* vt;
+  
+  vt = (rasqal_variables_table*)RASQAL_CALLOC(rasqal_variables_table, 1,
+                                              sizeof(rasqal_variables_table));
+  if(!vt)
+    return NULL;
+
+  vt->usage = 1;
+  vt->world = world;
+  
+  vt->variables_sequence = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_variable, (raptor_sequence_print_handler*)rasqal_variable_print);
+  if(!vt->variables_sequence)
+    goto tidy;
+
+  vt->anon_variables_sequence = raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_variable, (raptor_sequence_print_handler*)rasqal_variable_print);
+  if(!vt->anon_variables_sequence)
+    goto tidy;
+
+  vt->variable_names = NULL;
+
+  return vt;
+
+  tidy:
+  rasqal_free_variables_table(vt);
+  vt = NULL;
+  
+  return vt;
+}
+
+
+rasqal_variables_table*
+rasqal_new_variables_table_from_variables_table(rasqal_variables_table* vt)
+{
+  vt->usage++;
+  return vt;
+}
+
+
+void
+rasqal_free_variables_table(rasqal_variables_table* vt)
+{
+  RASQAL_ASSERT_OBJECT_POINTER_RETURN(vt, rasqal_variables_table);
+
+  if(--vt->usage)
+    return;
+  
+  if(vt->variables)
+    RASQAL_FREE(vararray, vt->variables);
+
+  if(vt->anon_variables_sequence)
+    raptor_free_sequence(vt->anon_variables_sequence);
+
+  if(vt->variables_sequence)
+    raptor_free_sequence(vt->variables_sequence);
+
+  if(vt->variable_names)
+    RASQAL_FREE(cstrings, vt->variable_names);
+
+  RASQAL_FREE(rasqal_variables_table, vt);
+}
+
+
+/**
+ * rasqal_variables_table_add:
+ * @vt: #rasqal_variables_table to associate the variable with
+ * @type: variable type defined by enumeration rasqal_variable_type
+ * @name: variable name
+ * @value: variable #rasqal_literal value (or NULL)
+ *
+ * Constructor - Add a variable to the variables table
+ * 
+ * The @name and @value become owned by the rasqal_variable structure
+ *
+ * Return value: a new #rasqal_variable or NULL on failure.
+ **/
+rasqal_variable*
+rasqal_variables_table_add(rasqal_variables_table* vt,
+                           rasqal_variable_type type, 
+                           const unsigned char *name, rasqal_literal *value)
+{
+  int i;
+  rasqal_variable* v;
+  raptor_sequence* seq = NULL;
+  int* count_p = NULL;
+
+  if(!vt)
+    return NULL;
+  
+  switch(type) {
+    case RASQAL_VARIABLE_TYPE_ANONYMOUS:
+      seq = vt->anon_variables_sequence;
+      count_p = &vt->anon_variables_count;
+      break;
+    case RASQAL_VARIABLE_TYPE_NORMAL:
+      seq = vt->variables_sequence;
+      count_p = &vt->variables_count;
+      break;
+      
+    case RASQAL_VARIABLE_TYPE_UNKNOWN:
+    default:
+      RASQAL_DEBUG2("Unknown variable type %d", type);
+      return NULL;
+  }
+  
+  for(i = 0; i < raptor_sequence_size(seq); i++) {
+    v = (rasqal_variable*)raptor_sequence_get_at(seq, i);
+    if(!strcmp((const char*)v->name, (const char*)name)) {
+      /* name already present, do not need a copy */
+      RASQAL_FREE(cstring, name);
+      return v;
+    }
+  }
+
+  
+  v = (rasqal_variable*)RASQAL_CALLOC(rasqal_variable, 1,
+                                      sizeof(rasqal_variable));
+  if(v) {
+    v->type= type;
+    v->name= name;
+    v->value= value;
+    if(count_p)
+      v->offset= (*count_p);
+
+    if(seq && raptor_sequence_push(seq, v))
+      return NULL;
+
+    if(type == RASQAL_VARIABLE_TYPE_ANONYMOUS) {
+      /* new anon variable: add base offset */
+      v->offset += vt->variables_count;
+    } else {
+      /* new normal variable: move all anon variable offsets up 1 */
+      for(i = 0; i < vt->anon_variables_count; i++) {
+        rasqal_variable* anon_v;
+        anon_v = (rasqal_variable*)raptor_sequence_get_at(vt->anon_variables_sequence, i);
+        anon_v->offset++;
+      }
+    }
+    
+
+    /* Increment count and free var names only after sequence push succeeded */
+    if(count_p)
+      (*count_p)++;
+
+    if(vt->variable_names) {
+      RASQAL_FREE(cstrings, vt->variable_names);
+      vt->variable_names = NULL;
+    }
+  } else {
+    RASQAL_FREE(cstring, name);
+    if(value)
+      rasqal_free_literal(value);
+  }
+  
+  return v;
+}
+
+
+
+rasqal_variable*
+rasqal_variables_table_get(rasqal_variables_table* vt, int idx)
+{
+  raptor_sequence* seq = NULL;
+
+  if(idx < 0)
+    return NULL;
+  
+  if(idx < vt->variables_count)
+    seq = vt->variables_sequence;
+  else {
+    idx -= vt->variables_count;
+    seq = vt->anon_variables_sequence;
+  }
+  
+  return (rasqal_variable*)raptor_sequence_get_at(seq, idx);
+}
+
+
+rasqal_literal*
+rasqal_variables_table_get_value(rasqal_variables_table* vt, int idx)
+{
+  rasqal_variable* v;
+  v = rasqal_variables_table_get(vt, idx);
+  if(!v)
+    return NULL;
+  return v->value;
+}
+
+
+rasqal_variable*
+rasqal_variables_table_get_by_name(rasqal_variables_table* vt,
+                                   const unsigned char *name)
+{
+  int i;
+  rasqal_variable* v;
+
+  for(i = 0; (v = rasqal_variables_table_get(vt, i)); i++) {
+    if(!strcmp((const char*)v->name, (const char*)name))
+      return v;
+  }
+  return NULL;
+}
+
+
+int
+rasqal_variables_table_has(rasqal_variables_table* vt,
+                           const unsigned char *name)
+{
+  return (rasqal_variables_table_get_by_name(vt, name) != NULL);
+}
+
+
+int
+rasqal_variables_table_set(rasqal_variables_table* vt,
+                           const unsigned char *name, rasqal_literal* value)
+{
+  rasqal_variable* v;
+  
+  v = rasqal_variables_table_get_by_name(vt, name);
+  if(!v)
+    return 1;
+
+  rasqal_variable_set_value(v, value);
+  return 0;
+}
+
+
+int
+rasqal_variables_table_get_named_variables_count(rasqal_variables_table* vt)
+{
+  return vt->variables_count;
+}
+
+
+int
+rasqal_variables_table_get_anonymous_variables_count(rasqal_variables_table* vt)
+{
+  return vt->anon_variables_count;
+}
+
+
+int
+rasqal_variables_table_get_total_variables_count(rasqal_variables_table* vt)
+{
+  return vt->variables_count + vt->anon_variables_count;
+}
+
+
+raptor_sequence*
+rasqal_variables_table_get_named_variables_sequence(rasqal_variables_table* vt)
+{
+  return vt->variables_sequence;
+}
+
+
+raptor_sequence*
+rasqal_variables_table_get_anonymous_variables_sequence(rasqal_variables_table* vt)
+{
+  return vt->anon_variables_sequence;
+}
+
+
+const unsigned char**
+rasqal_variables_table_get_names(rasqal_variables_table* vt)
+{
+  int size = vt->variables_count;
+  
+  if(!vt->variable_names && size) {
+    int i;
+    
+    vt->variable_names = (const unsigned char**)RASQAL_CALLOC(cstrings, sizeof(unsigned char*), (size+1));
+    if(!vt->variable_names)
+      return NULL;
+
+    for(i = 0; i < size; i++) {
+      rasqal_variable* v;
+      v = (rasqal_variable*)raptor_sequence_get_at(vt->variables_sequence, i);
+      vt->variable_names[i] = v->name;
+    }
+  }
+
+  return vt->variable_names;
+}
+
+#endif /* not STANDALONE */
+
+
+
+#ifdef STANDALONE
+#include <stdio.h>
+
+int main(int argc, char *argv[]);
+
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program = rasqal_basename(argv[0]);
+  rasqal_world* world = NULL;
+  rasqal_variables_table* vt = NULL;
+#define NUM_VARS 3
+  const char* var_names[NUM_VARS] = {"normal-null", "normal-value", "anon"};
+  unsigned char* names[NUM_VARS];
+  rasqal_variable* vars[NUM_VARS];
+  rasqal_literal *value = NULL;
+  int i;
+  int rc = 0;
+  
+  world = rasqal_new_world();
+  if(!world || rasqal_world_open(world)) {
+    fprintf(stderr, "%s: rasqal_world init failed\n", program);
+    rc = 1;
+    goto tidy;
+  }
+  
+  vt = rasqal_new_variables_table(world);
+  if(!vt) {
+    fprintf(stderr, "%s: Failed to make variables table\n", program);
+    rc = 1;
+    goto tidy;
+  }
+
+  for(i = 0; i < NUM_VARS; i++) {
+    size_t len = strlen(var_names[i]);
+    names[i] = (unsigned char*)malloc(len+1);
+    strncpy((char*)names[i], var_names[i], len+1);
+  }
+  
+  vars[0] = rasqal_variables_table_add(vt, RASQAL_VARIABLE_TYPE_NORMAL,
+                                     names[0], NULL);
+  if(!vars[0]) {
+    fprintf(stderr, "%s: Failed to make normal variable with NULL value\n",
+            program);
+    rc = 1;
+    goto tidy;
+  } else {
+    /* now owned by vars[0] owned by vt */
+    names[0] = NULL;
+  }
+  /* vars[0] now owned by vt */
+
+  value = rasqal_new_double_literal(world, 42.0);
+  if(!value) {
+    fprintf(stderr, "%s: Failed to make double literal\n", program);
+    rc = 1;
+    goto tidy;
+  }
+  vars[1] = rasqal_variables_table_add(vt, RASQAL_VARIABLE_TYPE_NORMAL,
+                                     names[1], value);
+  if(!vars[1]) {
+    fprintf(stderr, "%s: Failed to make normal variable with literal value\n",
+            program);
+    rc = 1;
+    goto tidy;
+  } else {
+    /* now owned by vars[1] owned by vt */
+    names[1] = NULL;
+    value = NULL;
+  }
+  /* vars[1] now owned by vt */
+  
+  vars[2] = rasqal_variables_table_add(vt, RASQAL_VARIABLE_TYPE_ANONYMOUS,
+                                     names[2], NULL);
+  if(!vars[2]) {
+    fprintf(stderr, "%s: Failed to make anonymous variable with NULL value\n",
+            program);
+    rc = 1;
+    goto tidy;
+  } else {
+    /* now owned by vars[2] owned by vt */
+    names[2] = NULL;
+  }
+  /* vars[2] now owned by vt */
+  
+  tidy:
+  for(i = 0; i < NUM_VARS; i++) {
+    if(names[i])
+      free(names[i]);
+  }
+  
+  if(value)
+    rasqal_free_literal(value);
+  if(vt)
+    rasqal_free_variables_table(vt);
+  
+  if(world)
+    rasqal_free_world(world);
+
+  return 0;
+}
+#endif
diff --git a/src/rasqal/rasqal_xsd_datatypes.c b/src/rasqal/rasqal_xsd_datatypes.c
new file mode 100644
index 0000000..e79f060
--- /dev/null
+++ b/src/rasqal/rasqal_xsd_datatypes.c
@@ -0,0 +1,981 @@
+/*
+ * rasqal_xsd_datatypes.c - Rasqal XML Schema Datatypes support
+ *
+ * Copyright (C) 2005-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2005-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+#include <limits.h>
+
+#include "rasqal.h"
+#include "rasqal_internal.h"
+
+#if 0
+/* libxml2 datatypes */
+#ifdef HAVE_LIBXML_XMLSCHEMAS_H
+#include <libxml/xmlschemas.h>
+#include <libxml/xmlschemastypes.h>
+#include <libxml/schemasInternals.h>
+#endif
+#endif
+
+
+/*
+ *
+ * References
+ *
+ * XPath Functions and Operators
+ * http://www.w3.org/TR/xpath-functions/
+ *
+ * Datatypes hierarchy
+ * http://www.w3.org/TR/xpath-functions/#datatypes
+ * 
+ * Casting
+ * http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive
+ *
+ */
+
+
+#if 0
+#define RASQAL_XPFO_BASE_URI "http://www.w3.org/2004/07/xpath-functions";
+
+#define RASQAL_SPARQL_OP_NAMESPACE_URI "http://www.w3.org/2001/sw/DataAccess/operations";
+
+#define RASQAL_XSD_DATATYPES_SIZE 7
+
+typedef enum {
+  DT_dateTime,
+  DT_time,
+  DT_date,
+  DT_string,
+  DT_numeric,
+  DT_double,
+  DT_integer,
+} rasqal_xsd_datatype_id;
+#endif
+
+
+static int
+rasqal_xsd_check_boolean_format(const unsigned char* string, int flags) 
+{
+  /* FIXME
+   * Strictly only {true, false, 1, 0} are allowed according to
+   * http://www.w3.org/TR/xmlschema-2/#boolean
+   */
+  if(!strcmp((const char*)string, "true") || 
+     !strcmp((const char*)string, "TRUE") ||
+     !strcmp((const char*)string, "1") ||
+     !strcmp((const char*)string, "false") || 
+     !strcmp((const char*)string, "FALSE") ||
+     !strcmp((const char*)string, "0"))
+    return 1;
+
+  return 0;
+}
+
+
+#define ADVANCE_OR_DIE(p) if(!*(++p)) return 0;
+
+
+/**
+ * rasqal_xsd_check_dateTime_format:
+ * @string: lexical form string
+ * flags: flags
+ *
+ * INTERNAL - Check an XSD dateTime lexical form
+ *
+ * Return value: non-0 if the string is valid
+ */
+static int
+rasqal_xsd_check_dateTime_format(const unsigned char* string, int flags) 
+{
+  /* This should be correct according to 
+   * http://www.w3.org/TR/xmlschema-2/#dateTime
+   */
+  return rasqal_xsd_datetime_check(string);
+}
+
+
+/**
+ * rasqal_xsd_check_decimal_format:
+ * @string: lexical form string
+ * flags: flags
+ *
+ * INTERNAL - Check an XSD decimal lexical form
+ *
+ * Return value: non-0 if the string is valid
+ */
+static int
+rasqal_xsd_check_decimal_format(const unsigned char* string, int flags) 
+{
+  const char* p;
+  
+  /* This should be correct according to 
+   * http://www.w3.org/TR/xmlschema-2/#decimal
+   */
+  p=(const char*)string;
+  if(*p == '+' || *p == '-') {
+    ADVANCE_OR_DIE(p);
+  }
+
+  while(*p && isdigit(*p))
+    p++;
+  if(!*p)
+    return 1;
+  /* Fail if first non-digit is not '.' */
+  if(*p != '.')
+    return 0;
+  p++;
+  
+  while(*p && isdigit(*p))
+    p++;
+  /* Fail if anything other than a digit seen before NUL */
+  if(*p)
+    return 0;
+
+  return 1;
+}
+
+
+/**
+ * rasqal_xsd_check_double_format:
+ * @string: lexical form string
+ * flags: flags
+ *
+ * INTERNAL - Check an XSD double lexical form
+ *
+ * Return value: non-0 if the string is valid
+ */
+static int
+rasqal_xsd_check_double_format(const unsigned char* string, int flags) 
+{
+  /* FIXME validate using
+   * http://www.w3.org/TR/xmlschema-2/#double
+   */
+  double d=0.0;
+  char* eptr=NULL;
+
+  d=strtod((const char*)string, &eptr);
+  if((unsigned char*)eptr != string && *eptr=='\0')
+    return 1;
+
+  return 0;
+}
+
+
+/**
+ * rasqal_xsd_check_float_format:
+ * @string: lexical form string
+ * flags: flags
+ *
+ * INTERNAL - Check an XSD float lexical form
+ *
+ * Return value: non-0 if the string is valid
+ */
+static int
+rasqal_xsd_check_float_format(const unsigned char* string, int flags) 
+{
+  /* FIXME validate using
+   * http://www.w3.org/TR/xmlschema-2/#float
+   */
+  double d=0.0;
+  char* eptr=NULL;
+
+  d=strtod((const char*)string, &eptr);
+  if((unsigned char*)eptr != string && *eptr=='\0')
+    return 1;
+
+  return 0;
+}
+
+
+/**
+ * rasqal_xsd_check_integer_format:
+ * @string: lexical form string
+ * flags: flags
+ *
+ * INTERNAL - Check an XSD integer lexical form
+ *
+ * Return value: non-0 if the string is valid
+ */
+static int
+rasqal_xsd_check_integer_format(const unsigned char* string, int flags)
+{
+  long int v;
+  char* eptr=NULL;
+
+  /* This should be correct according to 
+   * http://www.w3.org/TR/xmlschema-2/#integer
+   */
+
+  v=(int)strtol((const char*)string, &eptr, 10);
+
+  if((unsigned char*)eptr != string && *eptr=='\0')
+    return 1;
+
+  return 0;
+}
+
+
+
+
+/**
+ * rasqal_xsd_format_double:
+ * @d: double
+ * @len_p: pointer to length of result or NULL
+ *
+ * INTERNAL - Format a new an xsd:double correctly
+ *
+ * Return value: new string or NULL on failure
+ */
+unsigned char*
+rasqal_xsd_format_double(double d, size_t *len_p)
+{
+  size_t e_index = 0;
+  size_t trailing_zero_start = 0;
+  size_t exponent_start;
+  size_t len=0;
+  unsigned char* buf=NULL;
+  
+  if(d == 0.0f) {
+    len=5;
+    buf=(unsigned char*)RASQAL_MALLOC(cstring, len+1);
+    if(!buf)
+      return NULL;
+
+    strncpy((char*)buf, "0.0e0", len+1);
+    if(len_p)
+      *len_p=len;
+    return buf;
+  }
+
+  len=20;
+  buf=(unsigned char*)RASQAL_MALLOC(cstring, len+1);
+  if(!buf)
+    return NULL;
+  
+  snprintf((char*)buf, len, "%1.14e", d);
+
+  /* find the 'e' and start of mantissa trailing zeros */
+
+  for( ; buf[e_index]; ++e_index) {
+    if(e_index > 0 && buf[e_index] == '0' && buf[e_index-1] != '0')
+      trailing_zero_start = e_index;
+    else if(buf[e_index] == 'e')
+      break;
+  }
+
+  if(buf[trailing_zero_start-1] == '.')
+    ++trailing_zero_start;
+
+  /* write an 'e' where the trailing zeros started */
+  buf[trailing_zero_start] = 'e';
+  if(buf[e_index+1] == '-') {
+    buf[trailing_zero_start+1] = '-';
+    ++trailing_zero_start;
+  }
+
+  exponent_start = e_index+2;
+  while(buf[exponent_start] == '0')
+    ++exponent_start;
+
+  len = strlen((const char*)buf);
+  if(exponent_start == len) {
+    len=trailing_zero_start+2;
+    buf[len-1] = '0';
+    buf[len] = '\0';
+  } else {
+    /* copy the exponent (minus leading zeros) after the new E */
+    memmove(buf+trailing_zero_start+1, buf+exponent_start,
+            len-trailing_zero_start);
+    len = strlen((const char*)buf);
+  }
+
+  if(len_p)
+    *len_p=len;
+
+  return buf;
+}
+
+
+typedef rasqal_literal* (*rasqal_extension_fn)(raptor_uri* name, raptor_sequence *args, char **error_p);
+
+
+typedef struct {
+  const unsigned char *name;
+  int min_nargs;
+  int max_nargs;
+  rasqal_extension_fn fn;
+  raptor_uri* uri;
+} rasqal_xsd_datatype_fn_info;
+
+
+#define XSD_INTEGER_DERIVED_COUNT 12
+#define XSD_INTEGER_DERIVED_FIRST (RASQAL_LITERAL_LAST_XSD+1)
+#define XSD_INTEGER_DERIVED_LAST (RASQAL_LITERAL_LAST_XSD + XSD_INTEGER_DERIVED_COUNT-1)
+
+/* atomic XSD literals + 12 types derived from xsd:integer plus a NULL */
+#define SPARQL_XSD_NAMES_COUNT (RASQAL_LITERAL_LAST_XSD+1 + XSD_INTEGER_DERIVED_COUNT)
+
+
+static const char* const sparql_xsd_names[SPARQL_XSD_NAMES_COUNT+1]=
+{
+  NULL, /* RASQAL_LITERAL_UNKNOWN */
+  NULL, /* ...BLANK */
+  NULL, /* ...URI */ 
+  "string",
+  "boolean",
+  "integer", /* may type-promote to xsd:decimal */
+  "double",
+  "float",
+  "decimal",
+  "dateTime",
+  /* all of the following always type-promote to xsd:integer */
+  "nonPositiveInteger", "negativeInteger",
+  "long", "int", "short", "byte",
+  "nonNegativeInteger", "unsignedLong", "postiveInteger",
+  "unsignedInt", "unsignedShort", "unsignedByte",
+  NULL
+};
+
+
+static int (*const sparql_xsd_checkfns[RASQAL_LITERAL_LAST_XSD-RASQAL_LITERAL_FIRST_XSD+1])(const unsigned char* string, int flags) =
+{
+  NULL, /* RASQAL_LITERAL_STRING */
+  rasqal_xsd_check_boolean_format, /* RASQAL_LITERAL_BOOLEAN */
+  rasqal_xsd_check_integer_format, /* RASQAL_LITERAL_INTEGER */
+  rasqal_xsd_check_double_format, /* RASQAL_LITERAL_DOUBLE */
+  rasqal_xsd_check_float_format, /* RASQAL_LITERAL_FLOAT */
+  rasqal_xsd_check_decimal_format, /* RASQAL_LITERAL_DECIMAL */
+  rasqal_xsd_check_dateTime_format /* RASQAL_LITERAL_DATETIME */
+};
+
+int
+rasqal_xsd_init(rasqal_world* world) 
+{
+  int i;
+
+#ifdef RAPTOR_V2_AVAILABLE
+  world->xsd_namespace_uri = raptor_new_uri_v2(world->raptor_world_ptr, raptor_xmlschema_datatypes_namespace_uri);
+#else
+  world->xsd_namespace_uri = raptor_new_uri(raptor_xmlschema_datatypes_namespace_uri);
+#endif
+  if(!world->xsd_namespace_uri)
+    return 1;
+
+  world->xsd_datatype_uris=
+    (raptor_uri**)RASQAL_CALLOC(ptrarray,
+                                SPARQL_XSD_NAMES_COUNT+1,
+                                sizeof(raptor_uri*));
+  if(!world->xsd_datatype_uris)
+    return 1;
+
+  for(i=RASQAL_LITERAL_FIRST_XSD; i < SPARQL_XSD_NAMES_COUNT; i++) {
+    world->xsd_datatype_uris[i] =
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_new_uri_from_uri_local_name_v2(world->raptor_world_ptr, world->xsd_namespace_uri,
+                                            (const unsigned char *)sparql_xsd_names[i]);
+#else
+      raptor_new_uri_from_uri_local_name(world->xsd_namespace_uri,
+                                         (const unsigned char *)sparql_xsd_names[i]);
+#endif
+    if(!world->xsd_datatype_uris[i])
+      return 1;
+  }
+
+  return 0;
+}
+
+
+void
+rasqal_xsd_finish(rasqal_world* world) 
+{
+  if(world->xsd_datatype_uris) {
+    int i;
+    
+    for(i=RASQAL_LITERAL_FIRST_XSD; i < SPARQL_XSD_NAMES_COUNT; i++) {
+      if(world->xsd_datatype_uris[i])
+#ifdef RAPTOR_V2_AVAILABLE
+        raptor_free_uri_v2(world->raptor_world_ptr, world->xsd_datatype_uris[i]);
+#else
+        raptor_free_uri(world->xsd_datatype_uris[i]);
+#endif
+    }
+
+    RASQAL_FREE(table, world->xsd_datatype_uris);
+    world->xsd_datatype_uris = NULL;
+  }
+
+  if(world->xsd_namespace_uri) {
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(world->raptor_world_ptr, world->xsd_namespace_uri);
+#else
+    raptor_free_uri(world->xsd_namespace_uri);
+#endif
+    world->xsd_namespace_uri = NULL;
+  }
+}
+ 
+
+  
+rasqal_literal_type
+rasqal_xsd_datatype_uri_to_type(rasqal_world* world, raptor_uri* uri)
+{
+  int i;
+  rasqal_literal_type native_type=RASQAL_LITERAL_UNKNOWN;
+  
+  if(!uri || !world->xsd_datatype_uris)
+    return native_type;
+  
+  for(i=(int)RASQAL_LITERAL_FIRST_XSD; i <= (int)RASQAL_LITERAL_LAST_XSD; i++) {
+    if(
+#ifdef RAPTOR_V2_AVAILABLE    
+       raptor_uri_equals_v2(world->raptor_world_ptr, uri, world->xsd_datatype_uris[i])
+#else
+       raptor_uri_equals(uri, world->xsd_datatype_uris[i])
+#endif
+      )
+    {
+      native_type=(rasqal_literal_type)i;
+      break;
+    }
+  }
+  return native_type;
+}
+
+
+rasqal_literal_type
+rasqal_xsd_datatype_uri_parent_type(rasqal_world* world, raptor_uri* uri)
+{
+  int i;
+  rasqal_literal_type parent_type=RASQAL_LITERAL_UNKNOWN;
+  
+  if(!uri || !world->xsd_datatype_uris)
+    return parent_type;
+
+  /* xsd:integer parent is xsd:decimal */
+  if(
+#ifdef RAPTOR_V2_AVAILABLE
+     raptor_uri_equals_v2(world->raptor_world_ptr, uri,
+                          world->xsd_datatype_uris[RASQAL_LITERAL_INTEGER])
+#else
+     raptor_uri_equals(uri,
+                       world->xsd_datatype_uris[RASQAL_LITERAL_INTEGER])
+#endif
+    )
+    return RASQAL_LITERAL_DECIMAL;
+  
+  /* a pile of things have parent of xsd:integer */
+  for(i=(int)XSD_INTEGER_DERIVED_FIRST; i <= (int)XSD_INTEGER_DERIVED_LAST; i++) {
+    if(
+#ifdef RAPTOR_V2_AVAILABLE
+       raptor_uri_equals_v2(world->raptor_world_ptr, uri, world->xsd_datatype_uris[i])
+#else
+       raptor_uri_equals(uri, world->xsd_datatype_uris[i])
+#endif
+      )
+    {
+      parent_type=RASQAL_LITERAL_INTEGER;
+      break;
+    }
+  }
+
+  return parent_type;
+}
+
+
+raptor_uri*
+rasqal_xsd_datatype_type_to_uri(rasqal_world* world, rasqal_literal_type type)
+{
+  if(world->xsd_datatype_uris &&
+     type >= RASQAL_LITERAL_FIRST_XSD && type <= (int)RASQAL_LITERAL_LAST_XSD)
+    return world->xsd_datatype_uris[(int)type];
+  return NULL;
+}
+
+
+/**
+ * rasqal_xsd_datatype_check:
+ * @native_type: rasqal XSD type
+ * @string: string
+ * @flags: check flags
+ *
+ * INTERNAL - check a string as a valid lexical form of an XSD datatype
+ *
+ * Return value: non-0 if the string is valid
+ */
+int
+rasqal_xsd_datatype_check(rasqal_literal_type native_type, 
+                          const unsigned char* string, int flags)
+{
+  /* calculate check function index in sparql_xsd_checkfns table */
+  int checkidx=native_type-RASQAL_LITERAL_FIRST_XSD;
+
+  /* test for index out of bounds and check function not defined */
+  if(checkidx < 0 || checkidx >= (int)(sizeof(sparql_xsd_checkfns)/sizeof(*sparql_xsd_checkfns)) ||
+     !sparql_xsd_checkfns[checkidx])
+    return 1;
+
+  return sparql_xsd_checkfns[checkidx](string, flags);
+}
+
+
+const char*
+rasqal_xsd_datatype_label(rasqal_literal_type native_type)
+{
+  return sparql_xsd_names[native_type];
+}
+
+
+int
+rasqal_xsd_is_datatype_uri(rasqal_world* world, raptor_uri* uri)
+{
+  return (rasqal_xsd_datatype_uri_to_type(world, uri) != RASQAL_LITERAL_UNKNOWN);
+}
+
+
+int
+rasqal_xsd_datatype_is_numeric(rasqal_literal_type type)
+{
+  return (type >= RASQAL_LITERAL_BOOLEAN && type <= RASQAL_LITERAL_DECIMAL);
+}
+
+
+
+#if 0
+static rasqal_literal*
+rasqal_xsd_datatypes_date_less_than(raptor_uri* name, raptor_sequence *args,
+                                    char **error_p) {
+  int error=0;
+  int b;
+  rasqal_literal* l1;
+  rasqal_literal* l2;
+  
+  if(raptor_sequence_size(args) != 2)
+    return NULL;
+  
+  l1=(rasqal_literal*)raptor_sequence_get_at(args, 0);
+  l2=(rasqal_literal*)raptor_sequence_get_at(args, 1);
+  
+  b=(rasqal_literal_compare(l1, l2, 0, &error) < 0);
+  if(error)
+    return NULL;
+
+  return rasqal_new_boolean_literal(b);
+}
+
+
+static rasqal_literal*
+rasqal_xsd_datatypes_date_greater_than(raptor_uri* name, raptor_sequence *args,
+                                       char **error_p) {
+  int error=0;
+  int b;
+  rasqal_literal* l1;
+  rasqal_literal* l2;
+  
+  if(raptor_sequence_size(args) != 2)
+    return NULL;
+  
+  l1=(rasqal_literal*)raptor_sequence_get_at(args, 0);
+  l2=(rasqal_literal*)raptor_sequence_get_at(args, 1);
+  
+  b=(rasqal_literal_compare(l1, l2, 0, &error) > 0);
+  if(error)
+    return NULL;
+
+  return rasqal_new_boolean_literal(b);
+}
+
+
+static rasqal_literal*
+rasqal_xsd_datatypes_date_equal(raptor_uri* name, raptor_sequence *args,
+                                char **error_p) {
+  int error=0;
+  int b;
+  rasqal_literal* l1;
+  rasqal_literal* l2;
+  
+  if(raptor_sequence_size(args) != 2)
+    return NULL;
+  
+  l1=(rasqal_literal*)raptor_sequence_get_at(args, 0);
+  l2=(rasqal_literal*)raptor_sequence_get_at(args, 1);
+  
+  b=(rasqal_literal_compare(l1, l2, 0, &error) == 0);
+  if(error)
+    return NULL;
+
+  return rasqal_new_boolean_literal(b);
+}
+
+
+#define RASQAL_XSD_DATATYPE_FNS_SIZE 9
+static rasqal_xsd_datatype_fn_info rasqal_xsd_datatype_fns[RASQAL_XSD_DATATYPE_FNS_SIZE]={
+  { (const unsigned char*)"date-less-than",        1, 1, rasqal_xsd_datatypes_date_less_than },
+  { (const unsigned char*)"dateTime-less-than",    1, 1, rasqal_xsd_datatypes_date_less_than },
+  { (const unsigned char*)"time-less-than",        1, 1, rasqal_xsd_datatypes_date_less_than },
+  { (const unsigned char*)"date-greater-than",     1, 1, rasqal_xsd_datatypes_date_greater_than },
+  { (const unsigned char*)"dateTime-greater-than", 1, 1, rasqal_xsd_datatypes_date_greater_than },
+  { (const unsigned char*)"time-greater-than",     1, 1, rasqal_xsd_datatypes_date_greater_than },
+  { (const unsigned char*)"date-equal",            1, 1, rasqal_xsd_datatypes_date_equal },
+  { (const unsigned char*)"dateTime-equal",        1, 1, rasqal_xsd_datatypes_date_equal },
+  { (const unsigned char*)"time-equal",            1, 1, rasqal_xsd_datatypes_date_equal }
+};
+
+
+
+static raptor_uri* raptor_xpfo_base_uri=NULL;
+static raptor_uri* rasqal_sparql_op_namespace_uri=NULL;
+
+
+static void
+rasqal_init_datatypes(void) {
+  int i;
+  
+  raptor_xpfo_base_uri=raptor_new_uri((const unsigned char*)RASQAL_XPFO_BASE_URI);
+  rasqal_sparql_op_namespace_uri=raptor_new_uri((const unsigned char*)RASQAL_SPARQL_OP_NAMESPACE_URI);
+
+  for(i=0; i< RASQAL_XSD_DATATYPES_SIZE; i++) {
+    rasqal_xsd_datatypes[i].uri=raptor_new_uri_from_uri_local_name(raptor_xpfo_base_uri,
+                                                                   (const unsigned char*)rasqal_xsd_datatypes[i].name);
+  }
+
+  for(i=0; i< RASQAL_XSD_DATATYPE_FNS_SIZE; i++) {
+    rasqal_xsd_datatype_fns[i].uri=raptor_new_uri_from_uri_local_name(rasqal_sparql_op_namespace_uri,
+                                                                  rasqal_xsd_datatype_fns[i].name);
+  }
+
+}
+
+
+static void
+rasqal_finish_datatypes(void) {
+  int i;
+  
+  for(i=0; i< RASQAL_XSD_DATATYPES_SIZE; i++)
+    if(rasqal_xsd_datatypes[i].uri)
+      raptor_free_uri(rasqal_xsd_datatypes[i].uri);
+
+  for(i=0; i< RASQAL_XSD_DATATYPE_FNS_SIZE; i++)
+    if(rasqal_xsd_datatype_fns[i].uri)
+      raptor_free_uri(rasqal_xsd_datatype_fns[i].uri);
+
+  if(raptor_xpfo_base_uri)
+    raptor_free_uri(raptor_xpfo_base_uri);
+
+  if(rasqal_sparql_op_namespace_uri)
+    raptor_free_uri(rasqal_sparql_op_namespace_uri);
+}
+#endif
+
+
+/*
+ * 
+ * Facets
+ * 
+ * Ordered
+ * [Definition:] A value space, and hence a datatype, is said to be
+ * ordered if there exists an order-relation defined for that
+ * value space.
+ * -- http://www.w3.org/TR/xmlschema-2/#dt-ordered
+ * 
+ * Bounded
+ * [Definition:] A datatype is bounded if its value space has either
+ * an inclusive upper bound or an exclusive upper bound and either
+ * an inclusive lower bound or an exclusive lower bound.
+ * -- http://www.w3.org/TR/xmlschema-2/#dt-bounded
+ * 
+ * Cardinality
+ * [Definition:] Every value space has associated with it the concept
+ * of cardinality. Some value spaces are finite, some are countably
+ * infinite while still others could conceivably be uncountably infinite
+ * (although no value space defined by this specification is
+ * uncountable infinite). A datatype is said to have the cardinality of
+ * its value space.
+ * -- http://www.w3.org/TR/xmlschema-2/#dt-cardinality
+ * 
+ * Numeric
+ * [Definition:] A datatype is said to be numeric if its values are
+ * conceptually quantities (in some mathematical number system).
+ * -- http://www.w3.org/TR/xmlschema-2/#dt-numeric
+ */
+
+
+
+/*
+ * Types: dateTime, date, time
+ *   http://www.w3.org/TR/xmlschema-2/#dateTime
+ *   http://www.w3.org/TR/xmlschema-2/#date
+ *   http://www.w3.org/TR/xmlschema-2/#time
+ * all (partial ordered, bounded, countably infinite, not numeric)
+ * 
+ * Functions (all operators)
+ * op:date-equal, op:date-less-than, op:date-greater-than
+ *
+ * ??? dateTime equiv???
+ * op:dateTime-equal, op:dateTime-less-than, op:dateTime-greater-than
+ *
+ * ??? time equiv???
+ * op:time-equal, op:time-less-than, op:time-greater-than
+ */
+
+
+
+/* 
+ * Type: string
+ * (not ordered, not bounded, countably infinite, not numeric)
+ * 
+ * fn:contains
+ *   Indicates whether one xs:string contains another xs:string. A
+ *   collation may be specified.
+ *
+ * fn:starts-with
+ *   Indicates whether the value of one xs:string begins with the
+ *   collation units of another xs:string. A collation may be
+ *   specified.
+ *
+ * fn:ends-with
+ *   Indicates whether the value of one xs:string ends with the
+ *   collation units of another xs:string. A collation may be
+ *   specified.
+ *
+ * fn:substring-before
+ *   Returns the collation units of one xs:string that precede in
+ *   that xs:string the collation units of another xs:string. A
+ *   collation may be specified.
+ *
+ * fn:substring-after
+ *   Returns the collation units of xs:string that follow in that
+ *   xs:string the collation units of another xs:string. A collation
+ *   may be specified.
+ *
+ * fn:string-length
+ *   Returns the length of the argument.
+ *
+ * fn:upper-case
+ *   Returns the upper-cased value of the argument.
+ *
+ * fn:lower-case
+ *   Returns the lower-cased value of the argument.
+ *
+ * fn:matches (input, pattern)
+ *   fn:matches (input, pattern, flags)
+ *
+ *   Returns an xs:boolean value that indicates whether the
+ *   value of the first argument is matched by the regular expression that
+ *   is the value of the second argument.
+ *
+ *   flags = string of s,m,i,x char combinations ("" when omitted)
+ *
+ *   Regular expressions: Perl5 syntax as defined in "Functions and
+ *   Operators".
+ *
+ *  http://www.w3.org/TR/xpath-functions/#func-contains
+ *  http://www.w3.org/TR/xpath-functions/#func-starts-with
+ *  http://www.w3.org/TR/xpath-functions/#func-ends-with
+ *  http://www.w3.org/TR/xpath-functions/#func-substring-before
+ *  http://www.w3.org/TR/xpath-functions/#func-substring-after
+ *  http://www.w3.org/TR/xpath-functions/#func-string-length
+ *  http://www.w3.org/TR/xpath-functions/#func-upper-case
+ *  http://www.w3.org/TR/xpath-functions/#func-lower-case
+ *  http://www.w3.org/TR/xpath-functions/#func-matches
+ *
+ * ??? no equality comparison fn:compare???
+ *  fn:compare($comparand1 as xs:string, $comparand2 as xs:string) as xs:integer
+ *  fn:compare($comparand1 as xs:string, $comparand2 as xs:string,
+ *             $collation as xs:string) as xs:integer
+ * [[This function, invoked with the first signature, backs up the
+ * "eq", "ne", "gt", "lt", "le" and "ge" operators on string
+ * values.]]
+ *
+ */
+
+#if 0
+typedef struct
+{
+  unsigned char *string;
+  size_t length;
+} rasqal_xsd_string;
+#endif
+
+
+/*
+ * Type: double
+ *   (partial ordered, bounded, countably infinite, numeric)
+ * 
+ * Type: decimal
+ *   (total ordered, not bounded, countably infinite, numeric)
+ *
+ * Derived Type: integer (derived from decimal)
+ *   (total ordered, not bounded, countably infinite, numeric)
+ * 
+ * Functions:
+ * 1 arguments
+ *   op:numeric-unary-plus
+ *   op:numeric-unary-minus
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-unary-plus
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-unary-minus
+ *
+ * 2 arguments
+ *   op:numeric-equal
+ *   op:numeric-less-than
+ *   op:numeric-greater-than
+ *   op:numeric-add
+ *   op:numeric-subtract
+ *   op:numeric-multiply
+ *   op:numeric-divide
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-equal
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-less-than
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-greater-than
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-add
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-subtract
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-multiply
+ *   http://www.w3.org/TR/xpath-functions/#func-numeric-divide
+ *
+ * [[The parameters and return types for the above operators are the
+ * basic numeric types: xs:integer, xs:decimal, xs:float and
+ * xs:double, and types derived from them.  The word "numeric" in
+ * function signatures signifies these four types. For simplicity,
+ * each operator is defined to operate on operands of the same type
+ * and to return the same type. The exceptions are op:numeric-divide,
+ * which returns an xs:decimal if called with two xs:integer operands
+ * and op:numeric-integer-divide which always returns an xs:integer.]]
+ * -- http://www.w3.org/TR/xpath-functions/#op.numeric
+ *
+ *
+ * Numeric type promotion
+ * http://www.w3.org/TR/xpath20/#dt-type-promotion
+ *
+ * [[xs:decimal (or any type derived by restriction from xs:decimal,
+ * including xs:integer) can be promoted to either of the types
+ * xs:float or xs:double.]]
+ *
+ * For here that means xs:integer to xs:double and xs:decimal to xs:double
+ *
+ * [[A function that expects a parameter $p of type xs:decimal can be
+ * invoked with a value of type xs:integer. This is an example of
+ * subtype substitution. The value retains its original type. Within
+ * the body of the function, $p instance of xs:integer returns
+ * true.]]
+ *
+ *
+ * B.2 Operator Mapping
+ * http://www.w3.org/TR/xpath20/#mapping
+ *
+ * [[When referring to a type, the term numeric denotes the types
+ * xs:integer, xs:decimal, xs:float, and xs:double]]
+ *
+ * [[If the result type of an operator is listed as numeric, it means
+ * "the first type in the ordered list (xs:integer, xs:decimal,
+ * xs:float, xs:double) into which all operands can be converted by
+ * subtype substitution and numeric type promotion."]]
+ * 
+ */
+
+
+
+#ifdef STANDALONE
+#include <stdio.h>
+
+int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+
+#if 0
+  raptor_uri *xsd_uri;
+  raptor_uri *dateTime_uri;
+  rasqal_literal *l1, *l2;
+  int fn_i;
+  raptor_uri* fn_uri;
+  const unsigned char *fn_name;
+  rasqal_extension_fn fn;
+  raptor_sequence *fn_args;
+  char *error;
+  rasqal_literal *fn_result;
+  rasqal_world *world;
+  
+  world=rasqal_new_world();
+  if(!world || rasqal_world_open(world)) {
+    fprintf(stderr, "%s: rasqal_world init failed\n", program);
+    return(1);
+  }
+
+  xsd_uri=raptor_new_uri(raptor_xmlschema_datatypes_namespace_uri);
+  dateTime_uri=raptor_new_uri_from_uri_local_name(xsd_uri, (const unsigned char*)"dateTime");
+
+  rasqal_init_datatypes();
+
+  fn_args=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_literal, (raptor_sequence_print_handler*)rasqal_literal_print);
+  l1=rasqal_new_string_literal((unsigned char*)strdup("2004-05-04"), NULL, raptor_uri_copy(dateTime_uri), NULL);
+  raptor_sequence_push(fn_args, l1);
+  l2=rasqal_new_string_literal((unsigned char*)strdup("2003-01-02"), NULL, raptor_uri_copy(dateTime_uri), NULL);
+  raptor_sequence_push(fn_args, l2);
+  
+  fn_i=0;
+  fn_name=rasqal_xsd_datatype_fns[fn_i].name;
+  fn=rasqal_xsd_datatype_fns[fn_i].fn;
+  fn_uri=rasqal_xsd_datatype_fns[fn_i].uri;
+
+  error=NULL;
+  fn_result=fn(fn_uri, fn_args, &error);
+  raptor_free_sequence(fn_args);
+
+  if(!fn_result) {
+    if(error)
+      fprintf(stderr, "function %s failed with error %s\n", fn_name, error);
+    else
+      fprintf(stderr, "function %s unknown error\n", fn_name);
+  } else {
+    fprintf(stderr, "function %s returned result: ", fn_name);
+    rasqal_literal_print(fn_result, stderr);
+    fputc('\n', stderr);
+  }
+  
+
+  if(fn_result) 
+    rasqal_free_literal(fn_result);
+
+  rasqal_finish_datatypes();
+  
+  raptor_free_uri(xsd_uri);
+  raptor_free_uri(dateTime_uri);
+
+  rasqal_free_world(world);
+#endif
+
+  return 0;
+}
+#endif
diff --git a/src/rasqal/rdql_common.h b/src/rasqal/rdql_common.h
new file mode 100644
index 0000000..5546264
--- /dev/null
+++ b/src/rasqal/rdql_common.h
@@ -0,0 +1,63 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rdql_common.h - RDQL lexer/parser shared internals
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2004, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+#ifndef RDQL_COMMON_H
+#define RDQL_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* rdql_parser.y */
+int rdql_syntax_error(rasqal_query *rq, const char *message, ...) RASQAL_PRINTF_FORMAT(2, 3);
+int rdql_syntax_warning(rasqal_query *rq, const char *message, ...) RASQAL_PRINTF_FORMAT(2, 3);
+
+int rdql_query_lex(void);
+
+
+struct rasqal_rdql_query_language_s {
+  /* STATIC lexer */
+  yyscan_t scanner;
+
+  int scanner_set;
+
+  /* for error reporting */
+  unsigned int lineno;
+
+  /* count of errors in current query parse */
+  int error_count;
+
+  /* expression tree for AND ... */
+  rasqal_expression* constraint_expression;
+};
+
+
+typedef struct rasqal_rdql_query_language_s rasqal_rdql_query_language;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/rasqal/rdql_lexer.l b/src/rasqal/rdql_lexer.l
new file mode 100644
index 0000000..b53e80e
--- /dev/null
+++ b/src/rasqal/rdql_lexer.l
@@ -0,0 +1,1238 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rdql_lexer.l - Rasqal RDQL lexer - making tokens for rdql grammar generator
+ *
+ * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * To generate the C files from this source, rather than use the
+ * shipped rdql_lexer.c/.h needs a patched version of flex 2.5.31 such
+ * as the one available in Debian GNU/Linux.   Details below
+ * near the %option descriptions.
+ *
+ */
+
+
+/* recognise 8-bits */
+%option 8bit
+%option warn nodefault
+
+/* all symbols prefixed by this */
+%option prefix="rdql_lexer_"
+
+/* This is not needed, flex is invoked -ordql_lexer.c */
+%option outfile="rdql_lexer.c"
+
+/* Emit a C header file for prototypes
+ * Only available in flex 2.5.13 or newer.
+ * It was renamed to header-file in flex 2.5.19
+ */
+%option header-file="rdql_lexer.h"
+
+/* Do not emit #include <unistd.h>
+ * Only available in flex 2.5.7 or newer.
+ * Broken in flex 2.5.31 without patches.
+ */
+%option nounistd
+
+/* Never interactive */
+/*  No isatty() check */
+%option never-interactive
+
+/* Batch scanner */
+%option batch
+
+/* Never use yyunput */
+%option nounput
+
+/* Supply our own alloc/realloc/free functions */
+%option noyyalloc noyyrealloc noyyfree
+
+/* Re-entrant scanner */
+%option reentrant
+
+
+%x PATTERN ID
+
+  /* definitions */
+
+%{
+
+/* NOTE: These headers are NOT included here. They are inserted by fix-flex
+ * since otherwise it appears far too late in the generated C
+ */
+
+/*
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
+
+#include <rasqal.h>
+#include <rasqal_internal.h>
+
+#include <rdql_parser.h>
+
+#include <rdql_common.h>
+
+
+
+static int rdql_skip_c_comment(rasqal_query *rq);
+
+static unsigned char* rdql_copy_name(rasqal_query *rq, const unsigned char *text, size_t len);
+static unsigned char* rdql_copy_qname(rasqal_query *rq, const unsigned char *text, size_t len);
+static int rdql_copy_regex_token(rasqal_query *rq, YYSTYPE* lval, unsigned char delim);
+static int rdql_copy_string_token(rasqal_query *rq, YYSTYPE* lval, const unsigned char *text, size_t len, int delim);
+
+#ifdef RASQAL_DEBUG
+const char * rdql_token_print(rasqal_world* world, int token, YYSTYPE *lval);
+#endif
+
+int rdql_lexer_lex (YYSTYPE *rdql_parser_lval, yyscan_t yyscanner);
+#define YY_DECL int rdql_lexer_lex (YYSTYPE *rdql_parser_lval, yyscan_t yyscanner)
+
+#ifdef __cplusplus
+#define INPUT_FN yyinput
+#else
+#define INPUT_FN input
+#endif
+
+/* Remove the re-fill function since it should never be called */
+#define YY_INPUT(buf,result,max_size) { return YY_NULL; }
+
+
+/* Missing rdql_lexer.c/h prototypes */
+int rdql_lexer_get_column(yyscan_t yyscanner);
+void rdql_lexer_set_column(int  column_no , yyscan_t yyscanner);
+
+static void rdql_lexer_cleanup(yyscan_t yyscanner);
+
+#ifdef HAVE_SETJMP
+static jmp_buf rdql_lexer_fatal_error_longjmp_env;
+
+/* fatal error handler declaration */
+#define YY_FATAL_ERROR(msg) do {		\
+    rdql_lexer_fatal_error(msg, yyscanner);   \
+    longjmp(rdql_lexer_fatal_error_longjmp_env, 1);        \
+} while(0)
+#else
+#define YY_FATAL_ERROR(msg) do {		\
+    rdql_lexer_fatal_error(msg, yyscanner);   \
+    abort();                                    \
+} while(0)
+#endif
+ 
+static void rdql_lexer_fatal_error(yyconst char *msg, yyscan_t yyscanner);
+
+%}
+
+LANGUAGETOKEN [A-Za-z][-A-Z_a-z0-9]*
+/* See
+ * http://www.w3.org/TR/xml11/#NT-NameStartChar and 
+ * http://www.w3.org/TR/xml11/#NT-NameChar 
+ */
+PREFIX [A-Za-z\\\x80-\xff][-A-Z_a-z\\\x80-\xff0-9]*
+NAME [A-Za-z_\\\x80-\xff][-A-Z_a-z\\\x80-\xff0-9]*
+QNAME {PREFIX}:{NAME}*
+/* The initial char conditions are to ensure this doesn't grab < or <= */
+QUOTEDURI \<[A-Za-z][^>]+\>
+
+%%
+  /* rules */
+
+%{
+
+  int c;
+  rasqal_query *rq=(rasqal_query*)yyextra;
+  rasqal_rdql_query_language *rqe=(rasqal_rdql_query_language*)rq->context;
+
+#ifdef HAVE_SETJMP
+  if(setjmp(rdql_lexer_fatal_error_longjmp_env))
+    return 1;
+#endif
+  
+%}
+
+"//"[^\r\n]*(\r\n|\r|\n)	{ /* C++ comment */
+        rqe->lineno++;
+}
+
+"/*"	{ int lines=rdql_skip_c_comment(rq);
+          if(lines < 0)
+            yyterminate();
+          rqe->lineno += lines;
+        }
+
+\r\n|\r|\n     { rqe->lineno++; }
+
+[\ \t\v]+   { /* eat up other whitespace */
+	;
+}
+
+"SELECT"|"select" { return SELECT; }
+"SOURCE"|"source" { return SOURCE; }
+"FROM"|"from"     { return FROM; } 
+"WHERE"|"where"   { return WHERE; } 
+"AND"|"and"       { return AND; } 
+"USING"|"using"   { return USING; }
+"FOR"|"for"       { return FOR; }
+
+","      { return ','; } 
+"("      { return '('; } 
+")"      { return ')'; } 
+"?"  { BEGIN(ID); return '?'; }
+
+"||"         { return SC_OR; }
+"&&"         { return SC_AND; }
+
+"EQ"|"eq"  { return STR_EQ; }
+"NE"|"NE"  { return STR_NE; }
+
+"=~"|"~~"  { BEGIN(PATTERN); return STR_MATCH; }
+"!~"       { BEGIN(PATTERN); return STR_NMATCH; }
+
+<PATTERN>[ \t\v]+   {
+	;
+}
+
+<PATTERN>\r\n|\r|\n     { rqe->lineno++; }
+
+
+<PATTERN>. { /* first non whitespace */
+             if(!rdql_copy_regex_token(rq, rdql_parser_lval, *yytext)) {
+               BEGIN(INITIAL);
+               return PATTERN_LITERAL;
+             }
+             BEGIN(INITIAL);
+	     yyterminate();
+         };
+
+
+"=="            { return EQ; }
+"!="            { return NEQ; }
+"<"/[^A-Za-z=]  { return LT; }
+">"             { return GT; }
+"<="         { return LE; }
+">="         { return GE; }
+
+"+"         { return '+'; }
+"-"         { return '-'; }
+"*"         { return '*'; }
+"/"         { return '/'; }
+"%"         { return '%'; }
+"~"         { return '~'; }
+"!"         { return '!'; }
+
+[0-9]+["lL"]?   { c=yytext[yyleng-1];
+                  if (c== 'l' || c == 'L')
+                    yytext[yyleng-1]='\0';
+                  rdql_parser_lval->literal=rasqal_new_integer_literal(rq->world, RASQAL_LITERAL_INTEGER, atoi(yytext));
+ 		  return INTEGER_LITERAL; 
+}
+
+0[xX][0-9a-fA-F]+   { int i;
+                      int n;
+
+                      if(yytext[yyleng+1] == 'x') 
+                        n=sscanf(yytext+2, "%x", &i);
+                      else
+                        n=sscanf(yytext+2, "%X", &i);
+                      if(n != 1) {
+                        rdql_syntax_error(rq, "RDQL syntax error - Illegal hex constant %c%c%c",
+                                          yytext[0], yytext[1], yytext[2]);
+                        yyterminate();
+                      }
+                      rdql_parser_lval->literal=rasqal_new_integer_literal(rq->world, RASQAL_LITERAL_INTEGER, i);
+                      return INTEGER_LITERAL; 
+}
+
+[0-9]+"."[0-9]*[eE][+-]?[0-9]+[fFdD]?|"."[0-9]+[eE][+-]?[0-9]+[fFdD]?|[0-9]+[eE][+-]?[0-9]+[fFdD]?|[0-9]+[eE][+-]?[0-9]+[fFdD]?|[0-9]+"."[0-9]*  { 
+                        rdql_parser_lval->literal=rasqal_new_typed_literal(rq->world, RASQAL_LITERAL_DOUBLE, (const unsigned char*)yytext);
+                        if(!rdql_parser_lval->literal)
+                          yyterminate();
+                        return FLOATING_POINT_LITERAL;
+}
+
+'([^'\\\n\r]|\\[^\n\r])*'(@{LANGUAGETOKEN})?(^^({QUOTEDURI}|{QNAME}))?    { /*' */
+                        if(!rdql_copy_string_token(rq, rdql_parser_lval,
+                          (const unsigned char*)yytext+1, yyleng-1, '\''))
+                          return STRING_LITERAL;
+		        yyterminate();
+}
+
+\"([^"\\\n\r]|\\[^\n\r])*\"(@{LANGUAGETOKEN})?(^^({QUOTEDURI}|{QNAME}))?   { /* " */
+                        if(!rdql_copy_string_token(rq, rdql_parser_lval,
+                          (const unsigned char*)yytext+1, yyleng-1, '"'))
+                          return STRING_LITERAL; 
+		        yyterminate();
+}
+
+"true"|"false"	{ rdql_parser_lval->literal=rasqal_new_boolean_literal(rq->world, *yytext== 't');
+                  return BOOLEAN_LITERAL; }
+
+"null"	{ rdql_parser_lval->literal=NULL;
+          return NULL_LITERAL; }
+
+<*>{NAME}	{ rdql_parser_lval->name=rdql_copy_name(rq, (const unsigned char*)yytext, yyleng);
+		  if(!rdql_parser_lval->name)
+                    yyterminate();
+                          BEGIN(INITIAL);
+                          return IDENTIFIER; }
+<ID>(.|\n)	{	BEGIN(INITIAL);
+		rdql_syntax_error(rq, "RDQL syntax error - missing variable name after ?");
+                yyterminate();
+		}
+
+{QNAME}	{ rdql_parser_lval->name=rdql_copy_qname(rq, (const unsigned char*)yytext, yyleng);
+	  if(!rdql_parser_lval->name)
+            yyterminate();
+                          return QNAME_LITERAL; }
+
+\<{QNAME}\>	{ rdql_parser_lval->name=rdql_copy_qname(rq, (const unsigned char*)yytext+1, yyleng-2);
+		  if(!rdql_parser_lval->name)
+	            yyterminate();
+                  rdql_syntax_warning(rq, "Obsolete RDQL <qname> syntax found in \"%s\"", (const unsigned char*)yytext);
+                  return QNAME_LITERAL; }
+
+{QUOTEDURI}   { if(yyleng == 2) 
+#ifdef RAPTOR_V2_AVAILABLE
+                  rdql_parser_lval->uri = raptor_uri_copy_v2(rq->world->raptor_world_ptr, rq->base_uri);
+#else
+                  rdql_parser_lval->uri = raptor_uri_copy(rq->base_uri);
+#endif
+                else {
+                  yytext[yyleng-1]='\0';
+#ifdef RAPTOR_V2_AVAILABLE
+                  rdql_parser_lval->uri = raptor_new_uri_relative_to_base_v2(rq->world->raptor_world_ptr, rq->base_uri, (const unsigned char*)yytext+1);
+#else                  
+                  rdql_parser_lval->uri = raptor_new_uri_relative_to_base(rq->base_uri, (const unsigned char*)yytext+1);
+#endif
+                 }
+                 return URI_LITERAL; }
+
+\#              { while((c=INPUT_FN(yyscanner)) != '\n' && c)
+                    ;
+                }
+
+.         	{ if (!*yytext)
+                    return EOF;
+
+                  rdql_syntax_error(rq, "RDQL syntax error at '%s'", yytext);
+                  yyterminate();
+		}
+
+%%
+  /* user code */
+
+int
+yywrap (yyscan_t yyscanner) {
+  return 1;
+}
+
+
+static unsigned char *
+rdql_copy_name(rasqal_query *rq, const unsigned char *text, size_t len) {
+  size_t dest_len=0;
+  unsigned char *s;
+
+  s=rasqal_escaped_name_to_utf8_string((unsigned char*)text, len,
+                                       &dest_len,
+                                       (raptor_simple_message_handler)rdql_syntax_error, rq);
+  if(!s)
+    return s;
+
+  if(!raptor_xml_name_check(s, dest_len, 11))
+    rdql_syntax_warning(rq, "Invalid RDQL name \"%s\"", s);
+
+  return s;
+}
+
+
+static unsigned char *
+rdql_copy_qname(rasqal_query *rq, const unsigned char *text, size_t len) {
+  unsigned char *p;
+  size_t dest_len=0;
+  unsigned char *s;
+  
+  s=rasqal_escaped_name_to_utf8_string((unsigned char*)text, len,
+                                       &dest_len,
+                                       (raptor_simple_message_handler)rdql_syntax_error, rq);
+  if(!s)
+    return s;
+
+  p=(unsigned char*)strchr((const char*)s, ':');
+  if(!raptor_xml_name_check(s, p-s, 11))
+    rdql_syntax_warning(rq, "Invalid RDQL name \"%s\"", s);
+  if(!raptor_xml_name_check(p+1, dest_len-((p+1)-s), 11))
+    rdql_syntax_warning(rq, "Invalid RDQL name \"%s\"", p+1);
+
+  return s;
+}
+
+
+static int
+rdql_copy_regex_token(rasqal_query* rq, YYSTYPE* lval, unsigned char delim) {
+  rasqal_rdql_query_language *rqe=(rasqal_rdql_query_language*)rq->context;
+  yyscan_t yyscanner=rqe->scanner;
+  unsigned int ind=0;
+  size_t buffer_len=0;
+  unsigned char *buffer=NULL;
+  size_t flags_len=0;
+  unsigned char *flags=NULL;
+  int c;
+
+  if(delim == 'm') {
+    /* Handle pattern literal m/foo/ */
+    c=INPUT_FN(yyscanner);
+    if(c == EOF) {
+      rdql_syntax_error(rq, "RDQL syntax error - EOF in regex");
+      return 1;
+    }
+    delim=(unsigned char)c;
+  }
+
+  while((c=INPUT_FN(yyscanner)) && c != EOF && c != delim) {
+    /* May add 2 chars - \' */
+    if(ind+2 > buffer_len) {
+      unsigned char *new_buffer;
+      size_t new_buffer_len=buffer_len <<1;
+
+      if(new_buffer_len<10)
+        new_buffer_len=10;
+      new_buffer=(unsigned char *)RASQAL_CALLOC(cstring, 1, new_buffer_len+1);
+      if(buffer_len) {
+        strncpy((char*)new_buffer, (const char*)buffer, buffer_len);
+        RASQAL_FREE(cstring, buffer);
+      }
+      buffer=new_buffer;
+      buffer_len=new_buffer_len;
+    }
+    buffer[ind++]=c;
+    if(c == '\\') {
+      c=INPUT_FN(yyscanner);
+      buffer[ind++]=c;
+    }
+  }
+
+  if(!buffer) {
+    buffer_len=0;
+    buffer=(unsigned char *)RASQAL_CALLOC(cstring, 1, buffer_len+1);
+  }
+  buffer[ind]='\0';
+
+  if(c == EOF) {
+    rdql_syntax_error(rq, "RDQL syntax error - EOF in regex");
+    return 1;
+  }
+
+  /* flags */
+  ind=0;
+  while((c=INPUT_FN(yyscanner)) && c != EOF && isalpha(c)) {
+    if(ind+1 > flags_len) {
+      unsigned char *new_flags;
+      size_t new_flags_len=flags_len + 5;
+
+      if(new_flags_len<5)
+        new_flags_len=5;
+      new_flags=(unsigned char *)RASQAL_CALLOC(cstring, 1, new_flags_len+1);
+      if(flags_len) {
+        strncpy((char*)new_flags, (const char*)flags, flags_len);
+        RASQAL_FREE(cstring, flags);
+      }
+      flags=new_flags;
+      flags_len=new_flags_len;
+    }
+    flags[ind++]=c;
+  }
+  if(flags)
+    flags[ind]='\0';
+
+  lval->literal=rasqal_new_pattern_literal(rq->world, buffer, (const char*)flags);
+  return 0;
+}
+
+
+static int
+rdql_copy_string_token(rasqal_query* rq, YYSTYPE* lval,
+                       const unsigned char *text, size_t len, int delim) {
+  unsigned int i;
+  const unsigned char *s;
+  unsigned char *d;
+  unsigned char *string=(unsigned char *)RASQAL_MALLOC(cstring, len+1);
+  char *language=NULL;
+  unsigned char *dt=NULL;
+  raptor_uri *dt_uri=NULL;
+  unsigned char *dt_qname=NULL;
+
+  for(s=text, d=string, i=0; i<len; s++, i++) {
+    unsigned char c=*s;
+
+    if(c == '\\' ) {
+      s++; i++;
+      c=*s;
+      if(c == 'n')
+        *d++= '\n';
+      else if(c == 'r')
+        *d++= '\r';
+      else if(c == 't')
+        *d++= '\t';
+      else if(c == '\\' || c == delim)
+        *d++=c;
+      else if (c == 'u' || c == 'U') {
+        int ulen=(c == 'u') ? 4 : 8;
+        unsigned long unichar=0;
+        int n;
+        
+        s++; i++;
+        if(i+ulen > len) {
+          printf("\\%c over end of line", c);
+          RASQAL_FREE(cstring, string);
+          return 1;
+        }
+        
+        n=sscanf((const char*)s, ((ulen == 4) ? "%04lx" : "%08lx"), &unichar);
+        if(n != 1) {
+          rdql_syntax_error(rq, "RDQL syntax error - Illegal Unicode escape '%c%s...'", c, s);
+          RASQAL_FREE(cstring, string);
+          return 1;
+        }
+
+        s+= ulen-1;
+        i+= ulen-1;
+        
+        if(unichar > 0x10ffff) {
+          rdql_syntax_error(rq, "RDQL syntax error - Illegal Unicode character with code point #x%lX.", unichar);
+          RASQAL_FREE(cstring, string);
+          return 1;
+        }
+          
+        d+=raptor_unicode_char_to_utf8(unichar, d);
+      } else {
+        /* Ignore \x where x isn't the one of: \n \r \t \\ (delim) \u \U */
+        rdql_syntax_warning(rq, "Unknown RDQL string escape \\%c in \"%s\"", c, text);
+        *d++=c;
+      }
+    } else if(c== delim) {
+      *d++='\0';
+
+      /* skip delim */
+      s++; i++;
+
+      c=*s++; i++;
+      if(c=='@') {
+        language=(char*)d;
+        while(i<=len) {
+          c=*s++; i++;
+          if(!isalpha(c) && !isdigit(c) && c != '-')
+            break;
+          *d++=c;
+        }
+        *d++='\0';
+      }
+      if(c=='^') {
+        /* skip second char of ^^ */
+        s++; i++;
+
+        dt=d;
+        while(i++<=len)
+          *d++=*s++;
+        /* *d='\0' below */
+      } else if (language)
+        *d='\0';
+      
+      break;
+   } else
+    *d++=c;
+  } /* end of for */
+
+  *d='\0';
+
+  if(language) {
+    char *new_language=(char *)RASQAL_MALLOC(cstring, strlen((const char*)language)+1);
+    strcpy(new_language, language);
+    language=new_language;
+  }
+  
+  if(dt) {
+    /* dt can be a URI or qname */
+    if(*dt == '<') {
+      dt[strlen((const char*)dt)-1]='\0';
+#ifdef RAPTOR_V2_AVAILABLE
+      dt_uri = raptor_new_uri_v2(rq->world->raptor_world_ptr, dt+1);
+#else
+      dt_uri = raptor_new_uri(dt+1);
+#endif
+    } else {
+      size_t dt_qname_len=strlen((const char*)dt);
+      
+      if(!raptor_xml_name_check(dt, dt_qname_len, 11))
+        rdql_syntax_warning(rq, "Invalid RDQL name \"%s\"", dt);
+      
+      /* the qname is expanded later */
+      dt_qname=(unsigned char *)RASQAL_MALLOC(cstring, dt_qname_len+1);
+      strcpy((char*)dt_qname, (const char*)dt);
+    }
+  }
+
+#if RASQAL_DEBUG >3
+  fprintf(stderr, "string='%s', language='%s'\n", 
+          string, (language ? language : ""));
+  fprintf(stderr, "dt uri='%s',qname='%s'\n",
+          (dt_uri ? (const char*)raptor_uri_as_string(dt_uri) : ""),
+          (dt_qname ? (const char*)dt_qname : ""));
+#endif
+
+  lval->literal=rasqal_new_string_literal(rq->world, string, language, dt_uri, dt_qname);
+
+  return 0;
+}
+
+
+static int
+rdql_skip_c_comment(rasqal_query *rq) {
+  rasqal_rdql_query_language *rqe=(rasqal_rdql_query_language*)rq->context;
+  yyscan_t yyscanner=rqe->scanner;
+  int lines=0;
+  int c;
+  
+  while(1) {
+    while ((c=INPUT_FN(yyscanner)) != '*' && c!= EOF) {
+      if(c == '\r' || c == '\n')
+        lines++;
+    }
+    if( c == '*') {
+      while ((c=INPUT_FN(yyscanner)) == '*') {
+        if(c == '\r' || c == '\n')
+          lines++;
+      }
+
+      if(c == '/')
+        break;
+    }
+    if (c == EOF) {
+      rdql_syntax_error(rq, "RDQL syntax error - EOF in comment");
+      lines= -1;
+      break;
+    }
+  }
+  return lines;
+}
+
+
+/*
+ * rdql_lexer_fatal_error:
+ *
+ * INTERNAL - replacement for the generated error handler.
+ * Uses rasqal_query_fatal_error() when possible.
+ */
+static void rdql_lexer_fatal_error(yyconst char *msg, yyscan_t yyscanner)
+{
+  rasqal_query *rq=NULL;
+
+  if(yyscanner)
+    rq=(rasqal_query *)rdql_lexer_get_extra(yyscanner);
+
+  if(rq) {
+    /* avoid "format not a string literal and no format arguments" warning with %s */
+    rq->failed=1;
+    rasqal_log_error_simple(rq->world, RAPTOR_LOG_LEVEL_FATAL,
+                            &rq->locator, "%s", msg); 
+  } else
+    (void)fprintf(stderr, "%s\n", msg);
+
+  abort();
+}
+
+
+/* Define LEXER_ALLOC_TRACKING to enable allocated memory tracking
+ * - fixes lexer memory leak when ensure_buffer_stack fails
+ */
+
+#ifdef LEXER_ALLOC_TRACKING
+typedef struct {
+  /* Number of void* slots allocated */
+  int lexer_allocs_size;
+  /* Allocted void* slots follow in memory after this header */
+} lexer_alloc_tracker_header;
+
+/* Initial alloc tracker slot array size - 2 seems to be enough for almost all cases */
+static const int initial_lexer_allocs_size=2;
+#endif
+
+
+/*
+ * rdql_lexer_cleanup:
+ * @yyscanner:
+ *
+ * INTERNAL - Clean up unfreed lexer allocs if LEXER_ALLOC_TRACKING is enabled.
+ */
+static void rdql_lexer_cleanup(yyscan_t yyscanner)
+{
+#ifdef LEXER_ALLOC_TRACKING
+  rasqal_query *rq;
+  lexer_alloc_tracker_header *tracker;
+  void **lexer_allocs;
+  int i;
+
+  if(!yyscanner)
+    return;
+
+  rq=(rasqal_query *)rdql_lexer_get_extra(yyscanner);
+  if(!rq)
+    return;
+
+  tracker=(lexer_alloc_tracker_header *)rq->lexer_user_data;
+  if(!tracker)
+    return;
+  lexer_allocs=(void**)&tracker[1];
+
+  for(i=0; i<tracker->lexer_allocs_size; ++i) {
+    if(lexer_allocs[i])
+      free(lexer_allocs[i]);
+    lexer_allocs[i]=NULL;
+  }
+  free(rq->lexer_user_data);
+  rq->lexer_user_data=NULL;
+#endif
+}
+
+
+/*
+ * rdql_lexer_alloc:
+ * @size
+ * @yyscanner
+ *
+ * INTERNAL - alloc replacement.
+ * Tracks allocated cells if LEXER_ALLOC_TRACKING is enabled.
+ */
+void *rdql_lexer_alloc(yy_size_t size, yyscan_t yyscanner)
+{
+#ifdef LEXER_ALLOC_TRACKING
+  rasqal_query *rq;
+  lexer_alloc_tracker_header *tracker;
+  void **lexer_allocs;
+  int i;
+  void *ptr;
+
+  /* yyscanner not initialized -> probably initializing yyscanner itself
+   * -> just malloc without tracking
+   */
+  if(!yyscanner)
+    return malloc(size);
+
+  rq=(rasqal_query *)rdql_lexer_get_extra(yyscanner);
+  if(!rq)
+    YY_FATAL_ERROR("lexer_alloc: yyscanner extra not initialized");
+
+  /* try to allocate tracker if it does not exist */
+  tracker=(lexer_alloc_tracker_header *)rq->lexer_user_data;
+  if(!tracker) {
+    /* allocate tracker header + array of void* slots */
+    tracker=(lexer_alloc_tracker_header*)calloc(1, sizeof(lexer_alloc_tracker_header)+initial_lexer_allocs_size*sizeof(void*));
+    if(!tracker)
+      YY_FATAL_ERROR("lexer_alloc: cannot allocate tracker");
+    tracker->lexer_allocs_size=initial_lexer_allocs_size;
+    rq->lexer_user_data=(void *)tracker;
+  }
+  lexer_allocs=(void**)&tracker[1];
+
+  /* allocate memory */
+  ptr=malloc(size);
+  
+  /* find a free slot for ptr */
+  for(i=0; i<tracker->lexer_allocs_size; ++i) {
+    if(!lexer_allocs[i]) {
+      lexer_allocs[i]=ptr;
+      break;
+    }
+  }
+
+  /* no free slots -> grow tracker slot array */
+  if(i>=tracker->lexer_allocs_size) {
+    int j;
+    void **dest;
+    tracker=(lexer_alloc_tracker_header*)calloc(1, sizeof(lexer_alloc_tracker_header)+i*2*sizeof(void*));
+    if(!tracker) {
+      if(ptr)
+        free(ptr);
+      YY_FATAL_ERROR("lexer_alloc: cannot grow tracker");
+    }
+    tracker->lexer_allocs_size=i*2;
+    
+    /* copy data from old tracker */
+    dest=(void**)&tracker[1];
+    for(j=0; j<i; ++j) {
+      dest[j]=lexer_allocs[j];
+    }
+    
+    /* set new item to first free slot */
+    dest[j]=ptr;
+
+    /* free old tracker and replace with new one */
+    free(rq->lexer_user_data);
+    rq->lexer_user_data=tracker;
+  }
+
+  return ptr;
+#else
+  return malloc(size);
+#endif
+}
+
+
+/*
+ * rdql_lexer_realloc:
+ *
+ * INTERNAL - realloc replacement
+ * Tracks allocated cells if LEXER_ALLOC_TRACKING is enabled.
+ */
+void *rdql_lexer_realloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
+{
+#ifdef LEXER_ALLOC_TRACKING
+  rasqal_query *rq;
+  lexer_alloc_tracker_header *tracker;
+  void **lexer_allocs;
+  int i;
+  void *newptr;
+
+  if(!yyscanner)
+    YY_FATAL_ERROR("lexer_realloc: yyscanner not initialized");
+
+  rq=(rasqal_query *)rdql_lexer_get_extra(yyscanner);
+  if(!rq)
+    YY_FATAL_ERROR("lexer_realloc: yyscanner extra not initialized");
+
+  tracker=(lexer_alloc_tracker_header *)rq->lexer_user_data;
+  if(!tracker)
+    YY_FATAL_ERROR("lexer_realloc: no alloc tracker");
+  lexer_allocs=(void**)&tracker[1];
+
+  /* find the old slot for ptr */
+  for(i=0; i<tracker->lexer_allocs_size; ++i) {
+    if(lexer_allocs[i]==ptr)
+      break;
+  }
+
+  /* no old slot -> error */  
+  if(i>=tracker->lexer_allocs_size)
+    YY_FATAL_ERROR("lexer_realloc: cell not in tracker");
+
+  /* realloc */
+  newptr=realloc((char*)ptr, size);
+
+  /* replace entry in tracker */
+  lexer_allocs[i]=newptr;
+
+  return newptr;
+#else
+  return realloc((char*)ptr, size);
+#endif
+}
+
+
+/*
+ * rdql_lexer_free:
+ *
+ * INTERNAL - free replacement.
+ * Checks for NULL pointer to be freed unlike the default lexer free function.
+ * Tracks allocated cells if LEXER_ALLOC_TRACKING is enabled.
+ */
+void rdql_lexer_free(void *ptr, yyscan_t yyscanner)
+{
+#ifdef LEXER_ALLOC_TRACKING
+  rasqal_query *rq;
+  lexer_alloc_tracker_header *tracker;
+  void **lexer_allocs;
+  int i;
+
+  /* do not free NULL */
+  if(!ptr)
+    return;
+
+  /* free ptr even if we would encounter an error */
+  free(ptr);
+
+  /* yyscanner is allocated with rdql_lexer_alloc() but it's never stored in the tracker
+   * - we need yyscanner to access the tracker */
+  if(!yyscanner || ptr==yyscanner)
+    return;
+
+  rq=(rasqal_query *)rdql_lexer_get_extra(yyscanner);
+  if(!rq)
+    return;
+
+  tracker=(lexer_alloc_tracker_header *)rq->lexer_user_data;
+  if(!tracker)
+    return;
+  lexer_allocs=(void**)&tracker[1];
+
+  /* find the slot for ptr */
+  for(i=0; i<tracker->lexer_allocs_size; ++i) {
+    if(lexer_allocs[i]==ptr)
+      break;
+  }
+
+  /* no slot -> error */  
+  if(i>=tracker->lexer_allocs_size)
+    YY_FATAL_ERROR("lexer_free: cell not in tracker");
+
+  /* remove entry from tracker */
+  lexer_allocs[i]=NULL;
+#else
+  if(ptr)
+    free(ptr);
+#endif
+}
+
+
+#ifdef RASQAL_DEBUG
+
+const char *
+rdql_token_print(rasqal_world* world, int token, YYSTYPE *lval)
+{
+  static char buffer[2048];
+
+  if(!token)
+    return "<<EOF>>";
+  
+  switch(token) {
+    case SELECT:
+      return "SELECT";
+
+    case SOURCE:
+      return "SOURCE";
+
+    case FROM:
+      return "FROM";
+
+    case WHERE:
+      return "WHERE";
+
+    case AND:
+      return "AND";
+
+    case FOR:
+      return "FOR";
+
+    case ',':
+      return ",";
+
+    case '(':
+      return "(";
+
+    case ')':
+      return "(";
+
+    case '?':
+      return "?";
+
+    case USING:
+      return "USING";
+
+    case SC_AND:
+      return "SC_AND";
+
+    case SC_OR:
+      return "SC_OR";
+
+    case STR_NMATCH:
+      return "STR_NMATCH";
+
+    case STR_MATCH:
+      return "STR_MATCH";
+
+    case STR_NE:
+      return "STR_NE";
+
+    case STR_EQ:
+      return "STR_EQ";
+
+    case GE:
+      return "GE";
+
+    case LE:
+      return "LE";
+
+    case GT:
+      return "GT";
+
+    case LT:
+      return "LT";
+
+    case NEQ:
+      return "NEQ";
+
+    case EQ:
+      return "EQ";
+
+    case '%':
+      return "%";
+
+    case '/':
+      return "/";
+
+    case '*':
+      return "*";
+
+    case '-':
+      return "-";
+
+    case '+':
+      return "+";
+
+    case '!':
+      return "!";
+
+    case '~':
+      return "~";
+
+    case INTEGER_LITERAL:
+      sprintf(buffer, "INTEGER_LITERAL(%d)", lval->literal->value.integer);
+      return buffer;
+
+    case FLOATING_POINT_LITERAL:
+      sprintf(buffer, "FLOATING_POINT_LITERAL(%g)", lval->floating);
+      return buffer;
+
+    case STRING_LITERAL:
+      if(lval->literal->language) {
+        if(lval->literal->datatype)
+          sprintf(buffer, "STRING_LITERAL(\"%s\"@%s^^%s)",
+                  lval->literal->string, lval->literal->language,
+#ifdef RAPTOR_V2_AVAILABLE
+                  raptor_uri_as_string_v2(world->raptor_world_ptr, lval->literal->datatype)
+#else                  
+                  raptor_uri_as_string(lval->literal->datatype)
+#endif
+                  );
+        else
+          sprintf(buffer, "STRING_LITERAL(\"%s\"@%s)",
+                  lval->literal->string, lval->literal->language);
+      } else {
+        if(lval->literal->datatype)
+          sprintf(buffer, "STRING_LITERAL(\"%s\"^^%s)", 
+                  lval->literal->string,
+#ifdef RAPTOR_V2_AVAILABLE
+                  raptor_uri_as_string_v2(world->raptor_world_ptr, lval->literal->datatype)
+#else                  
+                  raptor_uri_as_string(lval->literal->datatype)
+#endif
+                  );
+        else
+          sprintf(buffer, "STRING_LITERAL(\"%s\")", lval->literal->string);
+      }
+      return buffer;
+
+    case PATTERN_LITERAL:
+      sprintf(buffer, "PATTERN_LITERAL(%s,%s)", lval->literal->string,
+              (lval->literal->flags ? (char*)lval->literal->flags : "-"));
+      return buffer;
+
+    case BOOLEAN_LITERAL:
+      return (lval->literal->value.integer ? "BOOLEAN_LITERAL(true)" : "BOOLEAN_LITERAL(false)");
+
+    case NULL_LITERAL:
+      return "NULL_LITERAL";
+
+    case URI_LITERAL:
+      sprintf(buffer, "URI_LITERAL(%s)",
+#ifdef RAPTOR_V2_AVAILABLE
+                  raptor_uri_as_string_v2(world->raptor_world_ptr, lval->uri)
+#else                  
+                  raptor_uri_as_string(lval->uri)
+#endif
+
+              );
+      return buffer;
+
+    case QNAME_LITERAL:
+      sprintf(buffer, "QNAME_LITERAL(%s)", lval->name);
+      return buffer;
+
+    case IDENTIFIER:
+      sprintf(buffer, "IDENTIFIER(%s)", lval->name);
+      return buffer;
+
+   default:
+     RASQAL_DEBUG2("UNKNOWN token %d - add a new case\n", token);
+     abort();
+  }
+}
+#endif
+
+
+
+#ifdef STANDALONE
+static void
+rdql_token_free(rasqal_world* world, int token, YYSTYPE *lval)
+{
+  if(!token)
+    return;
+  
+  switch(token) {
+    case STRING_LITERAL:
+    case PATTERN_LITERAL:
+      rasqal_free_literal(lval->literal);
+      break;
+    case URI_LITERAL:
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_free_uri_v2(world->raptor_world_ptr, lval->uri);
+#else    
+      raptor_free_uri(lval->uri);
+#endif
+      break;
+    case IDENTIFIER:
+      RASQAL_FREE(cstring, lval->name);
+      break;
+    case QNAME_LITERAL:
+      if(lval->name)
+        RASQAL_FREE(cstring, lval->name);
+      break;
+    default:
+      break;
+  }
+}
+
+
+#define FILE_READ_BUF_SIZE 2048
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program=rasqal_basename(argv[0]);
+  char *query_string=NULL;
+  rasqal_query rq;
+  rasqal_rdql_query_language rdql;
+  yyscan_t scanner;
+  int token=EOF;
+  YYSTYPE lval;
+  const unsigned char *uri_string;
+  const char *filename=NULL;
+  char *buf=NULL;
+  size_t len;
+  void *buffer;
+  rasqal_world *world;
+
+  world=rasqal_new_world();
+  if(!world || rasqal_world_open(world))
+    exit(1);
+
+  if(argc > 1) {
+    FILE *fh;
+    query_string=(char*)RASQAL_CALLOC(cstring, FILE_READ_BUF_SIZE, 1);
+    filename=argv[1];
+    fh=fopen(filename, "r");
+    if(fh) {
+      fread(query_string, FILE_READ_BUF_SIZE, 1, fh);
+      fclose(fh);
+    } else {
+      fprintf(stderr, "%s: Cannot open file %s - %s\n", program, filename,
+              strerror(errno));
+      exit(1);
+    }
+  } else {
+    filename="<stdin>";
+    query_string=(char*)RASQAL_CALLOC(cstring, FILE_READ_BUF_SIZE, 1);
+    fread(query_string, FILE_READ_BUF_SIZE, 1, stdin);
+  }
+
+  memset(&rq, 0, sizeof(rasqal_query));
+  rq.world=world;
+  memset(&rdql, 0, sizeof(rasqal_rdql_query_language));
+
+  yylex_init(&rdql.scanner);
+  scanner=rdql.scanner;
+
+#if 0
+  /* set
+   *   %option debug 
+   * above first before enabling this
+   */
+  rdql_lexer_set_debug(1, scanner);
+#endif
+  
+  len= strlen((const char*)query_string);
+  buf= (char *)RASQAL_MALLOC(cstring, len+3);
+  strncpy(buf, query_string, len);
+  buf[len]= ' ';
+  buf[len+1]= buf[len+2]='\0'; /* YY_END_OF_BUFFER_CHAR; */
+  buffer= rdql_lexer__scan_buffer(buf, len+3, scanner);
+
+  rdql_lexer_set_extra(&rq, scanner);
+
+  /* Initialise enough of the rasqal_query and locator to get error messages */
+  rq.context=&rdql;
+  rdql.lineno=1;
+  rq.locator.file=filename;
+  rq.locator.column= -1;
+
+  uri_string=raptor_uri_filename_to_uri_string(filename);
+#ifdef RAPTOR_V2_AVAILABLE
+  rq.base_uri = raptor_new_uri_v2(world->raptor_world_ptr, uri_string);
+#else
+  rq.base_uri = raptor_new_uri(uri_string);
+#endif
+  raptor_free_memory((void*)uri_string);
+
+  while(1) {
+    memset(&lval, 0, sizeof(YYSTYPE));
+    if(rdql_lexer_get_text(scanner) != NULL)
+      printf("yyinput '%s'\n", rdql_lexer_get_text(scanner));
+    token=yylex(&lval, scanner);
+#ifdef RASQAL_DEBUG
+    printf("token %s\n", rdql_token_print(world, token, &lval));
+#else
+    printf("token %d\n", token);
+#endif
+    rdql_token_free(world, token, &lval);
+    if(!token || token == EOF)
+      break;
+  }
+
+  if(buf)
+    RASQAL_FREE(cstring, buf);
+  
+  yylex_destroy(scanner);
+
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_free_uri_v2(world->raptor_world_ptr, rq.base_uri);
+#else
+  raptor_free_uri(rq.base_uri);
+#endif
+
+  RASQAL_FREE(cstring, query_string);
+
+  rasqal_free_world(world);
+
+  if(rq.failed)
+    return 1;
+ 
+  return 0;
+}
+#endif
diff --git a/src/rasqal/rdql_parser.y b/src/rasqal/rdql_parser.y
new file mode 100644
index 0000000..fe75a19
--- /dev/null
+++ b/src/rasqal/rdql_parser.y
@@ -0,0 +1,937 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * rdql_parser.y - Rasqal RDQL parser - over tokens from rdql grammar lexer
+ *
+ * Copyright (C) 2003-2008, David Beckett http://purl.org/net/dajobe/
+ * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * 
+ */
+
+%{
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <rasqal.h>
+#include <rasqal_internal.h>
+
+#include <rdql_parser.h>
+
+#define YY_DECL int rdql_lexer_lex (YYSTYPE *rdql_parser_lval, yyscan_t yyscanner)
+#define YY_NO_UNISTD_H 1
+#include <rdql_lexer.h>
+
+#include <rdql_common.h>
+
+
+/* Make verbose error messages for syntax errors */
+/*
+#ifdef RASQAL_DEBUG
+#define YYERROR_VERBOSE 1
+#endif
+*/
+#define YYERROR_VERBOSE 1
+
+/* Slow down the grammar operation and watch it work */
+#if RASQAL_DEBUG > 2
+#define YYDEBUG 1
+#endif
+
+/* the lexer does not seem to track this */
+#undef RASQAL_RDQL_USE_ERROR_COLUMNS
+
+/* Missing rdql_lexer.c/h prototypes */
+int rdql_lexer_get_column(yyscan_t yyscanner);
+/* Not used here */
+/* void rdql_lexer_set_column(int  column_no , yyscan_t yyscanner);*/
+
+
+/* What the lexer wants */
+extern int rdql_lexer_lex (YYSTYPE *rdql_parser_lval, yyscan_t scanner);
+#define YYLEX_PARAM ((rasqal_rdql_query_language*)(((rasqal_query*)rq)->context))->scanner
+
+/* Pure parser argument (a void*) */
+#define YYPARSE_PARAM rq
+
+/* Make the yyerror below use the rdf_parser */
+#undef yyerror
+#define yyerror(message) rdql_query_error((rasqal_query*)rq, message)
+
+/* Make lex/yacc interface as small as possible */
+#undef yylex
+#define yylex rdql_lexer_lex
+
+
+static int rdql_parse(rasqal_query* rq);
+static void rdql_query_error(rasqal_query* rq, const char *message);
+
+%}
+
+
+/* directives */
+
+
+%pure-parser
+
+
+/* Interface between lexer and parser */
+%union {
+  raptor_sequence *seq;
+  rasqal_variable *variable;
+  rasqal_literal *literal;
+  rasqal_triple *triple;
+  rasqal_expression *expr;
+  double floating;
+  raptor_uri *uri;
+  unsigned char *name;
+}
+
+
+/*
+ * No conflicts
+ */
+%expect 0
+
+
+/* word symbols */
+%token SELECT SOURCE FROM WHERE AND FOR
+
+/* expression delimitors */
+
+%token ',' '(' ')'
+%token '?'
+%token USING
+
+
+/* SC booleans */
+%left SC_OR "||"
+%left SC_AND "&&"
+
+/* string operations */
+%left STR_EQ "eq"
+%left STR_NE "ne"
+%left STR_MATCH "=~"
+%left STR_NMATCH "!~"
+
+/* operations */
+%left EQ "="
+%left NEQ "!="
+%left LT "<"
+%left GT ">"
+%left LE "<="
+%left GE ">="
+
+/* arithmetic operations */
+%left '+' '-' '*' '/' '%'
+
+/* unary operations */
+%left '~' '!'
+
+/* literals */
+%token <literal> FLOATING_POINT_LITERAL "floating point literal"
+%token <literal> STRING_LITERAL "string literal"
+%token <literal> INTEGER_LITERAL "integer literal"
+%token <literal> PATTERN_LITERAL "pattern literal"
+%token <literal> BOOLEAN_LITERAL "boolean literal"
+%token <literal> NULL_LITERAL "null"
+%token <uri> URI_LITERAL "URI literal"
+%token <name> QNAME_LITERAL "QName literal"
+
+%token <name> IDENTIFIER "identifier"
+
+
+%type <seq> SelectClause SourceClause UsingClause
+%type <seq> VarList TriplePatternList PrefixDeclList URIList
+
+%type <expr> Expression ConditionalAndExpression ValueLogical
+%type <expr> EqualityExpression RelationalExpression NumericExpression
+%type <expr> AdditiveExpression MultiplicativeExpression UnaryExpression
+%type <expr> UnaryExpressionNotPlusMinus
+%type <expr> ConstraintClause CommaAndConstraintClause
+
+%type <literal> VarOrLiteral VarOrURI
+
+%type <variable> Var
+%type <triple> TriplePattern
+%type <literal> PatternLiteral Literal
+
+%destructor {
+  if($$)
+    rasqal_free_literal($$);
+} FLOATING_POINT_LITERAL STRING_LITERAL INTEGER_LITERAL PATTERN_LITERAL BOOLEAN_LITERAL NULL_LITERAL
+
+%destructor {
+  if($$)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(((rasqal_query*)rq)->world->raptor_world_ptr, $$);
+#else    
+    raptor_free_uri($$);
+#endif
+} URI_LITERAL
+
+%destructor {
+  if($$)
+    RASQAL_FREE(cstring, $$);
+} QNAME_LITERAL IDENTIFIER
+
+%%
+
+
+Document : Query
+;
+
+
+Query : SELECT SelectClause SourceClause WHERE TriplePatternList ConstraintClause UsingClause
+{
+  ((rasqal_query*)rq)->selects=$2;
+  ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_SELECT;
+
+  if($3) {
+    int i;
+    
+    for(i=0; i < raptor_sequence_size($3); i++) {
+      raptor_uri* uri=(raptor_uri*)raptor_sequence_get_at($3, i);
+      rasqal_query_add_data_graph((rasqal_query*)rq, uri, NULL, RASQAL_DATA_GRAPH_BACKGROUND);
+    }
+    raptor_free_sequence($3);
+  }
+
+  /* ignoring $5 (sequence of triples): set in TriplePatternList to
+   * ((rasqal_query*)rq)->triples=$5; 
+   */
+
+  /* $6 (expression): ConstraintClause */
+  if($6) {
+    rasqal_rdql_query_language* rdql=(rasqal_rdql_query_language*)((rasqal_query*)rq)->context;
+    rdql->constraint_expression=$6;
+  }
+
+  /* ignoring $7 set in UsingClause ? */
+}
+;
+
+VarList : VarList ',' Var
+{
+  $$=$1;
+  raptor_sequence_push($$, $3);
+}
+| VarList Var
+{
+  $$=$1;
+  raptor_sequence_push($$, $2);
+}
+| Var
+{
+  /* The variables are freed from the rasqal_query field variables */
+  $$=raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_variable_print);
+  raptor_sequence_push($$, $1);
+}
+;
+
+
+SelectClause : VarList
+{
+  $$=$1;
+}
+| '*'
+{
+  $$=NULL;
+  ((rasqal_query*)rq)->wildcard=1;
+}
+;
+
+SourceClause : SOURCE URIList
+{
+  $$=$2;
+}
+| FROM URIList
+{
+  $$=$2;
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+/* Inlined into SourceClause: SourceSelector : URL */
+
+
+/* Jena RDQL allows optional ',' */
+TriplePatternList : TriplePatternList ',' TriplePattern
+{
+  $$=$1;
+  raptor_sequence_push($$, $3);
+}
+| TriplePatternList TriplePattern
+{
+  $$=$1;
+  raptor_sequence_push($$, $2);
+}
+| TriplePattern
+{
+  $$=((rasqal_query*)rq)->triples;
+  raptor_sequence_push($$, $1);
+}
+;
+
+/* Inlined:
+ TriplePatternClause : WHERE TriplePatternList 
+*/
+
+
+/* FIXME - maybe a better way to do this optional COMMA? */
+TriplePattern : '(' VarOrURI ',' VarOrURI ',' VarOrLiteral ')'
+{
+  $$=rasqal_new_triple($2, $4, $6);
+}
+| '(' VarOrURI VarOrURI ',' VarOrLiteral ')'
+{
+  $$=rasqal_new_triple($2, $3, $5);
+}
+| '(' VarOrURI ',' VarOrURI VarOrLiteral ')'
+{
+  $$=rasqal_new_triple($2, $4, $5);
+}
+| '(' VarOrURI VarOrURI VarOrLiteral ')'
+{
+  $$=rasqal_new_triple($2, $3, $4);
+}
+;
+
+
+/* Was:
+ConstraintClause : AND Expression ( ( ',' | AND ) Expression )*
+*/
+
+ConstraintClause : AND CommaAndConstraintClause
+{
+  $$=$2;
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+CommaAndConstraintClause : CommaAndConstraintClause ',' Expression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_AND, $1, $3);
+}
+| CommaAndConstraintClause AND Expression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_AND, $1, $3);
+}
+| Expression
+{
+  $$=$1;
+}
+;
+
+
+
+UsingClause : USING PrefixDeclList
+{
+  $$=$2;
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+PrefixDeclList : IDENTIFIER FOR URI_LITERAL ',' PrefixDeclList 
+{
+  $$=((rasqal_query*)rq)->prefixes;
+  raptor_sequence_shift($$, rasqal_new_prefix(((rasqal_query*)rq)->world, $1, $3));
+}
+| IDENTIFIER FOR URI_LITERAL PrefixDeclList 
+{
+  $$=((rasqal_query*)rq)->prefixes;
+  raptor_sequence_shift($$, rasqal_new_prefix(((rasqal_query*)rq)->world, $1, $3));
+}
+| IDENTIFIER FOR URI_LITERAL
+{
+  $$=((rasqal_query*)rq)->prefixes;
+  raptor_sequence_push($$, rasqal_new_prefix(((rasqal_query*)rq)->world, $1, $3));
+}
+;
+
+
+Expression : ConditionalAndExpression SC_OR Expression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_OR, $1, $3);
+}
+| ConditionalAndExpression
+{
+  $$=$1;
+}
+;
+
+ConditionalAndExpression: ValueLogical SC_AND ConditionalAndExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_AND, $1, $3);
+;
+}
+| ValueLogical
+{
+  $$=$1;
+}
+;
+
+ValueLogical : EqualityExpression STR_EQ EqualityExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_STR_EQ, $1, $3);
+}
+| EqualityExpression STR_NE EqualityExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_STR_NEQ, $1, $3);
+}
+| EqualityExpression STR_MATCH PatternLiteral
+{
+  $$=rasqal_new_string_op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_STR_MATCH, $1, $3);
+}
+| EqualityExpression STR_NMATCH PatternLiteral
+{
+  $$=rasqal_new_string_op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_STR_NMATCH, $1, $3);
+}
+| EqualityExpression
+{
+  $$=$1;
+}
+;
+
+EqualityExpression : RelationalExpression EQ RelationalExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_EQ, $1, $3);
+}
+| RelationalExpression NEQ RelationalExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_NEQ, $1, $3);
+}
+| RelationalExpression
+{
+  $$=$1;
+}
+;
+
+RelationalExpression : NumericExpression LT NumericExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_LT, $1, $3);
+}
+| NumericExpression GT NumericExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_GT, $1, $3);
+}
+| NumericExpression LE NumericExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_LE, $1, $3);
+}
+| NumericExpression GE NumericExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_GE, $1, $3);
+}
+| NumericExpression
+{
+  $$=$1;
+}
+;
+
+NumericExpression : AdditiveExpression
+{
+  $$=$1;
+}
+;
+
+
+AdditiveExpression : MultiplicativeExpression '+' AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_PLUS, $1, $3);
+}
+| MultiplicativeExpression '-' AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_MINUS, $1, $3);
+}
+| MultiplicativeExpression
+{
+  $$=$1;
+}
+;
+
+MultiplicativeExpression : UnaryExpression '*' MultiplicativeExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_STAR, $1, $3);
+}
+| UnaryExpression '/' MultiplicativeExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_SLASH, $1, $3);
+}
+| UnaryExpression '%' MultiplicativeExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_REM, $1, $3);
+}
+| UnaryExpression
+{
+  $$=$1;
+}
+;
+
+UnaryExpression : '+' UnaryExpression 
+{
+  $$=$2;
+}
+| '-' UnaryExpression
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_UMINUS, $2);
+}
+| UnaryExpressionNotPlusMinus
+{
+  $$=$1;
+}
+;
+
+UnaryExpressionNotPlusMinus : '~' UnaryExpression
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_TILDE, $2);
+}
+| '!' UnaryExpression
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_BANG, $2);
+}
+| Var
+{
+  rasqal_literal *l=rasqal_new_variable_literal(((rasqal_query*)rq)->world, $1);
+  $$=rasqal_new_literal_expression(((rasqal_query*)rq)->world, l);
+}
+| Literal
+{
+  $$=rasqal_new_literal_expression(((rasqal_query*)rq)->world, $1);
+}
+| '(' Expression ')'
+{
+  $$=$2;
+}
+;
+
+VarOrURI : Var
+{
+  $$=rasqal_new_variable_literal(((rasqal_query*)rq)->world, $1);
+}
+| URI_LITERAL
+{
+  $$=rasqal_new_uri_literal(((rasqal_query*)rq)->world, $1);
+}
+| QNAME_LITERAL
+{
+  $$=rasqal_new_simple_literal(((rasqal_query*)rq)->world, RASQAL_LITERAL_QNAME, $1);
+}
+;
+
+VarOrLiteral : Var
+{
+  $$=rasqal_new_variable_literal(((rasqal_query*)rq)->world, $1);
+}
+| Literal
+{
+  $$=$1;
+}
+;
+
+Var : '?' IDENTIFIER
+{
+  $$=rasqal_new_variable((rasqal_query*)rq, $2, NULL);
+}
+;
+
+PatternLiteral: PATTERN_LITERAL
+{
+  $$=$1;
+}
+;
+
+Literal : URI_LITERAL
+{
+  $$=rasqal_new_uri_literal(((rasqal_query*)rq)->world, $1);
+}
+| INTEGER_LITERAL
+{
+  $$=$1;
+}
+| FLOATING_POINT_LITERAL
+{
+  $$=$1;
+}
+| STRING_LITERAL
+{
+  $$=$1;
+}
+| BOOLEAN_LITERAL
+{
+  $$=$1;
+}
+| NULL_LITERAL
+{
+  $$=$1;
+} | QNAME_LITERAL
+{
+  $$=rasqal_new_simple_literal(((rasqal_query*)rq)->world, RASQAL_LITERAL_QNAME, $1);
+}
+
+;
+
+URIList : URI_LITERAL ',' URIList
+{
+  $$=$3;
+  raptor_sequence_shift($$, $1);
+}
+| URI_LITERAL
+{
+#ifdef RAPTOR_V2_AVAILABLE
+  $$=raptor_new_sequence_with_handler_context((raptor_sequence_free_handler_v2*)raptor_free_uri_v2, (raptor_sequence_print_handler_v2*)raptor_uri_print_v2, (void*)((rasqal_query*)rq)->world->raptor_world_ptr);
+#else
+  $$=raptor_new_sequence((raptor_sequence_free_handler*)raptor_free_uri, (raptor_sequence_print_handler*)raptor_sequence_print_uri);
+#endif
+  raptor_sequence_push($$, $1);
+}
+;
+
+%%
+
+
+/* Support functions */
+
+
+/* This is declared in rdql_lexer.h but never used, so we always get
+ * a warning unless this dummy code is here.  Used once below in an error case.
+ */
+static int yy_init_globals (yyscan_t yyscanner ) { return 0; };
+
+
+
+/**
+ * rasqal_rdql_query_language_init - Initialise the RDQL query language
+ *
+ * Return value: non 0 on failure
+ **/
+static int
+rasqal_rdql_query_language_init(rasqal_query* rdf_query, const char *name) {
+  /* rasqal_rdql_query_language* rdql=(rasqal_rdql_query_language*)rdf_query->context; */
+
+  /* Initialise rdf, rdfs, owl and xsd prefixes and namespaces */
+  raptor_namespaces_start_namespace_full(rdf_query->namespaces, 
+                                         (const unsigned char*)"rdf",
+                                         (const unsigned char*)RAPTOR_RDF_MS_URI,0);
+  raptor_namespaces_start_namespace_full(rdf_query->namespaces, 
+                                         (const unsigned char*)"rdfs", 
+                                         (const unsigned char*)RAPTOR_RDF_SCHEMA_URI,0);
+  raptor_namespaces_start_namespace_full(rdf_query->namespaces,
+                                         (const unsigned char*)"xsd",
+                                         (const unsigned char*)RAPTOR_XMLSCHEMA_DATATYPES_URI, 0);
+  raptor_namespaces_start_namespace_full(rdf_query->namespaces,
+                                         (const unsigned char*)"owl",
+                                         (const unsigned char*)RAPTOR_OWL_URI, 0);
+
+  rdf_query->compare_flags = RASQAL_COMPARE_URI;
+
+  return 0;
+}
+
+
+/**
+ * rasqal_rdql_query_language_terminate - Free the RDQL query language
+ *
+ * Return value: non 0 on failure
+ **/
+static void
+rasqal_rdql_query_language_terminate(rasqal_query* rdf_query) {
+  rasqal_rdql_query_language* rdql=(rasqal_rdql_query_language*)rdf_query->context;
+
+  if(rdql->scanner_set) {
+    rdql_lexer_lex_destroy(rdql->scanner);
+    rdql->scanner_set=0;
+  }
+
+}
+
+
+static int
+rasqal_rdql_query_language_prepare(rasqal_query* rdf_query) {
+  rasqal_rdql_query_language* rdql=(rasqal_rdql_query_language*)rdf_query->context;
+  int rc;
+  rasqal_graph_pattern *gp;
+  
+  if(!rdf_query->query_string)
+    return 1;
+
+  rdql->constraint_expression=NULL;
+  
+  rc=rdql_parse(rdf_query);
+  if(rc)
+    return rc;
+
+  rdf_query->query_graph_pattern=rasqal_new_graph_pattern_from_sequence(rdf_query, NULL, RASQAL_GRAPH_PATTERN_OPERATOR_GROUP);
+
+  gp=rasqal_new_basic_graph_pattern(rdf_query, rdf_query->triples,
+                                    0, raptor_sequence_size(rdf_query->triples)-1);
+
+  rasqal_graph_pattern_add_sub_graph_pattern(rdf_query->query_graph_pattern,
+                                             gp);
+
+  /* Add a FILTER graph pattern if there is a constraint expression */
+  if(rdql->constraint_expression) {
+    rasqal_graph_pattern* cgp;
+    cgp=rasqal_new_filter_graph_pattern(rdf_query, rdql->constraint_expression);
+    if(cgp)
+      rasqal_graph_pattern_add_sub_graph_pattern(rdf_query->query_graph_pattern,
+                                                 cgp);
+    rdql->constraint_expression=NULL;
+  }
+  
+  /* Only now can we handle the prefixes and qnames */
+  if(rasqal_query_declare_prefixes(rdf_query) ||
+     rasqal_query_expand_triple_qnames(rdf_query) ||
+     rasqal_query_expand_query_constraints_qnames(rdf_query))
+    return 1;
+
+  /* RDQL: Expand 'SELECT *' */
+  if(rasqal_query_expand_wildcards(rdf_query))
+    return 1;
+  
+  return 0;
+}
+
+
+static int
+rdql_parse(rasqal_query* rq) {
+  rasqal_rdql_query_language* rqe=(rasqal_rdql_query_language*)rq->context;
+  raptor_locator *locator=&rq->locator;
+  void *buffer;
+  
+  if(!rq->query_string)
+    return yy_init_globals(NULL); /* 0 but a way to use yy_init_globals */
+
+  locator->line=1;
+  locator->column= -1; /* No column info */
+  locator->byte= -1; /* No bytes info */
+
+#if RASQAL_DEBUG > 2
+  rdql_parser_debug=1;
+#endif
+
+  rqe->lineno=1;
+
+  rdql_lexer_lex_init(&rqe->scanner);
+  rqe->scanner_set=1;
+
+  rdql_lexer_set_extra(((rasqal_query*)rq), rqe->scanner);
+
+  buffer= rdql_lexer__scan_buffer((char*)rq->query_string, rq->query_string_length, rqe->scanner);
+
+  rqe->error_count=0;
+
+  rdql_parser_parse(rq);
+
+  rdql_lexer_lex_destroy(rqe->scanner);
+  rqe->scanner_set=0;
+
+  /* Parsing failed */
+  if(rq->failed)
+    return 1;
+  
+  return 0;
+}
+
+
+void
+rdql_query_error(rasqal_query *rq, const char *msg) {
+  rasqal_rdql_query_language* rqe=(rasqal_rdql_query_language*)rq->context;
+
+  if(rqe->error_count++)
+    return;
+
+  rq->locator.line=rqe->lineno;
+#ifdef RASQAL_RDQL_USE_ERROR_COLUMNS
+  /*  rq->locator.column=rdql_lexer_get_column(yyscanner);*/
+#endif
+
+  rq->failed=1;
+  rasqal_log_error_simple(rq->world, RAPTOR_LOG_LEVEL_FATAL,
+                          &rq->locator, "%s", msg);
+
+  return;
+}
+
+
+int
+rdql_syntax_error(rasqal_query *rq, const char *message, ...)
+{
+  rasqal_rdql_query_language *rqe=(rasqal_rdql_query_language*)rq->context;
+  va_list arguments;
+
+  if(rqe->error_count++)
+    return 0;
+
+  rq->locator.line=rqe->lineno;
+#ifdef RASQAL_RDQL_USE_ERROR_COLUMNS
+  /*  rp->locator.column=rdql_lexer_get_column(yyscanner);*/
+#endif
+
+  va_start(arguments, message);
+  rq->failed=1;
+  rasqal_log_error_varargs(rq->world, RAPTOR_LOG_LEVEL_FATAL, &rq->locator,
+                           message, arguments);
+  va_end(arguments);
+
+  return 0;
+}
+
+
+int
+rdql_syntax_warning(rasqal_query *rq, const char *message, ...)
+{
+  rasqal_rdql_query_language *rqe=(rasqal_rdql_query_language*)rq->context;
+  va_list arguments;
+
+  rq->locator.line=rqe->lineno;
+#ifdef RASQAL_RDQL_USE_ERROR_COLUMNS
+  /*  rq->locator.column=rdql_lexer_get_column(yyscanner);*/
+#endif
+
+  va_start(arguments, message);
+  rasqal_log_error_varargs(rq->world, RAPTOR_LOG_LEVEL_WARNING, &rq->locator,
+                           message, arguments);
+  va_end(arguments);
+
+   return (0);
+}
+
+
+static void
+rasqal_rdql_query_language_register_factory(rasqal_query_language_factory *factory)
+{
+  factory->context_length = sizeof(rasqal_rdql_query_language);
+
+  factory->init      = rasqal_rdql_query_language_init;
+  factory->terminate = rasqal_rdql_query_language_terminate;
+  factory->prepare   = rasqal_rdql_query_language_prepare;
+}
+
+
+int
+rasqal_init_query_language_rdql(rasqal_world* world) {
+  /* http://www.w3.org/Submission/2004/SUBM-RDQL-20040109/ */
+
+  return rasqal_query_language_register_factory(world,
+                                                "rdql", 
+                                                "RDF Data Query Language (RDQL)",
+                                                NULL,
+                                                (const unsigned char*)"http://jena.hpl.hp.com/2003/07/query/RDQL";,
+                                                &rasqal_rdql_query_language_register_factory);
+}
+
+
+
+#ifdef STANDALONE
+#include <stdio.h>
+#include <locale.h>
+
+#define RDQL_FILE_BUF_SIZE 2048
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program=rasqal_basename(argv[0]);
+  char query_string[RDQL_FILE_BUF_SIZE];
+  rasqal_query *query;
+  FILE *fh;
+  int rc;
+  const char *filename=NULL;
+  raptor_uri* base_uri=NULL;
+  unsigned char *uri_string;
+  rasqal_world *world;
+
+#if RASQAL_DEBUG > 2
+  rdql_parser_debug=1;
+#endif
+
+  if(argc > 1) {
+    filename=argv[1];
+    fh = fopen(argv[1], "r");
+    if(!fh) {
+      fprintf(stderr, "%s: Cannot open file %s - %s\n", program, filename,
+              strerror(errno));
+      exit(1);
+    }
+  } else {
+    filename="<stdin>";
+    fh = stdin;
+  }
+
+  memset(query_string, 0, RDQL_FILE_BUF_SIZE);
+  rc=fread(query_string, RDQL_FILE_BUF_SIZE, 1, fh);
+  if(rc < RDQL_FILE_BUF_SIZE) {
+    if(ferror(fh)) {
+      fprintf(stderr, "%s: file '%s' read failed - %s\n",
+              program, filename, strerror(errno));
+      fclose(fh);
+      return(1);
+    }
+  }
+  
+  if(argc>1)
+    fclose(fh);
+
+  world=rasqal_new_world();
+  if(!world || rasqal_world_open(world))
+    exit(1);
+
+  query=rasqal_new_query(world, "rdql", NULL);
+
+  uri_string=raptor_uri_filename_to_uri_string(filename);
+#ifdef RAPTOR_V2_AVAILABLE
+  base_uri = raptor_new_uri_v2(world->raptor_world_ptr, uri_string);
+#else
+  base_uri = raptor_new_uri(uri_string);
+#endif
+  
+  rc=rasqal_query_prepare(query, (const unsigned char*)query_string, base_uri);
+
+  rasqal_query_print(query, stdout);
+
+  rasqal_free_query(query);
+
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_free_uri_v2(world->raptor_world_ptr, base_uri);
+#else
+  raptor_free_uri(base_uri);
+#endif
+
+  raptor_free_memory(uri_string);
+
+  rasqal_free_world(world);
+
+  return rc;
+}
+#endif
diff --git a/src/rasqal/sparql_common.h b/src/rasqal/sparql_common.h
new file mode 100644
index 0000000..f84301d
--- /dev/null
+++ b/src/rasqal/sparql_common.h
@@ -0,0 +1,63 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * sparql_common.h - SPARQL lexer/parser shared internals
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2004, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+#ifndef SPARQL_COMMON_H
+#define SPARQL_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* sparql_parser.y */
+int sparql_syntax_error(rasqal_query *rq, const char *message, ...) RASQAL_PRINTF_FORMAT(2, 3);
+int sparql_syntax_warning(rasqal_query *rq, const char *message, ...) RASQAL_PRINTF_FORMAT(2, 3);
+
+int sparql_query_lex(void);
+
+
+struct rasqal_sparql_query_language_s {
+  /* STATIC lexer */
+  yyscan_t scanner;
+
+  int scanner_set;
+
+  /* for error reporting */
+  unsigned int lineno;
+
+  /* SPARQL extended */
+  int extended;
+
+  /* count of errors in current query parse */
+  int error_count;
+};
+
+
+typedef struct rasqal_sparql_query_language_s rasqal_sparql_query_language;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/rasqal/sparql_lexer.l b/src/rasqal/sparql_lexer.l
new file mode 100644
index 0000000..cf8db7b
--- /dev/null
+++ b/src/rasqal/sparql_lexer.l
@@ -0,0 +1,1610 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * sparql_lexer.l - Rasqal SPARQL lexer - making tokens for sparql grammar generator
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ * To generate the C files from this source, rather than use the
+ * shipped sparql_lexer.c/.h needs a patched version of flex 2.5.31 such
+ * as the one available in Debian GNU/Linux.   Details below
+ * near the %option descriptions.
+ *
+ * SPARQL defined in http://www.w3.org/TR/rdf-sparql-query/
+ *   http://www.w3.org/TR/2005/WD-rdf-sparql-query-20050419/
+ *
+ * Editor's draft of above http://www.w3.org/2001/sw/DataAccess/rq23/
+ */
+
+
+/* recognise 8-bits */
+%option 8bit
+%option warn nodefault
+
+/* all symbols prefixed by this */
+%option prefix="sparql_lexer_"
+
+/* This is not needed, flex is invoked -osparql_lexer.c */
+%option outfile="sparql_lexer.c"
+
+/* Emit a C header file for prototypes
+ * Only available in flex 2.5.13 or newer.
+ * It was renamed to header-file in flex 2.5.19
+ */
+%option header-file="sparql_lexer.h"
+
+/* Do not emit #include <unistd.h>
+ * Only available in flex 2.5.7 or newer.
+ * Broken in flex 2.5.31 without patches.
+ */
+%option nounistd
+
+/* Never interactive */
+/*  No isatty() check */
+%option never-interactive
+
+/* Batch scanner */
+%option batch
+
+/* Never use yyunput */
+%option nounput
+
+/* Supply our own alloc/realloc/free functions */
+%option noyyalloc noyyrealloc noyyfree
+
+/* Re-entrant scanner */
+%option reentrant
+
+
+%x ID SPID PREF LITERAL LITERAL2
+
+  /* definitions */
+
+%{
+
+/* NOTE: These headers are NOT included here. They are inserted by fix-flex
+ * since otherwise it appears far too late in the generated C
+ */
+
+/*
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
+
+#include <rasqal.h>
+#include <rasqal_internal.h>
+
+#include <sparql_parser.h>
+
+#include <sparql_common.h>
+
+
+
+static int sparql_skip_c_comment(rasqal_query *rq);
+
+/*
+ * Extra checks beyond valid Namespaces in XML 1.1 name
+ *
+ * SPARQL_NAME_CHECK_VARNAME (token VARNAME)
+ *   No '.' allowed.
+ *   No '-' allowed.
+ *
+ * SPARQL_NAME_CHECK_PREFIX (token NCNAME_PREFIX)
+ *   No '_' allowed as the first character.
+ *   No '.' allowed as the last character.
+ *
+ * SPARQL_NAME_CHECK_NCNAME (token NCNAME)
+ *  [0-9] allowed as the first character
+ *   No '.' allowed as the first character.
+ *   No '.' allowed as the last character.
+ *
+*/
+typedef enum {
+  SPARQL_NAME_CHECK_NO_UL_FIRST  = 1,
+  SPARQL_NAME_CHECK_NO_DOT_LAST  = 2,
+  SPARQL_NAME_CHECK_NO_DOT_MINUS = 4,
+  SPARQL_NAME_CHECK_ALLOW_09_FIRST = 8,
+
+  SPARQL_NAME_CHECK_VARNAME = SPARQL_NAME_CHECK_NO_DOT_MINUS,
+  SPARQL_NAME_CHECK_PREFIX  = SPARQL_NAME_CHECK_NO_UL_FIRST | SPARQL_NAME_CHECK_NO_DOT_LAST,
+  SPARQL_NAME_CHECK_NCNAME  = SPARQL_NAME_CHECK_NO_DOT_LAST | SPARQL_NAME_CHECK_ALLOW_09_FIRST
+} sparql_name_check_flags;
+
+
+static int rasqal_sparql_name_check(unsigned char *string, size_t length, sparql_name_check_flags check_flags);
+static unsigned char *sparql_copy_name(rasqal_query *rq, const unsigned char *text, size_t len, sparql_name_check_flags check_flags);
+static raptor_uri* sparql_copy_qname(rasqal_query *rq, const unsigned char *text, size_t len);
+static int sparql_copy_string_token(rasqal_query *rq, YYSTYPE* lval, const unsigned char *text, size_t len, int delim);
+
+#ifdef RASQAL_DEBUG
+const char * sparql_token_print(rasqal_world* world, int token, YYSTYPE *lval);
+#endif
+
+int sparql_lexer_lex (YYSTYPE *sparql_parser_lval, yyscan_t yyscanner);
+#define YY_DECL int sparql_lexer_lex (YYSTYPE *sparql_parser_lval, yyscan_t yyscanner)
+
+#ifdef __cplusplus
+#define INPUT_FN yyinput
+#else
+#define INPUT_FN input
+#endif
+
+/* Remove the re-fill function since it should never be called */
+#define YY_INPUT(buf,result,max_size) { return YY_NULL; }
+
+
+/* Missing sparql_lexer.c/h prototypes */
+int sparql_lexer_get_column(yyscan_t yyscanner);
+void sparql_lexer_set_column(int  column_no , yyscan_t yyscanner);
+
+static void sparql_lexer_cleanup(yyscan_t yyscanner);
+
+#ifdef HAVE_SETJMP
+static jmp_buf sparql_lexer_fatal_error_longjmp_env;
+
+/* fatal error handler declaration */
+#define YY_FATAL_ERROR(msg) do {		\
+    sparql_lexer_fatal_error(msg, yyscanner);   \
+    longjmp(sparql_lexer_fatal_error_longjmp_env, 1);        \
+} while(0)
+#else
+#define YY_FATAL_ERROR(msg) do {		\
+    sparql_lexer_fatal_error(msg, yyscanner);   \
+    abort();                                    \
+} while(0)
+#endif
+ 
+static void sparql_lexer_fatal_error(yyconst char *msg, yyscan_t yyscanner);
+
+/* Fatal error handler that returns EOF instead of abort()/longjmp()
+ * so that parser can clean up properly */
+#define YY_FATAL_ERROR_EOF(msg) do { \
+    sparql_lexer_fatal_error(msg, yyscanner); \
+    yyterminate(); \
+} while(0)
+%}
+
+LANGUAGETOKEN [A-Za-z][-A-Z_a-z0-9]*
+
+
+/*
+ * rq23 is http://www.w3.org/2001/sw/DataAccess/rq23/
+ * CVS ID 1.420 2005/07/12 15:38:40
+ */
+
+
+/* [85] NCCHAR1p ::= [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] |
+ *   [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] |
+ *   [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] |
+ *   [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] |
+ *   [#x10000-#xEFFFF]
+ *
+ * This is an XML 1.1 NameStartChar
+ *   http://www.w3.org/TR/2004/REC-xml11-20040204/#NT-NameStartChar
+ * except
+ *   No '_' allowed.
+ */
+NCCHAR1p [A-Za-z\\\x80-\xff]
+
+/* [86] NCCHAR1 ::= NCCHAR1p | '_'
+ * This is an XML 1.1 NameStartChar
+ *   http://www.w3.org/TR/2004/REC-xml11-20040204/#NT-NameStartChar
+ */
+NCCHAR1 [A-Za-z\\\x80-\xff_]
+
+NCCHAR2 [A-Za-z\\\x80-\xff_0-9]
+
+/* [87]  VARNAME ::= ( NCCHAR1 | _ ) 
+ *   ( NCCHAR1 | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )*
+ *
+ * This is an Namespaces in XML 1.1 Name except:
+ *   No '.' allowed.
+ *   No '-' allowed.
+ */
+VARNAME ({NCCHAR1}|[0-9])({NCCHAR1}|[0-9])*
+
+/* [88]  NCCHAR ::= 
+ *   NCCHAR1 | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
+ *
+ * This is XML 1.1 NameChar
+ *   http://www.w3.org/TR/2004/REC-xml11-20040204/#NT-NameChar
+ * except:
+ *   No '.' allowed.
+ */
+NCCHAR {NCCHAR1}|"-"|[0-9]
+
+/* [89]  NCNAME_PREFIX ::= NCCHAR1p ((NCCHAR|".")* NCCHAR)?
+ *
+ * This is an Namespaces in XML 1.1 Name except:
+ *   No '_' allowed as the first character.
+ *   No '.' allowed as the last character.
+ */
+NCNAME_PREFIX {NCCHAR1p}(({NCCHAR}|".")*{NCCHAR})?
+
+/* [90]  NCNAME ::= NCCHAR1 ((NCCHAR|".")* NCCHAR)?
+ *
+ * This is an Namespaces in XML 1.1 Name except:
+ *   No '.' allowed as the last character.
+ */
+NCNAME {NCCHAR1}(({NCCHAR}|".")*{NCCHAR})?
+
+/* SPARQL allows [0-9] after a : in the 
+ * W3C Candidate Recommendation 14 June 2007 
+ * as an at risk feature that may be removed.
+ */
+NCNAME2 {NCCHAR2}(({NCCHAR}|".")*{NCCHAR})?
+
+/* rq23 [67] QNAME_NS ::= NCNAME_PREFIX? ':'
+ * Inlined into in rule <PREF>{NCNAME_PREFIX}":" below 
+ */
+
+/* rq23 [68] QNAME ::= NCNAME_PREFIX? ':' NCNAME? */
+QNAME {NCNAME_PREFIX}?":"{NCNAME2}?
+
+/* rq23 [69] BNODE_LABEL (renamed to BNAME) ::= '_:' NCNAME */
+BNAME "_:"{NCNAME2}
+
+/* a blank node name written inside a URI - this is an illegal
+ * URI form and for convienence 
+ */
+BNAME2 "<_:"{NCNAME2}">"
+
+/* The initial char conditions are to ensure this doesn't grab < or <= 
+ * as operators.  starting with <_: is caught by BNAME2 above.
+ **/
+QUOTEDURI \<[^><= ][^>]*\>|"<>"
+
+INTEGER [0-9]+
+DECIMAL [0-9]+"."[0-9]*|"."[0-9]+
+DOUBLE [0-9]+"."[0-9]*{EXPONENT}|"."([0-9])+{EXPONENT}|([0-9])+{EXPONENT}
+EXPONENT [eE][+-]?[0-9]+
+
+
+%%
+  /* rules */
+
+%{
+
+  int c;
+  rasqal_query *rq=(rasqal_query*)yyextra;
+  rasqal_sparql_query_language *rqe=(rasqal_sparql_query_language*)rq->context;
+
+#ifdef HAVE_SETJMP
+  if(setjmp(sparql_lexer_fatal_error_longjmp_env))
+    return 1;
+#endif
+  
+%}
+
+"//"[^\r\n]*(\r\n|\r|\n)	{ /* C++ comment */
+        rqe->lineno++;
+}
+
+"/*"	{ int lines=sparql_skip_c_comment(rq);
+          if(lines < 0)
+            yyterminate();
+          rqe->lineno += lines;
+        }
+
+\r\n|\r|\n     { rqe->lineno++; }
+
+[\ \t\v]+   { /* eat up other whitespace */
+	;
+}
+
+[Ss][Ee][Ll][Ee][Cc][Tt] { return SELECT; }
+[Ff][Rr][Oo][Mm] { return FROM; }
+[Ww][Hh][Ee][Rr][Ee] { return WHERE; }
+[Pp][Rr][Ee][Ff][Ii][Xx] { BEGIN(PREF);
+		return PREFIX; }
+[Dd][Ee][Ss][Cc][Rr][Ii][Bb][Ee] { return DESCRIBE; }
+[Cc][Oo][Nn][Ss][Tt][Rr][Uu][Cc][Tt] { return CONSTRUCT; }
+[Aa][Ss][Kk] { return ASK; }
+[Dd][Ii][Ss][Tt][Ii][Nn][Cc][Tt] { return DISTINCT; }
+[Rr][Ee][Dd][Uu][Cc][Ee][Dd] { return REDUCED; }
+[Ll][Ii][Mm][Ii][Tt] { return LIMIT; }
+[Uu][Nn][Ii][Oo][Nn] { return UNION; }
+[Oo][Pp][Tt][Ii][Oo][Nn][Aa][Ll] { return OPTIONAL; }
+[Bb][Aa][Ss][Ee] { return BASE; }
+[Bb][Oo][Uu][Nn][Dd] { return BOUND; }
+[Ss][Tt][Rr] { return STR; }
+[Ll][Aa][Nn][Gg] { return LANG; }
+[Dd][Aa][Tt][Aa][Tt][Yy][Pp][Ee] { return DATATYPE; }
+[Ii][Ss][UuIi][Rr][Ii] { return ISURI; } /* isURI and isIRI */
+[Ii][Ss][Bb][Ll][Aa][Nn][Kk] { return ISBLANK; }
+[Ii][Ss][Ll][Ii][Tt][Ee][Rr][Aa][Ll] { return ISLITERAL; }
+[Gg][Rr][Aa][Pp][Hh] { return GRAPH; }
+[Nn][Aa][Mm][Ee][Dd] { return NAMED; }
+[Ff][Ii][Ll][Tt][Ee][Rr] { return FILTER; }
+[Oo][Ff][Ff][Ss][Ee][Tt] { return OFFSET; }
+[Oo][Rr][Dd][Ee][Rr] { return ORDER; }
+[Bb][Yy] { return BY; }
+[Rr][Ee][Gg][Ee][Xx] { return REGEX; }
+[Aa][Ss][Cc] { return ASC; }
+[Dd][Ee][Ss][Cc] { return DESC; } 
+[Ll][Aa][Nn][Gg][Mm][Aa][Tt][Cc][Hh][Ee][Ss] { return LANGMATCHES; } 
+[Ee][Xx][Pp][Ll][Aa][Ii][Nn] { return EXPLAIN; }
+[Gg][Rr][Oo][Uu][Pp] { return GROUP; }
+[Cc][Oo][Uu][Nn][Tt] { return COUNT; }
+[Aa][Ss] { BEGIN(SPID); return AS; }
+[Dd][Ee][Ll][Ee][Tt][Ee]  { return DELETE; }
+[Ii][Nn][Ss][Ee][Rr][Tt]  { return INSERT; }
+[Ss][Aa][Mm][Ee][Tt][Ee][Rr][Mm] { return SAMETERM; }
+
+"a" { return A; }
+
+","      { return ','; } 
+"("      { return '('; } 
+")"      { return ')'; } 
+"["       { return '['; }
+"]"       { return ']'; }
+"?"  { BEGIN(ID); return '?'; }
+"$"  { BEGIN(ID); return '$'; }
+"{"      { return '{'; } 
+"}"      { return '}'; } 
+"."      { return '.'; } 
+";"      { return ';'; } 
+
+"||"         { return SC_OR; }
+"&&"         { return SC_AND; }
+
+"="            { return EQ; }
+"!="            { return NEQ; }
+"<"/[^A-Za-z=>]  { return LT; }
+">"             { return GT; }
+"<="         { return LE; }
+">="         { return GE; }
+
+"*"         { return '*'; }
+"/"         { return '/'; }
+"!"         { return '!'; }
+
+
+[-+]?{INTEGER}   { c=*yytext;
+                  sparql_parser_lval->literal=rasqal_new_typed_literal(rq->world, RASQAL_LITERAL_INTEGER, (const unsigned char*)yytext);
+                  if(!sparql_parser_lval->literal)
+                    YY_FATAL_ERROR_EOF("rasqal_new_typed_literal failed");
+ 		  return (c=='+' ? INTEGER_POSITIVE_LITERAL : (c == '-' ? INTEGER_NEGATIVE_LITERAL : INTEGER_LITERAL));
+}
+
+[-+]?{DECIMAL}  { 
+                        c=*yytext;
+                        
+                        if(!rasqal_xsd_datatype_check(RASQAL_LITERAL_DECIMAL, (const unsigned char*)yytext, 0)) {
+                          sparql_syntax_error(rq, "SPARQL syntax error - Illegal decimal constant %s", yytext);
+                          yyterminate();
+                        }
+                        sparql_parser_lval->literal=rasqal_new_decimal_literal(rq->world, (const unsigned char*)yytext);
+                        if(!sparql_parser_lval->literal)
+                          YY_FATAL_ERROR_EOF("rasqal_new_decimal_literal failed");
+                        return (c=='+' ? DECIMAL_POSITIVE_LITERAL : (c == '-' ? DECIMAL_NEGATIVE_LITERAL : DECIMAL_LITERAL));
+}
+
+[-+]?{DOUBLE} {
+                        c=*yytext;
+                        if(!rasqal_xsd_datatype_check(RASQAL_LITERAL_DOUBLE, (const unsigned char*)yytext, 0)) {
+                          sparql_syntax_error(rq, "SPARQL syntax error - Illegal double constant %s", yytext);
+                          yyterminate();
+                        }
+                        sparql_parser_lval->literal=rasqal_new_typed_literal(rq->world, RASQAL_LITERAL_DOUBLE, (const unsigned char*)yytext);
+                        if(!sparql_parser_lval->literal)
+                          YY_FATAL_ERROR_EOF("rasqal_new_typed_literal failed");
+                        return (c=='+' ? DOUBLE_POSITIVE_LITERAL : (c == '-' ? DOUBLE_NEGATIVE_LITERAL : DOUBLE_LITERAL));
+}
+
+"+"         { return '+'; }
+"-"         { return '-'; }
+
+'([^'\\\n\r]|\\[^\n\r])*'(@{LANGUAGETOKEN})?(^^({QUOTEDURI}|{QNAME}))?    { /*' */
+                        if(sparql_copy_string_token(rq, sparql_parser_lval,
+                           (const unsigned char*)yytext+1, yyleng-1, '\''))
+                          YY_FATAL_ERROR_EOF("sparql_copy_string_token failed");
+                        return STRING_LITERAL; }
+
+\"([^"\\\n\r]|\\[^\n\r])*\"(@{LANGUAGETOKEN})?(^^({QUOTEDURI}|{QNAME}))?   { /* " */
+                        if(sparql_copy_string_token(rq, sparql_parser_lval,
+                           (const unsigned char*)yytext+1, yyleng-1, '"'))
+                          YY_FATAL_ERROR_EOF("sparql_copy_string_token failed");
+                        return STRING_LITERAL; }
+
+\"\"\"				{ BEGIN(LITERAL); }
+
+<LITERAL>(.|\n)*\"\"\"(^^({QUOTEDURI}|{QNAME}))?	{ if(sparql_copy_string_token(rq, sparql_parser_lval, 
+                            (unsigned char*)yytext, yyleng, '"')) /* ' */
+                            YY_FATAL_ERROR_EOF("sparql_copy_string_token failed");
+                          BEGIN(INITIAL);
+                          return STRING_LITERAL; }
+
+<LITERAL>(.|\n)	{ BEGIN(INITIAL);
+		  if (!*yytext)
+                    return EOF;
+
+                  sparql_syntax_error(rq, "syntax error at %c - \"\"\"string was not terminated", *yytext);
+                  yyterminate();  }
+
+
+\'\'\'				{ BEGIN(LITERAL2); }
+
+<LITERAL2>(.|\n)*\'\'\'(^^({QUOTEDURI}|{QNAME}))?	{ if(sparql_copy_string_token(rq, sparql_parser_lval, 
+                            (unsigned char*)yytext, yyleng, '\''))
+                            YY_FATAL_ERROR_EOF("sparql_copy_string_token failed");
+                          BEGIN(INITIAL);
+                          return STRING_LITERAL; }
+
+<LITERAL2>(.|\n)	{ BEGIN(INITIAL);
+		  if (!*yytext)
+                    return EOF;
+
+                  sparql_syntax_error(rq, "syntax error at %c - '''string was not terminated", *yytext);
+                  yyterminate();  }
+
+
+[Tt][Rr][Uu][Ee]	{ sparql_parser_lval->literal=rasqal_new_boolean_literal(rq->world, 1);
+                    if(!sparql_parser_lval->literal)
+                      YY_FATAL_ERROR_EOF("rasqal_new_boolean_literal failed");
+                  return BOOLEAN_LITERAL; }
+
+[Ff][Aa][Ll][Ss][Ee]	{ sparql_parser_lval->literal=rasqal_new_boolean_literal(rq->world, 0);
+                        if(!sparql_parser_lval->literal)
+                          YY_FATAL_ERROR_EOF("rasqal_new_boolean_literal failed");
+                  return BOOLEAN_LITERAL; }
+
+<ID>{VARNAME}	{ sparql_parser_lval->name=sparql_copy_name(rq, (const unsigned char*)yytext, yyleng, SPARQL_NAME_CHECK_VARNAME);
+		  if(!sparql_parser_lval->name)
+                    YY_FATAL_ERROR_EOF("sparql_copy_name failed");
+                          BEGIN(INITIAL);
+                          return IDENTIFIER; }
+<ID>(.|\n)	{	BEGIN(INITIAL);
+		sparql_syntax_error(rq, "SPARQL syntax error - missing variable name after ?");
+                yyterminate();
+}
+
+<SPID>[\ \t\v]+	{ /* eat up leading whitespace */
+	;
+}
+<SPID>{VARNAME}	{ sparql_parser_lval->name=sparql_copy_name(rq, (const unsigned char*)yytext, yyleng, SPARQL_NAME_CHECK_VARNAME);
+		  if(!sparql_parser_lval->name)
+                    YY_FATAL_ERROR_EOF("sparql_copy_name failed");
+                          BEGIN(INITIAL);
+                          return IDENTIFIER; }
+
+<SPID>(.|\n)	{	BEGIN(INITIAL);
+		sparql_syntax_error(rq, "SPARQL syntax error - missing variable name after ?");
+                yyterminate();
+}
+
+<PREF>[\ \t\v]+ { /* eat up leading whitespace */ }
+<PREF>{NCNAME_PREFIX}":"	{ BEGIN(INITIAL);
+		  	  sparql_parser_lval->name=sparql_copy_name(rq, (const unsigned char*)yytext, yyleng-1, SPARQL_NAME_CHECK_PREFIX);
+			  if(!sparql_parser_lval->name)
+			    YY_FATAL_ERROR_EOF("sparql_copy_name failed");
+                          return IDENTIFIER; }
+<PREF>":"	{ BEGIN(INITIAL);
+		  sparql_parser_lval->name=NULL;
+                  return IDENTIFIER; }
+
+<PREF>(.|\n)	{ BEGIN(INITIAL);
+		  if (!*yytext)
+                    return EOF;
+
+                  sparql_syntax_error(rq, "SPARQL syntax error at '%c'", *yytext);
+                  yyterminate();
+}
+
+{QNAME}\(?	{
+		int have_brace=(yytext[yyleng-1]=='(');
+		if(have_brace)
+			yyleng--;
+		sparql_parser_lval->uri=sparql_copy_qname(rq, (const unsigned char*)yytext, yyleng);
+		if(!sparql_parser_lval->uri)
+		  YY_FATAL_ERROR_EOF("sparql_copy_qname failed");
+ 		return have_brace ? URI_LITERAL_BRACE : URI_LITERAL;
+}
+
+{BNAME}	{	sparql_parser_lval->name=sparql_copy_name(rq, (unsigned char*)yytext+2, yyleng-2, SPARQL_NAME_CHECK_NCNAME);
+		return BLANK_LITERAL;
+}
+
+{BNAME2}	{	sparql_parser_lval->name=sparql_copy_name(rq, (unsigned char*)yytext+3, yyleng-4, SPARQL_NAME_CHECK_NCNAME);
+		return BLANK_LITERAL;
+}
+
+{QUOTEDURI}\(?   { 
+		int have_brace=(yytext[yyleng-1]=='(');
+		if(have_brace)
+			yyleng--;
+		if(yyleng == 2) 
+#ifdef RAPTOR_V2_AVAILABLE
+                  sparql_parser_lval->uri = raptor_uri_copy_v2(rq->world->raptor_world_ptr, rq->base_uri);
+#else
+                  sparql_parser_lval->uri = raptor_uri_copy(rq->base_uri);
+#endif
+                else {
+                  unsigned char* uri_string;
+
+                  yytext[yyleng-1]='\0';
+                  uri_string=rasqal_escaped_name_to_utf8_string((unsigned char*)yytext+1,
+                                                                yyleng-1,
+                                                                NULL,
+                                                                (raptor_simple_message_handler)sparql_syntax_error, rq);
+                  if(!uri_string)
+                    YY_FATAL_ERROR_EOF("rasqal_escaped_name_to_utf8_string failed");
+
+#ifdef RAPTOR_V2_AVAILABLE
+                  sparql_parser_lval->uri = raptor_new_uri_relative_to_base_v2(rq->world->raptor_world_ptr, rq->base_uri, uri_string);
+#else
+                  sparql_parser_lval->uri = raptor_new_uri_relative_to_base(rq->base_uri, uri_string);
+#endif
+                  RASQAL_FREE(cstring, uri_string);
+                  if(!sparql_parser_lval->uri)
+                    YY_FATAL_ERROR_EOF("raptor_new_uri_relative_to_base failed");
+                 }
+                 return have_brace ? URI_LITERAL_BRACE : URI_LITERAL; }
+
+\#[^\r\n]*(\r\n|\r|\n)	{ /* # comment */
+        	rqe->lineno++;
+                }
+
+.         	{ if (!*yytext)
+                    return EOF;
+
+                  sparql_syntax_error(rq, "SPARQL syntax error at '%c'", *yytext);
+                  yyterminate();
+		}
+
+%%
+  /* user code */
+
+int
+yywrap (yyscan_t yyscanner) {
+  return 1;
+}
+
+
+static int
+rasqal_sparql_name_check(unsigned char *string, size_t length,
+                         sparql_name_check_flags check_flags)
+{
+  int rc=0;
+  int c= -1;
+#if RASQAL_DEBUG > 2
+  RASQAL_DEBUG1("Checking name '");
+  if(length)
+     fwrite(string, length, sizeof(unsigned char), stderr);
+  fprintf(stderr, "' (length %d), flags %d\n", (int)length, (int)check_flags);
+#endif
+
+  if(!length)
+    return 1;
+
+  if(check_flags && SPARQL_NAME_CHECK_ALLOW_09_FIRST &&
+     (*string >= '0' && *string <= '9')) {
+    c=*string;
+    *string='X';
+  }
+
+  if(!raptor_xml_name_check(string, length, 11)) /* 11 = XML 1.1 */
+    goto done;
+  
+  if((check_flags & SPARQL_NAME_CHECK_NO_UL_FIRST) && *string == '_')
+    goto done;
+
+  if((check_flags & SPARQL_NAME_CHECK_NO_DOT_LAST) && string[length-1] == '.')
+    goto done;
+
+  if(check_flags & SPARQL_NAME_CHECK_NO_DOT_MINUS) {
+    int i;
+    for(i=0; i < (int)length; i++)
+      if(string[i] == '.' || string[i] == '-')
+        goto done;
+  }
+  rc=1;
+
+  done:
+  if(c >=0)
+    *string=c;
+  return rc;
+}
+
+
+static unsigned char *
+sparql_copy_name(rasqal_query *rq, const unsigned char *text, size_t len,
+                 sparql_name_check_flags check_flags) {
+  size_t dest_len=0;
+  unsigned char *s;
+
+  s=rasqal_escaped_name_to_utf8_string((unsigned char*)text, len,
+                                       &dest_len,
+                                       (raptor_simple_message_handler)sparql_syntax_error, rq);
+  if(!s)
+    return s;
+
+  if(!rasqal_sparql_name_check(s, dest_len, check_flags))
+    sparql_syntax_error(rq, "Invalid SPARQL name \"%s\"", s);
+
+  return s;
+}
+
+
+static raptor_uri*
+sparql_copy_qname(rasqal_query *rq, const unsigned char *text, size_t len) {
+  unsigned char *p;
+  size_t dest_len=0;
+  unsigned char *s;
+  raptor_uri* uri=NULL;
+  
+  s=rasqal_escaped_name_to_utf8_string((unsigned char*)text, len,
+                                       &dest_len,
+                                       (raptor_simple_message_handler)sparql_syntax_error, rq);
+  if(!s)
+    return NULL;
+
+  p=(unsigned char*)strchr((const char*)s, ':');
+  if(!rasqal_sparql_name_check(s, p-s, SPARQL_NAME_CHECK_PREFIX))
+    sparql_syntax_error(rq, "Invalid SPARQL prefix name \"%s\"", s);
+  if(!rasqal_sparql_name_check(p+1, dest_len-((p+1)-s), SPARQL_NAME_CHECK_NCNAME))
+    sparql_syntax_error(rq, "Invalid SPARQL local name \"%s\"", p+1);
+
+#ifdef STANDALONE
+  /* lexer test cannot declare namespaces - so just ignore expansion */
+# ifdef RAPTOR_V2_AVAILABLE
+  uri = raptor_new_uri_relative_to_base_v2(rq->world->raptor_world_ptr, rq->base_uri, s);
+# else
+  uri = raptor_new_uri_relative_to_base(rq->base_uri, s);
+# endif
+#else
+  if(!rq->namespaces) {
+    sparql_syntax_error(rq, "SPARQL syntax error - no namespaces declared");
+    return NULL;
+  }
+  
+  uri=raptor_qname_string_to_uri(rq->namespaces,
+                                 s, dest_len,
+                                 (raptor_simple_message_handler)rasqal_query_simple_error, rq);
+#endif
+  RASQAL_FREE(cstring, s);
+  
+  return uri;
+}
+
+
+static int
+sparql_copy_string_token(rasqal_query* rq, YYSTYPE* lval,
+                         const unsigned char *text, size_t len, int delim) {
+  unsigned int i;
+  const unsigned char *s;
+  unsigned char *d;
+  unsigned char *string;
+  char *language=NULL;
+  unsigned char *dt=NULL;
+  raptor_uri *dt_uri=NULL;
+  unsigned char *dt_qname=NULL;
+
+  string=(unsigned char *)RASQAL_MALLOC(cstring, len+1);
+  if(!string)
+    return 1;
+
+  for(s=text, d=string, i=0; i<len; s++, i++) {
+    unsigned char c=*s;
+
+    if(c == '\\' ) {
+      s++; i++;
+      c=*s;
+      if(c == 'n')
+        *d++= '\n';
+      else if(c == 'r')
+        *d++= '\r';
+      else if(c == 't')
+        *d++= '\t';
+      else if(c == '\\' || c == delim)
+        *d++=c;
+      else if (c == 'u' || c == 'U') {
+        int ulen=(c == 'u') ? 4 : 8;
+        unsigned long unichar=0;
+        int n;
+        
+        s++; i++;
+        if(i+ulen > len) {
+          printf("\\%c over end of line", c);
+          RASQAL_FREE(cstring, string);
+          return 1;
+        }
+        
+        n=sscanf((const char*)s, ((ulen == 4) ? "%04lx" : "%08lx"), &unichar);
+        if(n != 1) {
+          sparql_syntax_error(rq, "SPARQL syntax error - Illegal Uncode escape '%c%s...'", c, s);
+          RASQAL_FREE(cstring, string);
+          return 1;
+        }
+
+        s+= ulen-1;
+        i+= ulen-1;
+        
+        if(unichar > 0x10ffff) {
+          sparql_syntax_error(rq, "SPARQL syntax error - Illegal Unicode character with code point #x%lX.", unichar);
+          RASQAL_FREE(cstring, string);
+          return 1;
+        }
+          
+        d+=raptor_unicode_char_to_utf8(unichar, d);
+      } else {
+        /* Ignore \x where x isn't the one of: \n \r \t \\ (delim) \u \U */
+        sparql_syntax_warning(rq, "Unknown SPARQL string escape \\%c in \"%s\"", c, text);
+        *d++=c;
+      }
+    } else if(c== delim) {
+      *d++='\0';
+
+      /* skip delims (', ", ''' or """) */
+      while(c == delim) {
+        c=*s++; i++;
+      }
+      
+      if(c=='@') {
+        language=(char*)d;
+        while(i<=len) {
+          c=*s++; i++;
+          if(!isalpha(c) && !isdigit(c) && c!= '-')
+            break;
+          *d++=c;
+        }
+        *d++='\0';
+      }
+      if(c=='^') {
+        /* skip second char of ^^ */
+        s++; i++;
+
+        dt=d;
+        while(i++<=len)
+          *d++=*s++;
+        /* *d='\0' below */
+      } else if (language)
+        *d='\0';
+      
+      break;
+   } else
+    *d++=c;
+  } /* end of for */
+
+  *d='\0';
+
+  if(language) {
+    char *new_language=(char *)RASQAL_MALLOC(cstring, strlen((const char*)language)+1);
+    if(!new_language) {
+      RASQAL_FREE(cstring, string);
+      return 1;
+    }
+    strcpy(new_language, language);
+    language=new_language;
+  }
+  
+  if(dt) {
+    /* dt can be a URI or qname */
+    if(*dt == '<') {
+      dt[strlen((const char*)dt)-1]='\0';
+#ifdef RAPTOR_V2_AVAILABLE
+      dt_uri = raptor_new_uri_v2(rq->world->raptor_world_ptr, dt+1);
+#else
+      dt_uri = raptor_new_uri(dt+1);
+#endif
+      if(!dt_uri) {
+        if(language)
+          RASQAL_FREE(cstring, language);
+        RASQAL_FREE(cstring, string);
+        return 1;
+      }
+    } else {
+      unsigned char *dt_p;
+      size_t dest_len=0;
+      unsigned char *dt_s;
+      
+      dt_s=rasqal_escaped_name_to_utf8_string(dt,
+                                              strlen((const char*)dt),
+                                              &dest_len,
+                                              (raptor_simple_message_handler)sparql_syntax_error, rq);
+      if(!dt_s) {
+        if(language)
+          RASQAL_FREE(cstring, language);
+        RASQAL_FREE(cstring, string);
+        return 1;
+      }
+
+      dt_p=(unsigned char*)strchr((const char*)dt_s, ':');
+      if(!rasqal_sparql_name_check(dt_s, dt_p-dt_s, SPARQL_NAME_CHECK_PREFIX))
+        sparql_syntax_error(rq, "Invalid SPARQL prefix name \"%s\"", dt_s);
+      if(!rasqal_sparql_name_check(dt_p+1, dest_len-((dt_p+1)-dt_s), 
+                                   SPARQL_NAME_CHECK_NCNAME))
+        sparql_syntax_error(rq, "Invalid SPARQL local name \"%s\"", dt_p+1);
+
+#ifdef STANDALONE
+      /* lexer test cannot declare namespaces - so just ignore expansion */
+      dt_qname=dt_s;
+#else
+      if(!rq->namespaces) {
+        sparql_syntax_error(rq, "SPARQL syntax error - no namespaces declared");
+        RASQAL_FREE(cstring, dt_s);
+        if(language)
+          RASQAL_FREE(cstring, language);
+        RASQAL_FREE(cstring, string);
+        return 1;
+      }
+  
+      dt_uri=raptor_qname_string_to_uri(rq->namespaces,
+                                        dt_s, dest_len,
+                                        (raptor_simple_message_handler)rasqal_query_simple_error, rq);
+      RASQAL_FREE(cstring, dt_s);
+
+      if(!dt_uri) {
+        if(language)
+          RASQAL_FREE(cstring, language);
+        RASQAL_FREE(cstring, string);
+        return 1;
+      }
+#endif
+    }
+  }
+
+#if RASQAL_DEBUG >3
+  fprintf(stderr, "string='%s', language='%s'\n", 
+          string, (language ? language : ""));
+  fprintf(stderr, "datatype uri='%s'\n",
+          (dt_uri ? (const char*)raptor_uri_as_string(dt_uri) : ""));
+#endif
+
+  lval->literal=rasqal_new_string_literal(rq->world, string, language, dt_uri, dt_qname);
+  if(!lval->literal)
+    return 1;
+
+  return 0;
+}
+
+
+static int
+sparql_skip_c_comment(rasqal_query *rq) {
+  rasqal_sparql_query_language *rqe=(rasqal_sparql_query_language*)rq->context;
+  yyscan_t yyscanner=rqe->scanner;
+  int lines=0;
+  int c;
+  int lastc= -1;
+  
+  while(1) {
+    while ((c=INPUT_FN(yyscanner)) != '*' && c!= EOF) {
+      if(c == '\r' || (c == '\n' && lastc != '\r'))
+        lines++;
+      lastc= c;
+    }
+    if( c == '*') {
+      while ((c=INPUT_FN(yyscanner)) == '*') {
+        if(c == '\r' || (c == '\n' && lastc != '\r'))
+          lines++;
+        lastc= c;
+      }
+
+      if(c == '/')
+        break;
+    }
+    if (c == EOF) {
+      sparql_syntax_error(rq, "SPARQL syntax error - EOF in comment");
+      lines= -1;
+      break;
+    }
+    lastc= c;
+  }
+  return lines;
+}
+
+
+/*
+ * sparql_lexer_fatal_error:
+ * @msg:
+ * @yyscanner:
+ *
+ * INTERNAL - replacement for the generated error handler.
+ * Uses rasqal_query_fatal_error() when possible.
+ */
+static void sparql_lexer_fatal_error(yyconst char *msg, yyscan_t yyscanner)
+{
+  rasqal_query *rq=NULL;
+
+  if(yyscanner)
+    rq=(rasqal_query *)sparql_lexer_get_extra(yyscanner);
+
+  if(rq) {
+    /* avoid "format not a string literal and no format arguments" warning with %s */
+    rq->failed=1;
+    rasqal_log_error_simple(rq->world, RAPTOR_LOG_LEVEL_FATAL,
+                            &rq->locator, "%s", msg); 
+  } else {
+    fputs(msg, stderr);
+    fputc('\n', stderr);
+  }
+}
+
+
+/* Define LEXER_ALLOC_TRACKING to enable allocated memory tracking
+ * - fixes lexer memory leak when ensure_buffer_stack fails
+ */
+
+#ifdef LEXER_ALLOC_TRACKING
+typedef struct {
+  /* Number of void* slots allocated */
+  int lexer_allocs_size;
+  /* Allocted void* slots follow in memory after this header */
+} lexer_alloc_tracker_header;
+
+/* Initial alloc tracker slot array size - 2 seems to be enough for almost all cases */
+static const int initial_lexer_allocs_size=2;
+#endif
+
+/*
+ * sparql_lexer_cleanup:
+ * @yyscanner:
+ *
+ * INTERNAL - Clean up unfreed lexer allocs if LEXER_ALLOC_TRACKING is enabled.
+ */
+static void sparql_lexer_cleanup(yyscan_t yyscanner)
+{
+#ifdef LEXER_ALLOC_TRACKING
+  rasqal_query *rq;
+  lexer_alloc_tracker_header *tracker;
+  void **lexer_allocs;
+  int i;
+
+  if(!yyscanner)
+    return;
+
+  rq=(rasqal_query *)sparql_lexer_get_extra(yyscanner);
+  if(!rq)
+    return;
+
+  tracker=(lexer_alloc_tracker_header *)rq->lexer_user_data;
+  if(!tracker)
+    return;
+  lexer_allocs=(void**)&tracker[1];
+
+  for(i=0; i<tracker->lexer_allocs_size; ++i) {
+    if(lexer_allocs[i])
+      free(lexer_allocs[i]);
+    lexer_allocs[i]=NULL;
+  }
+  free(rq->lexer_user_data);
+  rq->lexer_user_data=NULL;
+#endif
+}
+
+
+/*
+ * sparql_lexer_alloc:
+ * @size
+ * @yyscanner
+ *
+ * INTERNAL - alloc replacement.
+ * Tracks allocated cells if LEXER_ALLOC_TRACKING is enabled.
+ */
+void *sparql_lexer_alloc(yy_size_t size, yyscan_t yyscanner)
+{
+#ifdef LEXER_ALLOC_TRACKING
+  rasqal_query *rq;
+  lexer_alloc_tracker_header *tracker;
+  void **lexer_allocs;
+  int i;
+  void *ptr;
+
+  /* yyscanner not initialized -> probably initializing yyscanner itself
+   * -> just malloc without tracking
+   */
+  if(!yyscanner)
+    return malloc(size);
+
+  rq=(rasqal_query *)sparql_lexer_get_extra(yyscanner);
+  if(!rq)
+    YY_FATAL_ERROR("lexer_alloc: yyscanner extra not initialized");
+
+  /* try to allocate tracker if it does not exist */
+  tracker=(lexer_alloc_tracker_header *)rq->lexer_user_data;
+  if(!tracker) {
+    /* allocate tracker header + array of void* slots */
+    tracker=(lexer_alloc_tracker_header*)calloc(1, sizeof(lexer_alloc_tracker_header)+initial_lexer_allocs_size*sizeof(void*));
+    if(!tracker)
+      YY_FATAL_ERROR("lexer_alloc: cannot allocate tracker");
+    tracker->lexer_allocs_size=initial_lexer_allocs_size;
+    rq->lexer_user_data=(void *)tracker;
+  }
+  lexer_allocs=(void**)&tracker[1];
+
+  /* allocate memory */
+  ptr=malloc(size);
+  
+  /* find a free slot for ptr */
+  for(i=0; i<tracker->lexer_allocs_size; ++i) {
+    if(!lexer_allocs[i]) {
+      lexer_allocs[i]=ptr;
+      break;
+    }
+  }
+
+  /* no free slots -> grow tracker slot array */
+  if(i>=tracker->lexer_allocs_size) {
+    int j;
+    void **dest;
+    tracker=(lexer_alloc_tracker_header*)calloc(1, sizeof(lexer_alloc_tracker_header)+i*2*sizeof(void*));
+    if(!tracker) {
+      if(ptr)
+        free(ptr);
+      YY_FATAL_ERROR("lexer_alloc: cannot grow tracker");
+    }
+    tracker->lexer_allocs_size=i*2;
+    
+    /* copy data from old tracker */
+    dest=(void**)&tracker[1];
+    for(j=0; j<i; ++j) {
+      dest[j]=lexer_allocs[j];
+    }
+    
+    /* set new item to first free slot */
+    dest[j]=ptr;
+
+    /* free old tracker and replace with new one */
+    free(rq->lexer_user_data);
+    rq->lexer_user_data=tracker;
+  }
+
+  return ptr;
+#else
+  return malloc(size);
+#endif
+}
+
+
+/*
+ * sparql_lexer_realloc:
+ *
+ * INTERNAL - realloc replacement
+ * Tracks allocated cells if LEXER_ALLOC_TRACKING is enabled.
+ */
+void *sparql_lexer_realloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
+{
+#ifdef LEXER_ALLOC_TRACKING
+  rasqal_query *rq;
+  lexer_alloc_tracker_header *tracker;
+  void **lexer_allocs;
+  int i;
+  void *newptr;
+
+  if(!yyscanner)
+    YY_FATAL_ERROR("lexer_realloc: yyscanner not initialized");
+
+  rq=(rasqal_query *)sparql_lexer_get_extra(yyscanner);
+  if(!rq)
+    YY_FATAL_ERROR("lexer_realloc: yyscanner extra not initialized");
+
+  tracker=(lexer_alloc_tracker_header *)rq->lexer_user_data;
+  if(!tracker)
+    YY_FATAL_ERROR("lexer_realloc: no alloc tracker");
+  lexer_allocs=(void**)&tracker[1];
+
+  /* find the old slot for ptr */
+  for(i=0; i<tracker->lexer_allocs_size; ++i) {
+    if(lexer_allocs[i]==ptr)
+      break;
+  }
+
+  /* no old slot -> error */  
+  if(i>=tracker->lexer_allocs_size)
+    YY_FATAL_ERROR("lexer_realloc: cell not in tracker");
+
+  /* realloc */
+  newptr=realloc((char*)ptr, size);
+
+  /* replace entry in tracker */
+  lexer_allocs[i]=newptr;
+
+  return newptr;
+#else
+  return realloc((char*)ptr, size);
+#endif
+}
+
+
+/*
+ * sparql_lexer_free:
+ *
+ * INTERNAL - free replacement.
+ * Checks for NULL pointer to be freed unlike the default lexer free function.
+ * Tracks allocated cells if LEXER_ALLOC_TRACKING is enabled.
+ */
+void sparql_lexer_free(void *ptr, yyscan_t yyscanner)
+{
+#ifdef LEXER_ALLOC_TRACKING
+  rasqal_query *rq;
+  lexer_alloc_tracker_header *tracker;
+  void **lexer_allocs;
+  int i;
+
+  /* do not free NULL */
+  if(!ptr)
+    return;
+
+  /* free ptr even if we would encounter an error */
+  free(ptr);
+
+  /* yyscanner is allocated with sparql_lexer_alloc() but it's never stored in the tracker
+   * - we need yyscanner to access the tracker */
+  if(!yyscanner || ptr==yyscanner)
+    return;
+
+  rq=(rasqal_query *)sparql_lexer_get_extra(yyscanner);
+  if(!rq)
+    return;
+
+  tracker=(lexer_alloc_tracker_header *)rq->lexer_user_data;
+  if(!tracker)
+    return;
+  lexer_allocs=(void**)&tracker[1];
+
+  /* find the slot for ptr */
+  for(i=0; i<tracker->lexer_allocs_size; ++i) {
+    if(lexer_allocs[i]==ptr)
+      break;
+  }
+
+  /* no slot -> error */  
+  if(i>=tracker->lexer_allocs_size)
+    YY_FATAL_ERROR("lexer_free: cell not in tracker");
+
+  /* remove entry from tracker */
+  lexer_allocs[i]=NULL;
+#else
+  if(ptr)
+    free(ptr);
+#endif
+}
+
+
+#ifdef RASQAL_DEBUG
+
+const char *
+sparql_token_print(rasqal_world* world, int token, YYSTYPE *lval)
+{
+  static char buffer[2048];
+
+  if(!token)
+    return "<<EOF>>";
+  
+  switch(token) {
+    case SELECT:
+      return "SELECT";
+
+    case FROM:
+      return "FROM";
+
+    case WHERE:
+      return "WHERE";
+
+    case PREFIX:
+      return "PREFIX";
+
+    case DESCRIBE:
+      return "DESCRIBE";
+
+    case CONSTRUCT:
+      return "CONSTRUCT";
+
+    case ASK:
+      return "ASK";
+
+    case DISTINCT:
+      return "DISTINCT";
+
+    case LIMIT:
+      return "LIMIT";
+
+    case UNION:
+      return "UNION";
+
+    case OPTIONAL:
+      return "OPTIONAL";
+
+    case BASE:
+      return "BASE";
+
+    case BOUND:
+      return "BOUND";
+
+    case STR:
+      return "STR";
+      
+    case LANG:
+      return "LANG";
+      
+    case DATATYPE:
+      return "DATATYPE";
+      
+    case ISURI:
+      return "ISURI";
+      
+    case ISBLANK:
+      return "ISBLANK";
+      
+    case ISLITERAL:
+      return "ISLITERAL";
+      
+    case GRAPH:
+      return "GRAPH";
+      
+    case NAMED:
+      return "NAMED";
+      
+    case FILTER:
+      return "FILTER";
+
+    case OFFSET:
+      return "OFFSET";
+      
+    case A:
+      return "a";
+      
+    case ORDER:
+      return "ORDER";
+      
+    case BY:
+      return "BY";
+      
+    case REGEX:
+      return "REGEX";
+      
+    case ASC:
+      return "ASC[";
+      
+    case DESC:
+      return "DESC[";
+      
+    case LANGMATCHES:
+      return "LANGMATCHES";
+      
+    case ',':
+      return ",";
+
+    case '(':
+      return "(";
+
+    case ')':
+      return ")";
+
+    case '[':
+      return "[";
+
+    case ']':
+      return "]";
+
+    case '{':
+      return "{";
+
+    case '}':
+      return "}";
+
+    case '.':
+      return ".";
+
+    case ';':
+      return ";";
+
+    case '?':
+      return "?";
+
+    case '$':
+      return "$";
+
+    case SC_AND:
+      return "SC_AND";
+
+    case SC_OR:
+      return "SC_OR";
+
+    case GE:
+      return "GE";
+
+    case LE:
+      return "LE";
+
+    case GT:
+      return "GT";
+
+    case LT:
+      return "LT";
+
+    case NEQ:
+      return "NEQ";
+
+    case EQ:
+      return "EQ";
+
+    case '/':
+      return "/";
+
+    case '*':
+      return "*";
+
+    case '-':
+      return "-";
+
+    case '+':
+      return "+";
+
+    case '!':
+      return "!";
+
+    case EXPLAIN:
+      return "EXPLAIN";
+
+    case GROUP:
+      return "GROUP";
+
+    case COUNT:
+      return "COUNT";
+
+    case AS:
+      return "AS";
+
+    case INTEGER_LITERAL:
+    case INTEGER_POSITIVE_LITERAL:
+    case INTEGER_NEGATIVE_LITERAL:
+      sprintf(buffer, "INTEGER_LITERAL(%d)", lval->literal->value.integer);
+      return buffer;
+
+    case DOUBLE_LITERAL:
+    case DOUBLE_POSITIVE_LITERAL:
+    case DOUBLE_NEGATIVE_LITERAL:
+      sprintf(buffer, "DOUBLE_LITERAL(%g)", lval->floating);
+      return buffer;
+
+    case STRING_LITERAL:
+      if(lval->literal->language) {
+        if(lval->literal->datatype)
+          sprintf(buffer, "STRING_LITERAL(\"%s\"@%s^^%s)",
+                  lval->literal->string, lval->literal->language,
+#ifdef RAPTOR_V2_AVAILABLE
+                  raptor_uri_as_string_v2(world->raptor_world_ptr, lval->literal->datatype)
+#else
+                  raptor_uri_as_string(lval->literal->datatype)
+#endif
+                  );
+        else
+          sprintf(buffer, "STRING_LITERAL(\"%s\"@%s)",
+                  lval->literal->string, lval->literal->language);
+      } else {
+        if(lval->literal->datatype)
+          sprintf(buffer, "STRING_LITERAL(\"%s\"^^%s)", 
+                  lval->literal->string,
+#ifdef RAPTOR_V2_AVAILABLE
+                  raptor_uri_as_string_v2(world->raptor_world_ptr, lval->literal->datatype)
+#else                  
+                  raptor_uri_as_string(lval->literal->datatype)
+#endif
+                  );
+        else
+          sprintf(buffer, "STRING_LITERAL(\"%s\")", lval->literal->string);
+      }
+      return buffer;
+
+    case BOOLEAN_LITERAL:
+      return (lval->literal->value.integer ? "BOOLEAN_LITERAL(true)" : "BOOLEAN_LITERAL(false)");
+
+    case URI_LITERAL:
+      sprintf(buffer, "URI_LITERAL(%s)",
+#ifdef RAPTOR_V2_AVAILABLE
+              raptor_uri_as_string_v2(world->raptor_world_ptr, lval->uri)
+#else
+              raptor_uri_as_string(lval->uri)
+#endif
+              );
+      return buffer;
+
+    case QNAME_LITERAL:
+      sprintf(buffer, "QNAME_LITERAL(%s)", lval->name);
+      return buffer;
+
+    case URI_LITERAL_BRACE:
+      sprintf(buffer, "URI_LITERAL_BRACE(%s)",
+#ifdef RAPTOR_V2_AVAILABLE
+              raptor_uri_as_string_v2(world->raptor_world_ptr, lval->uri)
+#else
+              raptor_uri_as_string(lval->uri)
+#endif
+              );
+      return buffer;
+
+    case QNAME_LITERAL_BRACE:
+      sprintf(buffer, "QNAME_LITERAL_BRACE(%s)", lval->name);
+      return buffer;
+
+    case IDENTIFIER:
+      sprintf(buffer, "IDENTIFIER(%s)", lval->name);
+      return buffer;
+
+    case BLANK_LITERAL:
+      sprintf(buffer, "BLANK_LITERAL(%s)", lval->name);
+      return buffer;
+
+    case DECIMAL_LITERAL:
+    case DECIMAL_POSITIVE_LITERAL:
+    case DECIMAL_NEGATIVE_LITERAL:
+      sprintf(buffer, "DECIMAL_LITERAL(%s)", lval->literal->string);
+      return buffer;
+
+   default:
+     RASQAL_DEBUG2("UNKNOWN token %d - add a new case\n", token);
+     abort();
+  }
+}
+#endif
+
+
+
+#ifdef STANDALONE
+static void
+sparql_token_free(rasqal_world* world, int token, YYSTYPE *lval)
+{
+  if(!token)
+    return;
+  
+  switch(token) {
+    case STRING_LITERAL:
+      rasqal_free_literal(lval->literal);
+      break;
+    case URI_LITERAL:
+#ifdef RAPTOR_V2_AVAILABLE
+      raptor_free_uri_v2(world->raptor_world_ptr, lval->uri);
+#else
+      raptor_free_uri(lval->uri);
+#endif
+      break;
+    case IDENTIFIER:
+    case BLANK_LITERAL:
+      RASQAL_FREE(cstring, lval->name);
+      break;
+    case QNAME_LITERAL:
+      if(lval->name)
+        RASQAL_FREE(cstring, lval->name);
+      break;
+    default:
+      break;
+  }
+}
+
+
+#define FILE_READ_BUF_SIZE 2048
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program=rasqal_basename(argv[0]);
+  char *query_string=NULL;
+  rasqal_query rq;
+  rasqal_sparql_query_language sparql;
+  yyscan_t scanner;
+  int token=EOF;
+  YYSTYPE lval;
+  const unsigned char *uri_string;
+  const char *filename=NULL;
+  char *buf=NULL;
+  size_t len;
+  void *buffer;
+  rasqal_world *world;
+
+  world=rasqal_new_world();
+  if(!world || rasqal_world_open(world))
+    exit(1);
+  
+  if(argc > 1) {
+    FILE *fh;
+    query_string=(char*)RASQAL_CALLOC(cstring, FILE_READ_BUF_SIZE, 1);
+    filename=argv[1];
+    fh=fopen(filename, "r");
+    if(fh) {
+      fread(query_string, FILE_READ_BUF_SIZE, 1, fh);
+      fclose(fh);
+    } else {
+      fprintf(stderr, "%s: Cannot open file %s - %s\n", program, filename,
+              strerror(errno));
+      exit(1);
+    }
+  } else {
+    filename="<stdin>";
+    query_string=(char*)RASQAL_CALLOC(cstring, FILE_READ_BUF_SIZE, 1);
+    fread(query_string, FILE_READ_BUF_SIZE, 1, stdin);
+  }
+
+  memset(&rq, 0, sizeof(rasqal_query));
+  rq.world=world;
+  memset(&sparql, 0, sizeof(rasqal_sparql_query_language));
+
+  yylex_init(&sparql.scanner);
+  scanner=sparql.scanner;
+
+  len= strlen((const char*)query_string);
+  buf= (char *)RASQAL_MALLOC(cstring, len+3);
+  strncpy(buf, query_string, len);
+  buf[len]= ' ';
+  buf[len+1]= buf[len+2]='\0'; /* YY_END_OF_BUFFER_CHAR; */
+  buffer= sparql_lexer__scan_buffer(buf, len+3, scanner);
+
+  sparql_lexer_set_extra(&rq, scanner);
+
+  /* Initialise enough of the rasqal_query and locator to get error messages */
+  rq.context=&sparql;
+  sparql.lineno=1;
+  rq.locator.file=filename;
+  rq.locator.column= -1;
+
+  uri_string=raptor_uri_filename_to_uri_string(filename);
+#ifdef RAPTOR_V2_AVAILABLE
+  rq.base_uri = raptor_new_uri_v2(world->raptor_world_ptr, uri_string);
+#else
+  rq.base_uri = raptor_new_uri(uri_string);
+#endif
+  raptor_free_memory((void*)uri_string);
+
+  while(1) {
+    memset(&lval, 0, sizeof(YYSTYPE));
+    if(sparql_lexer_get_text(scanner) != NULL)
+      printf("yyinput '%s'\n", sparql_lexer_get_text(scanner));
+    token=yylex(&lval, scanner);
+#ifdef RASQAL_DEBUG
+    printf("token %s\n", sparql_token_print(world, token, &lval));
+#else
+    printf("token %d\n", token);
+#endif
+    sparql_token_free(world, token, &lval);
+    if(!token || token == EOF)
+      break;
+  }
+
+  if(buf)
+    RASQAL_FREE(cstring, buf);
+  
+  yylex_destroy(scanner);
+
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_free_uri_v2(world->raptor_world_ptr, rq.base_uri);
+#else
+  raptor_free_uri(rq.base_uri);
+#endif
+
+  RASQAL_FREE(cstring, query_string);
+
+  rasqal_free_world(world);
+
+  if(rq.failed)
+    return 1;
+ 
+  return 0;
+}
+#endif
diff --git a/src/rasqal/sparql_parser.y b/src/rasqal/sparql_parser.y
new file mode 100644
index 0000000..7723dd0
--- /dev/null
+++ b/src/rasqal/sparql_parser.y
@@ -0,0 +1,3068 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * sparql_parser.y - Rasqal SPARQL parser over tokens from sparql_lexer.l
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ *
+ * References:
+ *   SPARQL Query Language for RDF, W3C Recommendation 15 January 2008
+ *   http://www.w3.org/TR/2008/REC-rdf-sparql-query-20080115/
+ *
+ */
+
+%{
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <rasqal.h>
+#include <rasqal_internal.h>
+
+#include <sparql_parser.h>
+
+#define YY_DECL int sparql_lexer_lex (YYSTYPE *sparql_parser_lval, yyscan_t yyscanner)
+#define YY_NO_UNISTD_H 1
+#include <sparql_lexer.h>
+
+#include <sparql_common.h>
+
+
+#if 0
+#undef RASQAL_DEBUG
+#define RASQAL_DEBUG 2
+#endif
+
+
+#define DEBUG_FH stderr
+
+/* Make verbose error messages for syntax errors */
+#define YYERROR_VERBOSE 1
+
+/* Fail with an debug error message if RASQAL_DEBUG > 1 */
+#if RASQAL_DEBUG > 1
+#define YYERROR_MSG(msg) do { fputs("** YYERROR ", DEBUG_FH); fputs(msg, DEBUG_FH); fputc('\n', DEBUG_FH); YYERROR; } while(0)
+#else
+#define YYERROR_MSG(ignore) YYERROR
+#endif
+
+/* Slow down the grammar operation and watch it work */
+#if RASQAL_DEBUG > 2
+#define YYDEBUG 1
+#endif
+
+/* the lexer does not seem to track this */
+#undef RASQAL_SPARQL_USE_ERROR_COLUMNS
+
+/* Missing sparql_lexer.c/h prototypes */
+int sparql_lexer_get_column(yyscan_t yyscanner);
+/* Not used here */
+/* void sparql_lexer_set_column(int  column_no , yyscan_t yyscanner);*/
+
+
+/* What the lexer wants */
+extern int sparql_lexer_lex (YYSTYPE *sparql_parser_lval, yyscan_t scanner);
+#define YYLEX_PARAM ((rasqal_sparql_query_language*)(((rasqal_query*)rq)->context))->scanner
+
+/* Pure parser argument (a void*) */
+#define YYPARSE_PARAM rq
+
+/* Make the yyerror below use the rdf_parser */
+#undef yyerror
+#define yyerror(message) sparql_query_error((rasqal_query*)rq, message)
+
+/* Make lex/yacc interface as small as possible */
+#undef yylex
+#define yylex sparql_lexer_lex
+
+
+static int sparql_parse(rasqal_query* rq);
+static void sparql_query_error(rasqal_query* rq, const char *message);
+static void sparql_query_error_full(rasqal_query *rq, const char *message, ...) RASQAL_PRINTF_FORMAT(2, 3);
+
+%}
+
+
+/* directives */
+
+
+%pure-parser
+
+
+/* Interface between lexer and parser */
+%union {
+  raptor_sequence *seq;
+  rasqal_variable *variable;
+  rasqal_literal *literal;
+  rasqal_triple *triple;
+  rasqal_expression *expr;
+  rasqal_graph_pattern *graph_pattern;
+  double floating;
+  raptor_uri *uri;
+  unsigned char *name;
+  rasqal_formula *formula;
+}
+
+
+/*
+ * shift/reduce conflicts
+ * FIXME: document this
+ */
+%expect 4
+
+/* word symbols */
+%token SELECT FROM WHERE
+%token OPTIONAL DESCRIBE CONSTRUCT ASK DISTINCT REDUCED LIMIT UNION
+%token PREFIX BASE BOUND
+%token GRAPH NAMED FILTER OFFSET ORDER BY REGEX ASC DESC LANGMATCHES
+%token A "a"
+%token STR "str"
+%token LANG "lang"
+%token DATATYPE "datatype"
+%token ISURI "isUri"
+%token ISBLANK "isBlank"
+%token ISLITERAL "isLiteral"
+%token SAMETERM "sameTerm"
+/* LAQRS */
+%token EXPLAIN GROUP COUNT AS
+%token DELETE INSERT
+
+
+/* expression delimiters */
+
+%token ',' '(' ')' '[' ']' '{' '}'
+%token '?' '$'
+
+/* SC booleans */
+%left SC_OR
+%left SC_AND
+
+/* operations */
+%left EQ
+%left NEQ
+%left LT
+%left GT
+%left LE
+%left GE
+
+
+/* arithmetic operations */
+%left '+' '-' '*' '/'
+
+/* unary operations */
+
+/* literals */
+%token <literal> STRING_LITERAL "string literal"
+%token <literal> DOUBLE_LITERAL "double literal"
+%token <literal> DOUBLE_POSITIVE_LITERAL "double positive literal"
+%token <literal> DOUBLE_NEGATIVE_LITERAL "double negative literal"
+%token <literal> INTEGER_LITERAL "integer literal"
+%token <literal> INTEGER_POSITIVE_LITERAL "integer positive literal"
+%token <literal> INTEGER_NEGATIVE_LITERAL "integer negative literal"
+%token <literal> DECIMAL_LITERAL "decimal literal"
+%token <literal> DECIMAL_POSITIVE_LITERAL "decimal positive literal"
+%token <literal> DECIMAL_NEGATIVE_LITERAL "decimal negative literal"
+%token <literal> BOOLEAN_LITERAL "boolean literal"
+
+%token <uri> URI_LITERAL "URI literal"
+%token <uri> URI_LITERAL_BRACE "URI literal ("
+
+%token <name> QNAME_LITERAL "QName literal"
+%token <name> QNAME_LITERAL_BRACE "QName literal ("
+%token <name> BLANK_LITERAL "blank node literal"
+%token <name> IDENTIFIER "identifier"
+
+
+%type <seq> SelectQuery ConstructQuery DescribeQuery
+%type <seq> SelectExpressionList VarOrIRIrefList ArgList ConstructTriplesOpt
+%type <seq> ConstructTemplate OrderConditionList
+%type <seq> GraphNodeListNotEmpty SelectExpressionListTail
+
+%type <formula> TriplesSameSubject
+%type <formula> PropertyList PropertyListTailOpt PropertyListNotEmpty
+%type <formula> ObjectList ObjectTail Collection
+%type <formula> VarOrTerm Verb Object GraphNode TriplesNode
+%type <formula> BlankNodePropertyList
+%type <formula> TriplesBlock TriplesBlockOpt 
+
+%type <graph_pattern> GroupGraphPattern
+%type <graph_pattern> GraphGraphPattern OptionalGraphPattern
+%type <graph_pattern> GroupOrUnionGraphPattern GroupOrUnionGraphPatternList
+%type <graph_pattern> GraphPatternNotTriples
+%type <graph_pattern> GraphPatternListOpt GraphPatternList GraphPatternListFilter
+
+%type <expr> Expression ConditionalOrExpression ConditionalAndExpression
+%type <expr> RelationalExpression AdditiveExpression
+%type <expr> MultiplicativeExpression UnaryExpression
+%type <expr> BuiltInCall RegexExpression FunctionCall
+%type <expr> BrackettedExpression PrimaryExpression
+%type <expr> OrderCondition Filter Constraint SelectExpression
+%type <expr> AggregateExpression CountAggregateExpression
+
+%type <literal> GraphTerm IRIref BlankNode
+%type <literal> VarOrIRIref
+%type <literal> IRIrefBrace SourceSelector
+%type <literal> NumericLiteral NumericLiteralUnsigned
+%type <literal> NumericLiteralPositive NumericLiteralNegative
+
+%type <variable> Var VarName SelectTerm
+
+
+%destructor {
+  if($$)
+    rasqal_free_literal($$);
+}
+STRING_LITERAL 
+DOUBLE_LITERAL INTEGER_LITERAL DECIMAL_LITERAL
+DOUBLE_POSITIVE_LITERAL DOUBLE_NEGATIVE_LITERAL
+INTEGER_POSITIVE_LITERAL INTEGER_NEGATIVE_LITERAL
+DECIMAL_POSITIVE_LITERAL DECIMAL_NEGATIVE_LITERAL
+BOOLEAN_LITERAL
+
+%destructor {
+  if($$)
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(((rasqal_query*)rq)->world->raptor_world_ptr, $$);
+#else
+    raptor_free_uri($$);
+#endif
+}
+URI_LITERAL URI_LITERAL_BRACE
+
+%destructor {
+  if($$)
+    RASQAL_FREE(cstring, $$);
+}
+QNAME_LITERAL QNAME_LITERAL_BRACE BLANK_LITERAL IDENTIFIER
+
+%destructor {
+  if($$)
+    raptor_free_sequence($$);
+}
+SelectQuery ConstructQuery DescribeQuery
+SelectExpressionList VarOrIRIrefList ArgList ConstructTriplesOpt
+ConstructTemplate OrderConditionList
+GraphNodeListNotEmpty SelectExpressionListTail
+
+%destructor {
+  if($$)
+    rasqal_free_formula($$);
+}
+TriplesSameSubject
+PropertyList PropertyListTailOpt PropertyListNotEmpty
+ObjectList ObjectTail Collection
+VarOrTerm Verb Object GraphNode TriplesNode
+BlankNodePropertyList
+TriplesBlock TriplesBlockOpt
+
+%destructor {
+  if($$)
+    rasqal_free_graph_pattern($$);
+}
+GroupGraphPattern
+GraphGraphPattern OptionalGraphPattern
+GroupOrUnionGraphPattern GroupOrUnionGraphPatternList
+GraphPatternNotTriples
+GraphPatternListOpt GraphPatternList GraphPatternListFilter
+
+%destructor {
+  if($$)
+    rasqal_free_expression($$);
+}
+Expression ConditionalOrExpression ConditionalAndExpression
+RelationalExpression AdditiveExpression
+MultiplicativeExpression UnaryExpression
+BuiltInCall RegexExpression FunctionCall
+BrackettedExpression PrimaryExpression
+OrderCondition Filter Constraint SelectExpression
+AggregateExpression CountAggregateExpression
+
+%destructor {
+  if($$)
+    rasqal_free_literal($$);
+}
+GraphTerm IRIref BlankNode
+VarOrIRIref
+IRIrefBrace SourceSelector
+NumericLiteral NumericLiteralUnsigned
+NumericLiteralPositive NumericLiteralNegative
+
+%destructor {
+  if($$)
+    rasqal_free_variable($$);
+}
+Var VarName SelectTerm
+
+
+%%
+
+/* Below here, grammar terms are numbered from
+ * http://www.w3.org/TR/2005/WD-rdf-sparql-query-20051123/
+ * except where noted
+ */
+
+/* SPARQL Grammar: [1] Query */
+Query: Prologue ExplainOpt ReportFormat
+{
+}
+;
+
+/* LAQRS */
+ExplainOpt: EXPLAIN
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(sparql->extended)
+    ((rasqal_query*)rq)->explain=1;
+  else
+    sparql_syntax_error((rasqal_query*)rq, "EXPLAIN cannot be used with SPARQL");
+}
+|
+{
+  /* nothing to do */
+}
+;
+
+
+/* NEW Grammar Term pulled out of [1] Query */
+ReportFormat: SelectQuery
+{
+  ((rasqal_query*)rq)->selects=$1;
+  ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_SELECT;
+}
+|  ConstructQuery
+{
+  ((rasqal_query*)rq)->constructs=$1;
+  ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_CONSTRUCT;
+}
+|  DescribeQuery
+{
+  ((rasqal_query*)rq)->describes=$1;
+  ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_DESCRIBE;
+}
+| AskQuery
+{
+  ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_ASK;
+}
+| DeleteQuery
+{
+  ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_DELETE;
+}
+| InsertQuery
+{
+  ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_INSERT;
+}
+;
+
+
+/* SPARQL Grammar: [2] Prologue */
+Prologue: BaseDeclOpt PrefixDeclListOpt
+{
+  /* nothing to do */
+}
+;
+
+
+/* SPARQL Grammar: [3] BaseDecl */
+BaseDeclOpt: BASE URI_LITERAL
+{
+  rasqal_query_set_base_uri((rasqal_query*)rq, $2);
+}
+| /* empty */
+{
+  /* nothing to do */
+}
+;
+
+
+/* SPARQL Grammar: [4] PrefixDecl renamed to include optional list */
+PrefixDeclListOpt: PrefixDeclListOpt PREFIX IDENTIFIER URI_LITERAL
+{
+  raptor_sequence *seq=((rasqal_query*)rq)->prefixes;
+  unsigned const char* prefix_string=$3;
+  size_t l=0;
+
+  if(prefix_string)
+    l=strlen((const char*)prefix_string);
+  
+  if(raptor_namespaces_find_namespace(((rasqal_query*)rq)->namespaces, prefix_string, l)) {
+    /* A prefix may be defined only once */
+    sparql_syntax_warning(((rasqal_query*)rq), 
+                          "PREFIX %s can be defined only once.",
+                          prefix_string ? (const char*)prefix_string : ":");
+    RASQAL_FREE(cstring, prefix_string);
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(((rasqal_query*)rq)->world->raptor_world_ptr, $4);
+#else
+    raptor_free_uri($4);
+#endif
+  } else {
+    rasqal_prefix *p=rasqal_new_prefix(((rasqal_query*)rq)->world, prefix_string, $4);
+    if(!p)
+      YYERROR_MSG("PrefixDeclOpt: failed to create new prefix");
+    if(raptor_sequence_push(seq, p))
+      YYERROR_MSG("PrefixDeclOpt: cannot push prefix to seq");
+    if(rasqal_query_declare_prefix(((rasqal_query*)rq), p)) {
+      YYERROR_MSG("PrefixDeclOpt: cannot declare prefix");
+    }
+  }
+}
+| /* empty */
+{
+  /* nothing to do, rq->prefixes already initialised */
+}
+;
+
+
+/* SPARQL Grammar: [5] SelectQuery */
+SelectQuery: SELECT DISTINCT SelectExpressionList
+        DatasetClauseListOpt WhereClauseOpt SolutionModifier
+{
+  $$=$3;
+  ((rasqal_query*)rq)->distinct=1;
+}
+| SELECT REDUCED SelectExpressionList
+        DatasetClauseListOpt WhereClauseOpt SolutionModifier
+{
+  $$=$3;
+  ((rasqal_query*)rq)->distinct=2;
+}
+| SELECT SelectExpressionList
+        DatasetClauseListOpt WhereClauseOpt SolutionModifier
+{
+  $$=$2;
+}
+;
+
+
+/* NEW Grammar Term pulled out of [5] SelectQuery
+ * A list of SelectTerm OR a NULL list and a wildcard
+ */
+SelectExpressionList: SelectExpressionListTail
+{
+  $$=$1;
+}
+| '*'
+{
+  $$=NULL;
+  ((rasqal_query*)rq)->wildcard=1;
+}
+;
+
+
+/* NEW Grammar Term pulled out of [5] SelectQuery 
+ * Non-empty list of SelectTerm with optional commas
+ */
+SelectExpressionListTail: SelectExpressionListTail SelectTerm
+{
+  $$=$1;
+  if(raptor_sequence_push($$, $2)) {
+    raptor_free_sequence($$);
+    $$=NULL;
+    YYERROR_MSG("SelectExpressionListTail 1: sequence push failed");
+  }
+}
+| SelectExpressionListTail ',' SelectTerm
+{
+  $$=$1;
+  if(raptor_sequence_push($$, $3)) {
+    raptor_free_sequence($$);
+    $$=NULL;
+    YYERROR_MSG("SelectExpressionListTail 2: sequence push failed");
+  }
+}
+| SelectTerm
+{
+  /* The variables are freed from the raptor_query field variables */
+  $$=raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_variable_print);
+  if(!$$)
+    YYERROR_MSG("SelectExpressionListTail 3: failed to create sequence");
+  if(raptor_sequence_push($$, $1)) {
+    raptor_free_sequence($$);
+    $$=NULL;
+    YYERROR_MSG("SelectExpressionListTail 3: sequence push failed");
+  }
+}
+;
+
+
+/* NEW Grammar Term pulled out of [5] SelectQuery 
+ * A variable (?x) or a select expression assigned to a name (x) with AS
+ */
+SelectTerm: Var
+{
+  $$=$1;
+}
+| SelectExpression AS VarName
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  $$=NULL;
+  if(!sparql->extended)
+    sparql_syntax_error((rasqal_query*)rq, "SELECT expression AS Variable cannot be used with SPARQL");
+  else {
+    if(rasqal_expression_mentions_variable($1, $3)) {
+      sparql_query_error_full((rasqal_query*)rq, "SELECT expression contains the AS variable name '%s'", $3->name);
+    } else {
+      $$=$3;
+      $3->expression=$1;
+    }
+
+  }
+}
+;
+
+
+/* NEW Grammar Term pulled out of [5] SelectQuery */
+SelectExpression: AggregateExpression
+{
+  $$=$1;
+}
+| '(' AggregateExpression ')'
+{
+  $$=$2;
+}
+| '(' Expression ')'
+{
+  $$=$2;
+}
+;
+
+
+AggregateExpression: CountAggregateExpression
+{
+  $$=$1;
+}
+;
+
+
+CountAggregateExpression: COUNT '(' Expression ')'
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended) {
+    sparql_syntax_error((rasqal_query*)rq, "COUNT cannot be used with SPARQL");
+    $$=NULL;
+  } else {
+    $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_COUNT, $3);
+    if(!$$)
+      YYERROR_MSG("CountAggregateExpression 1: cannot create expr");
+  }
+}
+| COUNT '(' '*' ')'
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended) {
+    sparql_syntax_error((rasqal_query*)rq, "COUNT cannot be used with SPARQL");
+    $$=NULL;
+  } else {
+    rasqal_expression* vs=rasqal_new_0op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_VARSTAR);
+    if(!vs)
+      YYERROR_MSG("CountAggregateExpression 2: cannot create varstar expr");
+    $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_COUNT, vs);
+    if(!$$)
+      YYERROR_MSG("CountAggregateExpression 2: cannot create expr");
+  }
+}
+;
+
+
+/* SPARQL Grammar: [6] ConstructQuery */
+ConstructQuery: CONSTRUCT ConstructTemplate
+        DatasetClauseListOpt WhereClauseOpt SolutionModifier
+{
+  $$=$2;
+}
+;
+
+
+/* SPARQL Grammar: [7] DescribeQuery */
+DescribeQuery: DESCRIBE VarOrIRIrefList
+        DatasetClauseListOpt WhereClauseOpt SolutionModifier
+{
+  $$=$2;
+}
+| DESCRIBE '*'
+        DatasetClauseListOpt WhereClauseOpt SolutionModifier
+{
+  $$=NULL;
+}
+;
+
+
+/* NEW Grammar Term pulled out of [7] DescribeQuery */
+VarOrIRIrefList: VarOrIRIrefList VarOrIRIref
+{
+  $$=$1;
+  if(raptor_sequence_push($$, $2)) {
+    raptor_free_sequence($$);
+    $$=NULL;
+    YYERROR_MSG("VarOrIRIrefList 1: sequence push failed");
+  }
+}
+| VarOrIRIrefList ',' VarOrIRIref
+{
+  $$=$1;
+  if(raptor_sequence_push($$, $3)) {
+    raptor_free_sequence($$);
+    $$=NULL;
+    YYERROR_MSG("VarOrIRIrefList 2: sequence push failed");
+  }
+}
+| VarOrIRIref
+{
+  $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_literal, (raptor_sequence_print_handler*)rasqal_literal_print);
+  if(!$$)
+    YYERROR_MSG("VarOrIRIrefList 3: cannot create seq");
+  if(raptor_sequence_push($$, $1)) {
+    raptor_free_sequence($$);
+    $$=NULL;
+    YYERROR_MSG("VarOrIRIrefList 3: sequence push failed");
+  }
+}
+;
+
+
+/* SPARQL Grammar: [8] AskQuery */
+AskQuery: ASK 
+        DatasetClauseListOpt WhereClauseOpt
+{
+  /* nothing to do */
+}
+;
+
+
+/* LAQRS */
+DeleteQuery: DELETE
+        DatasetClauseListOpt WhereClauseOpt
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended)
+    sparql_syntax_error((rasqal_query*)rq, "DELETE cannot be used with SPARQL");
+}
+;
+
+
+/* LAQRS */
+InsertQuery: INSERT
+        DatasetClauseListOpt WhereClauseOpt
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended)
+    sparql_syntax_error((rasqal_query*)rq, "INSERT cannot be used with SPARQL");
+}
+;
+
+
+/* SPARQL Grammar: [9] DatasetClause */
+DatasetClauseListOpt: DatasetClauseListOpt FROM DefaultGraphClause
+| DatasetClauseListOpt FROM NamedGraphClause
+| /* empty */
+;
+
+
+/* SPARQL Grammar: [10] DefaultGraphClause */
+DefaultGraphClause: SourceSelector
+{
+  if($1) {
+    raptor_uri* uri=rasqal_literal_as_uri($1);
+    if(rasqal_query_add_data_graph((rasqal_query*)rq, uri, NULL,
+                                   RASQAL_DATA_GRAPH_BACKGROUND)) {
+      rasqal_free_literal($1);
+      YYERROR_MSG("DefaultGraphClause: rasqal_query_add_data_graph failed");
+    }
+    rasqal_free_literal($1);
+  }
+}
+;  
+
+
+/* SPARQL Grammar: [11] NamedGraphClause */
+NamedGraphClause: NAMED SourceSelector
+{
+  if($2) {
+    raptor_uri* uri=rasqal_literal_as_uri($2);
+    if(rasqal_query_add_data_graph((rasqal_query*)rq, uri, uri,
+                                   RASQAL_DATA_GRAPH_NAMED)) {
+      rasqal_free_literal($2);
+      YYERROR_MSG("NamedGraphClause: rasqal_query_add_data_graph failed");
+    }
+    rasqal_free_literal($2);
+  }
+}
+;
+
+
+/* SPARQL Grammar: [12] SourceSelector */
+SourceSelector: IRIref
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [13] WhereClause - remained for clarity */
+WhereClauseOpt:  WHERE GroupGraphPattern
+{
+  ((rasqal_query*)rq)->query_graph_pattern=$2;
+}
+| GroupGraphPattern
+{
+  ((rasqal_query*)rq)->query_graph_pattern=$1;
+}
+| /* empty */
+;
+
+
+/* SPARQL Grammar: [14] SolutionModifier */
+SolutionModifier: GroupClauseOpt OrderClauseOpt LimitOffsetClausesOpt
+;
+
+
+/* LAQRS */
+GroupClauseOpt: GROUP BY OrderConditionList
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended)
+    sparql_syntax_error((rasqal_query*)rq, "GROUP BY cannot be used with SPARQL");
+  else if(((rasqal_query*)rq)->verb == RASQAL_QUERY_VERB_ASK) {
+    sparql_query_error((rasqal_query*)rq, "GROUP BY cannot be used with ASK");
+  } else {
+    raptor_sequence *seq=$3;
+    ((rasqal_query*)rq)->group_conditions_sequence=seq;
+    if(seq) {
+      int i;
+      
+      for(i=0; i < raptor_sequence_size(seq); i++) {
+        rasqal_expression* e=(rasqal_expression*)raptor_sequence_get_at(seq, i);
+        if(e->op == RASQAL_EXPR_ORDER_COND_ASC)
+          e->op = RASQAL_EXPR_GROUP_COND_ASC;
+        else
+          e->op = RASQAL_EXPR_GROUP_COND_DESC;
+      }
+    }
+  }
+}
+| /* empty */
+;
+
+
+/* SPARQL Grammar: [15] LimitOffsetClauses */
+LimitOffsetClausesOpt: LimitClause OffsetClause
+| OffsetClause LimitClause
+| LimitClause
+| OffsetClause
+| /* empty */
+{ 
+}
+;
+
+
+/* SPARQL Grammar: [16] OrderClause - remained for clarity */
+OrderClauseOpt: ORDER BY OrderConditionList
+{
+  if(((rasqal_query*)rq)->verb == RASQAL_QUERY_VERB_ASK) {
+    sparql_query_error((rasqal_query*)rq, "ORDER BY cannot be used with ASK");
+  } else {
+    ((rasqal_query*)rq)->order_conditions_sequence=$3;
+  }
+}
+| /* empty */
+;
+
+
+/* NEW Grammar Term pulled out of [16] OrderClauseOpt */
+OrderConditionList: OrderConditionList OrderCondition
+{
+  $$=$1;
+  if($2)
+    if(raptor_sequence_push($$, $2)) {
+      raptor_free_sequence($$);
+      $$=NULL;
+      YYERROR_MSG("OrderConditionList 1: sequence push failed");
+    }
+}
+| OrderCondition
+{
+  $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_expression, (raptor_sequence_print_handler*)rasqal_expression_print);
+  if(!$$) {
+    if($1)
+      rasqal_free_expression($1);
+    YYERROR_MSG("OrderConditionList 2: cannot create sequence");
+  }
+  if($1)
+    if(raptor_sequence_push($$, $1)) {
+      raptor_free_sequence($$);
+      $$=NULL;
+      YYERROR_MSG("OrderConditionList 2: sequence push failed");
+    }
+}
+;
+
+
+/* SPARQL Grammar: [17] OrderCondition */
+OrderCondition: ASC BrackettedExpression
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ORDER_COND_ASC, $2);
+  if(!$$)
+    YYERROR_MSG("OrderCondition 1: cannot create expr");
+}
+| DESC BrackettedExpression
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ORDER_COND_DESC, $2);
+  if(!$$)
+    YYERROR_MSG("OrderCondition 2: cannot create expr");
+}
+| FunctionCall 
+{
+  /* The direction of ordering is ascending by default */
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ORDER_COND_ASC, $1);
+  if(!$$)
+    YYERROR_MSG("OrderCondition 3: cannot create expr");
+}
+| Var
+{
+  rasqal_literal* l;
+  rasqal_expression *e;
+  l=rasqal_new_variable_literal(((rasqal_query*)rq)->world, $1);
+  if(!l)
+    YYERROR_MSG("OrderCondition 4: cannot create lit");
+  e=rasqal_new_literal_expression(((rasqal_query*)rq)->world, l);
+  if(!e)
+    YYERROR_MSG("OrderCondition 4: cannot create lit expr");
+
+  /* The direction of ordering is ascending by default */
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ORDER_COND_ASC, e);
+  if(!$$)
+    YYERROR_MSG("OrderCondition 1: cannot create expr");
+}
+| BrackettedExpression
+{
+  /* The direction of ordering is ascending by default */
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ORDER_COND_ASC, $1);
+  if(!$$)
+    YYERROR_MSG("OrderCondition 5: cannot create expr");
+}
+| BuiltInCall
+{
+  /* The direction of ordering is ascending by default */
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ORDER_COND_ASC, $1);
+  if(!$$)
+    YYERROR_MSG("OrderCondition 6: cannot create expr");
+}
+;
+
+
+/* SPARQL Grammar: [18] LimitClause - remained for clarity */
+LimitClause:  LIMIT INTEGER_LITERAL
+{
+  if(((rasqal_query*)rq)->verb == RASQAL_QUERY_VERB_ASK) {
+    sparql_query_error((rasqal_query*)rq, "LIMIT cannot be used with ASK");
+  } else {
+    if($2 != NULL) {
+      ((rasqal_query*)rq)->limit=$2->value.integer;
+      rasqal_free_literal($2);
+    }
+  }
+  
+}
+;
+
+
+/* SPARQL Grammar: [19] OffsetClause - remained for clarity */
+OffsetClause:  OFFSET INTEGER_LITERAL
+{
+  if(((rasqal_query*)rq)->verb == RASQAL_QUERY_VERB_ASK) {
+    sparql_query_error((rasqal_query*)rq, "LIMIT cannot be used with ASK");
+  } else {
+    if($2 != NULL) {
+      ((rasqal_query*)rq)->offset=$2->value.integer;
+      rasqal_free_literal($2);
+    }
+  }
+}
+;
+
+
+/* SPARQL Grammar: [20] GroupGraphPattern 
+ * TriplesBlockOpt: formula or NULL (on success or error)
+ * GraphPatternListOpt: always 1 Group GP or NULL (on error)
+ */
+GroupGraphPattern: '{' TriplesBlockOpt GraphPatternListOpt '}'
+{
+  rasqal_graph_pattern *formula_gp=NULL;
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "GroupGraphPattern\n  TriplesBlockOpt=");
+  if($2)
+    rasqal_formula_print($2, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, ", GraphpatternListOpt=");
+  if($3)
+    rasqal_graph_pattern_print($3, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n", DEBUG_FH);
+#endif
+
+
+  if(!$2 && !$3) {
+    $$=rasqal_new_2_group_graph_pattern((rasqal_query*)rq, NULL, NULL);
+    if(!$$)
+      YYERROR_MSG("GroupGraphPattern: cannot create group gp");
+  } else {
+    if($2) {
+      formula_gp=rasqal_new_basic_graph_pattern_from_formula((rasqal_query*)rq, $2);
+      if(!formula_gp) {
+        if($3)
+          rasqal_free_graph_pattern($3);
+        YYERROR_MSG("GroupGraphPattern: cannot create formula_gp");
+      }
+    }
+
+    if($3) {
+      $$=$3;
+      if(formula_gp && raptor_sequence_shift($$->graph_patterns, formula_gp)) {
+        rasqal_free_graph_pattern($$);
+        $$=NULL;
+        YYERROR_MSG("GroupGraphPattern: sequence push failed");
+      }
+    } else
+      $$=formula_gp;
+  }
+  
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  after graph pattern=");
+  if($$)
+    rasqal_graph_pattern_print($$, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+;
+
+
+/* Pulled out of SPARQL Grammar: [20] GroupGraphPattern */
+TriplesBlockOpt: TriplesBlock
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "TriplesBlockOpt 1\n  TriplesBlock=");
+  if($1)
+    rasqal_formula_print($1, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n\n", DEBUG_FH);
+#endif
+
+  $$=$1;
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+
+/* Pulled out of SPARQL Grammar: [20] GroupGraphPattern 
+ * GraphPatternListOpt: always 1 Group GP or NULL
+ * GraphPatternList: always 1 Group GP or NULL (on error)
+ *
+ * Result: always 1 Group GP or NULL (on error)
+ */
+GraphPatternListOpt: GraphPatternListOpt GraphPatternList
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "GraphPatternListOpt\n  GraphPatternListOpt=");
+  if($1)
+    rasqal_graph_pattern_print($1, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, ", GraphPatternList=");
+  if($2)
+    rasqal_graph_pattern_print($2, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n", DEBUG_FH);
+#endif
+
+  $$= ($1 ? $1 : $2);
+  if($1 && $2) {
+    $$=$1;
+    if(rasqal_graph_patterns_join($$, $2)) {
+      rasqal_free_graph_pattern($$);
+      rasqal_free_graph_pattern($2);
+      $$=NULL;
+      YYERROR_MSG("ConstructTriplesOpt: sequence join failed");
+    }
+    rasqal_free_graph_pattern($2);
+  }
+  
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  after grouping graph pattern=");
+  if($$)
+    rasqal_graph_pattern_print($$, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+| GraphPatternList
+{
+  $$=$1;
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+
+/* Pulled out of SPARQL Grammar: [20] GroupGraphPattern 
+ * GraphPatternListFilter: always 1 GP or NULL (on error)
+ * TriplesBlockOpt: formula or NULL (on success or error)
+ *
+ * Result: always 1 Group GP or NULL (on success or error)
+ */
+GraphPatternList: GraphPatternListFilter DotOptional TriplesBlockOpt
+{
+  rasqal_graph_pattern *formula_gp=NULL;
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "GraphPatternList\n  GraphPatternListFilter=");
+  if($1)
+    rasqal_graph_pattern_print($1, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, ", TriplesBlockOpt=");
+  if($3)
+    rasqal_formula_print($3, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n", DEBUG_FH);
+#endif
+
+  if($3) {
+    formula_gp=rasqal_new_basic_graph_pattern_from_formula((rasqal_query*)rq, $3);
+    if(!formula_gp) {
+      if($1)
+        rasqal_free_graph_pattern($1);
+      YYERROR_MSG("GraphPatternList: cannot create formula_gp");
+    }
+  }
+  $$=rasqal_new_2_group_graph_pattern((rasqal_query*)rq, $1, formula_gp);
+  if(!$$)
+    YYERROR_MSG("GraphPatternList: cannot create sequence");
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  after graph pattern=");
+  if($$)
+    rasqal_graph_pattern_print($$, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+;
+
+
+/* Pulled out of SPARQL Grammar: [20] GroupGraphPattern 
+ * GraphPatternNotTriples: always 1 GP or NULL (on error)
+ *
+ * Result: always 1 GP or NULL (on error)
+ */
+GraphPatternListFilter: GraphPatternNotTriples
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "GraphPatternListFilter 1\n  GraphPatternNotTriples=");
+  if($1)
+    rasqal_graph_pattern_print($1, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n\n", DEBUG_FH);
+#endif
+
+  $$=$1;
+}
+| Filter
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "GraphPatternListFilter 2\n  Filter=");
+  if($1)
+    rasqal_expression_print($1, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n", DEBUG_FH);
+#endif
+
+  $$=rasqal_new_filter_graph_pattern((rasqal_query*)rq, $1);
+  if(!$$)
+    YYERROR_MSG("GraphPatternListFilter 2: cannot create graph pattern");
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  after graph pattern=");
+  if($$)
+    rasqal_graph_pattern_print($$, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+;
+
+
+/* NEW Grammar Term */
+DotOptional: '.'
+| /* empty */
+;
+
+
+/* SPARQL Grammar: [21] TriplesBlock */
+TriplesBlock: TriplesSameSubject '.' TriplesBlockOpt
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "TriplesBlock\n  TriplesSameSubject=");
+  if($1)
+    rasqal_formula_print($1, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, ", TriplesBlockOpt=");
+  if($3)
+    rasqal_formula_print($3, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n", DEBUG_FH);
+#endif
+
+
+  $$= ($1 ? $1 : $3);
+  if($1 && $3) {
+    /* $1 and $3 are freed as necessary */
+    $$=rasqal_formula_join($1, $3);
+    if(!$1)
+      YYERROR_MSG("TriplesBlock: formula join failed");
+  }
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  after joining formula=");
+  rasqal_formula_print($$, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+| TriplesSameSubject
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [22] GraphPatternNotTriples */
+GraphPatternNotTriples: OptionalGraphPattern
+{
+  $$=$1;
+}
+| GroupOrUnionGraphPattern
+{
+  $$=$1;
+}
+| GraphGraphPattern
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [23] OptionalGraphPattern */
+OptionalGraphPattern: OPTIONAL GroupGraphPattern
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "PatternElementForms 4\n  graphpattern=");
+  if($2)
+    rasqal_graph_pattern_print($2, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n\n", DEBUG_FH);
+#endif
+
+  $$=NULL;
+
+  if($2) {
+    raptor_sequence *seq;
+
+    seq=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print);
+    if(!seq) {
+      rasqal_free_graph_pattern($2);
+      YYERROR_MSG("OptionalGraphPattern 1: cannot create sequence");
+    } else {
+      if(raptor_sequence_push(seq, $2)) {
+        raptor_free_sequence(seq);
+        YYERROR_MSG("OptionalGraphPattern 2: sequence push failed");
+      } else {
+        $$=rasqal_new_graph_pattern_from_sequence((rasqal_query*)rq,
+                                                  seq,
+                                                  RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL);
+        if(!$$)
+          YYERROR_MSG("OptionalGraphPattern: cannot create graph pattern");
+      }
+    }
+  }
+}
+;
+
+
+/* SPARQL Grammar: [24] GraphGraphPattern */
+GraphGraphPattern: GRAPH VarOrIRIref GroupGraphPattern
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "GraphGraphPattern 2\n  varoruri=");
+  rasqal_literal_print($2, DEBUG_FH);
+  fprintf(DEBUG_FH, ", graphpattern=");
+  if($3)
+    rasqal_graph_pattern_print($3, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fputs("\n\n", DEBUG_FH);
+#endif
+
+  if($3) {
+    rasqal_graph_pattern_set_origin($3, $2);
+    $3->op = RASQAL_GRAPH_PATTERN_OPERATOR_GRAPH;
+  }
+
+  rasqal_free_literal($2);
+  $$=$3;
+}
+;
+
+
+/* SPARQL Grammar: [25] GroupOrUnionGraphPattern */
+GroupOrUnionGraphPattern: GroupGraphPattern UNION GroupOrUnionGraphPatternList
+{
+  $$=$3;
+  if(raptor_sequence_shift($$->graph_patterns, $1)) {
+    rasqal_free_graph_pattern($$);
+    $$=NULL;
+    YYERROR_MSG("GroupOrUnionGraphPattern: sequence push failed");
+  }
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "UnionGraphPattern\n  graphpattern=");
+  rasqal_graph_pattern_print($$, DEBUG_FH);
+  fputs("\n\n", DEBUG_FH);
+#endif
+}
+| GroupGraphPattern
+{
+  $$=$1;
+}
+;
+
+/* NEW Grammar Term pulled out of [25] GroupOrUnionGraphPattern */
+GroupOrUnionGraphPatternList: GroupOrUnionGraphPatternList UNION GroupGraphPattern
+{
+  $$=$1;
+  if($3)
+    if(raptor_sequence_push($$->graph_patterns, $3)) {
+      rasqal_free_graph_pattern($$);
+      $$=NULL;
+      YYERROR_MSG("GroupOrUnionGraphPatternList 1: sequence push failed");
+    }
+}
+| GroupGraphPattern
+{
+  raptor_sequence *seq;
+  seq=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print);
+  if(!seq) {
+    if($1)
+      rasqal_free_graph_pattern($1);
+    YYERROR_MSG("GroupOrUnionGraphPatternList 2: cannot create sequence");
+  }
+  if($1)
+    if(raptor_sequence_push(seq, $1)) {
+      raptor_free_sequence(seq);
+      YYERROR_MSG("GroupOrUnionGraphPatternList 2: sequence push failed");
+    }
+  $$=rasqal_new_graph_pattern_from_sequence((rasqal_query*)rq,
+                                            seq,
+                                            RASQAL_GRAPH_PATTERN_OPERATOR_UNION);
+  if(!$$)
+    YYERROR_MSG("GroupOrUnionGraphPatternList 1: cannot create gp");
+}
+;
+
+
+/* SPARQL Grammar: [26] Filter */
+Filter: FILTER Constraint
+{
+  $$=$2;
+}
+;
+
+
+/* SPARQL Grammar: [27] Constraint */
+Constraint: BrackettedExpression
+{
+  $$=$1;
+}
+| BuiltInCall
+{
+  $$=$1;
+}
+| FunctionCall
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [28] FunctionCall */
+FunctionCall: IRIrefBrace ArgList ')'
+{
+  raptor_uri* uri=rasqal_literal_as_uri($1);
+  
+  if(!$2) {
+    $2=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_expression, (raptor_sequence_print_handler*)rasqal_expression_print);
+    if(!$2) {
+      rasqal_free_literal($1);
+      YYERROR_MSG("FunctionCall: cannot create sequence");
+    }
+  }
+
+#ifdef RAPTOR_V2_AVAILABLE
+  uri = raptor_uri_copy_v2(((rasqal_query*)rq)->world->raptor_world_ptr, uri);
+#else
+  uri = raptor_uri_copy(uri);
+#endif
+
+  if(raptor_sequence_size($2) == 1 &&
+     rasqal_xsd_is_datatype_uri(((rasqal_query*)rq)->world, uri)) {
+    rasqal_expression* e=(rasqal_expression*)raptor_sequence_pop($2);
+    $$=rasqal_new_cast_expression(((rasqal_query*)rq)->world, uri, e);
+    raptor_free_sequence($2);
+  } else {
+    $$=rasqal_new_function_expression(((rasqal_query*)rq)->world, uri, $2);
+  }
+  rasqal_free_literal($1);
+
+  if(!$$)
+    YYERROR_MSG("FunctionCall: cannot create expr");
+}
+;
+
+
+/* SPARQL Grammar: [29] ArgList */
+ArgList: ArgList ',' Expression
+{
+  $$=$1;
+  if($3)
+    if(raptor_sequence_push($$, $3)) {
+      raptor_free_sequence($$);
+      $$=NULL;
+      YYERROR_MSG("ArgList 1: sequence push failed");
+    }
+}
+| Expression
+{
+  $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_expression, (raptor_sequence_print_handler*)rasqal_expression_print);
+  if(!$$) {
+    if($1)
+      rasqal_free_expression($1);
+    YYERROR_MSG("ArgList 2: cannot create sequence");
+  }
+  if($1)
+    if(raptor_sequence_push($$, $1)) {
+      raptor_free_sequence($$);
+      $$=NULL;
+      YYERROR_MSG("ArgList 2: sequence push failed");
+    }
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+
+/* SPARQL Grammar: [30] ConstructTemplate */
+ConstructTemplate:  '{' ConstructTriplesOpt '}'
+{
+  $$=$2;
+}
+;
+
+
+/* SPARQL Grammar: [31] ConstructTriples renamed for clarity */
+ConstructTriplesOpt: TriplesSameSubject '.' ConstructTriplesOpt
+{
+  $$=NULL;
+ 
+  if($1) {
+    $$=$1->triples;
+    $1->triples=NULL;
+    rasqal_free_formula($1);
+  }
+  
+  if($3) {
+    if(!$$) {
+      $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print);
+      if(!$$) {
+        raptor_free_sequence($3);
+        YYERROR_MSG("ConstructTriplesOpt: cannot create sequence");
+      }
+    }
+
+    if(raptor_sequence_join($$, $3)) {
+      raptor_free_sequence($3);
+      raptor_free_sequence($$);
+      $$=NULL;
+      YYERROR_MSG("ConstructTriplesOpt: sequence join failed");
+    }
+    raptor_free_sequence($3);
+  }
+
+ }
+| TriplesSameSubject
+{
+  $$=NULL;
+  
+  if($1) {
+    $$=$1->triples;
+    $1->triples=NULL;
+    rasqal_free_formula($1);
+  }
+  
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+
+/* SPARQL Grammar: [32] TriplesSameSubject */
+TriplesSameSubject: VarOrTerm PropertyListNotEmpty
+{
+  int i;
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "TriplesSameSubject 1\n  subject=");
+  rasqal_formula_print($1, DEBUG_FH);
+  if($2) {
+    fprintf(DEBUG_FH, "\n  propertyList=");
+    rasqal_formula_print($2, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+  } else     
+    fprintf(DEBUG_FH, "\n  and empty propertyList\n");
+#endif
+
+  if($2) {
+    raptor_sequence *seq=$2->triples;
+    rasqal_literal *subject=$1->value;
+    
+    /* non-empty property list, handle it  */
+    for(i=0; i < raptor_sequence_size(seq); i++) {
+      rasqal_triple* t2=(rasqal_triple*)raptor_sequence_get_at(seq, i);
+      if(t2->subject)
+        continue;
+      t2->subject=rasqal_new_literal_from_literal(subject);
+    }
+#if RASQAL_DEBUG > 1  
+    fprintf(DEBUG_FH, "  after substitution propertyList=");
+    rasqal_formula_print($2, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+#endif
+  }
+
+  $$=rasqal_formula_join($1, $2);
+  if(!$$)
+    YYERROR_MSG("TriplesSameSubject 1: formula join failed");
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  after joining formula=");
+  rasqal_formula_print($$, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+| TriplesNode PropertyList
+{
+  int i;
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "TriplesSameSubject 2\n  subject=");
+  rasqal_formula_print($1, DEBUG_FH);
+  if($2) {
+    fprintf(DEBUG_FH, "\n  propertyList=");
+    rasqal_formula_print($2, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+  } else     
+    fprintf(DEBUG_FH, "\n  and empty propertyList\n");
+#endif
+
+  if($2) {
+    raptor_sequence *seq=$2->triples;
+    rasqal_literal *subject=$1->value;
+    
+    /* non-empty property list, handle it  */
+    for(i=0; i < raptor_sequence_size(seq); i++) {
+      rasqal_triple* t2=(rasqal_triple*)raptor_sequence_get_at(seq, i);
+      if(t2->subject)
+        continue;
+      t2->subject=rasqal_new_literal_from_literal(subject);
+    }
+#if RASQAL_DEBUG > 1  
+    fprintf(DEBUG_FH, "  after substitution propertyList=");
+    rasqal_formula_print($2, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+#endif
+  }
+
+  $$=rasqal_formula_join($1, $2);
+  if(!$$)
+    YYERROR_MSG("TriplesSameSubject 2: formula join failed");
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  after joining formula=");
+  rasqal_formula_print($$, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+;
+
+
+/* SPARQL Grammar: [33] PropertyListNotEmpty */
+PropertyListNotEmpty: Verb ObjectList PropertyListTailOpt
+{
+  int i;
+  
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "PropertyList 1\n  Verb=");
+  rasqal_formula_print($1, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n  ObjectList=");
+  rasqal_formula_print($2, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n  PropertyListTail=");
+  if($3 != NULL)
+    rasqal_formula_print($3, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, "\n");
+#endif
+  
+  if($2 == NULL) {
+#if RASQAL_DEBUG > 1  
+    fprintf(DEBUG_FH, " empty ObjectList not processed\n");
+#endif
+  } else if($1 && $2) {
+    raptor_sequence *seq=$2->triples;
+    rasqal_literal *predicate=$1->value;
+    rasqal_formula *formula;
+    rasqal_triple *t2;
+
+    formula=rasqal_new_formula();
+    if(!formula) {
+      rasqal_free_formula($1);
+      rasqal_free_formula($2);
+      if($3)
+        rasqal_free_formula($3);
+      YYERROR_MSG("PropertyList 1: cannot create formula");
+    }
+    formula->triples=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print);
+    if(!formula->triples) {
+      rasqal_free_formula(formula);
+      rasqal_free_formula($1);
+      rasqal_free_formula($2);
+      if($3)
+        rasqal_free_formula($3);
+      YYERROR_MSG("PropertyList 1: cannot create sequence");
+    }
+
+    /* non-empty property list, handle it  */
+    for(i=0; i<raptor_sequence_size(seq); i++) {
+      t2=(rasqal_triple*)raptor_sequence_get_at(seq, i);
+      if(!t2->predicate)
+        t2->predicate=(rasqal_literal*)rasqal_new_literal_from_literal(predicate);
+    }
+  
+#if RASQAL_DEBUG > 1  
+    fprintf(DEBUG_FH, "  after substitution ObjectList=");
+    raptor_sequence_print(seq, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+#endif
+
+    while(raptor_sequence_size(seq)) {
+      t2=(rasqal_triple*)raptor_sequence_unshift(seq);
+      if(raptor_sequence_push(formula->triples, t2)) {
+        rasqal_free_formula(formula);
+        rasqal_free_formula($1);
+        rasqal_free_formula($2);
+        if($3)
+          rasqal_free_formula($3);
+        YYERROR_MSG("PropertyList 1: sequence push failed");
+      }
+    }
+
+    $3=rasqal_formula_join(formula, $3);
+    if(!$3) {
+      rasqal_free_formula($1);
+      rasqal_free_formula($2);
+      YYERROR_MSG("PropertyList 1: formula join failed");
+    }
+
+#if RASQAL_DEBUG > 1  
+    fprintf(DEBUG_FH, "  after appending ObjectList=");
+    rasqal_formula_print($3, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n\n");
+#endif
+
+    rasqal_free_formula($2);
+  }
+
+  if($1)
+    rasqal_free_formula($1);
+
+  $$=$3;
+}
+;
+
+
+/* NEW Grammar Term pulled out of [33] PropertyListNotEmpty */
+PropertyListTailOpt: ';' PropertyList
+{
+  $$=$2;
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+
+/* SPARQL Grammar: [34] PropertyList */
+PropertyList: PropertyListNotEmpty
+{
+  $$=$1;
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+
+/* SPARQL Grammar: [35] ObjectList */
+ObjectList: Object ObjectTail
+{
+  rasqal_formula *formula;
+  rasqal_triple *triple;
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "ObjectList 1\n");
+  fprintf(DEBUG_FH, "  Object=\n");
+  rasqal_formula_print($1, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n");
+  if($2) {
+    fprintf(DEBUG_FH, "  ObjectTail=");
+    rasqal_formula_print($2, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+  } else
+    fprintf(DEBUG_FH, "  and empty ObjectTail\n");
+#endif
+
+  formula=rasqal_new_formula();
+  if(!formula) {
+    rasqal_free_formula($1);
+    if($2)
+      rasqal_free_formula($2);
+    YYERROR_MSG("ObjectList: cannot create formula");
+  }
+  
+  formula->triples=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print);
+  if(!formula->triples) {
+    rasqal_free_formula(formula);
+    rasqal_free_formula($1);
+    if($2)
+      rasqal_free_formula($2);
+    YYERROR_MSG("ObjectList: cannot create sequence");
+  }
+
+  triple=rasqal_new_triple(NULL, NULL, $1->value);
+  $1->value=NULL; /* value now owned by triple */
+  if(!triple) {
+    rasqal_free_formula(formula);
+    rasqal_free_formula($1);
+    if($2)
+      rasqal_free_formula($2);
+    YYERROR_MSG("ObjectList: cannot create triple");
+  }
+
+  if(raptor_sequence_push(formula->triples, triple)) {
+    rasqal_free_formula(formula);
+    rasqal_free_formula($1);
+    if($2)
+      rasqal_free_formula($2);
+    YYERROR_MSG("ObjectList: sequence push failed");
+  }
+
+  $$=rasqal_formula_join(formula, $1);
+  if(!$$) {
+    if($2)
+      rasqal_free_formula($2);
+    YYERROR_MSG("ObjectList: formula join $1 failed");
+  }
+
+  $$=rasqal_formula_join($$, $2);
+  if(!$$)
+    YYERROR_MSG("ObjectList: formula join $2 failed");
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  objectList is now ");
+  if($$)
+    raptor_sequence_print($$->triples, DEBUG_FH);
+  else
+    fputs("NULL", DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+;
+
+
+/* NEW Grammar Term pulled out of [35] ObjectList */
+ObjectTail: ',' ObjectList
+{
+  $$=$2;
+}
+| /* empty */
+{
+  $$=NULL;
+}
+;
+
+
+/* SPARQL Grammar: [36] Object */
+Object: GraphNode
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [37] Verb */
+Verb: VarOrIRIref
+{
+  $$=rasqal_new_formula();
+  if(!$$) {
+    if($1)
+      rasqal_free_literal($1);
+    YYERROR_MSG("Verb 1: cannot create formula");
+  }
+  $$->value=$1;
+}
+| A
+{
+  raptor_uri *uri;
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "verb Verb=rdf:type (a)\n");
+#endif
+
+#ifdef RAPTOR_V2_AVAILABLE
+  uri = raptor_new_uri_for_rdf_concept_v2(((rasqal_query*)rq)->world->raptor_world_ptr, "type");
+#else
+  uri = raptor_new_uri_for_rdf_concept("type");
+#endif
+  if(!uri)
+    YYERROR_MSG("Verb 2: uri for rdf concept type failed");
+  $$=rasqal_new_formula();
+  if(!$$) {
+#ifdef RAPTOR_V2_AVAILABLE
+    raptor_free_uri_v2(((rasqal_query*)rq)->world->raptor_world_ptr, uri);
+#else
+    raptor_free_uri(uri);
+#endif
+    YYERROR_MSG("Verb 2: cannot create formula");
+  }
+  $$->value=rasqal_new_uri_literal(((rasqal_query*)rq)->world, uri);
+  if(!$$->value) {
+    rasqal_free_formula($$);
+    $$=NULL;
+    YYERROR_MSG("Verb 2: cannot create uri literal");
+  }
+}
+;
+
+
+/* SPARQL Grammar: [38] TriplesNode */
+TriplesNode: Collection
+{
+  $$=$1;
+}
+| BlankNodePropertyList
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [39] BlankNodePropertyList */
+BlankNodePropertyList: '[' PropertyListNotEmpty ']'
+{
+  int i;
+  const unsigned char *id;
+
+  if($2 == NULL) {
+    $$=rasqal_new_formula();
+    if(!$$)
+      YYERROR_MSG("BlankNodePropertyList: cannot create formula");
+  } else {
+    $$=$2;
+    if($$->value) {
+      rasqal_free_literal($$->value);
+      $$->value=NULL;
+    }
+  }
+  
+  id=rasqal_query_generate_bnodeid((rasqal_query*)rq, NULL);
+  if(!id) {
+    rasqal_free_formula($$);
+    $$=NULL;
+    YYERROR_MSG("BlankNodeProperyList: cannot create bnodeid");
+  }
+
+  $$->value=rasqal_new_simple_literal(((rasqal_query*)rq)->world, RASQAL_LITERAL_BLANK, id);
+  if(!$$->value) {
+    rasqal_free_formula($$);
+    $$=NULL;
+    YYERROR_MSG("BlankNodePropertyList: cannot create literal");
+  }
+
+  if($2 == NULL) {
+#if RASQAL_DEBUG > 1  
+    fprintf(DEBUG_FH, "TriplesNode\n  PropertyList=");
+    rasqal_formula_print($$, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+#endif
+  } else {
+    raptor_sequence *seq=$2->triples;
+
+    /* non-empty property list, handle it  */
+#if RASQAL_DEBUG > 1  
+    fprintf(DEBUG_FH, "TriplesNode\n  PropertyList=");
+    raptor_sequence_print(seq, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+#endif
+
+    for(i=0; i<raptor_sequence_size(seq); i++) {
+      rasqal_triple* t2=(rasqal_triple*)raptor_sequence_get_at(seq, i);
+      if(t2->subject)
+        continue;
+      
+      t2->subject=(rasqal_literal*)rasqal_new_literal_from_literal($$->value);
+    }
+
+#if RASQAL_DEBUG > 1
+    fprintf(DEBUG_FH, "  after substitution formula=");
+    rasqal_formula_print($$, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n\n");
+#endif
+  }
+}
+;
+
+
+/* SPARQL Grammar: [40] Collection (allowing empty case) */
+Collection: '(' GraphNodeListNotEmpty ')'
+{
+  int i;
+  rasqal_query* rdf_query=(rasqal_query*)rq;
+  rasqal_literal* first_identifier=NULL;
+  rasqal_literal* rest_identifier=NULL;
+  rasqal_literal* object=NULL;
+  rasqal_literal* blank=NULL;
+
+#if RASQAL_DEBUG > 1
+  char const *errmsg;
+  #define YYERR_MSG_GOTO(label,msg) do { errmsg = msg; goto label; } while(0)
+#else
+  #define YYERR_MSG_GOTO(label,ignore) goto label
+#endif
+
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "Collection\n  GraphNodeListNotEmpty=");
+  raptor_sequence_print($2, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n");
+#endif
+
+  $$=rasqal_new_formula();
+  if(!$$)
+    YYERR_MSG_GOTO(err_Collection, "Collection: cannot create formula");
+
+  $$->triples=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print);
+  if(!$$->triples)
+    YYERR_MSG_GOTO(err_Collection, "Collection: cannot create sequence");
+
+  first_identifier = rasqal_new_uri_literal(rdf_query->world,
+#ifdef RAPTOR_V2_AVAILABLE
+                                            raptor_uri_copy_v2(rdf_query->world->raptor_world_ptr, rdf_query->world->rdf_first_uri)
+#else
+                                            raptor_uri_copy(rdf_query->world->rdf_first_uri)
+#endif
+                                            );
+  if(!first_identifier)
+    YYERR_MSG_GOTO(err_Collection, "Collection: cannot first_identifier");
+  
+  rest_identifier = rasqal_new_uri_literal(rdf_query->world,
+#ifdef RAPTOR_V2_AVAILABLE
+                                           raptor_uri_copy_v2(rdf_query->world->raptor_world_ptr, rdf_query->world->rdf_rest_uri)
+#else
+                                           raptor_uri_copy(rdf_query->world->rdf_rest_uri)
+#endif
+                                           );
+  if(!rest_identifier)
+    YYERR_MSG_GOTO(err_Collection, "Collection: cannot create rest_identifier");
+  
+  object = rasqal_new_uri_literal(rdf_query->world,
+#ifdef RAPTOR_V2_AVAILABLE
+                                  raptor_uri_copy_v2(rdf_query->world->raptor_world_ptr, rdf_query->world->rdf_nil_uri)
+#else
+                                  raptor_uri_copy(rdf_query->world->rdf_nil_uri)
+#endif
+                                  );
+  if(!object)
+    YYERR_MSG_GOTO(err_Collection, "Collection: cannot create nil object");
+
+  for(i=raptor_sequence_size($2)-1; i>=0; i--) {
+    rasqal_formula* f=(rasqal_formula*)raptor_sequence_get_at($2, i);
+    rasqal_triple *t2;
+    const unsigned char *blank_id=NULL;
+
+    blank_id=rasqal_query_generate_bnodeid(rdf_query, NULL);
+    if(!blank_id)
+      YYERR_MSG_GOTO(err_Collection, "Collection: cannot create bnodeid");
+
+    blank=rasqal_new_simple_literal(((rasqal_query*)rq)->world, RASQAL_LITERAL_BLANK, blank_id);
+    if(!blank)
+      YYERR_MSG_GOTO(err_Collection, "Collection: cannot create bnode");
+
+    /* Move existing formula triples */
+    if(f->triples)
+      if(raptor_sequence_join($$->triples, f->triples))
+        YYERR_MSG_GOTO(err_Collection, "Collection: sequence join failed");
+
+    /* add new triples we needed */
+    t2=rasqal_new_triple(rasqal_new_literal_from_literal(blank),
+                         rasqal_new_literal_from_literal(first_identifier),
+                         rasqal_new_literal_from_literal(f->value));
+    if(!t2)
+      YYERR_MSG_GOTO(err_Collection, "Collection: cannot create triple");
+
+    if(raptor_sequence_push($$->triples, t2))
+      YYERR_MSG_GOTO(err_Collection, "Collection: cannot create triple");
+
+    t2=rasqal_new_triple(rasqal_new_literal_from_literal(blank),
+                         rasqal_new_literal_from_literal(rest_identifier),
+                         rasqal_new_literal_from_literal(object));
+    if(!t2)
+      YYERR_MSG_GOTO(err_Collection, "Collection: cannot create triple 2");
+
+    if(raptor_sequence_push($$->triples, t2))
+      YYERR_MSG_GOTO(err_Collection, "Collection: sequence push 2 failed");
+
+    rasqal_free_literal(object);
+    object=blank;
+    blank=NULL;
+  }
+
+  $$->value=object;
+  
+#if RASQAL_DEBUG > 1
+  fprintf(DEBUG_FH, "  after substitution collection=");
+  rasqal_formula_print($$, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+
+  rasqal_free_literal(first_identifier);
+  rasqal_free_literal(rest_identifier);
+
+  break; /* success */
+
+  err_Collection:
+  
+  if(blank)
+    rasqal_free_literal(blank);
+  if(object)
+    rasqal_free_literal(object);
+  if(rest_identifier)
+    rasqal_free_literal(rest_identifier);
+  if(first_identifier)
+    rasqal_free_literal(first_identifier);
+  if($2)
+    raptor_free_sequence($2);
+  if($$) {
+    rasqal_free_formula($$);
+    $$=NULL;
+  }
+  YYERROR_MSG(errmsg);
+}
+;
+
+
+/* NEW Grammar Term pulled out of [40] Collection */
+/* Sequence of formula */
+GraphNodeListNotEmpty: GraphNodeListNotEmpty GraphNode
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "GraphNodeListNotEmpty 1\n");
+  if($2) {
+    fprintf(DEBUG_FH, "  GraphNode=");
+    rasqal_formula_print($2, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+  } else  
+    fprintf(DEBUG_FH, "  and empty GraphNode\n");
+  if($1) {
+    fprintf(DEBUG_FH, "  GraphNodeListNotEmpty=");
+    raptor_sequence_print($1, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+  } else
+    fprintf(DEBUG_FH, "  and empty GraphNodeListNotEmpty\n");
+#endif
+
+  if(!$2)
+    $$=NULL;
+  else {
+    /* FIXME: does not work:
+     * $$ not initialized
+     * $1 not freed
+     * also could need a test case */
+    if(raptor_sequence_push($$, $2)) {
+      raptor_free_sequence($$);
+      $$=NULL;
+      YYERROR_MSG("GraphNodeListNotEmpty 1: sequence push failed");
+    }
+#if RASQAL_DEBUG > 1  
+    fprintf(DEBUG_FH, "  itemList is now ");
+    raptor_sequence_print($$, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n\n");
+#endif
+  }
+
+}
+| GraphNode
+{
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "GraphNodeListNotEmpty 2\n");
+  if($1) {
+    fprintf(DEBUG_FH, "  GraphNode=");
+    rasqal_formula_print($1, DEBUG_FH);
+    fprintf(DEBUG_FH, "\n");
+  } else  
+    fprintf(DEBUG_FH, "  and empty GraphNode\n");
+#endif
+
+  if(!$1)
+    $$=NULL;
+  else {
+    $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_formula, (raptor_sequence_print_handler*)rasqal_formula_print);
+    if(!$$) {
+      rasqal_free_formula($1);
+      YYERROR_MSG("GraphNodeListNotEmpty 2: cannot create sequence");
+    }
+    if(raptor_sequence_push($$, $1)) {
+      raptor_free_sequence($$);
+      $$=NULL;
+      YYERROR_MSG("GraphNodeListNotEmpty 2: sequence push failed");
+    }
+  }
+#if RASQAL_DEBUG > 1  
+  fprintf(DEBUG_FH, "  GraphNodeListNotEmpty is now ");
+  raptor_sequence_print($$, DEBUG_FH);
+  fprintf(DEBUG_FH, "\n\n");
+#endif
+}
+;
+
+
+/* SPARQL Grammar: [41] GraphNode */
+GraphNode: VarOrTerm
+{
+  $$=$1;
+}
+| TriplesNode
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar Term: [42] VarOrTerm */
+VarOrTerm: Var
+{
+  $$=rasqal_new_formula();
+  if(!$$)
+    YYERROR_MSG("VarOrTerm 1: cannot create formula");
+  $$->value=rasqal_new_variable_literal(((rasqal_query*)rq)->world, $1);
+  if(!$$->value) {
+    rasqal_free_formula($$);
+    $$=NULL;
+    YYERROR_MSG("VarOrTerm 1: cannot create literal");
+  }
+}
+| GraphTerm
+{
+  $$=rasqal_new_formula();
+  if(!$$) {
+    if($1)
+      rasqal_free_literal($1);
+    YYERROR_MSG("VarOrTerm 2: cannot create formula");
+  }
+  $$->value=$1;
+}
+;
+
+/* SPARQL Grammar: [43] VarOrIRIref */
+VarOrIRIref: Var
+{
+  $$=rasqal_new_variable_literal(((rasqal_query*)rq)->world, $1);
+  if(!$$)
+    YYERROR_MSG("VarOrIRIref: cannot create literal");
+}
+| IRIref
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [44] Var */
+Var: '?' VarName
+{
+  $$=$2;
+}
+| '$' VarName
+{
+  $$=$2;
+}
+;
+
+/* NEW Grammar Term made from SPARQL Grammar: [44] Var */
+VarName: IDENTIFIER
+{
+  $$=rasqal_new_variable((rasqal_query*)rq, $1, NULL);
+  if(!$$)
+    YYERROR_MSG("VarName: cannot create var");
+}
+;
+
+
+
+/* SPARQL Grammar: [45] GraphTerm */
+GraphTerm: IRIref
+{
+  $$=$1;
+}
+| STRING_LITERAL
+{
+  $$=$1;
+}
+| NumericLiteral
+{
+  $$=$1;
+}
+| BOOLEAN_LITERAL
+{
+  $$=$1;
+}
+| BlankNode
+{
+  $$=$1;
+}
+|  '(' ')'
+{
+#ifdef RAPTOR_V2_AVAILABLE
+  $$=rasqal_new_uri_literal(((rasqal_query*)rq)->world, raptor_uri_copy_v2(((rasqal_query*)rq)->world->raptor_world_ptr, ((rasqal_query*)rq)->world->rdf_nil_uri));
+#else
+  $$=rasqal_new_uri_literal(((rasqal_query*)rq)->world, raptor_uri_copy(((rasqal_query*)rq)->world->rdf_nil_uri));
+#endif
+  if(!$$)
+    YYERROR_MSG("GraphTerm: cannot create literal");
+}
+;
+
+/* SPARQL Grammar: [46] Expression */
+Expression: ConditionalOrExpression
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [47] ConditionalOrExpression */
+ConditionalOrExpression: ConditionalOrExpression SC_OR ConditionalAndExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_OR, $1, $3);
+  if(!$$)
+    YYERROR_MSG("ConditionalOrExpression: cannot create expr");
+}
+| ConditionalAndExpression
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [48] ConditionalAndExpression */
+ConditionalAndExpression: ConditionalAndExpression SC_AND RelationalExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_AND, $1, $3);
+  if(!$$)
+    YYERROR_MSG("ConditionalAndExpression: cannot create expr");
+;
+}
+| RelationalExpression
+{
+  $$=$1;
+}
+;
+
+/* SPARQL Grammar: [49] ValueLogical - merged into RelationalExpression */
+
+/* SPARQL Grammar: [50] RelationalExpression */
+RelationalExpression: AdditiveExpression EQ AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_EQ, $1, $3);
+  if(!$$)
+    YYERROR_MSG("RelationalExpression 1: cannot create expr");
+}
+| AdditiveExpression NEQ AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_NEQ, $1, $3);
+  if(!$$)
+    YYERROR_MSG("RelationalExpression 2: cannot create expr");
+}
+| AdditiveExpression LT AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_LT, $1, $3);
+  if(!$$)
+    YYERROR_MSG("RelationalExpression 3: cannot create expr");
+}
+| AdditiveExpression GT AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_GT, $1, $3);
+  if(!$$)
+    YYERROR_MSG("RelationalExpression 4: cannot create expr");
+}
+| AdditiveExpression LE AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_LE, $1, $3);
+  if(!$$)
+    YYERROR_MSG("RelationalExpression 5: cannot create expr");
+}
+| AdditiveExpression GE AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_GE, $1, $3);
+  if(!$$)
+    YYERROR_MSG("RelationalExpression 6: cannot create expr");
+}
+| AdditiveExpression
+{
+  $$=$1;
+}
+;
+
+/* SPARQL Grammar: [51] NumericExpression - merged into AdditiveExpression */
+
+/* SPARQL Grammar: [52] AdditiveExpression */
+AdditiveExpression: MultiplicativeExpression '+' AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_PLUS, $1, $3);
+  if(!$$)
+    YYERROR_MSG("AdditiveExpression 1: cannot create expr");
+}
+| MultiplicativeExpression '-' AdditiveExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_MINUS, $1, $3);
+  if(!$$)
+    YYERROR_MSG("AdditiveExpression 2: cannot create expr");
+}
+| MultiplicativeExpression NumericLiteralPositive
+{
+  rasqal_expression *e=rasqal_new_literal_expression(((rasqal_query*)rq)->world, $2);
+  if(!e) {
+    rasqal_free_expression($1);
+    YYERROR_MSG("AdditiveExpression 3: cannot create expr");
+  }
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_PLUS, $1, e);
+  if(!$$)
+    YYERROR_MSG("AdditiveExpression 4: cannot create expr");
+}
+| MultiplicativeExpression NumericLiteralNegative
+{
+  rasqal_expression *e=rasqal_new_literal_expression(((rasqal_query*)rq)->world, $2);
+  if(!e) {
+    rasqal_free_expression($1);
+    YYERROR_MSG("AdditiveExpression 5: cannot create expr");
+  }
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_PLUS, $1, e);
+  if(!$$)
+    YYERROR_MSG("AdditiveExpression 6: cannot create expr");
+}
+| MultiplicativeExpression
+{
+  $$=$1;
+}
+;
+
+/* SPARQL Grammar: [53] MultiplicativeExpression */
+MultiplicativeExpression: UnaryExpression '*' MultiplicativeExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_STAR, $1, $3);
+  if(!$$)
+    YYERROR_MSG("MultiplicativeExpression 1: cannot create expr");
+}
+| UnaryExpression '/' MultiplicativeExpression
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_SLASH, $1, $3);
+  if(!$$)
+    YYERROR_MSG("MultiplicativeExpression 2: cannot create expr");
+}
+| UnaryExpression
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [54] UnaryExpression */
+UnaryExpression: '!' PrimaryExpression
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_BANG, $2);
+  if(!$$)
+    YYERROR_MSG("UnaryExpression 1: cannot create expr");
+}
+| '+' PrimaryExpression
+{
+  $$=$2;
+}
+| '-' PrimaryExpression
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_UMINUS, $2);
+  if(!$$)
+    YYERROR_MSG("UnaryExpression 3: cannot create expr");
+}
+| PrimaryExpression
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [55] PrimaryExpression
+ * == BrackettedExpression | BuiltInCall | IRIrefOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | Var
+ * == BrackettedExpression | BuiltInCall | IRIref ArgList? | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | Var
+ * == BrackettedExpression | BuiltInCall | FunctionCall |
+ *    approximately GraphTerm | Var
+ * 
+*/
+PrimaryExpression: BrackettedExpression 
+{
+  $$=$1;
+}
+| BuiltInCall
+{
+  $$=$1;
+}
+| FunctionCall
+{
+  /* Grammar has IRIrefOrFunction here which is "IRIref ArgList?"
+   * and essentially shorthand for FunctionCall | IRIref.  The Rasqal
+   * SPARQL lexer distinguishes these for us with IRIrefBrace.
+   * IRIref is covered below by GraphTerm.
+   */
+  $$=$1;
+}
+| GraphTerm
+{
+  $$=rasqal_new_literal_expression(((rasqal_query*)rq)->world, $1);
+  if(!$$)
+    YYERROR_MSG("PrimaryExpression 4: cannot create expr");
+}
+| Var
+{
+  rasqal_literal *l=rasqal_new_variable_literal(((rasqal_query*)rq)->world, $1);
+  if(!l)
+    YYERROR_MSG("PrimaryExpression 5: cannot create literal");
+  $$=rasqal_new_literal_expression(((rasqal_query*)rq)->world, l);
+  if(!$$)
+    YYERROR_MSG("PrimaryExpression 5: cannot create expr");
+}
+;
+
+
+/* SPARQL Grammar: [56] BrackettedExpression */
+BrackettedExpression: '(' Expression ')'
+{
+  $$=$2;
+}
+;
+
+
+/* SPARQL Grammar: [57] BuiltInCall */
+BuiltInCall: STR '(' Expression ')'
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_STR, $3);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 1: cannot create expr");
+}
+| LANG '(' Expression ')'
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_LANG, $3);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 2: cannot create expr");
+}
+| LANGMATCHES '(' Expression ',' Expression ')'
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_LANGMATCHES, $3, $5);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 3: cannot create expr");
+}
+| DATATYPE '(' Expression ')'
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_DATATYPE, $3);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 4: cannot create expr");
+}
+| BOUND '(' Var ')'
+{
+  rasqal_literal *l;
+  rasqal_expression *e;
+  l=rasqal_new_variable_literal(((rasqal_query*)rq)->world, $3);
+  if(!l)
+    YYERROR_MSG("BuiltInCall 5: cannot create literal");
+  e=rasqal_new_literal_expression(((rasqal_query*)rq)->world, l);
+  if(!e)
+    YYERROR_MSG("BuiltInCall 6: cannot create literal expr");
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_BOUND, e);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 7: cannot create expr");
+}
+| SAMETERM '(' Expression ',' Expression ')'
+{
+  $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_SAMETERM, $3, $5);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 8: cannot create expr");
+}
+| ISURI '(' Expression ')'
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ISURI, $3);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 9: cannot create expr");
+}
+| ISBLANK '(' Expression ')'
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ISBLANK, $3);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 10: cannot create expr");
+}
+| ISLITERAL '(' Expression ')'
+{
+  $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_ISLITERAL, $3);
+  if(!$$)
+    YYERROR_MSG("BuiltInCall 11: cannot create expr");
+}
+| RegexExpression
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [58] RegexExpression */
+RegexExpression: REGEX '(' Expression ',' Expression ')'
+{
+  $$=rasqal_new_3op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_REGEX, $3, $5, NULL);
+  if(!$$)
+    YYERROR_MSG("RegexExpression 1: cannot create expr");
+}
+| REGEX '(' Expression ',' Expression ',' Expression ')'
+{
+  $$=rasqal_new_3op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_REGEX, $3, $5, $7);
+  if(!$$)
+    YYERROR_MSG("RegexExpression 2: cannot create expr");
+}
+;
+
+/* SPARQL Grammar: [59] IRIrefOrFunction - not necessary in this
+   grammar as the IRIref ambiguity is determined in lexer with the
+   help of the IRIrefBrace token below */
+
+/* NEW Grammar Term made from SPARQL Grammar: [64] IRIref + '(' expanded */
+IRIrefBrace: URI_LITERAL_BRACE
+{
+  $$=rasqal_new_uri_literal(((rasqal_query*)rq)->world, $1);
+  if(!$$)
+    YYERROR_MSG("IRIrefBrace 1: cannot create literal");
+}
+| QNAME_LITERAL_BRACE
+{
+  $$=rasqal_new_simple_literal(((rasqal_query*)rq)->world, RASQAL_LITERAL_QNAME, $1);
+  if(!$$)
+    YYERROR_MSG("IRIrefBrace 2: cannot create literal");
+  if(rasqal_literal_expand_qname((rasqal_query*)rq, $$)) {
+    sparql_query_error_full((rasqal_query*)rq,
+                            "QName %s cannot be expanded", $1);
+    rasqal_free_literal($$);
+    $$=NULL;
+    YYERROR_MSG("IRIrefBrace 2: cannot expand qname");
+  }
+}
+;
+
+
+/* SPARQL Grammar: [60] RDFLiteral - merged into GraphTerm */
+
+/* SPARQL Grammar: [61] NumericLiteral */
+NumericLiteral: NumericLiteralUnsigned
+{
+  $$=$1;
+}
+| NumericLiteralPositive
+{
+  $$=$1;
+}
+| NumericLiteralNegative
+{
+  $$=$1;
+}
+;
+
+/* SPARQL Grammer: [62] NumericLiteralUnsigned */
+NumericLiteralUnsigned: INTEGER_LITERAL
+{
+  $$=$1;
+}
+| DECIMAL_LITERAL
+{
+  $$=$1;
+}
+| DOUBLE_LITERAL
+{
+  $$=$1;
+}
+;
+
+
+ /* SPARQL Grammer: [63] NumericLiteralPositive */
+NumericLiteralPositive: INTEGER_POSITIVE_LITERAL
+{
+  $$=$1;
+}
+| DECIMAL_POSITIVE_LITERAL
+{
+  $$=$1;
+}
+| DOUBLE_POSITIVE_LITERAL
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [64] NumericLiteralNegative */
+NumericLiteralNegative: INTEGER_NEGATIVE_LITERAL
+{
+  $$=$1;
+}
+| DECIMAL_NEGATIVE_LITERAL
+{
+  $$=$1;
+}
+| DOUBLE_NEGATIVE_LITERAL
+{
+  $$=$1;
+}
+;
+
+
+/* SPARQL Grammar: [62] BooleanLiteral - merged into GraphTerm */
+
+/* SPARQL Grammar: [63] String - merged into GraphTerm */
+
+/* SPARQL Grammar: [64] IRIref */
+IRIref: URI_LITERAL
+{
+  $$=rasqal_new_uri_literal(((rasqal_query*)rq)->world, $1);
+  if(!$$)
+    YYERROR_MSG("IRIref 1: cannot create literal");
+}
+| QNAME_LITERAL
+{
+  $$=rasqal_new_simple_literal(((rasqal_query*)rq)->world, RASQAL_LITERAL_QNAME, $1);
+  if(!$$)
+    YYERROR_MSG("IRIref 2: cannot create literal");
+  if(rasqal_literal_expand_qname((rasqal_query*)rq, $$)) {
+    sparql_query_error_full((rasqal_query*)rq,
+                            "QName %s cannot be expanded", $1);
+    rasqal_free_literal($$);
+    $$=NULL;
+    YYERROR_MSG("IRIrefBrace 2: cannot expand qname");
+  }
+}
+;
+
+
+/* SPARQL Grammar: [65] QName - made into terminal QNAME_LITERAL */
+
+/* SPARQL Grammar: [66] BlankNode */
+BlankNode: BLANK_LITERAL
+{
+  $$=rasqal_new_simple_literal(((rasqal_query*)rq)->world, RASQAL_LITERAL_BLANK, $1);
+  if(!$$)
+    YYERROR_MSG("BlankNode 1: cannot create literal");
+} | '[' ']'
+{
+  const unsigned char *id=rasqal_query_generate_bnodeid((rasqal_query*)rq, NULL);
+  if(!id)
+    YYERROR_MSG("BlankNode 2: cannot create bnodeid");
+  $$=rasqal_new_simple_literal(((rasqal_query*)rq)->world, RASQAL_LITERAL_BLANK, id);
+  if(!$$)
+    YYERROR_MSG("BlankNode 2: cannot create literal");
+}
+;
+
+/* SPARQL Grammar: [67] Q_IRI_REF onwards are all lexer items
+ * with similar names or are inlined.
+ */
+
+
+
+
+%%
+
+
+/* Support functions */
+
+
+/* This is declared in sparql_lexer.h but never used, so we always get
+ * a warning unless this dummy code is here.  Used once below in an error case.
+ */
+static int yy_init_globals (yyscan_t yyscanner ) { return 0; };
+
+
+/**
+ * rasqal_sparql_query_language_init - Initialise the SPARQL query language parser
+ *
+ * Return value: non 0 on failure
+ **/
+static int
+rasqal_sparql_query_language_init(rasqal_query* rdf_query, const char *name) {
+  rasqal_sparql_query_language* rqe=(rasqal_sparql_query_language*)rdf_query->context;
+
+  rdf_query->compare_flags = RASQAL_COMPARE_XQUERY;
+
+  rqe->extended = (strcmp(name, "laqrs") == 0);
+  return 0;
+}
+
+
+/**
+ * rasqal_sparql_query_language_terminate - Free the SPARQL query language parser
+ *
+ * Return value: non 0 on failure
+ **/
+static void
+rasqal_sparql_query_language_terminate(rasqal_query* rdf_query) {
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)rdf_query->context;
+
+  if(sparql && sparql->scanner_set) {
+    sparql_lexer_lex_destroy(sparql->scanner);
+    sparql->scanner_set=0;
+  }
+
+}
+
+
+static int
+rasqal_sparql_query_language_prepare(rasqal_query* rdf_query) {
+  /* rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)rdf_query->context; */
+  int rc;
+  
+  if(!rdf_query->query_string)
+    return 1;
+  
+  rc=sparql_parse(rdf_query);
+  if(rc)
+    return rc;
+
+  /* FIXME - should check remaining query parts  */
+  if(rasqal_sequence_has_qname(rdf_query->triples) ||
+     rasqal_sequence_has_qname(rdf_query->constructs) ||
+     rasqal_query_constraints_has_qname(rdf_query)) {
+    sparql_query_error(rdf_query, "SPARQL query has unexpanded QNames");
+    return 1;
+  }
+
+  /* SPARQL: Turn [] into anonymous variables */
+  if(rasqal_query_build_anonymous_variables(rdf_query))
+    return 1;
+  
+  /* SPARQL: Expand 'SELECT *' */
+  if(rasqal_query_expand_wildcards(rdf_query))
+    return 1;
+  
+  return 0;
+}
+
+
+static int
+sparql_parse(rasqal_query* rq) {
+  rasqal_sparql_query_language* rqe=(rasqal_sparql_query_language*)rq->context;
+  raptor_locator *locator=&rq->locator;
+  void *buffer;
+
+  if(!rq->query_string)
+    return yy_init_globals(NULL); /* 0 but a way to use yy_init_globals */
+
+  locator->line=1;
+  locator->column= -1; /* No column info */
+  locator->byte= -1; /* No bytes info */
+
+#if RASQAL_DEBUG > 2
+  sparql_parser_debug=1;
+#endif
+
+  rqe->lineno=1;
+
+  if(sparql_lexer_lex_init(&rqe->scanner))
+    return 1;
+  rqe->scanner_set=1;
+
+  sparql_lexer_set_extra(((rasqal_query*)rq), rqe->scanner);
+
+  buffer= sparql_lexer__scan_buffer((char*)rq->query_string, rq->query_string_length, rqe->scanner);
+
+  rqe->error_count=0;
+
+  sparql_parser_parse(rq);
+
+  sparql_lexer_lex_destroy(rqe->scanner);
+  rqe->scanner_set=0;
+
+  /* Parsing failed */
+  if(rq->failed)
+    return 1;
+  
+  return 0;
+}
+
+
+static void
+sparql_query_error(rasqal_query *rq, const char *msg) {
+  rasqal_sparql_query_language* rqe=(rasqal_sparql_query_language*)rq->context;
+
+  if(rqe->error_count++)
+    return;
+
+  rq->locator.line=rqe->lineno;
+#ifdef RASQAL_SPARQL_USE_ERROR_COLUMNS
+  /*  rq->locator.column=sparql_lexer_get_column(yyscanner);*/
+#endif
+
+  rq->failed=1;
+  rasqal_log_error_simple(((rasqal_query*)rq)->world, RAPTOR_LOG_LEVEL_ERROR, &rq->locator,
+                          "%s", msg);
+}
+
+
+static void
+sparql_query_error_full(rasqal_query *rq, const char *message, ...) {
+  va_list arguments;
+  rasqal_sparql_query_language* rqe=(rasqal_sparql_query_language*)rq->context;
+
+  if(rqe->error_count++)
+    return;
+
+  rq->locator.line=rqe->lineno;
+#ifdef RASQAL_SPARQL_USE_ERROR_COLUMNS
+  /*  rq->locator.column=sparql_lexer_get_column(yyscanner);*/
+#endif
+
+  va_start(arguments, message);
+
+  rq->failed=1;
+  rasqal_log_error_varargs(((rasqal_query*)rq)->world, RAPTOR_LOG_LEVEL_ERROR, &rq->locator,
+                           message, arguments);
+
+  va_end(arguments);
+}
+
+
+int
+sparql_syntax_error(rasqal_query *rq, const char *message, ...)
+{
+  rasqal_sparql_query_language *rqe=(rasqal_sparql_query_language*)rq->context;
+  va_list arguments;
+
+  if(rqe->error_count++)
+    return 0;
+
+  rq->locator.line=rqe->lineno;
+#ifdef RASQAL_SPARQL_USE_ERROR_COLUMNS
+  /*  rp->locator.column=sparql_lexer_get_column(yyscanner);*/
+#endif
+
+  va_start(arguments, message);
+  rq->failed=1;
+  rasqal_log_error_varargs(((rasqal_query*)rq)->world, RAPTOR_LOG_LEVEL_ERROR, &rq->locator,
+                           message, arguments);
+  va_end(arguments);
+
+  return 0;
+}
+
+
+int
+sparql_syntax_warning(rasqal_query *rq, const char *message, ...)
+{
+  rasqal_sparql_query_language *rqe=(rasqal_sparql_query_language*)rq->context;
+  va_list arguments;
+
+  rq->locator.line=rqe->lineno;
+#ifdef RASQAL_SPARQL_USE_ERROR_COLUMNS
+  /*  rq->locator.column=sparql_lexer_get_column(yyscanner);*/
+#endif
+
+  va_start(arguments, message);
+  rasqal_log_error_varargs(((rasqal_query*)rq)->world, RAPTOR_LOG_LEVEL_WARNING, &rq->locator,
+                           message, arguments);
+  va_end(arguments);
+
+  return (0);
+}
+
+
+static int
+rasqal_sparql_query_language_iostream_write_escaped_counted_string(rasqal_query* query,
+                                                                 raptor_iostream* iostr,
+                                                                 const unsigned char* string,
+                                                                 size_t len)
+{
+  const char delim='"';
+  
+  raptor_iostream_write_byte(iostr, delim);
+  if(raptor_iostream_write_string_ntriples(iostr, string, len, delim))
+    return 1;
+  
+  raptor_iostream_write_byte(iostr, delim);
+
+  return 0;
+}
+
+
+static void
+rasqal_sparql_query_language_register_factory(rasqal_query_language_factory *factory)
+{
+  factory->context_length = sizeof(rasqal_sparql_query_language);
+
+  factory->init      = rasqal_sparql_query_language_init;
+  factory->terminate = rasqal_sparql_query_language_terminate;
+  factory->prepare   = rasqal_sparql_query_language_prepare;
+  factory->iostream_write_escaped_counted_string = rasqal_sparql_query_language_iostream_write_escaped_counted_string;
+}
+
+
+int
+rasqal_init_query_language_sparql(rasqal_world* world) {
+  return rasqal_query_language_register_factory(world,
+                                                "sparql", 
+                                                "SPARQL W3C DAWG RDF Query Language",
+                                                NULL,
+                                                (const unsigned char*)"http://www.w3.org/TR/rdf-sparql-query/";,
+                                                &rasqal_sparql_query_language_register_factory);
+}
+
+int
+rasqal_init_query_language_laqrs(rasqal_world* world) {
+  return rasqal_query_language_register_factory(world,
+                                                "laqrs", 
+                                                "LAQRS adds to Querying RDF in SPARQL",
+                                                NULL,
+                                                NULL,
+                                                &rasqal_sparql_query_language_register_factory);
+}
+
+
+#ifdef STANDALONE
+#include <stdio.h>
+#include <locale.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifndef HAVE_GETOPT
+#include <rasqal_getopt.h>
+#endif
+
+#ifdef NEED_OPTIND_DECLARATION
+extern int optind;
+extern char *optarg;
+#endif
+
+#define GETOPT_STRING "di:"
+
+#define SPARQL_FILE_BUF_SIZE 2048
+
+int
+main(int argc, char *argv[]) 
+{
+  const char *program=rasqal_basename(argv[0]);
+  char query_string[SPARQL_FILE_BUF_SIZE];
+  rasqal_query *query;
+  FILE *fh;
+  int rc;
+  const char *filename=NULL;
+  raptor_uri* base_uri=NULL;
+  unsigned char *uri_string;
+  const char* query_languages[2]={"sparql", "laqrs"};
+  const char* query_language;
+  int usage=0;
+  int fh_opened_here=0;
+  rasqal_world *world;
+  
+  query_language=query_languages[0];
+  
+  while(!usage) {
+    int c = getopt (argc, argv, GETOPT_STRING);
+
+    if (c == -1)
+      break;
+
+    switch (c) {
+      case 0:
+      case '?': /* getopt() - unknown option */
+        usage=1;
+        break;
+        
+      case 'd':
+#if RASQAL_DEBUG > 2
+        sparql_parser_debug=1;
+#endif
+        break;
+  
+      case 'i':
+        if(optarg) {
+          if(!strcmp(optarg, "laqrs")) {
+            query_language=query_languages[1];
+          } else if(!strcmp(optarg, "sparql")) {
+            query_language=query_languages[0];
+          } else {
+            fprintf(stderr, "-i laqrs or -i sparql only\n");
+            usage=1;
+          }
+        }
+        break;
+    }
+  }
+
+  if((argc-optind)>1) {
+    fprintf(stderr, "%s: Too many arguments.\n", program);
+    usage=1;
+  }
+  
+  if(usage) {
+    fprintf(stderr, "SPARQL/LAQRS parser test for Rasqal %s\n", 
+            rasqal_version_string);
+    fprintf(stderr, "USAGE: %s [OPTIONS] [QUERY-FILE]\n", program);
+    fprintf(stderr, "OPTIONS:\n");
+#if RASQAL_DEBUG > 2
+    fprintf(stderr, " -d           Bison parser debugging\n");
+#endif
+    fprintf(stderr, " -i LANGUAGE  Set query language\n");
+    exit(1);
+  }
+
+ if(optind == argc-1) {
+    filename=argv[optind];
+    fh = fopen(argv[optind], "r");
+    if(!fh) {
+      fprintf(stderr, "%s: Cannot open file %s - %s\n", program, filename,
+              strerror(errno));
+      exit(1);
+    }
+    fh_opened_here=1;
+ } else {
+    filename="<stdin>";
+    fh = stdin;
+  }
+
+  memset(query_string, 0, SPARQL_FILE_BUF_SIZE);
+  rc=fread(query_string, SPARQL_FILE_BUF_SIZE, 1, fh);
+  if(rc < SPARQL_FILE_BUF_SIZE) {
+    if(ferror(fh)) {
+      fprintf(stderr, "%s: file '%s' read failed - %s\n",
+              program, filename, strerror(errno));
+      fclose(fh);
+      return(1);
+    }
+  }
+  
+  if(fh_opened_here)
+    fclose(fh);
+
+  world=rasqal_new_world();
+  if(!world || rasqal_world_open(world))
+    exit(1);
+
+  query=rasqal_new_query(world, query_language, NULL);
+
+  uri_string=raptor_uri_filename_to_uri_string(filename);
+#ifdef RAPTOR_V2_AVAILABLE
+  base_uri = raptor_new_uri_v2(world->raptor_world_ptr, uri_string);
+#else
+  base_uri = raptor_new_uri(uri_string);
+#endif
+
+  rc=rasqal_query_prepare(query, (const unsigned char*)query_string, base_uri);
+
+  rasqal_query_print(query, stdout);
+
+  rasqal_free_query(query);
+
+#ifdef RAPTOR_V2_AVAILABLE
+  raptor_free_uri_v2(world->raptor_world_ptr, base_uri);
+#else
+  raptor_free_uri(base_uri);
+#endif
+
+  raptor_free_memory(uri_string);
+
+  rasqal_free_world(world);
+
+  return rc;
+}
+#endif
diff --git a/src/rasqal/strcasecmp.c b/src/rasqal/strcasecmp.c
new file mode 100644
index 0000000..0565b26
--- /dev/null
+++ b/src/rasqal/strcasecmp.c
@@ -0,0 +1,118 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * strcasecmp.c - strcasecmp compatibility
+ *
+ * This file is in the public domain.
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <rasqal_config.h>
+#endif
+
+#ifdef WIN32
+#include <win32_rasqal_config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+int rasqal_strcasecmp(const char* s1, const char* s2);
+int rasqal_strncasecmp(const char* s1, const char* s2, size_t n);
+
+
+int
+rasqal_strcasecmp(const char* s1, const char* s2)
+{
+  register int c1, c2;
+  
+  while(*s1 && *s2) {
+    c1 = tolower(*s1);
+    c2 = tolower(*s2);
+    if (c1 != c2)
+      return (c1 - c2);
+    s1++;
+    s2++;
+  }
+  return (int) (*s1 - *s2);
+}
+
+
+int
+rasqal_strncasecmp(const char* s1, const char* s2, size_t n)
+{
+  register int c1, c2;
+  
+  while(*s1 && *s2 && n) {
+    c1 = tolower(*s1);
+    c2 = tolower(*s2);
+    if (c1 != c2)
+      return (c1 - c2);
+    s1++;
+    s2++;
+    n--;
+  }
+  return 0;
+}
+
+
+
+#ifdef STANDALONE
+
+#include <stdio.h>
+
+/* one more prototype */
+int main(int argc, char *argv[]);
+
+
+
+static int
+assert_strcasecmp (const char *s1, const char *s2, int expected)
+{
+  int result=strcasecmp(s1, s2);
+  result=(result>0) ? 1 : ((result <0) ? -1 : 0);
+
+  if (result != expected)
+    {
+      fprintf(stderr, "FAIL strcasecmp (%s, %s) gave %d != %d\n",
+              s1, s2, result, expected);
+      return 1;
+    }
+  return 0;
+}
+
+
+static int
+assert_strncasecmp (const char *s1, const char *s2, size_t size, int expected)
+{
+  int result=strncasecmp(s1, s2, size);
+  result=(result>0) ? 1 : ((result <0) ? -1 : 0);
+
+  if (result != expected)
+    {
+      fprintf(stderr, "FAIL strncasecmp (%s, %s, %d) gave %d != %d\n",
+              s1, s2, (unsigned int)size, result, expected);
+      return 1;
+    }
+  return 0;
+}
+
+
+int
+main(int argc, char *argv[]) 
+{
+  int failures=0;
+  
+  failures += assert_strcasecmp("foo", "foo", 0);
+  failures += assert_strcasecmp("foo", "FOO", 0);
+  failures += assert_strcasecmp("foo", "BaR", 1);
+
+  failures += assert_strncasecmp("foo", "foobar", 3, 0);
+  failures += assert_strncasecmp("foo", "FOOxyz", 3, 0);
+  failures += assert_strncasecmp("foo", "BaRfoo", 3, 1);
+
+  return failures;
+}
+
+#endif
diff --git a/src/rasqal/win32_rasqal_config.h b/src/rasqal/win32_rasqal_config.h
new file mode 100644
index 0000000..a3c26e9
--- /dev/null
+++ b/src/rasqal/win32_rasqal_config.h
@@ -0,0 +1,129 @@
+/* -*- Mode: c; c-basic-offset: 2 -*-
+ *
+ * win32_config.h - Rasqal WIN32 hard-coded config
+ *
+ * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
+ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
+ * 
+ * This package is Free Software and part of Redland http://librdf.org/
+ * 
+ * It is licensed under the following three licenses as alternatives:
+ *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+ *   2. GNU General Public License (GPL) V2 or any newer version
+ *   3. Apache License, V2.0 or any newer version
+ * 
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ * 
+ * See LICENSE.html or LICENSE.txt at the top of this package for the
+ * complete terms and further detail along with the license texts for
+ * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+ * 
+ */
+
+
+#ifndef WIN32_CONFIG_H
+#define WIN32_CONFIG_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WIN32_LEAN_AND_MEAN 1
+
+/* getopt is not in standard win32 C library - define if we have it */
+/* #define HAVE_GETOPT_H 1 */
+
+#define HAVE_STDLIB_H 1
+
+#define HAVE_STRICMP 1
+
+/* MS names for these functions */
+#define vsnprintf _vsnprintf
+#define snprintf _snprintf
+#define access _access
+#define stricmp _stricmp
+#define strnicmp _strnicmp
+
+#include <float.h>
+#define isnan _isnan
+
+/* This is a SPARQL token define */
+#undef OPTIONAL
+
+#define HAVE_C99_VSNPRINTF 1
+
+/* for access() which is POSIX but doesn't seem to have the defines in VC */
+#ifndef R_OK
+#define R_OK 4
+#endif
+
+/* __func__ doesn't exist in Visual Studio 6 */
+#define __func__ ""
+
+/* 
+ * Defines that come from config.h
+ */
+
+/* Release version as a decimal */
+#define RASQAL_VERSION_DECIMAL 917
+
+/* Major version number */
+#define RASQAL_VERSION_MAJOR 0
+
+/* Minor version number */
+#define RASQAL_VERSION_MINOR 9
+
+/* Release version number */
+#define RASQAL_VERSION_RELEASE 17
+
+/* Version number of package */
+#define VERSION "0.9.17"
+
+#include <windows.h>
+#include <io.h>
+#include <memory.h>
+
+/* This is a SPARQL token define */
+#ifdef OPTIONAL
+#undef OPTIONAL
+#endif
+
+/* bison: output uses ERROR in an enum which breaks if this is defined */
+#ifdef ERROR
+#undef ERROR
+#endif
+
+/* flex: const is available */
+#define YY_USE_CONST
+/* looks like the .c files define this anyway */
+/* #define YY_NO_UNISTD_H */
+
+#undef RASQAL_INLINE
+#define RASQAL_INLINE __inline
+
+/* Building RDQL query */
+#define RASQAL_QUERY_RDQL 1
+
+/* Building SPARQL query */
+#define RASQAL_QUERY_SPARQL 1
+
+/* Use raptor to provide triples */
+#define RAPTOR_TRIPLES_SOURCE_RAPTOR 1
+
+/* Use redland to provide triples */
+/* #define RAPTOR_TRIPLES_SOURCE_REDLAND 1 */
+
+/* Use PCRE regex library */
+#define RASQAL_REGEX_PCRE 1
+
+#ifdef _DEBUG
+#define RASQAL_DEBUG 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]