|
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 |
| -/* GUC variable */ |
| 68 | +/* GUC variables */ |
69 | 69 | char *default_tablespace = NULL;
|
| 70 | +char *temp_tablespaces = NULL; |
70 | 71 |
|
| 72 | +int next_temp_tablespace; |
| 73 | +int num_temp_tablespaces; |
71 | 74 |
|
72 | 75 | static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
|
73 | 76 | static void set_short_version(const char *path);
|
@@ -930,6 +933,142 @@ GetDefaultTablespace(void)
|
930 | 933 | return result;
|
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 | +const char * |
| 942 | +assign_temp_tablespaces(const char *newval, bool doit, GucSource source) |
| 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 | + return NULL; |
| 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 | + return newval; |
| 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 | + Oid result; |
| 1004 | + char *curname = NULL; |
| 1005 | + char *rawname; |
| 1006 | + List *namelist; |
| 1007 | + ListCell *l; |
| 1008 | + int i = 0; |
| 1009 | + |
| 1010 | + if ( temp_tablespaces == NULL ) |
| 1011 | + return InvalidOid; |
| 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 | + return InvalidOid; |
| 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 | + return InvalidOid; |
| 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 | + return result; |
| 1071 | +} |
933 | 1072 |
|
934 | 1073 | /*
|
935 | 1074 | * get_tablespace_oid - given a tablespace name, look up the OID
|
|
0 commit comments