Commit f45df8c0 authored by Tom Lane's avatar Tom Lane

Cause CHAR(n) to TEXT or VARCHAR conversion to automatically strip trailing

blanks, in hopes of reducing the surprise factor for newbies.  Remove
redundant operators for VARCHAR (it depends wholly on TEXT operations now).
Clean up resolution of ambiguous operators/functions to avoid surprising
choices for domains: domains are treated as equivalent to their base types
and binary-coercibility is no longer considered a preference item when
choosing among multiple operators/functions.  IsBinaryCoercible now correctly
reflects the notion that you need *only* relabel the type to get from type
A to type B: that is, a domain is binary-coercible to its base type, but
not vice versa.  Various marginal cleanup, including merging the essentially
duplicate resolution code in parse_func.c and parse_oper.c.  Improve opr_sanity
regression test to understand about binary compatibility (using pg_cast),
and fix a couple of small errors in the catalogs revealed thereby.
Restructure "special operator" handling to fetch operators via index opclasses
rather than hardwiring assumptions about names (cleans up the pattern_ops
stuff a little).
parent 297c1658
......@@ -145,43 +145,6 @@ array_all_textregexeq(ArrayType *array, void *value)
array, (Datum) value);
}
/*
* Iterator functions for type _varchar. Note that the regexp
* operators take the second argument of type text.
*/
int32
array_varchareq(ArrayType *array, void *value)
{
return array_iterator(F_VARCHAREQ,
0, /* logical or */
array, (Datum) value);
}
int32
array_all_varchareq(ArrayType *array, void *value)
{
return array_iterator(F_VARCHAREQ,
1, /* logical and */
array, (Datum) value);
}
int32
array_varcharregexeq(ArrayType *array, void *value)
{
return array_iterator(F_TEXTREGEXEQ,
0, /* logical or */
array, (Datum) value);
}
int32
array_all_varcharregexeq(ArrayType *array, void *value)
{
return array_iterator(F_TEXTREGEXEQ,
1, /* logical and */
array, (Datum) value);
}
/*
* Iterator functions for type _bpchar. Note that the regexp
* operators take the second argument of type text.
......
......@@ -9,11 +9,6 @@ int32 array_all_texteq(ArrayType *array, void *value);
int32 array_textregexeq(ArrayType *array, void *value);
int32 array_all_textregexeq(ArrayType *array, void *value);
int32 array_varchareq(ArrayType *array, void *value);
int32 array_all_varchareq(ArrayType *array, void *value);
int32 array_varcharregexeq(ArrayType *array, void *value);
int32 array_all_varcharregexeq(ArrayType *array, void *value);
int32 array_bpchareq(ArrayType *array, void *value);
int32 array_all_bpchareq(ArrayType *array, void *value);
int32 array_bpcharregexeq(ArrayType *array, void *value);
......
......@@ -55,59 +55,6 @@ CREATE OPERATOR **~ (
);
-- define the array operators *=, **=, *~ and **~ for type _varchar
--
-- NOTE: "varchar" is also a reserved word and must be quoted.
--
CREATE OR REPLACE FUNCTION array_varchareq(_varchar, varchar)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION array_all_varchareq(_varchar, varchar)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION array_varcharregexeq(_varchar, varchar)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION array_all_varcharregexeq(_varchar, varchar)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
DROP OPERATOR *=(_varchar,"varchar");
CREATE OPERATOR *= (
LEFTARG=_varchar,
RIGHTARG="varchar",
PROCEDURE=array_varchareq
);
DROP OPERATOR **=(_varchar,"varchar");
CREATE OPERATOR **= (
LEFTARG=_varchar,
RIGHTARG="varchar",
PROCEDURE=array_all_varchareq
);
DROP OPERATOR *~(_varchar,"varchar");
CREATE OPERATOR *~ (
LEFTARG=_varchar,
RIGHTARG="varchar",
PROCEDURE=array_varcharregexeq
);
DROP OPERATOR **~(_varchar,"varchar");
CREATE OPERATOR **~ (
LEFTARG=_varchar,
RIGHTARG="varchar",
PROCEDURE=array_all_varcharregexeq
);
-- define the array operators *=, **=, *~ and **~ for type _bpchar
--
CREATE OR REPLACE FUNCTION array_bpchareq(_bpchar, bpchar)
......
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.189 2003/05/22 18:31:45 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.190 2003/05/26 00:11:27 tgl Exp $
-->
<appendix id="release">
......@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
worries about funny characters.
-->
<literallayout><![CDATA[
CHAR(n) to TEXT conversion automatically strips trailing blanks
Pattern matching operations can use indexes regardless of locale
New frontend/backend protocol supports many long-requested features
SET AUTOCOMMIT TO OFF is no longer supported
......
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/typeconv.sgml,v 1.30 2003/03/25 16:15:38 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/typeconv.sgml,v 1.31 2003/05/26 00:11:27 tgl Exp $
-->
<chapter Id="typeconv">
......@@ -45,7 +45,7 @@ mixed-type expressions to be meaningful even with user-defined types.
<para>
The <productname>PostgreSQL</productname> scanner/parser decodes lexical
elements into only five fundamental categories: integers, floating-point numbers, strings,
names, and key words. Most extended types are first classified as
names, and key words. Constants of most non-numeric types are first classified as
strings. The <acronym>SQL</acronym> language definition allows specifying type
names with strings, and this mechanism can be used in
<productname>PostgreSQL</productname> to start the parser down the correct
......@@ -134,8 +134,8 @@ The system catalogs store information about which conversions, called
perform those conversions. Additional casts can be added by the user
with the <command>CREATE CAST</command> command. (This is usually
done in conjunction with defining new data types. The set of casts
between the built-in types has been carefully crafted and should not
be altered.)
between the built-in types has been carefully crafted and is best not
altered.)
</para>
<para>
......@@ -144,8 +144,8 @@ at proper behavior for <acronym>SQL</acronym> standard types. There are
several basic <firstterm>type categories</firstterm> defined: <type>boolean</type>,
<type>numeric</type>, <type>string</type>, <type>bitstring</type>, <type>datetime</type>, <type>timespan</type>, <type>geometric</type>, <type>network</type>,
and user-defined. Each category, with the exception of user-defined, has
a <firstterm>preferred type</firstterm> which is preferentially selected
when there is ambiguity.
one or more <firstterm>preferred types</firstterm> which are preferentially
selected when there is ambiguity.
In the user-defined category, each type is its own preferred type.
Ambiguous expressions (those with multiple candidate parsing solutions)
can therefore often be resolved when there are multiple possible built-in types, but
......@@ -175,7 +175,8 @@ be converted to a user-defined type (of course, only if conversion is necessary)
<para>
User-defined types are not related. Currently, <productname>PostgreSQL</productname>
does not have information available to it on relationships between types, other than
hardcoded heuristics for built-in types and implicit relationships based on available functions.
hardcoded heuristics for built-in types and implicit relationships based on
available functions and casts.
</para>
</listitem>
......@@ -203,14 +204,15 @@ should use this new function and will no longer do the implicit conversion using
<title>Operators</title>
<para>
The operand types of an operator invocation are resolved following
The specific operator to be used in an operator invocation is determined
by following
the procedure below. Note that this procedure is indirectly affected
by the precedence of the involved operators. See <xref
linkend="sql-precedence"> for more information.
</para>
<procedure>
<title>Operand Type Resolution</title>
<title>Operator Type Resolution</title>
<step performance="required">
<para>
......@@ -271,22 +273,16 @@ candidate remains, use it; else continue to the next step.
<step performance="required">
<para>
Run through all candidates and keep those with the most exact matches
on input types. Keep all candidates if none have any exact matches.
on input types. (Domain types are considered the same as their base type
for this purpose.) Keep all candidates if none have any exact matches.
If only one candidate remains, use it; else continue to the next step.
</para>
</step>
<step performance="required">
<para>
Run through all candidates and keep those with the most exact or
binary-compatible matches on input types. Keep all candidates if none have
any exact or binary-compatible matches.
If only one candidate remains, use it; else continue to the next step.
</para>
</step>
<step performance="required">
<para>
Run through all candidates and keep those that accept preferred types at
the most positions where type conversion will be required.
Run through all candidates and keep those that accept preferred types (of the
input datatype's type category) at the most positions where type conversion
will be required.
Keep all candidates if none accept preferred types.
If only one candidate remains, use it; else continue to the next step.
</para>
......@@ -295,12 +291,13 @@ If only one candidate remains, use it; else continue to the next step.
<para>
If any input arguments are <type>unknown</type>, check the type
categories accepted at those argument positions by the remaining
candidates. At each position, select the <literal>string</literal> category if any
candidates. At each position, select the <type>string</type> category
if any
candidate accepts that category. (This bias towards string is appropriate
since an unknown-type literal does look like a string.) Otherwise, if
all the remaining candidates accept the same type category, select that
category; otherwise fail because the correct choice cannot be deduced
without more clues. Now discard operator
without more clues. Now discard
candidates that do not accept the selected type category. Furthermore,
if any candidate accepts a preferred type at a given argument position,
discard candidates that accept non-preferred types for that argument.
......@@ -455,12 +452,12 @@ SELECT CAST('20' AS int8) ! AS "factorial";
<title>Functions</title>
<para>
The argument types of function calls are resolved according to the
following steps.
The specific function to be used in a function invocation is determined
according to the following steps.
</para>
<procedure>
<title>Function Argument Type Resolution</title>
<title>Function Type Resolution</title>
<step performance="required">
<para>
......@@ -523,29 +520,24 @@ candidate remains, use it; else continue to the next step.
<step performance="required">
<para>
Run through all candidates and keep those with the most exact matches
on input types. Keep all candidates if none have any exact matches.
If only one candidate remains, use it; else continue to the next step.
</para>
</step>
<step performance="required">
<para>
Run through all candidates and keep those with the most exact or
binary-compatible matches on input types. Keep all candidates if none have
any exact or binary-compatible matches.
on input types. (Domain types are considered the same as their base type
for this purpose.) Keep all candidates if none have any exact matches.
If only one candidate remains, use it; else continue to the next step.
</para>
</step>
<step performance="required">
<para>
Run through all candidates and keep those that accept preferred types at
the most positions where type conversion will be required.
Run through all candidates and keep those that accept preferred types (of the
input datatype's type category) at the most positions where type conversion
will be required.
Keep all candidates if none accept preferred types.
If only one candidate remains, use it; else continue to the next step.
</para>
</step>
<step performance="required">
<para>
If any input arguments are <type>unknown</type>, check the type categories accepted
If any input arguments are <type>unknown</type>, check the type categories
accepted
at those argument positions by the remaining candidates. At each position,
select the <type>string</type> category if any candidate accepts that category.
(This bias towards string
......@@ -553,8 +545,8 @@ is appropriate since an unknown-type literal does look like a string.)
Otherwise, if all the remaining candidates accept the same type category,
select that category; otherwise fail because
the correct choice cannot be deduced without more clues.
Now discard candidates that do not accept the selected type category;
furthermore, if any candidate accepts a preferred type at a given argument
Now discard candidates that do not accept the selected type category.
Furthermore, if any candidate accepts a preferred type at a given argument
position, discard candidates that accept non-preferred types for that
argument.
</para>
......@@ -571,6 +563,8 @@ then fail.
</procedure>
<para>
Note that the <quote>best match</> rules are identical for operator and
function type resolution.
Some examples follow.
</para>
......@@ -649,7 +643,8 @@ SELECT substr(CAST (varchar '1234' AS text), 3);
<para>
<note>
<para>
The parser is aware that <type>text</type> and <type>varchar</type>
The parser learns from the <structname>pg_cast</> catalog that
<type>text</type> and <type>varchar</type>
are binary-compatible, meaning that one can be passed to a function that
accepts the other without doing any physical conversion. Therefore, no
explicit type conversion call is really inserted in this case.
......
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.88 2003/02/15 20:12:40 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.89 2003/05/26 00:11:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -328,7 +328,7 @@ create_seqscan_path(Query *root, RelOptInfo *rel)
*
* 'rel' is the parent rel
* 'index' is an index on 'rel'
* 'restriction_clauses' is a list of RestrictInfo nodes
* 'restriction_clauses' is a list of lists of RestrictInfo nodes
* to be used as index qual conditions in the scan.
* 'pathkeys' describes the ordering of the path.
* 'indexscandir' is ForwardScanDirection or BackwardScanDirection
......@@ -352,9 +352,8 @@ create_index_path(Query *root,
pathnode->path.parent = rel;
pathnode->path.pathkeys = pathkeys;
indexquals = get_actual_clauses(restriction_clauses);
/* expand special operators to indexquals the executor can handle */
indexquals = expand_indexqual_conditions(indexquals);
/* Convert RestrictInfo nodes to indexquals the executor can handle */
indexquals = expand_indexqual_conditions(index, restriction_clauses);
/*
* We are making a pathnode for a single-scan indexscan; therefore,
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.96 2003/04/29 22:13:10 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.97 2003/05/26 00:11:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -32,7 +32,6 @@
static Node *coerce_type_typmod(Node *node,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, bool isExplicit);
static Oid PreferredType(CATEGORY category, Oid type);
static Node *build_func_call(Oid funcid, Oid rettype, List *args,
CoercionForm fformat);
......@@ -66,28 +65,43 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
if (can_coerce_type(1, &exprtype, &targettype, ccontext))
expr = coerce_type(pstate, expr, exprtype, targettype,
ccontext, cformat);
/*
* String hacks to get transparent conversions for char and varchar:
* if a coercion to text is available, use it for forced coercions to
* char(n) or varchar(n).
*
* This is pretty grotty, but seems easier to maintain than providing
* entries in pg_cast that parallel all the ones for text.
*/
else if (ccontext >= COERCION_ASSIGNMENT &&
(targettype == BPCHAROID || targettype == VARCHAROID))
else if (ccontext >= COERCION_ASSIGNMENT)
{
Oid text_id = TEXTOID;
/*
* String hacks to get transparent conversions for char and varchar:
* if a coercion to text is available, use it for forced coercions to
* char(n) or varchar(n) or domains thereof.
*
* This is pretty grotty, but seems easier to maintain than providing
* entries in pg_cast that parallel all the ones for text.
*/
Oid targetbasetype = getBaseType(targettype);
if (can_coerce_type(1, &exprtype, &text_id, ccontext))
if (targetbasetype == BPCHAROID || targetbasetype == VARCHAROID)
{
expr = coerce_type(pstate, expr, exprtype, text_id,
ccontext, cformat);
/* Need a RelabelType if no typmod coercion is performed */
if (targettypmod < 0)
expr = (Node *) makeRelabelType((Expr *) expr,
targettype, -1,
cformat);
Oid text_id = TEXTOID;
if (can_coerce_type(1, &exprtype, &text_id, ccontext))
{
expr = coerce_type(pstate, expr, exprtype, text_id,
ccontext, cformat);
if (targetbasetype != targettype)
{
/* need to coerce to domain over char or varchar */
expr = coerce_to_domain(expr, targetbasetype, targettype,
cformat);
}
else
{
/* need a RelabelType if no typmod coercion will be performed */
if (targettypmod < 0)
expr = (Node *) makeRelabelType((Expr *) expr,
targettype, -1,
cformat);
}
}
else
expr = NULL;
}
else
expr = NULL;
......@@ -923,7 +937,10 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
/* TypeCategory()
* Assign a category to the specified OID.
* Assign a category to the specified type OID.
*
* NB: this must not return INVALID_TYPE.
*
* XXX This should be moved to system catalog lookups
* to allow for better type extensibility.
* - thomas 2001-09-30
......@@ -1026,7 +1043,11 @@ TypeCategory(Oid inType)
/* IsPreferredType()
* Check if this type is a preferred type.
* Check if this type is a preferred type for the given category.
*
* If category is INVALID_TYPE, then we'll return TRUE for preferred types
* of any category; otherwise, only for preferred types of that category.
*
* XXX This should be moved to system catalog lookups
* to allow for better type extensibility.
* - thomas 2001-09-30
......@@ -1034,39 +1055,34 @@ TypeCategory(Oid inType)
bool
IsPreferredType(CATEGORY category, Oid type)
{
return (type == PreferredType(category, type));
} /* IsPreferredType() */
Oid preftype;
if (category == INVALID_TYPE)
category = TypeCategory(type);
else if (category != TypeCategory(type))
return false;
/* PreferredType()
* Return the preferred type OID for the specified category.
* XXX This should be moved to system catalog lookups
* to allow for better type extensibility.
* - thomas 2001-09-30
*/
static Oid
PreferredType(CATEGORY category, Oid type)
{
Oid result;
/*
* This switch should agree with TypeCategory(), above. Note that
* at this point, category certainly matches the type.
*/
switch (category)
{
case (INVALID_TYPE):
case (UNKNOWN_TYPE):
case (GENERIC_TYPE):
result = UNKNOWNOID;
preftype = UNKNOWNOID;
break;
case (BOOLEAN_TYPE):
result = BOOLOID;
preftype = BOOLOID;
break;
case (STRING_TYPE):
result = TEXTOID;
preftype = TEXTOID;
break;
case (BITSTRING_TYPE):
result = VARBITOID;
preftype = VARBITOID;
break;
case (NUMERIC_TYPE):
......@@ -1077,52 +1093,59 @@ PreferredType(CATEGORY category, Oid type)
type == REGOPERATOROID ||
type == REGCLASSOID ||
type == REGTYPEOID)
result = OIDOID;
preftype = OIDOID;
else
result = FLOAT8OID;
preftype = FLOAT8OID;
break;
case (DATETIME_TYPE):
if (type == DATEOID)
result = TIMESTAMPOID;
preftype = TIMESTAMPOID;
else
result = TIMESTAMPTZOID;
preftype = TIMESTAMPTZOID;
break;
case (TIMESPAN_TYPE):
result = INTERVALOID;
preftype = INTERVALOID;
break;
case (GEOMETRIC_TYPE):
result = type;
preftype = type;
break;
case (NETWORK_TYPE):
result = INETOID;
preftype = INETOID;
break;
case (USER_TYPE):
result = type;
preftype = type;
break;
default:
elog(ERROR, "PreferredType: unknown category");
result = UNKNOWNOID;
elog(ERROR, "IsPreferredType: unknown category");
preftype = UNKNOWNOID;
break;
}
return result;
} /* PreferredType() */
return (type == preftype);
} /* IsPreferredType() */
/* IsBinaryCoercible()
* Check if srctype is binary-coercible to targettype.
*
* This notion allows us to cheat and directly exchange values without
* going through the trouble of calling a conversion function.
* going through the trouble of calling a conversion function. Note that
* in general, this should only be an implementation shortcut. Before 7.4,
* this was also used as a heuristic for resolving overloaded functions and
* operators, but that's basically a bad idea.
*
* As of 7.3, binary coercibility isn't hardwired into the code anymore.
* We consider two types binary-coercible if there is an implicitly
* invokable, no-function-needed pg_cast entry.
* invokable, no-function-needed pg_cast entry. Also, a domain is always
* binary-coercible to its base type, though *not* vice versa (in the other
* direction, one must apply domain constraint checks before accepting the
* value as legitimate).
*
* This function replaces IsBinaryCompatible(), which was an inherently
* symmetric test. Since the pg_cast entries aren't necessarily symmetric,
......@@ -1139,13 +1162,11 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
if (srctype == targettype)
return true;
/* Perhaps the types are domains; if so, look at their base types */
/* If srctype is a domain, reduce to its base type */
if (OidIsValid(srctype))
srctype = getBaseType(srctype);
if (OidIsValid(targettype))
targettype = getBaseType(targettype);
/* Somewhat-fast path if same base type */
/* Somewhat-fast path for domain -> base type case */
if (srctype == targettype)
return true;
......@@ -1174,8 +1195,13 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
* ccontext determines the set of available casts.
*
* If we find a suitable entry in pg_cast, return TRUE, and set *funcid
* to the castfunc value (which may be InvalidOid for a binary-compatible
* coercion).
* to the castfunc value, which may be InvalidOid for a binary-compatible
* coercion.
*
* NOTE: *funcid == InvalidOid does not necessarily mean that no work is
* needed to do the coercion; if the target is a domain then we may need to
* apply domain constraint checking. If you want to check for a zero-effort
* conversion then use IsBinaryCoercible().
*/
bool
find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
......@@ -1193,7 +1219,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
if (OidIsValid(targetTypeId))
targetTypeId = getBaseType(targetTypeId);
/* Domains are automatically binary-compatible with their base type */
/* Domains are always coercible to and from their base type */
if (sourceTypeId == targetTypeId)
return true;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.96 2003/05/12 23:08:50 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.97 2003/05/26 00:11:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -343,7 +343,10 @@ name_bpchar(PG_FUNCTION_ARGS)
/*****************************************************************************
* varchar - varchar() *
* varchar - varchar(n)
*
* Note: varchar piggybacks on type text for most operations, and so has no
* C-coded functions except for I/O and typmod checking.
*****************************************************************************/
/*
......@@ -700,7 +703,7 @@ bpcharcmp(PG_FUNCTION_ARGS)
/*
* bpchar needs a specialized hash function because we want to ignore
* trailing blanks in comparisons. (varchar can use plain hashvarlena.)
* trailing blanks in comparisons.
*/
Datum
hashbpchar(PG_FUNCTION_ARGS)
......@@ -720,187 +723,3 @@ hashbpchar(PG_FUNCTION_ARGS)
return result;
}
/*****************************************************************************
* Functions used for varchar
*****************************************************************************/
Datum
varcharlen(PG_FUNCTION_ARGS)
{
VarChar *arg = PG_GETARG_VARCHAR_P(0);
/* optimization for single byte encoding */
if (pg_database_encoding_max_length() <= 1)
PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);
PG_RETURN_INT32(
pg_mbstrlen_with_len(VARDATA(arg), VARSIZE(arg) - VARHDRSZ)
);
}
Datum
varcharoctetlen(PG_FUNCTION_ARGS)
{
VarChar *arg = PG_GETARG_VARCHAR_P(0);
PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);
}
/*****************************************************************************
* Comparison Functions used for varchar
*
* Note: btree indexes need these routines not to leak memory; therefore,
* be careful to free working copies of toasted datums. Most places don't
* need to be so careful.
*****************************************************************************/
Datum
varchareq(PG_FUNCTION_ARGS)
{
VarChar *arg1 = PG_GETARG_VARCHAR_P(0);
VarChar *arg2 = PG_GETARG_VARCHAR_P(1);
int len1,
len2;
bool result;
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
/* fast path for different-length inputs */
if (len1 != len2)
result = false;
else
result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) == 0);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result);
}
Datum
varcharne(PG_FUNCTION_ARGS)
{
VarChar *arg1 = PG_GETARG_VARCHAR_P(0);
VarChar *arg2 = PG_GETARG_VARCHAR_P(1);
int len1,
len2;
bool result;
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
/* fast path for different-length inputs */
if (len1 != len2)
result = true;
else
result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) != 0);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result);
}
Datum
varcharlt(PG_FUNCTION_ARGS)
{
VarChar *arg1 = PG_GETARG_VARCHAR_P(0);
VarChar *arg2 = PG_GETARG_VARCHAR_P(1);
int len1,
len2;
int cmp;
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(cmp < 0);
}
Datum
varcharle(PG_FUNCTION_ARGS)
{
VarChar *arg1 = PG_GETARG_VARCHAR_P(0);
VarChar *arg2 = PG_GETARG_VARCHAR_P(1);
int len1,
len2;
int cmp;
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(cmp <= 0);
}
Datum
varchargt(PG_FUNCTION_ARGS)
{
VarChar *arg1 = PG_GETARG_VARCHAR_P(0);
VarChar *arg2 = PG_GETARG_VARCHAR_P(1);
int len1,
len2;
int cmp;
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(cmp > 0);
}
Datum
varcharge(PG_FUNCTION_ARGS)
{
VarChar *arg1 = PG_GETARG_VARCHAR_P(0);
VarChar *arg2 = PG_GETARG_VARCHAR_P(1);
int len1,
len2;
int cmp;
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(cmp >= 0);
}
Datum
varcharcmp(PG_FUNCTION_ARGS)
{
VarChar *arg1 = PG_GETARG_VARCHAR_P(0);
VarChar *arg2 = PG_GETARG_VARCHAR_P(1);
int len1,
len2;
int cmp;
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_INT32(cmp);
}
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.94 2003/05/13 04:38:58 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.95 2003/05/26 00:11:27 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
......@@ -80,6 +80,33 @@ op_requires_recheck(Oid opno, Oid opclass)
return result;
}
/*
* get_opclass_member
* Get the OID of the operator that implements the specified strategy
* for the specified opclass.
*
* Returns InvalidOid if there is no pg_amop entry for the given keys.
*/
Oid
get_opclass_member(Oid opclass, int16 strategy)
{
HeapTuple tp;
Form_pg_amop amop_tup;
Oid result;
tp = SearchSysCache(AMOPSTRATEGY,
ObjectIdGetDatum(opclass),
Int16GetDatum(strategy),
0, 0);
if (!HeapTupleIsValid(tp))
return InvalidOid;
amop_tup = (Form_pg_amop) GETSTRUCT(tp);
result = amop_tup->amopopr;
ReleaseSysCache(tp);
return result;
}
/* ---------- ATTRIBUTE CACHES ---------- */
/*
......
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.195 2003/05/23 22:33:22 tgl Exp $
* $Id: catversion.h,v 1.196 2003/05/26 00:11:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200305231
#define CATALOG_VERSION_NO 200305241
#endif
......@@ -16,7 +16,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_amop.h,v 1.48 2003/05/15 15:50:19 petere Exp $
* $Id: pg_amop.h,v 1.49 2003/05/26 00:11:27 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -219,14 +219,14 @@ DATA(insert ( 426 4 f 1061 ));
DATA(insert ( 426 5 f 1060 ));
/*
* btree varchar_ops
* btree varchar_ops (same operators as text_ops)
*/
DATA(insert ( 2003 1 f 1066 ));
DATA(insert ( 2003 2 f 1067 ));
DATA(insert ( 2003 3 f 1062 ));
DATA(insert ( 2003 4 f 1069 ));
DATA(insert ( 2003 5 f 1068 ));
DATA(insert ( 2003 1 f 664 ));
DATA(insert ( 2003 2 f 665 ));
DATA(insert ( 2003 3 f 98 ));
DATA(insert ( 2003 4 f 667 ));
DATA(insert ( 2003 5 f 666 ));
/*
* btree bytea_ops
......@@ -389,14 +389,14 @@ DATA(insert ( 2095 4 f 2317 ));
DATA(insert ( 2095 5 f 2318 ));
/*
* btree varchar pattern
* btree varchar pattern (same operators as text)
*/
DATA(insert ( 2096 1 f 2320 ));
DATA(insert ( 2096 2 f 2321 ));
DATA(insert ( 2096 3 f 2322 ));
DATA(insert ( 2096 4 f 2323 ));
DATA(insert ( 2096 5 f 2324 ));
DATA(insert ( 2096 1 f 2314 ));
DATA(insert ( 2096 2 f 2315 ));
DATA(insert ( 2096 3 f 2316 ));
DATA(insert ( 2096 4 f 2317 ));
DATA(insert ( 2096 5 f 2318 ));
/*
* btree bpchar pattern
......@@ -462,7 +462,7 @@ DATA(insert ( 1999 1 f 1320 ));
/* timetz_ops */
DATA(insert ( 2001 1 f 1550 ));
/* varchar_ops */
DATA(insert ( 2004 1 f 1062 ));
DATA(insert ( 2004 1 f 98 ));
/* timestamp_ops */
DATA(insert ( 2040 1 f 2060 ));
......
......@@ -14,7 +14,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_amproc.h,v 1.36 2003/05/15 15:50:19 petere Exp $
* $Id: pg_amproc.h,v 1.37 2003/05/26 00:11:27 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -103,10 +103,10 @@ DATA(insert ( 1996 1 1107 ));
DATA(insert ( 1998 1 1314 ));
DATA(insert ( 2000 1 1358 ));
DATA(insert ( 2002 1 1672 ));
DATA(insert ( 2003 1 1079 ));
DATA(insert ( 2039 1 1314 ));
DATA(insert ( 2003 1 360 ));
DATA(insert ( 2039 1 2045 ));
DATA(insert ( 2095 1 2166 ));
DATA(insert ( 2096 1 2173 ));
DATA(insert ( 2096 1 2166 ));
DATA(insert ( 2097 1 2180 ));
DATA(insert ( 2098 1 2187 ));
......
......@@ -7,7 +7,7 @@
*
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* $Id: pg_cast.h,v 1.6 2003/05/14 18:08:15 tgl Exp $
* $Id: pg_cast.h,v 1.7 2003/05/26 00:11:27 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -161,8 +161,8 @@ DATA(insert ( 2206 23 0 a ));
*/
DATA(insert ( 25 1042 0 i ));
DATA(insert ( 25 1043 0 i ));
DATA(insert ( 1042 25 0 i ));
DATA(insert ( 1042 1043 0 i ));
DATA(insert ( 1042 25 401 i ));
DATA(insert ( 1042 1043 401 i ));
DATA(insert ( 1043 25 0 i ));
DATA(insert ( 1043 1042 0 i ));
DATA(insert ( 18 25 946 i ));
......
......@@ -9,7 +9,7 @@
* of opclass name and index access method type. This row specifies the
* expected input data type for the opclass (the type of the heap column,
* or the function output type in the case of a functional index). Note
* that types binary-compatible with the specified type will be accepted too.
* that types binary-coercible to the specified type will be accepted too.
*
* For a given <opcamid, opcintype> pair, there can be at most one row that
* has opcdefault = true; this row is the default opclass for such data in
......@@ -26,7 +26,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_opclass.h,v 1.48 2003/05/15 15:50:19 petere Exp $
* $Id: pg_opclass.h,v 1.49 2003/05/26 00:11:27 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -92,11 +92,14 @@ DATA(insert OID = 423 ( 403 bit_ops PGNSP PGUID 1560 t 0 ));
DATA(insert OID = 424 ( 403 bool_ops PGNSP PGUID 16 t 0 ));
DATA(insert OID = 425 ( 402 box_ops PGNSP PGUID 603 t 0 ));
DATA(insert OID = 426 ( 403 bpchar_ops PGNSP PGUID 1042 t 0 ));
#define BPCHAR_BTREE_OPS_OID 426
DATA(insert OID = 427 ( 405 bpchar_ops PGNSP PGUID 1042 t 0 ));
DATA(insert OID = 428 ( 403 bytea_ops PGNSP PGUID 17 t 0 ));
#define BYTEA_BTREE_OPS_OID 428
DATA(insert OID = 429 ( 403 char_ops PGNSP PGUID 18 t 0 ));
DATA(insert OID = 431 ( 405 char_ops PGNSP PGUID 18 t 0 ));
DATA(insert OID = 432 ( 403 cidr_ops PGNSP PGUID 650 t 0 ));
#define CIDR_BTREE_OPS_OID 432
DATA(insert OID = 433 ( 405 cidr_ops PGNSP PGUID 650 t 0 ));
DATA(insert OID = 434 ( 403 date_ops PGNSP PGUID 1082 t 0 ));
DATA(insert OID = 435 ( 405 date_ops PGNSP PGUID 1082 t 0 ));
......@@ -105,6 +108,7 @@ DATA(insert OID = 1971 ( 405 float4_ops PGNSP PGUID 700 t 0 ));
DATA(insert OID = 1972 ( 403 float8_ops PGNSP PGUID 701 t 0 ));
DATA(insert OID = 1973 ( 405 float8_ops PGNSP PGUID 701 t 0 ));
DATA(insert OID = 1974 ( 403 inet_ops PGNSP PGUID 869 t 0 ));
#define INET_BTREE_OPS_OID 1974
DATA(insert OID = 1975 ( 405 inet_ops PGNSP PGUID 869 t 0 ));
DATA(insert OID = 1976 ( 403 int2_ops PGNSP PGUID 21 t 0 ));
#define INT2_BTREE_OPS_OID 1976
......@@ -119,6 +123,7 @@ DATA(insert OID = 1983 ( 405 interval_ops PGNSP PGUID 1186 t 0 ));
DATA(insert OID = 1984 ( 403 macaddr_ops PGNSP PGUID 829 t 0 ));
DATA(insert OID = 1985 ( 405 macaddr_ops PGNSP PGUID 829 t 0 ));
DATA(insert OID = 1986 ( 403 name_ops PGNSP PGUID 19 t 0 ));
#define NAME_BTREE_OPS_OID 1986
DATA(insert OID = 1987 ( 405 name_ops PGNSP PGUID 19 t 0 ));
DATA(insert OID = 1988 ( 403 numeric_ops PGNSP PGUID 1700 t 0 ));
DATA(insert OID = 1989 ( 403 oid_ops PGNSP PGUID 26 t 0 ));
......@@ -128,6 +133,7 @@ DATA(insert OID = 1991 ( 403 oidvector_ops PGNSP PGUID 30 t 0 ));
DATA(insert OID = 1992 ( 405 oidvector_ops PGNSP PGUID 30 t 0 ));
DATA(insert OID = 1993 ( 402 poly_ops PGNSP PGUID 604 t 0 ));
DATA(insert OID = 1994 ( 403 text_ops PGNSP PGUID 25 t 0 ));
#define TEXT_BTREE_OPS_OID 1994
DATA(insert OID = 1995 ( 405 text_ops PGNSP PGUID 25 t 0 ));
DATA(insert OID = 1996 ( 403 time_ops PGNSP PGUID 1083 t 0 ));
DATA(insert OID = 1997 ( 405 time_ops PGNSP PGUID 1083 t 0 ));
......@@ -137,12 +143,17 @@ DATA(insert OID = 2000 ( 403 timetz_ops PGNSP PGUID 1266 t 0 ));
DATA(insert OID = 2001 ( 405 timetz_ops PGNSP PGUID 1266 t 0 ));
DATA(insert OID = 2002 ( 403 varbit_ops PGNSP PGUID 1562 t 0 ));
DATA(insert OID = 2003 ( 403 varchar_ops PGNSP PGUID 1043 t 0 ));
#define VARCHAR_BTREE_OPS_OID 2003
DATA(insert OID = 2004 ( 405 varchar_ops PGNSP PGUID 1043 t 0 ));
DATA(insert OID = 2039 ( 403 timestamp_ops PGNSP PGUID 1114 t 0 ));
DATA(insert OID = 2040 ( 405 timestamp_ops PGNSP PGUID 1114 t 0 ));
DATA(insert OID = 2095 ( 403 text_pattern_ops PGNSP PGUID 25 f 0 ));
#define TEXT_PATTERN_BTREE_OPS_OID 2095
DATA(insert OID = 2096 ( 403 varchar_pattern_ops PGNSP PGUID 1043 f 0 ));
#define VARCHAR_PATTERN_BTREE_OPS_OID 2096
DATA(insert OID = 2097 ( 403 bpchar_pattern_ops PGNSP PGUID 1042 f 0 ));
#define BPCHAR_PATTERN_BTREE_OPS_OID 2097
DATA(insert OID = 2098 ( 403 name_pattern_ops PGNSP PGUID 19 f 0 ));
#define NAME_PATTERN_BTREE_OPS_OID 2098
#endif /* PG_OPCLASS_H */
This diff is collapsed.
This diff is collapsed.
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: paths.h,v 1.66 2003/02/15 20:12:41 tgl Exp $
* $Id: paths.h,v 1.67 2003/05/26 00:11:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -41,7 +41,8 @@ extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel,
extern List *extract_or_indexqual_conditions(RelOptInfo *rel,
IndexOptInfo *index,
Expr *orsubclause);
extern List *expand_indexqual_conditions(List *indexquals);
extern List *expand_indexqual_conditions(IndexOptInfo *index,
List *clausegroups);
/*
* orindxpath.c
......
......@@ -7,13 +7,14 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_func.h,v 1.45 2003/04/29 22:13:11 tgl Exp $
* $Id: parse_func.h,v 1.46 2003/05/26 00:11:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSER_FUNC_H
#define PARSER_FUNC_H
#include "catalog/namespace.h"
#include "parser/parse_node.h"
......@@ -48,6 +49,15 @@ extern FuncDetailCode func_get_detail(List *funcname, List *fargs,
Oid *funcid, Oid *rettype,
bool *retset, Oid **true_typeids);
extern int func_match_argtypes(int nargs,
Oid *input_typeids,
FuncCandidateList raw_candidates,
FuncCandidateList *candidates);
extern FuncCandidateList func_select_candidate(int nargs,
Oid *input_typeids,
FuncCandidateList candidates);
extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
extern void make_fn_arguments(ParseState *pstate,
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.218 2003/05/23 22:33:23 tgl Exp $
* $Id: builtins.h,v 1.219 2003/05/26 00:11:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -496,15 +496,6 @@ extern Datum varcharout(PG_FUNCTION_ARGS);
extern Datum varcharrecv(PG_FUNCTION_ARGS);
extern Datum varcharsend(PG_FUNCTION_ARGS);
extern Datum varchar(PG_FUNCTION_ARGS);
extern Datum varchareq(PG_FUNCTION_ARGS);
extern Datum varcharne(PG_FUNCTION_ARGS);
extern Datum varcharlt(PG_FUNCTION_ARGS);
extern Datum varcharle(PG_FUNCTION_ARGS);
extern Datum varchargt(PG_FUNCTION_ARGS);
extern Datum varcharge(PG_FUNCTION_ARGS);
extern Datum varcharcmp(PG_FUNCTION_ARGS);
extern Datum varcharlen(PG_FUNCTION_ARGS);
extern Datum varcharoctetlen(PG_FUNCTION_ARGS);
/* varlena.c */
extern Datum textin(PG_FUNCTION_ARGS);
......
......@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: lsyscache.h,v 1.69 2003/05/09 18:08:48 tgl Exp $
* $Id: lsyscache.h,v 1.70 2003/05/26 00:11:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -17,6 +17,7 @@
extern bool op_in_opclass(Oid opno, Oid opclass);
extern bool op_requires_recheck(Oid opno, Oid opclass);
extern Oid get_opclass_member(Oid opclass, int16 strategy);
extern char *get_attname(Oid relid, AttrNumber attnum);
extern AttrNumber get_attnum(Oid relid, const char *attname);
extern Oid get_atttype(Oid relid, AttrNumber attnum);
......
......@@ -27,7 +27,7 @@ INSERT INTO NAME_TBL(f1) VALUES ('d34aaasdf');
INSERT INTO NAME_TBL(f1) VALUES ('');
INSERT INTO NAME_TBL(f1) VALUES ('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ');
SELECT '' AS seven, NAME_TBL.*;
seven | f1
seven | f1
-------+-----------------------------------------------------------------
| 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQ
| 1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopq
......@@ -39,7 +39,7 @@ SELECT '' AS seven, NAME_TBL.*;
(7 rows)
SELECT '' AS six, c.f1 FROM NAME_TBL c WHERE c.f1 <> '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR';
six | f1
six | f1
-----+-----------------------------------------------------------------
| 1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopq
| asdfghjkl;
......@@ -49,20 +49,20 @@ SELECT '' AS six, c.f1 FROM NAME_TBL c WHERE c.f1 <> '1234567890ABCDEFGHIJKLMNOP
(5 rows)
SELECT '' AS one, c.f1 FROM NAME_TBL c WHERE c.f1 = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR';
one | f1
one | f1
-----+-----------------------------------------------------------------
| 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQ
| 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQ
(2 rows)
SELECT '' AS three, c.f1 FROM NAME_TBL c WHERE c.f1 < '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR';
three | f1
three | f1
-------+----
|
(1 row)
SELECT '' AS four, c.f1 FROM NAME_TBL c WHERE c.f1 <= '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR';
four | f1
four | f1
------+-----------------------------------------------------------------
| 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQ
|
......@@ -70,7 +70,7 @@ SELECT '' AS four, c.f1 FROM NAME_TBL c WHERE c.f1 <= '1234567890ABCDEFGHIJKLMNO
(3 rows)
SELECT '' AS three, c.f1 FROM NAME_TBL c WHERE c.f1 > '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR';
three | f1
three | f1
-------+-----------------------------------------------------------------
| 1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopq
| asdfghjkl;
......@@ -79,7 +79,7 @@ SELECT '' AS three, c.f1 FROM NAME_TBL c WHERE c.f1 > '1234567890ABCDEFGHIJKLMNO
(4 rows)
SELECT '' AS four, c.f1 FROM NAME_TBL c WHERE c.f1 >= '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR';
four | f1
four | f1
------+-----------------------------------------------------------------
| 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQ
| 1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopq
......@@ -90,7 +90,7 @@ SELECT '' AS four, c.f1 FROM NAME_TBL c WHERE c.f1 >= '1234567890ABCDEFGHIJKLMNO
(6 rows)
SELECT '' AS seven, c.f1 FROM NAME_TBL c WHERE c.f1 ~ '.*';
seven | f1
seven | f1
-------+-----------------------------------------------------------------
| 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQ
| 1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopq
......@@ -107,7 +107,7 @@ SELECT '' AS zero, c.f1 FROM NAME_TBL c WHERE c.f1 !~ '.*';
(0 rows)
SELECT '' AS three, c.f1 FROM NAME_TBL c WHERE c.f1 ~ '[0-9]';
three | f1
three | f1
-------+-----------------------------------------------------------------
| 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQ
| 1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopq
......
This diff is collapsed.
......@@ -1317,9 +1317,9 @@ SELECT tablename, rulename, definition FROM pg_rules
---------------+-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pg_settings | pg_settings_n | CREATE RULE pg_settings_n AS ON UPDATE TO pg_settings DO INSTEAD NOTHING;
pg_settings | pg_settings_u | CREATE RULE pg_settings_u AS ON UPDATE TO pg_settings WHERE (new.name = old.name) DO SELECT set_config(old.name, new.setting, false) AS set_config;
rtest_emp | rtest_emp_del | CREATE RULE rtest_emp_del AS ON DELETE TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (old.ename, "current_user"(), 'fired '::bpchar, '$0.00'::money, old.salary);
rtest_emp | rtest_emp_ins | CREATE RULE rtest_emp_ins AS ON INSERT TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'hired '::bpchar, new.salary, '$0.00'::money);
rtest_emp | rtest_emp_upd | CREATE RULE rtest_emp_upd AS ON UPDATE TO rtest_emp WHERE (new.salary <> old.salary) DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'honored '::bpchar, new.salary, old.salary);
rtest_emp | rtest_emp_del | CREATE RULE rtest_emp_del AS ON DELETE TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (old.ename, "current_user"(), 'fired'::bpchar, '$0.00'::money, old.salary);
rtest_emp | rtest_emp_ins | CREATE RULE rtest_emp_ins AS ON INSERT TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'hired'::bpchar, new.salary, '$0.00'::money);
rtest_emp | rtest_emp_upd | CREATE RULE rtest_emp_upd AS ON UPDATE TO rtest_emp WHERE (new.salary <> old.salary) DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'honored'::bpchar, new.salary, old.salary);
rtest_nothn1 | rtest_nothn_r1 | CREATE RULE rtest_nothn_r1 AS ON INSERT TO rtest_nothn1 WHERE ((new.a >= 10) AND (new.a < 20)) DO INSTEAD NOTHING;
rtest_nothn1 | rtest_nothn_r2 | CREATE RULE rtest_nothn_r2 AS ON INSERT TO rtest_nothn1 WHERE ((new.a >= 30) AND (new.a < 40)) DO INSTEAD NOTHING;
rtest_nothn2 | rtest_nothn_r3 | CREATE RULE rtest_nothn_r3 AS ON INSERT TO rtest_nothn2 WHERE (new.a >= 100) DO INSTEAD INSERT INTO rtest_nothn3 (a, b) VALUES (new.a, new.b);
......
......@@ -33,11 +33,11 @@ SELECT b, c FROM test_having
SELECT lower(c), count(c) FROM test_having
GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a)
ORDER BY lower(c);
lower | count
----------+-------
bbbb | 3
cccc | 4
xxxx | 1
lower | count
-------+-------
bbbb | 3
cccc | 4
xxxx | 1
(3 rows)
SELECT c, max(a) FROM test_having
......
......@@ -33,11 +33,11 @@ SELECT b, c FROM test_having
SELECT lower(c), count(c) FROM test_having
GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a)
ORDER BY lower(c);
lower | count
----------+-------
bbbb | 3
cccc | 4
xxxx | 1
lower | count
-------+-------
bbbb | 3
cccc | 4
xxxx | 1
(3 rows)
SELECT c, max(a) FROM test_having
......
......@@ -248,12 +248,12 @@ SELECT count(b) FROM test_missing_target GROUP BY b/2 ORDER BY b/2;
-- w/ existing GROUP BY target using a relation name in target
SELECT lower(test_missing_target.c), count(c)
FROM test_missing_target GROUP BY lower(c) ORDER BY lower(c);
lower | count
----------+-------
aaaa | 2
bbbb | 3
cccc | 4
xxxx | 1
lower | count
-------+-------
aaaa | 2
bbbb | 3
cccc | 4
xxxx | 1
(4 rows)
-- w/o existing GROUP BY target
......
......@@ -248,12 +248,12 @@ SELECT count(b) FROM test_missing_target GROUP BY b/2 ORDER BY b/2;
-- w/ existing GROUP BY target using a relation name in target
SELECT lower(test_missing_target.c), count(c)
FROM test_missing_target GROUP BY lower(c) ORDER BY lower(c);
lower | count
----------+-------
aaaa | 2
bbbb | 3
cccc | 4
xxxx | 1
lower | count
-------+-------
aaaa | 2
bbbb | 3
cccc | 4
xxxx | 1
(4 rows)
-- w/o existing GROUP BY target
......
......@@ -26,8 +26,8 @@ ERROR: parser: parse error at or near "' - third line'" at character 75
SELECT CAST(f1 AS text) AS "text(char)" FROM CHAR_TBL;
text(char)
------------
a
ab
a
ab
abcd
abcd
(4 rows)
......@@ -88,8 +88,8 @@ SELECT CAST(f1 AS varchar) AS "varchar(text)" FROM TEXT_TBL;
SELECT CAST(f1 AS varchar) AS "varchar(char)" FROM CHAR_TBL;
varchar(char)
---------------
a
ab
a
ab
abcd
abcd
(4 rows)
......@@ -570,16 +570,16 @@ SELECT text 'text' || ' and unknown' AS "Concat text to unknown type";
text and unknown
(1 row)
SELECT char(20) 'characters' || 'and text' AS "Concat char to unknown type";
Concat char to unknown type
------------------------------
characters and text
SELECT char(20) 'characters' || ' and text' AS "Concat char to unknown type";
Concat char to unknown type
-----------------------------
characters and text
(1 row)
SELECT text 'text' || char(20) ' and characters' AS "Concat text to char";
Concat text to char
--------------------------
text and characters
Concat text to char
---------------------
text and characters
(1 row)
SELECT text 'text' || varchar ' and varchar' AS "Concat text to varchar";
......
......@@ -203,21 +203,19 @@ SELECT f1 FROM INT4_TBL
123456
(5 rows)
SELECT f1 AS five FROM VARCHAR_TBL
SELECT CAST(f1 AS char(4)) AS three FROM VARCHAR_TBL
UNION
SELECT f1 FROM CHAR_TBL;
five
------
a
three
-------
a
ab
ab
abcd
(5 rows)
(3 rows)
SELECT f1 AS three FROM VARCHAR_TBL
UNION
SELECT TRIM(TRAILING FROM f1) FROM CHAR_TBL;
SELECT CAST(f1 AS varchar) FROM CHAR_TBL;
three
-------
a
......@@ -234,8 +232,8 @@ SELECT f1 FROM CHAR_TBL;
ab
abcd
abcd
a
ab
a
ab
abcd
abcd
(8 rows)
......
This diff is collapsed.
......@@ -199,7 +199,7 @@ SELECT 'unknown' || ' and unknown' AS "Concat unknown types";
SELECT text 'text' || ' and unknown' AS "Concat text to unknown type";
SELECT char(20) 'characters' || 'and text' AS "Concat char to unknown type";
SELECT char(20) 'characters' || ' and text' AS "Concat char to unknown type";
SELECT text 'text' || char(20) ' and characters' AS "Concat text to char";
......
......@@ -66,13 +66,13 @@ UNION
SELECT f1 FROM INT4_TBL
WHERE f1 BETWEEN 0 AND 1000000;
SELECT f1 AS five FROM VARCHAR_TBL
SELECT CAST(f1 AS char(4)) AS three FROM VARCHAR_TBL
UNION
SELECT f1 FROM CHAR_TBL;
SELECT f1 AS three FROM VARCHAR_TBL
UNION
SELECT TRIM(TRAILING FROM f1) FROM CHAR_TBL;
SELECT CAST(f1 AS varchar) FROM CHAR_TBL;
SELECT f1 AS eight FROM VARCHAR_TBL
UNION ALL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment