前面已经说过,在 exec_simple_query中,完成sql文的执行。
具体地说,是要构造portal,然后运行 PortalStart , PortalRun...
下面就先看看 portal如何构造:
在 exec_simple_query中,有这么一段:
1 /* 2 * Create unnamed portal to run the query or queries in. If there 3 * already is one, silently drop it. 4 */ 5 portal = CreatePortal("", true, true); 6 /* Don't display the portal in pg_cursors */ 7 portal->visible = false;
具体的CreatePortal,是如何作的(portalmem.c):
1 /* 2 * CreatePortal 3 * Returns a new portal given a name. 4 * 5 * allowDup: if true, automatically drop any pre-existing portal of the 6 * same name (if false, an error is raised). 7 * 8 * dupSilent: if true, don't even emit a WARNING. 9 */ 10 Portal 11 CreatePortal(const char *name, bool allowDup, bool dupSilent) 12 { 13 Portal portal; 14 15 AssertArg(PointerIsValid(name)); 16 17 portal = GetPortalByName(name); 18 19 20 if (PortalIsValid(portal)) 21 { 22 if (!allowDup) 23 ereport(ERROR, 24 (errcode(ERRCODE_DUPLICATE_CURSOR), 25 errmsg("cursor \"%s\" already exists", name))); 26 if (!dupSilent) 27 ereport(WARNING, 28 (errcode(ERRCODE_DUPLICATE_CURSOR), 29 errmsg("closing existing cursor \"%s\"", 30 name))); 31 PortalDrop(portal, false); 32 } 33 34 /* make new portal structure */ 35 portal = (Portal) MemoryContextAllocZero(PortalMemory, sizeof *portal); 36 37 /* initialize portal heap context; typically it won't store much */ 38 portal->heap = AllocSetContextCreate(PortalMemory, 39 "PortalHeapMemory", 40 ALLOCSET_SMALL_MINSIZE, 41 ALLOCSET_SMALL_INITSIZE, 42 ALLOCSET_SMALL_MAXSIZE); 43 44 /* create a resource owner for the portal */ 45 portal->resowner = ResourceOwnerCreate(CurTransactionResourceOwner, 46 "Portal"); 47 48 /* initialize portal fields that don't start off zero */ 49 portal->status = PORTAL_NEW; 50 portal->cleanup = PortalCleanup; 51 portal->createSubid = GetCurrentSubTransactionId(); 52 portal->strategy = PORTAL_MULTI_QUERY; 53 portal->cursorOptions = CURSOR_OPT_NO_SCROLL; 54 portal->atStart = true; 55 portal->atEnd = true; /* disallow fetches until query is set */ 56 portal->visible = true; 57 portal->creation_time = GetCurrentStatementStartTimestamp(); 58 59 /* put portal in table (sets portal->name) */ 60 PortalHashTableInsert(portal, name); 61 62 return portal; 63 }
由于调用 CreatePortal 的时候,传递name是空值,所以 portal = GetPortalByName(name); 返回NULL。
通过 MemoryContextAllocZero 建立一个初始的portal,然后再赋予各种值,最后压入哈希表中。此时name依然为空。