mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Standard pgindent run for 8.1.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.125 2005/10/10 18:49:03 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.126 2005/10/15 02:49:27 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -59,9 +59,9 @@
|
||||
* The cache is valid if cached_member_role is not InvalidOid.
|
||||
*/
|
||||
static Oid cached_privs_role = InvalidOid;
|
||||
static List *cached_privs_roles = NIL;
|
||||
static List *cached_privs_roles = NIL;
|
||||
static Oid cached_member_role = InvalidOid;
|
||||
static List *cached_membership_roles = NIL;
|
||||
static List *cached_membership_roles = NIL;
|
||||
|
||||
|
||||
static const char *getid(const char *s, char *n);
|
||||
@@ -73,7 +73,7 @@ static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
|
||||
Oid ownerId);
|
||||
static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs,
|
||||
Oid ownerId, DropBehavior behavior);
|
||||
static int oidComparator(const void *arg1, const void *arg2);
|
||||
static int oidComparator(const void *arg1, const void *arg2);
|
||||
|
||||
static AclMode convert_priv_string(text *priv_type_text);
|
||||
|
||||
@@ -143,8 +143,8 @@ getid(const char *s, char *n)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NAME_TOO_LONG),
|
||||
errmsg("identifier too long"),
|
||||
errdetail("Identifier must be less than %d characters.",
|
||||
NAMEDATALEN)));
|
||||
errdetail("Identifier must be less than %d characters.",
|
||||
NAMEDATALEN)));
|
||||
|
||||
n[len++] = *s;
|
||||
}
|
||||
@@ -230,7 +230,7 @@ aclparse(const char *s, AclItem *aip)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("unrecognized key word: \"%s\"", name),
|
||||
errhint("ACL key word must be \"group\" or \"user\".")));
|
||||
errhint("ACL key word must be \"group\" or \"user\".")));
|
||||
s = getid(s, name); /* move s to the name beyond the keyword */
|
||||
if (name[0] == '\0')
|
||||
ereport(ERROR,
|
||||
@@ -289,8 +289,8 @@ aclparse(const char *s, AclItem *aip)
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid mode character: must be one of \"%s\"",
|
||||
ACL_ALL_RIGHTS_STR)));
|
||||
errmsg("invalid mode character: must be one of \"%s\"",
|
||||
ACL_ALL_RIGHTS_STR)));
|
||||
}
|
||||
|
||||
privs |= read;
|
||||
@@ -302,8 +302,8 @@ aclparse(const char *s, AclItem *aip)
|
||||
aip->ai_grantee = get_roleid_checked(name);
|
||||
|
||||
/*
|
||||
* XXX Allow a degree of backward compatibility by defaulting the
|
||||
* grantor to the superuser.
|
||||
* XXX Allow a degree of backward compatibility by defaulting the grantor
|
||||
* to the superuser.
|
||||
*/
|
||||
if (*s == '/')
|
||||
{
|
||||
@@ -380,7 +380,7 @@ aclitemin(PG_FUNCTION_ARGS)
|
||||
if (*s)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("extra garbage at the end of the ACL specification")));
|
||||
errmsg("extra garbage at the end of the ACL specification")));
|
||||
|
||||
PG_RETURN_ACLITEM_P(aip);
|
||||
}
|
||||
@@ -565,14 +565,14 @@ acldefault(GrantObjectType objtype, Oid ownerId)
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the owner's entry shows all ordinary privileges but no
|
||||
* grant options. This is because his grant options come "from the
|
||||
* system" and not from his own efforts. (The SQL spec says that the
|
||||
* owner's rights come from a "_SYSTEM" authid.) However, we do
|
||||
* consider that the owner's ordinary privileges are self-granted;
|
||||
* this lets him revoke them. We implement the owner's grant options
|
||||
* without any explicit "_SYSTEM"-like ACL entry, by internally
|
||||
* special-casing the owner whereever we are testing grant options.
|
||||
* Note that the owner's entry shows all ordinary privileges but no grant
|
||||
* options. This is because his grant options come "from the system" and
|
||||
* not from his own efforts. (The SQL spec says that the owner's rights
|
||||
* come from a "_SYSTEM" authid.) However, we do consider that the
|
||||
* owner's ordinary privileges are self-granted; this lets him revoke
|
||||
* them. We implement the owner's grant options without any explicit
|
||||
* "_SYSTEM"-like ACL entry, by internally special-casing the owner
|
||||
* whereever we are testing grant options.
|
||||
*/
|
||||
aip->ai_grantee = ownerId;
|
||||
aip->ai_grantor = ownerId;
|
||||
@@ -631,10 +631,10 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
|
||||
old_aip = ACL_DAT(old_acl);
|
||||
|
||||
/*
|
||||
* Search the ACL for an existing entry for this grantee and grantor.
|
||||
* If one exists, just modify the entry in-place (well, in the same
|
||||
* position, since we actually return a copy); otherwise, insert the
|
||||
* new entry at the end.
|
||||
* Search the ACL for an existing entry for this grantee and grantor. If
|
||||
* one exists, just modify the entry in-place (well, in the same position,
|
||||
* since we actually return a copy); otherwise, insert the new entry at
|
||||
* the end.
|
||||
*/
|
||||
|
||||
for (dst = 0; dst < num; ++dst)
|
||||
@@ -676,7 +676,7 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
|
||||
break;
|
||||
case ACL_MODECHG_DEL:
|
||||
ACLITEM_SET_RIGHTS(new_aip[dst],
|
||||
old_rights & ~ACLITEM_GET_RIGHTS(*mod_aip));
|
||||
old_rights & ~ACLITEM_GET_RIGHTS(*mod_aip));
|
||||
break;
|
||||
case ACL_MODECHG_EQL:
|
||||
ACLITEM_SET_RIGHTS(new_aip[dst],
|
||||
@@ -700,8 +700,8 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove abandoned privileges (cascading revoke). Currently we can
|
||||
* only handle this when the grantee is not PUBLIC.
|
||||
* Remove abandoned privileges (cascading revoke). Currently we can only
|
||||
* handle this when the grantee is not PUBLIC.
|
||||
*/
|
||||
if ((old_goptions & ~new_goptions) != 0)
|
||||
{
|
||||
@@ -742,8 +742,8 @@ aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
|
||||
|
||||
/*
|
||||
* Make a copy of the given ACL, substituting new owner ID for old
|
||||
* wherever it appears as either grantor or grantee. Also note if the
|
||||
* new owner ID is already present.
|
||||
* wherever it appears as either grantor or grantee. Also note if the new
|
||||
* owner ID is already present.
|
||||
*/
|
||||
num = ACL_NUM(old_acl);
|
||||
old_aip = ACL_DAT(old_acl);
|
||||
@@ -763,21 +763,20 @@ aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
|
||||
}
|
||||
|
||||
/*
|
||||
* If the old ACL contained any references to the new owner, then we
|
||||
* may now have generated an ACL containing duplicate entries. Find
|
||||
* them and merge them so that there are not duplicates. (This is
|
||||
* relatively expensive since we use a stupid O(N^2) algorithm, but
|
||||
* it's unlikely to be the normal case.)
|
||||
* If the old ACL contained any references to the new owner, then we may
|
||||
* now have generated an ACL containing duplicate entries. Find them and
|
||||
* merge them so that there are not duplicates. (This is relatively
|
||||
* expensive since we use a stupid O(N^2) algorithm, but it's unlikely to
|
||||
* be the normal case.)
|
||||
*
|
||||
* To simplify deletion of duplicate entries, we temporarily leave them
|
||||
* in the array but set their privilege masks to zero; when we reach
|
||||
* such an entry it's just skipped. (Thus, a side effect of this code
|
||||
* will be to remove privilege-free entries, should there be any in
|
||||
* the input.) dst is the next output slot, targ is the currently
|
||||
* considered input slot (always >= dst), and src scans entries to the
|
||||
* right of targ looking for duplicates. Once an entry has been
|
||||
* emitted to dst it is known duplicate-free and need not be
|
||||
* considered anymore.
|
||||
* To simplify deletion of duplicate entries, we temporarily leave them in
|
||||
* the array but set their privilege masks to zero; when we reach such an
|
||||
* entry it's just skipped. (Thus, a side effect of this code will be to
|
||||
* remove privilege-free entries, should there be any in the input.) dst
|
||||
* is the next output slot, targ is the currently considered input slot
|
||||
* (always >= dst), and src scans entries to the right of targ looking for
|
||||
* duplicates. Once an entry has been emitted to dst it is known
|
||||
* duplicate-free and need not be considered anymore.
|
||||
*/
|
||||
if (newpresent)
|
||||
{
|
||||
@@ -877,14 +876,14 @@ cc_restart:
|
||||
own_privs = aclmask(acl,
|
||||
mod_aip->ai_grantor,
|
||||
ownerId,
|
||||
ACL_GRANT_OPTION_FOR(ACLITEM_GET_GOPTIONS(*mod_aip)),
|
||||
ACL_GRANT_OPTION_FOR(ACLITEM_GET_GOPTIONS(*mod_aip)),
|
||||
ACLMASK_ALL);
|
||||
own_privs = ACL_OPTION_TO_PRIVS(own_privs);
|
||||
|
||||
if ((ACLITEM_GET_GOPTIONS(*mod_aip) & ~own_privs) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
||||
errmsg("grant options cannot be granted back to your own grantor")));
|
||||
errmsg("grant options cannot be granted back to your own grantor")));
|
||||
|
||||
pfree(acl);
|
||||
}
|
||||
@@ -1041,11 +1040,11 @@ aclmask(const Acl *acl, Oid roleid, Oid ownerId,
|
||||
}
|
||||
|
||||
/*
|
||||
* Check privileges granted indirectly via role memberships.
|
||||
* We do this in a separate pass to minimize expensive indirect
|
||||
* membership tests. In particular, it's worth testing whether
|
||||
* a given ACL entry grants any privileges still of interest before
|
||||
* we perform the has_privs_of_role test.
|
||||
* Check privileges granted indirectly via role memberships. We do this in
|
||||
* a separate pass to minimize expensive indirect membership tests. In
|
||||
* particular, it's worth testing whether a given ACL entry grants any
|
||||
* privileges still of interest before we perform the has_privs_of_role
|
||||
* test.
|
||||
*/
|
||||
remaining = mask & ~result;
|
||||
for (i = 0; i < num; i++)
|
||||
@@ -1140,11 +1139,11 @@ aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId,
|
||||
int
|
||||
aclmembers(const Acl *acl, Oid **roleids)
|
||||
{
|
||||
Oid *list;
|
||||
Oid *list;
|
||||
const AclItem *acldat;
|
||||
int i,
|
||||
j,
|
||||
k;
|
||||
int i,
|
||||
j,
|
||||
k;
|
||||
|
||||
if (acl == NULL || ACL_NUM(acl) == 0)
|
||||
{
|
||||
@@ -1183,8 +1182,8 @@ aclmembers(const Acl *acl, Oid **roleids)
|
||||
}
|
||||
|
||||
/*
|
||||
* We could repalloc the array down to minimum size, but it's hardly
|
||||
* worth it since it's only transient memory.
|
||||
* We could repalloc the array down to minimum size, but it's hardly worth
|
||||
* it since it's only transient memory.
|
||||
*/
|
||||
*roleids = list;
|
||||
|
||||
@@ -1198,8 +1197,8 @@ aclmembers(const Acl *acl, Oid **roleids)
|
||||
static int
|
||||
oidComparator(const void *arg1, const void *arg2)
|
||||
{
|
||||
Oid oid1 = * (const Oid *) arg1;
|
||||
Oid oid2 = * (const Oid *) arg2;
|
||||
Oid oid1 = *(const Oid *) arg1;
|
||||
Oid oid2 = *(const Oid *) arg2;
|
||||
|
||||
if (oid1 > oid2)
|
||||
return 1;
|
||||
@@ -1257,7 +1256,7 @@ Datum
|
||||
makeaclitem(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid grantee = PG_GETARG_OID(0);
|
||||
Oid grantor = PG_GETARG_OID(1);
|
||||
Oid grantor = PG_GETARG_OID(1);
|
||||
text *privtext = PG_GETARG_TEXT_P(2);
|
||||
bool goption = PG_GETARG_BOOL(3);
|
||||
AclItem *result;
|
||||
@@ -1282,7 +1281,7 @@ convert_priv_string(text *priv_type_text)
|
||||
char *priv_type;
|
||||
|
||||
priv_type = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(priv_type_text)));
|
||||
PointerGetDatum(priv_type_text)));
|
||||
|
||||
if (pg_strcasecmp(priv_type, "SELECT") == 0)
|
||||
return ACL_SELECT;
|
||||
@@ -1410,7 +1409,7 @@ has_table_privilege_id(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid tableoid = PG_GETARG_OID(0);
|
||||
text *priv_type_text = PG_GETARG_TEXT_P(1);
|
||||
Oid roleid;
|
||||
Oid roleid;
|
||||
AclMode mode;
|
||||
AclResult aclresult;
|
||||
|
||||
@@ -1493,7 +1492,7 @@ convert_table_priv_string(text *priv_type_text)
|
||||
char *priv_type;
|
||||
|
||||
priv_type = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(priv_type_text)));
|
||||
PointerGetDatum(priv_type_text)));
|
||||
|
||||
/*
|
||||
* Return mode from priv_type string
|
||||
@@ -1704,7 +1703,7 @@ convert_database_name(text *databasename)
|
||||
Oid oid;
|
||||
|
||||
dbname = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(databasename)));
|
||||
PointerGetDatum(databasename)));
|
||||
|
||||
oid = get_database_oid(dbname);
|
||||
if (!OidIsValid(oid))
|
||||
@@ -1725,7 +1724,7 @@ convert_database_priv_string(text *priv_type_text)
|
||||
char *priv_type;
|
||||
|
||||
priv_type = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(priv_type_text)));
|
||||
PointerGetDatum(priv_type_text)));
|
||||
|
||||
/*
|
||||
* Return mode from priv_type string
|
||||
@@ -1916,10 +1915,10 @@ convert_function_name(text *functionname)
|
||||
Oid oid;
|
||||
|
||||
funcname = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(functionname)));
|
||||
PointerGetDatum(functionname)));
|
||||
|
||||
oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
|
||||
CStringGetDatum(funcname)));
|
||||
CStringGetDatum(funcname)));
|
||||
|
||||
if (!OidIsValid(oid))
|
||||
ereport(ERROR,
|
||||
@@ -1939,7 +1938,7 @@ convert_function_priv_string(text *priv_type_text)
|
||||
char *priv_type;
|
||||
|
||||
priv_type = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(priv_type_text)));
|
||||
PointerGetDatum(priv_type_text)));
|
||||
|
||||
/*
|
||||
* Return mode from priv_type string
|
||||
@@ -2120,7 +2119,7 @@ convert_language_name(text *languagename)
|
||||
Oid oid;
|
||||
|
||||
langname = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(languagename)));
|
||||
PointerGetDatum(languagename)));
|
||||
|
||||
oid = GetSysCacheOid(LANGNAME,
|
||||
CStringGetDatum(langname),
|
||||
@@ -2143,7 +2142,7 @@ convert_language_priv_string(text *priv_type_text)
|
||||
char *priv_type;
|
||||
|
||||
priv_type = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(priv_type_text)));
|
||||
PointerGetDatum(priv_type_text)));
|
||||
|
||||
/*
|
||||
* Return mode from priv_type string
|
||||
@@ -2324,7 +2323,7 @@ convert_schema_name(text *schemaname)
|
||||
Oid oid;
|
||||
|
||||
nspname = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(schemaname)));
|
||||
PointerGetDatum(schemaname)));
|
||||
|
||||
oid = GetSysCacheOid(NAMESPACENAME,
|
||||
CStringGetDatum(nspname),
|
||||
@@ -2347,7 +2346,7 @@ convert_schema_priv_string(text *priv_type_text)
|
||||
char *priv_type;
|
||||
|
||||
priv_type = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(priv_type_text)));
|
||||
PointerGetDatum(priv_type_text)));
|
||||
|
||||
/*
|
||||
* Return mode from priv_type string
|
||||
@@ -2462,7 +2461,7 @@ has_tablespace_privilege_id(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid tablespaceoid = PG_GETARG_OID(0);
|
||||
text *priv_type_text = PG_GETARG_TEXT_P(1);
|
||||
Oid roleid;
|
||||
Oid roleid;
|
||||
AclMode mode;
|
||||
AclResult aclresult;
|
||||
|
||||
@@ -2532,7 +2531,7 @@ convert_tablespace_name(text *tablespacename)
|
||||
Oid oid;
|
||||
|
||||
spcname = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(tablespacename)));
|
||||
PointerGetDatum(tablespacename)));
|
||||
oid = get_tablespace_oid(spcname);
|
||||
|
||||
if (!OidIsValid(oid))
|
||||
@@ -2553,7 +2552,7 @@ convert_tablespace_priv_string(text *priv_type_text)
|
||||
char *priv_type;
|
||||
|
||||
priv_type = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(priv_type_text)));
|
||||
PointerGetDatum(priv_type_text)));
|
||||
|
||||
/*
|
||||
* Return mode from priv_type string
|
||||
@@ -2663,7 +2662,7 @@ pg_has_role_id(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid roleoid = PG_GETARG_OID(0);
|
||||
text *priv_type_text = PG_GETARG_TEXT_P(1);
|
||||
Oid roleid;
|
||||
Oid roleid;
|
||||
AclMode mode;
|
||||
AclResult aclresult;
|
||||
|
||||
@@ -2739,7 +2738,7 @@ convert_role_priv_string(text *priv_type_text)
|
||||
char *priv_type;
|
||||
|
||||
priv_type = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(priv_type_text)));
|
||||
PointerGetDatum(priv_type_text)));
|
||||
|
||||
/*
|
||||
* Return mode from priv_type string
|
||||
@@ -2795,8 +2794,8 @@ initialize_acl(void)
|
||||
if (!IsBootstrapProcessingMode())
|
||||
{
|
||||
/*
|
||||
* In normal mode, set a callback on any syscache
|
||||
* invalidation of pg_auth_members rows
|
||||
* In normal mode, set a callback on any syscache invalidation of
|
||||
* pg_auth_members rows
|
||||
*/
|
||||
CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
|
||||
RoleMembershipCacheCallback,
|
||||
@@ -2806,7 +2805,7 @@ initialize_acl(void)
|
||||
|
||||
/*
|
||||
* RoleMembershipCacheCallback
|
||||
* Syscache inval callback function
|
||||
* Syscache inval callback function
|
||||
*/
|
||||
static void
|
||||
RoleMembershipCacheCallback(Datum arg, Oid relid)
|
||||
@@ -2853,19 +2852,19 @@ has_rolinherit(Oid roleid)
|
||||
static List *
|
||||
roles_has_privs_of(Oid roleid)
|
||||
{
|
||||
List *roles_list;
|
||||
ListCell *l;
|
||||
List *new_cached_privs_roles;
|
||||
MemoryContext oldctx;
|
||||
List *roles_list;
|
||||
ListCell *l;
|
||||
List *new_cached_privs_roles;
|
||||
MemoryContext oldctx;
|
||||
|
||||
/* If cache is already valid, just return the list */
|
||||
if (OidIsValid(cached_privs_role) && cached_privs_role == roleid)
|
||||
return cached_privs_roles;
|
||||
|
||||
/*
|
||||
* Find all the roles that roleid is a member of,
|
||||
* including multi-level recursion. The role itself will always
|
||||
* be the first element of the resulting list.
|
||||
/*
|
||||
* Find all the roles that roleid is a member of, including multi-level
|
||||
* recursion. The role itself will always be the first element of the
|
||||
* resulting list.
|
||||
*
|
||||
* Each element of the list is scanned to see if it adds any indirect
|
||||
* memberships. We can use a single list as both the record of
|
||||
@@ -2877,9 +2876,9 @@ roles_has_privs_of(Oid roleid)
|
||||
|
||||
foreach(l, roles_list)
|
||||
{
|
||||
Oid memberid = lfirst_oid(l);
|
||||
CatCList *memlist;
|
||||
int i;
|
||||
Oid memberid = lfirst_oid(l);
|
||||
CatCList *memlist;
|
||||
int i;
|
||||
|
||||
/* Ignore non-inheriting roles */
|
||||
if (!has_rolinherit(memberid))
|
||||
@@ -2892,12 +2891,12 @@ roles_has_privs_of(Oid roleid)
|
||||
for (i = 0; i < memlist->n_members; i++)
|
||||
{
|
||||
HeapTuple tup = &memlist->members[i]->tuple;
|
||||
Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
|
||||
Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
|
||||
|
||||
/*
|
||||
* Even though there shouldn't be any loops in the membership
|
||||
* graph, we must test for having already seen this role.
|
||||
* It is legal for instance to have both A->B and A->C->B.
|
||||
* graph, we must test for having already seen this role. It is
|
||||
* legal for instance to have both A->B and A->C->B.
|
||||
*/
|
||||
roles_list = list_append_unique_oid(roles_list, otherid);
|
||||
}
|
||||
@@ -2915,7 +2914,7 @@ roles_has_privs_of(Oid roleid)
|
||||
/*
|
||||
* Now safe to assign to state variable
|
||||
*/
|
||||
cached_privs_role = InvalidOid; /* just paranoia */
|
||||
cached_privs_role = InvalidOid; /* just paranoia */
|
||||
list_free(cached_privs_roles);
|
||||
cached_privs_roles = new_cached_privs_roles;
|
||||
cached_privs_role = roleid;
|
||||
@@ -2937,19 +2936,19 @@ roles_has_privs_of(Oid roleid)
|
||||
static List *
|
||||
roles_is_member_of(Oid roleid)
|
||||
{
|
||||
List *roles_list;
|
||||
ListCell *l;
|
||||
List *new_cached_membership_roles;
|
||||
MemoryContext oldctx;
|
||||
List *roles_list;
|
||||
ListCell *l;
|
||||
List *new_cached_membership_roles;
|
||||
MemoryContext oldctx;
|
||||
|
||||
/* If cache is already valid, just return the list */
|
||||
if (OidIsValid(cached_member_role) && cached_member_role == roleid)
|
||||
return cached_membership_roles;
|
||||
|
||||
/*
|
||||
* Find all the roles that roleid is a member of,
|
||||
* including multi-level recursion. The role itself will always
|
||||
* be the first element of the resulting list.
|
||||
/*
|
||||
* Find all the roles that roleid is a member of, including multi-level
|
||||
* recursion. The role itself will always be the first element of the
|
||||
* resulting list.
|
||||
*
|
||||
* Each element of the list is scanned to see if it adds any indirect
|
||||
* memberships. We can use a single list as both the record of
|
||||
@@ -2961,9 +2960,9 @@ roles_is_member_of(Oid roleid)
|
||||
|
||||
foreach(l, roles_list)
|
||||
{
|
||||
Oid memberid = lfirst_oid(l);
|
||||
CatCList *memlist;
|
||||
int i;
|
||||
Oid memberid = lfirst_oid(l);
|
||||
CatCList *memlist;
|
||||
int i;
|
||||
|
||||
/* Find roles that memberid is directly a member of */
|
||||
memlist = SearchSysCacheList(AUTHMEMMEMROLE, 1,
|
||||
@@ -2972,12 +2971,12 @@ roles_is_member_of(Oid roleid)
|
||||
for (i = 0; i < memlist->n_members; i++)
|
||||
{
|
||||
HeapTuple tup = &memlist->members[i]->tuple;
|
||||
Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
|
||||
Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
|
||||
|
||||
/*
|
||||
* Even though there shouldn't be any loops in the membership
|
||||
* graph, we must test for having already seen this role.
|
||||
* It is legal for instance to have both A->B and A->C->B.
|
||||
* graph, we must test for having already seen this role. It is
|
||||
* legal for instance to have both A->B and A->C->B.
|
||||
*/
|
||||
roles_list = list_append_unique_oid(roles_list, otherid);
|
||||
}
|
||||
@@ -3023,7 +3022,7 @@ has_privs_of_role(Oid member, Oid role)
|
||||
if (superuser_arg(member))
|
||||
return true;
|
||||
|
||||
/*
|
||||
/*
|
||||
* Find all the roles that member has the privileges of, including
|
||||
* multi-level recursion, then see if target role is any one of them.
|
||||
*/
|
||||
@@ -3047,7 +3046,7 @@ is_member_of_role(Oid member, Oid role)
|
||||
if (superuser_arg(member))
|
||||
return true;
|
||||
|
||||
/*
|
||||
/*
|
||||
* Find all the roles that member is a member of, including multi-level
|
||||
* recursion, then see if target role is any one of them.
|
||||
*/
|
||||
@@ -3080,8 +3079,8 @@ bool
|
||||
is_admin_of_role(Oid member, Oid role)
|
||||
{
|
||||
bool result = false;
|
||||
List *roles_list;
|
||||
ListCell *l;
|
||||
List *roles_list;
|
||||
ListCell *l;
|
||||
|
||||
/* Fast path for simple case */
|
||||
if (member == role)
|
||||
@@ -3091,18 +3090,18 @@ is_admin_of_role(Oid member, Oid role)
|
||||
if (superuser_arg(member))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Find all the roles that member is a member of,
|
||||
* including multi-level recursion. We build a list in the same way
|
||||
* that is_member_of_role does to track visited and unvisited roles.
|
||||
/*
|
||||
* Find all the roles that member is a member of, including multi-level
|
||||
* recursion. We build a list in the same way that is_member_of_role does
|
||||
* to track visited and unvisited roles.
|
||||
*/
|
||||
roles_list = list_make1_oid(member);
|
||||
|
||||
foreach(l, roles_list)
|
||||
{
|
||||
Oid memberid = lfirst_oid(l);
|
||||
CatCList *memlist;
|
||||
int i;
|
||||
Oid memberid = lfirst_oid(l);
|
||||
CatCList *memlist;
|
||||
int i;
|
||||
|
||||
/* Find roles that memberid is directly a member of */
|
||||
memlist = SearchSysCacheList(AUTHMEMMEMROLE, 1,
|
||||
@@ -3111,7 +3110,7 @@ is_admin_of_role(Oid member, Oid role)
|
||||
for (i = 0; i < memlist->n_members; i++)
|
||||
{
|
||||
HeapTuple tup = &memlist->members[i]->tuple;
|
||||
Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
|
||||
Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
|
||||
|
||||
if (otherid == role &&
|
||||
((Form_pg_auth_members) GETSTRUCT(tup))->admin_option)
|
||||
@@ -3138,7 +3137,7 @@ is_admin_of_role(Oid member, Oid role)
|
||||
static int
|
||||
count_one_bits(AclMode mask)
|
||||
{
|
||||
int nbits = 0;
|
||||
int nbits = 0;
|
||||
|
||||
/* this code relies on AclMode being an unsigned type */
|
||||
while (mask)
|
||||
@@ -3157,14 +3156,14 @@ count_one_bits(AclMode mask)
|
||||
* The grantor must always be either the object owner or some role that has
|
||||
* been explicitly granted grant options. This ensures that all granted
|
||||
* privileges appear to flow from the object owner, and there are never
|
||||
* multiple "original sources" of a privilege. Therefore, if the would-be
|
||||
* multiple "original sources" of a privilege. Therefore, if the would-be
|
||||
* grantor is a member of a role that has the needed grant options, we have
|
||||
* to do the grant as that role instead.
|
||||
*
|
||||
* It is possible that the would-be grantor is a member of several roles
|
||||
* that have different subsets of the desired grant options, but no one
|
||||
* role has 'em all. In this case we pick a role with the largest number
|
||||
* of desired options. Ties are broken in favor of closer ancestors.
|
||||
* of desired options. Ties are broken in favor of closer ancestors.
|
||||
*
|
||||
* roleId: the role attempting to do the GRANT/REVOKE
|
||||
* privileges: the privileges to be granted/revoked
|
||||
@@ -3181,15 +3180,15 @@ select_best_grantor(Oid roleId, AclMode privileges,
|
||||
Oid *grantorId, AclMode *grantOptions)
|
||||
{
|
||||
AclMode needed_goptions = ACL_GRANT_OPTION_FOR(privileges);
|
||||
List *roles_list;
|
||||
List *roles_list;
|
||||
int nrights;
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* The object owner is always treated as having all grant options,
|
||||
* so if roleId is the owner it's easy. Also, if roleId is a superuser
|
||||
* it's easy: superusers are implicitly members of every role, so they
|
||||
* act as the object owner.
|
||||
* The object owner is always treated as having all grant options, so if
|
||||
* roleId is the owner it's easy. Also, if roleId is a superuser it's
|
||||
* easy: superusers are implicitly members of every role, so they act as
|
||||
* the object owner.
|
||||
*/
|
||||
if (roleId == ownerId || superuser_arg(roleId))
|
||||
{
|
||||
@@ -3200,8 +3199,8 @@ select_best_grantor(Oid roleId, AclMode privileges,
|
||||
|
||||
/*
|
||||
* Otherwise we have to do a careful search to see if roleId has the
|
||||
* privileges of any suitable role. Note: we can hang onto the result
|
||||
* of roles_has_privs_of() throughout this loop, because aclmask_direct()
|
||||
* privileges of any suitable role. Note: we can hang onto the result of
|
||||
* roles_has_privs_of() throughout this loop, because aclmask_direct()
|
||||
* doesn't query any role memberships.
|
||||
*/
|
||||
roles_list = roles_has_privs_of(roleId);
|
||||
@@ -3213,8 +3212,8 @@ select_best_grantor(Oid roleId, AclMode privileges,
|
||||
|
||||
foreach(l, roles_list)
|
||||
{
|
||||
Oid otherrole = lfirst_oid(l);
|
||||
AclMode otherprivs;
|
||||
Oid otherrole = lfirst_oid(l);
|
||||
AclMode otherprivs;
|
||||
|
||||
otherprivs = aclmask_direct(acl, otherrole, ownerId,
|
||||
needed_goptions, ACLMASK_ALL);
|
||||
@@ -3225,13 +3224,14 @@ select_best_grantor(Oid roleId, AclMode privileges,
|
||||
*grantOptions = otherprivs;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it has just some of the needed privileges, remember best
|
||||
* candidate.
|
||||
*/
|
||||
if (otherprivs != ACL_NO_RIGHTS)
|
||||
{
|
||||
int nnewrights = count_one_bits(otherprivs);
|
||||
int nnewrights = count_one_bits(otherprivs);
|
||||
|
||||
if (nnewrights > nrights)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.15 2005/01/01 20:44:17 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.16 2005/10/15 02:49:27 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -96,17 +96,17 @@ array_push(PG_FUNCTION_ARGS)
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||
errmsg("argument must be empty or one-dimensional array")));
|
||||
errmsg("argument must be empty or one-dimensional array")));
|
||||
|
||||
/*
|
||||
* We arrange to look up info about element type only once per series
|
||||
* of calls, assuming the element type doesn't change underneath us.
|
||||
* We arrange to look up info about element type only once per series of
|
||||
* calls, assuming the element type doesn't change underneath us.
|
||||
*/
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
if (my_extra == NULL)
|
||||
{
|
||||
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
||||
sizeof(ArrayMetaState));
|
||||
sizeof(ArrayMetaState));
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
my_extra->element_type = InvalidOid;
|
||||
}
|
||||
@@ -194,8 +194,8 @@ array_cat(PG_FUNCTION_ARGS)
|
||||
ndims2 = ARR_NDIM(v2);
|
||||
|
||||
/*
|
||||
* short circuit - if one input array is empty, and the other is not,
|
||||
* we return the non-empty one as the result
|
||||
* short circuit - if one input array is empty, and the other is not, we
|
||||
* return the non-empty one as the result
|
||||
*
|
||||
* if both are empty, return the first one
|
||||
*/
|
||||
@@ -245,8 +245,8 @@ array_cat(PG_FUNCTION_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||
errmsg("cannot concatenate incompatible arrays"),
|
||||
errdetail("Arrays with differing element dimensions are "
|
||||
"not compatible for concatenation.")));
|
||||
errdetail("Arrays with differing element dimensions are "
|
||||
"not compatible for concatenation.")));
|
||||
|
||||
dims[i] = dims1[i];
|
||||
lbs[i] = lbs1[i];
|
||||
@@ -255,9 +255,8 @@ array_cat(PG_FUNCTION_ARGS)
|
||||
else if (ndims1 == ndims2 - 1)
|
||||
{
|
||||
/*
|
||||
* resulting array has the second argument as the outer array,
|
||||
* with the first argument appended to the front of the outer
|
||||
* dimension
|
||||
* resulting array has the second argument as the outer array, with
|
||||
* the first argument appended to the front of the outer dimension
|
||||
*/
|
||||
ndims = ndims2;
|
||||
dims = (int *) palloc(ndims * sizeof(int));
|
||||
@@ -278,8 +277,8 @@ array_cat(PG_FUNCTION_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||
errmsg("cannot concatenate incompatible arrays"),
|
||||
errdetail("Arrays with differing dimensions are not "
|
||||
"compatible for concatenation.")));
|
||||
errdetail("Arrays with differing dimensions are not "
|
||||
"compatible for concatenation.")));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -287,8 +286,8 @@ array_cat(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* (ndims1 == ndims2 + 1)
|
||||
*
|
||||
* resulting array has the first argument as the outer array, with
|
||||
* the second argument appended to the end of the outer dimension
|
||||
* resulting array has the first argument as the outer array, with the
|
||||
* second argument appended to the end of the outer dimension
|
||||
*/
|
||||
ndims = ndims1;
|
||||
dims = (int *) palloc(ndims * sizeof(int));
|
||||
@@ -306,8 +305,8 @@ array_cat(PG_FUNCTION_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||
errmsg("cannot concatenate incompatible arrays"),
|
||||
errdetail("Arrays with differing dimensions are not "
|
||||
"compatible for concatenation.")));
|
||||
errdetail("Arrays with differing dimensions are not "
|
||||
"compatible for concatenation.")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +350,7 @@ create_singleton_array(FunctionCallInfo fcinfo,
|
||||
if (element_type == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid array element type OID: %u", element_type)));
|
||||
errmsg("invalid array element type OID: %u", element_type)));
|
||||
if (ndims < 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
@@ -371,14 +370,14 @@ create_singleton_array(FunctionCallInfo fcinfo,
|
||||
}
|
||||
|
||||
/*
|
||||
* We arrange to look up info about element type only once per series
|
||||
* of calls, assuming the element type doesn't change underneath us.
|
||||
* We arrange to look up info about element type only once per series of
|
||||
* calls, assuming the element type doesn't change underneath us.
|
||||
*/
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
if (my_extra == NULL)
|
||||
{
|
||||
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
||||
sizeof(ArrayMetaState));
|
||||
sizeof(ArrayMetaState));
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
my_extra->element_type = InvalidOid;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.122 2005/08/15 19:40:20 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.123 2005/10/15 02:49:27 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -130,8 +130,7 @@ array_in(PG_FUNCTION_ARGS)
|
||||
char *string = PG_GETARG_CSTRING(0); /* external form */
|
||||
Oid element_type = PG_GETARG_OID(1); /* type of an array
|
||||
* element */
|
||||
int32 typmod = PG_GETARG_INT32(2); /* typmod for array
|
||||
* elements */
|
||||
int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */
|
||||
int typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
@@ -151,14 +150,14 @@ array_in(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* We arrange to look up info about element type, including its input
|
||||
* conversion proc, only once per series of calls, assuming the
|
||||
* element type doesn't change underneath us.
|
||||
* conversion proc, only once per series of calls, assuming the element
|
||||
* type doesn't change underneath us.
|
||||
*/
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
if (my_extra == NULL)
|
||||
{
|
||||
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
||||
sizeof(ArrayMetaState));
|
||||
sizeof(ArrayMetaState));
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
my_extra->element_type = ~element_type;
|
||||
}
|
||||
@@ -166,8 +165,7 @@ array_in(PG_FUNCTION_ARGS)
|
||||
if (my_extra->element_type != element_type)
|
||||
{
|
||||
/*
|
||||
* Get info about element type, including its input conversion
|
||||
* proc
|
||||
* Get info about element type, including its input conversion proc
|
||||
*/
|
||||
get_type_io_data(element_type, IOFunc_input,
|
||||
&my_extra->typlen, &my_extra->typbyval,
|
||||
@@ -191,8 +189,8 @@ array_in(PG_FUNCTION_ARGS)
|
||||
* Otherwise, we require the input to be in curly-brace style, and we
|
||||
* prescan the input to determine dimensions.
|
||||
*
|
||||
* Dimension info takes the form of one or more [n] or [m:n] items. The
|
||||
* outer loop iterates once per dimension item.
|
||||
* Dimension info takes the form of one or more [n] or [m:n] items. The outer
|
||||
* loop iterates once per dimension item.
|
||||
*/
|
||||
p = string_save;
|
||||
ndim = 0;
|
||||
@@ -250,7 +248,7 @@ array_in(PG_FUNCTION_ARGS)
|
||||
if (ub < lBound[ndim])
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||
errmsg("upper bound cannot be less than lower bound")));
|
||||
errmsg("upper bound cannot be less than lower bound")));
|
||||
|
||||
dim[ndim] = ub - lBound[ndim] + 1;
|
||||
ndim++;
|
||||
@@ -282,8 +280,8 @@ array_in(PG_FUNCTION_ARGS)
|
||||
p++;
|
||||
|
||||
/*
|
||||
* intuit dimensions from brace structure -- it better match what
|
||||
* we were given
|
||||
* intuit dimensions from brace structure -- it better match what we
|
||||
* were given
|
||||
*/
|
||||
if (*p != '{')
|
||||
ereport(ERROR,
|
||||
@@ -293,13 +291,13 @@ array_in(PG_FUNCTION_ARGS)
|
||||
if (ndim_braces != ndim)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("array dimensions incompatible with array literal")));
|
||||
errmsg("array dimensions incompatible with array literal")));
|
||||
for (i = 0; i < ndim; ++i)
|
||||
{
|
||||
if (dim[i] != dim_braces[i])
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("array dimensions incompatible with array literal")));
|
||||
errmsg("array dimensions incompatible with array literal")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,22 +404,22 @@ ArrayCount(char *str, int *dim, char typdelim)
|
||||
/* Signal a premature end of the string */
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
break;
|
||||
case '\\':
|
||||
|
||||
/*
|
||||
* An escape must be after a level start, after an
|
||||
* element start, or after an element delimiter. In
|
||||
* any case we now must be past an element start.
|
||||
* An escape must be after a level start, after an element
|
||||
* start, or after an element delimiter. In any case we
|
||||
* now must be past an element start.
|
||||
*/
|
||||
if (parse_state != ARRAY_LEVEL_STARTED &&
|
||||
parse_state != ARRAY_ELEM_STARTED &&
|
||||
parse_state != ARRAY_QUOTED_ELEM_STARTED &&
|
||||
parse_state != ARRAY_ELEM_DELIMITED)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
if (parse_state != ARRAY_QUOTED_ELEM_STARTED)
|
||||
parse_state = ARRAY_ELEM_STARTED;
|
||||
/* skip the escaped character */
|
||||
@@ -429,22 +427,22 @@ ArrayCount(char *str, int *dim, char typdelim)
|
||||
ptr++;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
break;
|
||||
case '\"':
|
||||
|
||||
/*
|
||||
* A quote must be after a level start, after a quoted
|
||||
* element start, or after an element delimiter. In
|
||||
* any case we now must be past an element start.
|
||||
* element start, or after an element delimiter. In any
|
||||
* case we now must be past an element start.
|
||||
*/
|
||||
if (parse_state != ARRAY_LEVEL_STARTED &&
|
||||
parse_state != ARRAY_QUOTED_ELEM_STARTED &&
|
||||
parse_state != ARRAY_ELEM_DELIMITED)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
in_quotes = !in_quotes;
|
||||
if (in_quotes)
|
||||
parse_state = ARRAY_QUOTED_ELEM_STARTED;
|
||||
@@ -455,22 +453,22 @@ ArrayCount(char *str, int *dim, char typdelim)
|
||||
if (!in_quotes)
|
||||
{
|
||||
/*
|
||||
* A left brace can occur if no nesting has
|
||||
* occurred yet, after a level start, or after a
|
||||
* level delimiter.
|
||||
* A left brace can occur if no nesting has occurred
|
||||
* yet, after a level start, or after a level
|
||||
* delimiter.
|
||||
*/
|
||||
if (parse_state != ARRAY_NO_LEVEL &&
|
||||
parse_state != ARRAY_LEVEL_STARTED &&
|
||||
parse_state != ARRAY_LEVEL_DELIMITED)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
parse_state = ARRAY_LEVEL_STARTED;
|
||||
if (nest_level >= MAXDIM)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
|
||||
nest_level, MAXDIM)));
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
|
||||
nest_level, MAXDIM)));
|
||||
temp[nest_level] = 0;
|
||||
nest_level++;
|
||||
if (ndim < nest_level)
|
||||
@@ -481,9 +479,9 @@ ArrayCount(char *str, int *dim, char typdelim)
|
||||
if (!in_quotes)
|
||||
{
|
||||
/*
|
||||
* A right brace can occur after an element start,
|
||||
* an element completion, a quoted element
|
||||
* completion, or a level completion.
|
||||
* A right brace can occur after an element start, an
|
||||
* element completion, a quoted element completion, or
|
||||
* a level completion.
|
||||
*/
|
||||
if (parse_state != ARRAY_ELEM_STARTED &&
|
||||
parse_state != ARRAY_ELEM_COMPLETED &&
|
||||
@@ -491,22 +489,22 @@ ArrayCount(char *str, int *dim, char typdelim)
|
||||
parse_state != ARRAY_LEVEL_COMPLETED &&
|
||||
!(nest_level == 1 && parse_state == ARRAY_LEVEL_STARTED))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
parse_state = ARRAY_LEVEL_COMPLETED;
|
||||
if (nest_level == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
nest_level--;
|
||||
|
||||
if ((nelems_last[nest_level] != 1) &&
|
||||
(nelems[nest_level] != nelems_last[nest_level]))
|
||||
(nelems[nest_level] != nelems_last[nest_level]))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("multidimensional arrays must have "
|
||||
"array expressions with matching "
|
||||
"dimensions")));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("multidimensional arrays must have "
|
||||
"array expressions with matching "
|
||||
"dimensions")));
|
||||
nelems_last[nest_level] = nelems[nest_level];
|
||||
nelems[nest_level] = 1;
|
||||
if (nest_level == 0)
|
||||
@@ -527,17 +525,17 @@ ArrayCount(char *str, int *dim, char typdelim)
|
||||
if (*ptr == typdelim)
|
||||
{
|
||||
/*
|
||||
* Delimiters can occur after an element
|
||||
* start, an element completion, a quoted
|
||||
* element completion, or a level completion.
|
||||
* Delimiters can occur after an element start, an
|
||||
* element completion, a quoted element
|
||||
* completion, or a level completion.
|
||||
*/
|
||||
if (parse_state != ARRAY_ELEM_STARTED &&
|
||||
parse_state != ARRAY_ELEM_COMPLETED &&
|
||||
parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
|
||||
parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
|
||||
parse_state != ARRAY_LEVEL_COMPLETED)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
if (parse_state == ARRAY_LEVEL_COMPLETED)
|
||||
parse_state = ARRAY_LEVEL_DELIMITED;
|
||||
else
|
||||
@@ -549,16 +547,16 @@ ArrayCount(char *str, int *dim, char typdelim)
|
||||
{
|
||||
/*
|
||||
* Other non-space characters must be after a
|
||||
* level start, after an element start, or
|
||||
* after an element delimiter. In any case we
|
||||
* now must be past an element start.
|
||||
* level start, after an element start, or after
|
||||
* an element delimiter. In any case we now must
|
||||
* be past an element start.
|
||||
*/
|
||||
if (parse_state != ARRAY_LEVEL_STARTED &&
|
||||
parse_state != ARRAY_ELEM_STARTED &&
|
||||
parse_state != ARRAY_ELEM_DELIMITED)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"", str)));
|
||||
parse_state = ARRAY_ELEM_STARTED;
|
||||
}
|
||||
}
|
||||
@@ -637,18 +635,18 @@ ReadArrayStr(char *arrayStr,
|
||||
MemSet(indx, 0, sizeof(indx));
|
||||
|
||||
/*
|
||||
* We have to remove " and \ characters to create a clean item value
|
||||
* to pass to the datatype input routine. We overwrite each item
|
||||
* value in-place within arrayStr to do this. srcptr is the current
|
||||
* scan point, and dstptr is where we are copying to.
|
||||
* We have to remove " and \ characters to create a clean item value to
|
||||
* pass to the datatype input routine. We overwrite each item value
|
||||
* in-place within arrayStr to do this. srcptr is the current scan point,
|
||||
* and dstptr is where we are copying to.
|
||||
*
|
||||
* We also want to suppress leading and trailing unquoted whitespace.
|
||||
* We use the leadingspace flag to suppress leading space. Trailing
|
||||
* space is tracked by using dstendptr to point to the last significant
|
||||
* output character.
|
||||
* We also want to suppress leading and trailing unquoted whitespace. We use
|
||||
* the leadingspace flag to suppress leading space. Trailing space is
|
||||
* tracked by using dstendptr to point to the last significant output
|
||||
* character.
|
||||
*
|
||||
* The error checking in this routine is mostly pro-forma, since we
|
||||
* expect that ArrayCount() already validated the string.
|
||||
* The error checking in this routine is mostly pro-forma, since we expect
|
||||
* that ArrayCount() already validated the string.
|
||||
*/
|
||||
srcptr = arrayStr;
|
||||
while (!eoArray)
|
||||
@@ -706,9 +704,9 @@ ReadArrayStr(char *arrayStr,
|
||||
{
|
||||
if (nest_level >= ndim)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"",
|
||||
origStr)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"",
|
||||
origStr)));
|
||||
nest_level++;
|
||||
indx[nest_level - 1] = 0;
|
||||
srcptr++;
|
||||
@@ -721,9 +719,9 @@ ReadArrayStr(char *arrayStr,
|
||||
{
|
||||
if (nest_level == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"",
|
||||
origStr)));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed array literal: \"%s\"",
|
||||
origStr)));
|
||||
if (i == -1)
|
||||
i = ArrayGetOffset0(ndim, indx, prod);
|
||||
indx[nest_level - 1] = 0;
|
||||
@@ -751,8 +749,8 @@ ReadArrayStr(char *arrayStr,
|
||||
else if (isspace((unsigned char) *srcptr))
|
||||
{
|
||||
/*
|
||||
* If leading space, drop it immediately. Else,
|
||||
* copy but don't advance dstendptr.
|
||||
* If leading space, drop it immediately. Else, copy
|
||||
* but don't advance dstendptr.
|
||||
*/
|
||||
if (leadingspace)
|
||||
srcptr++;
|
||||
@@ -913,14 +911,14 @@ array_out(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* We arrange to look up info about element type, including its output
|
||||
* conversion proc, only once per series of calls, assuming the
|
||||
* element type doesn't change underneath us.
|
||||
* conversion proc, only once per series of calls, assuming the element
|
||||
* type doesn't change underneath us.
|
||||
*/
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
if (my_extra == NULL)
|
||||
{
|
||||
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
||||
sizeof(ArrayMetaState));
|
||||
sizeof(ArrayMetaState));
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
my_extra->element_type = InvalidOid;
|
||||
}
|
||||
@@ -928,8 +926,7 @@ array_out(PG_FUNCTION_ARGS)
|
||||
if (my_extra->element_type != element_type)
|
||||
{
|
||||
/*
|
||||
* Get info about element type, including its output conversion
|
||||
* proc
|
||||
* Get info about element type, including its output conversion proc
|
||||
*/
|
||||
get_type_io_data(element_type, IOFunc_output,
|
||||
&my_extra->typlen, &my_extra->typbyval,
|
||||
@@ -956,8 +953,8 @@ array_out(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* we will need to add explicit dimensions if any dimension has a
|
||||
* lower bound other than one
|
||||
* we will need to add explicit dimensions if any dimension has a lower
|
||||
* bound other than one
|
||||
*/
|
||||
for (i = 0; i < ndim; i++)
|
||||
{
|
||||
@@ -969,9 +966,9 @@ array_out(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert all values to string form, count total space needed
|
||||
* (including any overhead such as escaping backslashes), and detect
|
||||
* whether each item needs double quotes.
|
||||
* Convert all values to string form, count total space needed (including
|
||||
* any overhead such as escaping backslashes), and detect whether each
|
||||
* item needs double quotes.
|
||||
*/
|
||||
values = (char **) palloc(nitems * sizeof(char *));
|
||||
needquotes = (bool *) palloc(nitems * sizeof(bool));
|
||||
@@ -991,7 +988,7 @@ array_out(PG_FUNCTION_ARGS)
|
||||
|
||||
/* count data plus backslashes; detect chars needing quotes */
|
||||
if (values[i][0] == '\0')
|
||||
needquote = true; /* force quotes for empty string */
|
||||
needquote = true; /* force quotes for empty string */
|
||||
else
|
||||
needquote = false;
|
||||
|
||||
@@ -1121,8 +1118,7 @@ array_recv(PG_FUNCTION_ARGS)
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
Oid spec_element_type = PG_GETARG_OID(1); /* type of an array
|
||||
* element */
|
||||
int32 typmod = PG_GETARG_INT32(2); /* typmod for array
|
||||
* elements */
|
||||
int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */
|
||||
Oid element_type;
|
||||
int typlen;
|
||||
bool typbyval;
|
||||
@@ -1174,15 +1170,15 @@ array_recv(PG_FUNCTION_ARGS)
|
||||
nitems = ArrayGetNItems(ndim, dim);
|
||||
|
||||
/*
|
||||
* We arrange to look up info about element type, including its
|
||||
* receive conversion proc, only once per series of calls, assuming
|
||||
* the element type doesn't change underneath us.
|
||||
* We arrange to look up info about element type, including its receive
|
||||
* conversion proc, only once per series of calls, assuming the element
|
||||
* type doesn't change underneath us.
|
||||
*/
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
if (my_extra == NULL)
|
||||
{
|
||||
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
||||
sizeof(ArrayMetaState));
|
||||
sizeof(ArrayMetaState));
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
my_extra->element_type = ~element_type;
|
||||
}
|
||||
@@ -1197,8 +1193,8 @@ array_recv(PG_FUNCTION_ARGS)
|
||||
if (!OidIsValid(my_extra->typiofunc))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("no binary input function available for type %s",
|
||||
format_type_be(element_type))));
|
||||
errmsg("no binary input function available for type %s",
|
||||
format_type_be(element_type))));
|
||||
fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
|
||||
fcinfo->flinfo->fn_mcxt);
|
||||
my_extra->element_type = element_type;
|
||||
@@ -1278,10 +1274,10 @@ ReadArrayBinary(StringInfo buf,
|
||||
errmsg("insufficient data left in message")));
|
||||
|
||||
/*
|
||||
* Rather than copying data around, we just set up a phony
|
||||
* StringInfo pointing to the correct portion of the input buffer.
|
||||
* We assume we can scribble on the input buffer so as to maintain
|
||||
* the convention that StringInfos have a trailing null.
|
||||
* Rather than copying data around, we just set up a phony StringInfo
|
||||
* pointing to the correct portion of the input buffer. We assume we
|
||||
* can scribble on the input buffer so as to maintain the convention
|
||||
* that StringInfos have a trailing null.
|
||||
*/
|
||||
elem_buf.data = &buf->data[buf->cursor];
|
||||
elem_buf.maxlen = itemlen + 1;
|
||||
@@ -1359,14 +1355,14 @@ array_send(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* We arrange to look up info about element type, including its send
|
||||
* conversion proc, only once per series of calls, assuming the
|
||||
* element type doesn't change underneath us.
|
||||
* conversion proc, only once per series of calls, assuming the element
|
||||
* type doesn't change underneath us.
|
||||
*/
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
if (my_extra == NULL)
|
||||
{
|
||||
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
||||
sizeof(ArrayMetaState));
|
||||
sizeof(ArrayMetaState));
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
my_extra->element_type = InvalidOid;
|
||||
}
|
||||
@@ -1381,8 +1377,8 @@ array_send(PG_FUNCTION_ARGS)
|
||||
if (!OidIsValid(my_extra->typiofunc))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("no binary output function available for type %s",
|
||||
format_type_be(element_type))));
|
||||
errmsg("no binary output function available for type %s",
|
||||
format_type_be(element_type))));
|
||||
fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
|
||||
fcinfo->flinfo->fn_mcxt);
|
||||
my_extra->element_type = element_type;
|
||||
@@ -1646,14 +1642,14 @@ array_get_slice(ArrayType *array,
|
||||
if (arraylen > 0)
|
||||
{
|
||||
/*
|
||||
* fixed-length arrays -- currently, cannot slice these because
|
||||
* parser labels output as being of the fixed-length array type!
|
||||
* Code below shows how we could support it if the parser were
|
||||
* changed to label output as a suitable varlena array type.
|
||||
* fixed-length arrays -- currently, cannot slice these because parser
|
||||
* labels output as being of the fixed-length array type! Code below
|
||||
* shows how we could support it if the parser were changed to label
|
||||
* output as a suitable varlena array type.
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("slices of fixed-length arrays not implemented")));
|
||||
errmsg("slices of fixed-length arrays not implemented")));
|
||||
|
||||
/*
|
||||
* fixed-length arrays -- these are assumed to be 1-d, 0-based XXX
|
||||
@@ -1678,10 +1674,9 @@ array_get_slice(ArrayType *array,
|
||||
}
|
||||
|
||||
/*
|
||||
* Check provided subscripts. A slice exceeding the current array
|
||||
* limits is silently truncated to the array limits. If we end up
|
||||
* with an empty slice, return NULL (should it be an empty array
|
||||
* instead?)
|
||||
* Check provided subscripts. A slice exceeding the current array limits
|
||||
* is silently truncated to the array limits. If we end up with an empty
|
||||
* slice, return NULL (should it be an empty array instead?)
|
||||
*/
|
||||
if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
|
||||
RETURN_NULL(ArrayType *);
|
||||
@@ -1719,8 +1714,8 @@ array_get_slice(ArrayType *array,
|
||||
memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int));
|
||||
|
||||
/*
|
||||
* Lower bounds of the new array are set to 1. Formerly (before 7.3)
|
||||
* we copied the given lowerIndx values ... but that seems confusing.
|
||||
* Lower bounds of the new array are set to 1. Formerly (before 7.3) we
|
||||
* copied the given lowerIndx values ... but that seems confusing.
|
||||
*/
|
||||
newlb = ARR_LBOUND(newarray);
|
||||
for (i = 0; i < ndim; i++)
|
||||
@@ -1815,9 +1810,9 @@ array_set(ArrayType *array,
|
||||
ndim = ARR_NDIM(array);
|
||||
|
||||
/*
|
||||
* if number of dims is zero, i.e. an empty array, create an array
|
||||
* with nSubscripts dimensions, and set the lower bounds to the
|
||||
* supplied subscripts
|
||||
* if number of dims is zero, i.e. an empty array, create an array with
|
||||
* nSubscripts dimensions, and set the lower bounds to the supplied
|
||||
* subscripts
|
||||
*/
|
||||
if (ndim == 0)
|
||||
{
|
||||
@@ -1987,7 +1982,7 @@ array_set_slice(ArrayType *array,
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("updates on slices of fixed-length arrays not implemented")));
|
||||
errmsg("updates on slices of fixed-length arrays not implemented")));
|
||||
}
|
||||
|
||||
/* detoast arrays if necessary */
|
||||
@@ -1999,9 +1994,9 @@ array_set_slice(ArrayType *array,
|
||||
ndim = ARR_NDIM(array);
|
||||
|
||||
/*
|
||||
* if number of dims is zero, i.e. an empty array, create an array
|
||||
* with nSubscripts dimensions, and set the upper and lower bounds to
|
||||
* the supplied subscripts
|
||||
* if number of dims is zero, i.e. an empty array, create an array with
|
||||
* nSubscripts dimensions, and set the upper and lower bounds to the
|
||||
* supplied subscripts
|
||||
*/
|
||||
if (ndim == 0)
|
||||
{
|
||||
@@ -2038,10 +2033,9 @@ array_set_slice(ArrayType *array,
|
||||
memcpy(lb, ARR_LBOUND(array), ndim * sizeof(int));
|
||||
|
||||
/*
|
||||
* Check provided subscripts. A slice exceeding the current array
|
||||
* limits throws an error, *except* in the 1-D case where we will
|
||||
* extend the array as long as no hole is created. An empty slice is
|
||||
* an error, too.
|
||||
* Check provided subscripts. A slice exceeding the current array limits
|
||||
* throws an error, *except* in the 1-D case where we will extend the
|
||||
* array as long as no hole is created. An empty slice is an error, too.
|
||||
*/
|
||||
for (i = 0; i < nSubscripts; i++)
|
||||
{
|
||||
@@ -2083,8 +2077,8 @@ array_set_slice(ArrayType *array,
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure source array has enough entries. Note we ignore the
|
||||
* shape of the source array and just read entries serially.
|
||||
* Make sure source array has enough entries. Note we ignore the shape of
|
||||
* the source array and just read entries serially.
|
||||
*/
|
||||
mda_get_range(ndim, span, lowerIndx, upperIndx);
|
||||
nsrcitems = ArrayGetNItems(ndim, span);
|
||||
@@ -2104,8 +2098,8 @@ array_set_slice(ArrayType *array,
|
||||
if (ndim > 1)
|
||||
{
|
||||
/*
|
||||
* here we do not need to cope with extension of the array; it
|
||||
* would be a lot more complicated if we had to do so...
|
||||
* here we do not need to cope with extension of the array; it would
|
||||
* be a lot more complicated if we had to do so...
|
||||
*/
|
||||
olditemsize = array_slice_size(ndim, dim, lb, ARR_DATA_PTR(array),
|
||||
lowerIndx, upperIndx,
|
||||
@@ -2115,8 +2109,7 @@ array_set_slice(ArrayType *array,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* here we must allow for possibility of slice larger than orig
|
||||
* array
|
||||
* here we must allow for possibility of slice larger than orig array
|
||||
*/
|
||||
int oldlb = ARR_LBOUND(array)[0];
|
||||
int oldub = oldlb + ARR_DIMS(array)[0] - 1;
|
||||
@@ -2148,8 +2141,8 @@ array_set_slice(ArrayType *array,
|
||||
if (ndim > 1)
|
||||
{
|
||||
/*
|
||||
* here we do not need to cope with extension of the array; it
|
||||
* would be a lot more complicated if we had to do so...
|
||||
* here we do not need to cope with extension of the array; it would
|
||||
* be a lot more complicated if we had to do so...
|
||||
*/
|
||||
array_insert_slice(ndim, dim, lb, ARR_DATA_PTR(array), olddatasize,
|
||||
ARR_DATA_PTR(newarray),
|
||||
@@ -2192,7 +2185,7 @@ array_set_slice(ArrayType *array,
|
||||
* or binary-compatible with, the first argument type of fn().
|
||||
* * retType: OID of element type of output array. This must be the same as,
|
||||
* or binary-compatible with, the result type of fn().
|
||||
* * amstate: workspace for array_map. Must be zeroed by caller before
|
||||
* * amstate: workspace for array_map. Must be zeroed by caller before
|
||||
* first call, and not touched after that.
|
||||
*
|
||||
* It is legitimate to pass a freshly-zeroed ArrayMapState on each call,
|
||||
@@ -2250,9 +2243,9 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
|
||||
}
|
||||
|
||||
/*
|
||||
* We arrange to look up info about input and return element types
|
||||
* only once per series of calls, assuming the element type doesn't
|
||||
* change underneath us.
|
||||
* We arrange to look up info about input and return element types only
|
||||
* once per series of calls, assuming the element type doesn't change
|
||||
* underneath us.
|
||||
*/
|
||||
inp_extra = &amstate->inp_extra;
|
||||
ret_extra = &amstate->ret_extra;
|
||||
@@ -2297,9 +2290,9 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
|
||||
/*
|
||||
* Apply the given function to source elt and extra args.
|
||||
*
|
||||
* We assume the extra args are non-NULL, so need not check whether
|
||||
* fn() is strict. Would need to do more work here to support
|
||||
* arrays containing nulls, too.
|
||||
* We assume the extra args are non-NULL, so need not check whether fn()
|
||||
* is strict. Would need to do more work here to support arrays
|
||||
* containing nulls, too.
|
||||
*/
|
||||
fcinfo->arg[0] = elt;
|
||||
fcinfo->argnull[0] = false;
|
||||
@@ -2329,8 +2322,7 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
|
||||
memcpy(ARR_DIMS(result), ARR_DIMS(v), 2 * ndim * sizeof(int));
|
||||
|
||||
/*
|
||||
* Note: do not risk trying to pfree the results of the called
|
||||
* function
|
||||
* Note: do not risk trying to pfree the results of the called function
|
||||
*/
|
||||
CopyArrayEls(ARR_DATA_PTR(result), values, nitems,
|
||||
typlen, typbyval, typalign, false);
|
||||
@@ -2543,7 +2535,7 @@ array_eq(PG_FUNCTION_ARGS)
|
||||
if (element_type != ARR_ELEMTYPE(array2))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("cannot compare arrays of different element types")));
|
||||
errmsg("cannot compare arrays of different element types")));
|
||||
|
||||
/* fast path if the arrays do not have the same number of elements */
|
||||
if (nitems1 != nitems2)
|
||||
@@ -2551,10 +2543,10 @@ array_eq(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We arrange to look up the equality function only once per
|
||||
* series of calls, assuming the element type doesn't change
|
||||
* underneath us. The typcache is used so that we have no memory
|
||||
* leakage when being used as an index support function.
|
||||
* We arrange to look up the equality function only once per series of
|
||||
* calls, assuming the element type doesn't change underneath us. The
|
||||
* typcache is used so that we have no memory leakage when being used
|
||||
* as an index support function.
|
||||
*/
|
||||
typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
|
||||
if (typentry == NULL ||
|
||||
@@ -2565,8 +2557,8 @@ array_eq(PG_FUNCTION_ARGS)
|
||||
if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify an equality operator for type %s",
|
||||
format_type_be(element_type))));
|
||||
errmsg("could not identify an equality operator for type %s",
|
||||
format_type_be(element_type))));
|
||||
fcinfo->flinfo->fn_extra = (void *) typentry;
|
||||
}
|
||||
typlen = typentry->typlen;
|
||||
@@ -2697,13 +2689,13 @@ array_cmp(FunctionCallInfo fcinfo)
|
||||
if (element_type != ARR_ELEMTYPE(array2))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("cannot compare arrays of different element types")));
|
||||
errmsg("cannot compare arrays of different element types")));
|
||||
|
||||
/*
|
||||
* We arrange to look up the comparison function only once per series
|
||||
* of calls, assuming the element type doesn't change underneath us.
|
||||
* The typcache is used so that we have no memory leakage when being
|
||||
* used as an index support function.
|
||||
* We arrange to look up the comparison function only once per series of
|
||||
* calls, assuming the element type doesn't change underneath us. The
|
||||
* typcache is used so that we have no memory leakage when being used as
|
||||
* an index support function.
|
||||
*/
|
||||
typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
|
||||
if (typentry == NULL ||
|
||||
@@ -2714,8 +2706,8 @@ array_cmp(FunctionCallInfo fcinfo)
|
||||
if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify a comparison function for type %s",
|
||||
format_type_be(element_type))));
|
||||
errmsg("could not identify a comparison function for type %s",
|
||||
format_type_be(element_type))));
|
||||
fcinfo->flinfo->fn_extra = (void *) typentry;
|
||||
}
|
||||
typlen = typentry->typlen;
|
||||
@@ -3121,11 +3113,11 @@ array_type_length_coerce_internal(ArrayType *src,
|
||||
errmsg("target type is not an array")));
|
||||
|
||||
/*
|
||||
* We don't deal with domain constraints yet, so bail out. This
|
||||
* isn't currently a problem, because we also don't support arrays
|
||||
* of domain type elements either. But in the future we might. At
|
||||
* that point consideration should be given to removing the check
|
||||
* below and adding a domain constraints check to the coercion.
|
||||
* We don't deal with domain constraints yet, so bail out. This isn't
|
||||
* currently a problem, because we also don't support arrays of domain
|
||||
* type elements either. But in the future we might. At that point
|
||||
* consideration should be given to removing the check below and
|
||||
* adding a domain constraints check to the coercion.
|
||||
*/
|
||||
if (getBaseType(tgt_elem_type) != tgt_elem_type)
|
||||
ereport(ERROR,
|
||||
@@ -3150,8 +3142,8 @@ array_type_length_coerce_internal(ArrayType *src,
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's binary-compatible, modify the element type in the array
|
||||
* header, but otherwise leave the array as we received it.
|
||||
* If it's binary-compatible, modify the element type in the array header,
|
||||
* but otherwise leave the array as we received it.
|
||||
*/
|
||||
if (my_extra->coerce_finfo.fn_oid == InvalidOid)
|
||||
{
|
||||
@@ -3166,8 +3158,8 @@ array_type_length_coerce_internal(ArrayType *src,
|
||||
/*
|
||||
* Use array_map to apply the function to each array element.
|
||||
*
|
||||
* We pass on the desttypmod and isExplicit flags whether or not the
|
||||
* function wants them.
|
||||
* We pass on the desttypmod and isExplicit flags whether or not the function
|
||||
* wants them.
|
||||
*/
|
||||
InitFunctionCallInfoData(locfcinfo, &my_extra->coerce_finfo, 3,
|
||||
NULL, NULL);
|
||||
@@ -3207,8 +3199,8 @@ array_length_coerce(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_ARRAYTYPE_P(v);
|
||||
|
||||
/*
|
||||
* We arrange to look up the element type's coercion function only
|
||||
* once per series of calls, assuming the element type doesn't change
|
||||
* We arrange to look up the element type's coercion function only once
|
||||
* per series of calls, assuming the element type doesn't change
|
||||
* underneath us.
|
||||
*/
|
||||
my_extra = (alc_extra *) fmgr_info->fn_extra;
|
||||
@@ -3303,7 +3295,7 @@ accumArrayResult(ArrayBuildState *astate,
|
||||
if ((astate->nelems % ARRAY_ELEMS_CHUNKSIZE) == 0)
|
||||
astate->dvalues = (Datum *)
|
||||
repalloc(astate->dvalues,
|
||||
(astate->nelems + ARRAY_ELEMS_CHUNKSIZE) * sizeof(Datum));
|
||||
(astate->nelems + ARRAY_ELEMS_CHUNKSIZE) * sizeof(Datum));
|
||||
}
|
||||
|
||||
if (disnull)
|
||||
@@ -3381,9 +3373,9 @@ makeMdArrayResult(ArrayBuildState *astate,
|
||||
Datum
|
||||
array_larger(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ArrayType *v1,
|
||||
*v2,
|
||||
*result;
|
||||
ArrayType *v1,
|
||||
*v2,
|
||||
*result;
|
||||
|
||||
v1 = PG_GETARG_ARRAYTYPE_P(0);
|
||||
v2 = PG_GETARG_ARRAYTYPE_P(1);
|
||||
@@ -3396,9 +3388,9 @@ array_larger(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
array_smaller(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ArrayType *v1,
|
||||
*v2,
|
||||
*result;
|
||||
ArrayType *v1,
|
||||
*v2,
|
||||
*result;
|
||||
|
||||
v1 = PG_GETARG_ARRAYTYPE_P(0);
|
||||
v2 = PG_GETARG_ARRAYTYPE_P(1);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ascii.c,v 1.25 2005/09/24 17:53:15 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ascii.c,v 1.26 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -73,8 +73,8 @@ pg_to_ascii(unsigned char *src, unsigned char *src_end, unsigned char *dest, int
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("encoding conversion from %s to ASCII not supported",
|
||||
pg_encoding_to_char(enc))));
|
||||
errmsg("encoding conversion from %s to ASCII not supported",
|
||||
pg_encoding_to_char(enc))));
|
||||
return; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* workings can be found in the book "Software Solutions in C" by
|
||||
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/cash.c,v 1.65 2005/07/21 04:41:43 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/cash.c,v 1.66 2005/10/15 02:49:28 momjian Exp $
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
@@ -85,14 +85,14 @@ cash_in(PG_FUNCTION_ARGS)
|
||||
struct lconv *lconvert = PGLC_localeconv();
|
||||
|
||||
/*
|
||||
* frac_digits will be CHAR_MAX in some locales, notably C. However,
|
||||
* just testing for == CHAR_MAX is risky, because of compilers like
|
||||
* gcc that "helpfully" let you alter the platform-standard definition
|
||||
* of whether char is signed or not. If we are so unfortunate as to
|
||||
* get compiled with a nonstandard -fsigned-char or -funsigned-char
|
||||
* switch, then our idea of CHAR_MAX will not agree with libc's. The
|
||||
* safest course is not to test for CHAR_MAX at all, but to impose a
|
||||
* range check for plausible frac_digits values.
|
||||
* frac_digits will be CHAR_MAX in some locales, notably C. However, just
|
||||
* testing for == CHAR_MAX is risky, because of compilers like gcc that
|
||||
* "helpfully" let you alter the platform-standard definition of whether
|
||||
* char is signed or not. If we are so unfortunate as to get compiled
|
||||
* with a nonstandard -fsigned-char or -funsigned-char switch, then our
|
||||
* idea of CHAR_MAX will not agree with libc's. The safest course is not
|
||||
* to test for CHAR_MAX at all, but to impose a range check for plausible
|
||||
* frac_digits values.
|
||||
*/
|
||||
fpoint = lconvert->frac_digits;
|
||||
if (fpoint < 0 || fpoint > 10)
|
||||
@@ -195,7 +195,7 @@ cash_in(PG_FUNCTION_ARGS)
|
||||
if (*s != '\0')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type money: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type money: \"%s\"", str)));
|
||||
|
||||
result = value * sgn;
|
||||
|
||||
@@ -238,8 +238,8 @@ cash_out(PG_FUNCTION_ARGS)
|
||||
points = 2; /* best guess in this case, I think */
|
||||
|
||||
/*
|
||||
* As with frac_digits, must apply a range check to mon_grouping to
|
||||
* avoid being fooled by variant CHAR_MAX values.
|
||||
* As with frac_digits, must apply a range check to mon_grouping to avoid
|
||||
* being fooled by variant CHAR_MAX values.
|
||||
*/
|
||||
mon_group = *lconvert->mon_grouping;
|
||||
if (mon_group <= 0 || mon_group > 6)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/char.c,v 1.42 2004/12/31 22:01:21 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/char.c,v 1.43 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -187,9 +187,9 @@ text_char(PG_FUNCTION_ARGS)
|
||||
char result;
|
||||
|
||||
/*
|
||||
* An empty input string is converted to \0 (for consistency with
|
||||
* charin). If the input is longer than one character, the excess data
|
||||
* is silently discarded.
|
||||
* An empty input string is converted to \0 (for consistency with charin).
|
||||
* If the input is longer than one character, the excess data is silently
|
||||
* discarded.
|
||||
*/
|
||||
if (VARSIZE(arg1) > VARHDRSZ)
|
||||
result = *(VARDATA(arg1));
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.121 2005/10/09 17:21:46 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.122 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include <time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "access/hash.h"
|
||||
#include "libpq/pqformat.h"
|
||||
@@ -38,10 +38,10 @@
|
||||
#endif
|
||||
|
||||
|
||||
static int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec);
|
||||
static int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp);
|
||||
static int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result);
|
||||
static int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result);
|
||||
static int time2tm(TimeADT time, struct pg_tm * tm, fsec_t *fsec);
|
||||
static int timetz2tm(TimeTzADT *time, struct pg_tm * tm, fsec_t *fsec, int *tzp);
|
||||
static int tm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result);
|
||||
static int tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result);
|
||||
static void AdjustTimeForTypmod(TimeADT *time, int32 typmod);
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -56,7 +56,7 @@ Datum
|
||||
date_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *str = PG_GETARG_CSTRING(0);
|
||||
DateADT date;
|
||||
DateADT date;
|
||||
fsec_t fsec;
|
||||
struct pg_tm tt,
|
||||
*tm = &tt;
|
||||
@@ -83,7 +83,7 @@ date_in(PG_FUNCTION_ARGS)
|
||||
case DTK_CURRENT:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("date/time value \"current\" is no longer supported")));
|
||||
errmsg("date/time value \"current\" is no longer supported")));
|
||||
|
||||
GetCurrentDateTime(tm);
|
||||
break;
|
||||
@@ -108,13 +108,13 @@ date_in(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
date_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
DateADT date = PG_GETARG_DATEADT(0);
|
||||
DateADT date = PG_GETARG_DATEADT(0);
|
||||
char *result;
|
||||
struct pg_tm tt,
|
||||
*tm = &tt;
|
||||
char buf[MAXDATELEN + 1];
|
||||
|
||||
j2date(date +POSTGRES_EPOCH_JDATE,
|
||||
j2date(date + POSTGRES_EPOCH_JDATE,
|
||||
&(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
|
||||
|
||||
EncodeDateOnly(tm, DateStyle, buf);
|
||||
@@ -140,7 +140,7 @@ date_recv(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
date_send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
DateADT date = PG_GETARG_DATEADT(0);
|
||||
DateADT date = PG_GETARG_DATEADT(0);
|
||||
StringInfoData buf;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
@@ -306,7 +306,7 @@ date2timestamptz(DateADT dateVal)
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
|
||||
#else
|
||||
result = dateVal * (double)SECS_PER_DAY + tz;
|
||||
result = dateVal * (double) SECS_PER_DAY + tz;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
@@ -715,7 +715,7 @@ date_timestamp(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
timestamp_date(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
|
||||
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
|
||||
DateADT result;
|
||||
struct pg_tm tt,
|
||||
*tm = &tt;
|
||||
@@ -797,11 +797,11 @@ abstime_date(PG_FUNCTION_ARGS)
|
||||
case NOEND_ABSTIME:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot convert reserved abstime value to date")));
|
||||
errmsg("cannot convert reserved abstime value to date")));
|
||||
|
||||
/*
|
||||
* pretend to drop through to make compiler think that result
|
||||
* will be set
|
||||
* pretend to drop through to make compiler think that result will
|
||||
* be set
|
||||
*/
|
||||
|
||||
default:
|
||||
@@ -821,7 +821,7 @@ Datum
|
||||
date_text(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Input is a Date, but may as well leave it in Datum form */
|
||||
Datum date = PG_GETARG_DATUM(0);
|
||||
Datum date = PG_GETARG_DATUM(0);
|
||||
text *result;
|
||||
char *str;
|
||||
int len;
|
||||
@@ -914,11 +914,11 @@ time_in(PG_FUNCTION_ARGS)
|
||||
* Convert a tm structure to a time data type.
|
||||
*/
|
||||
static int
|
||||
tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
|
||||
tm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
*result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec)
|
||||
* USECS_PER_SEC) + fsec;
|
||||
* USECS_PER_SEC) + fsec;
|
||||
#else
|
||||
*result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
|
||||
#endif
|
||||
@@ -931,7 +931,7 @@ tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
|
||||
* local time zone. If out of this range, leave as GMT. - tgl 97/05/27
|
||||
*/
|
||||
static int
|
||||
time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
|
||||
time2tm(TimeADT time, struct pg_tm * tm, fsec_t *fsec)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
tm->tm_hour = time / USECS_PER_HOUR;
|
||||
@@ -946,8 +946,8 @@ time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
|
||||
|
||||
recalc:
|
||||
trem = time;
|
||||
TMODULO(trem, tm->tm_hour, (double)SECS_PER_HOUR);
|
||||
TMODULO(trem, tm->tm_min, (double)SECS_PER_MINUTE);
|
||||
TMODULO(trem, tm->tm_hour, (double) SECS_PER_HOUR);
|
||||
TMODULO(trem, tm->tm_min, (double) SECS_PER_MINUTE);
|
||||
TMODULO(trem, tm->tm_sec, 1.0);
|
||||
trem = TIMEROUND(trem);
|
||||
/* roundoff may need to propagate to higher-order fields */
|
||||
@@ -989,6 +989,7 @@ Datum
|
||||
time_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
@@ -1072,7 +1073,6 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
|
||||
INT64CONST(5),
|
||||
INT64CONST(0)
|
||||
};
|
||||
|
||||
#else
|
||||
/* note MAX_TIME_PRECISION differs in this case */
|
||||
static const double TimeScales[MAX_TIME_PRECISION + 1] = {
|
||||
@@ -1093,21 +1093,21 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
|
||||
if (typmod >= 0 && typmod <= MAX_TIME_PRECISION)
|
||||
{
|
||||
/*
|
||||
* Note: this round-to-nearest code is not completely consistent
|
||||
* about rounding values that are exactly halfway between integral
|
||||
* values. On most platforms, rint() will implement
|
||||
* round-to-nearest-even, but the integer code always rounds up
|
||||
* (away from zero). Is it worth trying to be consistent?
|
||||
* Note: this round-to-nearest code is not completely consistent about
|
||||
* rounding values that are exactly halfway between integral values.
|
||||
* On most platforms, rint() will implement round-to-nearest-even, but
|
||||
* the integer code always rounds up (away from zero). Is it worth
|
||||
* trying to be consistent?
|
||||
*/
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
if (*time >= INT64CONST(0))
|
||||
*time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) *
|
||||
TimeScales[typmod];
|
||||
TimeScales[typmod];
|
||||
else
|
||||
*time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) *
|
||||
TimeScales[typmod]);
|
||||
TimeScales[typmod]);
|
||||
#else
|
||||
*time = rint((double) * time * TimeScales[typmod]) / TimeScales[typmod];
|
||||
*time = rint((double) *time * TimeScales[typmod]) / TimeScales[typmod];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1208,8 +1208,8 @@ Datum
|
||||
overlaps_time(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/*
|
||||
* The arguments are TimeADT, but we leave them as generic Datums to
|
||||
* avoid dereferencing nulls (TimeADT is pass-by-reference!)
|
||||
* The arguments are TimeADT, but we leave them as generic Datums to avoid
|
||||
* dereferencing nulls (TimeADT is pass-by-reference!)
|
||||
*/
|
||||
Datum ts1 = PG_GETARG_DATUM(0);
|
||||
Datum te1 = PG_GETARG_DATUM(1);
|
||||
@@ -1226,9 +1226,9 @@ overlaps_time(PG_FUNCTION_ARGS)
|
||||
(DatumGetTimeADT(t1) < DatumGetTimeADT(t2))
|
||||
|
||||
/*
|
||||
* If both endpoints of interval 1 are null, the result is null
|
||||
* (unknown). If just one endpoint is null, take ts1 as the non-null
|
||||
* one. Otherwise, take ts1 as the lesser endpoint.
|
||||
* If both endpoints of interval 1 are null, the result is null (unknown).
|
||||
* If just one endpoint is null, take ts1 as the non-null one. Otherwise,
|
||||
* take ts1 as the lesser endpoint.
|
||||
*/
|
||||
if (ts1IsNull)
|
||||
{
|
||||
@@ -1276,8 +1276,8 @@ overlaps_time(PG_FUNCTION_ARGS)
|
||||
if (TIMEADT_GT(ts1, ts2))
|
||||
{
|
||||
/*
|
||||
* This case is ts1 < te2 OR te1 < te2, which may look redundant
|
||||
* but in the presence of nulls it's not quite completely so.
|
||||
* This case is ts1 < te2 OR te1 < te2, which may look redundant but
|
||||
* in the presence of nulls it's not quite completely so.
|
||||
*/
|
||||
if (te2IsNull)
|
||||
PG_RETURN_NULL();
|
||||
@@ -1287,8 +1287,8 @@ overlaps_time(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
/*
|
||||
* If te1 is not null then we had ts1 <= te1 above, and we just
|
||||
* found ts1 >= te2, hence te1 >= te2.
|
||||
* If te1 is not null then we had ts1 <= te1 above, and we just found
|
||||
* ts1 >= te2, hence te1 >= te2.
|
||||
*/
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
@@ -1303,8 +1303,8 @@ overlaps_time(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
/*
|
||||
* If te2 is not null then we had ts2 <= te2 above, and we just
|
||||
* found ts2 >= te1, hence te2 >= te1.
|
||||
* If te2 is not null then we had ts2 <= te2 above, and we just found
|
||||
* ts2 >= te1, hence te2 >= te1.
|
||||
*/
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
@@ -1312,8 +1312,7 @@ overlaps_time(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/*
|
||||
* For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
|
||||
* rather silly way of saying "true if both are nonnull, else
|
||||
* null".
|
||||
* rather silly way of saying "true if both are nonnull, else null".
|
||||
*/
|
||||
if (te1IsNull || te2IsNull)
|
||||
PG_RETURN_NULL();
|
||||
@@ -1330,7 +1329,7 @@ overlaps_time(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
timestamp_time(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
|
||||
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
|
||||
TimeADT result;
|
||||
struct pg_tm tt,
|
||||
*tm = &tt;
|
||||
@@ -1351,7 +1350,7 @@ timestamp_time(PG_FUNCTION_ARGS)
|
||||
* USECS_PER_DAY) - timestamp;
|
||||
*/
|
||||
result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
|
||||
USECS_PER_SEC) + fsec;
|
||||
USECS_PER_SEC) + fsec;
|
||||
#else
|
||||
result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
|
||||
#endif
|
||||
@@ -1388,7 +1387,7 @@ timestamptz_time(PG_FUNCTION_ARGS)
|
||||
* USECS_PER_DAY) - timestamp;
|
||||
*/
|
||||
result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
|
||||
USECS_PER_SEC) + fsec;
|
||||
USECS_PER_SEC) + fsec;
|
||||
#else
|
||||
result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
|
||||
#endif
|
||||
@@ -1402,12 +1401,12 @@ timestamptz_time(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
datetime_timestamp(PG_FUNCTION_ARGS)
|
||||
{
|
||||
DateADT date = PG_GETARG_DATEADT(0);
|
||||
DateADT date = PG_GETARG_DATEADT(0);
|
||||
TimeADT time = PG_GETARG_TIMEADT(1);
|
||||
Timestamp result;
|
||||
|
||||
result = DatumGetTimestamp(DirectFunctionCall1(date_timestamp,
|
||||
DateADTGetDatum(date)));
|
||||
DateADTGetDatum(date)));
|
||||
result += time;
|
||||
|
||||
PG_RETURN_TIMESTAMP(result);
|
||||
@@ -1461,8 +1460,8 @@ interval_time(PG_FUNCTION_ARGS)
|
||||
}
|
||||
#else
|
||||
result = span->time;
|
||||
if (result >= (double)SECS_PER_DAY || result < 0)
|
||||
result -= floor(result / (double)SECS_PER_DAY) * (double)SECS_PER_DAY;
|
||||
if (result >= (double) SECS_PER_DAY || result < 0)
|
||||
result -= floor(result / (double) SECS_PER_DAY) * (double) SECS_PER_DAY;
|
||||
#endif
|
||||
|
||||
PG_RETURN_TIMEADT(result);
|
||||
@@ -1506,7 +1505,7 @@ time_pl_interval(PG_FUNCTION_ARGS)
|
||||
TimeADT time1;
|
||||
|
||||
result = time + span->time;
|
||||
TMODULO(result, time1, (double)SECS_PER_DAY);
|
||||
TMODULO(result, time1, (double) SECS_PER_DAY);
|
||||
if (result < 0)
|
||||
result += SECS_PER_DAY;
|
||||
#endif
|
||||
@@ -1533,7 +1532,7 @@ time_mi_interval(PG_FUNCTION_ARGS)
|
||||
TimeADT time1;
|
||||
|
||||
result = time - span->time;
|
||||
TMODULO(result, time1, (double)SECS_PER_DAY);
|
||||
TMODULO(result, time1, (double) SECS_PER_DAY);
|
||||
if (result < 0)
|
||||
result += SECS_PER_DAY;
|
||||
#endif
|
||||
@@ -1678,8 +1677,8 @@ time_part(PG_FUNCTION_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("\"time\" units \"%s\" not recognized",
|
||||
DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(units))))));
|
||||
DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(units))))));
|
||||
|
||||
result = 0;
|
||||
}
|
||||
@@ -1698,7 +1697,7 @@ time_part(PG_FUNCTION_ARGS)
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("\"time\" units \"%s\" not recognized",
|
||||
DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(units))))));
|
||||
PointerGetDatum(units))))));
|
||||
result = 0;
|
||||
}
|
||||
|
||||
@@ -1714,7 +1713,7 @@ time_part(PG_FUNCTION_ARGS)
|
||||
* Convert a tm structure to a time data type.
|
||||
*/
|
||||
static int
|
||||
tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
|
||||
tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result->time = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
|
||||
@@ -1787,6 +1786,7 @@ Datum
|
||||
timetz_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
@@ -1831,7 +1831,7 @@ timetz_send(PG_FUNCTION_ARGS)
|
||||
* Convert TIME WITH TIME ZONE data type to POSIX time structure.
|
||||
*/
|
||||
static int
|
||||
timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
|
||||
timetz2tm(TimeTzADT *time, struct pg_tm * tm, fsec_t *fsec, int *tzp)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
int64 trem = time->time;
|
||||
@@ -1846,8 +1846,8 @@ timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
|
||||
double trem = time->time;
|
||||
|
||||
recalc:
|
||||
TMODULO(trem, tm->tm_hour, (double)SECS_PER_HOUR);
|
||||
TMODULO(trem, tm->tm_min, (double)SECS_PER_MINUTE);
|
||||
TMODULO(trem, tm->tm_hour, (double) SECS_PER_HOUR);
|
||||
TMODULO(trem, tm->tm_min, (double) SECS_PER_MINUTE);
|
||||
TMODULO(trem, tm->tm_sec, 1.0);
|
||||
trem = TIMEROUND(trem);
|
||||
/* roundoff may need to propagate to higher-order fields */
|
||||
@@ -1995,8 +1995,8 @@ timetz_hash(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* Specify hash length as sizeof(double) + sizeof(int4), not as
|
||||
* sizeof(TimeTzADT), so that any garbage pad bytes in the structure
|
||||
* won't be included in the hash!
|
||||
* sizeof(TimeTzADT), so that any garbage pad bytes in the structure won't
|
||||
* be included in the hash!
|
||||
*/
|
||||
return hash_any((unsigned char *) key, sizeof(key->time) + sizeof(key->zone));
|
||||
}
|
||||
@@ -2052,7 +2052,7 @@ timetz_pl_interval(PG_FUNCTION_ARGS)
|
||||
result->time += USECS_PER_DAY;
|
||||
#else
|
||||
result->time = time->time + span->time;
|
||||
TMODULO(result->time, time1.time, (double)SECS_PER_DAY);
|
||||
TMODULO(result->time, time1.time, (double) SECS_PER_DAY);
|
||||
if (result->time < 0)
|
||||
result->time += SECS_PER_DAY;
|
||||
#endif
|
||||
@@ -2085,7 +2085,7 @@ timetz_mi_interval(PG_FUNCTION_ARGS)
|
||||
result->time += USECS_PER_DAY;
|
||||
#else
|
||||
result->time = time->time - span->time;
|
||||
TMODULO(result->time, time1.time, (double)SECS_PER_DAY);
|
||||
TMODULO(result->time, time1.time, (double) SECS_PER_DAY);
|
||||
if (result->time < 0)
|
||||
result->time += SECS_PER_DAY;
|
||||
#endif
|
||||
@@ -2105,8 +2105,8 @@ Datum
|
||||
overlaps_timetz(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/*
|
||||
* The arguments are TimeTzADT *, but we leave them as generic Datums
|
||||
* for convenience of notation --- and to avoid dereferencing nulls.
|
||||
* The arguments are TimeTzADT *, but we leave them as generic Datums for
|
||||
* convenience of notation --- and to avoid dereferencing nulls.
|
||||
*/
|
||||
Datum ts1 = PG_GETARG_DATUM(0);
|
||||
Datum te1 = PG_GETARG_DATUM(1);
|
||||
@@ -2123,9 +2123,9 @@ overlaps_timetz(PG_FUNCTION_ARGS)
|
||||
DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2))
|
||||
|
||||
/*
|
||||
* If both endpoints of interval 1 are null, the result is null
|
||||
* (unknown). If just one endpoint is null, take ts1 as the non-null
|
||||
* one. Otherwise, take ts1 as the lesser endpoint.
|
||||
* If both endpoints of interval 1 are null, the result is null (unknown).
|
||||
* If just one endpoint is null, take ts1 as the non-null one. Otherwise,
|
||||
* take ts1 as the lesser endpoint.
|
||||
*/
|
||||
if (ts1IsNull)
|
||||
{
|
||||
@@ -2173,8 +2173,8 @@ overlaps_timetz(PG_FUNCTION_ARGS)
|
||||
if (TIMETZ_GT(ts1, ts2))
|
||||
{
|
||||
/*
|
||||
* This case is ts1 < te2 OR te1 < te2, which may look redundant
|
||||
* but in the presence of nulls it's not quite completely so.
|
||||
* This case is ts1 < te2 OR te1 < te2, which may look redundant but
|
||||
* in the presence of nulls it's not quite completely so.
|
||||
*/
|
||||
if (te2IsNull)
|
||||
PG_RETURN_NULL();
|
||||
@@ -2184,8 +2184,8 @@ overlaps_timetz(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
/*
|
||||
* If te1 is not null then we had ts1 <= te1 above, and we just
|
||||
* found ts1 >= te2, hence te1 >= te2.
|
||||
* If te1 is not null then we had ts1 <= te1 above, and we just found
|
||||
* ts1 >= te2, hence te1 >= te2.
|
||||
*/
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
@@ -2200,8 +2200,8 @@ overlaps_timetz(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
/*
|
||||
* If te2 is not null then we had ts2 <= te2 above, and we just
|
||||
* found ts2 >= te1, hence te2 >= te1.
|
||||
* If te2 is not null then we had ts2 <= te2 above, and we just found
|
||||
* ts2 >= te1, hence te2 >= te1.
|
||||
*/
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
@@ -2209,8 +2209,7 @@ overlaps_timetz(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/*
|
||||
* For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
|
||||
* rather silly way of saying "true if both are nonnull, else
|
||||
* null".
|
||||
* rather silly way of saying "true if both are nonnull, else null".
|
||||
*/
|
||||
if (te1IsNull || te2IsNull)
|
||||
PG_RETURN_NULL();
|
||||
@@ -2297,14 +2296,14 @@ timestamptz_timetz(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
datetimetz_timestamptz(PG_FUNCTION_ARGS)
|
||||
{
|
||||
DateADT date = PG_GETARG_DATEADT(0);
|
||||
DateADT date = PG_GETARG_DATEADT(0);
|
||||
TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
|
||||
TimestampTz result;
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
|
||||
#else
|
||||
result = date * (double)SECS_PER_DAY + time->time + time->zone;
|
||||
result = date * (double) SECS_PER_DAY + time->time + time->zone;
|
||||
#endif
|
||||
|
||||
PG_RETURN_TIMESTAMP(result);
|
||||
@@ -2355,8 +2354,8 @@ text_timetz(PG_FUNCTION_ARGS)
|
||||
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
|
||||
errmsg("invalid input syntax for type time with time zone: \"%s\"",
|
||||
VARDATA(str))));
|
||||
errmsg("invalid input syntax for type time with time zone: \"%s\"",
|
||||
VARDATA(str))));
|
||||
|
||||
sp = VARDATA(str);
|
||||
dp = dstr;
|
||||
@@ -2410,12 +2409,12 @@ timetz_part(PG_FUNCTION_ARGS)
|
||||
case DTK_TZ_MINUTE:
|
||||
result = -tz;
|
||||
result /= SECS_PER_MINUTE;
|
||||
FMODULO(result, dummy, (double)SECS_PER_MINUTE);
|
||||
FMODULO(result, dummy, (double) SECS_PER_MINUTE);
|
||||
break;
|
||||
|
||||
case DTK_TZ_HOUR:
|
||||
dummy = -tz;
|
||||
FMODULO(dummy, result, (double)SECS_PER_HOUR);
|
||||
FMODULO(dummy, result, (double) SECS_PER_HOUR);
|
||||
break;
|
||||
|
||||
case DTK_MICROSEC:
|
||||
@@ -2460,9 +2459,9 @@ timetz_part(PG_FUNCTION_ARGS)
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("\"time with time zone\" units \"%s\" not recognized",
|
||||
DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(units))))));
|
||||
errmsg("\"time with time zone\" units \"%s\" not recognized",
|
||||
DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(units))))));
|
||||
|
||||
result = 0;
|
||||
}
|
||||
@@ -2479,9 +2478,9 @@ timetz_part(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("\"time with time zone\" units \"%s\" not recognized",
|
||||
DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(units))))));
|
||||
errmsg("\"time with time zone\" units \"%s\" not recognized",
|
||||
DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(units))))));
|
||||
|
||||
result = 0;
|
||||
}
|
||||
@@ -2500,15 +2499,15 @@ timetz_zone(PG_FUNCTION_ARGS)
|
||||
TimeTzADT *t = PG_GETARG_TIMETZADT_P(1);
|
||||
TimeTzADT *result;
|
||||
int tz;
|
||||
char tzname[TZ_STRLEN_MAX + 1];
|
||||
int len;
|
||||
char tzname[TZ_STRLEN_MAX + 1];
|
||||
int len;
|
||||
pg_tz *tzp;
|
||||
|
||||
/*
|
||||
* Look up the requested timezone. First we look in the timezone
|
||||
* database (to handle cases like "America/New_York"), and if that
|
||||
* fails, we look in the date token table (to handle cases like "EST").
|
||||
*/
|
||||
* Look up the requested timezone. First we look in the timezone database
|
||||
* (to handle cases like "America/New_York"), and if that fails, we look
|
||||
* in the date token table (to handle cases like "EST").
|
||||
*/
|
||||
len = Min(VARSIZE(zone) - VARHDRSZ, TZ_STRLEN_MAX);
|
||||
memcpy(tzname, VARDATA(zone), len);
|
||||
tzname[len] = '\0';
|
||||
@@ -2516,7 +2515,7 @@ timetz_zone(PG_FUNCTION_ARGS)
|
||||
if (tzp)
|
||||
{
|
||||
/* Get the offset-from-GMT that is valid today for the selected zone */
|
||||
pg_time_t now;
|
||||
pg_time_t now;
|
||||
struct pg_tm *tm;
|
||||
|
||||
now = time(NULL);
|
||||
@@ -2546,7 +2545,7 @@ timetz_zone(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
||||
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
|
||||
while (result->time < INT64CONST(0))
|
||||
@@ -2582,7 +2581,7 @@ timetz_izone(PG_FUNCTION_ARGS)
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("\"interval\" time zone \"%s\" not valid",
|
||||
DatumGetCString(DirectFunctionCall1(interval_out,
|
||||
PointerGetDatum(zone))))));
|
||||
PointerGetDatum(zone))))));
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
tz = -(zone->time / USECS_PER_SEC);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.159 2005/10/14 11:47:57 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.160 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -28,16 +28,16 @@
|
||||
|
||||
static int DecodeNumber(int flen, char *field, bool haveTextMonth,
|
||||
int fmask, int *tmask,
|
||||
struct pg_tm *tm, fsec_t *fsec, int *is2digits);
|
||||
struct pg_tm * tm, fsec_t *fsec, int *is2digits);
|
||||
static int DecodeNumberField(int len, char *str,
|
||||
int fmask, int *tmask,
|
||||
struct pg_tm *tm, fsec_t *fsec, int *is2digits);
|
||||
struct pg_tm * tm, fsec_t *fsec, int *is2digits);
|
||||
static int DecodeTime(char *str, int fmask, int *tmask,
|
||||
struct pg_tm *tm, fsec_t *fsec);
|
||||
struct pg_tm * tm, fsec_t *fsec);
|
||||
static int DecodeTimezone(char *str, int *tzp);
|
||||
static int DecodePosixTimezone(char *str, int *tzp);
|
||||
static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
|
||||
static int DecodeDate(char *str, int fmask, int *tmask, struct pg_tm *tm);
|
||||
static int DecodeDate(char *str, int fmask, int *tmask, struct pg_tm * tm);
|
||||
static void TrimTrailingZeros(char *str);
|
||||
|
||||
|
||||
@@ -308,8 +308,7 @@ static datetkn datetktbl[] = {
|
||||
{"lhdt", DTZ, POS(44)}, /* Lord Howe Daylight Time, Australia */
|
||||
{"lhst", TZ, POS(42)}, /* Lord Howe Standard Time, Australia */
|
||||
{"ligt", TZ, POS(40)}, /* From Melbourne, Australia */
|
||||
{"lint", TZ, POS(56)}, /* Line Islands Time (Kiribati; +14
|
||||
* hours!) */
|
||||
{"lint", TZ, POS(56)}, /* Line Islands Time (Kiribati; +14 hours!) */
|
||||
{"lkt", TZ, POS(24)}, /* Lanka Time */
|
||||
{"m", UNITS, DTK_MONTH}, /* "month" for ISO input */
|
||||
{"magst", DTZ, POS(48)}, /* Magadan Summer Time */
|
||||
@@ -681,7 +680,7 @@ j2day(int date)
|
||||
* Get the transaction start time ("now()") broken down as a struct pg_tm.
|
||||
*/
|
||||
void
|
||||
GetCurrentDateTime(struct pg_tm *tm)
|
||||
GetCurrentDateTime(struct pg_tm * tm)
|
||||
{
|
||||
int tz;
|
||||
fsec_t fsec;
|
||||
@@ -698,7 +697,7 @@ GetCurrentDateTime(struct pg_tm *tm)
|
||||
* including fractional seconds and timezone offset.
|
||||
*/
|
||||
void
|
||||
GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
|
||||
GetCurrentTimeUsec(struct pg_tm * tm, fsec_t *fsec, int *tzp)
|
||||
{
|
||||
int tz;
|
||||
|
||||
@@ -741,8 +740,8 @@ TrimTrailingZeros(char *str)
|
||||
*
|
||||
* timestr - the input string
|
||||
* workbuf - workspace for field string storage. This must be
|
||||
* larger than the largest legal input for this datetime type --
|
||||
* some additional space will be needed to NUL terminate fields.
|
||||
* larger than the largest legal input for this datetime type --
|
||||
* some additional space will be needed to NUL terminate fields.
|
||||
* buflen - the size of workbuf
|
||||
* field[] - pointers to field strings are returned in this array
|
||||
* ftype[] - field type indicators are returned in this array
|
||||
@@ -776,10 +775,10 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
|
||||
const char *bufend = workbuf + buflen;
|
||||
|
||||
/*
|
||||
* Set the character pointed-to by "bufptr" to "newchar", and
|
||||
* increment "bufptr". "end" gives the end of the buffer -- we
|
||||
* return an error if there is no space left to append a character
|
||||
* to the buffer. Note that "bufptr" is evaluated twice.
|
||||
* Set the character pointed-to by "bufptr" to "newchar", and increment
|
||||
* "bufptr". "end" gives the end of the buffer -- we return an error if
|
||||
* there is no space left to append a character to the buffer. Note that
|
||||
* "bufptr" is evaluated twice.
|
||||
*/
|
||||
#define APPEND_CHAR(bufptr, end, newchar) \
|
||||
do \
|
||||
@@ -835,8 +834,8 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
|
||||
APPEND_CHAR(bufp, bufend, *cp++);
|
||||
|
||||
/*
|
||||
* insist that the delimiters match to get a
|
||||
* three-field date.
|
||||
* insist that the delimiters match to get a three-field
|
||||
* date.
|
||||
*/
|
||||
if (*cp == delim)
|
||||
{
|
||||
@@ -855,8 +854,8 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
|
||||
}
|
||||
|
||||
/*
|
||||
* otherwise, number only and will determine year, month, day,
|
||||
* or concatenated fields later...
|
||||
* otherwise, number only and will determine year, month, day, or
|
||||
* concatenated fields later...
|
||||
*/
|
||||
else
|
||||
ftype[nf] = DTK_NUMBER;
|
||||
@@ -872,8 +871,7 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
|
||||
}
|
||||
|
||||
/*
|
||||
* text? then date string, month, day of week, special, or
|
||||
* timezone
|
||||
* text? then date string, month, day of week, special, or timezone
|
||||
*/
|
||||
else if (isalpha((unsigned char) *cp))
|
||||
{
|
||||
@@ -883,8 +881,8 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
|
||||
APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
|
||||
|
||||
/*
|
||||
* Full date string with leading text month? Could also be a
|
||||
* POSIX time zone...
|
||||
* Full date string with leading text month? Could also be a POSIX
|
||||
* time zone...
|
||||
*/
|
||||
if (*cp == '-' || *cp == '/' || *cp == '.')
|
||||
{
|
||||
@@ -969,13 +967,12 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
|
||||
*/
|
||||
int
|
||||
DecodeDateTime(char **field, int *ftype, int nf,
|
||||
int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp)
|
||||
int *dtype, struct pg_tm * tm, fsec_t *fsec, int *tzp)
|
||||
{
|
||||
int fmask = 0,
|
||||
tmask,
|
||||
type;
|
||||
int ptype = 0; /* "prefix type" for ISO y2001m02d04
|
||||
* format */
|
||||
int ptype = 0; /* "prefix type" for ISO y2001m02d04 format */
|
||||
int i;
|
||||
int val;
|
||||
int dterr;
|
||||
@@ -1054,8 +1051,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
|
||||
/*
|
||||
* Starts with a digit but we already have a time
|
||||
* field? Then we are in trouble with a date and
|
||||
* time already...
|
||||
* field? Then we are in trouble with a date and time
|
||||
* already...
|
||||
*/
|
||||
if ((fmask & DTK_TIME_M) == DTK_TIME_M)
|
||||
return DTERR_BAD_FORMAT;
|
||||
@@ -1070,8 +1067,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
*cp = '\0';
|
||||
|
||||
/*
|
||||
* Then read the rest of the field as a
|
||||
* concatenated time
|
||||
* Then read the rest of the field as a concatenated
|
||||
* time
|
||||
*/
|
||||
dterr = DecodeNumberField(strlen(field[i]), field[i],
|
||||
fmask,
|
||||
@@ -1115,8 +1112,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
* DecodeTime()
|
||||
*/
|
||||
/* test for > 24:00:00 */
|
||||
if (tm->tm_hour > 24 ||
|
||||
(tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)))
|
||||
if (tm->tm_hour > 24 ||
|
||||
(tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)))
|
||||
return DTERR_FIELD_OVERFLOW;
|
||||
break;
|
||||
|
||||
@@ -1132,9 +1129,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
return dterr;
|
||||
|
||||
/*
|
||||
* Already have a time zone? Then maybe this is the
|
||||
* second field of a POSIX time: EST+3 (equivalent to
|
||||
* PST)
|
||||
* Already have a time zone? Then maybe this is the second
|
||||
* field of a POSIX time: EST+3 (equivalent to PST)
|
||||
*/
|
||||
if (i > 0 && (fmask & DTK_M(TZ)) != 0 &&
|
||||
ftype[i - 1] == DTK_TZ &&
|
||||
@@ -1278,7 +1274,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
case DTK_TIME:
|
||||
/* previous field was "t" for ISO time */
|
||||
dterr = DecodeNumberField(strlen(field[i]), field[i],
|
||||
(fmask | DTK_DATE_M),
|
||||
(fmask | DTK_DATE_M),
|
||||
&tmask, tm,
|
||||
fsec, &is2digits);
|
||||
if (dterr < 0)
|
||||
@@ -1316,9 +1312,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
else if (cp != NULL && flen - strlen(cp) > 2)
|
||||
{
|
||||
/*
|
||||
* Interpret as a concatenated date or time Set
|
||||
* the type field to allow decoding other fields
|
||||
* later. Example: 20011223 or 040506
|
||||
* Interpret as a concatenated date or time Set the
|
||||
* type field to allow decoding other fields later.
|
||||
* Example: 20011223 or 040506
|
||||
*/
|
||||
dterr = DecodeNumberField(flen, field[i], fmask,
|
||||
&tmask, tm,
|
||||
@@ -1363,8 +1359,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
{
|
||||
case DTK_CURRENT:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("date/time value \"current\" is no longer supported")));
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("date/time value \"current\" is no longer supported")));
|
||||
|
||||
return DTERR_BAD_FORMAT;
|
||||
break;
|
||||
@@ -1380,7 +1376,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
*dtype = DTK_DATE;
|
||||
GetCurrentDateTime(tm);
|
||||
j2date(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - 1,
|
||||
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||
tm->tm_hour = 0;
|
||||
tm->tm_min = 0;
|
||||
tm->tm_sec = 0;
|
||||
@@ -1400,7 +1396,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
*dtype = DTK_DATE;
|
||||
GetCurrentDateTime(tm);
|
||||
j2date(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1,
|
||||
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||
tm->tm_hour = 0;
|
||||
tm->tm_min = 0;
|
||||
tm->tm_sec = 0;
|
||||
@@ -1425,8 +1421,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
case MONTH:
|
||||
|
||||
/*
|
||||
* already have a (numeric) month? then see if we
|
||||
* can substitute...
|
||||
* already have a (numeric) month? then see if we can
|
||||
* substitute...
|
||||
*/
|
||||
if ((fmask & DTK_M(MONTH)) && !haveTextMonth &&
|
||||
!(fmask & DTK_M(DAY)) && tm->tm_mon >= 1 &&
|
||||
@@ -1442,8 +1438,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
case DTZMOD:
|
||||
|
||||
/*
|
||||
* daylight savings time modifier (solves "MET
|
||||
* DST" syntax)
|
||||
* daylight savings time modifier (solves "MET DST"
|
||||
* syntax)
|
||||
*/
|
||||
tmask |= DTK_M(DTZ);
|
||||
tm->tm_isdst = 1;
|
||||
@@ -1455,8 +1451,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
case DTZ:
|
||||
|
||||
/*
|
||||
* set mask for TZ here _or_ check for DTZ later
|
||||
* when getting default timezone
|
||||
* set mask for TZ here _or_ check for DTZ later when
|
||||
* getting default timezone
|
||||
*/
|
||||
tmask |= DTK_M(TZ);
|
||||
tm->tm_isdst = 1;
|
||||
@@ -1497,9 +1493,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
case ISOTIME:
|
||||
|
||||
/*
|
||||
* This is a filler field "t" indicating that the
|
||||
* next field is time. Try to verify that this is
|
||||
* sensible.
|
||||
* This is a filler field "t" indicating that the next
|
||||
* field is time. Try to verify that this is sensible.
|
||||
*/
|
||||
tmask = 0;
|
||||
|
||||
@@ -1546,8 +1541,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
|
||||
errmsg("inconsistent use of year %04d and \"BC\"",
|
||||
tm->tm_year)));
|
||||
errmsg("inconsistent use of year %04d and \"BC\"",
|
||||
tm->tm_year)));
|
||||
}
|
||||
else if (is2digits)
|
||||
{
|
||||
@@ -1597,9 +1592,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for valid day of month, now that we know for sure the
|
||||
* month and year. Note we don't use MD_FIELD_OVERFLOW here,
|
||||
* since it seems unlikely that "Feb 29" is a YMD-order error.
|
||||
* Check for valid day of month, now that we know for sure the month
|
||||
* and year. Note we don't use MD_FIELD_OVERFLOW here, since it seems
|
||||
* unlikely that "Feb 29" is a YMD-order error.
|
||||
*/
|
||||
if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
|
||||
return DTERR_FIELD_OVERFLOW;
|
||||
@@ -1608,8 +1603,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
if (tzp != NULL && !(fmask & DTK_M(TZ)))
|
||||
{
|
||||
/*
|
||||
* daylight savings time modifier but no standard timezone?
|
||||
* then error
|
||||
* daylight savings time modifier but no standard timezone? then
|
||||
* error
|
||||
*/
|
||||
if (fmask & DTK_M(DTZMOD))
|
||||
return DTERR_BAD_FORMAT;
|
||||
@@ -1634,7 +1629,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
* of mktime(), anyway.
|
||||
*/
|
||||
int
|
||||
DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
|
||||
DetermineTimeZoneOffset(struct pg_tm * tm, pg_tz *tzp)
|
||||
{
|
||||
int date,
|
||||
sec;
|
||||
@@ -1658,15 +1653,15 @@ DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
|
||||
|
||||
/*
|
||||
* First, generate the pg_time_t value corresponding to the given
|
||||
* y/m/d/h/m/s taken as GMT time. If this overflows, punt and decide
|
||||
* the timezone is GMT. (We only need to worry about overflow on
|
||||
* machines where pg_time_t is 32 bits.)
|
||||
* y/m/d/h/m/s taken as GMT time. If this overflows, punt and decide the
|
||||
* timezone is GMT. (We only need to worry about overflow on machines
|
||||
* where pg_time_t is 32 bits.)
|
||||
*/
|
||||
if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
||||
goto overflow;
|
||||
date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - UNIX_EPOCH_JDATE;
|
||||
|
||||
day = ((pg_time_t) date) *SECS_PER_DAY;
|
||||
day = ((pg_time_t) date) * SECS_PER_DAY;
|
||||
if (day / SECS_PER_DAY != date)
|
||||
goto overflow;
|
||||
sec = tm->tm_sec + (tm->tm_min + tm->tm_hour * MINS_PER_HOUR) * SECS_PER_MINUTE;
|
||||
@@ -1676,10 +1671,10 @@ DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
|
||||
goto overflow;
|
||||
|
||||
/*
|
||||
* Find the DST time boundary just before or following the target time.
|
||||
* We assume that all zones have GMT offsets less than 24 hours, and
|
||||
* that DST boundaries can't be closer together than 48 hours, so
|
||||
* backing up 24 hours and finding the "next" boundary will work.
|
||||
* Find the DST time boundary just before or following the target time. We
|
||||
* assume that all zones have GMT offsets less than 24 hours, and that DST
|
||||
* boundaries can't be closer together than 48 hours, so backing up 24
|
||||
* hours and finding the "next" boundary will work.
|
||||
*/
|
||||
prevtime = mytime - SECS_PER_DAY;
|
||||
if (mytime < 0 && prevtime > 0)
|
||||
@@ -1689,7 +1684,7 @@ DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
|
||||
&before_gmtoff, &before_isdst,
|
||||
&boundary,
|
||||
&after_gmtoff, &after_isdst,
|
||||
tzp);
|
||||
tzp);
|
||||
if (res < 0)
|
||||
goto overflow; /* failure? */
|
||||
|
||||
@@ -1697,7 +1692,7 @@ DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
|
||||
{
|
||||
/* Non-DST zone, life is simple */
|
||||
tm->tm_isdst = before_isdst;
|
||||
return - (int) before_gmtoff;
|
||||
return -(int) before_gmtoff;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1722,24 +1717,25 @@ DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
|
||||
if (beforetime <= boundary && aftertime < boundary)
|
||||
{
|
||||
tm->tm_isdst = before_isdst;
|
||||
return - (int) before_gmtoff;
|
||||
return -(int) before_gmtoff;
|
||||
}
|
||||
if (beforetime > boundary && aftertime >= boundary)
|
||||
{
|
||||
tm->tm_isdst = after_isdst;
|
||||
return - (int) after_gmtoff;
|
||||
return -(int) after_gmtoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's an invalid or ambiguous time due to timezone transition.
|
||||
* Prefer the standard-time interpretation.
|
||||
* It's an invalid or ambiguous time due to timezone transition. Prefer
|
||||
* the standard-time interpretation.
|
||||
*/
|
||||
if (after_isdst == 0)
|
||||
{
|
||||
tm->tm_isdst = after_isdst;
|
||||
return - (int) after_gmtoff;
|
||||
return -(int) after_gmtoff;
|
||||
}
|
||||
tm->tm_isdst = before_isdst;
|
||||
return - (int) before_gmtoff;
|
||||
return -(int) before_gmtoff;
|
||||
|
||||
overflow:
|
||||
/* Given date is out of range, so assume UTC */
|
||||
@@ -1762,7 +1758,7 @@ overflow:
|
||||
*/
|
||||
int
|
||||
DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp)
|
||||
int *dtype, struct pg_tm * tm, fsec_t *fsec, int *tzp)
|
||||
{
|
||||
int fmask = 0,
|
||||
tmask,
|
||||
@@ -1792,8 +1788,8 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
case DTK_DATE:
|
||||
|
||||
/*
|
||||
* Time zone not allowed? Then should not accept dates or
|
||||
* time zones no matter what else!
|
||||
* Time zone not allowed? Then should not accept dates or time
|
||||
* zones no matter what else!
|
||||
*/
|
||||
if (tzp == NULL)
|
||||
return DTERR_BAD_FORMAT;
|
||||
@@ -1815,15 +1811,13 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
|
||||
/*
|
||||
* Starts with a digit but we already have a time
|
||||
* field? Then we are in trouble with time
|
||||
* already...
|
||||
* field? Then we are in trouble with time already...
|
||||
*/
|
||||
if ((fmask & DTK_TIME_M) == DTK_TIME_M)
|
||||
return DTERR_BAD_FORMAT;
|
||||
|
||||
/*
|
||||
* Should not get here and fail. Sanity check
|
||||
* only...
|
||||
* Should not get here and fail. Sanity check only...
|
||||
*/
|
||||
if ((cp = strchr(field[i], '-')) == NULL)
|
||||
return DTERR_BAD_FORMAT;
|
||||
@@ -1835,8 +1829,8 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
*cp = '\0';
|
||||
|
||||
/*
|
||||
* Then read the rest of the field as a
|
||||
* concatenated time
|
||||
* Then read the rest of the field as a concatenated
|
||||
* time
|
||||
*/
|
||||
dterr = DecodeNumberField(strlen(field[i]), field[i],
|
||||
(fmask | DTK_DATE_M),
|
||||
@@ -1879,9 +1873,8 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
return dterr;
|
||||
|
||||
/*
|
||||
* Already have a time zone? Then maybe this is the
|
||||
* second field of a POSIX time: EST+3 (equivalent to
|
||||
* PST)
|
||||
* Already have a time zone? Then maybe this is the second
|
||||
* field of a POSIX time: EST+3 (equivalent to PST)
|
||||
*/
|
||||
if (i > 0 && (fmask & DTK_M(TZ)) != 0 &&
|
||||
ftype[i - 1] == DTK_TZ &&
|
||||
@@ -2025,10 +2018,10 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
tmask |= DTK_TIME_M;
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
dt2time(time * USECS_PER_DAY,
|
||||
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||
#else
|
||||
dt2time(time * SECS_PER_DAY,
|
||||
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -2036,7 +2029,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
case DTK_TIME:
|
||||
/* previous field was "t" for ISO time */
|
||||
dterr = DecodeNumberField(strlen(field[i]), field[i],
|
||||
(fmask | DTK_DATE_M),
|
||||
(fmask | DTK_DATE_M),
|
||||
&tmask, tm,
|
||||
fsec, &is2digits);
|
||||
if (dterr < 0)
|
||||
@@ -2080,12 +2073,12 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
else if (flen - strlen(cp) > 2)
|
||||
{
|
||||
/*
|
||||
* Interpret as a concatenated date or time
|
||||
* Set the type field to allow decoding other
|
||||
* fields later. Example: 20011223 or 040506
|
||||
* Interpret as a concatenated date or time Set
|
||||
* the type field to allow decoding other fields
|
||||
* later. Example: 20011223 or 040506
|
||||
*/
|
||||
dterr = DecodeNumberField(flen, field[i],
|
||||
(fmask | DTK_DATE_M),
|
||||
(fmask | DTK_DATE_M),
|
||||
&tmask, tm,
|
||||
fsec, &is2digits);
|
||||
if (dterr < 0)
|
||||
@@ -2133,8 +2126,8 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
{
|
||||
case DTK_CURRENT:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("date/time value \"current\" is no longer supported")));
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("date/time value \"current\" is no longer supported")));
|
||||
return DTERR_BAD_FORMAT;
|
||||
break;
|
||||
|
||||
@@ -2162,8 +2155,8 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
case DTZMOD:
|
||||
|
||||
/*
|
||||
* daylight savings time modifier (solves "MET
|
||||
* DST" syntax)
|
||||
* daylight savings time modifier (solves "MET DST"
|
||||
* syntax)
|
||||
*/
|
||||
tmask |= DTK_M(DTZ);
|
||||
tm->tm_isdst = 1;
|
||||
@@ -2175,8 +2168,8 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
case DTZ:
|
||||
|
||||
/*
|
||||
* set mask for TZ here _or_ check for DTZ later
|
||||
* when getting default timezone
|
||||
* set mask for TZ here _or_ check for DTZ later when
|
||||
* getting default timezone
|
||||
*/
|
||||
tmask |= DTK_M(TZ);
|
||||
tm->tm_isdst = 1;
|
||||
@@ -2247,14 +2240,14 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
|
||||
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||
|
||||
tm->tm_sec < 0 || tm->tm_sec > 60 || tm->tm_hour > 24 ||
|
||||
/* test for > 24:00:00 */
|
||||
(tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0 ||
|
||||
/* test for > 24:00:00 */
|
||||
(tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0 ||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
*fsec > INT64CONST(0))) ||
|
||||
*fsec > INT64CONST(0))) ||
|
||||
*fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
|
||||
return DTERR_FIELD_OVERFLOW;
|
||||
#else
|
||||
*fsec > 0)) ||
|
||||
*fsec > 0)) ||
|
||||
*fsec < 0 || *fsec >= 1)
|
||||
return DTERR_FIELD_OVERFLOW;
|
||||
#endif
|
||||
@@ -2269,8 +2262,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
*tmp = &tt;
|
||||
|
||||
/*
|
||||
* daylight savings time modifier but no standard timezone? then
|
||||
* error
|
||||
* daylight savings time modifier but no standard timezone? then error
|
||||
*/
|
||||
if (fmask & DTK_M(DTZMOD))
|
||||
return DTERR_BAD_FORMAT;
|
||||
@@ -2300,7 +2292,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
* Insist on a complete set of fields.
|
||||
*/
|
||||
static int
|
||||
DecodeDate(char *str, int fmask, int *tmask, struct pg_tm *tm)
|
||||
DecodeDate(char *str, int fmask, int *tmask, struct pg_tm * tm)
|
||||
{
|
||||
fsec_t fsec;
|
||||
int nf = 0;
|
||||
@@ -2458,7 +2450,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct pg_tm *tm)
|
||||
* can be used to represent time spans.
|
||||
*/
|
||||
static int
|
||||
DecodeTime(char *str, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec)
|
||||
DecodeTime(char *str, int fmask, int *tmask, struct pg_tm * tm, fsec_t *fsec)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
@@ -2522,7 +2514,7 @@ DecodeTime(char *str, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec)
|
||||
*/
|
||||
static int
|
||||
DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask,
|
||||
int *tmask, struct pg_tm *tm, fsec_t *fsec, int *is2digits)
|
||||
int *tmask, struct pg_tm * tm, fsec_t *fsec, int *is2digits)
|
||||
{
|
||||
int val;
|
||||
char *cp;
|
||||
@@ -2539,8 +2531,8 @@ DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask,
|
||||
double frac;
|
||||
|
||||
/*
|
||||
* More than two digits before decimal point? Then could be a date
|
||||
* or a run-together time: 2001.360 20011225 040506.789
|
||||
* More than two digits before decimal point? Then could be a date or
|
||||
* a run-together time: 2001.360 20011225 040506.789
|
||||
*/
|
||||
if (cp - str > 2)
|
||||
{
|
||||
@@ -2581,9 +2573,9 @@ DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask,
|
||||
case 0:
|
||||
|
||||
/*
|
||||
* Nothing so far; make a decision about what we think the
|
||||
* input is. There used to be lots of heuristics here, but
|
||||
* the consensus now is to be paranoid. It *must* be either
|
||||
* Nothing so far; make a decision about what we think the input
|
||||
* is. There used to be lots of heuristics here, but the
|
||||
* consensus now is to be paranoid. It *must* be either
|
||||
* YYYY-MM-DD (with a more-than-two-digit year field), or the
|
||||
* field order defined by DateOrder.
|
||||
*/
|
||||
@@ -2614,12 +2606,11 @@ DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask,
|
||||
if (haveTextMonth)
|
||||
{
|
||||
/*
|
||||
* We are at the first numeric field of a date that
|
||||
* included a textual month name. We want to support the
|
||||
* variants MON-DD-YYYY, DD-MON-YYYY, and YYYY-MON-DD as
|
||||
* unambiguous inputs. We will also accept MON-DD-YY or
|
||||
* DD-MON-YY in either DMY or MDY modes, as well as
|
||||
* YY-MON-DD in YMD mode.
|
||||
* We are at the first numeric field of a date that included a
|
||||
* textual month name. We want to support the variants
|
||||
* MON-DD-YYYY, DD-MON-YYYY, and YYYY-MON-DD as unambiguous
|
||||
* inputs. We will also accept MON-DD-YY or DD-MON-YY in
|
||||
* either DMY or MDY modes, as well as YY-MON-DD in YMD mode.
|
||||
*/
|
||||
if (flen >= 3 || DateOrder == DATEORDER_YMD)
|
||||
{
|
||||
@@ -2693,8 +2684,8 @@ DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask,
|
||||
}
|
||||
|
||||
/*
|
||||
* When processing a year field, mark it for adjustment if it's only
|
||||
* one or two digits.
|
||||
* When processing a year field, mark it for adjustment if it's only one
|
||||
* or two digits.
|
||||
*/
|
||||
if (*tmask == DTK_M(YEAR))
|
||||
*is2digits = (flen <= 2);
|
||||
@@ -2712,13 +2703,13 @@ DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask,
|
||||
*/
|
||||
static int
|
||||
DecodeNumberField(int len, char *str, int fmask,
|
||||
int *tmask, struct pg_tm *tm, fsec_t *fsec, int *is2digits)
|
||||
int *tmask, struct pg_tm * tm, fsec_t *fsec, int *is2digits)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
/*
|
||||
* Have a decimal point? Then this is a date or something with a
|
||||
* seconds field...
|
||||
* Have a decimal point? Then this is a date or something with a seconds
|
||||
* field...
|
||||
*/
|
||||
if ((cp = strchr(str, '.')) != NULL)
|
||||
{
|
||||
@@ -2970,7 +2961,7 @@ DecodeSpecial(int field, char *lowtoken, int *val)
|
||||
* preceding an hh:mm:ss field. - thomas 1998-04-30
|
||||
*/
|
||||
int
|
||||
DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec)
|
||||
DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm, fsec_t *fsec)
|
||||
{
|
||||
int is_before = FALSE;
|
||||
char *cp;
|
||||
@@ -3014,9 +3005,9 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, f
|
||||
Assert(*field[i] == '-' || *field[i] == '+');
|
||||
|
||||
/*
|
||||
* A single signed number ends up here, but will be
|
||||
* rejected by DecodeTime(). So, work this out to drop
|
||||
* through to DTK_NUMBER, which *can* tolerate this.
|
||||
* A single signed number ends up here, but will be rejected
|
||||
* by DecodeTime(). So, work this out to drop through to
|
||||
* DTK_NUMBER, which *can* tolerate this.
|
||||
*/
|
||||
cp = field[i] + 1;
|
||||
while (*cp != '\0' && *cp != ':' && *cp != '.')
|
||||
@@ -3035,8 +3026,8 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, f
|
||||
|
||||
/*
|
||||
* Set the next type to be a day, if units are not
|
||||
* specified. This handles the case of '1 +02:03'
|
||||
* since we are reading right to left.
|
||||
* specified. This handles the case of '1 +02:03' since we
|
||||
* are reading right to left.
|
||||
*/
|
||||
type = DTK_DAY;
|
||||
tmask = DTK_M(TZ);
|
||||
@@ -3366,7 +3357,7 @@ DateTimeParseError(int dterr, const char *str, const char *datatype)
|
||||
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
||||
errmsg("date/time field value out of range: \"%s\"",
|
||||
str),
|
||||
errhint("Perhaps you need a different \"datestyle\" setting.")));
|
||||
errhint("Perhaps you need a different \"datestyle\" setting.")));
|
||||
break;
|
||||
case DTERR_INTERVAL_OVERFLOW:
|
||||
ereport(ERROR,
|
||||
@@ -3376,9 +3367,9 @@ DateTimeParseError(int dterr, const char *str, const char *datatype)
|
||||
break;
|
||||
case DTERR_TZDISP_OVERFLOW:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
|
||||
errmsg("time zone displacement out of range: \"%s\"",
|
||||
str)));
|
||||
(errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
|
||||
errmsg("time zone displacement out of range: \"%s\"",
|
||||
str)));
|
||||
break;
|
||||
case DTERR_BAD_FORMAT:
|
||||
default:
|
||||
@@ -3424,7 +3415,7 @@ datebsearch(char *key, datetkn *base, unsigned int nel)
|
||||
* Encode date as local time.
|
||||
*/
|
||||
int
|
||||
EncodeDateOnly(struct pg_tm *tm, int style, char *str)
|
||||
EncodeDateOnly(struct pg_tm * tm, int style, char *str)
|
||||
{
|
||||
if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR)
|
||||
return -1;
|
||||
@@ -3438,7 +3429,7 @@ EncodeDateOnly(struct pg_tm *tm, int style, char *str)
|
||||
tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||
else
|
||||
sprintf(str, "%04d-%02d-%02d %s",
|
||||
-(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
|
||||
-(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
|
||||
break;
|
||||
|
||||
case USE_SQL_DATES:
|
||||
@@ -3484,7 +3475,7 @@ EncodeDateOnly(struct pg_tm *tm, int style, char *str)
|
||||
* Encode time fields only.
|
||||
*/
|
||||
int
|
||||
EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, int *tzp, int style, char *str)
|
||||
EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str)
|
||||
{
|
||||
if (tm->tm_hour < 0 || tm->tm_hour > HOURS_PER_DAY)
|
||||
return -1;
|
||||
@@ -3492,8 +3483,8 @@ EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, int *tzp, int style, char *str)
|
||||
sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min);
|
||||
|
||||
/*
|
||||
* Print fractional seconds if any. The fractional field widths
|
||||
* here should be equal to the larger of MAX_TIME_PRECISION and
|
||||
* Print fractional seconds if any. The fractional field widths here
|
||||
* should be equal to the larger of MAX_TIME_PRECISION and
|
||||
* MAX_TIMESTAMP_PRECISION.
|
||||
*/
|
||||
if (fsec != 0)
|
||||
@@ -3534,15 +3525,15 @@ EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, int *tzp, int style, char *str)
|
||||
* European - dd/mm/yyyy
|
||||
*/
|
||||
int
|
||||
EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str)
|
||||
EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str)
|
||||
{
|
||||
int day,
|
||||
hour,
|
||||
min;
|
||||
|
||||
/*
|
||||
* Why are we checking only the month field? Change this to an
|
||||
* assert... if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR) return -1;
|
||||
* Why are we checking only the month field? Change this to an assert...
|
||||
* if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR) return -1;
|
||||
*/
|
||||
Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
|
||||
|
||||
@@ -3556,11 +3547,11 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
|
||||
|
||||
/*
|
||||
* Print fractional seconds if any. The field widths here
|
||||
* should be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||
* Print fractional seconds if any. The field widths here should
|
||||
* be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||
*
|
||||
* In float mode, don't print fractional seconds before 1 AD,
|
||||
* since it's unlikely there's any precision left ...
|
||||
* In float mode, don't print fractional seconds before 1 AD, since
|
||||
* it's unlikely there's any precision left ...
|
||||
*/
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
if (fsec != 0)
|
||||
@@ -3579,10 +3570,10 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
sprintf(str + strlen(str), ":%02d", tm->tm_sec);
|
||||
|
||||
/*
|
||||
* tzp == NULL indicates that we don't want *any* time zone
|
||||
* info in the output string. *tzn != NULL indicates that we
|
||||
* have alpha time zone info available. tm_isdst != -1
|
||||
* indicates that we have a valid time zone translation.
|
||||
* tzp == NULL indicates that we don't want *any* time zone info
|
||||
* in the output string. *tzn != NULL indicates that we have alpha
|
||||
* time zone info available. tm_isdst != -1 indicates that we have
|
||||
* a valid time zone translation.
|
||||
*/
|
||||
if (tzp != NULL && tm->tm_isdst >= 0)
|
||||
{
|
||||
@@ -3608,11 +3599,11 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
tm->tm_hour, tm->tm_min);
|
||||
|
||||
/*
|
||||
* Print fractional seconds if any. The field widths here
|
||||
* should be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||
* Print fractional seconds if any. The field widths here should
|
||||
* be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||
*
|
||||
* In float mode, don't print fractional seconds before 1 AD,
|
||||
* since it's unlikely there's any precision left ...
|
||||
* In float mode, don't print fractional seconds before 1 AD, since
|
||||
* it's unlikely there's any precision left ...
|
||||
*/
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
if (fsec != 0)
|
||||
@@ -3656,11 +3647,11 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
tm->tm_hour, tm->tm_min);
|
||||
|
||||
/*
|
||||
* Print fractional seconds if any. The field widths here
|
||||
* should be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||
* Print fractional seconds if any. The field widths here should
|
||||
* be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||
*
|
||||
* In float mode, don't print fractional seconds before 1 AD,
|
||||
* since it's unlikely there's any precision left ...
|
||||
* In float mode, don't print fractional seconds before 1 AD, since
|
||||
* it's unlikely there's any precision left ...
|
||||
*/
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
if (fsec != 0)
|
||||
@@ -3703,7 +3694,7 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
|
||||
strncpy(str, days[tm->tm_wday], 3);
|
||||
strcpy(str + 3, " ");
|
||||
|
||||
|
||||
if (DateOrder == DATEORDER_DMY)
|
||||
sprintf(str + 4, "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]);
|
||||
else
|
||||
@@ -3712,11 +3703,11 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
sprintf(str + 10, " %02d:%02d", tm->tm_hour, tm->tm_min);
|
||||
|
||||
/*
|
||||
* Print fractional seconds if any. The field widths here
|
||||
* should be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||
* Print fractional seconds if any. The field widths here should
|
||||
* be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||
*
|
||||
* In float mode, don't print fractional seconds before 1 AD,
|
||||
* since it's unlikely there's any precision left ...
|
||||
* In float mode, don't print fractional seconds before 1 AD, since
|
||||
* it's unlikely there's any precision left ...
|
||||
*/
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
if (fsec != 0)
|
||||
@@ -3735,7 +3726,7 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
sprintf(str + strlen(str), ":%02d", tm->tm_sec);
|
||||
|
||||
sprintf(str + strlen(str), " %04d",
|
||||
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1));
|
||||
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1));
|
||||
|
||||
if (tzp != NULL && tm->tm_isdst >= 0)
|
||||
{
|
||||
@@ -3745,10 +3736,9 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
{
|
||||
/*
|
||||
* We have a time zone, but no string version. Use the
|
||||
* numeric form, but be sure to include a leading
|
||||
* space to avoid formatting something which would be
|
||||
* rejected by the date/time parser later. - thomas
|
||||
* 2001-10-19
|
||||
* numeric form, but be sure to include a leading space to
|
||||
* avoid formatting something which would be rejected by
|
||||
* the date/time parser later. - thomas 2001-10-19
|
||||
*/
|
||||
hour = -(*tzp / SECS_PER_HOUR);
|
||||
min = (abs(*tzp) / MINS_PER_HOUR) % MINS_PER_HOUR;
|
||||
@@ -3774,7 +3764,7 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, int *tzp, char **tzn, int style, c
|
||||
* - thomas 1998-04-30
|
||||
*/
|
||||
int
|
||||
EncodeInterval(struct pg_tm *tm, fsec_t fsec, int style, char *str)
|
||||
EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
|
||||
{
|
||||
int is_before = FALSE;
|
||||
int is_nonzero = FALSE;
|
||||
@@ -3782,9 +3772,8 @@ EncodeInterval(struct pg_tm *tm, fsec_t fsec, int style, char *str)
|
||||
|
||||
/*
|
||||
* The sign of year and month are guaranteed to match, since they are
|
||||
* stored internally as "month". But we'll need to check for is_before
|
||||
* and is_nonzero when determining the signs of hour/minute/seconds
|
||||
* fields.
|
||||
* stored internally as "month". But we'll need to check for is_before and
|
||||
* is_nonzero when determining the signs of hour/minute/seconds fields.
|
||||
*/
|
||||
switch (style)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/datum.c,v 1.30 2004/12/31 22:01:21 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/datum.c,v 1.31 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -179,11 +179,10 @@ datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
|
||||
if (typByVal)
|
||||
{
|
||||
/*
|
||||
* just compare the two datums. NOTE: just comparing "len" bytes
|
||||
* will not do the work, because we do not know how these bytes
|
||||
* are aligned inside the "Datum". We assume instead that any
|
||||
* given datatype is consistent about how it fills extraneous bits
|
||||
* in the Datum.
|
||||
* just compare the two datums. NOTE: just comparing "len" bytes will
|
||||
* not do the work, because we do not know how these bytes are aligned
|
||||
* inside the "Datum". We assume instead that any given datatype is
|
||||
* consistent about how it fills extraneous bits in the Datum.
|
||||
*/
|
||||
res = (value1 == value2);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.5 2005/09/29 22:04:36 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.6 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -31,22 +31,22 @@ static int64
|
||||
db_dir_size(const char *path)
|
||||
{
|
||||
int64 dirsize = 0;
|
||||
struct dirent *direntry;
|
||||
DIR *dirdesc;
|
||||
char filename[MAXPGPATH];
|
||||
struct dirent *direntry;
|
||||
DIR *dirdesc;
|
||||
char filename[MAXPGPATH];
|
||||
|
||||
dirdesc = AllocateDir(path);
|
||||
|
||||
if (!dirdesc)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
while ((direntry = ReadDir(dirdesc, path)) != NULL)
|
||||
{
|
||||
struct stat fst;
|
||||
struct stat fst;
|
||||
|
||||
if (strcmp(direntry->d_name, ".") == 0 ||
|
||||
if (strcmp(direntry->d_name, ".") == 0 ||
|
||||
strcmp(direntry->d_name, "..") == 0)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name);
|
||||
|
||||
@@ -54,8 +54,8 @@ db_dir_size(const char *path)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not stat \"%s\": %m", filename)));
|
||||
|
||||
dirsize += fst.st_size;
|
||||
|
||||
dirsize += fst.st_size;
|
||||
}
|
||||
|
||||
FreeDir(dirdesc);
|
||||
@@ -69,10 +69,10 @@ static int64
|
||||
calculate_database_size(Oid dbOid)
|
||||
{
|
||||
int64 totalsize;
|
||||
DIR *dirdesc;
|
||||
struct dirent *direntry;
|
||||
char dirpath[MAXPGPATH];
|
||||
char pathname[MAXPGPATH];
|
||||
DIR *dirdesc;
|
||||
struct dirent *direntry;
|
||||
char dirpath[MAXPGPATH];
|
||||
char pathname[MAXPGPATH];
|
||||
|
||||
/* Shared storage in pg_global is not counted */
|
||||
|
||||
@@ -84,16 +84,16 @@ calculate_database_size(Oid dbOid)
|
||||
snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc", DataDir);
|
||||
dirdesc = AllocateDir(dirpath);
|
||||
if (!dirdesc)
|
||||
ereport(ERROR,
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not open tablespace directory \"%s\": %m",
|
||||
dirpath)));
|
||||
|
||||
while ((direntry = ReadDir(dirdesc, dirpath)) != NULL)
|
||||
{
|
||||
if (strcmp(direntry->d_name, ".") == 0 ||
|
||||
if (strcmp(direntry->d_name, ".") == 0 ||
|
||||
strcmp(direntry->d_name, "..") == 0)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
snprintf(pathname, MAXPGPATH, "%s/pg_tblspc/%s/%u",
|
||||
DataDir, direntry->d_name, dbOid);
|
||||
@@ -104,7 +104,7 @@ calculate_database_size(Oid dbOid)
|
||||
|
||||
/* Complain if we found no trace of the DB at all */
|
||||
if (!totalsize)
|
||||
ereport(ERROR,
|
||||
ereport(ERROR,
|
||||
(ERRCODE_UNDEFINED_DATABASE,
|
||||
errmsg("database with OID %u does not exist", dbOid)));
|
||||
|
||||
@@ -114,7 +114,7 @@ calculate_database_size(Oid dbOid)
|
||||
Datum
|
||||
pg_database_size_oid(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid dbOid = PG_GETARG_OID(0);
|
||||
Oid dbOid = PG_GETARG_OID(0);
|
||||
|
||||
PG_RETURN_INT64(calculate_database_size(dbOid));
|
||||
}
|
||||
@@ -122,8 +122,8 @@ pg_database_size_oid(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_database_size_name(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Name dbName = PG_GETARG_NAME(0);
|
||||
Oid dbOid = get_database_oid(NameStr(*dbName));
|
||||
Name dbName = PG_GETARG_NAME(0);
|
||||
Oid dbOid = get_database_oid(NameStr(*dbName));
|
||||
|
||||
if (!OidIsValid(dbOid))
|
||||
ereport(ERROR,
|
||||
@@ -141,16 +141,16 @@ pg_database_size_name(PG_FUNCTION_ARGS)
|
||||
static int64
|
||||
calculate_tablespace_size(Oid tblspcOid)
|
||||
{
|
||||
char tblspcPath[MAXPGPATH];
|
||||
char pathname[MAXPGPATH];
|
||||
int64 totalsize=0;
|
||||
DIR *dirdesc;
|
||||
struct dirent *direntry;
|
||||
char tblspcPath[MAXPGPATH];
|
||||
char pathname[MAXPGPATH];
|
||||
int64 totalsize = 0;
|
||||
DIR *dirdesc;
|
||||
struct dirent *direntry;
|
||||
|
||||
if (tblspcOid == DEFAULTTABLESPACE_OID)
|
||||
snprintf(tblspcPath, MAXPGPATH, "%s/base", DataDir);
|
||||
snprintf(tblspcPath, MAXPGPATH, "%s/base", DataDir);
|
||||
else if (tblspcOid == GLOBALTABLESPACE_OID)
|
||||
snprintf(tblspcPath, MAXPGPATH, "%s/global", DataDir);
|
||||
snprintf(tblspcPath, MAXPGPATH, "%s/global", DataDir);
|
||||
else
|
||||
snprintf(tblspcPath, MAXPGPATH, "%s/pg_tblspc/%u", DataDir, tblspcOid);
|
||||
|
||||
@@ -164,11 +164,11 @@ calculate_tablespace_size(Oid tblspcOid)
|
||||
|
||||
while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
|
||||
{
|
||||
struct stat fst;
|
||||
struct stat fst;
|
||||
|
||||
if (strcmp(direntry->d_name, ".") == 0 ||
|
||||
if (strcmp(direntry->d_name, ".") == 0 ||
|
||||
strcmp(direntry->d_name, "..") == 0)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name);
|
||||
|
||||
@@ -178,29 +178,29 @@ calculate_tablespace_size(Oid tblspcOid)
|
||||
errmsg("could not stat \"%s\": %m", pathname)));
|
||||
|
||||
if (fst.st_mode & S_IFDIR)
|
||||
totalsize += db_dir_size(pathname);
|
||||
|
||||
totalsize += fst.st_size;
|
||||
totalsize += db_dir_size(pathname);
|
||||
|
||||
totalsize += fst.st_size;
|
||||
}
|
||||
|
||||
FreeDir(dirdesc);
|
||||
|
||||
|
||||
return totalsize;
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_tablespace_size_oid(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid tblspcOid = PG_GETARG_OID(0);
|
||||
|
||||
Oid tblspcOid = PG_GETARG_OID(0);
|
||||
|
||||
PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_tablespace_size_name(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Name tblspcName = PG_GETARG_NAME(0);
|
||||
Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName));
|
||||
Name tblspcName = PG_GETARG_NAME(0);
|
||||
Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName));
|
||||
|
||||
if (!OidIsValid(tblspcOid))
|
||||
ereport(ERROR,
|
||||
@@ -226,22 +226,22 @@ calculate_relation_size(RelFileNode *rfn)
|
||||
Assert(OidIsValid(rfn->spcNode));
|
||||
|
||||
if (rfn->spcNode == DEFAULTTABLESPACE_OID)
|
||||
snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, rfn->dbNode);
|
||||
snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, rfn->dbNode);
|
||||
else if (rfn->spcNode == GLOBALTABLESPACE_OID)
|
||||
snprintf(dirpath, MAXPGPATH, "%s/global", DataDir);
|
||||
snprintf(dirpath, MAXPGPATH, "%s/global", DataDir);
|
||||
else
|
||||
snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u",
|
||||
snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u",
|
||||
DataDir, rfn->spcNode, rfn->dbNode);
|
||||
|
||||
for (segcount = 0; ; segcount++)
|
||||
for (segcount = 0;; segcount++)
|
||||
{
|
||||
struct stat fst;
|
||||
|
||||
if (segcount == 0)
|
||||
snprintf(pathname, MAXPGPATH, "%s/%u",
|
||||
snprintf(pathname, MAXPGPATH, "%s/%u",
|
||||
dirpath, rfn->relNode);
|
||||
else
|
||||
snprintf(pathname, MAXPGPATH, "%s/%u.%u",
|
||||
snprintf(pathname, MAXPGPATH, "%s/%u.%u",
|
||||
dirpath, rfn->relNode, segcount);
|
||||
|
||||
if (stat(pathname, &fst) < 0)
|
||||
@@ -262,7 +262,7 @@ calculate_relation_size(RelFileNode *rfn)
|
||||
Datum
|
||||
pg_relation_size_oid(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid relOid=PG_GETARG_OID(0);
|
||||
Oid relOid = PG_GETARG_OID(0);
|
||||
Relation rel;
|
||||
int64 size;
|
||||
|
||||
@@ -282,12 +282,12 @@ pg_relation_size_name(PG_FUNCTION_ARGS)
|
||||
RangeVar *relrv;
|
||||
Relation rel;
|
||||
int64 size;
|
||||
|
||||
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
||||
|
||||
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
||||
rel = relation_openrv(relrv, AccessShareLock);
|
||||
|
||||
|
||||
size = calculate_relation_size(&(rel->rd_node));
|
||||
|
||||
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
PG_RETURN_INT64(size);
|
||||
@@ -295,9 +295,9 @@ pg_relation_size_name(PG_FUNCTION_ARGS)
|
||||
|
||||
|
||||
/*
|
||||
* Compute the on-disk size of files for the relation according to the
|
||||
* stat function, optionally including heap data, index data, and/or
|
||||
* toast data.
|
||||
* Compute the on-disk size of files for the relation according to the
|
||||
* stat function, optionally including heap data, index data, and/or
|
||||
* toast data.
|
||||
*/
|
||||
static int64
|
||||
calculate_total_relation_size(Oid Relid)
|
||||
@@ -317,7 +317,7 @@ calculate_total_relation_size(Oid Relid)
|
||||
if (heapRel->rd_rel->relhasindex)
|
||||
{
|
||||
/* recursively include any dependent indexes */
|
||||
List *index_oids = RelationGetIndexList(heapRel);
|
||||
List *index_oids = RelationGetIndexList(heapRel);
|
||||
|
||||
foreach(cell, index_oids)
|
||||
{
|
||||
@@ -344,13 +344,13 @@ calculate_total_relation_size(Oid Relid)
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute on-disk size of files for 'relation' including
|
||||
* heap data, index data, and toasted data.
|
||||
* Compute on-disk size of files for 'relation' including
|
||||
* heap data, index data, and toasted data.
|
||||
*/
|
||||
Datum
|
||||
pg_total_relation_size_oid(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid relid = PG_GETARG_OID(0);
|
||||
Oid relid = PG_GETARG_OID(0);
|
||||
|
||||
PG_RETURN_INT64(calculate_total_relation_size(relid));
|
||||
}
|
||||
@@ -361,10 +361,10 @@ pg_total_relation_size_name(PG_FUNCTION_ARGS)
|
||||
text *relname = PG_GETARG_TEXT_P(0);
|
||||
RangeVar *relrv;
|
||||
Oid relid;
|
||||
|
||||
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
||||
|
||||
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
||||
relid = RangeVarGetRelid(relrv, false);
|
||||
|
||||
|
||||
PG_RETURN_INT64(calculate_total_relation_size(relid));
|
||||
}
|
||||
|
||||
@@ -374,35 +374,35 @@ pg_total_relation_size_name(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_size_pretty(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int64 size = PG_GETARG_INT64(0);
|
||||
char *result = palloc(50 + VARHDRSZ);
|
||||
int64 limit = 10 * 1024;
|
||||
int64 mult = 1;
|
||||
int64 size = PG_GETARG_INT64(0);
|
||||
char *result = palloc(50 + VARHDRSZ);
|
||||
int64 limit = 10 * 1024;
|
||||
int64 mult = 1;
|
||||
|
||||
if (size < limit * mult)
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " bytes", size);
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " bytes", size);
|
||||
else
|
||||
{
|
||||
mult *= 1024;
|
||||
if (size < limit * mult)
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " kB",
|
||||
(size + mult / 2) / mult);
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " kB",
|
||||
(size + mult / 2) / mult);
|
||||
else
|
||||
{
|
||||
mult *= 1024;
|
||||
if (size < limit * mult)
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " MB",
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " MB",
|
||||
(size + mult / 2) / mult);
|
||||
else
|
||||
{
|
||||
mult *= 1024;
|
||||
if (size < limit * mult)
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " GB",
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " GB",
|
||||
(size + mult / 2) / mult);
|
||||
else
|
||||
{
|
||||
mult *= 1024;
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " TB",
|
||||
mult *= 1024;
|
||||
snprintf(VARDATA(result), 50, INT64_FORMAT " TB",
|
||||
(size + mult / 2) / mult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/encode.c,v 1.15 2005/09/24 17:53:15 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/encode.c,v 1.16 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -175,7 +175,7 @@ hex_decode(const char *src, unsigned len, char *dst)
|
||||
if (s >= srcend)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid hexadecimal data: odd number of digits")));
|
||||
errmsg("invalid hexadecimal data: odd number of digits")));
|
||||
|
||||
v2 = get_hex(*s++);
|
||||
*p++ = v1 | v2;
|
||||
@@ -428,8 +428,8 @@ esc_decode(const char *src, unsigned srclen, char *dst)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* One backslash, not followed by ### valid octal. Should
|
||||
* never get here, since esc_dec_len does same check.
|
||||
* One backslash, not followed by ### valid octal. Should never
|
||||
* get here, since esc_dec_len does same check.
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.114 2005/04/06 23:56:07 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.115 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -235,11 +235,11 @@ CheckFloat8Val(double val)
|
||||
if (fabs(val) > FLOAT8_MAX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("type \"double precision\" value out of range: overflow")));
|
||||
errmsg("type \"double precision\" value out of range: overflow")));
|
||||
if (val != 0.0 && fabs(val) < FLOAT8_MIN)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("type \"double precision\" value out of range: underflow")));
|
||||
errmsg("type \"double precision\" value out of range: underflow")));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -258,15 +258,15 @@ float4in(PG_FUNCTION_ARGS)
|
||||
char *endptr;
|
||||
|
||||
/*
|
||||
* endptr points to the first character _after_ the sequence we
|
||||
* recognized as a valid floating point number. orig_num points to the
|
||||
* original input string.
|
||||
* endptr points to the first character _after_ the sequence we recognized
|
||||
* as a valid floating point number. orig_num points to the original input
|
||||
* string.
|
||||
*/
|
||||
orig_num = num;
|
||||
|
||||
/*
|
||||
* Check for an empty-string input to begin with, to avoid the
|
||||
* vagaries of strtod() on different platforms.
|
||||
* Check for an empty-string input to begin with, to avoid the vagaries of
|
||||
* strtod() on different platforms.
|
||||
*/
|
||||
if (*num == '\0')
|
||||
ereport(ERROR,
|
||||
@@ -285,10 +285,9 @@ float4in(PG_FUNCTION_ARGS)
|
||||
if (endptr == num || errno != 0)
|
||||
{
|
||||
/*
|
||||
* C99 requires that strtod() accept NaN and [-]Infinity, but not
|
||||
* all platforms support that yet (and some accept them but set
|
||||
* ERANGE anyway...) Therefore, we check for these inputs
|
||||
* ourselves.
|
||||
* C99 requires that strtod() accept NaN and [-]Infinity, but not all
|
||||
* platforms support that yet (and some accept them but set ERANGE
|
||||
* anyway...) Therefore, we check for these inputs ourselves.
|
||||
*/
|
||||
if (pg_strncasecmp(num, "NaN", 3) == 0)
|
||||
{
|
||||
@@ -320,9 +319,9 @@ float4in(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Many versions of Solaris have a bug wherein strtod sets endptr
|
||||
* to point one byte beyond the end of the string when given "inf"
|
||||
* or "infinity".
|
||||
* Many versions of Solaris have a bug wherein strtod sets endptr to
|
||||
* point one byte beyond the end of the string when given "inf" or
|
||||
* "infinity".
|
||||
*/
|
||||
if (endptr != num && endptr[-1] == '\0')
|
||||
endptr--;
|
||||
@@ -341,8 +340,8 @@ float4in(PG_FUNCTION_ARGS)
|
||||
orig_num)));
|
||||
|
||||
/*
|
||||
* if we get here, we have a legal double, still need to check to see
|
||||
* if it's a legal float4
|
||||
* if we get here, we have a legal double, still need to check to see if
|
||||
* it's a legal float4
|
||||
*/
|
||||
if (!isinf(val))
|
||||
CheckFloat4Val(val);
|
||||
@@ -426,21 +425,21 @@ float8in(PG_FUNCTION_ARGS)
|
||||
char *endptr;
|
||||
|
||||
/*
|
||||
* endptr points to the first character _after_ the sequence we
|
||||
* recognized as a valid floating point number. orig_num points to the
|
||||
* original input string.
|
||||
* endptr points to the first character _after_ the sequence we recognized
|
||||
* as a valid floating point number. orig_num points to the original input
|
||||
* string.
|
||||
*/
|
||||
orig_num = num;
|
||||
|
||||
/*
|
||||
* Check for an empty-string input to begin with, to avoid the
|
||||
* vagaries of strtod() on different platforms.
|
||||
* Check for an empty-string input to begin with, to avoid the vagaries of
|
||||
* strtod() on different platforms.
|
||||
*/
|
||||
if (*num == '\0')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
orig_num)));
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
orig_num)));
|
||||
|
||||
/* skip leading whitespace */
|
||||
while (*num != '\0' && isspace((unsigned char) *num))
|
||||
@@ -453,10 +452,9 @@ float8in(PG_FUNCTION_ARGS)
|
||||
if (endptr == num || errno != 0)
|
||||
{
|
||||
/*
|
||||
* C99 requires that strtod() accept NaN and [-]Infinity, but not
|
||||
* all platforms support that yet (and some accept them but set
|
||||
* ERANGE anyway...) Therefore, we check for these inputs
|
||||
* ourselves.
|
||||
* C99 requires that strtod() accept NaN and [-]Infinity, but not all
|
||||
* platforms support that yet (and some accept them but set ERANGE
|
||||
* anyway...) Therefore, we check for these inputs ourselves.
|
||||
*/
|
||||
if (pg_strncasecmp(num, "NaN", 3) == 0)
|
||||
{
|
||||
@@ -476,21 +474,21 @@ float8in(PG_FUNCTION_ARGS)
|
||||
else if (errno == ERANGE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("\"%s\" is out of range for type double precision",
|
||||
orig_num)));
|
||||
errmsg("\"%s\" is out of range for type double precision",
|
||||
orig_num)));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
orig_num)));
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
orig_num)));
|
||||
}
|
||||
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Many versions of Solaris have a bug wherein strtod sets endptr
|
||||
* to point one byte beyond the end of the string when given "inf"
|
||||
* or "infinity".
|
||||
* Many versions of Solaris have a bug wherein strtod sets endptr to
|
||||
* point one byte beyond the end of the string when given "inf" or
|
||||
* "infinity".
|
||||
*/
|
||||
if (endptr != num && endptr[-1] == '\0')
|
||||
endptr--;
|
||||
@@ -505,8 +503,8 @@ float8in(PG_FUNCTION_ARGS)
|
||||
if (*endptr != '\0')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
orig_num)));
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
orig_num)));
|
||||
|
||||
if (!isinf(val))
|
||||
CheckFloat8Val(val);
|
||||
@@ -860,9 +858,9 @@ static int
|
||||
float4_cmp_internal(float4 a, float4 b)
|
||||
{
|
||||
/*
|
||||
* We consider all NANs to be equal and larger than any non-NAN. This
|
||||
* is somewhat arbitrary; the important thing is to have a consistent
|
||||
* sort order.
|
||||
* We consider all NANs to be equal and larger than any non-NAN. This is
|
||||
* somewhat arbitrary; the important thing is to have a consistent sort
|
||||
* order.
|
||||
*/
|
||||
if (isnan(a))
|
||||
{
|
||||
@@ -956,9 +954,9 @@ static int
|
||||
float8_cmp_internal(float8 a, float8 b)
|
||||
{
|
||||
/*
|
||||
* We consider all NANs to be equal and larger than any non-NAN. This
|
||||
* is somewhat arbitrary; the important thing is to have a consistent
|
||||
* sort order.
|
||||
* We consider all NANs to be equal and larger than any non-NAN. This is
|
||||
* somewhat arbitrary; the important thing is to have a consistent sort
|
||||
* order.
|
||||
*/
|
||||
if (isnan(a))
|
||||
{
|
||||
@@ -1465,8 +1463,8 @@ dpow(PG_FUNCTION_ARGS)
|
||||
float8 result;
|
||||
|
||||
/*
|
||||
* The SQL spec requires that we emit a particular SQLSTATE error code
|
||||
* for certain error conditions.
|
||||
* The SQL spec requires that we emit a particular SQLSTATE error code for
|
||||
* certain error conditions.
|
||||
*/
|
||||
if ((arg1 == 0 && arg2 < 0) ||
|
||||
(arg1 < 0 && floor(arg2) != arg2))
|
||||
@@ -1475,8 +1473,8 @@ dpow(PG_FUNCTION_ARGS)
|
||||
errmsg("invalid argument for power function")));
|
||||
|
||||
/*
|
||||
* We must check both for errno getting set and for a NaN result, in
|
||||
* order to deal with the vagaries of different platforms...
|
||||
* We must check both for errno getting set and for a NaN result, in order
|
||||
* to deal with the vagaries of different platforms...
|
||||
*/
|
||||
errno = 0;
|
||||
result = pow(arg1, arg2);
|
||||
@@ -1504,9 +1502,9 @@ dexp(PG_FUNCTION_ARGS)
|
||||
float8 result;
|
||||
|
||||
/*
|
||||
* We must check both for errno getting set and for a NaN result, in
|
||||
* order to deal with the vagaries of different platforms. Also, a
|
||||
* zero result implies unreported underflow.
|
||||
* We must check both for errno getting set and for a NaN result, in order
|
||||
* to deal with the vagaries of different platforms. Also, a zero result
|
||||
* implies unreported underflow.
|
||||
*/
|
||||
errno = 0;
|
||||
result = exp(arg1);
|
||||
@@ -1534,8 +1532,8 @@ dlog1(PG_FUNCTION_ARGS)
|
||||
float8 result;
|
||||
|
||||
/*
|
||||
* Emit particular SQLSTATE error codes for ln(). This is required by
|
||||
* the SQL standard.
|
||||
* Emit particular SQLSTATE error codes for ln(). This is required by the
|
||||
* SQL standard.
|
||||
*/
|
||||
if (arg1 == 0.0)
|
||||
ereport(ERROR,
|
||||
@@ -1563,9 +1561,9 @@ dlog10(PG_FUNCTION_ARGS)
|
||||
float8 result;
|
||||
|
||||
/*
|
||||
* Emit particular SQLSTATE error codes for log(). The SQL spec
|
||||
* doesn't define log(), but it does define ln(), so it makes sense to
|
||||
* emit the same error code for an analogous error condition.
|
||||
* Emit particular SQLSTATE error codes for log(). The SQL spec doesn't
|
||||
* define log(), but it does define ln(), so it makes sense to emit the
|
||||
* same error code for an analogous error condition.
|
||||
*/
|
||||
if (arg1 == 0.0)
|
||||
ereport(ERROR,
|
||||
@@ -1914,9 +1912,8 @@ float8_accum(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* If we're invoked by nodeAgg, we can cheat and modify our first
|
||||
* parameter in-place to reduce palloc overhead. Otherwise we
|
||||
* construct a new array with the updated transition data and
|
||||
* return it.
|
||||
* parameter in-place to reduce palloc overhead. Otherwise we construct a
|
||||
* new array with the updated transition data and return it.
|
||||
*/
|
||||
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||
{
|
||||
@@ -1937,7 +1934,7 @@ float8_accum(PG_FUNCTION_ARGS)
|
||||
|
||||
result = construct_array(transdatums, 3,
|
||||
FLOAT8OID,
|
||||
sizeof(float8), false /* float8 byval */ , 'd');
|
||||
sizeof(float8), false /* float8 byval */ , 'd');
|
||||
|
||||
PG_RETURN_ARRAYTYPE_P(result);
|
||||
}
|
||||
@@ -1968,9 +1965,8 @@ float4_accum(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* If we're invoked by nodeAgg, we can cheat and modify our first
|
||||
* parameter in-place to reduce palloc overhead. Otherwise we
|
||||
* construct a new array with the updated transition data and
|
||||
* return it.
|
||||
* parameter in-place to reduce palloc overhead. Otherwise we construct a
|
||||
* new array with the updated transition data and return it.
|
||||
*/
|
||||
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||
{
|
||||
@@ -1991,7 +1987,7 @@ float4_accum(PG_FUNCTION_ARGS)
|
||||
|
||||
result = construct_array(transdatums, 3,
|
||||
FLOAT8OID,
|
||||
sizeof(float8), false /* float8 byval */ , 'd');
|
||||
sizeof(float8), false /* float8 byval */ , 'd');
|
||||
|
||||
PG_RETURN_ARRAYTYPE_P(result);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.40 2005/03/29 00:17:08 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.41 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -138,12 +138,12 @@ format_type_internal(Oid type_oid, int32 typemod,
|
||||
typeform = (Form_pg_type) GETSTRUCT(tuple);
|
||||
|
||||
/*
|
||||
* Check if it's an array (and not a domain --- we don't want to show
|
||||
* the substructure of a domain type). Fixed-length array types such
|
||||
* as "name" shouldn't get deconstructed either. As of Postgres 8.1,
|
||||
* rather than checking typlen we check the toast property, and don't
|
||||
* deconstruct "plain storage" array types --- this is because we don't
|
||||
* want to show oidvector as oid[].
|
||||
* Check if it's an array (and not a domain --- we don't want to show the
|
||||
* substructure of a domain type). Fixed-length array types such as
|
||||
* "name" shouldn't get deconstructed either. As of Postgres 8.1, rather
|
||||
* than checking typlen we check the toast property, and don't deconstruct
|
||||
* "plain storage" array types --- this is because we don't want to show
|
||||
* oidvector as oid[].
|
||||
*/
|
||||
array_base_type = typeform->typelem;
|
||||
|
||||
@@ -171,14 +171,14 @@ format_type_internal(Oid type_oid, int32 typemod,
|
||||
is_array = false;
|
||||
|
||||
/*
|
||||
* See if we want to special-case the output for certain built-in
|
||||
* types. Note that these special cases should all correspond to
|
||||
* special productions in gram.y, to ensure that the type name will be
|
||||
* taken as a system type, not a user type of the same name.
|
||||
* See if we want to special-case the output for certain built-in types.
|
||||
* Note that these special cases should all correspond to special
|
||||
* productions in gram.y, to ensure that the type name will be taken as a
|
||||
* system type, not a user type of the same name.
|
||||
*
|
||||
* If we do not provide a special-case output here, the type name will be
|
||||
* handled the same way as a user type name --- in particular, it will
|
||||
* be double-quoted if it matches any lexer keyword. This behavior is
|
||||
* handled the same way as a user type name --- in particular, it will be
|
||||
* double-quoted if it matches any lexer keyword. This behavior is
|
||||
* essential for some cases, such as types "bit" and "char".
|
||||
*/
|
||||
buf = NULL; /* flag for no special case */
|
||||
@@ -193,8 +193,8 @@ format_type_internal(Oid type_oid, int32 typemod,
|
||||
{
|
||||
/*
|
||||
* bit with typmod -1 is not the same as BIT, which means
|
||||
* BIT(1) per SQL spec. Report it as the quoted typename
|
||||
* so that parser will not assign a bogus typmod.
|
||||
* BIT(1) per SQL spec. Report it as the quoted typename so
|
||||
* that parser will not assign a bogus typmod.
|
||||
*/
|
||||
}
|
||||
else
|
||||
@@ -212,9 +212,9 @@ format_type_internal(Oid type_oid, int32 typemod,
|
||||
else if (typemod_given)
|
||||
{
|
||||
/*
|
||||
* bpchar with typmod -1 is not the same as CHARACTER,
|
||||
* which means CHARACTER(1) per SQL spec. Report it as
|
||||
* bpchar so that parser will not assign a bogus typmod.
|
||||
* bpchar with typmod -1 is not the same as CHARACTER, which
|
||||
* means CHARACTER(1) per SQL spec. Report it as bpchar so
|
||||
* that parser will not assign a bogus typmod.
|
||||
*/
|
||||
}
|
||||
else
|
||||
@@ -382,9 +382,9 @@ format_type_internal(Oid type_oid, int32 typemod,
|
||||
{
|
||||
/*
|
||||
* Default handling: report the name as it appears in the catalog.
|
||||
* Here, we must qualify the name if it is not visible in the
|
||||
* search path, and we must double-quote it if it's not a standard
|
||||
* identifier or if it matches any keyword.
|
||||
* Here, we must qualify the name if it is not visible in the search
|
||||
* path, and we must double-quote it if it's not a standard identifier
|
||||
* or if it matches any keyword.
|
||||
*/
|
||||
char *nspname;
|
||||
char *typname;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
* formatting.c
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.99 2005/08/18 13:43:08 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.100 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group
|
||||
@@ -135,9 +135,9 @@ typedef struct
|
||||
{
|
||||
const char *name; /* keyword */
|
||||
int len; /* keyword length */
|
||||
int (*action) (int arg, char *inout, /* action for keyword */
|
||||
int suf, bool is_to_char, bool is_interval,
|
||||
FormatNode *node, void *data);
|
||||
int (*action) (int arg, char *inout, /* action for keyword */
|
||||
int suf, bool is_to_char, bool is_interval,
|
||||
FormatNode *node, void *data);
|
||||
int id; /* keyword id */
|
||||
bool isitdigit; /* is expected output/input digit */
|
||||
} KeyWord;
|
||||
@@ -252,7 +252,7 @@ static char *numth[] = {"st", "nd", "rd", "th", NULL};
|
||||
* Flags for DCH version
|
||||
* ----------
|
||||
*/
|
||||
static bool DCH_global_fx = false;
|
||||
static bool DCH_global_fx = false;
|
||||
|
||||
|
||||
/* ----------
|
||||
@@ -379,7 +379,7 @@ typedef struct
|
||||
q,
|
||||
j,
|
||||
us,
|
||||
yysz; /* is it YY or YYYY ? */
|
||||
yysz; /* is it YY or YYYY ? */
|
||||
} TmFromChar;
|
||||
|
||||
#define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
|
||||
@@ -442,17 +442,17 @@ do { \
|
||||
errmsg("invalid format specification for an interval value"), \
|
||||
errhint("Intervals are not tied to specific calendar dates."))); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* KeyWords definition & action
|
||||
*****************************************************************************/
|
||||
|
||||
static int dch_global(int arg, char *inout, int suf, bool is_to_char,
|
||||
bool is_interval, FormatNode *node, void *data);
|
||||
static int dch_time(int arg, char *inout, int suf, bool is_to_char,
|
||||
bool is_interval, FormatNode *node, void *data);
|
||||
static int dch_date(int arg, char *inout, int suf, bool is_to_char,
|
||||
bool is_interval, FormatNode *node, void *data);
|
||||
static int dch_global(int arg, char *inout, int suf, bool is_to_char,
|
||||
bool is_interval, FormatNode *node, void *data);
|
||||
static int dch_time(int arg, char *inout, int suf, bool is_to_char,
|
||||
bool is_interval, FormatNode *node, void *data);
|
||||
static int dch_date(int arg, char *inout, int suf, bool is_to_char,
|
||||
bool is_interval, FormatNode *node, void *data);
|
||||
|
||||
/* ----------
|
||||
* Suffixes:
|
||||
@@ -803,7 +803,7 @@ static const KeyWord NUM_keywords[] = {
|
||||
* KeyWords index for DATE-TIME version
|
||||
* ----------
|
||||
*/
|
||||
static const int DCH_index[KeyWord_INDEX_SIZE] = {
|
||||
static const int DCH_index[KeyWord_INDEX_SIZE] = {
|
||||
/*
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
*/
|
||||
@@ -827,7 +827,7 @@ static const int DCH_index[KeyWord_INDEX_SIZE] = {
|
||||
* KeyWords index for NUMBER version
|
||||
* ----------
|
||||
*/
|
||||
static const int NUM_index[KeyWord_INDEX_SIZE] = {
|
||||
static const int NUM_index[KeyWord_INDEX_SIZE] = {
|
||||
/*
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
*/
|
||||
@@ -871,8 +871,7 @@ typedef struct NUMProc
|
||||
*number_p, /* pointer to current number position */
|
||||
*inout, /* in / out buffer */
|
||||
*inout_p, /* pointer to current inout position */
|
||||
*last_relevant, /* last relevant number after decimal
|
||||
* point */
|
||||
*last_relevant, /* last relevant number after decimal point */
|
||||
|
||||
*L_negative_sign, /* Locale */
|
||||
*L_positive_sign,
|
||||
@@ -887,13 +886,13 @@ typedef struct NUMProc
|
||||
* ----------
|
||||
*/
|
||||
static const KeyWord *index_seq_search(char *str, const KeyWord *kw,
|
||||
const int *index);
|
||||
const int *index);
|
||||
static KeySuffix *suff_search(char *str, KeySuffix *suf, int type);
|
||||
static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
|
||||
static void parse_format(FormatNode *node, char *str, const KeyWord *kw,
|
||||
KeySuffix *suf, const int *index, int ver, NUMDesc *Num);
|
||||
static char *DCH_processor(FormatNode *node, char *inout, bool is_to_char,
|
||||
bool is_interval, void *data);
|
||||
bool is_interval, void *data);
|
||||
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
static void dump_index(const KeyWord *k, const int *index);
|
||||
@@ -909,7 +908,7 @@ static char *str_tolower(char *buff);
|
||||
/* static int is_acdc(char *str, int *len); */
|
||||
static int seq_search(char *name, char **array, int type, int max, int *len);
|
||||
static void do_to_timestamp(text *date_txt, text *fmt,
|
||||
struct pg_tm *tm, fsec_t *fsec);
|
||||
struct pg_tm * tm, fsec_t *fsec);
|
||||
static char *fill_str(char *str, int c, int max);
|
||||
static FormatNode *NUM_cache(int len, NUMDesc *Num, char *pars_str, bool *shouldFree);
|
||||
static char *int_to_roman(int number);
|
||||
@@ -1047,7 +1046,7 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
|
||||
NUM_cache_remove(last_NUMCacheEntry);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("cannot use \"V\" and decimal point together")));
|
||||
errmsg("cannot use \"V\" and decimal point together")));
|
||||
}
|
||||
num->flag |= NUM_F_DECIMAL;
|
||||
break;
|
||||
@@ -1152,7 +1151,7 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
|
||||
NUM_cache_remove(last_NUMCacheEntry);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("cannot use \"V\" and decimal point together")));
|
||||
errmsg("cannot use \"V\" and decimal point together")));
|
||||
}
|
||||
num->flag |= NUM_F_MULTI;
|
||||
break;
|
||||
@@ -1324,11 +1323,11 @@ DCH_processor(FormatNode *node, char *inout, bool is_to_char,
|
||||
if (!is_to_char && *s == '\0')
|
||||
|
||||
/*
|
||||
* The input string is shorter than format picture, so it's
|
||||
* good time to break this loop...
|
||||
* The input string is shorter than format picture, so it's good
|
||||
* time to break this loop...
|
||||
*
|
||||
* Note: this isn't relevant for TO_CHAR mode, beacuse it use
|
||||
* 'inout' allocated by format picture length.
|
||||
* Note: this isn't relevant for TO_CHAR mode, beacuse it use 'inout'
|
||||
* allocated by format picture length.
|
||||
*/
|
||||
break;
|
||||
|
||||
@@ -1393,7 +1392,7 @@ dump_node(FormatNode *node, int max)
|
||||
{
|
||||
if (n->type == NODE_TYPE_ACTION)
|
||||
elog(DEBUG_elog_output, "%d:\t NODE_TYPE_ACTION '%s'\t(%s,%s)",
|
||||
a, n->key->name, DUMP_THth(n->suffix), DUMP_FM(n->suffix));
|
||||
a, n->key->name, DUMP_THth(n->suffix), DUMP_FM(n->suffix));
|
||||
else if (n->type == NODE_TYPE_CHAR)
|
||||
elog(DEBUG_elog_output, "%d:\t NODE_TYPE_CHAR '%c'", a, n->character);
|
||||
else if (n->type == NODE_TYPE_END)
|
||||
@@ -1578,8 +1577,8 @@ seq_search(char *name, char **array, int type, int max, int *len)
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
|
||||
/*
|
||||
* elog(DEBUG_elog_output, "N: %c, P: %c, A: %s (%s)", *n, *p,
|
||||
* *a, name);
|
||||
* elog(DEBUG_elog_output, "N: %c, P: %c, A: %s (%s)", *n, *p, *a,
|
||||
* name);
|
||||
*/
|
||||
#endif
|
||||
if (*n != *p)
|
||||
@@ -1637,7 +1636,7 @@ dump_index(const KeyWord *k, const int *index)
|
||||
*/
|
||||
static int
|
||||
dch_global(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
FormatNode *node, void *data)
|
||||
FormatNode *node, void *data)
|
||||
{
|
||||
if (arg == DCH_FX)
|
||||
DCH_global_fx = true;
|
||||
@@ -1704,7 +1703,7 @@ strdigits_len(char *str)
|
||||
*/
|
||||
static int
|
||||
dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
FormatNode *node, void *data)
|
||||
FormatNode *node, void *data)
|
||||
{
|
||||
char *p_inout = inout;
|
||||
struct pg_tm *tm = NULL;
|
||||
@@ -1727,7 +1726,7 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
if (is_to_char)
|
||||
{
|
||||
strcpy(inout, ((tm->tm_hour > 11
|
||||
&& tm->tm_hour < HOURS_PER_DAY) ? P_M_STR : A_M_STR));
|
||||
&& tm->tm_hour < HOURS_PER_DAY) ? P_M_STR : A_M_STR));
|
||||
return strlen(p_inout);
|
||||
}
|
||||
else
|
||||
@@ -1747,7 +1746,7 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
if (is_to_char)
|
||||
{
|
||||
strcpy(inout, ((tm->tm_hour > 11
|
||||
&& tm->tm_hour < HOURS_PER_DAY) ? PM_STR : AM_STR));
|
||||
&& tm->tm_hour < HOURS_PER_DAY) ? PM_STR : AM_STR));
|
||||
return strlen(p_inout);
|
||||
}
|
||||
else
|
||||
@@ -1767,7 +1766,7 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
if (is_to_char)
|
||||
{
|
||||
strcpy(inout, ((tm->tm_hour > 11
|
||||
&& tm->tm_hour < HOURS_PER_DAY) ? p_m_STR : a_m_STR));
|
||||
&& tm->tm_hour < HOURS_PER_DAY) ? p_m_STR : a_m_STR));
|
||||
return strlen(p_inout);
|
||||
}
|
||||
else
|
||||
@@ -1787,7 +1786,7 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
if (is_to_char)
|
||||
{
|
||||
strcpy(inout, ((tm->tm_hour > 11
|
||||
&& tm->tm_hour < HOURS_PER_DAY) ? pm_STR : am_STR));
|
||||
&& tm->tm_hour < HOURS_PER_DAY) ? pm_STR : am_STR));
|
||||
return strlen(p_inout);
|
||||
}
|
||||
else
|
||||
@@ -1925,15 +1924,13 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
}
|
||||
|
||||
/*
|
||||
* 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not
|
||||
* 0.25
|
||||
* 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not 0.25
|
||||
*/
|
||||
tmfc->ms *= x == 1 ? 100 :
|
||||
x == 2 ? 10 : 1;
|
||||
|
||||
/*
|
||||
* elog(DEBUG3, "X: %d, MS: %d, LEN: %d", x, tmfc->ms,
|
||||
* len);
|
||||
* elog(DEBUG3, "X: %d, MS: %d, LEN: %d", x, tmfc->ms, len);
|
||||
*/
|
||||
return len + SKIP_THth(suf);
|
||||
}
|
||||
@@ -1974,8 +1971,7 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
x == 5 ? 10 : 1;
|
||||
|
||||
/*
|
||||
* elog(DEBUG3, "X: %d, US: %d, LEN: %d", x, tmfc->us,
|
||||
* len);
|
||||
* elog(DEBUG3, "X: %d, US: %d, LEN: %d", x, tmfc->us, len);
|
||||
*/
|
||||
return len + SKIP_THth(suf);
|
||||
}
|
||||
@@ -2049,7 +2045,7 @@ do { \
|
||||
*/
|
||||
static int
|
||||
dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
FormatNode *node, void *data)
|
||||
FormatNode *node, void *data)
|
||||
{
|
||||
char buff[DCH_CACHE_SIZE],
|
||||
workbuff[32],
|
||||
@@ -2069,8 +2065,8 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
tmfc = (TmFromChar *) data;
|
||||
|
||||
/*
|
||||
* In the FROM-char is not difference between "January" or "JANUARY"
|
||||
* or "january", all is before search convert to "first-upper". This
|
||||
* In the FROM-char is not difference between "January" or "JANUARY" or
|
||||
* "january", all is before search convert to "first-upper". This
|
||||
* convention is used for MONTH, MON, DAY, DY
|
||||
*/
|
||||
if (!is_to_char)
|
||||
@@ -2193,7 +2189,7 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
return strlen(p_inout);
|
||||
|
||||
case DCH_MON:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
if (!tm->tm_mon)
|
||||
return -1;
|
||||
strcpy(inout, months[tm->tm_mon - 1]);
|
||||
@@ -2201,14 +2197,14 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
return strlen(p_inout);
|
||||
|
||||
case DCH_Mon:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
if (!tm->tm_mon)
|
||||
return -1;
|
||||
strcpy(inout, months[tm->tm_mon - 1]);
|
||||
return strlen(p_inout);
|
||||
|
||||
case DCH_mon:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
if (!tm->tm_mon)
|
||||
return -1;
|
||||
strcpy(inout, months[tm->tm_mon - 1]);
|
||||
@@ -2238,38 +2234,38 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
}
|
||||
break;
|
||||
case DCH_DAY:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
strcpy(workbuff, days[tm->tm_wday]);
|
||||
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(workbuff));
|
||||
return strlen(p_inout);
|
||||
|
||||
case DCH_Day:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]);
|
||||
return strlen(p_inout);
|
||||
|
||||
case DCH_day:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]);
|
||||
*inout = pg_tolower((unsigned char) *inout);
|
||||
return strlen(p_inout);
|
||||
|
||||
case DCH_DY:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
strcpy(inout, days[tm->tm_wday]);
|
||||
str_toupper(inout);
|
||||
return 3; /* truncate */
|
||||
return 3; /* truncate */
|
||||
|
||||
case DCH_Dy:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
strcpy(inout, days[tm->tm_wday]);
|
||||
return 3; /* truncate */
|
||||
return 3; /* truncate */
|
||||
|
||||
case DCH_dy:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
strcpy(inout, days[tm->tm_wday]);
|
||||
*inout = pg_tolower((unsigned char) *inout);
|
||||
return 3; /* truncate */
|
||||
return 3; /* truncate */
|
||||
|
||||
case DCH_DDD:
|
||||
if (is_to_char)
|
||||
@@ -2316,7 +2312,7 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
}
|
||||
break;
|
||||
case DCH_D:
|
||||
INVALID_FOR_INTERVAL;
|
||||
INVALID_FOR_INTERVAL;
|
||||
if (is_to_char)
|
||||
{
|
||||
sprintf(inout, "%d", tm->tm_wday + 1);
|
||||
@@ -2357,7 +2353,7 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
if (is_to_char)
|
||||
{
|
||||
sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
|
||||
date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
|
||||
date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
|
||||
if (S_THth(suf))
|
||||
str_numth(p_inout, inout, S_TH_TYPE(suf));
|
||||
return strlen(p_inout);
|
||||
@@ -2447,17 +2443,17 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
arg == DCH_YYYY ?
|
||||
ADJUST_YEAR(tm->tm_year, is_interval) :
|
||||
ADJUST_YEAR(date2isoyear(
|
||||
tm->tm_year,
|
||||
tm->tm_mon,
|
||||
tm->tm_mday), is_interval));
|
||||
tm->tm_year,
|
||||
tm->tm_mon,
|
||||
tm->tm_mday), is_interval));
|
||||
else
|
||||
sprintf(inout, "%d",
|
||||
arg == DCH_YYYY ?
|
||||
ADJUST_YEAR(tm->tm_year, is_interval) :
|
||||
ADJUST_YEAR(date2isoyear(
|
||||
tm->tm_year,
|
||||
tm->tm_mon,
|
||||
tm->tm_mday), is_interval));
|
||||
tm->tm_year,
|
||||
tm->tm_mon,
|
||||
tm->tm_mday), is_interval));
|
||||
if (S_THth(suf))
|
||||
str_numth(p_inout, inout, S_TH_TYPE(suf));
|
||||
return strlen(p_inout);
|
||||
@@ -2486,8 +2482,8 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
arg == DCH_YYY ?
|
||||
ADJUST_YEAR(tm->tm_year, is_interval) :
|
||||
ADJUST_YEAR(date2isoyear(tm->tm_year,
|
||||
tm->tm_mon, tm->tm_mday),
|
||||
is_interval));
|
||||
tm->tm_mon, tm->tm_mday),
|
||||
is_interval));
|
||||
i = strlen(buff);
|
||||
strcpy(inout, buff + (i - 3));
|
||||
if (S_THth(suf))
|
||||
@@ -2518,8 +2514,8 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
arg == DCH_YY ?
|
||||
ADJUST_YEAR(tm->tm_year, is_interval) :
|
||||
ADJUST_YEAR(date2isoyear(tm->tm_year,
|
||||
tm->tm_mon, tm->tm_mday),
|
||||
is_interval));
|
||||
tm->tm_mon, tm->tm_mday),
|
||||
is_interval));
|
||||
i = strlen(buff);
|
||||
strcpy(inout, buff + (i - 2));
|
||||
if (S_THth(suf))
|
||||
@@ -2531,8 +2527,8 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
sscanf(inout, "%02d", &tmfc->year);
|
||||
|
||||
/*
|
||||
* 2-digit year: '00' ... '69' = 2000 ... 2069 '70' ...
|
||||
* '99' = 1970 ... 1999
|
||||
* 2-digit year: '00' ... '69' = 2000 ... 2069 '70' ... '99'
|
||||
* = 1970 ... 1999
|
||||
*/
|
||||
if (tmfc->year < 70)
|
||||
tmfc->year += 2000;
|
||||
@@ -2550,8 +2546,8 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
|
||||
arg == DCH_Y ?
|
||||
ADJUST_YEAR(tm->tm_year, is_interval) :
|
||||
ADJUST_YEAR(date2isoyear(tm->tm_year,
|
||||
tm->tm_mon, tm->tm_mday),
|
||||
is_interval));
|
||||
tm->tm_mon, tm->tm_mday),
|
||||
is_interval));
|
||||
i = strlen(buff);
|
||||
strcpy(inout, buff + (i - 1));
|
||||
if (S_THth(suf))
|
||||
@@ -2751,8 +2747,8 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
|
||||
result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
|
||||
|
||||
/*
|
||||
* Allocate new memory if format picture is bigger than static cache
|
||||
* and not use cache (call parser always)
|
||||
* Allocate new memory if format picture is bigger than static cache and
|
||||
* not use cache (call parser always)
|
||||
*/
|
||||
if (fmt_len > DCH_CACHE_SIZE)
|
||||
{
|
||||
@@ -2778,8 +2774,8 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
|
||||
ent = DCH_cache_getnew(fmt_str);
|
||||
|
||||
/*
|
||||
* Not in the cache, must run parser and save a new
|
||||
* format-picture to the cache.
|
||||
* Not in the cache, must run parser and save a new format-picture
|
||||
* to the cache.
|
||||
*/
|
||||
parse_format(ent->format, fmt_str, DCH_keywords,
|
||||
DCH_suff, DCH_index, DCH_TYPE, NULL);
|
||||
@@ -2802,8 +2798,8 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
|
||||
pfree(fmt_str);
|
||||
|
||||
/*
|
||||
* for result is allocated max memory, which current format-picture
|
||||
* needs, now it allocate result with real size
|
||||
* for result is allocated max memory, which current format-picture needs,
|
||||
* now it allocate result with real size
|
||||
*/
|
||||
if (result && *result)
|
||||
{
|
||||
@@ -2965,7 +2961,7 @@ to_date(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
static void
|
||||
do_to_timestamp(text *date_txt, text *fmt,
|
||||
struct pg_tm *tm, fsec_t *fsec)
|
||||
struct pg_tm * tm, fsec_t *fsec)
|
||||
{
|
||||
FormatNode *format;
|
||||
TmFromChar tmfc;
|
||||
@@ -2990,8 +2986,8 @@ do_to_timestamp(text *date_txt, text *fmt,
|
||||
*(fmt_str + fmt_len) = '\0';
|
||||
|
||||
/*
|
||||
* Allocate new memory if format picture is bigger than static
|
||||
* cache and not use cache (call parser always)
|
||||
* Allocate new memory if format picture is bigger than static cache
|
||||
* and not use cache (call parser always)
|
||||
*/
|
||||
if (fmt_len > DCH_CACHE_SIZE)
|
||||
{
|
||||
@@ -3059,8 +3055,8 @@ do_to_timestamp(text *date_txt, text *fmt,
|
||||
DEBUG_TMFC(&tmfc);
|
||||
|
||||
/*
|
||||
* Convert values that user define for FROM_CHAR
|
||||
* (to_date/to_timestamp) to standard 'tm'
|
||||
* Convert values that user define for FROM_CHAR (to_date/to_timestamp) to
|
||||
* standard 'tm'
|
||||
*/
|
||||
if (tmfc.ssss)
|
||||
{
|
||||
@@ -3125,18 +3121,19 @@ do_to_timestamp(text *date_txt, text *fmt,
|
||||
|
||||
if (tmfc.year)
|
||||
{
|
||||
if (tmfc.yysz==2 && tmfc.cc)
|
||||
if (tmfc.yysz == 2 && tmfc.cc)
|
||||
{
|
||||
/* CC and YY defined
|
||||
* why -[2000|1900]? See dch_date() DCH_YY code.
|
||||
/*
|
||||
* CC and YY defined why -[2000|1900]? See dch_date() DCH_YY code.
|
||||
*/
|
||||
tm->tm_year = (tmfc.cc-1)*100 + (tmfc.year >= 2000 ? tmfc.year-2000 : tmfc.year-1900);
|
||||
tm->tm_year = (tmfc.cc - 1) * 100 + (tmfc.year >= 2000 ? tmfc.year - 2000 : tmfc.year - 1900);
|
||||
}
|
||||
else if (tmfc.yysz==1 && tmfc.cc)
|
||||
else if (tmfc.yysz == 1 && tmfc.cc)
|
||||
{
|
||||
/* CC and Y defined
|
||||
/*
|
||||
* CC and Y defined
|
||||
*/
|
||||
tm->tm_year = (tmfc.cc-1)*100 + tmfc.year-2000;
|
||||
tm->tm_year = (tmfc.cc - 1) * 100 + tmfc.year - 2000;
|
||||
}
|
||||
else
|
||||
/* set year (and ignore CC if defined) */
|
||||
@@ -3184,7 +3181,7 @@ do_to_timestamp(text *date_txt, text *fmt,
|
||||
if (!tm->tm_year)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
|
||||
errmsg("cannot calculate day of year without year information")));
|
||||
errmsg("cannot calculate day of year without year information")));
|
||||
|
||||
y = ysum[isleap(tm->tm_year)];
|
||||
|
||||
@@ -3369,9 +3366,9 @@ NUM_cache(int len, NUMDesc *Num, char *pars_str, bool *shouldFree)
|
||||
*(str + len) = '\0';
|
||||
|
||||
/*
|
||||
* Allocate new memory if format picture is bigger than static cache
|
||||
* and not use cache (call parser always). This branches sets
|
||||
* shouldFree to true, accordingly.
|
||||
* Allocate new memory if format picture is bigger than static cache and
|
||||
* not use cache (call parser always). This branches sets shouldFree to
|
||||
* true, accordingly.
|
||||
*/
|
||||
if (len > NUM_CACHE_SIZE)
|
||||
{
|
||||
@@ -3402,8 +3399,8 @@ NUM_cache(int len, NUMDesc *Num, char *pars_str, bool *shouldFree)
|
||||
ent = NUM_cache_getnew(str);
|
||||
|
||||
/*
|
||||
* Not in the cache, must run parser and save a new
|
||||
* format-picture to the cache.
|
||||
* Not in the cache, must run parser and save a new format-picture
|
||||
* to the cache.
|
||||
*/
|
||||
parse_format(ent->format, str, NUM_keywords,
|
||||
NULL, NUM_index, NUM_TYPE, &ent->Num);
|
||||
@@ -3591,18 +3588,18 @@ get_last_relevant_decnum(char *num)
|
||||
static void
|
||||
NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
{
|
||||
bool isread = FALSE;
|
||||
|
||||
bool isread = FALSE;
|
||||
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
elog(DEBUG_elog_output, " --- scan start --- id=%s",
|
||||
(id==NUM_0 || id==NUM_9) ? "NUM_0/9" : id==NUM_DEC ? "NUM_DEC" : "???");
|
||||
(id == NUM_0 || id == NUM_9) ? "NUM_0/9" : id == NUM_DEC ? "NUM_DEC" : "???");
|
||||
#endif
|
||||
|
||||
if (*Np->inout_p == ' ')
|
||||
Np->inout_p++;
|
||||
|
||||
#define OVERLOAD_TEST (Np->inout_p >= Np->inout + plen)
|
||||
#define AMOUNT_TEST(_s) (plen-(Np->inout_p-Np->inout) >= _s)
|
||||
#define AMOUNT_TEST(_s) (plen-(Np->inout_p-Np->inout) >= _s)
|
||||
|
||||
if (*Np->inout_p == ' ')
|
||||
Np->inout_p++;
|
||||
@@ -3613,13 +3610,13 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
/*
|
||||
* read sign before number
|
||||
*/
|
||||
if (*Np->number == ' ' && (id == NUM_0 || id == NUM_9 ) &&
|
||||
(Np->read_pre + Np->read_post)==0)
|
||||
if (*Np->number == ' ' && (id == NUM_0 || id == NUM_9) &&
|
||||
(Np->read_pre + Np->read_post) == 0)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
elog(DEBUG_elog_output, "Try read sign (%c), locale positive: %s, negative: %s",
|
||||
*Np->inout_p, Np->L_positive_sign, Np->L_negative_sign);
|
||||
elog(DEBUG_elog_output, "Try read sign (%c), locale positive: %s, negative: %s",
|
||||
*Np->inout_p, Np->L_positive_sign, Np->L_negative_sign);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -3627,20 +3624,21 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
*/
|
||||
if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_PRE)
|
||||
{
|
||||
int x=0;
|
||||
int x = 0;
|
||||
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
elog(DEBUG_elog_output, "Try read locale pre-sign (%c)", *Np->inout_p);
|
||||
#endif
|
||||
if ((x = strlen(Np->L_negative_sign)) &&
|
||||
if ((x = strlen(Np->L_negative_sign)) &&
|
||||
AMOUNT_TEST(x) &&
|
||||
strncmp(Np->inout_p, Np->L_negative_sign, x)==0)
|
||||
strncmp(Np->inout_p, Np->L_negative_sign, x) == 0)
|
||||
{
|
||||
Np->inout_p += x;
|
||||
*Np->number = '-';
|
||||
}
|
||||
else if ((x = strlen(Np->L_positive_sign)) &&
|
||||
AMOUNT_TEST(x) &&
|
||||
strncmp(Np->inout_p, Np->L_positive_sign, x)==0)
|
||||
else if ((x = strlen(Np->L_positive_sign)) &&
|
||||
AMOUNT_TEST(x) &&
|
||||
strncmp(Np->inout_p, Np->L_positive_sign, x) == 0)
|
||||
{
|
||||
Np->inout_p += x;
|
||||
*Np->number = '+';
|
||||
@@ -3651,6 +3649,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
elog(DEBUG_elog_output, "Try read simple sign (%c)", *Np->inout_p);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* simple + - < >
|
||||
*/
|
||||
@@ -3658,14 +3657,14 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
*Np->inout_p == '<'))
|
||||
{
|
||||
|
||||
*Np->number = '-'; /* set - */
|
||||
*Np->number = '-'; /* set - */
|
||||
Np->inout_p++;
|
||||
|
||||
}
|
||||
else if (*Np->inout_p == '+')
|
||||
{
|
||||
|
||||
*Np->number = '+'; /* set + */
|
||||
*Np->number = '+'; /* set + */
|
||||
Np->inout_p++;
|
||||
}
|
||||
}
|
||||
@@ -3673,11 +3672,11 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
|
||||
if (OVERLOAD_TEST)
|
||||
return;
|
||||
|
||||
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
elog(DEBUG_elog_output, "Scan for numbers (%c), current number: '%s'", *Np->inout_p, Np->number);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* read digit
|
||||
*/
|
||||
@@ -3696,13 +3695,14 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
Np->read_pre++;
|
||||
|
||||
isread = TRUE;
|
||||
|
||||
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
elog(DEBUG_elog_output, "Read digit (%c)", *Np->inout_p);
|
||||
#endif
|
||||
/*
|
||||
* read decimal point
|
||||
*/
|
||||
|
||||
/*
|
||||
* read decimal point
|
||||
*/
|
||||
}
|
||||
else if (IS_DECIMAL(Np->Num) && Np->read_dec == FALSE)
|
||||
{
|
||||
@@ -3726,7 +3726,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
elog(DEBUG_elog_output, "Try read locale point (%c)",
|
||||
*Np->inout_p);
|
||||
#endif
|
||||
if (x && AMOUNT_TEST(x) && strncmp(Np->inout_p, Np->decimal, x)==0)
|
||||
if (x && AMOUNT_TEST(x) && strncmp(Np->inout_p, Np->decimal, x) == 0)
|
||||
{
|
||||
Np->inout_p += x - 1;
|
||||
*Np->number_p = '.';
|
||||
@@ -3739,69 +3739,68 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
|
||||
|
||||
if (OVERLOAD_TEST)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* Read sign behind "last" number
|
||||
*
|
||||
* We need sign detection because determine exact position of
|
||||
* post-sign is difficult:
|
||||
* We need sign detection because determine exact position of post-sign is
|
||||
* difficult:
|
||||
*
|
||||
* FM9999.9999999S -> 123.001-
|
||||
* 9.9S -> .5-
|
||||
* FM9.999999MI -> 5.01-
|
||||
* FM9999.9999999S -> 123.001- 9.9S -> .5- FM9.999999MI
|
||||
* -> 5.01-
|
||||
*/
|
||||
if (*Np->number == ' ' && Np->read_pre + Np->read_post > 0)
|
||||
{
|
||||
/*
|
||||
* locale sign (NUM_S) is always anchored behind a last number, if:
|
||||
* - locale sign expected
|
||||
* - last read char was NUM_0/9 or NUM_DEC
|
||||
* - and next char is not digit
|
||||
*/
|
||||
if (IS_LSIGN(Np->Num) && isread &&
|
||||
(Np->inout_p+1) <= Np->inout + plen &&
|
||||
!isdigit((unsigned char) *(Np->inout_p+1)))
|
||||
* locale sign (NUM_S) is always anchored behind a last number, if: -
|
||||
* locale sign expected - last read char was NUM_0/9 or NUM_DEC - and
|
||||
* next char is not digit
|
||||
*/
|
||||
if (IS_LSIGN(Np->Num) && isread &&
|
||||
(Np->inout_p + 1) <= Np->inout + plen &&
|
||||
!isdigit((unsigned char) *(Np->inout_p + 1)))
|
||||
{
|
||||
int x;
|
||||
char *tmp = Np->inout_p++;
|
||||
|
||||
int x;
|
||||
char *tmp = Np->inout_p++;
|
||||
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
elog(DEBUG_elog_output, "Try read locale post-sign (%c)", *Np->inout_p);
|
||||
#endif
|
||||
if ((x = strlen(Np->L_negative_sign)) &&
|
||||
if ((x = strlen(Np->L_negative_sign)) &&
|
||||
AMOUNT_TEST(x) &&
|
||||
strncmp(Np->inout_p, Np->L_negative_sign, x)==0)
|
||||
strncmp(Np->inout_p, Np->L_negative_sign, x) == 0)
|
||||
{
|
||||
Np->inout_p += x-1; /* -1 .. NUM_processor() do inout_p++ */
|
||||
Np->inout_p += x - 1; /* -1 .. NUM_processor() do inout_p++ */
|
||||
*Np->number = '-';
|
||||
}
|
||||
else if ((x = strlen(Np->L_positive_sign)) &&
|
||||
AMOUNT_TEST(x) &&
|
||||
strncmp(Np->inout_p, Np->L_positive_sign, x)==0)
|
||||
else if ((x = strlen(Np->L_positive_sign)) &&
|
||||
AMOUNT_TEST(x) &&
|
||||
strncmp(Np->inout_p, Np->L_positive_sign, x) == 0)
|
||||
{
|
||||
Np->inout_p += x-1; /* -1 .. NUM_processor() do inout_p++ */
|
||||
Np->inout_p += x - 1; /* -1 .. NUM_processor() do inout_p++ */
|
||||
*Np->number = '+';
|
||||
}
|
||||
if (*Np->number == ' ')
|
||||
/* no sign read */
|
||||
Np->inout_p = tmp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* try read non-locale sign, it's happen only if format is not exact
|
||||
* and we cannot determine sign position of MI/PL/SG, an example:
|
||||
*
|
||||
* FM9.999999MI -> 5.01-
|
||||
* FM9.999999MI -> 5.01-
|
||||
*
|
||||
* if (.... && IS_LSIGN(Np->Num)==FALSE) prevents read wrong formats
|
||||
* like to_number('1 -', '9S') where sign is not anchored to last number.
|
||||
* if (.... && IS_LSIGN(Np->Num)==FALSE) prevents read wrong formats like
|
||||
* to_number('1 -', '9S') where sign is not anchored to last number.
|
||||
*/
|
||||
else if (isread==FALSE && IS_LSIGN(Np->Num)==FALSE &&
|
||||
(IS_PLUS(Np->Num) || IS_MINUS(Np->Num)))
|
||||
else if (isread == FALSE && IS_LSIGN(Np->Num) == FALSE &&
|
||||
(IS_PLUS(Np->Num) || IS_MINUS(Np->Num)))
|
||||
{
|
||||
#ifdef DEBUG_TO_FROM_CHAR
|
||||
elog(DEBUG_elog_output, "Try read simple post-sign (%c)", *Np->inout_p);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* simple + -
|
||||
*/
|
||||
@@ -3848,8 +3847,8 @@ NUM_numpart_to_char(NUMProc *Np, int id)
|
||||
Np->num_in = FALSE;
|
||||
|
||||
/*
|
||||
* Write sign if real number will write to output Note:
|
||||
* IS_PREDEC_SPACE() handle "9.9" --> " .1"
|
||||
* Write sign if real number will write to output Note: IS_PREDEC_SPACE()
|
||||
* handle "9.9" --> " .1"
|
||||
*/
|
||||
if (Np->sign_wrote == FALSE &&
|
||||
(Np->num_curr >= Np->num_pre || (IS_ZERO(Np->Num) && Np->Num->zero_start == Np->num_curr)) &&
|
||||
@@ -4032,7 +4031,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
|
||||
Np->inout = inout;
|
||||
Np->last_relevant = NULL;
|
||||
Np->read_post = 0;
|
||||
Np->read_pre = 0;
|
||||
Np->read_pre = 0;
|
||||
Np->read_dec = FALSE;
|
||||
|
||||
if (Np->Num->zero_start)
|
||||
@@ -4114,8 +4113,8 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
|
||||
if (IS_DECIMAL(Np->Num))
|
||||
Np->last_relevant = get_last_relevant_decnum(
|
||||
Np->number +
|
||||
((Np->Num->zero_end - Np->num_pre > 0) ?
|
||||
Np->Num->zero_end - Np->num_pre : 0));
|
||||
((Np->Num->zero_end - Np->num_pre > 0) ?
|
||||
Np->Num->zero_end - Np->num_pre : 0));
|
||||
}
|
||||
|
||||
if (Np->sign_wrote == FALSE && Np->num_pre == 0)
|
||||
@@ -4185,10 +4184,10 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
|
||||
/*
|
||||
* Create/reading digit/zero/blank/sing
|
||||
*
|
||||
* 'NUM_S' note:
|
||||
* The locale sign is anchored to number and we read/write it
|
||||
* when we work with first or last number (NUM_0/NUM_9). This
|
||||
* is reason why NUM_S missing in follow switch().
|
||||
* 'NUM_S' note: The locale sign is anchored to number and we
|
||||
* read/write it when we work with first or last number
|
||||
* (NUM_0/NUM_9). This is reason why NUM_S missing in follow
|
||||
* switch().
|
||||
*/
|
||||
switch (n->key->id)
|
||||
{
|
||||
@@ -4497,7 +4496,7 @@ numeric_to_number(PG_FUNCTION_ARGS)
|
||||
result = DirectFunctionCall3(numeric_in,
|
||||
CStringGetDatum(numstr),
|
||||
ObjectIdGetDatum(InvalidOid),
|
||||
Int32GetDatum(((precision << 16) | scale) + VARHDRSZ));
|
||||
Int32GetDatum(((precision << 16) | scale) + VARHDRSZ));
|
||||
pfree(numstr);
|
||||
return result;
|
||||
}
|
||||
@@ -4536,7 +4535,7 @@ numeric_to_char(PG_FUNCTION_ARGS)
|
||||
Int32GetDatum(0)));
|
||||
numstr = orgnum =
|
||||
int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4,
|
||||
NumericGetDatum(x))));
|
||||
NumericGetDatum(x))));
|
||||
pfree(x);
|
||||
}
|
||||
else
|
||||
@@ -4546,16 +4545,16 @@ numeric_to_char(PG_FUNCTION_ARGS)
|
||||
if (IS_MULTI(&Num))
|
||||
{
|
||||
Numeric a = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
|
||||
Int32GetDatum(10)));
|
||||
Int32GetDatum(10)));
|
||||
Numeric b = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
|
||||
Int32GetDatum(Num.multi)));
|
||||
Int32GetDatum(Num.multi)));
|
||||
|
||||
x = DatumGetNumeric(DirectFunctionCall2(numeric_power,
|
||||
NumericGetDatum(a),
|
||||
NumericGetDatum(b)));
|
||||
val = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
|
||||
NumericGetDatum(value),
|
||||
NumericGetDatum(x)));
|
||||
NumericGetDatum(value),
|
||||
NumericGetDatum(x)));
|
||||
pfree(x);
|
||||
pfree(a);
|
||||
pfree(b);
|
||||
@@ -4639,7 +4638,7 @@ int4_to_char(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
orgnum = DatumGetCString(DirectFunctionCall1(int4out,
|
||||
Int32GetDatum(value)));
|
||||
Int32GetDatum(value)));
|
||||
}
|
||||
len = strlen(orgnum);
|
||||
|
||||
@@ -4711,7 +4710,7 @@ int8_to_char(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Currently don't support int8 conversion to roman... */
|
||||
numstr = orgnum = int_to_roman(DatumGetInt32(
|
||||
DirectFunctionCall1(int84, Int64GetDatum(value))));
|
||||
DirectFunctionCall1(int84, Int64GetDatum(value))));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4720,14 +4719,14 @@ int8_to_char(PG_FUNCTION_ARGS)
|
||||
double multi = pow((double) 10, (double) Num.multi);
|
||||
|
||||
value = DatumGetInt64(DirectFunctionCall2(int8mul,
|
||||
Int64GetDatum(value),
|
||||
DirectFunctionCall1(dtoi8,
|
||||
Float8GetDatum(multi))));
|
||||
Int64GetDatum(value),
|
||||
DirectFunctionCall1(dtoi8,
|
||||
Float8GetDatum(multi))));
|
||||
Num.pre += Num.multi;
|
||||
}
|
||||
|
||||
orgnum = DatumGetCString(DirectFunctionCall1(int8out,
|
||||
Int64GetDatum(value)));
|
||||
Int64GetDatum(value)));
|
||||
len = strlen(orgnum);
|
||||
|
||||
if (*orgnum == '-')
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2004-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
*
|
||||
* Author: Andreas Pflug <pgadmin@pse-consulting.de>
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/genfile.c,v 1.6 2005/08/29 19:39:39 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/genfile.c,v 1.7 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,10 +30,10 @@
|
||||
#include "utils/memutils.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
char *location;
|
||||
DIR *dirdesc;
|
||||
char *location;
|
||||
DIR *dirdesc;
|
||||
} directory_fctx;
|
||||
|
||||
|
||||
@@ -46,9 +46,9 @@ typedef struct
|
||||
static char *
|
||||
check_and_make_absolute(text *arg)
|
||||
{
|
||||
int input_len = VARSIZE(arg) - VARHDRSZ;
|
||||
char *filename = palloc(input_len + 1);
|
||||
|
||||
int input_len = VARSIZE(arg) - VARHDRSZ;
|
||||
char *filename = palloc(input_len + 1);
|
||||
|
||||
memcpy(filename, VARDATA(arg), input_len);
|
||||
filename[input_len] = '\0';
|
||||
|
||||
@@ -58,7 +58,7 @@ check_and_make_absolute(text *arg)
|
||||
if (path_contains_parent_reference(filename))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("reference to parent directory (\"..\") not allowed"))));
|
||||
(errmsg("reference to parent directory (\"..\") not allowed"))));
|
||||
|
||||
if (is_absolute_path(filename))
|
||||
{
|
||||
@@ -70,14 +70,15 @@ check_and_make_absolute(text *arg)
|
||||
path_is_prefix_of_path(Log_directory, filename))
|
||||
return filename;
|
||||
|
||||
ereport(ERROR,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("absolute path not allowed"))));
|
||||
return NULL; /* keep compiler quiet */
|
||||
}
|
||||
else
|
||||
{
|
||||
char *absname = palloc(strlen(DataDir) + strlen(filename) + 2);
|
||||
char *absname = palloc(strlen(DataDir) + strlen(filename) + 2);
|
||||
|
||||
sprintf(absname, "%s/%s", DataDir, filename);
|
||||
pfree(filename);
|
||||
return absname;
|
||||
@@ -94,13 +95,13 @@ pg_read_file(PG_FUNCTION_ARGS)
|
||||
text *filename_t = PG_GETARG_TEXT_P(0);
|
||||
int64 seek_offset = PG_GETARG_INT64(1);
|
||||
int64 bytes_to_read = PG_GETARG_INT64(2);
|
||||
char *buf;
|
||||
char *buf;
|
||||
size_t nbytes;
|
||||
FILE *file;
|
||||
char *filename;
|
||||
FILE *file;
|
||||
char *filename;
|
||||
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("must be superuser to read files"))));
|
||||
|
||||
@@ -128,7 +129,7 @@ pg_read_file(PG_FUNCTION_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("requested length too large")));
|
||||
|
||||
|
||||
buf = palloc((Size) bytes_to_read + VARHDRSZ);
|
||||
|
||||
nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
|
||||
@@ -153,7 +154,7 @@ Datum
|
||||
pg_stat_file(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *filename_t = PG_GETARG_TEXT_P(0);
|
||||
char *filename;
|
||||
char *filename;
|
||||
struct stat fst;
|
||||
Datum values[6];
|
||||
bool isnull[6];
|
||||
@@ -161,7 +162,7 @@ pg_stat_file(PG_FUNCTION_ARGS)
|
||||
TupleDesc tupdesc;
|
||||
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("must be superuser to get file information"))));
|
||||
|
||||
@@ -173,8 +174,8 @@ pg_stat_file(PG_FUNCTION_ARGS)
|
||||
errmsg("could not stat file \"%s\": %m", filename)));
|
||||
|
||||
/*
|
||||
* This record type had better match the output parameters declared
|
||||
* for me in pg_proc.h (actually, in system_views.sql at the moment).
|
||||
* This record type had better match the output parameters declared for me
|
||||
* in pg_proc.h (actually, in system_views.sql at the moment).
|
||||
*/
|
||||
tupdesc = CreateTemplateTupleDesc(6, false);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 1,
|
||||
@@ -220,12 +221,12 @@ pg_stat_file(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_ls_dir(PG_FUNCTION_ARGS)
|
||||
{
|
||||
FuncCallContext *funcctx;
|
||||
struct dirent *de;
|
||||
directory_fctx *fctx;
|
||||
FuncCallContext *funcctx;
|
||||
struct dirent *de;
|
||||
directory_fctx *fctx;
|
||||
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("must be superuser to get directory listings"))));
|
||||
|
||||
@@ -242,7 +243,7 @@ pg_ls_dir(PG_FUNCTION_ARGS)
|
||||
fctx->dirdesc = AllocateDir(fctx->location);
|
||||
|
||||
if (!fctx->dirdesc)
|
||||
ereport(ERROR,
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not open directory \"%s\": %m",
|
||||
fctx->location)));
|
||||
@@ -252,16 +253,16 @@ pg_ls_dir(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
funcctx = SRF_PERCALL_SETUP();
|
||||
fctx = (directory_fctx*) funcctx->user_fctx;
|
||||
fctx = (directory_fctx *) funcctx->user_fctx;
|
||||
|
||||
while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
|
||||
{
|
||||
int len = strlen(de->d_name);
|
||||
text *result;
|
||||
text *result;
|
||||
|
||||
if (strcmp(de->d_name, ".") == 0 ||
|
||||
strcmp(de->d_name, "..") == 0)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
result = palloc(len + VARHDRSZ);
|
||||
VARATT_SIZEP(result) = len + VARHDRSZ;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.90 2005/07/01 19:19:02 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.91 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -387,7 +387,7 @@ box_in(PG_FUNCTION_ARGS)
|
||||
|| (*s != '\0'))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type box: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type box: \"%s\"", str)));
|
||||
|
||||
/* reorder corners if necessary... */
|
||||
if (box->high.x < box->low.x)
|
||||
@@ -951,7 +951,7 @@ line_in(PG_FUNCTION_ARGS)
|
||||
|| (*s != '\0'))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type line: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type line: \"%s\"", str)));
|
||||
|
||||
line = (LINE *) palloc(sizeof(LINE));
|
||||
line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
|
||||
@@ -1292,10 +1292,9 @@ line_interpt_internal(LINE *l1, LINE *l2)
|
||||
y;
|
||||
|
||||
/*
|
||||
* NOTE: if the lines are identical then we will find they are
|
||||
* parallel and report "no intersection". This is a little weird, but
|
||||
* since there's no *unique* intersection, maybe it's appropriate
|
||||
* behavior.
|
||||
* NOTE: if the lines are identical then we will find they are parallel
|
||||
* and report "no intersection". This is a little weird, but since
|
||||
* there's no *unique* intersection, maybe it's appropriate behavior.
|
||||
*/
|
||||
if (DatumGetBool(DirectFunctionCall2(line_parallel,
|
||||
LinePGetDatum(l1),
|
||||
@@ -1400,7 +1399,7 @@ path_in(PG_FUNCTION_ARGS)
|
||||
if ((npts = pair_count(str, ',')) <= 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type path: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type path: \"%s\"", str)));
|
||||
|
||||
s = str;
|
||||
while (isspace((unsigned char) *s))
|
||||
@@ -1420,10 +1419,10 @@ path_in(PG_FUNCTION_ARGS)
|
||||
path->npts = npts;
|
||||
|
||||
if ((!path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0])))
|
||||
&& (!((depth == 0) && (*s == '\0'))) && !((depth >= 1) && (*s == RDELIM)))
|
||||
&& (!((depth == 0) && (*s == '\0'))) && !((depth >= 1) && (*s == RDELIM)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type path: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type path: \"%s\"", str)));
|
||||
|
||||
path->closed = (!isopen);
|
||||
|
||||
@@ -1460,7 +1459,7 @@ path_recv(PG_FUNCTION_ARGS)
|
||||
if (npts < 0 || npts >= (int32) ((INT_MAX - offsetof(PATH, p[0])) / sizeof(Point)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("invalid number of points in external \"path\" value")));
|
||||
errmsg("invalid number of points in external \"path\" value")));
|
||||
|
||||
size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts;
|
||||
path = (PATH *) palloc(size);
|
||||
@@ -1730,7 +1729,7 @@ path_distance(PG_FUNCTION_ARGS)
|
||||
|
||||
tmp = DatumGetFloat8(DirectFunctionCall2(lseg_distance,
|
||||
LsegPGetDatum(&seg1),
|
||||
LsegPGetDatum(&seg2)));
|
||||
LsegPGetDatum(&seg2)));
|
||||
if (!have_min || tmp < min)
|
||||
{
|
||||
min = tmp;
|
||||
@@ -1801,7 +1800,7 @@ point_in(PG_FUNCTION_ARGS)
|
||||
if (!pair_decode(str, &x, &y, &s) || (*s != '\0'))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type point: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type point: \"%s\"", str)));
|
||||
|
||||
point = (Point *) palloc(sizeof(Point));
|
||||
|
||||
@@ -1976,7 +1975,7 @@ point_dt(Point *pt1, Point *pt2)
|
||||
{
|
||||
#ifdef GEODEBUG
|
||||
printf("point_dt- segment (%f,%f),(%f,%f) length is %f\n",
|
||||
pt1->x, pt1->y, pt2->x, pt2->y, HYPOT(pt1->x - pt2->x, pt1->y - pt2->y));
|
||||
pt1->x, pt1->y, pt2->x, pt2->y, HYPOT(pt1->x - pt2->x, pt1->y - pt2->y));
|
||||
#endif
|
||||
return HYPOT(pt1->x - pt2->x, pt1->y - pt2->y);
|
||||
}
|
||||
@@ -2029,7 +2028,7 @@ lseg_in(PG_FUNCTION_ARGS)
|
||||
|| (*s != '\0'))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type lseg: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type lseg: \"%s\"", str)));
|
||||
|
||||
#ifdef NOT_USED
|
||||
lseg->m = point_sl(&lseg->p[0], &lseg->p[1]);
|
||||
@@ -2374,8 +2373,8 @@ lseg_interpt(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
/*
|
||||
* If the line intersection point isn't within l1 (or equivalently
|
||||
* l2), there is no valid segment intersection point at all.
|
||||
* If the line intersection point isn't within l1 (or equivalently l2),
|
||||
* there is no valid segment intersection point at all.
|
||||
*/
|
||||
if (!on_ps_internal(result, l1) ||
|
||||
!on_ps_internal(result, l2))
|
||||
@@ -2393,7 +2392,7 @@ lseg_interpt(PG_FUNCTION_ARGS)
|
||||
result->y = l1->p[0].y;
|
||||
}
|
||||
else if ((FPeq(l1->p[1].x, l2->p[0].x) && FPeq(l1->p[1].y, l2->p[0].y)) ||
|
||||
(FPeq(l1->p[1].x, l2->p[1].x) && FPeq(l1->p[1].y, l2->p[1].y)))
|
||||
(FPeq(l1->p[1].x, l2->p[1].x) && FPeq(l1->p[1].y, l2->p[1].y)))
|
||||
{
|
||||
result->x = l1->p[1].x;
|
||||
result->y = l1->p[1].y;
|
||||
@@ -2521,8 +2520,8 @@ dist_ppath(PG_FUNCTION_ARGS)
|
||||
Assert(path->npts > 1);
|
||||
|
||||
/*
|
||||
* the distance from a point to a path is the smallest
|
||||
* distance from the point to any of its constituent segments.
|
||||
* the distance from a point to a path is the smallest distance
|
||||
* from the point to any of its constituent segments.
|
||||
*/
|
||||
for (i = 0; i < path->npts; i++)
|
||||
{
|
||||
@@ -2534,8 +2533,7 @@ dist_ppath(PG_FUNCTION_ARGS)
|
||||
{
|
||||
if (!path->closed)
|
||||
continue;
|
||||
iprev = path->npts - 1; /* include the closure
|
||||
* segment */
|
||||
iprev = path->npts - 1; /* include the closure segment */
|
||||
}
|
||||
|
||||
statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
|
||||
@@ -2853,8 +2851,8 @@ close_ps(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* vert. and horiz. cases are down, now check if the closest point is
|
||||
* one of the end points or someplace on the lseg.
|
||||
* vert. and horiz. cases are down, now check if the closest point is one
|
||||
* of the end points or someplace on the lseg.
|
||||
*/
|
||||
|
||||
invm = -1.0 / point_sl(&(lseg->p[0]), &(lseg->p[1]));
|
||||
@@ -2862,8 +2860,8 @@ close_ps(PG_FUNCTION_ARGS)
|
||||
* "band" */
|
||||
if (pt->y < (tmp->A * pt->x + tmp->C))
|
||||
{ /* we are below the lower edge */
|
||||
result = point_copy(&lseg->p[!yh]); /* below the lseg, take
|
||||
* lower end pt */
|
||||
result = point_copy(&lseg->p[!yh]); /* below the lseg, take lower
|
||||
* end pt */
|
||||
#ifdef GEODEBUG
|
||||
printf("close_ps below: tmp A %f B %f C %f m %f\n",
|
||||
tmp->A, tmp->B, tmp->C, tmp->m);
|
||||
@@ -2874,8 +2872,8 @@ close_ps(PG_FUNCTION_ARGS)
|
||||
* "band" */
|
||||
if (pt->y > (tmp->A * pt->x + tmp->C))
|
||||
{ /* we are below the lower edge */
|
||||
result = point_copy(&lseg->p[yh]); /* above the lseg, take
|
||||
* higher end pt */
|
||||
result = point_copy(&lseg->p[yh]); /* above the lseg, take higher
|
||||
* end pt */
|
||||
#ifdef GEODEBUG
|
||||
printf("close_ps above: tmp A %f B %f C %f m %f\n",
|
||||
tmp->A, tmp->B, tmp->C, tmp->m);
|
||||
@@ -2884,8 +2882,8 @@ close_ps(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* at this point the "normal" from point will hit lseg. The closet
|
||||
* point will be somewhere on the lseg
|
||||
* at this point the "normal" from point will hit lseg. The closet point
|
||||
* will be somewhere on the lseg
|
||||
*/
|
||||
tmp = line_construct_pm(pt, invm);
|
||||
#ifdef GEODEBUG
|
||||
@@ -2927,22 +2925,22 @@ close_lseg(PG_FUNCTION_ARGS)
|
||||
if ((d = dist_ps_internal(&l2->p[0], l1)) < dist)
|
||||
{
|
||||
result = DatumGetPointP(DirectFunctionCall2(close_ps,
|
||||
PointPGetDatum(&l2->p[0]),
|
||||
PointPGetDatum(&l2->p[0]),
|
||||
LsegPGetDatum(l1)));
|
||||
memcpy(&point, result, sizeof(Point));
|
||||
result = DatumGetPointP(DirectFunctionCall2(close_ps,
|
||||
PointPGetDatum(&point),
|
||||
PointPGetDatum(&point),
|
||||
LsegPGetDatum(l2)));
|
||||
}
|
||||
|
||||
if ((d = dist_ps_internal(&l2->p[1], l1)) < dist)
|
||||
{
|
||||
result = DatumGetPointP(DirectFunctionCall2(close_ps,
|
||||
PointPGetDatum(&l2->p[1]),
|
||||
PointPGetDatum(&l2->p[1]),
|
||||
LsegPGetDatum(l1)));
|
||||
memcpy(&point, result, sizeof(Point));
|
||||
result = DatumGetPointP(DirectFunctionCall2(close_ps,
|
||||
PointPGetDatum(&point),
|
||||
PointPGetDatum(&point),
|
||||
LsegPGetDatum(l2)));
|
||||
}
|
||||
|
||||
@@ -3235,11 +3233,11 @@ on_sl(PG_FUNCTION_ARGS)
|
||||
LINE *line = PG_GETARG_LINE_P(1);
|
||||
|
||||
PG_RETURN_BOOL(DatumGetBool(DirectFunctionCall2(on_pl,
|
||||
PointPGetDatum(&lseg->p[0]),
|
||||
LinePGetDatum(line))) &&
|
||||
PointPGetDatum(&lseg->p[0]),
|
||||
LinePGetDatum(line))) &&
|
||||
DatumGetBool(DirectFunctionCall2(on_pl,
|
||||
PointPGetDatum(&lseg->p[1]),
|
||||
LinePGetDatum(line))));
|
||||
PointPGetDatum(&lseg->p[1]),
|
||||
LinePGetDatum(line))));
|
||||
}
|
||||
|
||||
Datum
|
||||
@@ -3249,10 +3247,10 @@ on_sb(PG_FUNCTION_ARGS)
|
||||
BOX *box = PG_GETARG_BOX_P(1);
|
||||
|
||||
PG_RETURN_BOOL(DatumGetBool(DirectFunctionCall2(on_pb,
|
||||
PointPGetDatum(&lseg->p[0]),
|
||||
PointPGetDatum(&lseg->p[0]),
|
||||
BoxPGetDatum(box))) &&
|
||||
DatumGetBool(DirectFunctionCall2(on_pb,
|
||||
PointPGetDatum(&lseg->p[1]),
|
||||
PointPGetDatum(&lseg->p[1]),
|
||||
BoxPGetDatum(box))));
|
||||
}
|
||||
|
||||
@@ -3437,7 +3435,7 @@ poly_in(PG_FUNCTION_ARGS)
|
||||
if ((npts = pair_count(str, ',')) <= 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type polygon: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type polygon: \"%s\"", str)));
|
||||
|
||||
size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * npts;
|
||||
poly = (POLYGON *) palloc0(size); /* zero any holes */
|
||||
@@ -3449,7 +3447,7 @@ poly_in(PG_FUNCTION_ARGS)
|
||||
|| (*s != '\0'))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type polygon: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type polygon: \"%s\"", str)));
|
||||
|
||||
make_bound_box(poly);
|
||||
|
||||
@@ -3489,7 +3487,7 @@ poly_recv(PG_FUNCTION_ARGS)
|
||||
if (npts < 0 || npts >= (int32) ((INT_MAX - offsetof(POLYGON, p[0])) / sizeof(Point)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("invalid number of points in external \"polygon\" value")));
|
||||
errmsg("invalid number of points in external \"polygon\" value")));
|
||||
|
||||
size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * npts;
|
||||
poly = (POLYGON *) palloc0(size); /* zero any holes */
|
||||
@@ -3544,8 +3542,7 @@ poly_left(PG_FUNCTION_ARGS)
|
||||
result = polya->boundbox.high.x < polyb->boundbox.low.x;
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3568,8 +3565,7 @@ poly_overleft(PG_FUNCTION_ARGS)
|
||||
result = polya->boundbox.high.x <= polyb->boundbox.high.x;
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3592,8 +3588,7 @@ poly_right(PG_FUNCTION_ARGS)
|
||||
result = polya->boundbox.low.x > polyb->boundbox.high.x;
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3616,8 +3611,7 @@ poly_overright(PG_FUNCTION_ARGS)
|
||||
result = polya->boundbox.low.x >= polyb->boundbox.low.x;
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3640,8 +3634,7 @@ poly_below(PG_FUNCTION_ARGS)
|
||||
result = polya->boundbox.high.y < polyb->boundbox.low.y;
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3664,8 +3657,7 @@ poly_overbelow(PG_FUNCTION_ARGS)
|
||||
result = polya->boundbox.high.y <= polyb->boundbox.high.y;
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3688,8 +3680,7 @@ poly_above(PG_FUNCTION_ARGS)
|
||||
result = polya->boundbox.low.y > polyb->boundbox.high.y;
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3712,8 +3703,7 @@ poly_overabove(PG_FUNCTION_ARGS)
|
||||
result = polya->boundbox.low.y >= polyb->boundbox.low.y;
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3742,8 +3732,7 @@ poly_same(PG_FUNCTION_ARGS)
|
||||
result = plist_same(polya->npts, polya->p, polyb->p);
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3767,8 +3756,7 @@ poly_overlap(PG_FUNCTION_ARGS)
|
||||
result = box_ov(&polya->boundbox, &polyb->boundbox);
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -3833,8 +3821,7 @@ poly_contain(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree
|
||||
* indexes
|
||||
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
|
||||
*/
|
||||
PG_FREE_IF_COPY(polya, 0);
|
||||
PG_FREE_IF_COPY(polyb, 1);
|
||||
@@ -4169,7 +4156,7 @@ path_mul_pt(PG_FUNCTION_ARGS)
|
||||
for (i = 0; i < path->npts; i++)
|
||||
{
|
||||
p = DatumGetPointP(DirectFunctionCall2(point_mul,
|
||||
PointPGetDatum(&path->p[i]),
|
||||
PointPGetDatum(&path->p[i]),
|
||||
PointPGetDatum(point)));
|
||||
path->p[i].x = p->x;
|
||||
path->p[i].y = p->y;
|
||||
@@ -4189,7 +4176,7 @@ path_div_pt(PG_FUNCTION_ARGS)
|
||||
for (i = 0; i < path->npts; i++)
|
||||
{
|
||||
p = DatumGetPointP(DirectFunctionCall2(point_div,
|
||||
PointPGetDatum(&path->p[i]),
|
||||
PointPGetDatum(&path->p[i]),
|
||||
PointPGetDatum(point)));
|
||||
path->p[i].x = p->x;
|
||||
path->p[i].y = p->y;
|
||||
@@ -4392,7 +4379,7 @@ circle_in(PG_FUNCTION_ARGS)
|
||||
if (!pair_decode(s, &circle->center.x, &circle->center.y, &s))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
||||
|
||||
if (*s == DELIM)
|
||||
s++;
|
||||
@@ -4402,7 +4389,7 @@ circle_in(PG_FUNCTION_ARGS)
|
||||
if ((!single_decode(s, &circle->radius, &s)) || (circle->radius < 0))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
||||
|
||||
while (depth > 0)
|
||||
{
|
||||
@@ -4417,13 +4404,13 @@ circle_in(PG_FUNCTION_ARGS)
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
||||
}
|
||||
|
||||
if (*s != '\0')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type circle: \"%s\"", str)));
|
||||
|
||||
PG_RETURN_CIRCLE_P(circle);
|
||||
}
|
||||
@@ -4780,7 +4767,7 @@ circle_mul_pt(PG_FUNCTION_ARGS)
|
||||
result = circle_copy(circle);
|
||||
|
||||
p = DatumGetPointP(DirectFunctionCall2(point_mul,
|
||||
PointPGetDatum(&circle->center),
|
||||
PointPGetDatum(&circle->center),
|
||||
PointPGetDatum(point)));
|
||||
result->center.x = p->x;
|
||||
result->center.y = p->y;
|
||||
@@ -4800,7 +4787,7 @@ circle_div_pt(PG_FUNCTION_ARGS)
|
||||
result = circle_copy(circle);
|
||||
|
||||
p = DatumGetPointP(DirectFunctionCall2(point_div,
|
||||
PointPGetDatum(&circle->center),
|
||||
PointPGetDatum(&circle->center),
|
||||
PointPGetDatum(point)));
|
||||
result->center.x = p->x;
|
||||
result->center.y = p->y;
|
||||
@@ -5001,7 +4988,7 @@ circle_poly(PG_FUNCTION_ARGS)
|
||||
if (FPzero(circle->radius))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot convert circle with radius zero to polygon")));
|
||||
errmsg("cannot convert circle with radius zero to polygon")));
|
||||
|
||||
if (npts < 2)
|
||||
ereport(ERROR,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/inet_net_ntop.c,v 1.20 2005/09/24 22:54:38 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/inet_net_ntop.c,v 1.21 2005/10/15 02:49:28 momjian Exp $
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
@@ -412,11 +412,11 @@ static char *
|
||||
inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
|
||||
{
|
||||
/*
|
||||
* Note that int32_t and int16_t need only be "at least" large enough
|
||||
* to contain a value of the specified size. On some systems, like
|
||||
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||
* Keep this in mind if you think this function should have been coded
|
||||
* to use pointer overlays. All the world's not a VAX.
|
||||
* Note that int32_t and int16_t need only be "at least" large enough to
|
||||
* contain a value of the specified size. On some systems, like Crays,
|
||||
* there is no such thing as an integer variable with 16 bits. Keep this
|
||||
* in mind if you think this function should have been coded to use
|
||||
* pointer overlays. All the world's not a VAX.
|
||||
*/
|
||||
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
|
||||
char *tp;
|
||||
@@ -435,8 +435,8 @@ inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
|
||||
}
|
||||
|
||||
/*
|
||||
* Preprocess: Copy the input (bytewise) array into a wordwise array.
|
||||
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||
* Preprocess: Copy the input (bytewise) array into a wordwise array. Find
|
||||
* the longest run of 0x00's in src[] for :: shorthanding.
|
||||
*/
|
||||
memset(words, '\0', sizeof words);
|
||||
for (i = 0; i < NS_IN6ADDRSZ; i++)
|
||||
@@ -491,8 +491,8 @@ inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
|
||||
*tp++ = ':';
|
||||
/* Is this address an encapsulated IPv4? */
|
||||
if (i == 6 && best.base == 0 && (best.len == 6 ||
|
||||
(best.len == 7 && words[7] != 0x0001) ||
|
||||
(best.len == 5 && words[5] == 0xffff)))
|
||||
(best.len == 7 && words[7] != 0x0001) ||
|
||||
(best.len == 5 && words[5] == 0xffff)))
|
||||
{
|
||||
int n;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/inet_net_pton.c,v 1.20 2005/02/01 00:59:09 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/inet_net_pton.c,v 1.21 2005/10/15 02:49:28 momjian Exp $
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
@@ -207,7 +207,8 @@ inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size)
|
||||
bits = 24;
|
||||
else if (*odst >= 128) /* Class B */
|
||||
bits = 16;
|
||||
else /* Class A */
|
||||
else
|
||||
/* Class A */
|
||||
bits = 8;
|
||||
/* If imputed mask is narrower than specified octets, widen. */
|
||||
if (bits < ((dst - odst) * 8))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.67 2005/07/10 21:36:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.68 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -120,7 +120,7 @@ int2send(PG_FUNCTION_ARGS)
|
||||
int2vector *
|
||||
buildint2vector(const int2 *int2s, int n)
|
||||
{
|
||||
int2vector *result;
|
||||
int2vector *result;
|
||||
|
||||
result = (int2vector *) palloc0(Int2VectorSize(n));
|
||||
|
||||
@@ -128,8 +128,8 @@ buildint2vector(const int2 *int2s, int n)
|
||||
memcpy(result->values, int2s, n * sizeof(int2));
|
||||
|
||||
/*
|
||||
* Attach standard array header. For historical reasons, we set the
|
||||
* index lower bound to 0 not 1.
|
||||
* Attach standard array header. For historical reasons, we set the index
|
||||
* lower bound to 0 not 1.
|
||||
*/
|
||||
result->size = Int2VectorSize(n);
|
||||
result->ndim = 1;
|
||||
@@ -212,7 +212,7 @@ Datum
|
||||
int2vectorrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
int2vector *result;
|
||||
int2vector *result;
|
||||
|
||||
result = (int2vector *)
|
||||
DatumGetPointer(DirectFunctionCall3(array_recv,
|
||||
@@ -686,10 +686,11 @@ int4pl(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 + arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum
|
||||
* had better be that sign too.
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum had
|
||||
* better be that sign too.
|
||||
*/
|
||||
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -706,10 +707,11 @@ int4mi(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 - arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then
|
||||
* the result should be of the same sign as the first input.
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then the
|
||||
* result should be of the same sign as the first input.
|
||||
*/
|
||||
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -726,21 +728,22 @@ int4mul(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 * arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. We basically check to see if result / arg2 gives
|
||||
* arg1 again. There are two cases where this fails: arg2 = 0 (which
|
||||
* cannot overflow) and arg1 = INT_MIN, arg2 = -1 (where the division
|
||||
* itself will overflow and thus incorrectly match).
|
||||
* Overflow check. We basically check to see if result / arg2 gives arg1
|
||||
* again. There are two cases where this fails: arg2 = 0 (which cannot
|
||||
* overflow) and arg1 = INT_MIN, arg2 = -1 (where the division itself will
|
||||
* overflow and thus incorrectly match).
|
||||
*
|
||||
* Since the division is likely much more expensive than the actual
|
||||
* multiplication, we'd like to skip it where possible. The best
|
||||
* bang for the buck seems to be to check whether both inputs are in
|
||||
* the int16 range; if so, no overflow is possible.
|
||||
* multiplication, we'd like to skip it where possible. The best bang for
|
||||
* the buck seems to be to check whether both inputs are in the int16
|
||||
* range; if so, no overflow is possible.
|
||||
*/
|
||||
if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
|
||||
arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
|
||||
arg2 != 0 &&
|
||||
(result/arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
|
||||
(result / arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("integer out of range")));
|
||||
@@ -760,10 +763,11 @@ int4div(PG_FUNCTION_ARGS)
|
||||
errmsg("division by zero")));
|
||||
|
||||
result = arg1 / arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. The only possible overflow case is for
|
||||
* arg1 = INT_MIN, arg2 = -1, where the correct result is -INT_MIN,
|
||||
* which can't be represented on a two's-complement machine.
|
||||
* Overflow check. The only possible overflow case is for arg1 = INT_MIN,
|
||||
* arg2 = -1, where the correct result is -INT_MIN, which can't be
|
||||
* represented on a two's-complement machine.
|
||||
*/
|
||||
if (arg2 == -1 && arg1 < 0 && result < 0)
|
||||
ereport(ERROR,
|
||||
@@ -819,10 +823,11 @@ int2pl(PG_FUNCTION_ARGS)
|
||||
int16 result;
|
||||
|
||||
result = arg1 + arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum
|
||||
* had better be that sign too.
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum had
|
||||
* better be that sign too.
|
||||
*/
|
||||
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -839,10 +844,11 @@ int2mi(PG_FUNCTION_ARGS)
|
||||
int16 result;
|
||||
|
||||
result = arg1 - arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then
|
||||
* the result should be of the same sign as the first input.
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then the
|
||||
* result should be of the same sign as the first input.
|
||||
*/
|
||||
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -859,11 +865,11 @@ int2mul(PG_FUNCTION_ARGS)
|
||||
int32 result32;
|
||||
|
||||
/*
|
||||
* The most practical way to detect overflow is to do the arithmetic
|
||||
* in int32 (so that the result can't overflow) and then do a range
|
||||
* check.
|
||||
* The most practical way to detect overflow is to do the arithmetic in
|
||||
* int32 (so that the result can't overflow) and then do a range check.
|
||||
*/
|
||||
result32 = (int32) arg1 * (int32) arg2;
|
||||
result32 = (int32) arg1 *(int32) arg2;
|
||||
|
||||
if (result32 < SHRT_MIN || result32 > SHRT_MAX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
@@ -885,10 +891,11 @@ int2div(PG_FUNCTION_ARGS)
|
||||
errmsg("division by zero")));
|
||||
|
||||
result = arg1 / arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. The only possible overflow case is for
|
||||
* arg1 = SHRT_MIN, arg2 = -1, where the correct result is -SHRT_MIN,
|
||||
* which can't be represented on a two's-complement machine.
|
||||
* Overflow check. The only possible overflow case is for arg1 =
|
||||
* SHRT_MIN, arg2 = -1, where the correct result is -SHRT_MIN, which can't
|
||||
* be represented on a two's-complement machine.
|
||||
*/
|
||||
if (arg2 == -1 && arg1 < 0 && result < 0)
|
||||
ereport(ERROR,
|
||||
@@ -905,10 +912,11 @@ int24pl(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 + arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum
|
||||
* had better be that sign too.
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum had
|
||||
* better be that sign too.
|
||||
*/
|
||||
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -925,10 +933,11 @@ int24mi(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 - arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then
|
||||
* the result should be of the same sign as the first input.
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then the
|
||||
* result should be of the same sign as the first input.
|
||||
*/
|
||||
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -945,18 +954,19 @@ int24mul(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 * arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. We basically check to see if result / arg2 gives
|
||||
* arg1 again. There is one case where this fails: arg2 = 0 (which
|
||||
* cannot overflow).
|
||||
* Overflow check. We basically check to see if result / arg2 gives arg1
|
||||
* again. There is one case where this fails: arg2 = 0 (which cannot
|
||||
* overflow).
|
||||
*
|
||||
* Since the division is likely much more expensive than the actual
|
||||
* multiplication, we'd like to skip it where possible. The best
|
||||
* bang for the buck seems to be to check whether both inputs are in
|
||||
* the int16 range; if so, no overflow is possible.
|
||||
* multiplication, we'd like to skip it where possible. The best bang for
|
||||
* the buck seems to be to check whether both inputs are in the int16
|
||||
* range; if so, no overflow is possible.
|
||||
*/
|
||||
if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
|
||||
result/arg2 != arg1)
|
||||
result / arg2 != arg1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("integer out of range")));
|
||||
@@ -985,10 +995,11 @@ int42pl(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 + arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum
|
||||
* had better be that sign too.
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum had
|
||||
* better be that sign too.
|
||||
*/
|
||||
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -1005,10 +1016,11 @@ int42mi(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 - arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then
|
||||
* the result should be of the same sign as the first input.
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then the
|
||||
* result should be of the same sign as the first input.
|
||||
*/
|
||||
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -1025,18 +1037,19 @@ int42mul(PG_FUNCTION_ARGS)
|
||||
int32 result;
|
||||
|
||||
result = arg1 * arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. We basically check to see if result / arg1 gives
|
||||
* arg2 again. There is one case where this fails: arg1 = 0 (which
|
||||
* cannot overflow).
|
||||
* Overflow check. We basically check to see if result / arg1 gives arg2
|
||||
* again. There is one case where this fails: arg1 = 0 (which cannot
|
||||
* overflow).
|
||||
*
|
||||
* Since the division is likely much more expensive than the actual
|
||||
* multiplication, we'd like to skip it where possible. The best
|
||||
* bang for the buck seems to be to check whether both inputs are in
|
||||
* the int16 range; if so, no overflow is possible.
|
||||
* multiplication, we'd like to skip it where possible. The best bang for
|
||||
* the buck seems to be to check whether both inputs are in the int16
|
||||
* range; if so, no overflow is possible.
|
||||
*/
|
||||
if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
|
||||
result/arg1 != arg2)
|
||||
result / arg1 != arg2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("integer out of range")));
|
||||
@@ -1056,10 +1069,11 @@ int42div(PG_FUNCTION_ARGS)
|
||||
errmsg("division by zero")));
|
||||
|
||||
result = arg1 / arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. The only possible overflow case is for
|
||||
* arg1 = INT_MIN, arg2 = -1, where the correct result is -INT_MIN,
|
||||
* which can't be represented on a two's-complement machine.
|
||||
* Overflow check. The only possible overflow case is for arg1 = INT_MIN,
|
||||
* arg2 = -1, where the correct result is -INT_MIN, which can't be
|
||||
* represented on a two's-complement machine.
|
||||
*/
|
||||
if (arg2 == -1 && arg1 < 0 && result < 0)
|
||||
ereport(ERROR,
|
||||
@@ -1352,8 +1366,7 @@ generate_series_step_int4(PG_FUNCTION_ARGS)
|
||||
funcctx = SRF_FIRSTCALL_INIT();
|
||||
|
||||
/*
|
||||
* switch to memory context appropriate for multiple function
|
||||
* calls
|
||||
* switch to memory context appropriate for multiple function calls
|
||||
*/
|
||||
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||
|
||||
@@ -1376,8 +1389,7 @@ generate_series_step_int4(PG_FUNCTION_ARGS)
|
||||
funcctx = SRF_PERCALL_SETUP();
|
||||
|
||||
/*
|
||||
* get the saved state and use current as the result for this
|
||||
* iteration
|
||||
* get the saved state and use current as the result for this iteration
|
||||
*/
|
||||
fctx = funcctx->user_fctx;
|
||||
result = fctx->current;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.58 2005/03/12 20:25:06 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.59 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -59,8 +59,8 @@ scanint8(const char *str, bool errorOK, int64 *result)
|
||||
int sign = 1;
|
||||
|
||||
/*
|
||||
* Do our own scan, rather than relying on sscanf which might be
|
||||
* broken for long long.
|
||||
* Do our own scan, rather than relying on sscanf which might be broken
|
||||
* for long long.
|
||||
*/
|
||||
|
||||
/* skip leading spaces */
|
||||
@@ -74,8 +74,7 @@ scanint8(const char *str, bool errorOK, int64 *result)
|
||||
|
||||
/*
|
||||
* Do an explicit check for INT64_MIN. Ugly though this is, it's
|
||||
* cleaner than trying to get the loop below to handle it
|
||||
* portably.
|
||||
* cleaner than trying to get the loop below to handle it portably.
|
||||
*/
|
||||
#ifndef INT64_IS_BUSTED
|
||||
if (strncmp(ptr, "9223372036854775808", 19) == 0)
|
||||
@@ -115,8 +114,8 @@ scanint8(const char *str, bool errorOK, int64 *result)
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("value \"%s\" is out of range for type bigint",
|
||||
str)));
|
||||
errmsg("value \"%s\" is out of range for type bigint",
|
||||
str)));
|
||||
}
|
||||
tmp = newtmp;
|
||||
}
|
||||
@@ -524,10 +523,11 @@ int8pl(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 + arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum
|
||||
* had better be that sign too.
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum had
|
||||
* better be that sign too.
|
||||
*/
|
||||
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -544,10 +544,11 @@ int8mi(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 - arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then
|
||||
* the result should be of the same sign as the first input.
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then the
|
||||
* result should be of the same sign as the first input.
|
||||
*/
|
||||
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -564,21 +565,22 @@ int8mul(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 * arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. We basically check to see if result / arg2 gives
|
||||
* arg1 again. There are two cases where this fails: arg2 = 0 (which
|
||||
* cannot overflow) and arg1 = INT64_MIN, arg2 = -1 (where the division
|
||||
* itself will overflow and thus incorrectly match).
|
||||
* Overflow check. We basically check to see if result / arg2 gives arg1
|
||||
* again. There are two cases where this fails: arg2 = 0 (which cannot
|
||||
* overflow) and arg1 = INT64_MIN, arg2 = -1 (where the division itself
|
||||
* will overflow and thus incorrectly match).
|
||||
*
|
||||
* Since the division is likely much more expensive than the actual
|
||||
* multiplication, we'd like to skip it where possible. The best
|
||||
* bang for the buck seems to be to check whether both inputs are in
|
||||
* the int32 range; if so, no overflow is possible.
|
||||
* multiplication, we'd like to skip it where possible. The best bang for
|
||||
* the buck seems to be to check whether both inputs are in the int32
|
||||
* range; if so, no overflow is possible.
|
||||
*/
|
||||
if (!(arg1 == (int64) ((int32) arg1) &&
|
||||
arg2 == (int64) ((int32) arg2)) &&
|
||||
arg2 != 0 &&
|
||||
(result/arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
|
||||
(result / arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("bigint out of range")));
|
||||
@@ -598,10 +600,11 @@ int8div(PG_FUNCTION_ARGS)
|
||||
errmsg("division by zero")));
|
||||
|
||||
result = arg1 / arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. The only possible overflow case is for
|
||||
* arg1 = INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN,
|
||||
* which can't be represented on a two's-complement machine.
|
||||
* Overflow check. The only possible overflow case is for arg1 =
|
||||
* INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
|
||||
* can't be represented on a two's-complement machine.
|
||||
*/
|
||||
if (arg2 == -1 && arg1 < 0 && result < 0)
|
||||
ereport(ERROR,
|
||||
@@ -653,9 +656,9 @@ int8inc(PG_FUNCTION_ARGS)
|
||||
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||
{
|
||||
/*
|
||||
* Special case to avoid palloc overhead for COUNT(): when called
|
||||
* from nodeAgg, we know that the argument is modifiable local
|
||||
* storage, so just update it in-place.
|
||||
* Special case to avoid palloc overhead for COUNT(): when called from
|
||||
* nodeAgg, we know that the argument is modifiable local storage, so
|
||||
* just update it in-place.
|
||||
*
|
||||
* Note: this assumes int8 is a pass-by-ref type; if we ever support
|
||||
* pass-by-val int8, this should be ifdef'd out when int8 is
|
||||
@@ -723,10 +726,11 @@ int84pl(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 + arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum
|
||||
* had better be that sign too.
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum had
|
||||
* better be that sign too.
|
||||
*/
|
||||
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -743,10 +747,11 @@ int84mi(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 - arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then
|
||||
* the result should be of the same sign as the first input.
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then the
|
||||
* result should be of the same sign as the first input.
|
||||
*/
|
||||
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -763,18 +768,19 @@ int84mul(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 * arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. We basically check to see if result / arg1 gives
|
||||
* arg2 again. There is one case where this fails: arg1 = 0 (which
|
||||
* cannot overflow).
|
||||
* Overflow check. We basically check to see if result / arg1 gives arg2
|
||||
* again. There is one case where this fails: arg1 = 0 (which cannot
|
||||
* overflow).
|
||||
*
|
||||
* Since the division is likely much more expensive than the actual
|
||||
* multiplication, we'd like to skip it where possible. The best
|
||||
* bang for the buck seems to be to check whether both inputs are in
|
||||
* the int32 range; if so, no overflow is possible.
|
||||
* multiplication, we'd like to skip it where possible. The best bang for
|
||||
* the buck seems to be to check whether both inputs are in the int32
|
||||
* range; if so, no overflow is possible.
|
||||
*/
|
||||
if (arg1 != (int64) ((int32) arg1) &&
|
||||
result/arg1 != arg2)
|
||||
result / arg1 != arg2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("bigint out of range")));
|
||||
@@ -794,10 +800,11 @@ int84div(PG_FUNCTION_ARGS)
|
||||
errmsg("division by zero")));
|
||||
|
||||
result = arg1 / arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. The only possible overflow case is for
|
||||
* arg1 = INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN,
|
||||
* which can't be represented on a two's-complement machine.
|
||||
* Overflow check. The only possible overflow case is for arg1 =
|
||||
* INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
|
||||
* can't be represented on a two's-complement machine.
|
||||
*/
|
||||
if (arg2 == -1 && arg1 < 0 && result < 0)
|
||||
ereport(ERROR,
|
||||
@@ -814,10 +821,11 @@ int48pl(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 + arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum
|
||||
* had better be that sign too.
|
||||
* Overflow check. If the inputs are of different signs then their sum
|
||||
* cannot overflow. If the inputs are of the same sign, their sum had
|
||||
* better be that sign too.
|
||||
*/
|
||||
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -834,10 +842,11 @@ int48mi(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 - arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then
|
||||
* the result should be of the same sign as the first input.
|
||||
* Overflow check. If the inputs are of the same sign then their
|
||||
* difference cannot overflow. If they are of different signs then the
|
||||
* result should be of the same sign as the first input.
|
||||
*/
|
||||
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
||||
ereport(ERROR,
|
||||
@@ -854,18 +863,19 @@ int48mul(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
result = arg1 * arg2;
|
||||
|
||||
/*
|
||||
* Overflow check. We basically check to see if result / arg2 gives
|
||||
* arg1 again. There is one case where this fails: arg2 = 0 (which
|
||||
* cannot overflow).
|
||||
* Overflow check. We basically check to see if result / arg2 gives arg1
|
||||
* again. There is one case where this fails: arg2 = 0 (which cannot
|
||||
* overflow).
|
||||
*
|
||||
* Since the division is likely much more expensive than the actual
|
||||
* multiplication, we'd like to skip it where possible. The best
|
||||
* bang for the buck seems to be to check whether both inputs are in
|
||||
* the int32 range; if so, no overflow is possible.
|
||||
* multiplication, we'd like to skip it where possible. The best bang for
|
||||
* the buck seems to be to check whether both inputs are in the int32
|
||||
* range; if so, no overflow is possible.
|
||||
*/
|
||||
if (arg2 != (int64) ((int32) arg2) &&
|
||||
result/arg2 != arg1)
|
||||
result / arg2 != arg1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("bigint out of range")));
|
||||
@@ -1027,9 +1037,9 @@ dtoi8(PG_FUNCTION_ARGS)
|
||||
arg = rint(arg);
|
||||
|
||||
/*
|
||||
* Does it fit in an int64? Avoid assuming that we have handy
|
||||
* constants defined for the range boundaries, instead test for
|
||||
* overflow by reverse-conversion.
|
||||
* Does it fit in an int64? Avoid assuming that we have handy constants
|
||||
* defined for the range boundaries, instead test for overflow by
|
||||
* reverse-conversion.
|
||||
*/
|
||||
result = (int64) arg;
|
||||
|
||||
@@ -1066,9 +1076,9 @@ ftoi8(PG_FUNCTION_ARGS)
|
||||
darg = rint(arg);
|
||||
|
||||
/*
|
||||
* Does it fit in an int64? Avoid assuming that we have handy
|
||||
* constants defined for the range boundaries, instead test for
|
||||
* overflow by reverse-conversion.
|
||||
* Does it fit in an int64? Avoid assuming that we have handy constants
|
||||
* defined for the range boundaries, instead test for overflow by
|
||||
* reverse-conversion.
|
||||
*/
|
||||
result = (int64) darg;
|
||||
|
||||
@@ -1183,8 +1193,7 @@ generate_series_step_int8(PG_FUNCTION_ARGS)
|
||||
funcctx = SRF_FIRSTCALL_INIT();
|
||||
|
||||
/*
|
||||
* switch to memory context appropriate for multiple function
|
||||
* calls
|
||||
* switch to memory context appropriate for multiple function calls
|
||||
*/
|
||||
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||
|
||||
@@ -1207,8 +1216,7 @@ generate_series_step_int8(PG_FUNCTION_ARGS)
|
||||
funcctx = SRF_PERCALL_SETUP();
|
||||
|
||||
/*
|
||||
* get the saved state and use current as the result for this
|
||||
* iteration
|
||||
* get the saved state and use current as the result for this iteration
|
||||
*/
|
||||
fctx = funcctx->user_fctx;
|
||||
result = fctx->current;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/like.c,v 1.61 2005/09/24 17:53:15 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/like.c,v 1.62 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -28,13 +28,13 @@
|
||||
#define LIKE_ABORT (-1)
|
||||
|
||||
|
||||
static int MatchText(char *t, int tlen, char *p, int plen);
|
||||
static int MatchTextIC(char *t, int tlen, char *p, int plen);
|
||||
static int MatchBytea(char *t, int tlen, char *p, int plen);
|
||||
static int MatchText(char *t, int tlen, char *p, int plen);
|
||||
static int MatchTextIC(char *t, int tlen, char *p, int plen);
|
||||
static int MatchBytea(char *t, int tlen, char *p, int plen);
|
||||
static text *do_like_escape(text *, text *);
|
||||
|
||||
static int MBMatchText(char *t, int tlen, char *p, int plen);
|
||||
static int MBMatchTextIC(char *t, int tlen, char *p, int plen);
|
||||
static int MBMatchText(char *t, int tlen, char *p, int plen);
|
||||
static int MBMatchTextIC(char *t, int tlen, char *p, int plen);
|
||||
static text *MB_do_like_escape(text *, text *);
|
||||
|
||||
/*--------------------
|
||||
@@ -48,7 +48,7 @@ wchareq(char *p1, char *p2)
|
||||
int p1_len;
|
||||
|
||||
/* Optimization: quickly compare the first byte. */
|
||||
if(*p1 != *p2)
|
||||
if (*p1 != *p2)
|
||||
return (0);
|
||||
|
||||
p1_len = pg_mblen(p1);
|
||||
@@ -80,15 +80,15 @@ iwchareq(char *p1, char *p2)
|
||||
int l;
|
||||
|
||||
/*
|
||||
* short cut. if *p1 and *p2 is lower than CHARMAX, then we could
|
||||
* assume they are ASCII
|
||||
* short cut. if *p1 and *p2 is lower than CHARMAX, then we could assume
|
||||
* they are ASCII
|
||||
*/
|
||||
if ((unsigned char) *p1 < CHARMAX && (unsigned char) *p2 < CHARMAX)
|
||||
return (tolower((unsigned char) *p1) == tolower((unsigned char) *p2));
|
||||
|
||||
/*
|
||||
* if one of them is an ASCII while the other is not, then they must
|
||||
* be different characters
|
||||
* if one of them is an ASCII while the other is not, then they must be
|
||||
* different characters
|
||||
*/
|
||||
else if ((unsigned char) *p1 < CHARMAX || (unsigned char) *p2 < CHARMAX)
|
||||
return (0);
|
||||
@@ -452,7 +452,7 @@ like_escape_bytea(PG_FUNCTION_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
|
||||
errmsg("invalid escape string"),
|
||||
errhint("Escape string must be empty or one character.")));
|
||||
errhint("Escape string must be empty or one character.")));
|
||||
|
||||
e = VARDATA(esc);
|
||||
|
||||
@@ -466,9 +466,9 @@ like_escape_bytea(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, convert occurrences of the specified escape
|
||||
* character to '\', and double occurrences of '\' --- unless they
|
||||
* immediately follow an escape character!
|
||||
* Otherwise, convert occurrences of the specified escape character to
|
||||
* '\', and double occurrences of '\' --- unless they immediately
|
||||
* follow an escape character!
|
||||
*/
|
||||
afterescape = false;
|
||||
while (plen > 0)
|
||||
@@ -530,8 +530,8 @@ MatchBytea(char *t, int tlen, char *p, int plen)
|
||||
return LIKE_TRUE;
|
||||
|
||||
/*
|
||||
* Otherwise, scan for a text position at which we can match
|
||||
* the rest of the pattern.
|
||||
* Otherwise, scan for a text position at which we can match the
|
||||
* rest of the pattern.
|
||||
*/
|
||||
while (tlen > 0)
|
||||
{
|
||||
@@ -551,16 +551,16 @@ MatchBytea(char *t, int tlen, char *p, int plen)
|
||||
}
|
||||
|
||||
/*
|
||||
* End of text with no match, so no point in trying later
|
||||
* places to start matching this pattern.
|
||||
* End of text with no match, so no point in trying later places
|
||||
* to start matching this pattern.
|
||||
*/
|
||||
return LIKE_ABORT;
|
||||
}
|
||||
else if ((*p != '_') && !BYTEA_CHAREQ(t, p))
|
||||
{
|
||||
/*
|
||||
* Not the single-character wildcard and no explicit match?
|
||||
* Then time to quit...
|
||||
* Not the single-character wildcard and no explicit match? Then
|
||||
* time to quit...
|
||||
*/
|
||||
return LIKE_FALSE;
|
||||
}
|
||||
@@ -580,8 +580,8 @@ MatchBytea(char *t, int tlen, char *p, int plen)
|
||||
return LIKE_TRUE;
|
||||
|
||||
/*
|
||||
* End of text with no match, so no point in trying later places to
|
||||
* start matching this pattern.
|
||||
* End of text with no match, so no point in trying later places to start
|
||||
* matching this pattern.
|
||||
*/
|
||||
return LIKE_ABORT;
|
||||
} /* MatchBytea() */
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/like_match.c,v 1.11 2005/09/24 17:53:15 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/like_match.c,v 1.12 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -97,8 +97,8 @@ MatchText(char *t, int tlen, char *p, int plen)
|
||||
return LIKE_TRUE;
|
||||
|
||||
/*
|
||||
* Otherwise, scan for a text position at which we can match
|
||||
* the rest of the pattern.
|
||||
* Otherwise, scan for a text position at which we can match the
|
||||
* rest of the pattern.
|
||||
*/
|
||||
while (tlen > 0)
|
||||
{
|
||||
@@ -118,16 +118,16 @@ MatchText(char *t, int tlen, char *p, int plen)
|
||||
}
|
||||
|
||||
/*
|
||||
* End of text with no match, so no point in trying later
|
||||
* places to start matching this pattern.
|
||||
* End of text with no match, so no point in trying later places
|
||||
* to start matching this pattern.
|
||||
*/
|
||||
return LIKE_ABORT;
|
||||
}
|
||||
else if ((*p != '_') && !CHAREQ(t, p))
|
||||
{
|
||||
/*
|
||||
* Not the single-character wildcard and no explicit match?
|
||||
* Then time to quit...
|
||||
* Not the single-character wildcard and no explicit match? Then
|
||||
* time to quit...
|
||||
*/
|
||||
return LIKE_FALSE;
|
||||
}
|
||||
@@ -147,8 +147,8 @@ MatchText(char *t, int tlen, char *p, int plen)
|
||||
return LIKE_TRUE;
|
||||
|
||||
/*
|
||||
* End of text with no match, so no point in trying later places to
|
||||
* start matching this pattern.
|
||||
* End of text with no match, so no point in trying later places to start
|
||||
* matching this pattern.
|
||||
*/
|
||||
return LIKE_ABORT;
|
||||
} /* MatchText() */
|
||||
@@ -183,8 +183,8 @@ MatchTextIC(char *t, int tlen, char *p, int plen)
|
||||
return LIKE_TRUE;
|
||||
|
||||
/*
|
||||
* Otherwise, scan for a text position at which we can match
|
||||
* the rest of the pattern.
|
||||
* Otherwise, scan for a text position at which we can match the
|
||||
* rest of the pattern.
|
||||
*/
|
||||
while (tlen > 0)
|
||||
{
|
||||
@@ -204,16 +204,16 @@ MatchTextIC(char *t, int tlen, char *p, int plen)
|
||||
}
|
||||
|
||||
/*
|
||||
* End of text with no match, so no point in trying later
|
||||
* places to start matching this pattern.
|
||||
* End of text with no match, so no point in trying later places
|
||||
* to start matching this pattern.
|
||||
*/
|
||||
return LIKE_ABORT;
|
||||
}
|
||||
else if ((*p != '_') && !ICHAREQ(t, p))
|
||||
{
|
||||
/*
|
||||
* Not the single-character wildcard and no explicit match?
|
||||
* Then time to quit...
|
||||
* Not the single-character wildcard and no explicit match? Then
|
||||
* time to quit...
|
||||
*/
|
||||
return LIKE_FALSE;
|
||||
}
|
||||
@@ -233,8 +233,8 @@ MatchTextIC(char *t, int tlen, char *p, int plen)
|
||||
return LIKE_TRUE;
|
||||
|
||||
/*
|
||||
* End of text with no match, so no point in trying later places to
|
||||
* start matching this pattern.
|
||||
* End of text with no match, so no point in trying later places to start
|
||||
* matching this pattern.
|
||||
*/
|
||||
return LIKE_ABORT;
|
||||
} /* MatchTextIC() */
|
||||
@@ -289,7 +289,7 @@ do_like_escape(text *pat, text *esc)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
|
||||
errmsg("invalid escape string"),
|
||||
errhint("Escape string must be empty or one character.")));
|
||||
errhint("Escape string must be empty or one character.")));
|
||||
|
||||
e = VARDATA(esc);
|
||||
|
||||
@@ -303,9 +303,9 @@ do_like_escape(text *pat, text *esc)
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, convert occurrences of the specified escape
|
||||
* character to '\', and double occurrences of '\' --- unless they
|
||||
* immediately follow an escape character!
|
||||
* Otherwise, convert occurrences of the specified escape character to
|
||||
* '\', and double occurrences of '\' --- unless they immediately
|
||||
* follow an escape character!
|
||||
*/
|
||||
afterescape = false;
|
||||
while (plen > 0)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.19 2005/06/18 19:33:42 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.20 2005/10/15 02:49:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
|
||||
/* This must match enum LockTagType! */
|
||||
static const char * const LockTagTypeNames[] = {
|
||||
static const char *const LockTagTypeNames[] = {
|
||||
"relation",
|
||||
"extend",
|
||||
"page",
|
||||
@@ -57,8 +57,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
|
||||
funcctx = SRF_FIRSTCALL_INIT();
|
||||
|
||||
/*
|
||||
* switch to memory context appropriate for multiple function
|
||||
* calls
|
||||
* switch to memory context appropriate for multiple function calls
|
||||
*/
|
||||
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||
|
||||
@@ -95,8 +94,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
|
||||
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
|
||||
|
||||
/*
|
||||
* Collect all the locking information that we will format and
|
||||
* send out as a result set.
|
||||
* Collect all the locking information that we will format and send
|
||||
* out as a result set.
|
||||
*/
|
||||
mystatus = (PG_Lock_Status *) palloc(sizeof(PG_Lock_Status));
|
||||
funcctx->user_fctx = (void *) mystatus;
|
||||
@@ -130,9 +129,9 @@ pg_lock_status(PG_FUNCTION_ARGS)
|
||||
proc = &(lockData->procs[mystatus->currIdx]);
|
||||
|
||||
/*
|
||||
* Look to see if there are any held lock modes in this PROCLOCK.
|
||||
* If so, report, and destructively modify lockData so we don't
|
||||
* report again.
|
||||
* Look to see if there are any held lock modes in this PROCLOCK. If
|
||||
* so, report, and destructively modify lockData so we don't report
|
||||
* again.
|
||||
*/
|
||||
granted = false;
|
||||
if (proclock->holdMask)
|
||||
@@ -160,16 +159,16 @@ pg_lock_status(PG_FUNCTION_ARGS)
|
||||
mode = proc->waitLockMode;
|
||||
|
||||
/*
|
||||
* We are now done with this PROCLOCK, so advance pointer
|
||||
* to continue with next one on next call.
|
||||
* We are now done with this PROCLOCK, so advance pointer to
|
||||
* continue with next one on next call.
|
||||
*/
|
||||
mystatus->currIdx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Okay, we've displayed all the locks associated with
|
||||
* this PROCLOCK, proceed to the next one.
|
||||
* Okay, we've displayed all the locks associated with this
|
||||
* PROCLOCK, proceed to the next one.
|
||||
*/
|
||||
mystatus->currIdx++;
|
||||
continue;
|
||||
@@ -191,7 +190,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
|
||||
locktypename = tnbuf;
|
||||
}
|
||||
values[0] = DirectFunctionCall1(textin,
|
||||
CStringGetDatum(locktypename));
|
||||
CStringGetDatum(locktypename));
|
||||
|
||||
|
||||
switch (lock->tag.locktag_type)
|
||||
@@ -257,7 +256,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
|
||||
else
|
||||
nulls[10] = 'n';
|
||||
values[11] = DirectFunctionCall1(textin,
|
||||
CStringGetDatum(GetLockmodeName(mode)));
|
||||
CStringGetDatum(GetLockmodeName(mode)));
|
||||
values[12] = BoolGetDatum(granted);
|
||||
|
||||
tuple = heap_formtuple(funcctx->tuple_desc, values, nulls);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* PostgreSQL type definitions for MAC addresses.
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/mac.c,v 1.34 2004/08/29 05:06:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/mac.c,v 1.35 2005/10/15 02:49:28 momjian Exp $
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
@@ -62,14 +62,14 @@ macaddr_in(PG_FUNCTION_ARGS)
|
||||
if (count != 6)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type macaddr: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type macaddr: \"%s\"", str)));
|
||||
|
||||
if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
|
||||
(c < 0) || (c > 255) || (d < 0) || (d > 255) ||
|
||||
(e < 0) || (e > 255) || (f < 0) || (f > 255))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
|
||||
errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
|
||||
|
||||
result = (macaddr *) palloc(sizeof(macaddr));
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.48 2005/09/16 05:35:40 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.49 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -79,16 +79,16 @@ pg_signal_backend(int pid, int sig)
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("must be superuser to signal other server processes"))));
|
||||
(errmsg("must be superuser to signal other server processes"))));
|
||||
|
||||
if (!IsBackendPid(pid))
|
||||
{
|
||||
/*
|
||||
* This is just a warning so a loop-through-resultset will not
|
||||
* abort if one backend terminated on it's own during the run
|
||||
* This is just a warning so a loop-through-resultset will not abort
|
||||
* if one backend terminated on it's own during the run
|
||||
*/
|
||||
ereport(WARNING,
|
||||
(errmsg("PID %d is not a PostgreSQL server process", pid)));
|
||||
(errmsg("PID %d is not a PostgreSQL server process", pid)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ pg_cancel_backend(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_reload_conf(PG_FUNCTION_ARGS)
|
||||
{
|
||||
if (!superuser())
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("must be superuser to signal the postmaster"))));
|
||||
@@ -133,7 +133,7 @@ pg_reload_conf(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_rotate_logfile(PG_FUNCTION_ARGS)
|
||||
{
|
||||
if (!superuser())
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("must be superuser to rotate log files"))));
|
||||
@@ -141,7 +141,7 @@ pg_rotate_logfile(PG_FUNCTION_ARGS)
|
||||
if (!Redirect_stderr)
|
||||
{
|
||||
ereport(WARNING,
|
||||
(errmsg("rotation not possible because log redirection not active")));
|
||||
(errmsg("rotation not possible because log redirection not active")));
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
|
||||
@@ -186,8 +186,7 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
|
||||
fctx = palloc(sizeof(ts_db_fctx));
|
||||
|
||||
/*
|
||||
* size = tablespace dirname length + dir sep
|
||||
* char + oid + terminator
|
||||
* size = tablespace dirname length + dir sep char + oid + terminator
|
||||
*/
|
||||
fctx->location = (char *) palloc(10 + 10 + 1);
|
||||
if (tablespaceOid == GLOBALTABLESPACE_OID)
|
||||
@@ -214,7 +213,7 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
|
||||
errmsg("could not open directory \"%s\": %m",
|
||||
fctx->location)));
|
||||
ereport(WARNING,
|
||||
(errmsg("%u is not a tablespace OID", tablespaceOid)));
|
||||
(errmsg("%u is not a tablespace OID", tablespaceOid)));
|
||||
}
|
||||
}
|
||||
funcctx->user_fctx = fctx;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.144 2005/10/14 11:47:57 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.145 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -77,11 +77,11 @@
|
||||
* Function prototypes -- internal to this file only
|
||||
*/
|
||||
|
||||
static AbsoluteTime tm2abstime(struct pg_tm *tm, int tz);
|
||||
static void reltime2tm(RelativeTime time, struct pg_tm *tm);
|
||||
static AbsoluteTime tm2abstime(struct pg_tm * tm, int tz);
|
||||
static void reltime2tm(RelativeTime time, struct pg_tm * tm);
|
||||
static void parsetinterval(char *i_string,
|
||||
AbsoluteTime *i_start,
|
||||
AbsoluteTime *i_end);
|
||||
AbsoluteTime *i_start,
|
||||
AbsoluteTime *i_end);
|
||||
|
||||
|
||||
/*
|
||||
@@ -100,21 +100,21 @@ GetCurrentAbsoluteTime(void)
|
||||
|
||||
|
||||
void
|
||||
abstime2tm(AbsoluteTime _time, int *tzp, struct pg_tm *tm, char **tzn)
|
||||
abstime2tm(AbsoluteTime _time, int *tzp, struct pg_tm * tm, char **tzn)
|
||||
{
|
||||
pg_time_t time = (pg_time_t) _time;
|
||||
struct pg_tm *tx;
|
||||
|
||||
/*
|
||||
* If HasCTZSet is true then we have a brute force time zone
|
||||
* specified. Go ahead and rotate to the local time zone since we will
|
||||
* later bypass any calls which adjust the tm fields.
|
||||
* If HasCTZSet is true then we have a brute force time zone specified. Go
|
||||
* ahead and rotate to the local time zone since we will later bypass any
|
||||
* calls which adjust the tm fields.
|
||||
*/
|
||||
if (HasCTZSet && (tzp != NULL))
|
||||
time -= CTimeZone;
|
||||
|
||||
if (!HasCTZSet && tzp != NULL)
|
||||
tx = pg_localtime(&time,global_timezone);
|
||||
tx = pg_localtime(&time, global_timezone);
|
||||
else
|
||||
tx = pg_gmtime(&time);
|
||||
|
||||
@@ -156,8 +156,8 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct pg_tm *tm, char **tzn)
|
||||
{
|
||||
/*
|
||||
* Copy no more than MAXTZLEN bytes of timezone to tzn, in
|
||||
* case it contains an error message, which doesn't fit in
|
||||
* the buffer
|
||||
* case it contains an error message, which doesn't fit in the
|
||||
* buffer
|
||||
*/
|
||||
StrNCpy(*tzn, tm->tm_zone, MAXTZLEN + 1);
|
||||
if (strlen(tm->tm_zone) > MAXTZLEN)
|
||||
@@ -178,7 +178,7 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct pg_tm *tm, char **tzn)
|
||||
* Note that tm has full year (not 1900-based) and 1-based month.
|
||||
*/
|
||||
static AbsoluteTime
|
||||
tm2abstime(struct pg_tm *tm, int tz)
|
||||
tm2abstime(struct pg_tm * tm, int tz)
|
||||
{
|
||||
int day;
|
||||
AbsoluteTime sec;
|
||||
@@ -188,7 +188,7 @@ tm2abstime(struct pg_tm *tm, int tz)
|
||||
tm->tm_mon < 1 || tm->tm_mon > 12 ||
|
||||
tm->tm_mday < 1 || tm->tm_mday > 31 ||
|
||||
tm->tm_hour < 0 ||
|
||||
tm->tm_hour > 24 || /* test for > 24:00:00 */
|
||||
tm->tm_hour > 24 || /* test for > 24:00:00 */
|
||||
(tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)) ||
|
||||
tm->tm_min < 0 || tm->tm_min > 59 ||
|
||||
tm->tm_sec < 0 || tm->tm_sec > 60)
|
||||
@@ -204,11 +204,11 @@ tm2abstime(struct pg_tm *tm, int tz)
|
||||
sec = tm->tm_sec + tz + (tm->tm_min + (day * HOURS_PER_DAY + tm->tm_hour) * MINS_PER_HOUR) * SECS_PER_MINUTE;
|
||||
|
||||
/*
|
||||
* check for overflow. We need a little slop here because the H/M/S plus
|
||||
* check for overflow. We need a little slop here because the H/M/S plus
|
||||
* TZ offset could add up to more than 1 day.
|
||||
*/
|
||||
if ((day >= MAX_DAYNUM-10 && sec < 0) ||
|
||||
(day <= MIN_DAYNUM+10 && sec > 0))
|
||||
if ((day >= MAX_DAYNUM - 10 && sec < 0) ||
|
||||
(day <= MIN_DAYNUM + 10 && sec > 0))
|
||||
return INVALID_ABSTIME;
|
||||
|
||||
/* check for reserved values (e.g. "current" on edge of usual range */
|
||||
@@ -254,8 +254,8 @@ abstimein(PG_FUNCTION_ARGS)
|
||||
case DTK_EPOCH:
|
||||
|
||||
/*
|
||||
* Don't bother retaining this as a reserved value, but
|
||||
* instead just set to the actual epoch time (1970-01-01)
|
||||
* Don't bother retaining this as a reserved value, but instead
|
||||
* just set to the actual epoch time (1970-01-01)
|
||||
*/
|
||||
result = 0;
|
||||
break;
|
||||
@@ -370,9 +370,9 @@ static int
|
||||
abstime_cmp_internal(AbsoluteTime a, AbsoluteTime b)
|
||||
{
|
||||
/*
|
||||
* We consider all INVALIDs to be equal and larger than any
|
||||
* non-INVALID. This is somewhat arbitrary; the important thing is to
|
||||
* have a consistent sort order.
|
||||
* We consider all INVALIDs to be equal and larger than any non-INVALID.
|
||||
* This is somewhat arbitrary; the important thing is to have a consistent
|
||||
* sort order.
|
||||
*/
|
||||
if (a == INVALID_ABSTIME)
|
||||
{
|
||||
@@ -463,7 +463,7 @@ btabstimecmp(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
timestamp_abstime(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
|
||||
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
|
||||
AbsoluteTime result;
|
||||
fsec_t fsec;
|
||||
int tz;
|
||||
@@ -509,7 +509,7 @@ abstime_timestamp(PG_FUNCTION_ARGS)
|
||||
case INVALID_ABSTIME:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot convert abstime \"invalid\" to timestamp")));
|
||||
errmsg("cannot convert abstime \"invalid\" to timestamp")));
|
||||
TIMESTAMP_NOBEGIN(result);
|
||||
break;
|
||||
|
||||
@@ -582,7 +582,7 @@ abstime_timestamptz(PG_FUNCTION_ARGS)
|
||||
case INVALID_ABSTIME:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot convert abstime \"invalid\" to timestamp")));
|
||||
errmsg("cannot convert abstime \"invalid\" to timestamp")));
|
||||
TIMESTAMP_NOBEGIN(result);
|
||||
break;
|
||||
|
||||
@@ -703,7 +703,7 @@ reltimesend(PG_FUNCTION_ARGS)
|
||||
|
||||
|
||||
static void
|
||||
reltime2tm(RelativeTime time, struct pg_tm *tm)
|
||||
reltime2tm(RelativeTime time, struct pg_tm * tm)
|
||||
{
|
||||
double dtime = time;
|
||||
|
||||
@@ -764,12 +764,12 @@ tintervalout(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
p = DatumGetCString(DirectFunctionCall1(abstimeout,
|
||||
AbsoluteTimeGetDatum(tinterval->data[0])));
|
||||
AbsoluteTimeGetDatum(tinterval->data[0])));
|
||||
strcat(i_str, p);
|
||||
pfree(p);
|
||||
strcat(i_str, "\" \"");
|
||||
p = DatumGetCString(DirectFunctionCall1(abstimeout,
|
||||
AbsoluteTimeGetDatum(tinterval->data[1])));
|
||||
AbsoluteTimeGetDatum(tinterval->data[1])));
|
||||
strcat(i_str, p);
|
||||
pfree(p);
|
||||
}
|
||||
@@ -788,16 +788,16 @@ tintervalrecv(PG_FUNCTION_ARGS)
|
||||
|
||||
tinterval = (TimeInterval) palloc(sizeof(TimeIntervalData));
|
||||
|
||||
tinterval ->status = pq_getmsgint(buf, sizeof(tinterval->status));
|
||||
tinterval->status = pq_getmsgint(buf, sizeof(tinterval->status));
|
||||
|
||||
if (!(tinterval->status == T_INTERVAL_INVAL ||
|
||||
tinterval->status == T_INTERVAL_VALID))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("invalid status in external \"tinterval\" value")));
|
||||
errmsg("invalid status in external \"tinterval\" value")));
|
||||
|
||||
tinterval ->data[0] = pq_getmsgint(buf, sizeof(tinterval->data[0]));
|
||||
tinterval ->data[1] = pq_getmsgint(buf, sizeof(tinterval->data[1]));
|
||||
tinterval->data[0] = pq_getmsgint(buf, sizeof(tinterval->data[0]));
|
||||
tinterval->data[1] = pq_getmsgint(buf, sizeof(tinterval->data[1]));
|
||||
|
||||
PG_RETURN_TIMEINTERVAL(tinterval);
|
||||
}
|
||||
@@ -844,11 +844,11 @@ interval_reltime(PG_FUNCTION_ARGS)
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
span = ((INT64CONST(365250000) * year + INT64CONST(30000000) * month +
|
||||
INT64CONST(1000000) * day) * INT64CONST(86400)) +
|
||||
interval->time;
|
||||
INT64CONST(1000000) * day) * INT64CONST(86400)) +
|
||||
interval->time;
|
||||
span /= USECS_PER_SEC;
|
||||
#else
|
||||
span = (DAYS_PER_YEAR * year + (double)DAYS_PER_MONTH * month + day) * SECS_PER_DAY + interval->time;
|
||||
span = (DAYS_PER_YEAR * year + (double) DAYS_PER_MONTH * month + day) * SECS_PER_DAY + interval->time;
|
||||
#endif
|
||||
|
||||
if (span < INT_MIN || span > INT_MAX)
|
||||
@@ -876,7 +876,7 @@ reltime_interval(PG_FUNCTION_ARGS)
|
||||
case INVALID_RELTIME:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot convert reltime \"invalid\" to interval")));
|
||||
errmsg("cannot convert reltime \"invalid\" to interval")));
|
||||
result->time = 0;
|
||||
result->day = 0;
|
||||
result->month = 0;
|
||||
@@ -954,7 +954,7 @@ timepl(PG_FUNCTION_ARGS)
|
||||
if (AbsoluteTimeIsReal(t1) &&
|
||||
RelativeTimeIsValid(t2) &&
|
||||
((t2 > 0 && t1 < NOEND_ABSTIME - t2) ||
|
||||
(t2 <= 0 && t1 > NOSTART_ABSTIME - t2))) /* prevent overflow */
|
||||
(t2 <= 0 && t1 > NOSTART_ABSTIME - t2))) /* prevent overflow */
|
||||
PG_RETURN_ABSOLUTETIME(t1 + t2);
|
||||
|
||||
PG_RETURN_ABSOLUTETIME(INVALID_ABSTIME);
|
||||
@@ -973,7 +973,7 @@ timemi(PG_FUNCTION_ARGS)
|
||||
if (AbsoluteTimeIsReal(t1) &&
|
||||
RelativeTimeIsValid(t2) &&
|
||||
((t2 > 0 && t1 > NOSTART_ABSTIME + t2) ||
|
||||
(t2 <= 0 && t1 < NOEND_ABSTIME + t2))) /* prevent overflow */
|
||||
(t2 <= 0 && t1 < NOEND_ABSTIME + t2))) /* prevent overflow */
|
||||
PG_RETURN_ABSOLUTETIME(t1 - t2);
|
||||
|
||||
PG_RETURN_ABSOLUTETIME(INVALID_ABSTIME);
|
||||
@@ -993,10 +993,10 @@ intinterval(PG_FUNCTION_ARGS)
|
||||
{
|
||||
if (DatumGetBool(DirectFunctionCall2(abstimege,
|
||||
AbsoluteTimeGetDatum(t),
|
||||
AbsoluteTimeGetDatum(tinterval->data[0]))) &&
|
||||
AbsoluteTimeGetDatum(tinterval->data[0]))) &&
|
||||
DatumGetBool(DirectFunctionCall2(abstimele,
|
||||
AbsoluteTimeGetDatum(t),
|
||||
AbsoluteTimeGetDatum(tinterval->data[1]))))
|
||||
AbsoluteTimeGetDatum(tinterval->data[1]))))
|
||||
PG_RETURN_BOOL(true);
|
||||
}
|
||||
PG_RETURN_BOOL(false);
|
||||
@@ -1046,9 +1046,9 @@ static int
|
||||
reltime_cmp_internal(RelativeTime a, RelativeTime b)
|
||||
{
|
||||
/*
|
||||
* We consider all INVALIDs to be equal and larger than any
|
||||
* non-INVALID. This is somewhat arbitrary; the important thing is to
|
||||
* have a consistent sort order.
|
||||
* We consider all INVALIDs to be equal and larger than any non-INVALID.
|
||||
* This is somewhat arbitrary; the important thing is to have a consistent
|
||||
* sort order.
|
||||
*/
|
||||
if (a == INVALID_RELTIME)
|
||||
{
|
||||
@@ -1147,11 +1147,11 @@ tintervalsame(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_BOOL(false);
|
||||
|
||||
if (DatumGetBool(DirectFunctionCall2(abstimeeq,
|
||||
AbsoluteTimeGetDatum(i1->data[0]),
|
||||
AbsoluteTimeGetDatum(i2->data[0]))) &&
|
||||
AbsoluteTimeGetDatum(i1->data[0]),
|
||||
AbsoluteTimeGetDatum(i2->data[0]))) &&
|
||||
DatumGetBool(DirectFunctionCall2(abstimeeq,
|
||||
AbsoluteTimeGetDatum(i1->data[1]),
|
||||
AbsoluteTimeGetDatum(i2->data[1]))))
|
||||
AbsoluteTimeGetDatum(i1->data[1]),
|
||||
AbsoluteTimeGetDatum(i2->data[1]))))
|
||||
PG_RETURN_BOOL(true);
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
@@ -1172,16 +1172,16 @@ tinterval_cmp_internal(TimeInterval a, TimeInterval b)
|
||||
AbsoluteTime b_len;
|
||||
|
||||
/*
|
||||
* We consider all INVALIDs to be equal and larger than any
|
||||
* non-INVALID. This is somewhat arbitrary; the important thing is to
|
||||
* have a consistent sort order.
|
||||
* We consider all INVALIDs to be equal and larger than any non-INVALID.
|
||||
* This is somewhat arbitrary; the important thing is to have a consistent
|
||||
* sort order.
|
||||
*/
|
||||
a_invalid = a->status == T_INTERVAL_INVAL ||
|
||||
a->data[0] == INVALID_ABSTIME ||
|
||||
a->data[1] == INVALID_ABSTIME;
|
||||
a->data[0] == INVALID_ABSTIME ||
|
||||
a->data[1] == INVALID_ABSTIME;
|
||||
b_invalid = b->status == T_INTERVAL_INVAL ||
|
||||
b->data[0] == INVALID_ABSTIME ||
|
||||
b->data[1] == INVALID_ABSTIME;
|
||||
b->data[0] == INVALID_ABSTIME ||
|
||||
b->data[1] == INVALID_ABSTIME;
|
||||
|
||||
if (a_invalid)
|
||||
{
|
||||
@@ -1293,7 +1293,7 @@ tintervalleneq(PG_FUNCTION_ARGS)
|
||||
if (i->status == T_INTERVAL_INVAL || t == INVALID_RELTIME)
|
||||
PG_RETURN_BOOL(false);
|
||||
rt = DatumGetRelativeTime(DirectFunctionCall1(tintervalrel,
|
||||
TimeIntervalGetDatum(i)));
|
||||
TimeIntervalGetDatum(i)));
|
||||
PG_RETURN_BOOL(rt != INVALID_RELTIME && rt == t);
|
||||
}
|
||||
|
||||
@@ -1307,7 +1307,7 @@ tintervallenne(PG_FUNCTION_ARGS)
|
||||
if (i->status == T_INTERVAL_INVAL || t == INVALID_RELTIME)
|
||||
PG_RETURN_BOOL(false);
|
||||
rt = DatumGetRelativeTime(DirectFunctionCall1(tintervalrel,
|
||||
TimeIntervalGetDatum(i)));
|
||||
TimeIntervalGetDatum(i)));
|
||||
PG_RETURN_BOOL(rt != INVALID_RELTIME && rt != t);
|
||||
}
|
||||
|
||||
@@ -1321,7 +1321,7 @@ tintervallenlt(PG_FUNCTION_ARGS)
|
||||
if (i->status == T_INTERVAL_INVAL || t == INVALID_RELTIME)
|
||||
PG_RETURN_BOOL(false);
|
||||
rt = DatumGetRelativeTime(DirectFunctionCall1(tintervalrel,
|
||||
TimeIntervalGetDatum(i)));
|
||||
TimeIntervalGetDatum(i)));
|
||||
PG_RETURN_BOOL(rt != INVALID_RELTIME && rt < t);
|
||||
}
|
||||
|
||||
@@ -1335,7 +1335,7 @@ tintervallengt(PG_FUNCTION_ARGS)
|
||||
if (i->status == T_INTERVAL_INVAL || t == INVALID_RELTIME)
|
||||
PG_RETURN_BOOL(false);
|
||||
rt = DatumGetRelativeTime(DirectFunctionCall1(tintervalrel,
|
||||
TimeIntervalGetDatum(i)));
|
||||
TimeIntervalGetDatum(i)));
|
||||
PG_RETURN_BOOL(rt != INVALID_RELTIME && rt > t);
|
||||
}
|
||||
|
||||
@@ -1349,7 +1349,7 @@ tintervallenle(PG_FUNCTION_ARGS)
|
||||
if (i->status == T_INTERVAL_INVAL || t == INVALID_RELTIME)
|
||||
PG_RETURN_BOOL(false);
|
||||
rt = DatumGetRelativeTime(DirectFunctionCall1(tintervalrel,
|
||||
TimeIntervalGetDatum(i)));
|
||||
TimeIntervalGetDatum(i)));
|
||||
PG_RETURN_BOOL(rt != INVALID_RELTIME && rt <= t);
|
||||
}
|
||||
|
||||
@@ -1363,7 +1363,7 @@ tintervallenge(PG_FUNCTION_ARGS)
|
||||
if (i->status == T_INTERVAL_INVAL || t == INVALID_RELTIME)
|
||||
PG_RETURN_BOOL(false);
|
||||
rt = DatumGetRelativeTime(DirectFunctionCall1(tintervalrel,
|
||||
TimeIntervalGetDatum(i)));
|
||||
TimeIntervalGetDatum(i)));
|
||||
PG_RETURN_BOOL(rt != INVALID_RELTIME && rt >= t);
|
||||
}
|
||||
|
||||
@@ -1379,11 +1379,11 @@ tintervalct(PG_FUNCTION_ARGS)
|
||||
if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
|
||||
PG_RETURN_BOOL(false);
|
||||
if (DatumGetBool(DirectFunctionCall2(abstimele,
|
||||
AbsoluteTimeGetDatum(i1->data[0]),
|
||||
AbsoluteTimeGetDatum(i2->data[0]))) &&
|
||||
AbsoluteTimeGetDatum(i1->data[0]),
|
||||
AbsoluteTimeGetDatum(i2->data[0]))) &&
|
||||
DatumGetBool(DirectFunctionCall2(abstimege,
|
||||
AbsoluteTimeGetDatum(i1->data[1]),
|
||||
AbsoluteTimeGetDatum(i2->data[1]))))
|
||||
AbsoluteTimeGetDatum(i1->data[1]),
|
||||
AbsoluteTimeGetDatum(i2->data[1]))))
|
||||
PG_RETURN_BOOL(true);
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
@@ -1400,11 +1400,11 @@ tintervalov(PG_FUNCTION_ARGS)
|
||||
if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
|
||||
PG_RETURN_BOOL(false);
|
||||
if (DatumGetBool(DirectFunctionCall2(abstimelt,
|
||||
AbsoluteTimeGetDatum(i1->data[1]),
|
||||
AbsoluteTimeGetDatum(i2->data[0]))) ||
|
||||
AbsoluteTimeGetDatum(i1->data[1]),
|
||||
AbsoluteTimeGetDatum(i2->data[0]))) ||
|
||||
DatumGetBool(DirectFunctionCall2(abstimegt,
|
||||
AbsoluteTimeGetDatum(i1->data[0]),
|
||||
AbsoluteTimeGetDatum(i2->data[1]))))
|
||||
AbsoluteTimeGetDatum(i1->data[0]),
|
||||
AbsoluteTimeGetDatum(i2->data[1]))))
|
||||
PG_RETURN_BOOL(false);
|
||||
PG_RETURN_BOOL(true);
|
||||
}
|
||||
@@ -1492,8 +1492,7 @@ parsetinterval(char *i_string,
|
||||
goto bogus; /* syntax error */
|
||||
p++;
|
||||
if (strncmp(INVALID_INTERVAL_STR, p, strlen(INVALID_INTERVAL_STR)) == 0)
|
||||
goto bogus; /* undefined range, handled like a syntax
|
||||
* err. */
|
||||
goto bogus; /* undefined range, handled like a syntax err. */
|
||||
/* search for the end of the first date and change it to a \0 */
|
||||
p1 = p;
|
||||
while ((c = *p1) != '\0')
|
||||
@@ -1507,7 +1506,7 @@ parsetinterval(char *i_string,
|
||||
*p1 = '\0';
|
||||
/* get the first date */
|
||||
*i_start = DatumGetAbsoluteTime(DirectFunctionCall1(abstimein,
|
||||
CStringGetDatum(p)));
|
||||
CStringGetDatum(p)));
|
||||
/* undo change to \0 */
|
||||
*p1 = c;
|
||||
p = ++p1;
|
||||
@@ -1537,7 +1536,7 @@ parsetinterval(char *i_string,
|
||||
*p1 = '\0';
|
||||
/* get the second date */
|
||||
*i_end = DatumGetAbsoluteTime(DirectFunctionCall1(abstimein,
|
||||
CStringGetDatum(p)));
|
||||
CStringGetDatum(p)));
|
||||
/* undo change to \0 */
|
||||
*p1 = c;
|
||||
p = ++p1;
|
||||
@@ -1566,7 +1565,7 @@ bogus:
|
||||
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
|
||||
errmsg("invalid input syntax for type tinterval: \"%s\"",
|
||||
i_string)));
|
||||
*i_start = *i_end = INVALID_ABSTIME; /* keep compiler quiet */
|
||||
*i_start = *i_end = INVALID_ABSTIME; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
|
||||
@@ -1595,7 +1594,7 @@ timeofday(PG_FUNCTION_ARGS)
|
||||
gettimeofday(&tp, &tpz);
|
||||
tt = (pg_time_t) tp.tv_sec;
|
||||
pg_strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z",
|
||||
pg_localtime(&tt,global_timezone));
|
||||
pg_localtime(&tt, global_timezone));
|
||||
snprintf(buf, sizeof(buf), templ, tp.tv_usec);
|
||||
|
||||
len = VARHDRSZ + strlen(buf);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/name.c,v 1.55 2004/12/31 22:01:22 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/name.c,v 1.56 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -258,8 +258,8 @@ namecpy(Name n1, Name n2)
|
||||
int
|
||||
namecat(Name n1, Name n2)
|
||||
{
|
||||
return namestrcat(n1, NameStr(*n2)); /* n2 can't be any longer
|
||||
* than n1 */
|
||||
return namestrcat(n1, NameStr(*n2)); /* n2 can't be any longer than
|
||||
* n1 */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* PostgreSQL type definitions for the INET and CIDR types.
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.54 2004/10/08 01:10:31 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.55 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
* Jon Postel RIP 16 Oct 1998
|
||||
*/
|
||||
@@ -74,9 +74,9 @@ network_in(char *src, int type)
|
||||
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
|
||||
|
||||
/*
|
||||
* First, check to see if this is an IPv6 or IPv4 address. IPv6
|
||||
* addresses will have a : somewhere in them (several, in fact) so if
|
||||
* there is one present, assume it's V6, otherwise assume it's V4.
|
||||
* First, check to see if this is an IPv6 or IPv4 address. IPv6 addresses
|
||||
* will have a : somewhere in them (several, in fact) so if there is one
|
||||
* present, assume it's V6, otherwise assume it's V4.
|
||||
*/
|
||||
|
||||
if (strchr(src, ':') != NULL)
|
||||
@@ -94,8 +94,7 @@ network_in(char *src, int type)
|
||||
type ? "cidr" : "inet", src)));
|
||||
|
||||
/*
|
||||
* Error check: CIDR values must not have any bits set beyond the
|
||||
* masklen.
|
||||
* Error check: CIDR values must not have any bits set beyond the masklen.
|
||||
*/
|
||||
if (type)
|
||||
{
|
||||
@@ -195,7 +194,7 @@ inet_recv(PG_FUNCTION_ARGS)
|
||||
ip_family(addr) != PGSQL_AF_INET6)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("invalid address family in external \"inet\" value")));
|
||||
errmsg("invalid address family in external \"inet\" value")));
|
||||
bits = pq_getmsgbyte(buf);
|
||||
if (bits < 0 || bits > ip_maxbits(addr))
|
||||
ereport(ERROR,
|
||||
@@ -221,8 +220,7 @@ inet_recv(PG_FUNCTION_ARGS)
|
||||
addrptr[i] = pq_getmsgbyte(buf);
|
||||
|
||||
/*
|
||||
* Error check: CIDR values must not have any bits set beyond the
|
||||
* masklen.
|
||||
* Error check: CIDR values must not have any bits set beyond the masklen.
|
||||
*/
|
||||
if (ip_type(addr))
|
||||
{
|
||||
@@ -457,7 +455,7 @@ network_sub(PG_FUNCTION_ARGS)
|
||||
if (ip_family(a1) == ip_family(a2))
|
||||
{
|
||||
PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2)
|
||||
&& bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
|
||||
&& bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
|
||||
}
|
||||
|
||||
PG_RETURN_BOOL(false);
|
||||
@@ -472,7 +470,7 @@ network_subeq(PG_FUNCTION_ARGS)
|
||||
if (ip_family(a1) == ip_family(a2))
|
||||
{
|
||||
PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2)
|
||||
&& bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
|
||||
&& bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
|
||||
}
|
||||
|
||||
PG_RETURN_BOOL(false);
|
||||
@@ -487,7 +485,7 @@ network_sup(PG_FUNCTION_ARGS)
|
||||
if (ip_family(a1) == ip_family(a2))
|
||||
{
|
||||
PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2)
|
||||
&& bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
|
||||
&& bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
|
||||
}
|
||||
|
||||
PG_RETURN_BOOL(false);
|
||||
@@ -502,7 +500,7 @@ network_supeq(PG_FUNCTION_ARGS)
|
||||
if (ip_family(a1) == ip_family(a2))
|
||||
{
|
||||
PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2)
|
||||
&& bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
|
||||
&& bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
|
||||
}
|
||||
|
||||
PG_RETURN_BOOL(false);
|
||||
@@ -870,8 +868,8 @@ convert_network_to_scalar(Datum value, Oid typid)
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't get here unless someone tries to use scalarltsel/scalargtsel
|
||||
* on an operator with one network and one non-network operand.
|
||||
* Can't get here unless someone tries to use scalarltsel/scalargtsel on
|
||||
* an operator with one network and one non-network operand.
|
||||
*/
|
||||
elog(ERROR, "unsupported type: %u", typid);
|
||||
return 0;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* Copyright (c) 1998-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.85 2005/07/10 21:13:59 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.86 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -131,8 +131,7 @@ typedef struct NumericVar
|
||||
{
|
||||
int ndigits; /* # of digits in digits[] - can be 0! */
|
||||
int weight; /* weight of first digit */
|
||||
int sign; /* NUMERIC_POS, NUMERIC_NEG, or
|
||||
* NUMERIC_NAN */
|
||||
int sign; /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
|
||||
int dscale; /* display scale */
|
||||
NumericDigit *buf; /* start of palloc'd space for digits[] */
|
||||
NumericDigit *digits; /* base-NBASE digits */
|
||||
@@ -157,10 +156,8 @@ static NumericVar const_two =
|
||||
|
||||
#if DEC_DIGITS == 4
|
||||
static NumericDigit const_zero_point_five_data[1] = {5000};
|
||||
|
||||
#elif DEC_DIGITS == 2
|
||||
static NumericDigit const_zero_point_five_data[1] = {50};
|
||||
|
||||
#elif DEC_DIGITS == 1
|
||||
static NumericDigit const_zero_point_five_data[1] = {5};
|
||||
#endif
|
||||
@@ -169,10 +166,8 @@ static NumericVar const_zero_point_five =
|
||||
|
||||
#if DEC_DIGITS == 4
|
||||
static NumericDigit const_zero_point_nine_data[1] = {9000};
|
||||
|
||||
#elif DEC_DIGITS == 2
|
||||
static NumericDigit const_zero_point_nine_data[1] = {90};
|
||||
|
||||
#elif DEC_DIGITS == 1
|
||||
static NumericDigit const_zero_point_nine_data[1] = {9};
|
||||
#endif
|
||||
@@ -183,12 +178,10 @@ static NumericVar const_zero_point_nine =
|
||||
static NumericDigit const_zero_point_01_data[1] = {100};
|
||||
static NumericVar const_zero_point_01 =
|
||||
{1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
|
||||
|
||||
#elif DEC_DIGITS == 2
|
||||
static NumericDigit const_zero_point_01_data[1] = {1};
|
||||
static NumericVar const_zero_point_01 =
|
||||
{1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
|
||||
|
||||
#elif DEC_DIGITS == 1
|
||||
static NumericDigit const_zero_point_01_data[1] = {1};
|
||||
static NumericVar const_zero_point_01 =
|
||||
@@ -197,10 +190,8 @@ static NumericVar const_zero_point_01 =
|
||||
|
||||
#if DEC_DIGITS == 4
|
||||
static NumericDigit const_one_point_one_data[2] = {1, 1000};
|
||||
|
||||
#elif DEC_DIGITS == 2
|
||||
static NumericDigit const_one_point_one_data[2] = {1, 10};
|
||||
|
||||
#elif DEC_DIGITS == 1
|
||||
static NumericDigit const_one_point_one_data[2] = {1, 1};
|
||||
#endif
|
||||
@@ -223,7 +214,6 @@ static const int round_powers[4] = {0, 1000, 100, 10};
|
||||
#ifdef NUMERIC_DEBUG
|
||||
static void dump_numeric(const char *str, Numeric num);
|
||||
static void dump_var(const char *str, NumericVar *var);
|
||||
|
||||
#else
|
||||
#define dump_numeric(s,n)
|
||||
#define dump_var(s,v)
|
||||
@@ -322,8 +312,8 @@ numeric_in(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NUMERIC(make_result(&const_nan));
|
||||
|
||||
/*
|
||||
* Use set_var_from_str() to parse the input string and return it in
|
||||
* the packed DB storage format
|
||||
* Use set_var_from_str() to parse the input string and return it in the
|
||||
* packed DB storage format
|
||||
*/
|
||||
init_var(&value);
|
||||
set_var_from_str(str, &value);
|
||||
@@ -358,10 +348,10 @@ numeric_out(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Get the number in the variable format.
|
||||
*
|
||||
* Even if we didn't need to change format, we'd still need to copy the
|
||||
* value to have a modifiable copy for rounding. set_var_from_num()
|
||||
* also guarantees there is extra digit space in case we produce a
|
||||
* carry out from rounding.
|
||||
* Even if we didn't need to change format, we'd still need to copy the value
|
||||
* to have a modifiable copy for rounding. set_var_from_num() also
|
||||
* guarantees there is extra digit space in case we produce a carry out
|
||||
* from rounding.
|
||||
*/
|
||||
init_var(&x);
|
||||
set_var_from_num(num, &x);
|
||||
@@ -383,6 +373,7 @@ Datum
|
||||
numeric_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
@@ -419,7 +410,7 @@ numeric_recv(PG_FUNCTION_ARGS)
|
||||
if (d < 0 || d >= NBASE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("invalid digit in external \"numeric\" value")));
|
||||
errmsg("invalid digit in external \"numeric\" value")));
|
||||
value.digits[i] = d;
|
||||
}
|
||||
|
||||
@@ -468,7 +459,7 @@ numeric_send(PG_FUNCTION_ARGS)
|
||||
* scale of the attribute have to be applied on the value.
|
||||
*/
|
||||
Datum
|
||||
numeric (PG_FUNCTION_ARGS)
|
||||
numeric(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Numeric num = PG_GETARG_NUMERIC(0);
|
||||
int32 typmod = PG_GETARG_INT32(1);
|
||||
@@ -487,8 +478,8 @@ numeric (PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NUMERIC(make_result(&const_nan));
|
||||
|
||||
/*
|
||||
* If the value isn't a valid type modifier, simply return a copy of
|
||||
* the input value
|
||||
* If the value isn't a valid type modifier, simply return a copy of the
|
||||
* input value
|
||||
*/
|
||||
if (typmod < (int32) (VARHDRSZ))
|
||||
{
|
||||
@@ -507,9 +498,8 @@ numeric (PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* If the number is certainly in bounds and due to the target scale no
|
||||
* rounding could be necessary, just make a copy of the input and
|
||||
* modify its scale fields. (Note we assume the existing dscale is
|
||||
* honest...)
|
||||
* rounding could be necessary, just make a copy of the input and modify
|
||||
* its scale fields. (Note we assume the existing dscale is honest...)
|
||||
*/
|
||||
ddigits = (num->n_weight + 1) * DEC_DIGITS;
|
||||
if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num))
|
||||
@@ -587,9 +577,9 @@ numeric_uminus(PG_FUNCTION_ARGS)
|
||||
memcpy(res, num, num->varlen);
|
||||
|
||||
/*
|
||||
* The packed format is known to be totally zero digit trimmed always.
|
||||
* So we can identify a ZERO by the fact that there are no digits at
|
||||
* all. Do nothing to a zero.
|
||||
* The packed format is known to be totally zero digit trimmed always. So
|
||||
* we can identify a ZERO by the fact that there are no digits at all. Do
|
||||
* nothing to a zero.
|
||||
*/
|
||||
if (num->varlen != NUMERIC_HDRSZ)
|
||||
{
|
||||
@@ -638,17 +628,16 @@ numeric_sign(PG_FUNCTION_ARGS)
|
||||
init_var(&result);
|
||||
|
||||
/*
|
||||
* The packed format is known to be totally zero digit trimmed always.
|
||||
* So we can identify a ZERO by the fact that there are no digits at
|
||||
* all.
|
||||
* The packed format is known to be totally zero digit trimmed always. So
|
||||
* we can identify a ZERO by the fact that there are no digits at all.
|
||||
*/
|
||||
if (num->varlen == NUMERIC_HDRSZ)
|
||||
set_var_from_var(&const_zero, &result);
|
||||
else
|
||||
{
|
||||
/*
|
||||
* And if there are some, we return a copy of ONE with the sign of
|
||||
* our argument
|
||||
* And if there are some, we return a copy of ONE with the sign of our
|
||||
* argument
|
||||
*/
|
||||
set_var_from_var(&const_one, &result);
|
||||
result.sign = NUMERIC_SIGN(num);
|
||||
@@ -837,8 +826,8 @@ width_bucket_numeric(PG_FUNCTION_ARGS)
|
||||
|
||||
if (count <= 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
|
||||
errmsg("count must be greater than zero")));
|
||||
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
|
||||
errmsg("count must be greater than zero")));
|
||||
|
||||
init_var(&result_var);
|
||||
init_var(&count_var);
|
||||
@@ -850,8 +839,8 @@ width_bucket_numeric(PG_FUNCTION_ARGS)
|
||||
{
|
||||
case 0:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
|
||||
errmsg("lower bound cannot equal upper bound")));
|
||||
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
|
||||
errmsg("lower bound cannot equal upper bound")));
|
||||
|
||||
/* bound1 < bound2 */
|
||||
case -1:
|
||||
@@ -1055,9 +1044,9 @@ cmp_numerics(Numeric num1, Numeric num2)
|
||||
int result;
|
||||
|
||||
/*
|
||||
* We consider all NANs to be equal and larger than any non-NAN. This
|
||||
* is somewhat arbitrary; the important thing is to have a consistent
|
||||
* sort order.
|
||||
* We consider all NANs to be equal and larger than any non-NAN. This is
|
||||
* somewhat arbitrary; the important thing is to have a consistent sort
|
||||
* order.
|
||||
*/
|
||||
if (NUMERIC_IS_NAN(num1))
|
||||
{
|
||||
@@ -1208,10 +1197,10 @@ numeric_mul(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* Unpack the values, let mul_var() compute the result and return it.
|
||||
* Unlike add_var() and sub_var(), mul_var() will round its result. In
|
||||
* the case of numeric_mul(), which is invoked for the * operator on
|
||||
* numerics, we request exact representation for the product (rscale =
|
||||
* sum(dscale of arg1, dscale of arg2)).
|
||||
* Unlike add_var() and sub_var(), mul_var() will round its result. In the
|
||||
* case of numeric_mul(), which is invoked for the * operator on numerics,
|
||||
* we request exact representation for the product (rscale = sum(dscale of
|
||||
* arg1, dscale of arg2)).
|
||||
*/
|
||||
init_var(&arg1);
|
||||
init_var(&arg2);
|
||||
@@ -1368,8 +1357,8 @@ numeric_smaller(PG_FUNCTION_ARGS)
|
||||
Numeric num2 = PG_GETARG_NUMERIC(1);
|
||||
|
||||
/*
|
||||
* Use cmp_numerics so that this will agree with the comparison
|
||||
* operators, particularly as regards comparisons involving NaN.
|
||||
* Use cmp_numerics so that this will agree with the comparison operators,
|
||||
* particularly as regards comparisons involving NaN.
|
||||
*/
|
||||
if (cmp_numerics(num1, num2) < 0)
|
||||
PG_RETURN_NUMERIC(num1);
|
||||
@@ -1390,8 +1379,8 @@ numeric_larger(PG_FUNCTION_ARGS)
|
||||
Numeric num2 = PG_GETARG_NUMERIC(1);
|
||||
|
||||
/*
|
||||
* Use cmp_numerics so that this will agree with the comparison
|
||||
* operators, particularly as regards comparisons involving NaN.
|
||||
* Use cmp_numerics so that this will agree with the comparison operators,
|
||||
* particularly as regards comparisons involving NaN.
|
||||
*/
|
||||
if (cmp_numerics(num1, num2) > 0)
|
||||
PG_RETURN_NUMERIC(num1);
|
||||
@@ -1469,9 +1458,9 @@ numeric_sqrt(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NUMERIC(make_result(&const_nan));
|
||||
|
||||
/*
|
||||
* Unpack the argument and determine the result scale. We choose a
|
||||
* scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
|
||||
* but in any case not less than the input's dscale.
|
||||
* Unpack the argument and determine the result scale. We choose a scale
|
||||
* to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
|
||||
* case not less than the input's dscale.
|
||||
*/
|
||||
init_var(&arg);
|
||||
init_var(&result);
|
||||
@@ -1522,9 +1511,9 @@ numeric_exp(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NUMERIC(make_result(&const_nan));
|
||||
|
||||
/*
|
||||
* Unpack the argument and determine the result scale. We choose a
|
||||
* scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
|
||||
* but in any case not less than the input's dscale.
|
||||
* Unpack the argument and determine the result scale. We choose a scale
|
||||
* to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
|
||||
* case not less than the input's dscale.
|
||||
*/
|
||||
init_var(&arg);
|
||||
init_var(&result);
|
||||
@@ -1535,8 +1524,8 @@ numeric_exp(PG_FUNCTION_ARGS)
|
||||
val = numericvar_to_double_no_overflow(&arg);
|
||||
|
||||
/*
|
||||
* log10(result) = num * log10(e), so this is approximately the
|
||||
* decimal weight of the result:
|
||||
* log10(result) = num * log10(e), so this is approximately the decimal
|
||||
* weight of the result:
|
||||
*/
|
||||
val *= 0.434294481903252;
|
||||
|
||||
@@ -1646,8 +1635,8 @@ numeric_log(PG_FUNCTION_ARGS)
|
||||
set_var_from_num(num2, &arg2);
|
||||
|
||||
/*
|
||||
* Call log_var() to compute and return the result; note it handles
|
||||
* scale selection itself.
|
||||
* Call log_var() to compute and return the result; note it handles scale
|
||||
* selection itself.
|
||||
*/
|
||||
log_var(&arg1, &arg2, &result);
|
||||
|
||||
@@ -1698,8 +1687,8 @@ numeric_power(PG_FUNCTION_ARGS)
|
||||
trunc_var(&arg2_trunc, 0);
|
||||
|
||||
/*
|
||||
* Return special SQLSTATE error codes for a few conditions mandated
|
||||
* by the standard.
|
||||
* Return special SQLSTATE error codes for a few conditions mandated by
|
||||
* the standard.
|
||||
*/
|
||||
if ((cmp_var(&arg1, &const_zero) == 0 &&
|
||||
cmp_var(&arg2, &const_zero) < 0) ||
|
||||
@@ -2093,8 +2082,8 @@ do_numeric_accum(ArrayType *transarray, Numeric newval)
|
||||
NumericGetDatum(newval));
|
||||
sumX2 = DirectFunctionCall2(numeric_add, sumX2,
|
||||
DirectFunctionCall2(numeric_mul,
|
||||
NumericGetDatum(newval),
|
||||
NumericGetDatum(newval)));
|
||||
NumericGetDatum(newval),
|
||||
NumericGetDatum(newval)));
|
||||
|
||||
transdatums[0] = N;
|
||||
transdatums[1] = sumX;
|
||||
@@ -2252,7 +2241,7 @@ numeric_variance(PG_FUNCTION_ARGS)
|
||||
{
|
||||
mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
|
||||
rscale = select_div_scale(&vsumX2, &vNminus1);
|
||||
div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
|
||||
div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
|
||||
|
||||
res = make_result(&vsumX);
|
||||
}
|
||||
@@ -2328,7 +2317,7 @@ numeric_stddev(PG_FUNCTION_ARGS)
|
||||
{
|
||||
mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
|
||||
rscale = select_div_scale(&vsumX2, &vNminus1);
|
||||
div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
|
||||
div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
|
||||
sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
|
||||
|
||||
res = make_result(&vsumX);
|
||||
@@ -2377,12 +2366,12 @@ int2_sum(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* If we're invoked by nodeAgg, we can cheat and modify out first
|
||||
* parameter in-place to avoid palloc overhead. If not, we need to
|
||||
* return the new value of the transition variable.
|
||||
* parameter in-place to avoid palloc overhead. If not, we need to return
|
||||
* the new value of the transition variable.
|
||||
*/
|
||||
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||
{
|
||||
int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
|
||||
int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
|
||||
|
||||
/* Leave the running sum unchanged in the new input is null */
|
||||
if (!PG_ARGISNULL(1))
|
||||
@@ -2422,12 +2411,12 @@ int4_sum(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* If we're invoked by nodeAgg, we can cheat and modify out first
|
||||
* parameter in-place to avoid palloc overhead. If not, we need to
|
||||
* return the new value of the transition variable.
|
||||
* parameter in-place to avoid palloc overhead. If not, we need to return
|
||||
* the new value of the transition variable.
|
||||
*/
|
||||
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||
{
|
||||
int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
|
||||
int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
|
||||
|
||||
/* Leave the running sum unchanged in the new input is null */
|
||||
if (!PG_ARGISNULL(1))
|
||||
@@ -2467,9 +2456,9 @@ int8_sum(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that we cannot special-case the nodeAgg case here, as we
|
||||
* do for int2_sum and int4_sum: numeric is of variable size, so
|
||||
* we cannot modify our first parameter in-place.
|
||||
* Note that we cannot special-case the nodeAgg case here, as we do for
|
||||
* int2_sum and int4_sum: numeric is of variable size, so we cannot modify
|
||||
* our first parameter in-place.
|
||||
*/
|
||||
|
||||
oldsum = PG_GETARG_NUMERIC(0);
|
||||
@@ -2514,8 +2503,8 @@ int2_avg_accum(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* If we're invoked by nodeAgg, we can cheat and modify our first
|
||||
* parameter in-place to reduce palloc overhead. Otherwise we need
|
||||
* to make a copy of it before scribbling on it.
|
||||
* parameter in-place to reduce palloc overhead. Otherwise we need to make
|
||||
* a copy of it before scribbling on it.
|
||||
*/
|
||||
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||
transarray = PG_GETARG_ARRAYTYPE_P(0);
|
||||
@@ -2541,8 +2530,8 @@ int4_avg_accum(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* If we're invoked by nodeAgg, we can cheat and modify our first
|
||||
* parameter in-place to reduce palloc overhead. Otherwise we need
|
||||
* to make a copy of it before scribbling on it.
|
||||
* parameter in-place to reduce palloc overhead. Otherwise we need to make
|
||||
* a copy of it before scribbling on it.
|
||||
*/
|
||||
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||
transarray = PG_GETARG_ARRAYTYPE_P(0);
|
||||
@@ -2743,8 +2732,8 @@ set_var_from_str(const char *str, NumericVar *dest)
|
||||
NumericDigit *digits;
|
||||
|
||||
/*
|
||||
* We first parse the string to extract decimal digits and determine
|
||||
* the correct decimal weight. Then convert to NBASE representation.
|
||||
* We first parse the string to extract decimal digits and determine the
|
||||
* correct decimal weight. Then convert to NBASE representation.
|
||||
*/
|
||||
|
||||
/* skip leading spaces */
|
||||
@@ -2777,7 +2766,7 @@ set_var_from_str(const char *str, NumericVar *dest)
|
||||
if (!isdigit((unsigned char) *cp))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"", str)));
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"", str)));
|
||||
|
||||
decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
|
||||
|
||||
@@ -2800,8 +2789,8 @@ set_var_from_str(const char *str, NumericVar *dest)
|
||||
if (have_dp)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"",
|
||||
str)));
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"",
|
||||
str)));
|
||||
have_dp = TRUE;
|
||||
cp++;
|
||||
}
|
||||
@@ -2824,15 +2813,15 @@ set_var_from_str(const char *str, NumericVar *dest)
|
||||
if (endptr == cp)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"",
|
||||
str)));
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"",
|
||||
str)));
|
||||
cp = endptr;
|
||||
if (exponent > NUMERIC_MAX_PRECISION ||
|
||||
exponent < -NUMERIC_MAX_PRECISION)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"",
|
||||
str)));
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"",
|
||||
str)));
|
||||
dweight += (int) exponent;
|
||||
dscale -= (int) exponent;
|
||||
if (dscale < 0)
|
||||
@@ -2845,16 +2834,16 @@ set_var_from_str(const char *str, NumericVar *dest)
|
||||
if (!isspace((unsigned char) *cp))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"",
|
||||
str)));
|
||||
errmsg("invalid input syntax for type numeric: \"%s\"",
|
||||
str)));
|
||||
cp++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Okay, convert pure-decimal representation to base NBASE. First we
|
||||
* need to determine the converted weight and ndigits. offset is the
|
||||
* number of decimal zeroes to insert before the first given digit to
|
||||
* have a correctly aligned first NBASE digit.
|
||||
* Okay, convert pure-decimal representation to base NBASE. First we need
|
||||
* to determine the converted weight and ndigits. offset is the number of
|
||||
* decimal zeroes to insert before the first given digit to have a
|
||||
* correctly aligned first NBASE digit.
|
||||
*/
|
||||
if (dweight >= 0)
|
||||
weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
|
||||
@@ -2969,10 +2958,10 @@ get_str_from_var(NumericVar *var, int dscale)
|
||||
/*
|
||||
* Allocate space for the result.
|
||||
*
|
||||
* i is set to to # of decimal digits before decimal point. dscale is the
|
||||
* # of decimal digits we will print after decimal point. We may
|
||||
* generate as many as DEC_DIGITS-1 excess digits at the end, and in
|
||||
* addition we need room for sign, decimal point, null terminator.
|
||||
* i is set to to # of decimal digits before decimal point. dscale is the #
|
||||
* of decimal digits we will print after decimal point. We may generate as
|
||||
* many as DEC_DIGITS-1 excess digits at the end, and in addition we need
|
||||
* room for sign, decimal point, null terminator.
|
||||
*/
|
||||
i = (var->weight + 1) * DEC_DIGITS;
|
||||
if (i <= 0)
|
||||
@@ -3037,9 +3026,9 @@ get_str_from_var(NumericVar *var, int dscale)
|
||||
}
|
||||
|
||||
/*
|
||||
* If requested, output a decimal point and all the digits that follow
|
||||
* it. We initially put out a multiple of DEC_DIGITS digits, then
|
||||
* truncate if needed.
|
||||
* If requested, output a decimal point and all the digits that follow it.
|
||||
* We initially put out a multiple of DEC_DIGITS digits, then truncate if
|
||||
* needed.
|
||||
*/
|
||||
if (dscale > 0)
|
||||
{
|
||||
@@ -3179,10 +3168,10 @@ apply_typmod(NumericVar *var, int32 typmod)
|
||||
|
||||
/*
|
||||
* Check for overflow - note we can't do this before rounding, because
|
||||
* rounding could raise the weight. Also note that the var's weight
|
||||
* could be inflated by leading zeroes, which will be stripped before
|
||||
* storage but perhaps might not have been yet. In any case, we must
|
||||
* recognize a true zero, whose weight doesn't mean anything.
|
||||
* rounding could raise the weight. Also note that the var's weight could
|
||||
* be inflated by leading zeroes, which will be stripped before storage
|
||||
* but perhaps might not have been yet. In any case, we must recognize a
|
||||
* true zero, whose weight doesn't mean anything.
|
||||
*/
|
||||
ddigits = (var->weight + 1) * DEC_DIGITS;
|
||||
if (ddigits > maxdigits)
|
||||
@@ -3254,9 +3243,8 @@ numericvar_to_int8(NumericVar *var, int64 *result)
|
||||
}
|
||||
|
||||
/*
|
||||
* For input like 10000000000, we must treat stripped digits as real.
|
||||
* So the loop assumes there are weight+1 digits before the decimal
|
||||
* point.
|
||||
* For input like 10000000000, we must treat stripped digits as real. So
|
||||
* the loop assumes there are weight+1 digits before the decimal point.
|
||||
*/
|
||||
weight = var->weight;
|
||||
Assert(weight >= 0 && ndigits <= weight + 1);
|
||||
@@ -3274,10 +3262,10 @@ numericvar_to_int8(NumericVar *var, int64 *result)
|
||||
|
||||
/*
|
||||
* The overflow check is a bit tricky because we want to accept
|
||||
* INT64_MIN, which will overflow the positive accumulator. We
|
||||
* can detect this case easily though because INT64_MIN is the
|
||||
* only nonzero value for which -val == val (on a two's complement
|
||||
* machine, anyway).
|
||||
* INT64_MIN, which will overflow the positive accumulator. We can
|
||||
* detect this case easily though because INT64_MIN is the only
|
||||
* nonzero value for which -val == val (on a two's complement machine,
|
||||
* anyway).
|
||||
*/
|
||||
if ((val / NBASE) != oldval) /* possible overflow? */
|
||||
{
|
||||
@@ -3355,8 +3343,8 @@ numeric_to_double_no_overflow(Numeric num)
|
||||
/* shouldn't happen ... */
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
tmp)));
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
tmp)));
|
||||
}
|
||||
|
||||
pfree(tmp);
|
||||
@@ -3381,8 +3369,8 @@ numericvar_to_double_no_overflow(NumericVar *var)
|
||||
/* shouldn't happen ... */
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
tmp)));
|
||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||
tmp)));
|
||||
}
|
||||
|
||||
pfree(tmp);
|
||||
@@ -3454,8 +3442,7 @@ add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* var1 is positive, var2 is negative Must compare absolute
|
||||
* values
|
||||
* var1 is positive, var2 is negative Must compare absolute values
|
||||
*/
|
||||
switch (cmp_abs(var1, var2))
|
||||
{
|
||||
@@ -3715,10 +3702,9 @@ mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
|
||||
/*
|
||||
* Determine number of result digits to compute. If the exact result
|
||||
* would have more than rscale fractional digits, truncate the
|
||||
* computation with MUL_GUARD_DIGITS guard digits. We do that by
|
||||
* pretending that one or both inputs have fewer digits than they
|
||||
* really do.
|
||||
* would have more than rscale fractional digits, truncate the computation
|
||||
* with MUL_GUARD_DIGITS guard digits. We do that by pretending that one
|
||||
* or both inputs have fewer digits than they really do.
|
||||
*/
|
||||
res_ndigits = var1ndigits + var2ndigits + 1;
|
||||
maxdigits = res_weight + 1 + (rscale * DEC_DIGITS) + MUL_GUARD_DIGITS;
|
||||
@@ -3752,12 +3738,12 @@ mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
|
||||
/*
|
||||
* We do the arithmetic in an array "dig[]" of signed int's. Since
|
||||
* INT_MAX is noticeably larger than NBASE*NBASE, this gives us
|
||||
* headroom to avoid normalizing carries immediately.
|
||||
* INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
|
||||
* to avoid normalizing carries immediately.
|
||||
*
|
||||
* maxdig tracks the maximum possible value of any dig[] entry; when this
|
||||
* threatens to exceed INT_MAX, we take the time to propagate carries.
|
||||
* To avoid overflow in maxdig itself, it actually represents the max
|
||||
* threatens to exceed INT_MAX, we take the time to propagate carries. To
|
||||
* avoid overflow in maxdig itself, it actually represents the max
|
||||
* possible value divided by NBASE-1.
|
||||
*/
|
||||
dig = (int *) palloc0(res_ndigits * sizeof(int));
|
||||
@@ -3801,9 +3787,9 @@ mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we do a final carry propagation pass to normalize the result,
|
||||
* which we combine with storing the result digits into the output.
|
||||
* Note that this is still done at full precision w/guard digits.
|
||||
* Now we do a final carry propagation pass to normalize the result, which
|
||||
* we combine with storing the result digits into the output. Note that
|
||||
* this is still done at full precision w/guard digits.
|
||||
*/
|
||||
alloc_var(result, res_ndigits);
|
||||
res_digits = result->digits;
|
||||
@@ -3909,24 +3895,24 @@ div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
|
||||
/*
|
||||
* We do the arithmetic in an array "div[]" of signed int's. Since
|
||||
* INT_MAX is noticeably larger than NBASE*NBASE, this gives us
|
||||
* headroom to avoid normalizing carries immediately.
|
||||
* INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
|
||||
* to avoid normalizing carries immediately.
|
||||
*
|
||||
* We start with div[] containing one zero digit followed by the
|
||||
* dividend's digits (plus appended zeroes to reach the desired
|
||||
* precision including guard digits). Each step of the main loop
|
||||
* computes an (approximate) quotient digit and stores it into div[],
|
||||
* removing one position of dividend space. A final pass of carry
|
||||
* propagation takes care of any mistaken quotient digits.
|
||||
* We start with div[] containing one zero digit followed by the dividend's
|
||||
* digits (plus appended zeroes to reach the desired precision including
|
||||
* guard digits). Each step of the main loop computes an (approximate)
|
||||
* quotient digit and stores it into div[], removing one position of
|
||||
* dividend space. A final pass of carry propagation takes care of any
|
||||
* mistaken quotient digits.
|
||||
*/
|
||||
div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
|
||||
for (i = 0; i < var1ndigits; i++)
|
||||
div[i + 1] = var1digits[i];
|
||||
|
||||
/*
|
||||
* We estimate each quotient digit using floating-point arithmetic,
|
||||
* taking the first four digits of the (current) dividend and divisor.
|
||||
* This must be float to avoid overflow.
|
||||
* We estimate each quotient digit using floating-point arithmetic, taking
|
||||
* the first four digits of the (current) dividend and divisor. This must
|
||||
* be float to avoid overflow.
|
||||
*/
|
||||
fdivisor = (double) var2digits[0];
|
||||
for (i = 1; i < 4; i++)
|
||||
@@ -3938,10 +3924,10 @@ div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
fdivisorinverse = 1.0 / fdivisor;
|
||||
|
||||
/*
|
||||
* maxdiv tracks the maximum possible absolute value of any div[]
|
||||
* entry; when this threatens to exceed INT_MAX, we take the time to
|
||||
* propagate carries. To avoid overflow in maxdiv itself, it actually
|
||||
* represents the max possible abs. value divided by NBASE-1.
|
||||
* maxdiv tracks the maximum possible absolute value of any div[] entry;
|
||||
* when this threatens to exceed INT_MAX, we take the time to propagate
|
||||
* carries. To avoid overflow in maxdiv itself, it actually represents
|
||||
* the max possible abs. value divided by NBASE-1.
|
||||
*/
|
||||
maxdiv = 1;
|
||||
|
||||
@@ -3992,8 +3978,8 @@ div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
div[qi] = newdig;
|
||||
|
||||
/*
|
||||
* All the div[] digits except possibly div[qi] are now in
|
||||
* the range 0..NBASE-1.
|
||||
* All the div[] digits except possibly div[qi] are now in the
|
||||
* range 0..NBASE-1.
|
||||
*/
|
||||
maxdiv = Abs(newdig) / (NBASE - 1);
|
||||
maxdiv = Max(maxdiv, 1);
|
||||
@@ -4012,8 +3998,7 @@ div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
/* Compute the (approximate) quotient digit */
|
||||
fquotient = fdividend * fdivisorinverse;
|
||||
qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
|
||||
(((int) fquotient) - 1); /* truncate towards
|
||||
* -infinity */
|
||||
(((int) fquotient) - 1); /* truncate towards -infinity */
|
||||
maxdiv += Abs(qdigit);
|
||||
}
|
||||
|
||||
@@ -4028,10 +4013,10 @@ div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
}
|
||||
|
||||
/*
|
||||
* The dividend digit we are about to replace might still be
|
||||
* nonzero. Fold it into the next digit position. We don't need
|
||||
* to worry about overflow here since this should nearly cancel
|
||||
* with the subtraction of the divisor.
|
||||
* The dividend digit we are about to replace might still be nonzero.
|
||||
* Fold it into the next digit position. We don't need to worry about
|
||||
* overflow here since this should nearly cancel with the subtraction
|
||||
* of the divisor.
|
||||
*/
|
||||
div[qi + 1] += div[qi] * NBASE;
|
||||
|
||||
@@ -4050,9 +4035,9 @@ div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
div[qi] = qdigit;
|
||||
|
||||
/*
|
||||
* Now we do a final carry propagation pass to normalize the result,
|
||||
* which we combine with storing the result digits into the output.
|
||||
* Note that this is still done at full precision w/guard digits.
|
||||
* Now we do a final carry propagation pass to normalize the result, which
|
||||
* we combine with storing the result digits into the output. Note that
|
||||
* this is still done at full precision w/guard digits.
|
||||
*/
|
||||
alloc_var(result, div_ndigits + 1);
|
||||
res_digits = result->digits;
|
||||
@@ -4089,7 +4074,7 @@ div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
|
||||
round_var(result, rscale);
|
||||
else
|
||||
trunc_var(result, rscale);
|
||||
|
||||
|
||||
/* Strip leading and trailing zeroes */
|
||||
strip_var(result);
|
||||
}
|
||||
@@ -4112,8 +4097,8 @@ select_div_scale(NumericVar *var1, NumericVar *var2)
|
||||
int rscale;
|
||||
|
||||
/*
|
||||
* The result scale of a division isn't specified in any SQL standard.
|
||||
* For PostgreSQL we select a result scale that will give at least
|
||||
* The result scale of a division isn't specified in any SQL standard. For
|
||||
* PostgreSQL we select a result scale that will give at least
|
||||
* NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
|
||||
* result no less accurate than float8; but use a scale not less than
|
||||
* either input's display scale.
|
||||
@@ -4274,8 +4259,8 @@ sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL2003 defines sqrt() in terms of power, so we need to emit the
|
||||
* right SQLSTATE error code if the operand is negative.
|
||||
* SQL2003 defines sqrt() in terms of power, so we need to emit the right
|
||||
* SQLSTATE error code if the operand is negative.
|
||||
*/
|
||||
if (stat < 0)
|
||||
ereport(ERROR,
|
||||
@@ -4445,9 +4430,8 @@ exp_var_internal(NumericVar *arg, NumericVar *result, int rscale)
|
||||
*
|
||||
* exp(x) = 1 + x + x^2/2! + x^3/3! + ...
|
||||
*
|
||||
* Given the limited range of x, this should converge reasonably quickly.
|
||||
* We run the series until the terms fall below the local_rscale
|
||||
* limit.
|
||||
* Given the limited range of x, this should converge reasonably quickly. We
|
||||
* run the series until the terms fall below the local_rscale limit.
|
||||
*/
|
||||
add_var(&const_one, &x, result);
|
||||
set_var_from_var(&x, &xpow);
|
||||
@@ -4535,11 +4519,11 @@ ln_var(NumericVar *arg, NumericVar *result, int rscale)
|
||||
*
|
||||
* z + z^3/3 + z^5/5 + ...
|
||||
*
|
||||
* where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
|
||||
* due to the above range-reduction of x.
|
||||
* where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048 due
|
||||
* to the above range-reduction of x.
|
||||
*
|
||||
* The convergence of this is not as fast as one would like, but is
|
||||
* tolerable given that z is small.
|
||||
* The convergence of this is not as fast as one would like, but is tolerable
|
||||
* given that z is small.
|
||||
*/
|
||||
sub_var(&x, &const_one, result);
|
||||
add_var(&x, &const_one, &elem);
|
||||
@@ -4711,8 +4695,7 @@ power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
|
||||
val = numericvar_to_double_no_overflow(&ln_num);
|
||||
|
||||
/*
|
||||
* log10(result) = num * log10(e), so this is approximately the
|
||||
* weight:
|
||||
* log10(result) = num * log10(e), so this is approximately the weight:
|
||||
*/
|
||||
val *= 0.434294481903252;
|
||||
|
||||
@@ -4772,8 +4755,7 @@ power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
|
||||
|
||||
/*
|
||||
* The general case repeatedly multiplies base according to the bit
|
||||
* pattern of exp. We do the multiplications with some extra
|
||||
* precision.
|
||||
* pattern of exp. We do the multiplications with some extra precision.
|
||||
*/
|
||||
neg = (exp < 0);
|
||||
exp = Abs(exp);
|
||||
@@ -4866,8 +4848,8 @@ cmp_abs(NumericVar *var1, NumericVar *var2)
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we've run out of digits on one side or the other; so
|
||||
* any remaining nonzero digits imply that side is larger
|
||||
* At this point, we've run out of digits on one side or the other; so any
|
||||
* remaining nonzero digits imply that side is larger
|
||||
*/
|
||||
while (i1 < var1->ndigits)
|
||||
{
|
||||
@@ -5071,8 +5053,8 @@ round_var(NumericVar *var, int rscale)
|
||||
di = (var->weight + 1) * DEC_DIGITS + rscale;
|
||||
|
||||
/*
|
||||
* If di = 0, the value loses all digits, but could round up to 1 if
|
||||
* its first extra digit is >= 5. If di < 0 the result must be 0.
|
||||
* If di = 0, the value loses all digits, but could round up to 1 if its
|
||||
* first extra digit is >= 5. If di < 0 the result must be 0.
|
||||
*/
|
||||
if (di < 0)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/numutils.c,v 1.68 2005/01/09 21:03:19 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/numutils.c,v 1.69 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -63,8 +63,8 @@ pg_atoi(char *s, int size, int c)
|
||||
char *badp;
|
||||
|
||||
/*
|
||||
* Some versions of strtol treat the empty string as an error, but
|
||||
* some seem not to. Make an explicit test to be sure we catch it.
|
||||
* Some versions of strtol treat the empty string as an error, but some
|
||||
* seem not to. Make an explicit test to be sure we catch it.
|
||||
*/
|
||||
if (s == NULL)
|
||||
elog(ERROR, "NULL pointer");
|
||||
@@ -85,8 +85,8 @@ pg_atoi(char *s, int size, int c)
|
||||
s)));
|
||||
|
||||
/*
|
||||
* Skip any trailing whitespace; if anything but whitespace remains
|
||||
* before the terminating character, bail out
|
||||
* Skip any trailing whitespace; if anything but whitespace remains before
|
||||
* the terminating character, bail out
|
||||
*/
|
||||
while (*badp && *badp != c && isspace((unsigned char) *badp))
|
||||
badp++;
|
||||
@@ -108,19 +108,19 @@ pg_atoi(char *s, int size, int c)
|
||||
)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("value \"%s\" is out of range for type integer", s)));
|
||||
errmsg("value \"%s\" is out of range for type integer", s)));
|
||||
break;
|
||||
case sizeof(int16):
|
||||
if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("value \"%s\" is out of range for type smallint", s)));
|
||||
errmsg("value \"%s\" is out of range for type smallint", s)));
|
||||
break;
|
||||
case sizeof(int8):
|
||||
if (errno == ERANGE || l < SCHAR_MIN || l > SCHAR_MAX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("value \"%s\" is out of range for 8-bit integer", s)));
|
||||
errmsg("value \"%s\" is out of range for 8-bit integer", s)));
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unsupported result size: %d", size);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.63 2005/07/10 21:36:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.64 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -47,9 +47,9 @@ oidin_subr(const char *funcname, const char *s, char **endloc)
|
||||
cvt = strtoul(s, &endptr, 10);
|
||||
|
||||
/*
|
||||
* strtoul() normally only sets ERANGE. On some systems it also may
|
||||
* set EINVAL, which simply means it couldn't parse the input string.
|
||||
* This is handled by the second "if" consistent across platforms.
|
||||
* strtoul() normally only sets ERANGE. On some systems it also may set
|
||||
* EINVAL, which simply means it couldn't parse the input string. This is
|
||||
* handled by the second "if" consistent across platforms.
|
||||
*/
|
||||
if (errno && errno != ERANGE && errno != EINVAL)
|
||||
ereport(ERROR,
|
||||
@@ -88,16 +88,16 @@ oidin_subr(const char *funcname, const char *s, char **endloc)
|
||||
result = (Oid) cvt;
|
||||
|
||||
/*
|
||||
* Cope with possibility that unsigned long is wider than Oid, in
|
||||
* which case strtoul will not raise an error for some values that are
|
||||
* out of the range of Oid.
|
||||
* Cope with possibility that unsigned long is wider than Oid, in which
|
||||
* case strtoul will not raise an error for some values that are out of
|
||||
* the range of Oid.
|
||||
*
|
||||
* For backwards compatibility, we want to accept inputs that are given
|
||||
* with a minus sign, so allow the input value if it matches after
|
||||
* either signed or unsigned extension to long.
|
||||
* For backwards compatibility, we want to accept inputs that are given with
|
||||
* a minus sign, so allow the input value if it matches after either
|
||||
* signed or unsigned extension to long.
|
||||
*
|
||||
* To ensure consistent results on 32-bit and 64-bit platforms, make sure
|
||||
* the error message is the same as if strtoul() had returned ERANGE.
|
||||
* To ensure consistent results on 32-bit and 64-bit platforms, make sure the
|
||||
* error message is the same as if strtoul() had returned ERANGE.
|
||||
*/
|
||||
#if OID_MAX != ULONG_MAX
|
||||
if (cvt != (unsigned long) result &&
|
||||
@@ -171,8 +171,8 @@ buildoidvector(const Oid *oids, int n)
|
||||
memcpy(result->values, oids, n * sizeof(Oid));
|
||||
|
||||
/*
|
||||
* Attach standard array header. For historical reasons, we set the
|
||||
* index lower bound to 0 not 1.
|
||||
* Attach standard array header. For historical reasons, we set the index
|
||||
* lower bound to 0 not 1.
|
||||
*/
|
||||
result->size = OidVectorSize(n);
|
||||
result->ndim = 1;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.61 2005/08/24 17:50:00 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.62 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -87,12 +87,12 @@ texttowcs(const text *txt)
|
||||
if (ncodes == (size_t) -1)
|
||||
{
|
||||
/*
|
||||
* Invalid multibyte character encountered. We try to give a
|
||||
* useful error message by letting pg_verifymbstr check the
|
||||
* string. But it's possible that the string is OK to us, and not
|
||||
* OK to mbstowcs --- this suggests that the LC_CTYPE locale is
|
||||
* different from the database encoding. Give a generic error
|
||||
* message if verifymbstr can't find anything wrong.
|
||||
* Invalid multibyte character encountered. We try to give a useful
|
||||
* error message by letting pg_verifymbstr check the string. But it's
|
||||
* possible that the string is OK to us, and not OK to mbstowcs ---
|
||||
* this suggests that the LC_CTYPE locale is different from the
|
||||
* database encoding. Give a generic error message if verifymbstr
|
||||
* can't find anything wrong.
|
||||
*/
|
||||
pg_verifymbstr(workstr, nbytes, false);
|
||||
ereport(ERROR,
|
||||
@@ -164,11 +164,11 @@ win32_utf8_texttowcs(const text *txt)
|
||||
{
|
||||
int nbytes = VARSIZE(txt) - VARHDRSZ;
|
||||
wchar_t *result;
|
||||
int r;
|
||||
int r;
|
||||
|
||||
/* Overflow paranoia */
|
||||
if (nbytes < 0 ||
|
||||
nbytes > (int) (INT_MAX / sizeof(wchar_t)) -1)
|
||||
nbytes > (int) (INT_MAX / sizeof(wchar_t)) - 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of memory")));
|
||||
@@ -206,9 +206,9 @@ win32_utf8_texttowcs(const text *txt)
|
||||
static text *
|
||||
win32_utf8_wcstotext(const wchar_t *str)
|
||||
{
|
||||
text *result;
|
||||
int nbytes;
|
||||
int r;
|
||||
text *result;
|
||||
int nbytes;
|
||||
int r;
|
||||
|
||||
nbytes = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
|
||||
if (nbytes == 0) /* shouldn't happen */
|
||||
@@ -217,7 +217,7 @@ win32_utf8_wcstotext(const wchar_t *str)
|
||||
errmsg("UTF16 to UTF8 translation failed: %lu",
|
||||
GetLastError())));
|
||||
|
||||
result = palloc(nbytes+VARHDRSZ);
|
||||
result = palloc(nbytes + VARHDRSZ);
|
||||
|
||||
r = WideCharToMultiByte(CP_UTF8, 0, str, -1, VARDATA(result), nbytes,
|
||||
NULL, NULL);
|
||||
@@ -227,7 +227,7 @@ win32_utf8_wcstotext(const wchar_t *str)
|
||||
errmsg("UTF16 to UTF8 translation failed: %lu",
|
||||
GetLastError())));
|
||||
|
||||
VARATT_SIZEP(result) = nbytes + VARHDRSZ - 1; /* -1 to ignore null */
|
||||
VARATT_SIZEP(result) = nbytes + VARHDRSZ - 1; /* -1 to ignore null */
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -256,8 +256,7 @@ win32_wcstotext(const wchar_t *str, int ncodes)
|
||||
|
||||
#define texttowcs win32_texttowcs
|
||||
#define wcstotext win32_wcstotext
|
||||
|
||||
#endif /* WIN32 */
|
||||
#endif /* WIN32 */
|
||||
|
||||
|
||||
/********************************************************************
|
||||
@@ -278,10 +277,11 @@ Datum
|
||||
lower(PG_FUNCTION_ARGS)
|
||||
{
|
||||
#ifdef USE_WIDE_UPPER_LOWER
|
||||
|
||||
/*
|
||||
* Use wide char code only when max encoding length > 1 and ctype != C.
|
||||
* Some operating systems fail with multi-byte encodings and a C locale.
|
||||
* Also, for a C locale there is no need to process as multibyte.
|
||||
* Use wide char code only when max encoding length > 1 and ctype != C.
|
||||
* Some operating systems fail with multi-byte encodings and a C locale.
|
||||
* Also, for a C locale there is no need to process as multibyte.
|
||||
*/
|
||||
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
|
||||
{
|
||||
@@ -309,8 +309,7 @@ lower(PG_FUNCTION_ARGS)
|
||||
int m;
|
||||
|
||||
/*
|
||||
* Since we copied the string, we can scribble directly on the
|
||||
* value
|
||||
* Since we copied the string, we can scribble directly on the value
|
||||
*/
|
||||
ptr = VARDATA(string);
|
||||
m = VARSIZE(string) - VARHDRSZ;
|
||||
@@ -344,10 +343,11 @@ Datum
|
||||
upper(PG_FUNCTION_ARGS)
|
||||
{
|
||||
#ifdef USE_WIDE_UPPER_LOWER
|
||||
|
||||
/*
|
||||
* Use wide char code only when max encoding length > 1 and ctype != C.
|
||||
* Some operating systems fail with multi-byte encodings and a C locale.
|
||||
* Also, for a C locale there is no need to process as multibyte.
|
||||
* Use wide char code only when max encoding length > 1 and ctype != C.
|
||||
* Some operating systems fail with multi-byte encodings and a C locale.
|
||||
* Also, for a C locale there is no need to process as multibyte.
|
||||
*/
|
||||
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
|
||||
{
|
||||
@@ -375,8 +375,7 @@ upper(PG_FUNCTION_ARGS)
|
||||
int m;
|
||||
|
||||
/*
|
||||
* Since we copied the string, we can scribble directly on the
|
||||
* value
|
||||
* Since we copied the string, we can scribble directly on the value
|
||||
*/
|
||||
ptr = VARDATA(string);
|
||||
m = VARSIZE(string) - VARHDRSZ;
|
||||
@@ -413,10 +412,11 @@ Datum
|
||||
initcap(PG_FUNCTION_ARGS)
|
||||
{
|
||||
#ifdef USE_WIDE_UPPER_LOWER
|
||||
|
||||
/*
|
||||
* Use wide char code only when max encoding length > 1 and ctype != C.
|
||||
* Some operating systems fail with multi-byte encodings and a C locale.
|
||||
* Also, for a C locale there is no need to process as multibyte.
|
||||
* Use wide char code only when max encoding length > 1 and ctype != C.
|
||||
* Some operating systems fail with multi-byte encodings and a C locale.
|
||||
* Also, for a C locale there is no need to process as multibyte.
|
||||
*/
|
||||
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
|
||||
{
|
||||
@@ -452,8 +452,7 @@ initcap(PG_FUNCTION_ARGS)
|
||||
int m;
|
||||
|
||||
/*
|
||||
* Since we copied the string, we can scribble directly on the
|
||||
* value
|
||||
* Since we copied the string, we can scribble directly on the value
|
||||
*/
|
||||
ptr = VARDATA(string);
|
||||
m = VARSIZE(string) - VARHDRSZ;
|
||||
@@ -732,8 +731,8 @@ dotrim(const char *string, int stringlen,
|
||||
{
|
||||
/*
|
||||
* In the multibyte-encoding case, build arrays of pointers to
|
||||
* character starts, so that we can avoid inefficient checks
|
||||
* in the inner loops.
|
||||
* character starts, so that we can avoid inefficient checks in
|
||||
* the inner loops.
|
||||
*/
|
||||
const char **stringchars;
|
||||
const char **setchars;
|
||||
@@ -828,8 +827,7 @@ dotrim(const char *string, int stringlen,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* In the single-byte-encoding case, we don't need such
|
||||
* overhead.
|
||||
* In the single-byte-encoding case, we don't need such overhead.
|
||||
*/
|
||||
if (doltrim)
|
||||
{
|
||||
@@ -1152,9 +1150,9 @@ translate(PG_FUNCTION_ARGS)
|
||||
VARATT_SIZEP(result) = retlen + VARHDRSZ;
|
||||
|
||||
/*
|
||||
* There may be some wasted space in the result if deletions occurred,
|
||||
* but it's not worth reallocating it; the function result probably
|
||||
* won't live long anyway.
|
||||
* There may be some wasted space in the result if deletions occurred, but
|
||||
* it's not worth reallocating it; the function result probably won't live
|
||||
* long anyway.
|
||||
*/
|
||||
|
||||
PG_RETURN_TEXT_P(result);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Portions Copyright (c) 2002-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.31 2005/03/16 00:02:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.32 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -124,9 +124,9 @@ const char *
|
||||
locale_messages_assign(const char *value, bool doit, GucSource source)
|
||||
{
|
||||
#ifndef WIN32
|
||||
|
||||
/*
|
||||
* LC_MESSAGES category does not exist everywhere, but accept it
|
||||
* anyway
|
||||
* LC_MESSAGES category does not exist everywhere, but accept it anyway
|
||||
*/
|
||||
#ifdef LC_MESSAGES
|
||||
if (doit)
|
||||
@@ -138,16 +138,15 @@ locale_messages_assign(const char *value, bool doit, GucSource source)
|
||||
value = locale_xxx_assign(LC_MESSAGES, value, false, source);
|
||||
#endif /* LC_MESSAGES */
|
||||
return value;
|
||||
|
||||
#else /* WIN32 */
|
||||
#else /* WIN32 */
|
||||
|
||||
/*
|
||||
* Win32 does not have working setlocale() for LC_MESSAGES. We can only
|
||||
* use environment variables to change it (per gettext FAQ). This
|
||||
* means we can't actually check the supplied value, so always assume
|
||||
* it's good. Also, ignore attempts to set to "", which really means
|
||||
* "keep using the old value". (Actually it means "use the environment
|
||||
* value", but we are too lazy to try to implement that exactly.)
|
||||
* use environment variables to change it (per gettext FAQ). This means
|
||||
* we can't actually check the supplied value, so always assume it's good.
|
||||
* Also, ignore attempts to set to "", which really means "keep using the
|
||||
* old value". (Actually it means "use the environment value", but we are
|
||||
* too lazy to try to implement that exactly.)
|
||||
*/
|
||||
if (doit && value[0])
|
||||
{
|
||||
@@ -160,12 +159,12 @@ locale_messages_assign(const char *value, bool doit, GucSource source)
|
||||
if (!SetEnvironmentVariable("LC_MESSAGES", value))
|
||||
return NULL;
|
||||
|
||||
snprintf(env, sizeof(env)-1, "LC_MESSAGES=%s", value);
|
||||
snprintf(env, sizeof(env) - 1, "LC_MESSAGES=%s", value);
|
||||
if (_putenv(env))
|
||||
return NULL;
|
||||
}
|
||||
return value;
|
||||
#endif /* WIN32 */
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
|
||||
@@ -289,8 +288,8 @@ PGLC_localeconv(void)
|
||||
extlconv = localeconv();
|
||||
|
||||
/*
|
||||
* Must copy all values since restoring internal settings may
|
||||
* overwrite localeconv()'s results.
|
||||
* Must copy all values since restoring internal settings may overwrite
|
||||
* localeconv()'s results.
|
||||
*/
|
||||
CurrentLocaleConv = *extlconv;
|
||||
CurrentLocaleConv.currency_symbol = strdup(extlconv->currency_symbol);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* ----------
|
||||
* pg_lzcompress.c -
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_lzcompress.c,v 1.19 2005/05/25 21:40:41 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_lzcompress.c,v 1.20 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
* This is an implementation of LZ compression for PostgreSQL.
|
||||
* It uses a simple history table and generates 2-3 byte tags
|
||||
@@ -219,11 +219,11 @@ static PGLZ_Strategy strategy_default_data = {
|
||||
6144, /* Data chunks greater equal 6K force
|
||||
* compression */
|
||||
/* except compressed result is greater uncompressed data */
|
||||
20, /* Compression rates below 20% mean
|
||||
* fallback to uncompressed */
|
||||
20, /* Compression rates below 20% mean fallback
|
||||
* to uncompressed */
|
||||
/* storage except compression is forced by previous parameter */
|
||||
128, /* Stop history lookup if a match of 128
|
||||
* bytes is found */
|
||||
128, /* Stop history lookup if a match of 128 bytes
|
||||
* is found */
|
||||
10 /* Lower good match size by 10% at every
|
||||
* lookup loop iteration. */
|
||||
};
|
||||
@@ -233,10 +233,9 @@ PGLZ_Strategy *PGLZ_strategy_default = &strategy_default_data;
|
||||
static PGLZ_Strategy strategy_always_data = {
|
||||
0, /* Chunks of any size are compressed */
|
||||
0, /* */
|
||||
0, /* We want to save at least one single
|
||||
* byte */
|
||||
128, /* Stop history lookup if a match of 128
|
||||
* bytes is found */
|
||||
0, /* We want to save at least one single byte */
|
||||
128, /* Stop history lookup if a match of 128 bytes
|
||||
* is found */
|
||||
6 /* Look harder for a good match. */
|
||||
};
|
||||
PGLZ_Strategy *PGLZ_strategy_always = &strategy_always_data;
|
||||
@@ -246,8 +245,7 @@ static PGLZ_Strategy strategy_never_data = {
|
||||
0, /* */
|
||||
0, /* */
|
||||
0, /* */
|
||||
0, /* Zero indicates "store uncompressed
|
||||
* always" */
|
||||
0, /* Zero indicates "store uncompressed always" */
|
||||
0 /* */
|
||||
};
|
||||
PGLZ_Strategy *PGLZ_strategy_never = &strategy_never_data;
|
||||
@@ -395,8 +393,7 @@ pglz_find_match(PGLZ_HistEntry **hstart, char *input, char *end,
|
||||
int32 off = 0;
|
||||
|
||||
/*
|
||||
* Traverse the linked history list until a good enough match is
|
||||
* found.
|
||||
* Traverse the linked history list until a good enough match is found.
|
||||
*/
|
||||
hent = hstart[pglz_hist_idx(input, end)];
|
||||
while (hent)
|
||||
@@ -414,12 +411,12 @@ pglz_find_match(PGLZ_HistEntry **hstart, char *input, char *end,
|
||||
break;
|
||||
|
||||
/*
|
||||
* Determine length of match. A better match must be larger than
|
||||
* the best so far. And if we already have a match of 16 or more
|
||||
* bytes, it's worth the call overhead to use memcmp() to check if
|
||||
* this match is equal for the same size. After that we must
|
||||
* fallback to character by character comparison to know the exact
|
||||
* position where the diff occurred.
|
||||
* Determine length of match. A better match must be larger than the
|
||||
* best so far. And if we already have a match of 16 or more bytes,
|
||||
* it's worth the call overhead to use memcmp() to check if this match
|
||||
* is equal for the same size. After that we must fallback to
|
||||
* character by character comparison to know the exact position where
|
||||
* the diff occurred.
|
||||
*/
|
||||
thislen = 0;
|
||||
if (len >= 16)
|
||||
@@ -462,8 +459,8 @@ pglz_find_match(PGLZ_HistEntry **hstart, char *input, char *end,
|
||||
hent = hent->next;
|
||||
|
||||
/*
|
||||
* Be happy with lesser good matches the more entries we visited.
|
||||
* But no point in doing calculation if we're at end of list.
|
||||
* Be happy with lesser good matches the more entries we visited. But
|
||||
* no point in doing calculation if we're at end of list.
|
||||
*/
|
||||
if (hent)
|
||||
{
|
||||
@@ -565,10 +562,10 @@ pglz_compress(char *source, int32 slen, PGLZ_Header *dest, PGLZ_Strategy *strate
|
||||
memset((void *) hist_start, 0, sizeof(hist_start));
|
||||
|
||||
/*
|
||||
* Compute the maximum result size allowed by the strategy. If the
|
||||
* input size exceeds force_input_size, the max result size is the
|
||||
* input size itself. Otherwise, it is the input size minus the
|
||||
* minimum wanted compression rate.
|
||||
* Compute the maximum result size allowed by the strategy. If the input
|
||||
* size exceeds force_input_size, the max result size is the input size
|
||||
* itself. Otherwise, it is the input size minus the minimum wanted
|
||||
* compression rate.
|
||||
*/
|
||||
if (slen >= strategy->force_input_size)
|
||||
result_max = slen;
|
||||
@@ -588,8 +585,8 @@ pglz_compress(char *source, int32 slen, PGLZ_Header *dest, PGLZ_Strategy *strate
|
||||
while (dp < dend)
|
||||
{
|
||||
/*
|
||||
* If we already exceeded the maximum result size, set no
|
||||
* compression flag and stop this. But don't check too often.
|
||||
* If we already exceeded the maximum result size, set no compression
|
||||
* flag and stop this. But don't check too often.
|
||||
*/
|
||||
if (bp - bstart >= result_max)
|
||||
{
|
||||
@@ -632,9 +629,9 @@ pglz_compress(char *source, int32 slen, PGLZ_Header *dest, PGLZ_Strategy *strate
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are still in compressing mode, write out the last control
|
||||
* byte and determine if the compression gained the rate requested by
|
||||
* the strategy.
|
||||
* If we are still in compressing mode, write out the last control byte
|
||||
* and determine if the compression gained the rate requested by the
|
||||
* strategy.
|
||||
*/
|
||||
if (do_compress)
|
||||
{
|
||||
@@ -647,8 +644,8 @@ pglz_compress(char *source, int32 slen, PGLZ_Header *dest, PGLZ_Strategy *strate
|
||||
|
||||
/*
|
||||
* Done - if we successfully compressed and matched the strategy's
|
||||
* constraints, return the compressed result. Otherwise copy the
|
||||
* original source over it and return the original length.
|
||||
* constraints, return the compressed result. Otherwise copy the original
|
||||
* source over it and return the original length.
|
||||
*/
|
||||
if (do_compress)
|
||||
{
|
||||
@@ -704,9 +701,9 @@ pglz_decompress(PGLZ_Header *source, char *dest)
|
||||
/*
|
||||
* Otherwise it contains the match length minus 3 and the
|
||||
* upper 4 bits of the offset. The next following byte
|
||||
* contains the lower 8 bits of the offset. If the length
|
||||
* is coded as 18, another extension tag byte tells how
|
||||
* much longer the match really was (0-255).
|
||||
* contains the lower 8 bits of the offset. If the length is
|
||||
* coded as 18, another extension tag byte tells how much
|
||||
* longer the match really was (0-255).
|
||||
*/
|
||||
len = (dp[0] & 0x0f) + 3;
|
||||
off = ((dp[0] & 0xf0) << 4) | dp[1];
|
||||
@@ -715,10 +712,10 @@ pglz_decompress(PGLZ_Header *source, char *dest)
|
||||
len += *dp++;
|
||||
|
||||
/*
|
||||
* Now we copy the bytes specified by the tag from OUTPUT
|
||||
* to OUTPUT. It is dangerous and platform dependent to
|
||||
* use memcpy() here, because the copied areas could
|
||||
* overlap extremely!
|
||||
* Now we copy the bytes specified by the tag from OUTPUT to
|
||||
* OUTPUT. It is dangerous and platform dependent to use
|
||||
* memcpy() here, because the copied areas could overlap
|
||||
* extremely!
|
||||
*/
|
||||
while (len--)
|
||||
{
|
||||
@@ -729,8 +726,8 @@ pglz_decompress(PGLZ_Header *source, char *dest)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* An unset control bit means LITERAL BYTE. So we just
|
||||
* copy one from INPUT to OUTPUT.
|
||||
* An unset control bit means LITERAL BYTE. So we just copy
|
||||
* one from INPUT to OUTPUT.
|
||||
*/
|
||||
*bp++ = *dp++;
|
||||
}
|
||||
@@ -764,8 +761,8 @@ pglz_get_next_decomp_char_from_lzdata(PGLZ_DecompState *dstate)
|
||||
if (dstate->tocopy > 0)
|
||||
{
|
||||
/*
|
||||
* Copy one byte from output to output until we did it for the
|
||||
* length specified by the last tag. Return that byte.
|
||||
* Copy one byte from output to output until we did it for the length
|
||||
* specified by the last tag. Return that byte.
|
||||
*/
|
||||
dstate->tocopy--;
|
||||
return (*(dstate->cp_out++) = *(dstate->cp_copy++));
|
||||
@@ -774,21 +771,20 @@ pglz_get_next_decomp_char_from_lzdata(PGLZ_DecompState *dstate)
|
||||
if (dstate->ctrl_count == 0)
|
||||
{
|
||||
/*
|
||||
* Get the next control byte if we need to, but check for EOF
|
||||
* before.
|
||||
* Get the next control byte if we need to, but check for EOF before.
|
||||
*/
|
||||
if (dstate->cp_in == dstate->cp_end)
|
||||
return EOF;
|
||||
|
||||
/*
|
||||
* This decompression method saves time only, if we stop near the
|
||||
* beginning of the data (maybe because we're called by a
|
||||
* comparison function and a difference occurs early). Otherwise,
|
||||
* all the checks, needed here, cause too much overhead.
|
||||
* beginning of the data (maybe because we're called by a comparison
|
||||
* function and a difference occurs early). Otherwise, all the checks,
|
||||
* needed here, cause too much overhead.
|
||||
*
|
||||
* Thus we decompress the entire rest at once into the temporary
|
||||
* buffer and change the decomp state to return the prepared data
|
||||
* from the buffer by the more simple calls to
|
||||
* Thus we decompress the entire rest at once into the temporary buffer
|
||||
* and change the decomp state to return the prepared data from the
|
||||
* buffer by the more simple calls to
|
||||
* pglz_get_next_decomp_char_from_plain().
|
||||
*/
|
||||
if (dstate->cp_out - dstate->temp_buf >= 256)
|
||||
@@ -856,8 +852,8 @@ pglz_get_next_decomp_char_from_lzdata(PGLZ_DecompState *dstate)
|
||||
if (dstate->ctrl & 0x01)
|
||||
{
|
||||
/*
|
||||
* Bit is set, so tag is following. Setup copy information and do
|
||||
* the copy for the first byte as above.
|
||||
* Bit is set, so tag is following. Setup copy information and do the
|
||||
* copy for the first byte as above.
|
||||
*/
|
||||
int off;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.24 2005/06/29 22:51:56 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.25 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -354,8 +354,8 @@ pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
|
||||
result = beentry->activity_start_timestamp;
|
||||
|
||||
/*
|
||||
* No time recorded for start of current query -- this is the case if
|
||||
* the user hasn't enabled query-level stats collection.
|
||||
* No time recorded for start of current query -- this is the case if the
|
||||
* user hasn't enabled query-level stats collection.
|
||||
*/
|
||||
if (result == 0)
|
||||
PG_RETURN_NULL();
|
||||
@@ -366,7 +366,7 @@ pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_stat_get_backend_start(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 beid = PG_GETARG_INT32(0);
|
||||
int32 beid = PG_GETARG_INT32(0);
|
||||
TimestampTz result;
|
||||
PgStat_StatBeEntry *beentry;
|
||||
|
||||
@@ -389,7 +389,7 @@ Datum
|
||||
pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PgStat_StatBeEntry *beentry;
|
||||
int32 beid;
|
||||
int32 beid;
|
||||
char remote_host[NI_MAXHOST];
|
||||
int ret;
|
||||
|
||||
@@ -432,7 +432,7 @@ Datum
|
||||
pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PgStat_StatBeEntry *beentry;
|
||||
int32 beid;
|
||||
int32 beid;
|
||||
char remote_port[NI_MAXSERV];
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.16 2005/07/02 17:01:50 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.17 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -65,13 +65,13 @@ quote_literal(PG_FUNCTION_ARGS)
|
||||
cp1 = VARDATA(t);
|
||||
cp2 = VARDATA(result);
|
||||
|
||||
for(; len-- > 0; cp1++)
|
||||
for (; len-- > 0; cp1++)
|
||||
if (*cp1 == '\\')
|
||||
{
|
||||
*cp2++ = ESCAPE_STRING_SYNTAX;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
len = VARSIZE(t) - VARHDRSZ;
|
||||
cp1 = VARDATA(t);
|
||||
*cp2++ = '\'';
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/regexp.c,v 1.58 2005/09/24 17:53:15 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/regexp.c,v 1.59 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
* Alistair Crooks added the code for the regex caching
|
||||
* agc - cached the regular expressions used - there's a good chance
|
||||
@@ -85,8 +85,8 @@ static cached_re_str re_array[MAX_CACHED_RES]; /* cached re's */
|
||||
*
|
||||
* Returns regex_t
|
||||
*
|
||||
* text_re --- the pattern, expressed as an *untoasted* TEXT object
|
||||
* cflags --- compile options for the pattern
|
||||
* text_re --- the pattern, expressed as an *untoasted* TEXT object
|
||||
* cflags --- compile options for the pattern
|
||||
*
|
||||
* Pattern is given in the database encoding. We internally convert to
|
||||
* array of pg_wchar which is what Spencer's regex package wants.
|
||||
@@ -104,8 +104,8 @@ RE_compile_and_cache(text *text_re, int cflags)
|
||||
|
||||
/*
|
||||
* Look for a match among previously compiled REs. Since the data
|
||||
* structure is self-organizing with most-used entries at the front,
|
||||
* our search strategy can just be to scan from the front.
|
||||
* structure is self-organizing with most-used entries at the front, our
|
||||
* search strategy can just be to scan from the front.
|
||||
*/
|
||||
for (i = 0; i < num_res; i++)
|
||||
{
|
||||
@@ -171,8 +171,8 @@ RE_compile_and_cache(text *text_re, int cflags)
|
||||
re_temp.cre_flags = cflags;
|
||||
|
||||
/*
|
||||
* Okay, we have a valid new item in re_temp; insert it into the
|
||||
* storage array. Discard last entry if needed.
|
||||
* Okay, we have a valid new item in re_temp; insert it into the storage
|
||||
* array. Discard last entry if needed.
|
||||
*/
|
||||
if (num_res >= MAX_CACHED_RES)
|
||||
{
|
||||
@@ -213,7 +213,7 @@ RE_compile_and_execute(text *text_re, char *dat, int dat_len,
|
||||
size_t data_len;
|
||||
int regexec_result;
|
||||
regex_t re;
|
||||
char errMsg[100];
|
||||
char errMsg[100];
|
||||
|
||||
/* Convert data string to wide characters */
|
||||
data = (pg_wchar *) palloc((dat_len + 1) * sizeof(pg_wchar));
|
||||
@@ -405,10 +405,10 @@ textregexsubstr(PG_FUNCTION_ARGS)
|
||||
regmatch_t pmatch[2];
|
||||
|
||||
/*
|
||||
* We pass two regmatch_t structs to get info about the overall match
|
||||
* and the match for the first parenthesized subexpression (if any).
|
||||
* If there is a parenthesized subexpression, we return what it
|
||||
* matched; else return what the whole regexp matched.
|
||||
* We pass two regmatch_t structs to get info about the overall match and
|
||||
* the match for the first parenthesized subexpression (if any). If there
|
||||
* is a parenthesized subexpression, we return what it matched; else
|
||||
* return what the whole regexp matched.
|
||||
*/
|
||||
match = RE_compile_and_execute(p,
|
||||
VARDATA(s),
|
||||
@@ -432,9 +432,9 @@ textregexsubstr(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
return DirectFunctionCall3(text_substr,
|
||||
PointerGetDatum(s),
|
||||
Int32GetDatum(so + 1),
|
||||
Int32GetDatum(eo - so));
|
||||
PointerGetDatum(s),
|
||||
Int32GetDatum(so + 1),
|
||||
Int32GetDatum(eo - so));
|
||||
}
|
||||
|
||||
PG_RETURN_NULL();
|
||||
@@ -442,7 +442,7 @@ textregexsubstr(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* textregexreplace_noopt()
|
||||
* Return a replace string matched by a regular expression.
|
||||
* Return a replace string matched by a regular expression.
|
||||
* This function is a version that doesn't specify the option of
|
||||
* textregexreplace. This is case sensitive, replace the first
|
||||
* instance only.
|
||||
@@ -458,15 +458,15 @@ textregexreplace_noopt(PG_FUNCTION_ARGS)
|
||||
re = RE_compile_and_cache(p, regex_flavor);
|
||||
|
||||
return DirectFunctionCall4(replace_text_regexp,
|
||||
PointerGetDatum(s),
|
||||
PointerGetDatum(&re),
|
||||
PointerGetDatum(r),
|
||||
BoolGetDatum(false));
|
||||
PointerGetDatum(s),
|
||||
PointerGetDatum(&re),
|
||||
PointerGetDatum(r),
|
||||
BoolGetDatum(false));
|
||||
}
|
||||
|
||||
/*
|
||||
* textregexreplace()
|
||||
* Return a replace string matched by a regular expression.
|
||||
* Return a replace string matched by a regular expression.
|
||||
*/
|
||||
Datum
|
||||
textregexreplace(PG_FUNCTION_ARGS)
|
||||
@@ -478,7 +478,7 @@ textregexreplace(PG_FUNCTION_ARGS)
|
||||
char *opt_p = VARDATA(opt);
|
||||
int opt_len = (VARSIZE(opt) - VARHDRSZ);
|
||||
int i;
|
||||
bool global = false;
|
||||
bool global = false;
|
||||
bool ignorecase = false;
|
||||
regex_t re;
|
||||
|
||||
@@ -492,12 +492,13 @@ textregexreplace(PG_FUNCTION_ARGS)
|
||||
break;
|
||||
case 'g':
|
||||
global = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid option of regexp_replace: %c",
|
||||
opt_p[i])));
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid option of regexp_replace: %c",
|
||||
opt_p[i])));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -508,10 +509,10 @@ textregexreplace(PG_FUNCTION_ARGS)
|
||||
re = RE_compile_and_cache(p, regex_flavor);
|
||||
|
||||
return DirectFunctionCall4(replace_text_regexp,
|
||||
PointerGetDatum(s),
|
||||
PointerGetDatum(&re),
|
||||
PointerGetDatum(r),
|
||||
BoolGetDatum(global));
|
||||
PointerGetDatum(s),
|
||||
PointerGetDatum(&re),
|
||||
PointerGetDatum(r),
|
||||
BoolGetDatum(global));
|
||||
}
|
||||
|
||||
/* similar_escape()
|
||||
@@ -555,7 +556,7 @@ similar_escape(PG_FUNCTION_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
|
||||
errmsg("invalid escape string"),
|
||||
errhint("Escape string must be empty or one character.")));
|
||||
errhint("Escape string must be empty or one character.")));
|
||||
}
|
||||
|
||||
/* We need room for ^, $, and up to 2 output bytes per input byte */
|
||||
@@ -566,7 +567,7 @@ similar_escape(PG_FUNCTION_ARGS)
|
||||
|
||||
while (plen > 0)
|
||||
{
|
||||
char pchar = *p;
|
||||
char pchar = *p;
|
||||
|
||||
if (afterescape)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.95 2005/10/02 23:50:10 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.96 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -71,17 +71,17 @@ regprocin(PG_FUNCTION_ARGS)
|
||||
strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
|
||||
{
|
||||
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(pro_name_or_oid)));
|
||||
CStringGetDatum(pro_name_or_oid)));
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/* Else it's a name, possibly schema-qualified */
|
||||
|
||||
/*
|
||||
* In bootstrap mode we assume the given name is not schema-qualified,
|
||||
* and just search pg_proc for a unique match. This is needed for
|
||||
* initializing other system catalogs (pg_namespace may not exist yet,
|
||||
* and certainly there are no schemas other than pg_catalog).
|
||||
* In bootstrap mode we assume the given name is not schema-qualified, and
|
||||
* just search pg_proc for a unique match. This is needed for
|
||||
* initializing other system catalogs (pg_namespace may not exist yet, and
|
||||
* certainly there are no schemas other than pg_catalog).
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
{
|
||||
@@ -113,7 +113,7 @@ regprocin(PG_FUNCTION_ARGS)
|
||||
if (matches == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
|
||||
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
|
||||
|
||||
else if (matches > 1)
|
||||
ereport(ERROR,
|
||||
@@ -125,8 +125,8 @@ regprocin(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Normal case: parse the name into components and see if it matches
|
||||
* any pg_proc entries in the current search path.
|
||||
* Normal case: parse the name into components and see if it matches any
|
||||
* pg_proc entries in the current search path.
|
||||
*/
|
||||
names = stringToQualifiedNameList(pro_name_or_oid, "regprocin");
|
||||
clist = FuncnameGetCandidates(names, -1);
|
||||
@@ -134,7 +134,7 @@ regprocin(PG_FUNCTION_ARGS)
|
||||
if (clist == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
|
||||
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
|
||||
else if (clist->next != NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
|
||||
@@ -172,9 +172,9 @@ regprocout(PG_FUNCTION_ARGS)
|
||||
char *proname = NameStr(procform->proname);
|
||||
|
||||
/*
|
||||
* In bootstrap mode, skip the fancy namespace stuff and just
|
||||
* return the proc name. (This path is only needed for debugging
|
||||
* output anyway.)
|
||||
* In bootstrap mode, skip the fancy namespace stuff and just return
|
||||
* the proc name. (This path is only needed for debugging output
|
||||
* anyway.)
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
result = pstrdup(proname);
|
||||
@@ -258,15 +258,15 @@ regprocedurein(PG_FUNCTION_ARGS)
|
||||
strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
|
||||
{
|
||||
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(pro_name_or_oid)));
|
||||
CStringGetDatum(pro_name_or_oid)));
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Else it's a name and arguments. Parse the name and arguments, look
|
||||
* up potential matches in the current namespace search list, and scan
|
||||
* to see which one exactly matches the given argument types. (There
|
||||
* will not be more than one match.)
|
||||
* Else it's a name and arguments. Parse the name and arguments, look up
|
||||
* potential matches in the current namespace search list, and scan to see
|
||||
* which one exactly matches the given argument types. (There will not be
|
||||
* more than one match.)
|
||||
*
|
||||
* XXX at present, this code will not work in bootstrap mode, hence this
|
||||
* datatype cannot be used for any system column that needs to receive
|
||||
@@ -286,7 +286,7 @@ regprocedurein(PG_FUNCTION_ARGS)
|
||||
if (clist == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
|
||||
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
|
||||
|
||||
result = clist->oid;
|
||||
|
||||
@@ -323,8 +323,8 @@ format_procedure(Oid procedure_oid)
|
||||
initStringInfo(&buf);
|
||||
|
||||
/*
|
||||
* Would this proc be found (given the right args) by
|
||||
* regprocedurein? If not, we need to qualify it.
|
||||
* Would this proc be found (given the right args) by regprocedurein?
|
||||
* If not, we need to qualify it.
|
||||
*/
|
||||
if (FunctionIsVisible(procedure_oid))
|
||||
nspname = NULL;
|
||||
@@ -421,17 +421,17 @@ regoperin(PG_FUNCTION_ARGS)
|
||||
strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
|
||||
{
|
||||
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(opr_name_or_oid)));
|
||||
CStringGetDatum(opr_name_or_oid)));
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/* Else it's a name, possibly schema-qualified */
|
||||
|
||||
/*
|
||||
* In bootstrap mode we assume the given name is not schema-qualified,
|
||||
* and just search pg_operator for a unique match. This is needed for
|
||||
* initializing other system catalogs (pg_namespace may not exist yet,
|
||||
* and certainly there are no schemas other than pg_catalog).
|
||||
* In bootstrap mode we assume the given name is not schema-qualified, and
|
||||
* just search pg_operator for a unique match. This is needed for
|
||||
* initializing other system catalogs (pg_namespace may not exist yet, and
|
||||
* certainly there are no schemas other than pg_catalog).
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
{
|
||||
@@ -463,7 +463,7 @@ regoperin(PG_FUNCTION_ARGS)
|
||||
if (matches == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("operator does not exist: %s", opr_name_or_oid)));
|
||||
errmsg("operator does not exist: %s", opr_name_or_oid)));
|
||||
else if (matches > 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
|
||||
@@ -474,8 +474,8 @@ regoperin(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Normal case: parse the name into components and see if it matches
|
||||
* any pg_operator entries in the current search path.
|
||||
* Normal case: parse the name into components and see if it matches any
|
||||
* pg_operator entries in the current search path.
|
||||
*/
|
||||
names = stringToQualifiedNameList(opr_name_or_oid, "regoperin");
|
||||
clist = OpernameGetCandidates(names, '\0');
|
||||
@@ -521,9 +521,9 @@ regoperout(PG_FUNCTION_ARGS)
|
||||
char *oprname = NameStr(operform->oprname);
|
||||
|
||||
/*
|
||||
* In bootstrap mode, skip the fancy namespace stuff and just
|
||||
* return the oper name. (This path is only needed for debugging
|
||||
* output anyway.)
|
||||
* In bootstrap mode, skip the fancy namespace stuff and just return
|
||||
* the oper name. (This path is only needed for debugging output
|
||||
* anyway.)
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
result = pstrdup(oprname);
|
||||
@@ -556,8 +556,7 @@ regoperout(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If OID doesn't match any pg_operator entry, return it
|
||||
* numerically
|
||||
* If OID doesn't match any pg_operator entry, return it numerically
|
||||
*/
|
||||
result = (char *) palloc(NAMEDATALEN);
|
||||
snprintf(result, NAMEDATALEN, "%u", oprid);
|
||||
@@ -616,15 +615,15 @@ regoperatorin(PG_FUNCTION_ARGS)
|
||||
strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
|
||||
{
|
||||
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(opr_name_or_oid)));
|
||||
CStringGetDatum(opr_name_or_oid)));
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Else it's a name and arguments. Parse the name and arguments, look
|
||||
* up potential matches in the current namespace search list, and scan
|
||||
* to see which one exactly matches the given argument types. (There
|
||||
* will not be more than one match.)
|
||||
* Else it's a name and arguments. Parse the name and arguments, look up
|
||||
* potential matches in the current namespace search list, and scan to see
|
||||
* which one exactly matches the given argument types. (There will not be
|
||||
* more than one match.)
|
||||
*
|
||||
* XXX at present, this code will not work in bootstrap mode, hence this
|
||||
* datatype cannot be used for any system column that needs to receive
|
||||
@@ -696,8 +695,8 @@ format_operator(Oid operator_oid)
|
||||
initStringInfo(&buf);
|
||||
|
||||
/*
|
||||
* Would this oper be found (given the right args) by
|
||||
* regoperatorin? If not, we need to qualify it.
|
||||
* Would this oper be found (given the right args) by regoperatorin?
|
||||
* If not, we need to qualify it.
|
||||
*/
|
||||
if (!OperatorIsVisible(operator_oid))
|
||||
{
|
||||
@@ -727,8 +726,7 @@ format_operator(Oid operator_oid)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If OID doesn't match any pg_operator entry, return it
|
||||
* numerically
|
||||
* If OID doesn't match any pg_operator entry, return it numerically
|
||||
*/
|
||||
result = (char *) palloc(NAMEDATALEN);
|
||||
snprintf(result, NAMEDATALEN, "%u", operator_oid);
|
||||
@@ -797,20 +795,20 @@ regclassin(PG_FUNCTION_ARGS)
|
||||
/* Numeric OID? */
|
||||
if (class_name_or_oid[0] >= '0' &&
|
||||
class_name_or_oid[0] <= '9' &&
|
||||
strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid))
|
||||
strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid))
|
||||
{
|
||||
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(class_name_or_oid)));
|
||||
CStringGetDatum(class_name_or_oid)));
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/* Else it's a name, possibly schema-qualified */
|
||||
|
||||
/*
|
||||
* In bootstrap mode we assume the given name is not schema-qualified,
|
||||
* and just search pg_class for a match. This is needed for
|
||||
* initializing other system catalogs (pg_namespace may not exist yet,
|
||||
* and certainly there are no schemas other than pg_catalog).
|
||||
* In bootstrap mode we assume the given name is not schema-qualified, and
|
||||
* just search pg_class for a match. This is needed for initializing
|
||||
* other system catalogs (pg_namespace may not exist yet, and certainly
|
||||
* there are no schemas other than pg_catalog).
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
{
|
||||
@@ -833,7 +831,7 @@ regclassin(PG_FUNCTION_ARGS)
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_TABLE),
|
||||
errmsg("relation \"%s\" does not exist", class_name_or_oid)));
|
||||
errmsg("relation \"%s\" does not exist", class_name_or_oid)));
|
||||
|
||||
/* We assume there can be only one match */
|
||||
|
||||
@@ -844,8 +842,8 @@ regclassin(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Normal case: parse the name into components and see if it matches
|
||||
* any pg_class entries in the current search path.
|
||||
* Normal case: parse the name into components and see if it matches any
|
||||
* pg_class entries in the current search path.
|
||||
*/
|
||||
names = stringToQualifiedNameList(class_name_or_oid, "regclassin");
|
||||
|
||||
@@ -880,9 +878,9 @@ regclassout(PG_FUNCTION_ARGS)
|
||||
char *classname = NameStr(classform->relname);
|
||||
|
||||
/*
|
||||
* In bootstrap mode, skip the fancy namespace stuff and just
|
||||
* return the class name. (This path is only needed for debugging
|
||||
* output anyway.)
|
||||
* In bootstrap mode, skip the fancy namespace stuff and just return
|
||||
* the class name. (This path is only needed for debugging output
|
||||
* anyway.)
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
result = pstrdup(classname);
|
||||
@@ -891,8 +889,7 @@ regclassout(PG_FUNCTION_ARGS)
|
||||
char *nspname;
|
||||
|
||||
/*
|
||||
* Would this class be found by regclassin? If not, qualify
|
||||
* it.
|
||||
* Would this class be found by regclassin? If not, qualify it.
|
||||
*/
|
||||
if (RelationIsVisible(classid))
|
||||
nspname = NULL;
|
||||
@@ -966,17 +963,17 @@ regtypein(PG_FUNCTION_ARGS)
|
||||
strspn(typ_name_or_oid, "0123456789") == strlen(typ_name_or_oid))
|
||||
{
|
||||
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(typ_name_or_oid)));
|
||||
CStringGetDatum(typ_name_or_oid)));
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/* Else it's a type name, possibly schema-qualified or decorated */
|
||||
|
||||
/*
|
||||
* In bootstrap mode we assume the given name is not schema-qualified,
|
||||
* and just search pg_type for a match. This is needed for
|
||||
* initializing other system catalogs (pg_namespace may not exist yet,
|
||||
* and certainly there are no schemas other than pg_catalog).
|
||||
* In bootstrap mode we assume the given name is not schema-qualified, and
|
||||
* just search pg_type for a match. This is needed for initializing other
|
||||
* system catalogs (pg_namespace may not exist yet, and certainly there
|
||||
* are no schemas other than pg_catalog).
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
{
|
||||
@@ -999,7 +996,7 @@ regtypein(PG_FUNCTION_ARGS)
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist", typ_name_or_oid)));
|
||||
errmsg("type \"%s\" does not exist", typ_name_or_oid)));
|
||||
|
||||
/* We assume there can be only one match */
|
||||
|
||||
@@ -1010,8 +1007,8 @@ regtypein(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Normal case: invoke the full parser to deal with special cases such
|
||||
* as array syntax.
|
||||
* Normal case: invoke the full parser to deal with special cases such as
|
||||
* array syntax.
|
||||
*/
|
||||
parseTypeString(typ_name_or_oid, &result, &typmod);
|
||||
|
||||
@@ -1043,9 +1040,9 @@ regtypeout(PG_FUNCTION_ARGS)
|
||||
Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup);
|
||||
|
||||
/*
|
||||
* In bootstrap mode, skip the fancy namespace stuff and just
|
||||
* return the type name. (This path is only needed for debugging
|
||||
* output anyway.)
|
||||
* In bootstrap mode, skip the fancy namespace stuff and just return
|
||||
* the type name. (This path is only needed for debugging output
|
||||
* anyway.)
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.12 2005/07/10 21:13:59 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.13 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -54,6 +54,7 @@ record_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *string = PG_GETARG_CSTRING(0);
|
||||
Oid tupType = PG_GETARG_OID(1);
|
||||
|
||||
#ifdef NOT_USED
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
#endif
|
||||
@@ -72,14 +73,14 @@ record_in(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* Use the passed type unless it's RECORD; we can't support input of
|
||||
* anonymous types, mainly because there's no good way to figure out
|
||||
* which anonymous type is wanted. Note that for RECORD, what we'll
|
||||
* probably actually get is RECORD's typelem, ie, zero.
|
||||
* anonymous types, mainly because there's no good way to figure out which
|
||||
* anonymous type is wanted. Note that for RECORD, what we'll probably
|
||||
* actually get is RECORD's typelem, ie, zero.
|
||||
*/
|
||||
if (tupType == InvalidOid || tupType == RECORDOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("input of anonymous composite types is not implemented")));
|
||||
errmsg("input of anonymous composite types is not implemented")));
|
||||
tupTypmod = -1; /* for all non-anonymous types */
|
||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||
ncolumns = tupdesc->natts;
|
||||
@@ -153,7 +154,7 @@ record_in(PG_FUNCTION_ARGS)
|
||||
/* *ptr must be ')' */
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed record literal: \"%s\"", string),
|
||||
errmsg("malformed record literal: \"%s\"", string),
|
||||
errdetail("Too few columns.")));
|
||||
}
|
||||
|
||||
@@ -184,10 +185,10 @@ record_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
if (*ptr == '\0')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed record literal: \"%s\"",
|
||||
string),
|
||||
errdetail("Unexpected end of input.")));
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("malformed record literal: \"%s\"",
|
||||
string),
|
||||
errdetail("Unexpected end of input.")));
|
||||
appendStringInfoChar(&buf, *ptr++);
|
||||
}
|
||||
else if (ch == '\"')
|
||||
@@ -221,8 +222,8 @@ record_in(PG_FUNCTION_ARGS)
|
||||
|
||||
values[i] = FunctionCall3(&column_info->proc,
|
||||
CStringGetDatum(buf.data),
|
||||
ObjectIdGetDatum(column_info->typioparam),
|
||||
Int32GetDatum(tupdesc->attrs[i]->atttypmod));
|
||||
ObjectIdGetDatum(column_info->typioparam),
|
||||
Int32GetDatum(tupdesc->attrs[i]->atttypmod));
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
|
||||
@@ -249,9 +250,9 @@ record_in(PG_FUNCTION_ARGS)
|
||||
tuple = heap_formtuple(tupdesc, values, nulls);
|
||||
|
||||
/*
|
||||
* We cannot return tuple->t_data because heap_formtuple allocates it
|
||||
* as part of a larger chunk, and our caller may expect to be able to
|
||||
* pfree our result. So must copy the info into a new palloc chunk.
|
||||
* We cannot return tuple->t_data because heap_formtuple allocates it as
|
||||
* part of a larger chunk, and our caller may expect to be able to pfree
|
||||
* our result. So must copy the info into a new palloc chunk.
|
||||
*/
|
||||
result = (HeapTupleHeader) palloc(tuple->t_len);
|
||||
memcpy(result, tuple->t_data, tuple->t_len);
|
||||
@@ -420,6 +421,7 @@ record_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
Oid tupType = PG_GETARG_OID(1);
|
||||
|
||||
#ifdef NOT_USED
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
#endif
|
||||
@@ -437,14 +439,14 @@ record_recv(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* Use the passed type unless it's RECORD; we can't support input of
|
||||
* anonymous types, mainly because there's no good way to figure out
|
||||
* which anonymous type is wanted. Note that for RECORD, what we'll
|
||||
* probably actually get is RECORD's typelem, ie, zero.
|
||||
* anonymous types, mainly because there's no good way to figure out which
|
||||
* anonymous type is wanted. Note that for RECORD, what we'll probably
|
||||
* actually get is RECORD's typelem, ie, zero.
|
||||
*/
|
||||
if (tupType == InvalidOid || tupType == RECORDOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("input of anonymous composite types is not implemented")));
|
||||
errmsg("input of anonymous composite types is not implemented")));
|
||||
tupTypmod = -1; /* for all non-anonymous types */
|
||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||
ncolumns = tupdesc->natts;
|
||||
@@ -537,10 +539,9 @@ record_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/*
|
||||
* Rather than copying data around, we just set up a phony
|
||||
* StringInfo pointing to the correct portion of the input
|
||||
* buffer. We assume we can scribble on the input buffer so as
|
||||
* to maintain the convention that StringInfos have a trailing
|
||||
* null.
|
||||
* StringInfo pointing to the correct portion of the input buffer.
|
||||
* We assume we can scribble on the input buffer so as to maintain
|
||||
* the convention that StringInfos have a trailing null.
|
||||
*/
|
||||
StringInfoData item_buf;
|
||||
char csave;
|
||||
@@ -568,16 +569,16 @@ record_recv(PG_FUNCTION_ARGS)
|
||||
|
||||
values[i] = FunctionCall3(&column_info->proc,
|
||||
PointerGetDatum(&item_buf),
|
||||
ObjectIdGetDatum(column_info->typioparam),
|
||||
Int32GetDatum(tupdesc->attrs[i]->atttypmod));
|
||||
ObjectIdGetDatum(column_info->typioparam),
|
||||
Int32GetDatum(tupdesc->attrs[i]->atttypmod));
|
||||
nulls[i] = ' ';
|
||||
|
||||
/* Trouble if it didn't eat the whole buffer */
|
||||
if (item_buf.cursor != itemlen)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("improper binary format in record column %d",
|
||||
i + 1)));
|
||||
errmsg("improper binary format in record column %d",
|
||||
i + 1)));
|
||||
|
||||
buf->data[buf->cursor] = csave;
|
||||
}
|
||||
@@ -586,9 +587,9 @@ record_recv(PG_FUNCTION_ARGS)
|
||||
tuple = heap_formtuple(tupdesc, values, nulls);
|
||||
|
||||
/*
|
||||
* We cannot return tuple->t_data because heap_formtuple allocates it
|
||||
* as part of a larger chunk, and our caller may expect to be able to
|
||||
* pfree our result. So must copy the info into a new palloc chunk.
|
||||
* We cannot return tuple->t_data because heap_formtuple allocates it as
|
||||
* part of a larger chunk, and our caller may expect to be able to pfree
|
||||
* our result. So must copy the info into a new palloc chunk.
|
||||
*/
|
||||
result = (HeapTupleHeader) palloc(tuple->t_len);
|
||||
memcpy(result, tuple->t_data, tuple->t_len);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* back to source text
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.206 2005/10/06 19:51:14 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.207 2005/10/15 02:49:29 momjian Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -201,11 +201,11 @@ static void get_agg_expr(Aggref *aggref, deparse_context *context);
|
||||
static void get_const_expr(Const *constval, deparse_context *context);
|
||||
static void get_sublink_expr(SubLink *sublink, deparse_context *context);
|
||||
static void get_from_clause(Query *query, const char *prefix,
|
||||
deparse_context *context);
|
||||
deparse_context *context);
|
||||
static void get_from_clause_item(Node *jtnode, Query *query,
|
||||
deparse_context *context);
|
||||
static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
|
||||
deparse_context *context);
|
||||
deparse_context *context);
|
||||
static void get_from_clause_coldeflist(List *coldeflist,
|
||||
deparse_context *context);
|
||||
static void get_opclass_name(Oid opclass, Oid actual_datatype,
|
||||
@@ -486,8 +486,8 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
||||
trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
|
||||
|
||||
/*
|
||||
* Start the trigger definition. Note that the trigger's name should
|
||||
* never be schema-qualified, but the trigger rel's name may be.
|
||||
* Start the trigger definition. Note that the trigger's name should never
|
||||
* be schema-qualified, but the trigger rel's name may be.
|
||||
*/
|
||||
initStringInfo(&buf);
|
||||
|
||||
@@ -527,7 +527,7 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
||||
{
|
||||
if (trigrec->tgconstrrelid != InvalidOid)
|
||||
appendStringInfo(&buf, "FROM %s ",
|
||||
generate_relation_name(trigrec->tgconstrrelid));
|
||||
generate_relation_name(trigrec->tgconstrrelid));
|
||||
if (!trigrec->tgdeferrable)
|
||||
appendStringInfo(&buf, "NOT ");
|
||||
appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
|
||||
@@ -688,9 +688,9 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
|
||||
amrec = (Form_pg_am) GETSTRUCT(ht_am);
|
||||
|
||||
/*
|
||||
* Get the index expressions, if any. (NOTE: we do not use the
|
||||
* relcache versions of the expressions and predicate, because we want
|
||||
* to display non-const-folded expressions.)
|
||||
* Get the index expressions, if any. (NOTE: we do not use the relcache
|
||||
* versions of the expressions and predicate, because we want to display
|
||||
* non-const-folded expressions.)
|
||||
*/
|
||||
if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
|
||||
{
|
||||
@@ -714,8 +714,8 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
|
||||
context = deparse_context_for(get_rel_name(indrelid), indrelid);
|
||||
|
||||
/*
|
||||
* Start the index definition. Note that the index's name should
|
||||
* never be schema-qualified, but the indexed rel's name may be.
|
||||
* Start the index definition. Note that the index's name should never be
|
||||
* schema-qualified, but the indexed rel's name may be.
|
||||
*/
|
||||
initStringInfo(&buf);
|
||||
|
||||
@@ -764,7 +764,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
|
||||
{
|
||||
/* Need parens if it's not a bare function call */
|
||||
if (indexkey && IsA(indexkey, FuncExpr) &&
|
||||
((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
|
||||
((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
|
||||
appendStringInfoString(&buf, str);
|
||||
else
|
||||
appendStringInfo(&buf, "(%s)", str);
|
||||
@@ -831,7 +831,7 @@ pg_get_constraintdef(PG_FUNCTION_ARGS)
|
||||
Oid constraintId = PG_GETARG_OID(0);
|
||||
|
||||
PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
|
||||
false, 0)));
|
||||
false, 0)));
|
||||
}
|
||||
|
||||
Datum
|
||||
@@ -843,7 +843,7 @@ pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
|
||||
|
||||
prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
|
||||
PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
|
||||
false, prettyFlags)));
|
||||
false, prettyFlags)));
|
||||
}
|
||||
|
||||
/* Internal version that returns a palloc'd C string */
|
||||
@@ -865,8 +865,8 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
|
||||
Form_pg_constraint conForm;
|
||||
|
||||
/*
|
||||
* Fetch the pg_constraint row. There's no syscache for pg_constraint
|
||||
* so we must do it the hard way.
|
||||
* Fetch the pg_constraint row. There's no syscache for pg_constraint so
|
||||
* we must do it the hard way.
|
||||
*/
|
||||
conDesc = heap_open(ConstraintRelationId, AccessShareLock);
|
||||
|
||||
@@ -914,7 +914,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
|
||||
|
||||
/* add foreign relation name */
|
||||
appendStringInfo(&buf, ") REFERENCES %s(",
|
||||
generate_relation_name(conForm->confrelid));
|
||||
generate_relation_name(conForm->confrelid));
|
||||
|
||||
/* Fetch and build referenced-column list */
|
||||
val = heap_getattr(tup, Anum_pg_constraint_confkey,
|
||||
@@ -1067,15 +1067,13 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
|
||||
prettyFlags, 0);
|
||||
|
||||
/*
|
||||
* Now emit the constraint definition. There are cases
|
||||
* where the constraint expression will be fully
|
||||
* parenthesized and we don't need the outer parens ...
|
||||
* but there are other cases where we do need 'em. Be
|
||||
* conservative for now.
|
||||
* Now emit the constraint definition. There are cases where
|
||||
* the constraint expression will be fully parenthesized and
|
||||
* we don't need the outer parens ... but there are other
|
||||
* cases where we do need 'em. Be conservative for now.
|
||||
*
|
||||
* Note that simply checking for leading '(' and trailing ')'
|
||||
* would NOT be good enough, consider "(x > 0) AND (y >
|
||||
* 0)".
|
||||
* would NOT be good enough, consider "(x > 0) AND (y > 0)".
|
||||
*/
|
||||
appendStringInfo(&buf, "CHECK (%s)", consrc);
|
||||
|
||||
@@ -1259,7 +1257,7 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS)
|
||||
|
||||
/* Get the number of the column */
|
||||
column = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(columnname)));
|
||||
PointerGetDatum(columnname)));
|
||||
|
||||
attnum = get_attnum(tableOid, column);
|
||||
if (attnum == InvalidAttrNumber)
|
||||
@@ -1292,8 +1290,8 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS)
|
||||
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
|
||||
|
||||
/*
|
||||
* We assume any internal dependency of a relation on a column
|
||||
* must be what we are looking for.
|
||||
* We assume any internal dependency of a relation on a column must be
|
||||
* what we are looking for.
|
||||
*/
|
||||
if (deprec->classid == RelationRelationId &&
|
||||
deprec->objsubid == 0 &&
|
||||
@@ -1510,7 +1508,7 @@ deparse_context_for_subplan(const char *name, List *tlist,
|
||||
if (var->varnoold > 0 && var->varnoold <= rtablelength)
|
||||
{
|
||||
RangeTblEntry *varrte = rt_fetch(var->varnoold, rtable);
|
||||
AttrNumber varattnum = var->varoattno;
|
||||
AttrNumber varattnum = var->varoattno;
|
||||
|
||||
/* need this test in case it's referencing a resjunk col */
|
||||
if (varattnum <= list_length(varrte->eref->colnames))
|
||||
@@ -1637,8 +1635,8 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
|
||||
appendStringInfo(buf, " TO %s", generate_relation_name(ev_class));
|
||||
if (ev_attr > 0)
|
||||
appendStringInfo(buf, ".%s",
|
||||
quote_identifier(get_relid_attribute_name(ev_class,
|
||||
ev_attr)));
|
||||
quote_identifier(get_relid_attribute_name(ev_class,
|
||||
ev_attr)));
|
||||
|
||||
/* If the rule has an event qualification, add it */
|
||||
if (ev_qual == NULL)
|
||||
@@ -1658,15 +1656,15 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
|
||||
|
||||
/*
|
||||
* We need to make a context for recognizing any Vars in the qual
|
||||
* (which can only be references to OLD and NEW). Use the rtable
|
||||
* of the first query in the action list for this purpose.
|
||||
* (which can only be references to OLD and NEW). Use the rtable of
|
||||
* the first query in the action list for this purpose.
|
||||
*/
|
||||
query = (Query *) linitial(actions);
|
||||
|
||||
/*
|
||||
* If the action is INSERT...SELECT, OLD/NEW have been pushed down
|
||||
* into the SELECT, and that's what we need to look at. (Ugly
|
||||
* kluge ... try to fix this when we redesign querytrees.)
|
||||
* into the SELECT, and that's what we need to look at. (Ugly kluge
|
||||
* ... try to fix this when we redesign querytrees.)
|
||||
*/
|
||||
query = getInsertSelectQuery(query, NULL);
|
||||
|
||||
@@ -1809,9 +1807,9 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace,
|
||||
|
||||
/*
|
||||
* Before we begin to examine the query, acquire locks on referenced
|
||||
* relations, and fix up deleted columns in JOIN RTEs. This ensures
|
||||
* consistent results. Note we assume it's OK to scribble on the
|
||||
* passed querytree!
|
||||
* relations, and fix up deleted columns in JOIN RTEs. This ensures
|
||||
* consistent results. Note we assume it's OK to scribble on the passed
|
||||
* querytree!
|
||||
*/
|
||||
AcquireRewriteLocks(query);
|
||||
|
||||
@@ -1874,9 +1872,9 @@ get_select_query_def(Query *query, deparse_context *context,
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* If the Query node has a setOperations tree, then it's the top level
|
||||
* of a UNION/INTERSECT/EXCEPT query; only the ORDER BY and LIMIT
|
||||
* fields are interesting in the top query itself.
|
||||
* If the Query node has a setOperations tree, then it's the top level of
|
||||
* a UNION/INTERSECT/EXCEPT query; only the ORDER BY and LIMIT fields are
|
||||
* interesting in the top query itself.
|
||||
*/
|
||||
if (query->setOperations)
|
||||
{
|
||||
@@ -1909,7 +1907,7 @@ get_select_query_def(Query *query, deparse_context *context,
|
||||
sortcoltype = exprType(sortexpr);
|
||||
/* See whether operator is default < or > for datatype */
|
||||
typentry = lookup_type_cache(sortcoltype,
|
||||
TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
|
||||
TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
|
||||
if (srt->sortop == typentry->lt_opr)
|
||||
/* ASC is default, so emit nothing */ ;
|
||||
else if (srt->sortop == typentry->gt_opr)
|
||||
@@ -2025,10 +2023,10 @@ get_basic_select_query(Query *query, deparse_context *context,
|
||||
get_rule_expr((Node *) tle->expr, context, true);
|
||||
|
||||
/*
|
||||
* Figure out what the result column should be called. In the
|
||||
* context of a view, use the view's tuple descriptor (so as to
|
||||
* pick up the effects of any column RENAME that's been done on
|
||||
* the view). Otherwise, just use what we can find in the TLE.
|
||||
* Figure out what the result column should be called. In the context
|
||||
* of a view, use the view's tuple descriptor (so as to pick up the
|
||||
* effects of any column RENAME that's been done on the view).
|
||||
* Otherwise, just use what we can find in the TLE.
|
||||
*/
|
||||
if (resultDesc && colno <= resultDesc->natts)
|
||||
colname = NameStr(resultDesc->attrs[colno - 1]->attname);
|
||||
@@ -2130,10 +2128,10 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
|
||||
SetOperationStmt *op = (SetOperationStmt *) setOp;
|
||||
|
||||
/*
|
||||
* We force parens whenever nesting two SetOperationStmts. There
|
||||
* are some cases in which parens are needed around a leaf query
|
||||
* too, but those are more easily handled at the next level down
|
||||
* (see code above).
|
||||
* We force parens whenever nesting two SetOperationStmts. There are
|
||||
* some cases in which parens are needed around a leaf query too, but
|
||||
* those are more easily handled at the next level down (see code
|
||||
* above).
|
||||
*/
|
||||
need_paren = !IsA(op->larg, RangeTblRef);
|
||||
|
||||
@@ -2231,8 +2229,8 @@ get_insert_query_def(Query *query, deparse_context *context)
|
||||
List *strippedexprs;
|
||||
|
||||
/*
|
||||
* If it's an INSERT ... SELECT there will be a single subquery RTE
|
||||
* for the SELECT.
|
||||
* If it's an INSERT ... SELECT there will be a single subquery RTE for
|
||||
* the SELECT.
|
||||
*/
|
||||
foreach(l, query->rtable)
|
||||
{
|
||||
@@ -2279,13 +2277,12 @@ get_insert_query_def(Query *query, deparse_context *context)
|
||||
* tle->resname, since resname will fail to track RENAME.
|
||||
*/
|
||||
appendStringInfoString(buf,
|
||||
quote_identifier(get_relid_attribute_name(rte->relid,
|
||||
tle->resno)));
|
||||
quote_identifier(get_relid_attribute_name(rte->relid,
|
||||
tle->resno)));
|
||||
|
||||
/*
|
||||
* Print any indirection needed (subfields or subscripts), and
|
||||
* strip off the top-level nodes representing the indirection
|
||||
* assignments.
|
||||
* Print any indirection needed (subfields or subscripts), and strip
|
||||
* off the top-level nodes representing the indirection assignments.
|
||||
*/
|
||||
strippedexprs = lappend(strippedexprs,
|
||||
processIndirection((Node *) tle->expr,
|
||||
@@ -2351,13 +2348,12 @@ get_update_query_def(Query *query, deparse_context *context)
|
||||
* tle->resname, since resname will fail to track RENAME.
|
||||
*/
|
||||
appendStringInfoString(buf,
|
||||
quote_identifier(get_relid_attribute_name(rte->relid,
|
||||
tle->resno)));
|
||||
quote_identifier(get_relid_attribute_name(rte->relid,
|
||||
tle->resno)));
|
||||
|
||||
/*
|
||||
* Print any indirection needed (subfields or subscripts), and
|
||||
* strip off the top-level nodes representing the indirection
|
||||
* assignments.
|
||||
* Print any indirection needed (subfields or subscripts), and strip
|
||||
* off the top-level nodes representing the indirection assignments.
|
||||
*/
|
||||
expr = processIndirection((Node *) tle->expr, context);
|
||||
|
||||
@@ -2432,8 +2428,8 @@ get_utility_query_def(Query *query, deparse_context *context)
|
||||
appendContextKeyword(context, "",
|
||||
0, PRETTYINDENT_STD, 1);
|
||||
appendStringInfo(buf, "NOTIFY %s",
|
||||
quote_qualified_identifier(stmt->relation->schemaname,
|
||||
stmt->relation->relname));
|
||||
quote_qualified_identifier(stmt->relation->schemaname,
|
||||
stmt->relation->relname));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2517,10 +2513,9 @@ get_names_for_var(Var *var, int levelsup, deparse_context *context,
|
||||
if (rte->rtekind == RTE_RELATION)
|
||||
{
|
||||
/*
|
||||
* It's possible that use of the bare refname would find
|
||||
* another more-closely-nested RTE, or be ambiguous, in which
|
||||
* case we need to specify the schemaname to avoid these
|
||||
* errors.
|
||||
* It's possible that use of the bare refname would find another
|
||||
* more-closely-nested RTE, or be ambiguous, in which case we need
|
||||
* to specify the schemaname to avoid these errors.
|
||||
*/
|
||||
if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
|
||||
*schemaname =
|
||||
@@ -2530,20 +2525,20 @@ get_names_for_var(Var *var, int levelsup, deparse_context *context,
|
||||
{
|
||||
/*
|
||||
* If it's an unnamed join, look at the expansion of the alias
|
||||
* variable. If it's a simple reference to one of the input
|
||||
* vars then recursively find the name of that var, instead.
|
||||
* (This allows correct decompiling of cases where there are
|
||||
* identically named columns on both sides of the join.)
|
||||
* When it's not a simple reference, we have to just return
|
||||
* the unqualified variable name (this can only happen with
|
||||
* columns that were merged by USING or NATURAL clauses).
|
||||
* variable. If it's a simple reference to one of the input vars
|
||||
* then recursively find the name of that var, instead. (This
|
||||
* allows correct decompiling of cases where there are identically
|
||||
* named columns on both sides of the join.) When it's not a
|
||||
* simple reference, we have to just return the unqualified
|
||||
* variable name (this can only happen with columns that were
|
||||
* merged by USING or NATURAL clauses).
|
||||
*/
|
||||
if (var->varattno > 0)
|
||||
{
|
||||
Var *aliasvar;
|
||||
Var *aliasvar;
|
||||
|
||||
aliasvar = (Var *) list_nth(rte->joinaliasvars,
|
||||
var->varattno-1);
|
||||
var->varattno - 1);
|
||||
if (IsA(aliasvar, Var))
|
||||
{
|
||||
get_names_for_var(aliasvar,
|
||||
@@ -2568,9 +2563,9 @@ get_names_for_var(Var *var, int levelsup, deparse_context *context,
|
||||
* Get the name of a field of a Var of type RECORD.
|
||||
*
|
||||
* Since no actual table or view column is allowed to have type RECORD, such
|
||||
* a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
|
||||
* a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
|
||||
* drill down to find the ultimate defining expression and attempt to infer
|
||||
* the field name from it. We ereport if we can't determine the name.
|
||||
* the field name from it. We ereport if we can't determine the name.
|
||||
*
|
||||
* levelsup is an extra offset to interpret the Var's varlevelsup correctly.
|
||||
*
|
||||
@@ -2609,6 +2604,7 @@ get_name_for_var_field(Var *var, int fieldno,
|
||||
{
|
||||
case RTE_RELATION:
|
||||
case RTE_SPECIAL:
|
||||
|
||||
/*
|
||||
* This case should not occur: a column of a table shouldn't have
|
||||
* type RECORD. Fall through and fail (most likely) at the
|
||||
@@ -2629,7 +2625,7 @@ get_name_for_var_field(Var *var, int fieldno,
|
||||
{
|
||||
/*
|
||||
* Recurse into the sub-select to see what its Var refers
|
||||
* to. We have to build an additional level of namespace
|
||||
* to. We have to build an additional level of namespace
|
||||
* to keep in step with varlevelsup in the subselect.
|
||||
*/
|
||||
deparse_namespace mydpns;
|
||||
@@ -2662,18 +2658,19 @@ get_name_for_var_field(Var *var, int fieldno,
|
||||
/* else fall through to inspect the expression */
|
||||
break;
|
||||
case RTE_FUNCTION:
|
||||
|
||||
/*
|
||||
* We couldn't get here unless a function is declared with one
|
||||
* of its result columns as RECORD, which is not allowed.
|
||||
* We couldn't get here unless a function is declared with one of
|
||||
* its result columns as RECORD, which is not allowed.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have an expression we can't expand any more, so see if
|
||||
* get_expr_result_type() can do anything with it. If not, pass
|
||||
* to lookup_rowtype_tupdesc() which will probably fail, but will
|
||||
* give an appropriate error message while failing.
|
||||
* get_expr_result_type() can do anything with it. If not, pass to
|
||||
* lookup_rowtype_tupdesc() which will probably fail, but will give an
|
||||
* appropriate error message while failing.
|
||||
*/
|
||||
if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
|
||||
tupleDesc = lookup_rowtype_tupdesc(exprType(expr), exprTypmod(expr));
|
||||
@@ -2866,8 +2863,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Operators are same priority --- can skip parens
|
||||
* only if we have (a - b) - c, not a - (b - c).
|
||||
* Operators are same priority --- can skip parens only if
|
||||
* we have (a - b) - c, not a - (b - c).
|
||||
*/
|
||||
if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
|
||||
return true;
|
||||
@@ -2897,11 +2894,11 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||
case T_BoolExpr: /* lower precedence */
|
||||
case T_ArrayRef: /* other separators */
|
||||
case T_ArrayExpr: /* other separators */
|
||||
case T_RowExpr: /* other separators */
|
||||
case T_RowExpr: /* other separators */
|
||||
case T_CoalesceExpr: /* own parentheses */
|
||||
case T_MinMaxExpr: /* own parentheses */
|
||||
case T_NullIfExpr: /* other separators */
|
||||
case T_Aggref: /* own parentheses */
|
||||
case T_Aggref: /* own parentheses */
|
||||
case T_CaseExpr: /* other separators */
|
||||
return true;
|
||||
default:
|
||||
@@ -2945,11 +2942,11 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||
}
|
||||
case T_ArrayRef: /* other separators */
|
||||
case T_ArrayExpr: /* other separators */
|
||||
case T_RowExpr: /* other separators */
|
||||
case T_RowExpr: /* other separators */
|
||||
case T_CoalesceExpr: /* own parentheses */
|
||||
case T_MinMaxExpr: /* own parentheses */
|
||||
case T_NullIfExpr: /* other separators */
|
||||
case T_Aggref: /* own parentheses */
|
||||
case T_Aggref: /* own parentheses */
|
||||
case T_CaseExpr: /* other separators */
|
||||
return true;
|
||||
default:
|
||||
@@ -3055,10 +3052,10 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
|
||||
/*
|
||||
* Each level of get_rule_expr must emit an indivisible term
|
||||
* (parenthesized if necessary) to ensure result is reparsed into the
|
||||
* same expression tree. The only exception is that when the input
|
||||
* is a List, we emit the component items comma-separated with no
|
||||
* surrounding decoration; this is convenient for most callers.
|
||||
* (parenthesized if necessary) to ensure result is reparsed into the same
|
||||
* expression tree. The only exception is that when the input is a List,
|
||||
* we emit the component items comma-separated with no surrounding
|
||||
* decoration; this is convenient for most callers.
|
||||
*
|
||||
* There might be some work left here to support additional node types.
|
||||
*/
|
||||
@@ -3129,8 +3126,8 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
|
||||
/*
|
||||
* Parenthesize the argument unless it's a simple Var or a
|
||||
* FieldSelect. (In particular, if it's another ArrayRef,
|
||||
* we *must* parenthesize to avoid confusion.)
|
||||
* FieldSelect. (In particular, if it's another ArrayRef, we
|
||||
* *must* parenthesize to avoid confusion.)
|
||||
*/
|
||||
need_parens = !IsA(aref->refexpr, Var) &&
|
||||
!IsA(aref->refexpr, FieldSelect);
|
||||
@@ -3188,7 +3185,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
appendStringInfo(buf, " %s %s (",
|
||||
generate_operator_name(expr->opno,
|
||||
exprType(arg1),
|
||||
get_element_type(exprType(arg2))),
|
||||
get_element_type(exprType(arg2))),
|
||||
expr->useOr ? "ANY" : "ALL");
|
||||
get_rule_expr_paren(arg2, context, true, node);
|
||||
appendStringInfoChar(buf, ')');
|
||||
@@ -3261,9 +3258,8 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
case T_SubPlan:
|
||||
{
|
||||
/*
|
||||
* We cannot see an already-planned subplan in rule
|
||||
* deparsing, only while EXPLAINing a query plan. For now,
|
||||
* just punt.
|
||||
* We cannot see an already-planned subplan in rule deparsing,
|
||||
* only while EXPLAINing a query plan. For now, just punt.
|
||||
*/
|
||||
if (((SubPlan *) node)->useHashTable)
|
||||
appendStringInfo(buf, "(hashed subplan)");
|
||||
@@ -3282,12 +3278,11 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
|
||||
/*
|
||||
* Parenthesize the argument unless it's an ArrayRef or
|
||||
* another FieldSelect. Note in particular that it would
|
||||
* be WRONG to not parenthesize a Var argument; simplicity
|
||||
* is not the issue here, having the right number of names
|
||||
* is.
|
||||
* another FieldSelect. Note in particular that it would be
|
||||
* WRONG to not parenthesize a Var argument; simplicity is not
|
||||
* the issue here, having the right number of names is.
|
||||
*/
|
||||
need_parens = !IsA(arg, ArrayRef) && !IsA(arg, FieldSelect);
|
||||
need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
|
||||
if (need_parens)
|
||||
appendStringInfoChar(buf, '(');
|
||||
get_rule_expr(arg, context, true);
|
||||
@@ -3296,8 +3291,8 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
|
||||
/*
|
||||
* If it's a Var of type RECORD, we have to find what the Var
|
||||
* refers to; otherwise we can use get_expr_result_type.
|
||||
* If that fails, we try lookup_rowtype_tupdesc, which will
|
||||
* refers to; otherwise we can use get_expr_result_type. If
|
||||
* that fails, we try lookup_rowtype_tupdesc, which will
|
||||
* probably fail too, but will ereport an acceptable message.
|
||||
*/
|
||||
if (IsA(arg, Var) &&
|
||||
@@ -3324,8 +3319,8 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
case T_FieldStore:
|
||||
|
||||
/*
|
||||
* We shouldn't see FieldStore here; it should have been
|
||||
* stripped off by processIndirection().
|
||||
* We shouldn't see FieldStore here; it should have been stripped
|
||||
* off by processIndirection().
|
||||
*/
|
||||
elog(ERROR, "unexpected FieldStore");
|
||||
break;
|
||||
@@ -3349,8 +3344,8 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
if (!PRETTY_PAREN(context))
|
||||
appendStringInfoChar(buf, ')');
|
||||
appendStringInfo(buf, "::%s",
|
||||
format_type_with_typemod(relabel->resulttype,
|
||||
relabel->resulttypmod));
|
||||
format_type_with_typemod(relabel->resulttype,
|
||||
relabel->resulttypmod));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3374,7 +3369,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
if (!PRETTY_PAREN(context))
|
||||
appendStringInfoChar(buf, ')');
|
||||
appendStringInfo(buf, "::%s",
|
||||
format_type_with_typemod(convert->resulttype, -1));
|
||||
format_type_with_typemod(convert->resulttype, -1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3444,9 +3439,9 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
char *sep;
|
||||
|
||||
/*
|
||||
* If it's a named type and not RECORD, we may have to
|
||||
* skip dropped columns and/or claim there are NULLs for
|
||||
* added columns.
|
||||
* If it's a named type and not RECORD, we may have to skip
|
||||
* dropped columns and/or claim there are NULLs for added
|
||||
* columns.
|
||||
*/
|
||||
if (rowexpr->row_typeid != RECORDOID)
|
||||
{
|
||||
@@ -3455,8 +3450,8 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL99 allows "ROW" to be omitted when there is more
|
||||
* than one column, but for simplicity we always print it.
|
||||
* SQL99 allows "ROW" to be omitted when there is more than
|
||||
* one column, but for simplicity we always print it.
|
||||
*/
|
||||
appendStringInfo(buf, "ROW(");
|
||||
sep = "";
|
||||
@@ -3490,7 +3485,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
appendStringInfo(buf, ")");
|
||||
if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
|
||||
appendStringInfo(buf, "::%s",
|
||||
format_type_with_typemod(rowexpr->row_typeid, -1));
|
||||
format_type_with_typemod(rowexpr->row_typeid, -1));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3611,8 +3606,8 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
if (!PRETTY_PAREN(context))
|
||||
appendStringInfoChar(buf, ')');
|
||||
appendStringInfo(buf, "::%s",
|
||||
format_type_with_typemod(ctest->resulttype,
|
||||
ctest->resulttypmod));
|
||||
format_type_with_typemod(ctest->resulttype,
|
||||
ctest->resulttypmod));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3724,9 +3719,8 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* If the function call came from an implicit coercion, then just show
|
||||
* the first argument --- unless caller wants to see implicit
|
||||
* coercions.
|
||||
* If the function call came from an implicit coercion, then just show the
|
||||
* first argument --- unless caller wants to see implicit coercions.
|
||||
*/
|
||||
if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
|
||||
{
|
||||
@@ -3755,14 +3749,14 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
|
||||
if (!PRETTY_PAREN(context))
|
||||
appendStringInfoChar(buf, ')');
|
||||
appendStringInfo(buf, "::%s",
|
||||
format_type_with_typemod(rettype, coercedTypmod));
|
||||
format_type_with_typemod(rettype, coercedTypmod));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normal function: display as proname(args). First we need to
|
||||
* extract the argument datatypes.
|
||||
* Normal function: display as proname(args). First we need to extract
|
||||
* the argument datatypes.
|
||||
*/
|
||||
nargs = 0;
|
||||
foreach(l, expr->args)
|
||||
@@ -3791,7 +3785,7 @@ get_agg_expr(Aggref *aggref, deparse_context *context)
|
||||
Oid argtype = exprType((Node *) aggref->target);
|
||||
|
||||
appendStringInfo(buf, "%s(%s",
|
||||
generate_function_name(aggref->aggfnoid, 1, &argtype),
|
||||
generate_function_name(aggref->aggfnoid, 1, &argtype),
|
||||
aggref->aggdistinct ? "DISTINCT " : "");
|
||||
if (aggref->aggstar)
|
||||
appendStringInfo(buf, "*");
|
||||
@@ -3821,11 +3815,11 @@ get_const_expr(Const *constval, deparse_context *context)
|
||||
if (constval->constisnull)
|
||||
{
|
||||
/*
|
||||
* Always label the type of a NULL constant to prevent
|
||||
* misdecisions about type when reparsing.
|
||||
* Always label the type of a NULL constant to prevent misdecisions
|
||||
* about type when reparsing.
|
||||
*/
|
||||
appendStringInfo(buf, "NULL::%s",
|
||||
format_type_with_typemod(constval->consttype, -1));
|
||||
format_type_with_typemod(constval->consttype, -1));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3846,14 +3840,13 @@ get_const_expr(Const *constval, deparse_context *context)
|
||||
case NUMERICOID:
|
||||
{
|
||||
/*
|
||||
* These types are printed without quotes unless they
|
||||
* contain values that aren't accepted by the scanner
|
||||
* unquoted (e.g., 'NaN'). Note that strtod() and friends
|
||||
* might accept NaN, so we can't use that to test.
|
||||
* These types are printed without quotes unless they contain
|
||||
* values that aren't accepted by the scanner unquoted (e.g.,
|
||||
* 'NaN'). Note that strtod() and friends might accept NaN,
|
||||
* so we can't use that to test.
|
||||
*
|
||||
* In reality we only need to defend against infinity and
|
||||
* NaN, so we need not get too crazy about pattern
|
||||
* matching here.
|
||||
* In reality we only need to defend against infinity and NaN, so
|
||||
* we need not get too crazy about pattern matching here.
|
||||
*/
|
||||
if (strspn(extval, "0123456789+-eE.") == strlen(extval))
|
||||
{
|
||||
@@ -3879,13 +3872,14 @@ get_const_expr(Const *constval, deparse_context *context)
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/*
|
||||
* We must quote any funny characters in the constant's
|
||||
* representation. XXX Any MULTIBYTE considerations here?
|
||||
*/
|
||||
for (valptr = extval; *valptr; valptr++)
|
||||
if (*valptr == '\\' ||
|
||||
(unsigned char)*valptr < (unsigned char)' ')
|
||||
(unsigned char) *valptr < (unsigned char) ' ')
|
||||
{
|
||||
appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
|
||||
break;
|
||||
@@ -3901,7 +3895,7 @@ get_const_expr(Const *constval, deparse_context *context)
|
||||
appendStringInfoChar(buf, ch);
|
||||
appendStringInfoChar(buf, ch);
|
||||
}
|
||||
else if ((unsigned char)ch < (unsigned char)' ')
|
||||
else if ((unsigned char) ch < (unsigned char) ' ')
|
||||
appendStringInfo(buf, "\\%03o", (int) ch);
|
||||
else
|
||||
appendStringInfoChar(buf, ch);
|
||||
@@ -3913,9 +3907,9 @@ get_const_expr(Const *constval, deparse_context *context)
|
||||
pfree(extval);
|
||||
|
||||
/*
|
||||
* Append ::typename unless the constant will be implicitly typed as
|
||||
* the right type when it is read in. XXX this code has to be kept in
|
||||
* sync with the behavior of the parser, especially make_const.
|
||||
* Append ::typename unless the constant will be implicitly typed as the
|
||||
* right type when it is read in. XXX this code has to be kept in sync
|
||||
* with the behavior of the parser, especially make_const.
|
||||
*/
|
||||
switch (constval->consttype)
|
||||
{
|
||||
@@ -3935,7 +3929,7 @@ get_const_expr(Const *constval, deparse_context *context)
|
||||
}
|
||||
if (needlabel)
|
||||
appendStringInfo(buf, "::%s",
|
||||
format_type_with_typemod(constval->consttype, -1));
|
||||
format_type_with_typemod(constval->consttype, -1));
|
||||
}
|
||||
|
||||
|
||||
@@ -3969,10 +3963,10 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
|
||||
need_paren = true;
|
||||
|
||||
/*
|
||||
* XXX we regurgitate the originally given operator name, with or
|
||||
* without schema qualification. This is not necessarily 100% right
|
||||
* but it's the best we can do, since the operators actually used
|
||||
* might not all be in the same schema.
|
||||
* XXX we regurgitate the originally given operator name, with or without
|
||||
* schema qualification. This is not necessarily 100% right but it's the
|
||||
* best we can do, since the operators actually used might not all be in
|
||||
* the same schema.
|
||||
*/
|
||||
switch (sublink->subLinkType)
|
||||
{
|
||||
@@ -4044,11 +4038,11 @@ get_from_clause(Query *query, const char *prefix, deparse_context *context)
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* We use the query's jointree as a guide to what to print. However,
|
||||
* we must ignore auto-added RTEs that are marked not inFromCl. (These
|
||||
* can only appear at the top level of the jointree, so it's
|
||||
* sufficient to check here.) This check also ensures we ignore
|
||||
* the rule pseudo-RTEs for NEW and OLD.
|
||||
* We use the query's jointree as a guide to what to print. However, we
|
||||
* must ignore auto-added RTEs that are marked not inFromCl. (These can
|
||||
* only appear at the top level of the jointree, so it's sufficient to
|
||||
* check here.) This check also ensures we ignore the rule pseudo-RTEs
|
||||
* for NEW and OLD.
|
||||
*/
|
||||
foreach(l, query->jointree->fromlist)
|
||||
{
|
||||
@@ -4124,10 +4118,10 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||
strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
|
||||
{
|
||||
/*
|
||||
* Apparently the rel has been renamed since the rule was
|
||||
* made. Emit a fake alias clause so that variable references
|
||||
* will still work. This is not a 100% solution but should
|
||||
* work in most reasonable situations.
|
||||
* Apparently the rel has been renamed since the rule was made.
|
||||
* Emit a fake alias clause so that variable references will still
|
||||
* work. This is not a 100% solution but should work in most
|
||||
* reasonable situations.
|
||||
*/
|
||||
appendStringInfo(buf, " %s",
|
||||
quote_identifier(rte->eref->aliasname));
|
||||
@@ -4136,10 +4130,9 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||
else if (rte->rtekind == RTE_FUNCTION)
|
||||
{
|
||||
/*
|
||||
* For a function RTE, always give an alias.
|
||||
* This covers possible renaming of the function and/or
|
||||
* instability of the FigureColname rules for things that
|
||||
* aren't simple functions.
|
||||
* For a function RTE, always give an alias. This covers possible
|
||||
* renaming of the function and/or instability of the
|
||||
* FigureColname rules for things that aren't simple functions.
|
||||
*/
|
||||
appendStringInfo(buf, " %s",
|
||||
quote_identifier(rte->eref->aliasname));
|
||||
@@ -4175,7 +4168,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||
|
||||
need_paren_on_right = PRETTY_PAREN(context) &&
|
||||
!IsA(j->rarg, RangeTblRef) &&
|
||||
!(IsA(j->rarg, JoinExpr) && ((JoinExpr*) j->rarg)->alias != NULL);
|
||||
!(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
|
||||
|
||||
if (!PRETTY_PAREN(context) || j->alias != NULL)
|
||||
appendStringInfoChar(buf, '(');
|
||||
@@ -4278,7 +4271,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||
if (col != list_head(j->using))
|
||||
appendStringInfo(buf, ", ");
|
||||
appendStringInfoString(buf,
|
||||
quote_identifier(strVal(lfirst(col))));
|
||||
quote_identifier(strVal(lfirst(col))));
|
||||
}
|
||||
appendStringInfoChar(buf, ')');
|
||||
}
|
||||
@@ -4415,8 +4408,7 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
|
||||
opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
|
||||
|
||||
/*
|
||||
* Special case for ARRAY_OPS: pretend it is default for any array
|
||||
* type
|
||||
* Special case for ARRAY_OPS: pretend it is default for any array type
|
||||
*/
|
||||
if (OidIsValid(actual_datatype))
|
||||
{
|
||||
@@ -4476,19 +4468,19 @@ processIndirection(Node *node, deparse_context *context)
|
||||
format_type_be(fstore->resulttype));
|
||||
|
||||
/*
|
||||
* Get the field name. Note we assume here that there's only
|
||||
* one field being assigned to. This is okay in stored rules
|
||||
* but could be wrong in executable target lists. Presently
|
||||
* no problem since explain.c doesn't print plan targetlists,
|
||||
* but someday may have to think of something ...
|
||||
* Get the field name. Note we assume here that there's only one
|
||||
* field being assigned to. This is okay in stored rules but
|
||||
* could be wrong in executable target lists. Presently no
|
||||
* problem since explain.c doesn't print plan targetlists, but
|
||||
* someday may have to think of something ...
|
||||
*/
|
||||
fieldname = get_relid_attribute_name(typrelid,
|
||||
linitial_int(fstore->fieldnums));
|
||||
linitial_int(fstore->fieldnums));
|
||||
appendStringInfo(buf, ".%s", quote_identifier(fieldname));
|
||||
|
||||
/*
|
||||
* We ignore arg since it should be an uninteresting reference
|
||||
* to the target column or subcolumn.
|
||||
* We ignore arg since it should be an uninteresting reference to
|
||||
* the target column or subcolumn.
|
||||
*/
|
||||
node = (Node *) linitial(fstore->newvals);
|
||||
}
|
||||
@@ -4501,8 +4493,8 @@ processIndirection(Node *node, deparse_context *context)
|
||||
printSubscripts(aref, context);
|
||||
|
||||
/*
|
||||
* We ignore refexpr since it should be an uninteresting
|
||||
* reference to the target column or subcolumn.
|
||||
* We ignore refexpr since it should be an uninteresting reference
|
||||
* to the target column or subcolumn.
|
||||
*/
|
||||
node = (Node *) aref->refassgnexpr;
|
||||
}
|
||||
@@ -4545,10 +4537,9 @@ const char *
|
||||
quote_identifier(const char *ident)
|
||||
{
|
||||
/*
|
||||
* Can avoid quoting if ident starts with a lowercase letter or
|
||||
* underscore and contains only lowercase letters, digits, and
|
||||
* underscores, *and* is not any SQL keyword. Otherwise, supply
|
||||
* quotes.
|
||||
* Can avoid quoting if ident starts with a lowercase letter or underscore
|
||||
* and contains only lowercase letters, digits, and underscores, *and* is
|
||||
* not any SQL keyword. Otherwise, supply quotes.
|
||||
*/
|
||||
int nquotes = 0;
|
||||
bool safe;
|
||||
@@ -4557,8 +4548,8 @@ quote_identifier(const char *ident)
|
||||
char *optr;
|
||||
|
||||
/*
|
||||
* would like to use <ctype.h> macros here, but they might yield
|
||||
* unwanted locale-specific results...
|
||||
* would like to use <ctype.h> macros here, but they might yield unwanted
|
||||
* locale-specific results...
|
||||
*/
|
||||
safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
|
||||
|
||||
@@ -4583,13 +4574,13 @@ quote_identifier(const char *ident)
|
||||
if (safe)
|
||||
{
|
||||
/*
|
||||
* Check for keyword. This test is overly strong, since many of
|
||||
* the "keywords" known to the parser are usable as column names,
|
||||
* but the parser doesn't provide any easy way to test for whether
|
||||
* an identifier is safe or not... so be safe not sorry.
|
||||
* Check for keyword. This test is overly strong, since many of the
|
||||
* "keywords" known to the parser are usable as column names, but the
|
||||
* parser doesn't provide any easy way to test for whether an
|
||||
* identifier is safe or not... so be safe not sorry.
|
||||
*
|
||||
* Note: ScanKeywordLookup() does case-insensitive comparison, but
|
||||
* that's fine, since we already know we have all-lower-case.
|
||||
* Note: ScanKeywordLookup() does case-insensitive comparison, but that's
|
||||
* fine, since we already know we have all-lower-case.
|
||||
*/
|
||||
if (ScanKeywordLookup(ident) != NULL)
|
||||
safe = false;
|
||||
@@ -4702,8 +4693,8 @@ generate_function_name(Oid funcid, int nargs, Oid *argtypes)
|
||||
|
||||
/*
|
||||
* The idea here is to schema-qualify only if the parser would fail to
|
||||
* resolve the correct function given the unqualified func name with
|
||||
* the specified argtypes.
|
||||
* resolve the correct function given the unqualified func name with the
|
||||
* specified argtypes.
|
||||
*/
|
||||
p_result = func_get_detail(list_make1(makeString(proname)),
|
||||
NIL, nargs, argtypes,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.46 2005/09/24 17:53:16 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.47 2005/10/15 02:49:30 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -83,8 +83,8 @@ bit_in(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Otherwise it's binary. This allows things like cast('1001' as
|
||||
* bit) to work transparently.
|
||||
* Otherwise it's binary. This allows things like cast('1001' as bit)
|
||||
* to work transparently.
|
||||
*/
|
||||
bit_not_hex = true;
|
||||
sp = input_string;
|
||||
@@ -98,16 +98,16 @@ bit_in(PG_FUNCTION_ARGS)
|
||||
bitlen = slen * 4;
|
||||
|
||||
/*
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to
|
||||
* make sure that the bitstring fits.
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
||||
* sure that the bitstring fits.
|
||||
*/
|
||||
if (atttypmod <= 0)
|
||||
atttypmod = bitlen;
|
||||
else if (bitlen != atttypmod)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
||||
errmsg("bit string length %d does not match type bit(%d)",
|
||||
bitlen, atttypmod)));
|
||||
errmsg("bit string length %d does not match type bit(%d)",
|
||||
bitlen, atttypmod)));
|
||||
|
||||
len = VARBITTOTALLEN(atttypmod);
|
||||
/* set to 0 so that *r is always initialised and string is zero-padded */
|
||||
@@ -204,8 +204,8 @@ bit_out(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Go back one step if we printed a hex number that was not part of
|
||||
* the bitstring anymore
|
||||
* Go back one step if we printed a hex number that was not part of the
|
||||
* bitstring anymore
|
||||
*/
|
||||
if (i > len)
|
||||
r--;
|
||||
@@ -222,6 +222,7 @@ Datum
|
||||
bit_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
@@ -239,14 +240,14 @@ bit_recv(PG_FUNCTION_ARGS)
|
||||
errmsg("invalid length in external bit string")));
|
||||
|
||||
/*
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to
|
||||
* make sure that the bitstring fits.
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
||||
* sure that the bitstring fits.
|
||||
*/
|
||||
if (atttypmod > 0 && bitlen != atttypmod)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
||||
errmsg("bit string length %d does not match type bit(%d)",
|
||||
bitlen, atttypmod)));
|
||||
errmsg("bit string length %d does not match type bit(%d)",
|
||||
bitlen, atttypmod)));
|
||||
|
||||
len = VARBITTOTALLEN(bitlen);
|
||||
result = (VarBit *) palloc(len);
|
||||
@@ -301,8 +302,8 @@ bit(PG_FUNCTION_ARGS)
|
||||
if (!isExplicit)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
||||
errmsg("bit string length %d does not match type bit(%d)",
|
||||
VARBITLEN(arg), len)));
|
||||
errmsg("bit string length %d does not match type bit(%d)",
|
||||
VARBITLEN(arg), len)));
|
||||
|
||||
rlen = VARBITTOTALLEN(len);
|
||||
/* set to 0 so that string is zero-padded */
|
||||
@@ -314,9 +315,9 @@ bit(PG_FUNCTION_ARGS)
|
||||
Min(VARBITBYTES(result), VARBITBYTES(arg)));
|
||||
|
||||
/*
|
||||
* Make sure last byte is zero-padded if needed. This is useless but
|
||||
* safe if source data was shorter than target length (we assume the
|
||||
* last byte of the source data was itself correctly zero-padded).
|
||||
* Make sure last byte is zero-padded if needed. This is useless but safe
|
||||
* if source data was shorter than target length (we assume the last byte
|
||||
* of the source data was itself correctly zero-padded).
|
||||
*/
|
||||
ipad = VARBITPAD(result);
|
||||
if (ipad > 0)
|
||||
@@ -378,8 +379,8 @@ varbit_in(PG_FUNCTION_ARGS)
|
||||
bitlen = slen * 4;
|
||||
|
||||
/*
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to
|
||||
* make sure that the bitstring fits.
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
||||
* sure that the bitstring fits.
|
||||
*/
|
||||
if (atttypmod <= 0)
|
||||
atttypmod = bitlen;
|
||||
@@ -500,6 +501,7 @@ Datum
|
||||
varbit_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
@@ -517,8 +519,8 @@ varbit_recv(PG_FUNCTION_ARGS)
|
||||
errmsg("invalid length in external bit string")));
|
||||
|
||||
/*
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to
|
||||
* make sure that the bitstring fits.
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
||||
* sure that the bitstring fits.
|
||||
*/
|
||||
if (atttypmod > 0 && bitlen > atttypmod)
|
||||
ereport(ERROR,
|
||||
@@ -874,8 +876,8 @@ bitsubstr(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* OK, we've got a true substring starting at position s1-1 and
|
||||
* ending at position e1-1
|
||||
* OK, we've got a true substring starting at position s1-1 and ending
|
||||
* at position e1-1
|
||||
*/
|
||||
rbitlen = e1 - s1;
|
||||
len = VARBITTOTALLEN(rbitlen);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.112 2005/07/29 12:59:15 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.113 2005/10/15 02:49:30 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -81,7 +81,7 @@ bpchar_input(const char *s, size_t len, int32 atttypmod)
|
||||
maxlen = len;
|
||||
else
|
||||
{
|
||||
size_t charlen; /* number of CHARACTERS in the input */
|
||||
size_t charlen; /* number of CHARACTERS in the input */
|
||||
|
||||
maxlen = atttypmod - VARHDRSZ;
|
||||
charlen = pg_mbstrlen_with_len(s, len);
|
||||
@@ -106,16 +106,16 @@ bpchar_input(const char *s, size_t len, int32 atttypmod)
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we set maxlen to the necessary byte length, not
|
||||
* the number of CHARACTERS!
|
||||
* Now we set maxlen to the necessary byte length, not the number
|
||||
* of CHARACTERS!
|
||||
*/
|
||||
maxlen = len = mbmaxlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Now we set maxlen to the necessary byte length, not
|
||||
* the number of CHARACTERS!
|
||||
* Now we set maxlen to the necessary byte length, not the number
|
||||
* of CHARACTERS!
|
||||
*/
|
||||
maxlen = len + (maxlen - charlen);
|
||||
}
|
||||
@@ -141,6 +141,7 @@ Datum
|
||||
bpcharin(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *s = PG_GETARG_CSTRING(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
@@ -178,6 +179,7 @@ Datum
|
||||
bpcharrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
@@ -226,8 +228,8 @@ bpchar(PG_FUNCTION_ARGS)
|
||||
char *r;
|
||||
char *s;
|
||||
int i;
|
||||
int charlen; /* number of characters in the input string
|
||||
* + VARHDRSZ */
|
||||
int charlen; /* number of characters in the input string +
|
||||
* VARHDRSZ */
|
||||
|
||||
/* No work if typmod is invalid */
|
||||
if (maxlen < (int32) VARHDRSZ)
|
||||
@@ -254,24 +256,24 @@ bpchar(PG_FUNCTION_ARGS)
|
||||
for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
|
||||
if (*(VARDATA(source) + i) != ' ')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
||||
errmsg("value too long for type character(%d)",
|
||||
maxlen - VARHDRSZ)));
|
||||
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
||||
errmsg("value too long for type character(%d)",
|
||||
maxlen - VARHDRSZ)));
|
||||
}
|
||||
|
||||
len = maxmblen;
|
||||
|
||||
/*
|
||||
* XXX: at this point, maxlen is the necessary byte
|
||||
* length+VARHDRSZ, not the number of CHARACTERS!
|
||||
* XXX: at this point, maxlen is the necessary byte length+VARHDRSZ,
|
||||
* not the number of CHARACTERS!
|
||||
*/
|
||||
maxlen = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* XXX: at this point, maxlen is the necessary byte
|
||||
* length+VARHDRSZ, not the number of CHARACTERS!
|
||||
* XXX: at this point, maxlen is the necessary byte length+VARHDRSZ,
|
||||
* not the number of CHARACTERS!
|
||||
*/
|
||||
maxlen = len + (maxlen - charlen);
|
||||
}
|
||||
@@ -407,8 +409,8 @@ varchar_input(const char *s, size_t len, int32 atttypmod)
|
||||
if (s[j] != ' ')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
||||
errmsg("value too long for type character varying(%d)",
|
||||
(int) maxlen)));
|
||||
errmsg("value too long for type character varying(%d)",
|
||||
(int) maxlen)));
|
||||
}
|
||||
|
||||
len = mbmaxlen;
|
||||
@@ -429,6 +431,7 @@ Datum
|
||||
varcharin(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *s = PG_GETARG_CSTRING(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
@@ -466,11 +469,12 @@ Datum
|
||||
varcharrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 atttypmod = PG_GETARG_INT32(2);
|
||||
VarChar *result;
|
||||
VarChar *result;
|
||||
char *str;
|
||||
int nbytes;
|
||||
|
||||
@@ -531,8 +535,8 @@ varchar(PG_FUNCTION_ARGS)
|
||||
if (*(VARDATA(source) + i) != ' ')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
||||
errmsg("value too long for type character varying(%d)",
|
||||
maxlen - VARHDRSZ)));
|
||||
errmsg("value too long for type character varying(%d)",
|
||||
maxlen - VARHDRSZ)));
|
||||
}
|
||||
|
||||
len = maxmblen + VARHDRSZ;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.135 2005/09/24 17:53:16 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.136 2005/10/15 02:49:30 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -147,8 +147,7 @@ byteain(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We should never get here. The first pass should not allow
|
||||
* it.
|
||||
* We should never get here. The first pass should not allow it.
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
@@ -550,8 +549,8 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
|
||||
{
|
||||
S1 = Max(S, 1);
|
||||
|
||||
if (length_not_specified) /* special case - get length to
|
||||
* end of string */
|
||||
if (length_not_specified) /* special case - get length to end of
|
||||
* string */
|
||||
L1 = -1;
|
||||
else
|
||||
{
|
||||
@@ -559,18 +558,18 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
|
||||
int E = S + length;
|
||||
|
||||
/*
|
||||
* A negative value for L is the only way for the end position
|
||||
* to be before the start. SQL99 says to throw an error.
|
||||
* A negative value for L is the only way for the end position to
|
||||
* be before the start. SQL99 says to throw an error.
|
||||
*/
|
||||
if (E < S)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SUBSTRING_ERROR),
|
||||
errmsg("negative substring length not allowed")));
|
||||
errmsg("negative substring length not allowed")));
|
||||
|
||||
/*
|
||||
* A zero or negative value for the end position can happen if
|
||||
* the start was negative or one. SQL99 says to return a
|
||||
* zero-length string.
|
||||
* A zero or negative value for the end position can happen if the
|
||||
* start was negative or one. SQL99 says to return a zero-length
|
||||
* string.
|
||||
*/
|
||||
if (E < 1)
|
||||
return PG_STR_GET_TEXT("");
|
||||
@@ -579,9 +578,9 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
|
||||
}
|
||||
|
||||
/*
|
||||
* If the start position is past the end of the string, SQL99 says
|
||||
* to return a zero-length string -- PG_GETARG_TEXT_P_SLICE() will
|
||||
* do that for us. Convert to zero-based starting position
|
||||
* If the start position is past the end of the string, SQL99 says to
|
||||
* return a zero-length string -- PG_GETARG_TEXT_P_SLICE() will do
|
||||
* that for us. Convert to zero-based starting position
|
||||
*/
|
||||
return DatumGetTextPSlice(str, S1 - 1, L1);
|
||||
}
|
||||
@@ -589,8 +588,8 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
|
||||
{
|
||||
/*
|
||||
* When encoding max length is > 1, we can't get LC without
|
||||
* detoasting, so we'll grab a conservatively large slice now and
|
||||
* go back later to do the right thing
|
||||
* detoasting, so we'll grab a conservatively large slice now and go
|
||||
* back later to do the right thing
|
||||
*/
|
||||
int32 slice_start;
|
||||
int32 slice_size;
|
||||
@@ -603,38 +602,38 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
|
||||
text *ret;
|
||||
|
||||
/*
|
||||
* if S is past the end of the string, the tuple toaster will
|
||||
* return a zero-length string to us
|
||||
* if S is past the end of the string, the tuple toaster will return a
|
||||
* zero-length string to us
|
||||
*/
|
||||
S1 = Max(S, 1);
|
||||
|
||||
/*
|
||||
* We need to start at position zero because there is no way to
|
||||
* know in advance which byte offset corresponds to the supplied
|
||||
* start position.
|
||||
* We need to start at position zero because there is no way to know
|
||||
* in advance which byte offset corresponds to the supplied start
|
||||
* position.
|
||||
*/
|
||||
slice_start = 0;
|
||||
|
||||
if (length_not_specified) /* special case - get length to
|
||||
* end of string */
|
||||
if (length_not_specified) /* special case - get length to end of
|
||||
* string */
|
||||
slice_size = L1 = -1;
|
||||
else
|
||||
{
|
||||
int E = S + length;
|
||||
|
||||
/*
|
||||
* A negative value for L is the only way for the end position
|
||||
* to be before the start. SQL99 says to throw an error.
|
||||
* A negative value for L is the only way for the end position to
|
||||
* be before the start. SQL99 says to throw an error.
|
||||
*/
|
||||
if (E < S)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SUBSTRING_ERROR),
|
||||
errmsg("negative substring length not allowed")));
|
||||
errmsg("negative substring length not allowed")));
|
||||
|
||||
/*
|
||||
* A zero or negative value for the end position can happen if
|
||||
* the start was negative or one. SQL99 says to return a
|
||||
* zero-length string.
|
||||
* A zero or negative value for the end position can happen if the
|
||||
* start was negative or one. SQL99 says to return a zero-length
|
||||
* string.
|
||||
*/
|
||||
if (E < 1)
|
||||
return PG_STR_GET_TEXT("");
|
||||
@@ -646,9 +645,8 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
|
||||
L1 = E - S1;
|
||||
|
||||
/*
|
||||
* Total slice size in bytes can't be any longer than the
|
||||
* start position plus substring length times the encoding max
|
||||
* length.
|
||||
* Total slice size in bytes can't be any longer than the start
|
||||
* position plus substring length times the encoding max length.
|
||||
*/
|
||||
slice_size = (S1 + L1) * eml;
|
||||
}
|
||||
@@ -662,16 +660,15 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
|
||||
slice_strlen = pg_mbstrlen_with_len(VARDATA(slice), VARSIZE(slice) - VARHDRSZ);
|
||||
|
||||
/*
|
||||
* Check that the start position wasn't > slice_strlen. If so,
|
||||
* SQL99 says to return a zero-length string.
|
||||
* Check that the start position wasn't > slice_strlen. If so, SQL99
|
||||
* says to return a zero-length string.
|
||||
*/
|
||||
if (S1 > slice_strlen)
|
||||
return PG_STR_GET_TEXT("");
|
||||
|
||||
/*
|
||||
* Adjust L1 and E1 now that we know the slice string length.
|
||||
* Again remember that S1 is one based, and slice_start is zero
|
||||
* based.
|
||||
* Adjust L1 and E1 now that we know the slice string length. Again
|
||||
* remember that S1 is one based, and slice_start is zero based.
|
||||
*/
|
||||
if (L1 > -1)
|
||||
E1 = Min(S1 + L1, slice_start + 1 + slice_strlen);
|
||||
@@ -679,8 +676,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
|
||||
E1 = slice_start + 1 + slice_strlen;
|
||||
|
||||
/*
|
||||
* Find the start position in the slice; remember S1 is not zero
|
||||
* based
|
||||
* Find the start position in the slice; remember S1 is not zero based
|
||||
*/
|
||||
p = VARDATA(slice);
|
||||
for (i = 0; i < S1 - 1; i++)
|
||||
@@ -834,11 +830,10 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
|
||||
int result;
|
||||
|
||||
/*
|
||||
* Unfortunately, there is no strncoll(), so in the non-C locale case
|
||||
* we have to do some memory copying. This turns out to be
|
||||
* significantly slower, so we optimize the case where LC_COLLATE is
|
||||
* C. We also try to optimize relatively-short strings by avoiding
|
||||
* palloc/pfree overhead.
|
||||
* Unfortunately, there is no strncoll(), so in the non-C locale case we
|
||||
* have to do some memory copying. This turns out to be significantly
|
||||
* slower, so we optimize the case where LC_COLLATE is C. We also try to
|
||||
* optimize relatively-short strings by avoiding palloc/pfree overhead.
|
||||
*/
|
||||
if (lc_collate_is_c())
|
||||
{
|
||||
@@ -859,11 +854,11 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
|
||||
/* Win32 does not have UTF-8, so we need to map to UTF-16 */
|
||||
if (GetDatabaseEncoding() == PG_UTF8)
|
||||
{
|
||||
int a1len;
|
||||
int a2len;
|
||||
int r;
|
||||
int a1len;
|
||||
int a2len;
|
||||
int r;
|
||||
|
||||
if (len1 >= STACKBUFLEN/2)
|
||||
if (len1 >= STACKBUFLEN / 2)
|
||||
{
|
||||
a1len = len1 * 2 + 2;
|
||||
a1p = palloc(a1len);
|
||||
@@ -873,7 +868,7 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
|
||||
a1len = STACKBUFLEN;
|
||||
a1p = a1buf;
|
||||
}
|
||||
if (len2 >= STACKBUFLEN/2)
|
||||
if (len2 >= STACKBUFLEN / 2)
|
||||
{
|
||||
a2len = len2 * 2 + 2;
|
||||
a2p = palloc(a2len);
|
||||
@@ -890,7 +885,7 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
|
||||
else
|
||||
{
|
||||
r = MultiByteToWideChar(CP_UTF8, 0, arg1, len1,
|
||||
(LPWSTR) a1p, a1len/2);
|
||||
(LPWSTR) a1p, a1len / 2);
|
||||
if (!r)
|
||||
ereport(ERROR,
|
||||
(errmsg("could not convert string to UTF16: %lu",
|
||||
@@ -903,7 +898,7 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
|
||||
else
|
||||
{
|
||||
r = MultiByteToWideChar(CP_UTF8, 0, arg2, len2,
|
||||
(LPWSTR) a2p, a2len/2);
|
||||
(LPWSTR) a2p, a2len / 2);
|
||||
if (!r)
|
||||
ereport(ERROR,
|
||||
(errmsg("could not convert string to UTF16: %lu",
|
||||
@@ -913,7 +908,8 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
|
||||
|
||||
errno = 0;
|
||||
result = wcscoll((LPWSTR) a1p, (LPWSTR) a2p);
|
||||
if (result == 2147483647) /* _NLSCMPERROR; missing from mingw headers */
|
||||
if (result == 2147483647) /* _NLSCMPERROR; missing from mingw
|
||||
* headers */
|
||||
ereport(ERROR,
|
||||
(errmsg("could not compare unicode strings: %d",
|
||||
errno)));
|
||||
@@ -925,7 +921,7 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
#endif /* WIN32 */
|
||||
|
||||
if (len1 >= STACKBUFLEN)
|
||||
a1p = (char *) palloc(len1 + 1);
|
||||
@@ -1349,9 +1345,8 @@ bytea_substr(PG_FUNCTION_ARGS)
|
||||
if (fcinfo->nargs == 2)
|
||||
{
|
||||
/*
|
||||
* Not passed a length - PG_GETARG_BYTEA_P_SLICE() grabs
|
||||
* everything to the end of the string if we pass it a negative
|
||||
* value for length.
|
||||
* Not passed a length - PG_GETARG_BYTEA_P_SLICE() grabs everything to
|
||||
* the end of the string if we pass it a negative value for length.
|
||||
*/
|
||||
L1 = -1;
|
||||
}
|
||||
@@ -1361,8 +1356,8 @@ bytea_substr(PG_FUNCTION_ARGS)
|
||||
int E = S + PG_GETARG_INT32(2);
|
||||
|
||||
/*
|
||||
* A negative value for L is the only way for the end position to
|
||||
* be before the start. SQL99 says to throw an error.
|
||||
* A negative value for L is the only way for the end position to be
|
||||
* before the start. SQL99 says to throw an error.
|
||||
*/
|
||||
if (E < S)
|
||||
ereport(ERROR,
|
||||
@@ -1382,8 +1377,8 @@ bytea_substr(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* If the start position is past the end of the string, SQL99 says to
|
||||
* return a zero-length string -- PG_GETARG_TEXT_P_SLICE() will do
|
||||
* that for us. Convert to zero-based starting position
|
||||
* return a zero-length string -- PG_GETARG_TEXT_P_SLICE() will do that
|
||||
* for us. Convert to zero-based starting position
|
||||
*/
|
||||
PG_RETURN_BYTEA_P(PG_GETARG_BYTEA_P_SLICE(0, S1 - 1, L1));
|
||||
}
|
||||
@@ -1686,7 +1681,7 @@ textToQualifiedNameList(text *textval)
|
||||
/* Convert to C string (handles possible detoasting). */
|
||||
/* Note we rely on being able to modify rawname below. */
|
||||
rawname = DatumGetCString(DirectFunctionCall1(textout,
|
||||
PointerGetDatum(textval)));
|
||||
PointerGetDatum(textval)));
|
||||
|
||||
if (!SplitIdentifierString(rawname, '.', &namelist))
|
||||
ereport(ERROR,
|
||||
@@ -1788,14 +1783,13 @@ SplitIdentifierString(char *rawstring, char separator,
|
||||
return false; /* empty unquoted name not allowed */
|
||||
|
||||
/*
|
||||
* Downcase the identifier, using same code as main lexer
|
||||
* does.
|
||||
* Downcase the identifier, using same code as main lexer does.
|
||||
*
|
||||
* XXX because we want to overwrite the input in-place, we cannot
|
||||
* support a downcasing transformation that increases the
|
||||
* string length. This is not a problem given the current
|
||||
* implementation of downcase_truncate_identifier, but we'll
|
||||
* probably have to do something about this someday.
|
||||
* support a downcasing transformation that increases the string
|
||||
* length. This is not a problem given the current implementation
|
||||
* of downcase_truncate_identifier, but we'll probably have to do
|
||||
* something about this someday.
|
||||
*/
|
||||
len = endp - curname;
|
||||
downname = downcase_truncate_identifier(curname, len, false);
|
||||
@@ -2083,12 +2077,14 @@ check_replace_text_has_escape_char(const text *replace_text)
|
||||
if (pg_database_encoding_max_length() == 1)
|
||||
{
|
||||
for (; p < p_end; p++)
|
||||
if (*p == '\\') return true;
|
||||
if (*p == '\\')
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; p < p_end; p += pg_mblen(p))
|
||||
if (*p == '\\') return true;
|
||||
if (*p == '\\')
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -2100,7 +2096,7 @@ check_replace_text_has_escape_char(const text *replace_text)
|
||||
*/
|
||||
static void
|
||||
appendStringInfoRegexpSubstr(StringInfo str, text *replace_text,
|
||||
regmatch_t *pmatch, text *src_text)
|
||||
regmatch_t *pmatch, text *src_text)
|
||||
{
|
||||
const char *p = VARDATA(replace_text);
|
||||
const char *p_end = p + (VARSIZE(replace_text) - VARHDRSZ);
|
||||
@@ -2129,19 +2125,20 @@ appendStringInfoRegexpSubstr(StringInfo str, text *replace_text,
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the text when there is a text in the left of escape char
|
||||
* or escape char is not found.
|
||||
* Copy the text when there is a text in the left of escape char or
|
||||
* escape char is not found.
|
||||
*/
|
||||
if (ch_cnt)
|
||||
{
|
||||
text *append_text = text_substring(PointerGetDatum(replace_text),
|
||||
substr_start, ch_cnt, false);
|
||||
text *append_text = text_substring(PointerGetDatum(replace_text),
|
||||
substr_start, ch_cnt, false);
|
||||
|
||||
appendStringInfoText(str, append_text);
|
||||
pfree(append_text);
|
||||
}
|
||||
substr_start += ch_cnt + 1;
|
||||
|
||||
if (p >= p_end) /* When escape char is not found. */
|
||||
if (p >= p_end) /* When escape char is not found. */
|
||||
break;
|
||||
|
||||
/* See the next character of escape char. */
|
||||
@@ -2151,7 +2148,8 @@ appendStringInfoRegexpSubstr(StringInfo str, text *replace_text,
|
||||
if (*p >= '1' && *p <= '9')
|
||||
{
|
||||
/* Use the back reference of regexp. */
|
||||
int idx = *p - '0';
|
||||
int idx = *p - '0';
|
||||
|
||||
so = pmatch[idx].rm_so;
|
||||
eo = pmatch[idx].rm_eo;
|
||||
p++;
|
||||
@@ -2169,8 +2167,9 @@ appendStringInfoRegexpSubstr(StringInfo str, text *replace_text,
|
||||
if (so != -1 && eo != -1)
|
||||
{
|
||||
/* Copy the text that is back reference of regexp. */
|
||||
text *append_text = text_substring(PointerGetDatum(src_text),
|
||||
so + 1, (eo - so), false);
|
||||
text *append_text = text_substring(PointerGetDatum(src_text),
|
||||
so + 1, (eo - so), false);
|
||||
|
||||
appendStringInfoText(str, append_text);
|
||||
pfree(append_text);
|
||||
}
|
||||
@@ -2189,9 +2188,9 @@ replace_text_regexp(PG_FUNCTION_ARGS)
|
||||
text *ret_text;
|
||||
text *src_text = PG_GETARG_TEXT_P(0);
|
||||
int src_text_len = VARSIZE(src_text) - VARHDRSZ;
|
||||
regex_t *re = (regex_t *)PG_GETARG_POINTER(1);
|
||||
regex_t *re = (regex_t *) PG_GETARG_POINTER(1);
|
||||
text *replace_text = PG_GETARG_TEXT_P(2);
|
||||
bool global = PG_GETARG_BOOL(3);
|
||||
bool global = PG_GETARG_BOOL(3);
|
||||
StringInfo str = makeStringInfo();
|
||||
int regexec_result;
|
||||
regmatch_t pmatch[REGEXP_REPLACE_BACKREF_CNT];
|
||||
@@ -2214,33 +2213,34 @@ replace_text_regexp(PG_FUNCTION_ARGS)
|
||||
data,
|
||||
data_len,
|
||||
search_start,
|
||||
NULL, /* no details */
|
||||
NULL, /* no details */
|
||||
REGEXP_REPLACE_BACKREF_CNT,
|
||||
pmatch,
|
||||
0);
|
||||
|
||||
if (regexec_result != REG_OKAY && regexec_result != REG_NOMATCH)
|
||||
{
|
||||
char errMsg[100];
|
||||
char errMsg[100];
|
||||
|
||||
/* re failed??? */
|
||||
pg_regerror(regexec_result, re, errMsg, sizeof(errMsg));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
|
||||
errmsg("regular expression failed: %s", errMsg)));
|
||||
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
|
||||
errmsg("regular expression failed: %s", errMsg)));
|
||||
}
|
||||
|
||||
if (regexec_result == REG_NOMATCH)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Copy the text when there is a text in the left of matched position.
|
||||
*/
|
||||
/*
|
||||
* Copy the text when there is a text in the left of matched position.
|
||||
*/
|
||||
if (pmatch[0].rm_so - data_pos > 0)
|
||||
{
|
||||
text *left_text = text_substring(PointerGetDatum(src_text),
|
||||
data_pos + 1,
|
||||
pmatch[0].rm_so - data_pos, false);
|
||||
text *left_text = text_substring(PointerGetDatum(src_text),
|
||||
data_pos + 1,
|
||||
pmatch[0].rm_so - data_pos, false);
|
||||
|
||||
appendStringInfoText(str, left_text);
|
||||
pfree(left_text);
|
||||
}
|
||||
@@ -2270,13 +2270,14 @@ replace_text_regexp(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the text when there is a text at the right of last matched
|
||||
* or regexp is not matched.
|
||||
* Copy the text when there is a text at the right of last matched or
|
||||
* regexp is not matched.
|
||||
*/
|
||||
if (data_pos < data_len)
|
||||
{
|
||||
text *right_text = text_substring(PointerGetDatum(src_text),
|
||||
data_pos + 1, -1, true);
|
||||
text *right_text = text_substring(PointerGetDatum(src_text),
|
||||
data_pos + 1, -1, true);
|
||||
|
||||
appendStringInfoText(str, right_text);
|
||||
pfree(right_text);
|
||||
}
|
||||
@@ -2392,7 +2393,7 @@ text_to_array(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
if (fldsep_len < 1)
|
||||
PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
|
||||
CStringGetDatum(inputstring), 1));
|
||||
CStringGetDatum(inputstring), 1));
|
||||
|
||||
/* start with end position holding the initial start position */
|
||||
end_posn = 0;
|
||||
@@ -2409,17 +2410,17 @@ text_to_array(PG_FUNCTION_ARGS)
|
||||
if (fldnum == 1)
|
||||
{
|
||||
/*
|
||||
* first element return one element, 1D, array using the
|
||||
* input string
|
||||
* first element return one element, 1D, array using the input
|
||||
* string
|
||||
*/
|
||||
PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
|
||||
CStringGetDatum(inputstring), 1));
|
||||
CStringGetDatum(inputstring), 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise create array and exit */
|
||||
PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate,
|
||||
CurrentMemoryContext));
|
||||
CurrentMemoryContext));
|
||||
}
|
||||
}
|
||||
else if (start_posn == 0)
|
||||
@@ -2439,7 +2440,7 @@ text_to_array(PG_FUNCTION_ARGS)
|
||||
/* interior field requested */
|
||||
result_text = text_substring(PointerGetDatum(inputstring),
|
||||
start_posn + fldsep_len,
|
||||
end_posn - start_posn - fldsep_len,
|
||||
end_posn - start_posn - fldsep_len,
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -2489,14 +2490,14 @@ array_to_text(PG_FUNCTION_ARGS)
|
||||
|
||||
/*
|
||||
* We arrange to look up info about element type, including its output
|
||||
* conversion proc, only once per series of calls, assuming the
|
||||
* element type doesn't change underneath us.
|
||||
* conversion proc, only once per series of calls, assuming the element
|
||||
* type doesn't change underneath us.
|
||||
*/
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
if (my_extra == NULL)
|
||||
{
|
||||
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
||||
sizeof(ArrayMetaState));
|
||||
sizeof(ArrayMetaState));
|
||||
my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
|
||||
my_extra->element_type = InvalidOid;
|
||||
}
|
||||
@@ -2504,8 +2505,7 @@ array_to_text(PG_FUNCTION_ARGS)
|
||||
if (my_extra->element_type != element_type)
|
||||
{
|
||||
/*
|
||||
* Get info about element type, including its output conversion
|
||||
* proc
|
||||
* Get info about element type, including its output conversion proc
|
||||
*/
|
||||
get_type_io_data(element_type, IOFunc_output,
|
||||
&my_extra->typlen, &my_extra->typbyval,
|
||||
@@ -2606,7 +2606,7 @@ md5_text(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *in_text = PG_GETARG_TEXT_P(0);
|
||||
size_t len;
|
||||
char hexsum[MD5_HASH_LEN + 1];
|
||||
char hexsum[MD5_HASH_LEN + 1];
|
||||
text *result_text;
|
||||
|
||||
/* Calculate the length of the buffer using varlena metadata */
|
||||
@@ -2661,7 +2661,7 @@ pg_column_size(PG_FUNCTION_ARGS)
|
||||
if (fcinfo->flinfo->fn_extra == NULL)
|
||||
{
|
||||
/* Lookup the datatype of the supplied argument */
|
||||
Oid argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
|
||||
Oid argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
|
||||
|
||||
typlen = get_typlen(argtypeid);
|
||||
if (typlen == 0) /* should not happen */
|
||||
|
||||
Reference in New Issue
Block a user