@@ -807,54 +807,91 @@ pg_ptrack_clear(void)
807
807
808
808
/* Read and clear ptrack files of the target relation.
809
809
* 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)
810
813
*/
811
814
static 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 ,
813
816
size_t * result_size )
814
817
{
815
818
PGconn * tmp_conn ;
816
819
PGresult * res_db ,
820
+ * res_pg_global ,
817
821
* res ;
818
822
char * dbname ;
819
823
char * params [2 ];
820
824
char * result ;
825
+ Oid pg_global_oid ;
821
826
822
827
params [0 ] = palloc (64 );
823
828
params [1 ] = palloc (64 );
824
- sprintf (params [0 ], "%i" , db_oid );
825
829
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 ;
829
843
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 );
836
846
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 );
839
858
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
+ }
843
889
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 );
849
890
result = (char * ) PQunescapeBytea ((unsigned char * ) PQgetvalue (res , 0 , 0 ),
850
891
result_size );
851
892
PQclear (res );
852
-
853
- pgut_disconnect (tmp_conn );
854
-
855
893
pfree (params [0 ]);
856
894
pfree (params [1 ]);
857
- pfree (dbname );
858
895
859
896
return result ;
860
897
}
@@ -1843,6 +1880,7 @@ make_pagemap_from_ptrack(parray *files)
1843
1880
if (p -> ptrack_path != NULL )
1844
1881
{
1845
1882
char * tablespace ;
1883
+ char * global ;
1846
1884
Oid db_oid ,
1847
1885
rel_oid ,
1848
1886
tablespace_oid = 0 ;
@@ -1861,8 +1899,9 @@ make_pagemap_from_ptrack(parray *files)
1861
1899
1862
1900
/*
1863
1901
* 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
1866
1905
*/
1867
1906
sep_iter = strlen (p -> path );
1868
1907
while (sep_iter >= 0 )
@@ -1878,9 +1917,20 @@ make_pagemap_from_ptrack(parray *files)
1878
1917
elog (ERROR , "path of the file \"%s\" has wrong format" ,
1879
1918
p -> path );
1880
1919
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 );
1882
1932
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*/
1884
1934
ptrack_nonparsed = pg_ptrack_get_and_clear (tablespace_oid , db_oid ,
1885
1935
rel_oid , & ptrack_nonparsed_size );
1886
1936
if (ptrack_nonparsed != NULL )
0 commit comments