@@ -807,54 +807,91 @@ pg_ptrack_clear(void)
807807
808808/* Read and clear ptrack files of the target relation.
809809 * Result is a bytea ptrack map of all segments of the target relation.
810+ * case 1: we know a tablespace_oid, db_oid, and rel_filenode
811+ * case 2: we know db_oid and rel_filenode (no tablespace_oid, because file in pg_default)
812+ * case 3: we know only rel_filenode (because file in pg_global)
810813 */
811814static char *
812- pg_ptrack_get_and_clear (Oid tablespace_oid , Oid db_oid , Oid rel_oid ,
815+ pg_ptrack_get_and_clear (Oid tablespace_oid , Oid db_oid , Oid rel_filenode ,
813816 size_t * result_size )
814817{
815818 PGconn * tmp_conn ;
816819 PGresult * res_db ,
820+ * res_pg_global ,
817821 * res ;
818822 char * dbname ;
819823 char * params [2 ];
820824 char * result ;
825+ Oid pg_global_oid ;
821826
822827 params [0 ] = palloc (64 );
823828 params [1 ] = palloc (64 );
824- sprintf (params [0 ], "%i" , db_oid );
825829
826- res_db = pgut_execute (backup_conn ,
827- "SELECT datname FROM pg_database WHERE oid=$1" ,
828- 1 , (const char * * ) params );
830+ /* regular file (not in directory 'global') */
831+ if (db_oid != 0 )
832+ {
833+ sprintf (params [0 ], "%i" , db_oid );
834+ res_db = pgut_execute (backup_conn ,
835+ "SELECT datname FROM pg_database WHERE oid=$1" ,
836+ 1 , (const char * * ) params );
837+ /*
838+ * If database is not found, it's not an error.
839+ * It could have been deleted since previous backup.
840+ */
841+ if (PQntuples (res_db ) != 1 || PQnfields (res_db ) != 1 )
842+ return NULL ;
829843
830- /*
831- * If database is not found, it's not an error.
832- * It could have been deleted since previous backup.
833- */
834- if (PQntuples (res_db ) != 1 || PQnfields (res_db ) != 1 )
835- return NULL ;
844+ dbname = pstrdup (PQgetvalue (res_db , 0 , 0 ));
845+ PQclear (res_db );
836846
837- dbname = pstrdup (PQgetvalue (res_db , 0 , 0 ));
838- PQclear (res_db );
847+ tmp_conn = pgut_connect (dbname );
848+ sprintf (params [0 ], "%i" , tablespace_oid );
849+ sprintf (params [1 ], "%i" , rel_filenode );
850+ res = pgut_execute (tmp_conn , "SELECT pg_ptrack_get_and_clear($1, $2)" ,
851+ 2 , (const char * * )params );
852+
853+ if (PQnfields (res ) != 1 )
854+ elog (ERROR , "cannot get ptrack file from database \"%s\" by tablespace oid %u and relation oid %u" ,
855+ dbname , tablespace_oid , rel_filenode );
856+ pfree (dbname );
857+ pgut_disconnect (tmp_conn );
839858
840- tmp_conn = pgut_connect (dbname );
841- sprintf (params [0 ], "%i" , tablespace_oid );
842- sprintf (params [1 ], "%i" , rel_oid );
859+ }
860+ /* file in directory 'global' */
861+ else
862+ {
863+ /* get oid of pg_global */
864+ res_pg_global = pgut_execute (backup_conn ,
865+ "SELECT oid FROM pg_tablespace WHERE spcname = 'pg_global'" ,
866+ 0 , NULL );
867+ /*
868+ * something is very wrong, i.e. ptrack file are present in pg_global directory
869+ * but pg_global tablespace is missing in PostgreSQL catalogue
870+ */
871+ if (PQntuples (res_pg_global ) != 1 || PQnfields (res_pg_global ) != 1 )
872+ elog (ERROR , "cannot get oid of pg_global tablespace, which was needed"
873+ "for getting ptrack file content of filenode %u" ,
874+ rel_filenode );
875+
876+ pg_global_oid = atoi (pstrdup (PQgetvalue (res_pg_global , 0 , 0 )));
877+ PQclear (res_pg_global );
878+
879+ /* execute ptrack_get_and_clear for relation in pg_global */
880+ sprintf (params [0 ], "%i" , pg_global_oid );
881+ sprintf (params [1 ], "%i" , rel_filenode );
882+ res = pgut_execute (backup_conn , "SELECT pg_ptrack_get_and_clear($1, $2)" ,
883+ 2 , (const char * * )params );
884+
885+ if (PQnfields (res ) != 1 )
886+ elog (ERROR , "cannot get ptrack file from pg_global tablespace and relation oid %u" ,
887+ rel_filenode );
888+ }
843889
844- res = pgut_execute (tmp_conn , "SELECT pg_ptrack_get_and_clear($1, $2)" ,
845- 2 , (const char * * )params );
846- if (PQnfields (res ) != 1 )
847- elog (ERROR , "cannot get ptrack file from database \"%s\" by tablespace oid %u and relation oid %u" ,
848- dbname , tablespace_oid , rel_oid );
849890 result = (char * ) PQunescapeBytea ((unsigned char * ) PQgetvalue (res , 0 , 0 ),
850891 result_size );
851892 PQclear (res );
852-
853- pgut_disconnect (tmp_conn );
854-
855893 pfree (params [0 ]);
856894 pfree (params [1 ]);
857- pfree (dbname );
858895
859896 return result ;
860897}
@@ -1843,6 +1880,7 @@ make_pagemap_from_ptrack(parray *files)
18431880 if (p -> ptrack_path != NULL )
18441881 {
18451882 char * tablespace ;
1883+ char * global ;
18461884 Oid db_oid ,
18471885 rel_oid ,
18481886 tablespace_oid = 0 ;
@@ -1861,8 +1899,9 @@ make_pagemap_from_ptrack(parray *files)
18611899
18621900 /*
18631901 * Path has format:
1864- * pg_tblspc/tablespace_oid/tablespace_version_subdir/db_oid/rel_oid
1865- * base/db_oid/rel_oid
1902+ * pg_tblspc/tablespace_oid/tablespace_version_subdir/db_oid/rel_filenode
1903+ * base/db_oid/rel_filenode
1904+ * global/rel_filenode
18661905 */
18671906 sep_iter = strlen (p -> path );
18681907 while (sep_iter >= 0 )
@@ -1878,9 +1917,20 @@ make_pagemap_from_ptrack(parray *files)
18781917 elog (ERROR , "path of the file \"%s\" has wrong format" ,
18791918 p -> path );
18801919
1881- sscanf (p -> path + sep_iter + 1 , "%u/%u" , & db_oid , & rel_oid );
1920+ /*
1921+ * If file lies in directory 'global' we cannot get its db_oid from file path
1922+ * In this case we set db_oid to 0
1923+ */
1924+ global = strstr (p -> path + sep_iter + 1 , PG_GLOBAL_DIR );
1925+ if (global )
1926+ {
1927+ sscanf (global + strlen (PG_GLOBAL_DIR )+ 1 , "%u" , & rel_oid );
1928+ db_oid = 0 ;
1929+ }
1930+ else
1931+ sscanf (p -> path + sep_iter + 1 , "%u/%u" , & db_oid , & rel_oid );
18821932
1883- /* get ptrack map for all segments of the relation in a raw format */
1933+ /* get ptrack map for all segments of the relation in a raw format*/
18841934 ptrack_nonparsed = pg_ptrack_get_and_clear (tablespace_oid , db_oid ,
18851935 rel_oid , & ptrack_nonparsed_size );
18861936 if (ptrack_nonparsed != NULL )
0 commit comments