358{
363 bool check_option;
365
366 /*
367 * Run parse analysis to convert the raw parse tree to a Query. Note this
368 * also acquires sufficient locks on the source table(s).
369 */
374
376
377 /*
378 * The grammar should ensure that the result is a single SELECT Query.
379 * However, it doesn't forbid SELECT INTO, so we have to check for that.
380 */
382 elog(
ERROR,
"unexpected parse analysis result");
386 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
387 errmsg(
"views must not contain SELECT INTO")));
389 elog(
ERROR,
"unexpected parse analysis result");
390
391 /*
392 * Check for unsupported cases. These tests are redundant with ones in
393 * DefineQueryRewrite(), but that function will complain about a bogus ON
394 * SELECT rule, and we'd rather the message complain about a view.
395 */
396 if (viewParse->hasModifyingCTE)
398 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
399 errmsg(
"views must not contain data-modifying statements in WITH")));
400
401 /*
402 * If the user specified the WITH CHECK OPTION, add it to the list of
403 * reloptions.
404 */
413
414 /*
415 * Check that the view is auto-updatable if WITH CHECK OPTION was
416 * specified.
417 */
418 check_option = false;
419
420 foreach(cell,
stmt->options)
421 {
423
424 if (strcmp(defel->
defname,
"check_option") == 0)
425 check_option = true;
426 }
427
428 /*
429 * If the check option is specified, look to see if the view is actually
430 * auto-updatable or not.
431 */
432 if (check_option)
433 {
434 const char *view_updatable_error =
436
437 if (view_updatable_error)
439 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
440 errmsg(
"WITH CHECK OPTION is supported only on automatically updatable views"),
441 errhint(
"%s",
_(view_updatable_error))));
442 }
443
444 /*
445 * If a list of column names was given, run through and insert these into
446 * the actual query tree. - thomas 2000年03月08日
447 */
449 {
452
454 {
456
457 /* junk columns don't get aliases */
458 if (te->resjunk)
459 continue;
461 alist_item =
lnext(
stmt->aliases, alist_item);
462 if (alist_item == NULL)
463 break; /* done assigning aliases */
464 }
465
466 if (alist_item != NULL)
468 (
errcode(ERRCODE_SYNTAX_ERROR),
469 errmsg(
"CREATE VIEW specifies more column "
470 "names than columns")));
471 }
472
473 /* Unlogged views are not sensible. */
474 if (
stmt->view->relpersistence == RELPERSISTENCE_UNLOGGED)
476 (
errcode(ERRCODE_SYNTAX_ERROR),
477 errmsg(
"views cannot be unlogged because they do not have storage")));
478
479 /*
480 * If the user didn't explicitly ask for a temporary view, check whether
481 * we need one implicitly. We allow TEMP to be inserted automatically as
482 * long as the CREATE command is consistent with that --- no explicit
483 * schema name.
484 */
485 view =
copyObject(
stmt->view);
/* don't corrupt original command */
488 {
491 (
errmsg(
"view \"%s\" will be a temporary view",
493 }
494
495 /*
496 * Create the view relation
497 *
498 * NOTE: if it already exists and replace is false, the xact will be
499 * aborted.
500 */
502 stmt->replace,
stmt->options, viewParse);
503
504 return address;
505}
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
List * lappend(List *list, void *datum)
DefElem * makeDefElem(char *name, Node *arg, int location)
char * pstrdup(const char *in)
#define IsA(nodeptr, _type_)
bool isQueryUsingTempRelation(Query *query)
Query * parse_analyze_fixedparams(RawStmt *parseTree, const char *sourceText, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
#define lfirst_node(type, lc)
static ListCell * list_head(const List *l)
static ListCell * lnext(const List *l, const ListCell *c)
const char * view_query_is_auto_updatable(Query *viewquery, bool check_cols)
String * makeString(char *str)
static ObjectAddress DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace, List *options, Query *viewParse)