You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ss...@apache.org on 2013/11/06 17:09:06 UTC

git commit: SPARQL fulltext support

Updated Branches:
  refs/heads/develop 90bd64034 -> c0e5d9daf


SPARQL fulltext support


Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/c0e5d9da
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/c0e5d9da
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/c0e5d9da

Branch: refs/heads/develop
Commit: c0e5d9dafc88b99734afbcdc4837e46aef86f7a0
Parents: 90bd640
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Wed Nov 6 17:09:01 2013 +0100
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Wed Nov 6 17:09:01 2013 +0100

----------------------------------------------------------------------
 .../sparql/function/FulltextQueryFunction.java  | 47 ++++++++++++
 .../sparql/function/FulltextSearchFunction.java | 46 ++++++++++++
 .../kiwi/sparql/sail/KiWiSparqlSail.java        | 79 +++++++++++++++++++-
 ...f.query.algebra.evaluation.function.Function |  2 +
 .../persistence/h2/create_fulltext_index.sql    | 21 ++++++
 .../persistence/mysql/create_fulltext_index.sql | 20 +++++
 .../persistence/pgsql/create_fulltext_index.sql | 20 +++++
 .../pgsql/create_fulltext_index_generic.sql     | 20 +++++
 .../pgsql/create_fulltext_langlookup.sql        | 42 +++++++++++
 .../kiwi/sparql/test/KiWiSparqlJoinTest.java    | 63 ++++++++++++++++
 .../marmotta/kiwi/sparql/test/query22.sparql    | 27 +++++++
 .../marmotta/kiwi/sparql/test/query23.sparql    | 27 +++++++
 .../marmotta/kiwi/config/KiWiConfiguration.java | 42 +++++++++++
 .../kiwi/persistence/KiWiConnection.java        | 75 ++++++++++++++++++-
 .../kiwi/persistence/mysql/MySQLDialect.java    | 18 +++++
 .../persistence/pgsql/PostgreSQLDialect.java    | 19 +++++
 .../marmotta/kiwi/vocabulary/FN_MARMOTTA.java   | 41 ++++++++++
 .../kiwi/persistence/h2/statements.properties   |  3 +
 .../persistence/mysql/create_base_tables.sql    |  2 +-
 .../persistence/mysql/statements.properties     |  3 +
 .../persistence/pgsql/statements.properties     |  3 +
 21 files changed, 615 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/function/FulltextQueryFunction.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/function/FulltextQueryFunction.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/function/FulltextQueryFunction.java
