commit 235a42271eb45c9efdfeeddfd7fdba0ead282f19
Author: Sofia Papagiannaki <papagian@gmail.com>
Date:   Mon Apr 22 13:31:26 2013 +0300

    pithos: use other db escape string literal character
    
    Refs: #3645

diff --git a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/dbworker.py b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/dbworker.py
index 9f74c50..8ca8673 100644
--- a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/dbworker.py
+++ b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/dbworker.py
@@ -31,6 +31,7 @@
 # interpreted as representing official policies, either expressed
 # or implied, of GRNET S.A.
 
+ESCAPE_CHAR = '@'
 
 class DBWorker(object):
     """Database connection handler."""
@@ -42,5 +43,10 @@ class DBWorker(object):
         self.conn = wrapper.conn
         self.engine = wrapper.engine
 
-    def escape_like(self, s):
-        return s.replace('\\', '\\\\').replace('%', '\%').replace('_', '\_')
+    def escape_like(self, s, escape_char=ESCAPE_CHAR):
+        return (
+                s
+                .replace(escape_char, escape_char * 2)
+                .replace('%', escape_char + '%')
+                .replace('_', escape_char + '_')
+        )
diff --git a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/node.py b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/node.py
index bfce554..14f4706 100644
--- a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/node.py
+++ b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/node.py
@@ -40,7 +40,7 @@ from sqlalchemy.ext.compiler import compiles
 from sqlalchemy.engine.reflection import Inspector
 from sqlalchemy.exc import NoSuchTableError
 
-from dbworker import DBWorker
+from dbworker import DBWorker, ESCAPE_CHAR
 
 from pithos.backends.filter import parse_filters
 
@@ -237,7 +237,7 @@ class Node(DBWorker):
 
         # Use LIKE for comparison to avoid MySQL problems with trailing spaces.
         s = select([self.nodes.c.node], self.nodes.c.path.like(
-            self.escape_like(path), escape='\\'))
+            self.escape_like(path), escape=ESCAPE_CHAR))
         r = self.conn.execute(s)
         row = r.fetchone()
         r.close()
@@ -617,7 +617,7 @@ class Node(DBWorker):
             c1 = select([self.nodes.c.serial],
                         self.nodes.c.node == v.c.node)
         c2 = select([self.nodes.c.node], self.nodes.c.path.like(
-            self.escape_like(path) + '%', escape='\\'))
+            self.escape_like(path) + '%', escape=ESCAPE_CHAR))
         s = s.where(and_(v.c.serial == c1,
                          v.c.cluster != except_cluster,
                          v.c.node.in_(c2)))
@@ -904,7 +904,11 @@ class Node(DBWorker):
         for path, match in pathq:
             if match == MATCH_PREFIX:
                 conj.append(
-                    n.c.path.like(self.escape_like(path) + '%', escape='\\'))
+                    n.c.path.like(
+                        self.escape_like(path) + '%',
+                        escape=ESCAPE_CHAR
+                    )
+                )
             elif match == MATCH_EXACT:
                 conj.append(n.c.path == path)
         if conj:
@@ -999,7 +1003,11 @@ class Node(DBWorker):
         for path, match in pathq:
             if match == MATCH_PREFIX:
                 conj.append(
-                    n.c.path.like(self.escape_like(path) + '%', escape='\\'))
+                    n.c.path.like(
+                        self.escape_like(path) + '%',
+                        escape=ESCAPE_CHAR
+                    )
+                )
             elif match == MATCH_EXACT:
                 conj.append(n.c.path == path)
         if conj:
diff --git a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/permissions.py b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/permissions.py
index c914c07..41ddaeb 100644
--- a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/permissions.py
+++ b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/permissions.py
@@ -38,6 +38,8 @@ from xfeatures import XFeatures
 from groups import Groups
 from public import Public
 
+from dbworker import ESCAPE_CHAR
+
 
 READ = 0
 WRITE = 1
@@ -172,7 +174,8 @@ class Permissions(XFeatures, Groups, Public):
         s = select([self.xfeatures.c.path], from_obj=[inner_join]).distinct()
         if prefix:
             s = s.where(self.xfeatures.c.path.like(
-                self.escape_like(prefix) + '%', escape='\\'))
+                self.escape_like(prefix) + '%', escape=ESCAPE_CHAR
+            ))
         r = self.conn.execute(s)
         l = [row[0] for row in r.fetchall()]
         r.close()
@@ -182,7 +185,10 @@ class Permissions(XFeatures, Groups, Public):
         """Return the list of shared paths."""
 
         s = select([self.xfeatures.c.path],
-                   self.xfeatures.c.path.like(self.escape_like(prefix) + '%', escape='\\')).order_by(self.xfeatures.c.path.asc())
+                   self.xfeatures.c.path.like(self.escape_like(prefix) + '%',
+                                              escape=ESCAPE_CHAR
+                   )
+        ).order_by(self.xfeatures.c.path.asc())
         r = self.conn.execute(s)
         l = [row[0] for row in r.fetchall()]
         r.close()
diff --git a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/public.py b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/public.py
index 076d73e..16b0adb 100644
--- a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/public.py
+++ b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/public.py
@@ -39,6 +39,8 @@ from sqlalchemy.exc import NoSuchTableError
 
 from pithos.backends.random_word import get_random_word
 
+from dbworker import ESCAPE_CHAR
+
 import logging
 
 logger = logging.getLogger(__name__)
@@ -124,7 +126,7 @@ class Public(DBWorker):
     def public_list(self, prefix):
         s = select([self.public.c.path, self.public.c.url])
         s = s.where(self.public.c.path.like(
-            self.escape_like(prefix) + '%', escape='\\'))
+            self.escape_like(prefix) + '%', escape=ESCAPE_CHAR))
         s = s.where(self.public.c.active == True)
         r = self.conn.execute(s)
         rows = r.fetchall()
