CVS User Account cvsuser
Tue Jun 7 22:51:10 PDT 2005
Log Message:
-----------
Addressing bug report #1323...

There is a function called slon_quote_input() which puts extra "quotes"
into the input string in order to make it a valid fully quoted table
name or namespace name.

The version of the function in Beta5 uses arrays (and is somewhat gross;
I had a difficult time following how it worked) in a way not supported
by PostgreSQL 7.3.x.

In addition to replacing the function, it also turns out to be needful
to use the function in several queries in remote_worker.c where the
names of objects were not being quoted using this consistent approach.

Tested on...
 1. Debian/Linux (7.3.9, 8.0.2, 7.4.8)
 2. AIX (8.0.3)
 3. Solaris (8.0.3)

Modified Files:
--------------
    slony1-engine/src/backend:
        slony1_base.sql (r1.26 -> r1.27)
        slony1_funcs.sql (r1.63 -> r1.64)
        slony1_funcs.v73.sql (r1.6 -> r1.7)
    slony1-engine/src/slon:
        remote_worker.c (r1.85 -> r1.86)

-------------- next part --------------
Index: slony1_base.sql
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/backend/slony1_base.sql,v
retrieving revision 1.26
retrieving revision 1.27
diff -Lsrc/backend/slony1_base.sql -Lsrc/backend/slony1_base.sql -u -w -r1.26 -r1.27
--- src/backend/slony1_base.sql
+++ src/backend/slony1_base.sql
@@ -360,7 +360,7 @@
 	p_seqname	alias for $1;
 	v_seq_row	record;
 begin
-	for v_seq_row in execute ''select last_value from '' || p_seqname
+	for v_seq_row in execute ''select last_value from '' || @NAMESPACE at .slon_quote_input(p_seqname)
 	loop
 		return v_seq_row.last_value;
 	end loop;
Index: slony1_funcs.sql
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/backend/slony1_funcs.sql,v
retrieving revision 1.63
retrieving revision 1.64
diff -Lsrc/backend/slony1_funcs.sql -Lsrc/backend/slony1_funcs.sql -u -w -r1.63 -r1.64
--- src/backend/slony1_funcs.sql
+++ src/backend/slony1_funcs.sql
@@ -289,52 +289,84 @@
 --	This function will be used to quote user input.
 -- ----------------------------------------------------------------------
 
