|
37 | 37 | *
|
38 | 38 | *
|
39 | 39 | * IDENTIFICATION
|
40 |
| - * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.40 2007/01/05 22:19:26 momjian Exp $ |
| 40 | + * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.41 2007/01/25 04:35:10 momjian Exp $ |
41 | 41 | *
|
42 | 42 | *-------------------------------------------------------------------------
|
43 | 43 | */
|
|
65 | 65 | #include"utils/lsyscache.h"
|
66 | 66 |
|
67 | 67 |
|
68 |
| -/* GUCvariable */ |
| 68 | +/* GUCvariables */ |
69 | 69 | char*default_tablespace=NULL;
|
| 70 | +char*temp_tablespaces=NULL; |
70 | 71 |
|
| 72 | +intnext_temp_tablespace; |
| 73 | +intnum_temp_tablespaces; |
71 | 74 |
|
72 | 75 | staticboolremove_tablespace_directories(Oidtablespaceoid,boolredo);
|
73 | 76 | staticvoidset_short_version(constchar*path);
|
@@ -930,6 +933,142 @@ GetDefaultTablespace(void)
|
930 | 933 | returnresult;
|
931 | 934 | }
|
932 | 935 |
|
| 936 | +/* |
| 937 | + * Routines for handling the GUC variable 'temp_tablespaces'. |
| 938 | + */ |
| 939 | + |
| 940 | +/* assign_hook: validate new temp_tablespaces, do extra actions as needed */ |
| 941 | +constchar* |
| 942 | +assign_temp_tablespaces(constchar*newval,booldoit,GucSourcesource) |
| 943 | +{ |
| 944 | +char*rawname; |
| 945 | +List*namelist; |
| 946 | +ListCell*l; |
| 947 | + |
| 948 | +/* Need a modifiable copy of string */ |
| 949 | +rawname=pstrdup(newval); |
| 950 | + |
| 951 | +/* Parse string into list of identifiers */ |
| 952 | +if (!SplitIdentifierString(rawname,',',&namelist)) |
| 953 | +{ |
| 954 | +/* syntax error in name list */ |
| 955 | +pfree(rawname); |
| 956 | +list_free(namelist); |
| 957 | +returnNULL; |
| 958 | +} |
| 959 | + |
| 960 | +num_temp_tablespaces=0; |
| 961 | +foreach(l,namelist) |
| 962 | +{ |
| 963 | +char*curname= (char*)lfirst(l); |
| 964 | + |
| 965 | +/* |
| 966 | + * If we aren't inside a transaction, we cannot do database access so |
| 967 | + * cannot verify the individual names.Must accept the list on faith. |
| 968 | + */ |
| 969 | +if (source >=PGC_S_INTERACTIVE&&IsTransactionState()) |
| 970 | +{ |
| 971 | +/* |
| 972 | + * Verify that all the names are valid tablspace names |
| 973 | + * We do not check for USAGE rights should we? |
| 974 | + */ |
| 975 | +if (get_tablespace_oid(curname)==InvalidOid) |
| 976 | +ereport((source==PGC_S_TEST) ?NOTICE :ERROR, |
| 977 | +(errcode(ERRCODE_UNDEFINED_OBJECT), |
| 978 | +errmsg("tablespace \"%s\" does not exist",curname))); |
| 979 | +} |
| 980 | +num_temp_tablespaces++; |
| 981 | +} |
| 982 | + |
| 983 | +/* |
| 984 | + * Select the first tablespace to use |
| 985 | + */ |
| 986 | +next_temp_tablespace=MyProcPid %num_temp_tablespaces; |
| 987 | + |
| 988 | +pfree(rawname); |
| 989 | +list_free(namelist); |
| 990 | +returnnewval; |
| 991 | +} |
| 992 | + |
| 993 | +/* |
| 994 | + * GetTempTablespace -- get the OID of the tablespace for temporary objects |
| 995 | + * |
| 996 | + * May return InvalidOid to indicate "use the database's default tablespace" |
| 997 | + * |
| 998 | + * This exists to hide the temp_tablespace GUC variable. |
| 999 | + */ |
| 1000 | +Oid |
| 1001 | +GetTempTablespace(void) |
| 1002 | +{ |
| 1003 | +Oidresult; |
| 1004 | +char*curname=NULL; |
| 1005 | +char*rawname; |
| 1006 | +List*namelist; |
| 1007 | +ListCell*l; |
| 1008 | +inti=0; |
| 1009 | + |
| 1010 | +if (temp_tablespaces==NULL ) |
| 1011 | +returnInvalidOid; |
| 1012 | + |
| 1013 | +/* Need a modifiable version of temp_tablespaces */ |
| 1014 | +rawname=pstrdup(temp_tablespaces); |
| 1015 | + |
| 1016 | +/* Parse string into list of identifiers */ |
| 1017 | +if (!SplitIdentifierString(rawname,',',&namelist)) |
| 1018 | +{ |
| 1019 | +/* syntax error in name list */ |
| 1020 | +pfree(rawname); |
| 1021 | +list_free(namelist); |
| 1022 | +returnInvalidOid; |
| 1023 | +} |
| 1024 | + |
| 1025 | +/* |
| 1026 | + * Iterate through the list of namespaces until the one we need |
| 1027 | + * (next_temp_tablespace) |
| 1028 | + */ |
| 1029 | +foreach(l,namelist) |
| 1030 | +{ |
| 1031 | +curname= (char*)lfirst(l); |
| 1032 | +if (i==next_temp_tablespace ) |
| 1033 | +break; |
| 1034 | +i++; |
| 1035 | +} |
| 1036 | + |
| 1037 | + |
| 1038 | +/* Prepare for the next time the function is called */ |
| 1039 | +next_temp_tablespace++; |
| 1040 | +if (next_temp_tablespace==num_temp_tablespaces) |
| 1041 | +next_temp_tablespace=0; |
| 1042 | + |
| 1043 | +/* Fast path for temp_tablespaces == "" */ |
| 1044 | +if (curname==NULL||curname[0]=='\0') { |
| 1045 | +list_free(namelist); |
| 1046 | +pfree(rawname); |
| 1047 | +returnInvalidOid; |
| 1048 | +} |
| 1049 | + |
| 1050 | +/* |
| 1051 | + * It is tempting to cache this lookup for more speed, but then we would |
| 1052 | + * fail to detect the case where the tablespace was dropped since the GUC |
| 1053 | + * variable was set. Note also that we don't complain if the value fails |
| 1054 | + * to refer to an existing tablespace; we just silently return InvalidOid, |
| 1055 | + * causing the new object to be created in the database's tablespace. |
| 1056 | + */ |
| 1057 | +result=get_tablespace_oid(curname); |
| 1058 | + |
| 1059 | +/* We don't free rawname before because curname points to a part of it */ |
| 1060 | +pfree(rawname); |
| 1061 | + |
| 1062 | +/* |
| 1063 | + * Allow explicit specification of database's default tablespace in |
| 1064 | + * default_tablespace without triggering permissions checks. |
| 1065 | + */ |
| 1066 | +if (result==MyDatabaseTableSpace) |
| 1067 | +result=InvalidOid; |
| 1068 | + |
| 1069 | +list_free(namelist); |
| 1070 | +returnresult; |
| 1071 | +} |
933 | 1072 |
|
934 | 1073 | /*
|
935 | 1074 | * get_tablespace_oid - given a tablespace name, look up the OID
|
|