new file mode 100644
index 0000000..222487b
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/function/FulltextQueryFunction.java
@@ -0,0 +1,47 @@
+package org.apache.marmotta.kiwi.sparql.function;
+
+import org.apache.marmotta.kiwi.vocabulary.FN_MARMOTTA;
+import org.openrdf.model.Value;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.query.algebra.evaluation.ValueExprEvaluationException;
+import org.openrdf.query.algebra.evaluation.function.Function;
+import org.openrdf.query.algebra.evaluation.function.FunctionRegistry;
+
+/**
+ * A SPARQL function for doing a full-text search on the content of a string using a query language with boolean operators.
+ * The query syntax is the syntax of PostgreSQL (see http://www.postgresql.org/docs/9.1/static/datatype-textsearch.html)
+ * Should be implemented directly in the database, as the in-memory implementation is non-functional.
+ * <p/>
+ * The function can be called either as:
+ * <ul>
+ *     <li>fn:fulltext-query(?var, 'query') - using a generic stemmer and dictionary</li>
+ *     <li>
+ *         fn:fulltext-query(?var, 'query', 'language') - using a language-specific stemmer and dictionary
+ *         (currently only supported by PostgreSQL with the language values 'english', 'german', 'french', 'italian', 'spanish'
+ *         and some other languages as supported by PostgreSQL).
+ *     </li>*
+ * </ul>
+ * Note that for performance reasons it might be preferrable to create a full-text index for your database. Please
+ * consult your database documentation on how to do this.
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class FulltextQueryFunction implements Function {
+
+    // auto-register for SPARQL environment
+    static {
+        if(!FunctionRegistry.getInstance().has(FN_MARMOTTA.QUERY_FULLTEXT.toString())) {
+            FunctionRegistry.getInstance().add(new FulltextQueryFunction());
+        }
+    }
+
+    @Override
+    public Value evaluate(ValueFactory valueFactory, Value... args) throws ValueExprEvaluationException {
+        throw new UnsupportedOperationException("cannot evaluate in-memory, needs to be supported by the database");
+    }
+
+    @Override
+    public String getURI() {
+        return FN_MARMOTTA.QUERY_FULLTEXT.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/function/FulltextSearchFunction.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/function/FulltextSearchFunction.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/function/FulltextSearchFunction.java
new file mode 100644
index 0000000..9ce47e8
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/function/FulltextSearchFunction.java
@@ -0,0 +1,46 @@
+package org.apache.marmotta.kiwi.sparql.function;
+
+import org.apache.marmotta.kiwi.vocabulary.FN_MARMOTTA;
+import org.openrdf.model.Value;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.query.algebra.evaluation.ValueExprEvaluationException;
+import org.openrdf.query.algebra.evaluation.function.Function;
+import org.openrdf.query.algebra.evaluation.function.FunctionRegistry;
+
+/**
+ * A SPARQL function for doing a full-text search on the content of a string. Should be implemented directly in
+ * the database, as the in-memory implementation is non-functional.
+ * <p/>
+ * The function can be called either as:
+ * <ul>
+ *     <li>fn:fulltext-search(?var, 'query') - using a generic stemmer and dictionary</li>
+ *     <li>
+ *         fn:fulltext-search(?var, 'query', 'language') - using a language-specific stemmer and dictionary
+ *         (currently only supported by PostgreSQL with the language values 'english', 'german', 'french', 'italian', 'spanish'
+ *         and some other languages as supported by PostgreSQL).
+ *     </li>*
+ * </ul>
+ * Note that for performance reasons it might be preferrable to create a full-text index for your database. Please
+ * consult your database documentation on how to do this.
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class FulltextSearchFunction implements Function {
+
+    // auto-register for SPARQL environment
+    static {
+        if(!FunctionRegistry.getInstance().has(FN_MARMOTTA.SEARCH_FULLTEXT.toString())) {
+            FunctionRegistry.getInstance().add(new FulltextSearchFunction());
+        }
+    }
+
+    @Override
+    public Value evaluate(ValueFactory valueFactory, Value... args) throws ValueExprEvaluationException {
+        throw new UnsupportedOperationException("cannot evaluate in-memory, needs to be supported by the database");
+    }
+
+    @Override
+    public String getURI() {
+        return FN_MARMOTTA.SEARCH_FULLTEXT.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSail.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSail.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSail.java
index eb1b810..e8a6cb5 100644
--- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSail.java
+++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/sail/KiWiSparqlSail.java
@@ -17,14 +17,28 @@
 
 package org.apache.marmotta.kiwi.sparql.sail;
 
+import org.apache.commons.io.IOUtils;
+import org.apache.marmotta.kiwi.config.KiWiConfiguration;
+import org.apache.marmotta.kiwi.persistence.KiWiConnection;
+import org.apache.marmotta.kiwi.persistence.mysql.MySQLDialect;
+import org.apache.marmotta.kiwi.persistence.pgsql.PostgreSQLDialect;
+import org.apache.marmotta.kiwi.persistence.util.ScriptRunner;
 import org.apache.marmotta.kiwi.sail.KiWiSailConnection;
 import org.apache.marmotta.kiwi.sail.KiWiStore;
 import org.apache.marmotta.kiwi.sparql.persistence.KiWiSparqlConnection;
-import org.openrdf.sail.*;
+import org.openrdf.sail.NotifyingSail;
+import org.openrdf.sail.NotifyingSailConnection;
+import org.openrdf.sail.Sail;
+import org.openrdf.sail.SailConnection;
+import org.openrdf.sail.SailException;
 import org.openrdf.sail.helpers.NotifyingSailWrapper;
 import org.openrdf.sail.helpers.SailConnectionWrapper;
 import org.openrdf.sail.helpers.SailWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
+import java.io.StringReader;
 import java.sql.SQLException;
 
 /**
@@ -34,13 +48,21 @@ import java.sql.SQLException;
  */
 public class KiWiSparqlSail extends NotifyingSailWrapper {
 
+    private static Logger log = LoggerFactory.getLogger(KiWiSparqlSail.class);
+
+
     private KiWiStore parent;
 
     public KiWiSparqlSail(NotifyingSail baseSail) {
         super(baseSail);
 
         this.parent = getRootSail(baseSail);
+    }
 
+    @Override
+    public void initialize() throws SailException {
+        super.initialize();
+        prepareFulltext(this.parent.getPersistence().getConfiguration());
     }
 
     /**
@@ -58,6 +80,61 @@ public class KiWiSparqlSail extends NotifyingSailWrapper {
         }
     }
 
+
+    private void prepareFulltext(KiWiConfiguration configuration) {
+        try {
+            if(configuration.isFulltextEnabled()) {
+                KiWiConnection connection = parent.getPersistence().getConnection();
+                try {
+                    if(configuration.getDialect() instanceof PostgreSQLDialect) {
+
+                        // for postgres, we need to create
+                        // - a stored procedure for mapping ISO language codes to PostgreSQL fulltext configuration names
+                        // - if languages are not null, for each configured language as well as for the generic configuration
+                        //   an index over nodes.svalue
+
+                        ScriptRunner runner = new ScriptRunner(connection.getJDBCConnection(), false, false);
+                        if(connection.getMetadata("fulltext.langlookup") == null) {
+                            runner.runScript(new StringReader(IOUtils.toString(PostgreSQLDialect.class.getResourceAsStream("create_fulltext_langlookup.sql")).replaceAll("\\n"," ")));
+                        }
+
+                        if(configuration.getFulltextLanguages() != null) {
+                            String script = IOUtils.toString(PostgreSQLDialect.class.getResourceAsStream("create_fulltext_index.sql")).replaceAll("\\n"," ");
+                            for(String lang : configuration.getFulltextLanguages()) {
+                                if(connection.getMetadata("fulltext.index."+lang) == null) {
+                                    String script_lang = script.replaceAll("@LANGUAGE@", lang);
+                                    runner.runScript(new StringReader(script_lang));
+                                }
+                            }
+                        }
+                    } else if(configuration.getDialect() instanceof MySQLDialect) {
+
+                        // for MySQL, just create a fulltext index (no language support)
+                        if(connection.getMetadata("fulltext.index") == null) {
+                            ScriptRunner runner = new ScriptRunner(connection.getJDBCConnection(), false, false);
+                            String script = IOUtils.toString(MySQLDialect.class.getResourceAsStream("create_fulltext_index.sql"));
+                            runner.runScript(new StringReader(script));
+                        }
+                        /*
+                    } else if(configuration.getDialect() instanceof H2Dialect) {
+
+                        // for H2, just create a fulltext index (no language support)
+                        if(connection.getMetadata("fulltext.index") == null) {
+                            ScriptRunner runner = new ScriptRunner(connection.getJDBCConnection(), false, false);
+                            String script = IOUtils.toString(H2Dialect.class.getResourceAsStream("create_fulltext_index.sql"));
+                            runner.runScript(new StringReader(script));
+                        }
+                        */
+                    }
+                } finally {
+                    connection.close();
+                }
+            }
+        } catch (IOException | SQLException ex) {
+            log.error("error while preparing fulltext support",ex);
+        }
+    }
+
     /**
      * Get the root connection in a wrapped sail connection stack
      * @param connection

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function b/libraries/kiwi/kiwi-sparql/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function
new file mode 100644
index 0000000..2686bd2
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/resources/META-INF/services/org.openrdf.query.algebra.evaluation.function.Function
@@ -0,0 +1,2 @@
+org.apache.marmotta.kiwi.sparql.function.FulltextSearchFunction
+org.apache.marmotta.kiwi.sparql.function.FulltextQueryFunction
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/create_fulltext_index.sql
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/create_fulltext_index.sql b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/create_fulltext_index.sql
new file mode 100644
index 0000000..82fcfd2
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/create_fulltext_index.sql
@@ -0,0 +1,21 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--      http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+CALL FT_INIT();
+CALL FT_DROP_INDEX('PUBLIC','nodes');
+CALL FT_CREATE_INDEX('PUBLIC','nodes','svalue');
+
+INSERT INTO metadata(mkey,mvalue) VALUES ('fulltext.index','true');
+

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_fulltext_index.sql
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_fulltext_index.sql b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_fulltext_index.sql
new file mode 100644
index 0000000..c61ab91
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_fulltext_index.sql
@@ -0,0 +1,20 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--      http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+DROP INDEX IF EXISTS kiwi_ft_idx;
+CREATE FULLTEXT INDEX kiwi_ft_idx ON nodes(svalue);
+
+INSERT INTO metadata(mkey,mvalue) VALUES ('fulltext.index','true');
+

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_index.sql
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_index.sql b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_index.sql
new file mode 100644
index 0000000..40cf7fa
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_index.sql
@@ -0,0 +1,20 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--      http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+DROP INDEX IF EXISTS kiwi_ft_idx_@LANGUAGE@;
+CREATE INDEX kiwi_ft_idx_@LANGUAGE@ ON nodes USING gin(to_tsvector(kiwi_ft_lang('@LANGUAGE@'),svalue));
+
+INSERT INTO metadata(mkey,mvalue) VALUES ('fulltext.index.@LANGUAGE@','true');
+

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_index_generic.sql
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_index_generic.sql b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_index_generic.sql
new file mode 100644
index 0000000..a4edf19
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_index_generic.sql
@@ -0,0 +1,20 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--      http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+DROP INDEX IF EXISTS kiwi_ft_idx_generic;
+CREATE INDEX kiwi_ft_idx_generic ON nodes USING gin(to_tsvector('simple',svalue));
+
+INSERT INTO metadata(mkey,mvalue) VALUES ('fulltext.index.generic,'true');
+

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_langlookup.sql
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_langlookup.sql b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_langlookup.sql
new file mode 100644
index 0000000..561a1d0
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/create_fulltext_langlookup.sql
@@ -0,0 +1,42 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--      http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+CREATE OR REPLACE FUNCTION kiwi_ft_lang(lang_iso TEXT) RETURNS regconfig AS $$
+DECLARE
+  lang2 TEXT;
+BEGIN
+  lang2 := lower(left(lang_iso,2));
+  CASE lang2
+    WHEN 'en' THEN RETURN 'english';
+    WHEN 'de' THEN RETURN 'german';
+    WHEN 'fr' THEN RETURN 'french';
+    WHEN 'it' THEN RETURN 'italian';
+    WHEN 'es' THEN RETURN 'spanish';
+    WHEN 'pt' THEN RETURN 'portuguese';
+    WHEN 'sv' THEN RETURN 'swedish';
+    WHEN 'no' THEN RETURN 'norwegian';
+    WHEN 'dk' THEN RETURN 'danish';
+    WHEN 'nl' THEN RETURN 'dutch';
+    WHEN 'ru' THEN RETURN 'russian';
+    WHEN 'tr' THEN RETURN 'turkish';
+    WHEN 'hu' THEN RETURN 'hungarian';
+    WHEN 'fi' THEN RETURN 'finnish';
+    ELSE RETURN 'simple';
+  END CASE;
+END
+$$ LANGUAGE plpgsql;
+
+INSERT INTO metadata(mkey,mvalue) VALUES ('fulltext.langlookup','true');
+

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java b/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java
index fc94ffd..7ffcad1 100644
--- a/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java
+++ b/libraries/kiwi/kiwi-sparql/src/test/java/org/apache/marmotta/kiwi/sparql/test/KiWiSparqlJoinTest.java
@@ -26,6 +26,8 @@ import org.apache.marmotta.kiwi.config.KiWiConfiguration;
 import org.apache.marmotta.kiwi.sail.KiWiStore;
 import org.apache.marmotta.kiwi.sparql.sail.KiWiSparqlSail;
 import org.apache.marmotta.kiwi.test.junit.KiWiDatabaseRunner;
+import org.apache.marmotta.kiwi.vocabulary.FN_MARMOTTA;
+import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Assume;
@@ -78,6 +80,8 @@ public class KiWiSparqlJoinTest {
 
     public KiWiSparqlJoinTest(KiWiConfiguration dbConfig) {
         this.dbConfig = dbConfig;
+        dbConfig.setFulltextEnabled(true);
+        dbConfig.setFulltextLanguages(new String[] {"en"});
     }
 
 
@@ -263,6 +267,65 @@ public class KiWiSparqlJoinTest {
         testQuery("query21.sparql");
     }
 
+    // fulltext search filter
+    @Test
+    public void testQuery22() throws Exception {
+        Assume.assumeTrue(dbConfig.getDialect().isFunctionSupported(FN_MARMOTTA.SEARCH_FULLTEXT));
+        String queryString = IOUtils.toString(this.getClass().getResourceAsStream("query22.sparql"), "UTF-8");
+
+        RepositoryConnection con1 = repository.getConnection();
+        try {
+            con1.begin();
+
+            TupleQuery query1 = con1.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
+            TupleQueryResult result1 = query1.evaluate();
+
+            con1.commit();
+
+            Assert.assertTrue(result1.hasNext());
+
+            BindingSet next = result1.next();
+
+            Assert.assertEquals("http://localhost:8080/LMF/resource/hans_meier", next.getValue("p1").stringValue());
+
+        } catch(RepositoryException ex) {
+            con1.rollback();
+        } finally {
+            con1.close();
+        }
+
+    }
+
+    // fulltext query filter
+    @Test
+    public void testQuery23() throws Exception {
+        Assume.assumeTrue(dbConfig.getDialect().isFunctionSupported(FN_MARMOTTA.SEARCH_FULLTEXT));
+        String queryString = IOUtils.toString(this.getClass().getResourceAsStream("query23.sparql"), "UTF-8");
+
+        RepositoryConnection con1 = repository.getConnection();
+        try {
+            con1.begin();
+
+            TupleQuery query1 = con1.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
+            TupleQueryResult result1 = query1.evaluate();
+
+            con1.commit();
+
+            Assert.assertTrue(result1.hasNext());
+
+            while (result1.hasNext()) {
+                BindingSet next = result1.next();
+                Assert.assertThat(next.getValue("p1").stringValue(), Matchers.isOneOf("http://localhost:8080/LMF/resource/hans_meier", "http://localhost:8080/LMF/resource/sepp_huber"));
+            }
+
+        } catch(RepositoryException ex) {
+            con1.rollback();
+        } finally {
+            con1.close();
+        }
+
+    }
+
 
     private void testQuery(String filename) throws Exception {
         String queryString = IOUtils.toString(this.getClass().getResourceAsStream(filename), "UTF-8");

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query22.sparql
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query22.sparql b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query22.sparql
new file mode 100644
index 0000000..1ffbf14
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query22.sparql
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+PREFIX mm: <http://marmotta.apache.org/vocabulary/sparql-functions#>
+
+SELECT ?p1 ?fn ?age WHERE {
+    ?p1 foaf:name ?fn .
+    ?p1 foaf:age ?age .
+    ?p1 dc:description ?desc .
+    FILTER( mm:fulltext-search(str(?desc), "software", lang(?desc)) )
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query23.sparql
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query23.sparql b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query23.sparql
new file mode 100644
index 0000000..1d8e533
--- /dev/null
+++ b/libraries/kiwi/kiwi-sparql/src/test/resources/org/apache/marmotta/kiwi/sparql/test/query23.sparql
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+PREFIX mm: <http://marmotta.apache.org/vocabulary/sparql-functions#>
+
+SELECT ?p1 ?fn ?age WHERE {
+    ?p1 foaf:name ?fn .
+    ?p1 foaf:age ?age .
+    ?p1 dc:description ?desc .
+    FILTER( mm:fulltext-query(str(?desc), "software | climber", lang(?desc)) )
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/config/KiWiConfiguration.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/config/KiWiConfiguration.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/config/KiWiConfiguration.java
index 7b044e6..aaa13a2 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/config/KiWiConfiguration.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/config/KiWiConfiguration.java
@@ -97,6 +97,9 @@ public class KiWiConfiguration {
      */
     private int cursorSize = 1000;
 
