variable.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:13k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*
  2.  * Routines for handling of 'SET var TO',
  3.  * 'SHOW var' and 'RESET var' statements.
  4.  *
  5.  * $Id: variable.c,v 1.23.2.1 1999/08/02 05:57:00 scrappy Exp $
  6.  *
  7.  */
  8. #include <ctype.h>
  9. #include <time.h>
  10. #include "postgres.h"
  11. #include "access/xact.h"
  12. #include "commands/variable.h"
  13. #include "miscadmin.h"
  14. #include "optimizer/internal.h"
  15. #include "utils/builtins.h"
  16. #include "utils/tqual.h"
  17. #ifdef MULTIBYTE
  18. #include "mb/pg_wchar.h"
  19. #endif
  20. static bool show_date(void);
  21. static bool reset_date(void);
  22. static bool parse_date(const char *);
  23. static bool show_timezone(void);
  24. static bool reset_timezone(void);
  25. static bool parse_timezone(const char *);
  26. static bool show_cost_heap(void);
  27. static bool reset_cost_heap(void);
  28. static bool parse_cost_heap(const char *);
  29. static bool show_cost_index(void);
  30. static bool reset_cost_index(void);
  31. static bool parse_cost_index(const char *);
  32. static bool reset_geqo(void);
  33. static bool show_geqo(void);
  34. static bool parse_geqo(const char *);
  35. static bool show_ksqo(void);
  36. static bool reset_ksqo(void);
  37. static bool parse_ksqo(const char *);
  38. static bool show_XactIsoLevel(void);
  39. static bool reset_XactIsoLevel(void);
  40. static bool parse_XactIsoLevel(const char *);
  41. extern Cost _cpu_page_weight_;
  42. extern Cost _cpu_index_page_weight_;
  43. extern bool _use_geqo_;
  44. extern int32 _use_geqo_rels_;
  45. extern bool _use_keyset_query_optimizer;
  46. /*
  47.  *
  48.  * Get_Token
  49.  *
  50.  */
  51. static const char *
  52. get_token(char **tok, char **val, const char *str)
  53. {
  54. const char *start;
  55. int len = 0;
  56. *tok = NULL;
  57. if (val != NULL)
  58. *val = NULL;
  59. if (!(*str))
  60. return NULL;
  61. /* skip white spaces */
  62. while (isspace(*str))
  63. str++;
  64. if (*str == ',' || *str == '=')
  65. elog(ERROR, "Syntax error near (%s): empty setting", str);
  66. /* end of string? then return NULL */
  67. if (!(*str))
  68. return NULL;
  69. /* OK, at beginning of non-NULL string... */
  70. start = str;
  71. /*
  72.  * count chars in token until we hit white space or comma or '=' or
  73.  * end of string
  74.  */
  75. while (*str && (!isspace(*str))
  76.    && *str != ',' && *str != '=')
  77. {
  78. str++;
  79. len++;
  80. }
  81. *tok = (char *) palloc(len + 1);
  82. StrNCpy(*tok, start, len + 1);
  83. /* skip white spaces */
  84. while (isspace(*str))
  85. str++;
  86. /* end of string? */
  87. if (!(*str))
  88. {
  89. return str;
  90. /* delimiter? */
  91. }
  92. else if (*str == ',')
  93. {
  94. return ++str;
  95. }
  96. else if ((val == NULL) || (*str != '='))
  97. {
  98. elog(ERROR, "Syntax error near (%s)", str);
  99. };
  100. str++; /* '=': get value */
  101. len = 0;
  102. /* skip white spaces */
  103. while (isspace(*str))
  104. str++;
  105. if (*str == ',' || !(*str))
  106. elog(ERROR, "Syntax error near (=%s)", str);
  107. start = str;
  108. /*
  109.  * count chars in token's value until we hit white space or comma or
  110.  * end of string
  111.  */
  112. while (*str && (!isspace(*str)) && *str != ',')
  113. {
  114. str++;
  115. len++;
  116. }
  117. *val = (char *) palloc(len + 1);
  118. StrNCpy(*val, start, len + 1);
  119. /* skip white spaces */
  120. while (isspace(*str))
  121. str++;
  122. if (!(*str))
  123. return NULL;
  124. if (*str == ',')
  125. return ++str;
  126. elog(ERROR, "Syntax error near (%s)", str);
  127. return str;
  128. }
  129. /*
  130.  *
  131.  * GEQO
  132.  *
  133.  */
  134. static bool
  135. parse_geqo(const char *value)
  136. {
  137. const char *rest;
  138. char    *tok,
  139.    *val;
  140. if (value == NULL)
  141. {
  142. reset_geqo();
  143. return TRUE;
  144. }
  145. rest = get_token(&tok, &val, value);
  146. if (tok == NULL)
  147. elog(ERROR, "Value undefined");
  148. if ((rest) && (*rest != ''))
  149. elog(ERROR, "Unable to parse '%s'", value);
  150. if (strcasecmp(tok, "on") == 0)
  151. {
  152. int32 geqo_rels = GEQO_RELS;
  153. if (val != NULL)
  154. {
  155. geqo_rels = pg_atoi(val, sizeof(int32), '');
  156. if (geqo_rels <= 1)
  157. elog(ERROR, "Bad value for # of relations (%s)", val);
  158. pfree(val);
  159. }
  160. _use_geqo_ = true;
  161. _use_geqo_rels_ = geqo_rels;
  162. }
  163. else if (strcasecmp(tok, "off") == 0)
  164. {
  165. if ((val != NULL) && (*val != ''))
  166. elog(ERROR, "%s does not allow a parameter", tok);
  167. _use_geqo_ = false;
  168. }
  169. else
  170. elog(ERROR, "Bad value for GEQO (%s)", value);
  171. pfree(tok);
  172. return TRUE;
  173. }
  174. static bool
  175. show_geqo()
  176. {
  177. if (_use_geqo_)
  178. elog(NOTICE, "GEQO is ON beginning with %d relations", _use_geqo_rels_);
  179. else
  180. elog(NOTICE, "GEQO is OFF");
  181. return TRUE;
  182. }
  183. static bool
  184. reset_geqo(void)
  185. {
  186. #ifdef GEQO
  187. _use_geqo_ = true;
  188. #else
  189. _use_geqo_ = false;
  190. #endif
  191. _use_geqo_rels_ = GEQO_RELS;
  192. return TRUE;
  193. }
  194. /*
  195.  *
  196.  * COST_HEAP
  197.  *
  198.  */
  199. static bool
  200. parse_cost_heap(const char *value)
  201. {
  202. float32 res;
  203. if (value == NULL)
  204. {
  205. reset_cost_heap();
  206. return TRUE;
  207. }
  208. res = float4in((char *) value);
  209. _cpu_page_weight_ = *res;
  210. return TRUE;
  211. }
  212. static bool
  213. show_cost_heap()
  214. {
  215. elog(NOTICE, "COST_HEAP is %f", _cpu_page_weight_);
  216. return TRUE;
  217. }
  218. static bool
  219. reset_cost_heap()
  220. {
  221. _cpu_page_weight_ = _CPU_PAGE_WEIGHT_;
  222. return TRUE;
  223. }
  224. /*
  225.  *
  226.  * COST_INDEX
  227.  *
  228.  */
  229. static bool
  230. parse_cost_index(const char *value)
  231. {
  232. float32 res;
  233. if (value == NULL)
  234. {
  235. reset_cost_index();
  236. return TRUE;
  237. }
  238. res = float4in((char *) value);
  239. _cpu_index_page_weight_ = *res;
  240. return TRUE;
  241. }
  242. static bool
  243. show_cost_index()
  244. {
  245. elog(NOTICE, "COST_INDEX is %f", _cpu_index_page_weight_);
  246. return TRUE;
  247. }
  248. static bool
  249. reset_cost_index()
  250. {
  251. _cpu_index_page_weight_ = _CPU_INDEX_PAGE_WEIGHT_;
  252. return TRUE;
  253. }
  254. /*
  255.  *
  256.  * DATE_STYLE
  257.  *
  258.  */
  259. static bool
  260. parse_date(const char *value)
  261. {
  262. char    *tok;
  263. int dcnt = 0,
  264. ecnt = 0;
  265. if (value == NULL)
  266. {
  267. reset_date();
  268. return TRUE;
  269. }
  270. while ((value = get_token(&tok, NULL, value)) != 0)
  271. {
  272. /* Ugh. Somebody ought to write a table driven version -- mjl */
  273. if (!strcasecmp(tok, "ISO"))
  274. {
  275. DateStyle = USE_ISO_DATES;
  276. dcnt++;
  277. }
  278. else if (!strcasecmp(tok, "SQL"))
  279. {
  280. DateStyle = USE_SQL_DATES;
  281. dcnt++;
  282. }
  283. else if (!strcasecmp(tok, "POSTGRES"))
  284. {
  285. DateStyle = USE_POSTGRES_DATES;
  286. dcnt++;
  287. }
  288. else if (!strcasecmp(tok, "GERMAN"))
  289. {
  290. DateStyle = USE_GERMAN_DATES;
  291. dcnt++;
  292. EuroDates = TRUE;
  293. if ((ecnt > 0) && (!EuroDates))
  294. ecnt++;
  295. }
  296. else if (!strncasecmp(tok, "EURO", 4))
  297. {
  298. EuroDates = TRUE;
  299. if ((dcnt <= 0) || (DateStyle != USE_GERMAN_DATES))
  300. ecnt++;
  301. }
  302. else if ((!strcasecmp(tok, "US"))
  303.  || (!strncasecmp(tok, "NONEURO", 7)))
  304. {
  305. EuroDates = FALSE;
  306. if ((dcnt <= 0) || (DateStyle == USE_GERMAN_DATES))
  307. ecnt++;
  308. }
  309. else if (!strcasecmp(tok, "DEFAULT"))
  310. {
  311. DateStyle = USE_POSTGRES_DATES;
  312. EuroDates = FALSE;
  313. ecnt++;
  314. }
  315. else
  316. elog(ERROR, "Bad value for date style (%s)", tok);
  317. pfree(tok);
  318. }
  319. if (dcnt > 1 || ecnt > 1)
  320. elog(NOTICE, "Conflicting settings for date");
  321. return TRUE;
  322. }
  323. static bool
  324. show_date()
  325. {
  326. char buf[64];
  327. strcpy(buf, "DateStyle is ");
  328. switch (DateStyle)
  329. {
  330. case USE_ISO_DATES:
  331. strcat(buf, "ISO");
  332. break;
  333. case USE_SQL_DATES:
  334. strcat(buf, "SQL");
  335. break;
  336. case USE_GERMAN_DATES:
  337. strcat(buf, "German");
  338. break;
  339. default:
  340. strcat(buf, "Postgres");
  341. break;
  342. };
  343. strcat(buf, " with ");
  344. strcat(buf, ((EuroDates) ? "European" : "US (NonEuropean)"));
  345. strcat(buf, " conventions");
  346. elog(NOTICE, buf, NULL);
  347. return TRUE;
  348. }
  349. static bool
  350. reset_date()
  351. {
  352. DateStyle = USE_POSTGRES_DATES;
  353. EuroDates = FALSE;
  354. return TRUE;
  355. }
  356. /* Timezone support
  357.  * Working storage for strings is allocated with an arbitrary size of 64 bytes.
  358.  */
  359. static char *defaultTZ = NULL;
  360. static char TZvalue[64];
  361. static char tzbuf[64];
  362. /*
  363.  *
  364.  * TIMEZONE
  365.  *
  366.  */
  367. /* parse_timezone()
  368.  * Handle SET TIME ZONE...
  369.  * Try to save existing TZ environment variable for later use in RESET TIME ZONE.
  370.  * - thomas 1997-11-10
  371.  */
  372. static bool
  373. parse_timezone(const char *value)
  374. {
  375. char    *tok;
  376. if (value == NULL)
  377. {
  378. reset_timezone();
  379. return TRUE;
  380. }
  381. while ((value = get_token(&tok, NULL, value)) != 0)
  382. {
  383. /* Not yet tried to save original value from environment? */
  384. if (defaultTZ == NULL)
  385. {
  386. /* found something? then save it for later */
  387. if ((defaultTZ = getenv("TZ")) != NULL)
  388. strcpy(TZvalue, defaultTZ);
  389. /* found nothing so mark with an invalid pointer */
  390. else
  391. defaultTZ = (char *) -1;
  392. }
  393. strcpy(tzbuf, "TZ=");
  394. strcat(tzbuf, tok);
  395. if (putenv(tzbuf) != 0)
  396. elog(ERROR, "Unable to set TZ environment variable to %s", tok);
  397. tzset();
  398. pfree(tok);
  399. }
  400. return TRUE;
  401. } /* parse_timezone() */
  402. static bool
  403. show_timezone()
  404. {
  405. char    *tz;
  406. tz = getenv("TZ");
  407. elog(NOTICE, "Time zone is %s", ((tz != NULL) ? tz : "unknown"));
  408. return TRUE;
  409. } /* show_timezone() */
  410. /* reset_timezone()
  411.  * Set TZ environment variable to original value.
  412.  * Note that if TZ was originally not set, TZ should be cleared.
  413.  * unsetenv() works fine, but is BSD, not POSIX, and is not available
  414.  * under Solaris, among others. Apparently putenv() called as below
  415.  * clears the process-specific environment variables.
  416.  * Other reasonable arguments to putenv() (e.g. "TZ=", "TZ", "") result
  417.  * in a core dump (under Linux anyway).
  418.  * - thomas 1998-01-26
  419.  */
  420. static bool
  421. reset_timezone()
  422. {
  423. /* no time zone has been set in this session? */
  424. if (defaultTZ == NULL)
  425. {
  426. }
  427. /* time zone was set and original explicit time zone available? */
  428. else if (defaultTZ != (char *) -1)
  429. {
  430. strcpy(tzbuf, "TZ=");
  431. strcat(tzbuf, TZvalue);
  432. if (putenv(tzbuf) != 0)
  433. elog(ERROR, "Unable to set TZ environment variable to %s", TZvalue);
  434. tzset();
  435. }
  436. /*
  437.  * otherwise, time zone was set but no original explicit time zone
  438.  * available
  439.  */
  440. else
  441. {
  442. strcpy(tzbuf, "=");
  443. if (putenv(tzbuf) != 0)
  444. elog(ERROR, "Unable to clear TZ environment variable", NULL);
  445. tzset();
  446. }
  447. return TRUE;
  448. } /* reset_timezone() */
  449. /*-----------------------------------------------------------------------*/
  450. struct VariableParsers
  451. {
  452. const char *name;
  453. bool (*parser) (const char *);
  454. bool (*show) ();
  455. bool (*reset) ();
  456. } VariableParsers[] =
  457. {
  458. {
  459. "datestyle", parse_date, show_date, reset_date
  460. },
  461. {
  462. "timezone", parse_timezone, show_timezone, reset_timezone
  463. },
  464. {
  465. "cost_heap", parse_cost_heap, show_cost_heap, reset_cost_heap
  466. },
  467. {
  468. "cost_index", parse_cost_index, show_cost_index, reset_cost_index
  469. },
  470. {
  471. "geqo", parse_geqo, show_geqo, reset_geqo
  472. },
  473. #ifdef MULTIBYTE
  474. {
  475. "client_encoding", parse_client_encoding, show_client_encoding, reset_client_encoding
  476. },
  477. {
  478. "server_encoding", parse_server_encoding, show_server_encoding, reset_server_encoding
  479. },
  480. #endif
  481. {
  482. "ksqo", parse_ksqo, show_ksqo, reset_ksqo
  483. },
  484. {
  485. "XactIsoLevel", parse_XactIsoLevel, show_XactIsoLevel, reset_XactIsoLevel
  486. },
  487. {
  488. NULL, NULL, NULL, NULL
  489. }
  490. };
  491. /*-----------------------------------------------------------------------*/
  492. bool
  493. SetPGVariable(const char *name, const char *value)
  494. {
  495. struct VariableParsers *vp;
  496. for (vp = VariableParsers; vp->name; vp++)
  497. {
  498. if (!strcasecmp(vp->name, name))
  499. return (vp->parser) (value);
  500. }
  501. elog(NOTICE, "Unrecognized variable %s", name);
  502. return TRUE;
  503. }
  504. /*-----------------------------------------------------------------------*/
  505. bool
  506. GetPGVariable(const char *name)
  507. {
  508. struct VariableParsers *vp;
  509. for (vp = VariableParsers; vp->name; vp++)
  510. {
  511. if (!strcasecmp(vp->name, name))
  512. return (vp->show) ();
  513. }
  514. elog(NOTICE, "Unrecognized variable %s", name);
  515. return TRUE;
  516. }
  517. /*-----------------------------------------------------------------------*/
  518. bool
  519. ResetPGVariable(const char *name)
  520. {
  521. struct VariableParsers *vp;
  522. for (vp = VariableParsers; vp->name; vp++)
  523. {
  524. if (!strcasecmp(vp->name, name))
  525. return (vp->reset) ();
  526. }
  527. elog(NOTICE, "Unrecognized variable %s", name);
  528. return TRUE;
  529. }
  530. /*-----------------------------------------------------------------------
  531. KSQO code will one day be unnecessary when the optimizer makes use of
  532. indexes when multiple ORs are specified in the where clause.
  533. See optimizer/prep/prepkeyset.c for more on this.
  534. daveh@insightdist.com  6/16/98
  535. -----------------------------------------------------------------------*/
  536. static bool
  537. parse_ksqo(const char *value)
  538. {
  539. if (value == NULL)
  540. {
  541. reset_ksqo();
  542. return TRUE;
  543. }
  544. if (strcasecmp(value, "on") == 0)
  545. _use_keyset_query_optimizer = true;
  546. else if (strcasecmp(value, "off") == 0)
  547. _use_keyset_query_optimizer = false;
  548. else
  549. elog(ERROR, "Bad value for Key Set Query Optimizer (%s)", value);
  550. return TRUE;
  551. }
  552. static bool
  553. show_ksqo()
  554. {
  555. if (_use_keyset_query_optimizer)
  556. elog(NOTICE, "Key Set Query Optimizer is ON");
  557. else
  558. elog(NOTICE, "Key Set Query Optimizer is OFF");
  559. return TRUE;
  560. }
  561. static bool
  562. reset_ksqo()
  563. {
  564. _use_keyset_query_optimizer = false;
  565. return TRUE;
  566. }
  567. /* SET TRANSACTION */
  568. static bool
  569. parse_XactIsoLevel(const char *value)
  570. {
  571. if (value == NULL)
  572. {
  573. reset_XactIsoLevel();
  574. return TRUE;
  575. }
  576. if (SerializableSnapshot != NULL)
  577. {
  578. elog(ERROR, "SET TRANSACTION ISOLATION LEVEL must be called before any query");
  579. return TRUE;
  580. }
  581. if (strcasecmp(value, "SERIALIZABLE") == 0)
  582. XactIsoLevel = XACT_SERIALIZABLE;
  583. else if (strcasecmp(value, "COMMITTED") == 0)
  584. XactIsoLevel = XACT_READ_COMMITTED;
  585. else
  586. elog(ERROR, "Bad TRANSACTION ISOLATION LEVEL (%s)", value);
  587. return TRUE;
  588. }
  589. static bool
  590. show_XactIsoLevel()
  591. {
  592. if (XactIsoLevel == XACT_SERIALIZABLE)
  593. elog(NOTICE, "TRANSACTION ISOLATION LEVEL is SERIALIZABLE");
  594. else
  595. elog(NOTICE, "TRANSACTION ISOLATION LEVEL is READ COMMITTED");
  596. return TRUE;
  597. }
  598. static bool
  599. reset_XactIsoLevel()
  600. {
  601. if (SerializableSnapshot != NULL)
  602. {
  603. elog(ERROR, "SET TRANSACTION ISOLATION LEVEL must be called before any query");
  604. return TRUE;
  605. }
  606. XactIsoLevel = DefaultXactIsoLevel;
  607. return TRUE;
  608. }