-create or replace function @NAMESPACE at .slon_quote_input (text) returns text
-as '
+--create or replace function @NAMESPACE at .slon_quote_input (text) returns text
+--as '
+--declare
+--    p_tab_fqname alias for $1;
+--    v_temp_fqname text default '''';
+--    v_pre_quoted text[] default ''{}'';
+--    v_pre_quote_counter smallint default 0;
+--    v_count_fqname smallint default 0;
+--    v_fqname_split text[];
+--    v_quoted_fqname text default '''';
+--begin
+--    v_temp_fqname := p_tab_fqname;
+
+--    LOOP
+--	v_pre_quote_counter := v_pre_quote_counter + 1;
+--	v_pre_quoted[v_pre_quote_counter] := 
+--	    substring(v_temp_fqname from ''%#"\"%\"#"%'' for ''#'');
+--	IF v_pre_quoted[v_pre_quote_counter] <> '''' THEN
+--	    v_temp_fqname := replace(v_temp_fqname,
+--	        v_pre_quoted[v_pre_quote_counter], ''@'' ||
+--		v_pre_quote_counter);
+--	ELSE
+--	    EXIT;
+--	END IF;
+--    END LOOP;
+
+--    v_fqname_split := string_to_array(v_temp_fqname , ''.'');
+--    v_count_fqname := array_upper (v_fqname_split, 1);
+
+--    FOR i in 1..v_count_fqname LOOP
+--        IF substring(v_fqname_split[i],1,1) = ''@'' THEN
+--            v_quoted_fqname := v_quoted_fqname || 
+--		v_pre_quoted[substring (v_fqname_split[i] from 2)::int];
+--        ELSE
+--            v_quoted_fqname := v_quoted_fqname || ''"'' || 
+--		v_fqname_split[i] || ''"'';
+--        END IF;
+
+--        IF i < v_count_fqname THEN
+--            v_quoted_fqname := v_quoted_fqname || ''.'' ;
+--        END IF;
+--    END LOOP;
+	
+--    return v_quoted_fqname;
+--end;
+--' language plpgsql;
+
+
+create or replace function @NAMESPACE at .slon_quote_input(text) returns text as '
 declare
     p_tab_fqname alias for $1;
-    v_temp_fqname text default '''';
-    v_pre_quoted text[] default ''{}'';
-    v_pre_quote_counter smallint default 0;
-    v_count_fqname smallint default 0;
-    v_fqname_split text[];
-    v_quoted_fqname text default '''';
-begin
-    v_temp_fqname := p_tab_fqname;
-
-    LOOP
-	v_pre_quote_counter := v_pre_quote_counter + 1;
-	v_pre_quoted[v_pre_quote_counter] := 
-	    substring(v_temp_fqname from ''%#"\"%\"#"%'' for ''#'');
-	IF v_pre_quoted[v_pre_quote_counter] <> '''' THEN
-	    v_temp_fqname := replace(v_temp_fqname,
-	        v_pre_quoted[v_pre_quote_counter], ''@'' ||
-		v_pre_quote_counter);
-	ELSE
-	    EXIT;
-	END IF;
-    END LOOP;
-
-    v_fqname_split := string_to_array(v_temp_fqname , ''.'');
-    v_count_fqname := array_upper (v_fqname_split, 1);
-
-    FOR i in 1..v_count_fqname LOOP
-        IF substring(v_fqname_split[i],1,1) = ''@'' THEN
-            v_quoted_fqname := v_quoted_fqname || 
-		v_pre_quoted[substring (v_fqname_split[i] from 2)::int];
-        ELSE
-            v_quoted_fqname := v_quoted_fqname || ''"'' || 
-		v_fqname_split[i] || ''"'';
-        END IF;
-
-        IF i < v_count_fqname THEN
-            v_quoted_fqname := v_quoted_fqname || ''.'' ;
-        END IF;
-    END LOOP;
-	
-    return v_quoted_fqname;
-end;
-' language plpgsql;
+     v_nsp_name text;
+     v_tab_name text;
+     v_pq2 integer;
+begin
+  if (p_tab_fqname like ''"%"."%"'') then
+    v_pq2 := position (''"'' in substr(p_tab_fqname, 2));
+    v_nsp_name := substr(p_tab_fqname, 2, v_pq2 - 1);
+    v_tab_name := substr(p_tab_fqname, v_pq2 + 4, length(p_tab_fqname) - (v_pq2 + 4));
+  elsif (p_tab_fqname like ''"%".%'') then
+    v_pq2 := position (''"'' in substr(p_tab_fqname, 2));
+    v_nsp_name := substr(p_tab_fqname, 2, v_pq2 - 1);
+    v_tab_name := substr(p_tab_fqname, v_pq2 + 3, length(p_tab_fqname) - (v_pq2 + 2));
+  elsif (p_tab_fqname like ''%."%"'') then
+    v_pq2 := position (''.'' in substr(p_tab_fqname, 2));
+    v_nsp_name := substr(p_tab_fqname, 1, v_pq2);
+    v_tab_name := substr(p_tab_fqname, v_pq2 + 3, length(p_tab_fqname) - (v_pq2 + 3));
+  elsif (p_tab_fqname like ''%.%'') then
+    v_pq2 := position (''.'' in substr(p_tab_fqname, 2));
+    v_nsp_name := substr(p_tab_fqname, 1, v_pq2);
+    v_tab_name := substr(p_tab_fqname, v_pq2 + 2);
+  elsif (p_tab_fqname like ''"%"'') then
+    return p_tab_fqname;
+  else
+     return ''"'' || p_tab_fqname || ''"'';
+  end if;
+  return ''"'' || v_nsp_name || ''"."'' || v_tab_name || ''"'';
+end;' language plpgsql;
 
 comment on function @NAMESPACE at .slon_quote_input(text) is
   'quote all words that aren''t quoted yet';
Index: slony1_funcs.v73.sql
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/backend/slony1_funcs.v73.sql,v
retrieving revision 1.6
retrieving revision 1.7
diff -Lsrc/backend/slony1_funcs.v73.sql -Lsrc/backend/slony1_funcs.v73.sql -u -w -r1.6 -r1.7
--- src/backend/slony1_funcs.v73.sql
+++ src/backend/slony1_funcs.v73.sql
@@ -21,9 +21,8 @@
 declare
 	p_tab_fqname		alias for $1;
 begin
-	execute ''delete from only '' || p_tab_fqname;
+	execute ''delete from only '' || @NAMESPACE at .slon_quote_input(p_tab_fqname);
 	return 1;
 end;
 ' language plpgsql;
 
-
Index: remote_worker.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/remote_worker.c,v
retrieving revision 1.85
retrieving revision 1.86
diff -Lsrc/slon/remote_worker.c -Lsrc/slon/remote_worker.c -u -w -r1.85 -r1.86
--- src/slon/remote_worker.c
+++ src/slon/remote_worker.c
@@ -2383,8 +2383,8 @@
 	 */
 	slon_mkquery(&query1,
 		     "select T.tab_id, "
-		     "    \"pg_catalog\".quote_ident(PGN.nspname) || '.' || "
-		     "    \"pg_catalog\".quote_ident(PGC.relname) as tab_fqname, "
+		     "    %s.slon_quote_input('\"' || PGN.nspname || '\".\"' || "
+		     "    PGC.relname || '\"') as tab_fqname, "
 		     "    T.tab_idxname, T.tab_comment "
 		     "from %s.sl_table T, "
 		     "    \"pg_catalog\".pg_class PGC, "
@@ -2393,7 +2393,9 @@
 		     "    and T.tab_reloid = PGC.oid "
 		     "    and PGC.relnamespace = PGN.oid "
 		     "order by tab_id; ",
-		     rtcfg_namespace, set_id);
+		     rtcfg_namespace, 
+		     rtcfg_namespace, 
+		     set_id);
 	res1 = PQexec(pro_dbconn, dstring_data(&query1));
 	if (PQresultStatus(res1) != PGRES_TUPLES_OK)
 	{
@@ -2491,8 +2493,8 @@
 	 */
 	slon_mkquery(&query1,
 		     "select SQ.seq_id, "
-		     "		\"pg_catalog\".quote_ident(PGN.nspname) || '.' || "
-		     "		\"pg_catalog\".quote_ident(PGC.relname), "
+		     "    %s.slon_quote_input('\"' || PGN.nspname || '\".\"' || "
+		     "    PGC.relname || '\"') as tab_fqname, "
 		     "		SQ.seq_comment "
 		     "	from %s.sl_sequence SQ, "
 		     "		\"pg_catalog\".pg_class PGC, "
@@ -2500,7 +2502,9 @@
 		     "	where SQ.seq_set = %d "
 		     "		and PGC.oid = SQ.seq_reloid "
 		     "		and PGN.oid = PGC.relnamespace; ",
-		     rtcfg_namespace, set_id);
+		     rtcfg_namespace, 
+		     rtcfg_namespace, 
+		     set_id);
 	res1 = PQexec(pro_dbconn, dstring_data(&query1));
 	if (PQresultStatus(res1) != PGRES_TUPLES_OK)
 	{
@@ -2545,8 +2549,8 @@
 	 */
 	slon_mkquery(&query1,
 		     "select T.tab_id, "
-		     "    \"pg_catalog\".quote_ident(PGN.nspname) || '.' || "
-		     "    \"pg_catalog\".quote_ident(PGC.relname) as tab_fqname, "
+		     "    %s.slon_quote_input('\"' || PGN.nspname || '\".\"' || "
+		     "    PGC.relname || '\"') as tab_fqname, "
 		     "    T.tab_idxname, T.tab_comment "
 		     "from %s.sl_table T, "
 		     "    \"pg_catalog\".pg_class PGC, "
@@ -2555,7 +2559,9 @@
 		     "    and T.tab_reloid = PGC.oid "
 		     "    and PGC.relnamespace = PGN.oid "
 		     "order by tab_id; ",
-		     rtcfg_namespace, set_id);
+		     rtcfg_namespace, 
+		     rtcfg_namespace, 
+		     set_id);
 	res1 = PQexec(pro_dbconn, dstring_data(&query1));
 	if (PQresultStatus(res1) != PGRES_TUPLES_OK)
 	{
@@ -2954,7 +2960,7 @@
 		}
 		PQputline(loc_dbconn, "\\.\n");
 		if (archive_dir) {
-			rc = submit_string_to_archive("\\\.");
+			rc = submit_string_to_archive("\\.");
 		}
 		/*
 		 * End the COPY to stdout on the provider
@@ -3092,8 +3098,8 @@
 	 */
 	slon_mkquery(&query1,
 		     "select SL.seql_seqid, SL.seql_last_value, "
-		     "	\"pg_catalog\".quote_ident(PGN.nspname) || '.' || "
-		     "	\"pg_catalog\".quote_ident(PGC.relname) "
+		     "    %s.slon_quote_input('\"' || PGN.nspname || '\".\"' || "
+		     "    PGC.relname || '\"') as tab_fqname "
 		     "	from %s.sl_sequence SQ, %s.sl_seqlog SL, "
 		     "		\"pg_catalog\".pg_class PGC, "
 		     "		\"pg_catalog\".pg_namespace PGN "
@@ -3102,7 +3108,9 @@
 		     "		and SL.seql_ev_seqno = '%s' "
 		     "		and PGC.oid = SQ.seq_reloid "
 		     "		and PGN.oid = PGC.relnamespace; ",
-		     rtcfg_namespace, rtcfg_namespace,
+		     rtcfg_namespace, 
+		     rtcfg_namespace, 
+		     rtcfg_namespace,
 		     set_id, seqbuf);
 	res1 = PQexec(pro_dbconn, dstring_data(&query1));
 	if (PQresultStatus(res1) != PGRES_TUPLES_OK)
@@ -3692,15 +3700,17 @@
 			 */
 			slon_mkquery(&query,
 						 "select T.tab_id, T.tab_set, "
-					 "    \"pg_catalog\".quote_ident(PGN.nspname) || '.' || "
-				 "    \"pg_catalog\".quote_ident(PGC.relname) as tab_fqname "
+				     "    %s.slon_quote_input('\"' || PGN.nspname || '\".\"' || "
+				     "    PGC.relname || '\"') as tab_fqname "
 						 "from %s.sl_table T, "
 						 "    \"pg_catalog\".pg_class PGC, "
 						 "    \"pg_catalog\".pg_namespace PGN "
 						 "where T.tab_set = %d "
 						 "    and PGC.oid = T.tab_reloid "
 						 "    and PGC.relnamespace = PGN.oid; ",
-						 rtcfg_namespace, sub_set);
+				     rtcfg_namespace, 
+				     rtcfg_namespace, 
+				     sub_set);
 			res2 = PQexec(local_dbconn, dstring_data(&query));
 			if (PQresultStatus(res2) != PGRES_TUPLES_OK)
 			{


More information about the Slony1-commit mailing list