+    private boolean fulltextEnabled     = false;
+    private String[] fulltextLanguages;
+
     /**
      * The method to use for generating row IDs. Starting with Marmotta 3.2, the default is to use the Twitter Snowflake
      * algorithm.
@@ -258,4 +261,43 @@ public class KiWiConfiguration {
     public void setIdGeneratorType(IDGeneratorType idGeneratorType) {
         this.idGeneratorType = idGeneratorType;
     }
+
+    /**
+     * Return true in case fulltext support is enabled in this configuration. If this is the case, the SPARQL module
+     * will prepare the database with appropriate fulltext index support. Since this adds additional overhead, it is
+     * not enabled by default.
+     *
+     * @return
+     */
+    public boolean isFulltextEnabled() {
+        return fulltextEnabled;
+    }
+
+    /**
+     * Set to true in case fulltext support is enabled in this configuration. If this is the case, the SPARQL module
+     * will prepare the database with appropriate fulltext index support. Since this adds additional overhead, it is
+     * not enabled by default.
+     */
+    public void setFulltextEnabled(boolean fulltextEnabled) {
+        this.fulltextEnabled = fulltextEnabled;
+    }
+
+    /**
+     * Return the languages (ISO codes) for which to add specific fulltext search support. The SPARQL module will add a
+     * separate fulltext index for each supported language, adding additional overhead. In case you only want generic
+     * fulltext support, use the empty array.
+     */
+    public String[] getFulltextLanguages() {
+        return fulltextLanguages;
+    }
+
+    /**
+     * Set the languages (ISO codes) for which to add specific fulltext search support. The SPARQL module will add a
+     * separate fulltext index for each supported language, adding additional overhead. In case you only want generic
+     * fulltext support, use the empty array.
+     */
+    public void setFulltextLanguages(String[] fulltextLanguages) {
+        this.fulltextLanguages = fulltextLanguages;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
index c33b157..d0f0172 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
@@ -18,7 +18,15 @@
 package org.apache.marmotta.kiwi.persistence;
 
 import com.google.common.base.Preconditions;
-import info.aduna.iteration.*;
+import info.aduna.iteration.CloseableIteration;
+import info.aduna.iteration.ConvertingIteration;
+import info.aduna.iteration.DelayedIteration;
+import info.aduna.iteration.DistinctIteration;
+import info.aduna.iteration.EmptyIteration;
+import info.aduna.iteration.ExceptionConvertingIteration;
+import info.aduna.iteration.Iteration;
+import info.aduna.iteration.IteratorIteration;
+import info.aduna.iteration.UnionIteration;
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.Element;
 import org.apache.marmotta.commons.sesame.model.LiteralCommons;
@@ -38,9 +46,14 @@ import org.openrdf.repository.RepositoryResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.sql.*;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+import java.sql.Timestamp;
+import java.sql.Types;
 import java.util.*;
-import java.util.Date;
 import java.util.concurrent.locks.ReentrantLock;
 
 /**
@@ -1841,6 +1854,62 @@ public class KiWiConnection {
         }
     }
 
+    /**
+     * Return the metadata value with the given key; can be used by KiWi modules to retrieve module-specific metadata.
+     *
+     * @param key
+     * @return
+     * @throws SQLException
+     */
+    public String getMetadata(String key) throws SQLException {
+        requireJDBCConnection();
+
+        PreparedStatement statement = getPreparedStatement("meta.get");
+        statement.setString(1,key);
+        ResultSet result = statement.executeQuery();
+        try {
+            if(result.next()) {
+                return result.getString(1);
+            } else {
+                return null;
+            }
+        } finally {
+            result.close();
+        }
+    }
+
+
+    /**
+     * Update the metadata value for the given key; can be used by KiWi modules to set module-specific metadata.
+     *
+     * @param key
+     * @return
+     * @throws SQLException
+     */
+    public void setMetadata(String key, String value) throws SQLException {
+        requireJDBCConnection();
+
+        PreparedStatement statement = getPreparedStatement("meta.get");
+        ResultSet result = statement.executeQuery();
+        try {
+            if(result.next()) {
+                PreparedStatement update = getPreparedStatement("meta.update");
+                update.clearParameters();
+                update.setString(1, value);
+                update.setString(2, key);
+                update.executeUpdate();
+            } else {
+                PreparedStatement insert = getPreparedStatement("meta.insert");
+                insert.clearParameters();
+                insert.setString(1, key);
+                insert.setString(2, value);
+                insert.executeUpdate();
+            }
+        } finally {
+            result.close();
+        }
+    }
+
 
     /**
      * Return the KiWi version of the database this connection is operating on. This query is necessary for

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
index fcd731f..db49b8a 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/mysql/MySQLDialect.java
@@ -21,6 +21,7 @@ import com.google.common.base.Preconditions;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.marmotta.kiwi.exception.DriverNotFoundException;
 import org.apache.marmotta.kiwi.persistence.KiWiDialect;
+import org.apache.marmotta.kiwi.vocabulary.FN_MARMOTTA;
 import org.openrdf.model.URI;
 import org.openrdf.model.vocabulary.FN;
 
@@ -58,6 +59,8 @@ public class MySQLDialect extends KiWiDialect {
         supportedFunctions.add(FN.STRING_LENGTH);
         supportedFunctions.add(FN.STARTS_WITH);
         supportedFunctions.add(FN.ENDS_WITH);
+        supportedFunctions.add(FN_MARMOTTA.SEARCH_FULLTEXT);
+        supportedFunctions.add(FN_MARMOTTA.QUERY_FULLTEXT);
     }
 
     /**
@@ -163,6 +166,21 @@ public class MySQLDialect extends KiWiDialect {
         } else if(FN.ENDS_WITH.equals(fnUri)) {
             Preconditions.checkArgument(args.length == 2);
             return String.format("(POSITION(reverse(%2$s) IN reverse(%1$s)) = 1)", args[0], args[1]);
+        } else if(FN_MARMOTTA.SEARCH_FULLTEXT.equals(fnUri)) {
+            Preconditions.checkArgument(args.length == 2 || args.length == 3); // no specific language support in MySQL
+            return String.format("(MATCH (%1$s) AGAINST (%2$s))", args[0], args[1]);
+        } else if(FN_MARMOTTA.QUERY_FULLTEXT.equals(fnUri)) {
+            Preconditions.checkArgument(args.length == 2 || args.length == 3); // no specific language support in MySQL
+
+            // basic transformation from postgres to mysql syntax, assuming the argument is a constant query
+            String query;
+            if(args[1].startsWith("'")) {
+                query = args[1].replaceAll("&","+").replaceAll("\\|", " ").replaceAll("!"," -");
+            } else {
+                query = args[1];
+            }
+
+            return String.format("(MATCH (%1$s) AGAINST (%2$s IN BOOLEAN MODE))", args[0], query);
         }
         throw new UnsupportedOperationException("operation "+fnUri+" not supported");
     }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
index c0f681a..8e780f0 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/pgsql/PostgreSQLDialect.java
@@ -21,6 +21,7 @@ import com.google.common.base.Preconditions;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.marmotta.kiwi.exception.DriverNotFoundException;
 import org.apache.marmotta.kiwi.persistence.KiWiDialect;
+import org.apache.marmotta.kiwi.vocabulary.FN_MARMOTTA;
 import org.openrdf.model.URI;
 import org.openrdf.model.vocabulary.FN;
 
@@ -49,6 +50,8 @@ public class PostgreSQLDialect extends KiWiDialect {
         supportedFunctions.add(FN.STRING_LENGTH);
         supportedFunctions.add(FN.STARTS_WITH);
         supportedFunctions.add(FN.ENDS_WITH);
+        supportedFunctions.add(FN_MARMOTTA.SEARCH_FULLTEXT);
+        supportedFunctions.add(FN_MARMOTTA.QUERY_FULLTEXT);
     }
 
     /**
@@ -183,6 +186,22 @@ public class PostgreSQLDialect extends KiWiDialect {
         } else if(FN.ENDS_WITH.equals(fnUri)) {
             Preconditions.checkArgument(args.length == 2);
             return String.format("(POSITION(reverse(%2$s) IN reverse(%1$s)) = 1)", args[0], args[1]);
+        } else if(FN_MARMOTTA.SEARCH_FULLTEXT.equals(fnUri)) {
+            if(args.length == 2) {
+                return String.format("(to_tsvector('simple' :: regconfig,%1$s) @@ plainto_tsquery('simple' :: regconfig,%2$s))", args[0], args[1]);
+            } else if(args.length == 3) {
+                return String.format("(to_tsvector(kiwi_ft_lang(%3$s) :: regconfig, %1$s) @@ plainto_tsquery(kiwi_ft_lang(%3$s) :: regconfig, %2$s))", args[0], args[1], args[2]);
+            } else {
+                throw new IllegalArgumentException("invalid number of arguments");
+           }
+        } else if(FN_MARMOTTA.QUERY_FULLTEXT.equals(fnUri)) {
+            if(args.length == 2) {
+                return String.format("(to_tsvector('simple' :: regconfig,%1$s) @@ to_tsquery('simple' :: regconfig,%2$s))", args[0], args[1]);
+            } else if(args.length == 3) {
+                return String.format("(to_tsvector(kiwi_ft_lang(%3$s) :: regconfig, %1$s) @@ to_tsquery(kiwi_ft_lang(%3$s) :: regconfig, %2$s))", args[0], args[1], args[2]);
+            } else {
+                throw new IllegalArgumentException("invalid number of arguments");
+            }
         }
         throw new UnsupportedOperationException("operation "+fnUri+" not supported");
     }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/vocabulary/FN_MARMOTTA.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/vocabulary/FN_MARMOTTA.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/vocabulary/FN_MARMOTTA.java
new file mode 100644
index 0000000..c788bb0
--- /dev/null
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/vocabulary/FN_MARMOTTA.java
@@ -0,0 +1,41 @@
+package org.apache.marmotta.kiwi.vocabulary;
+
+import org.openrdf.model.Namespace;
+import org.openrdf.model.URI;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.model.impl.NamespaceImpl;
+import org.openrdf.model.impl.ValueFactoryImpl;
+
+/**
+ * Add file description here!
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class FN_MARMOTTA {
+
+    public static final String NAMESPACE = "http://marmotta.apache.org/vocabulary/sparql-functions#";
+
+    /**
+     * Recommended prefix for the XPath Functions namespace: "fn"
+     */
+    public static final String PREFIX = "mm";
+
+    /**
+     * An immutable {@link org.openrdf.model.Namespace} constant that represents the XPath
+     * Functions namespace.
+     */
+    public static final Namespace NS = new NamespaceImpl(PREFIX, NAMESPACE);
+
+
+
+    public static final URI SEARCH_FULLTEXT;
+
+    public static final URI QUERY_FULLTEXT;
+
+    static {
+        ValueFactory f = new ValueFactoryImpl();
+
+        SEARCH_FULLTEXT = f.createURI(NAMESPACE,"fulltext-search");
+        QUERY_FULLTEXT = f.createURI(NAMESPACE,"fulltext-query");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
index cdebd9e..4977ba6 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
+++ b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
@@ -19,6 +19,9 @@
 # get metainformation
 meta.tables            = SHOW TABLES;
 meta.version           = SELECT mvalue FROM metadata WHERE mkey = 'version';
+meta.insert            = INSERT INTO metadata(mkey,mvalue) VALUES(?,?);
+meta.update            = UPDATE metadata SET mvalue = ? WHERE mkey = ?;
+meta.get               = SELECT mvalue FROM metadata WHERE mkey = ?;
 
 # get sequence numbers
 seq.nodes              = SELECT nextval('seq_nodes')

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_base_tables.sql
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_base_tables.sql b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_base_tables.sql
index 67425ac..b4f3611 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_base_tables.sql
+++ b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/create_base_tables.sql
@@ -38,7 +38,7 @@ CREATE TABLE nodes (
   lang      varchar(5),
   createdAt timestamp  NOT NULL DEFAULT CURRENT_TIMESTAMP,
   PRIMARY KEY(id)
-) CHARACTER SET utf8 COLLATE utf8_bin  ENGINE=InnoDB;
+) CHARACTER SET utf8 COLLATE utf8_bin  ENGINE=MyISAM;
 
 CREATE TABLE triples (
   id        bigint     NOT NULL,

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
index a94272a..277311b 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
+++ b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
@@ -19,6 +19,9 @@
 # get metainformation
 meta.tables            = SHOW TABLES;
 meta.version           = SELECT mvalue FROM metadata WHERE mkey = 'version';
+meta.insert            = INSERT INTO metadata(mkey,mvalue) VALUES(?,?);
+meta.update            = UPDATE metadata SET mvalue = ? WHERE mkey = ?;
+meta.get               = SELECT mvalue FROM metadata WHERE mkey = ?;
 
 # get sequence numbers
 seq.nodes.prep         = UPDATE seq_nodes SET id=LAST_INSERT_ID(id+1);

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c0e5d9da/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
index 2ae6fa6..1007c03 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
+++ b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
@@ -18,6 +18,9 @@
 
 # get metainformation
 meta.tables            = select tablename from pg_tables where schemaname='public';
+meta.insert            = INSERT INTO metadata(mkey,mvalue) VALUES(?,?);
+meta.update            = UPDATE metadata SET mvalue = ? WHERE mkey = ?;
+meta.get               = SELECT mvalue FROM metadata WHERE mkey = ?;
 meta.version           = SELECT mvalue FROM metadata WHERE mkey = 'version';
 
 # get sequence numbers