mirror of https://github.com/postgres/postgres
parent
c6cf21825a
commit
5eb17f53b6
@ -1,251 +0,0 @@ |
|||||||
/*
|
|
||||||
* array_iterator.c -- |
|
||||||
* |
|
||||||
* This file defines a new group of operators which take an |
|
||||||
* array and a scalar value, iterate a scalar operator over the |
|
||||||
* elements of the array and the value and compute a result as |
|
||||||
* the logical OR or AND of the results. |
|
||||||
* For example array_int4eq returns true if some of the elements |
|
||||||
* of an array of int4 is equal to the given value: |
|
||||||
* |
|
||||||
* array_int4eq({1,2,3}, 1) --> true |
|
||||||
* array_int4eq({1,2,3}, 4) --> false |
|
||||||
* |
|
||||||
* If we have defined T array types and O scalar operators |
|
||||||
* we can define T x O array operators, each of them has a name |
|
||||||
* like "array_<basetype><operation>" and takes an array of type T |
|
||||||
* iterating the operator O over all the elements. Note however |
|
||||||
* that some of the possible combination are invalid, for example |
|
||||||
* the array_int4_like because there is no like operator for int4. |
|
||||||
* It is now possible to write queries which look inside the arrays: |
|
||||||
* |
|
||||||
* create table t(id int4[], txt text[]); |
|
||||||
* select * from t where t.id *= 123; |
|
||||||
* select * from t where t.txt *~ '[a-z]'; |
|
||||||
* select * from t where t.txt[1:3] **~ '[a-z]'; |
|
||||||
* |
|
||||||
* Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it> |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <ctype.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <sys/types.h> |
|
||||||
#include <string.h> |
|
||||||
|
|
||||||
#include "postgres.h" |
|
||||||
#include "pg_type.h" |
|
||||||
#include "miscadmin.h" |
|
||||||
#include "syscache.h" |
|
||||||
#include "access/xact.h" |
|
||||||
#include "utils/builtins.h" |
|
||||||
#include "utils/elog.h" |
|
||||||
|
|
||||||
static int32 |
|
||||||
array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value) |
|
||||||
{ |
|
||||||
HeapTuple typ_tuple; |
|
||||||
TypeTupleForm typ_struct; |
|
||||||
bool typbyval; |
|
||||||
int typlen; |
|
||||||
func_ptr proc_fn; |
|
||||||
int pronargs; |
|
||||||
int nitems, i, result; |
|
||||||
int ndim, *dim; |
|
||||||
char *p; |
|
||||||
|
|
||||||
/* Sanity checks */ |
|
||||||
if ((array == (ArrayType *) NULL) |
|
||||||
|| (ARR_IS_LO(array) == true)) { |
|
||||||
/* elog(NOTICE, "array_iterator: array is null"); */ |
|
||||||
return (0); |
|
||||||
} |
|
||||||
ndim = ARR_NDIM(array); |
|
||||||
dim = ARR_DIMS(array); |
|
||||||
nitems = getNitems(ndim, dim); |
|
||||||
if (nitems == 0) { |
|
||||||
/* elog(NOTICE, "array_iterator: nitems = 0"); */ |
|
||||||
return (0); |
|
||||||
} |
|
||||||
|
|
||||||
/* Lookup element type information */ |
|
||||||
typ_tuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(elemtype),0,0,0); |
|
||||||
if (!HeapTupleIsValid(typ_tuple)) { |
|
||||||
elog(WARN,"array_iterator: cache lookup failed for type %d", elemtype); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
typ_struct = (TypeTupleForm) GETSTRUCT(typ_tuple); |
|
||||||
typlen = typ_struct->typlen; |
|
||||||
typbyval = typ_struct->typbyval; |
|
||||||
|
|
||||||
/* Lookup the function entry point */ |
|
||||||
proc_fn == (func_ptr) NULL; |
|
||||||
fmgr_info(proc, &proc_fn, &pronargs); |
|
||||||
if ((proc_fn == NULL) || (pronargs != 2)) { |
|
||||||
elog(WARN, "array_iterator: fmgr_info lookup failed for oid %d", proc); |
|
||||||
return (0); |
|
||||||
} |
|
||||||
|
|
||||||
/* Scan the array and apply the operator to each element */ |
|
||||||
result = 0; |
|
||||||
p = ARR_DATA_PTR(array); |
|
||||||
for (i = 0; i < nitems; i++) { |
|
||||||
if (typbyval) { |
|
||||||
switch(typlen) { |
|
||||||
case 1: |
|
||||||
result = (int) (*proc_fn)(*p, value); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
result = (int) (*proc_fn)(* (int16 *) p, value); |
|
||||||
break; |
|
||||||
case 3: |
|
||||||
case 4: |
|
||||||
result = (int) (*proc_fn)(* (int32 *) p, value); |
|
||||||
break; |
|
||||||
} |
|
||||||
p += typlen; |
|
||||||
} else { |
|
||||||
result = (int) (*proc_fn)(p, value); |
|
||||||
if (typlen > 0) { |
|
||||||
p += typlen; |
|
||||||
} else { |
|
||||||
p += INTALIGN(* (int32 *) p); |
|
||||||
} |
|
||||||
} |
|
||||||
if (result) { |
|
||||||
if (!and) { |
|
||||||
return (1); |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (and) { |
|
||||||
return (0); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (and && result) { |
|
||||||
return (1); |
|
||||||
} else { |
|
||||||
return (0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterators for type _text |
|
||||||
*/ |
|
||||||
|
|
||||||
int32 |
|
||||||
array_texteq(ArrayType *array, char* value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 25, /* text */ |
|
||||||
(Oid) 67, /* texteq */ |
|
||||||
0, /* logical or */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_all_texteq(ArrayType *array, char* value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 25, /* text */ |
|
||||||
(Oid) 67, /* texteq */ |
|
||||||
1, /* logical and */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_textregexeq(ArrayType *array, char* value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 25, /* text */ |
|
||||||
(Oid) 81, /* textregexeq */ |
|
||||||
0, /* logical or */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_all_textregexeq(ArrayType *array, char* value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 25, /* text */ |
|
||||||
(Oid) 81, /* textregexeq */ |
|
||||||
1, /* logical and */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterators for type _char16. Note that the regexp operators |
|
||||||
* take the second argument of type text. |
|
||||||
*/ |
|
||||||
|
|
||||||
int32 |
|
||||||
array_char16eq(ArrayType *array, char* value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 20, /* char16 */ |
|
||||||
(Oid) 490, /* char16eq */ |
|
||||||
0, /* logical or */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_all_char16eq(ArrayType *array, char* value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 20, /* char16 */ |
|
||||||
(Oid) 490, /* char16eq */ |
|
||||||
1, /* logical and */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_char16regexeq(ArrayType *array, char* value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 20, /* char16 */ |
|
||||||
(Oid) 700, /* char16regexeq */ |
|
||||||
0, /* logical or */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_all_char16regexeq(ArrayType *array, char* value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 20, /* char16 */ |
|
||||||
(Oid) 700, /* char16regexeq */ |
|
||||||
1, /* logical and */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterators for type _int4 |
|
||||||
*/ |
|
||||||
|
|
||||||
int32 |
|
||||||
array_int4eq(ArrayType *array, int4 value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 23, /* int4 */ |
|
||||||
(Oid) 65, /* int4eq */ |
|
||||||
0, /* logical or */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_all_int4eq(ArrayType *array, int4 value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 23, /* int4 */ |
|
||||||
(Oid) 65, /* int4eq */ |
|
||||||
1, /* logical and */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_int4gt(ArrayType *array, int4 value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 23, /* int4 */ |
|
||||||
(Oid) 147, /* int4gt */ |
|
||||||
0, /* logical or */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
||||||
|
|
||||||
int32 |
|
||||||
array_all_int4gt(ArrayType *array, int4 value) |
|
||||||
{ |
|
||||||
return array_iterator((Oid) 23, /* int4 */ |
|
||||||
(Oid) 147, /* int4gt */ |
|
||||||
1, /* logical and */ |
|
||||||
array, (Datum)value); |
|
||||||
} |
|
@ -1,26 +0,0 @@ |
|||||||
From: Massimo Dal Zotto <dz@cs.unitn.it> |
|
||||||
Date: Mon, 6 May 1996 01:03:37 +0200 (MET DST) |
|
||||||
Subject: [PG95]: new operators for arrays |
|
||||||
|
|
||||||
- -----BEGIN PGP SIGNED MESSAGE----- |
|
||||||
|
|
||||||
Hi, |
|
||||||
|
|
||||||
I have written an extension to Postgres95 which allows to use qualification |
|
||||||
clauses based on the values of single elements of arrays. |
|
||||||
For example I can now select rows having some or all element of an array |
|
||||||
attribute equal to a given value or matching a regular expression: |
|
||||||
|
|
||||||
select * from t where t.foo *= 'bar'; |
|
||||||
select * from t where t.foo **~ '^ba[rz]'; |
|
||||||
|
|
||||||
The scheme is quite general, each operator which operates on a base type can |
|
||||||
be iterated over the elements of an array. It seem to work well but defining |
|
||||||
each new operators requires writing a different C function. Furthermore in |
|
||||||
each function there are two hardcoded OIDs which reference a base type and |
|
||||||
a procedure. Not very portable. Can anyone suggest a better and more portable |
|
||||||
way to do it ? Do you think this could be a useful feature for next release ? |
|
||||||
Here is my code, it can be compiled and loaded as a dynamic module without |
|
||||||
need to recompile the backend. I have defined only the few operators I needed, |
|
||||||
the list can be extended. Feddback is welcome. |
|
||||||
|
|
@ -1,137 +0,0 @@ |
|||||||
/* |
|
||||||
* SQL code |
|
||||||
|
|
||||||
- - -- load the new functions |
|
||||||
- - -- |
|
||||||
load '/home/dz/lib/postgres/array_iterator.so'; |
|
||||||
|
|
||||||
- - -- define the array operators *=, **=, *~ and **~ for type _text |
|
||||||
- - -- |
|
||||||
create function array_texteq(_text, text) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_all_texteq(_text, text) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_textregexeq(_text, text) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_all_textregexeq(_text, text) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create operator *= ( |
|
||||||
leftarg=_text, |
|
||||||
rightarg=text, |
|
||||||
procedure=array_texteq); |
|
||||||
|
|
||||||
create operator **= ( |
|
||||||
leftarg=_text, |
|
||||||
rightarg=text, |
|
||||||
procedure=array_all_texteq); |
|
||||||
|
|
||||||
create operator *~ ( |
|
||||||
leftarg=_text, |
|
||||||
rightarg=text, |
|
||||||
procedure=array_textregexeq); |
|
||||||
|
|
||||||
create operator **~ ( |
|
||||||
leftarg=_text, |
|
||||||
rightarg=text, |
|
||||||
procedure=array_all_textregexeq); |
|
||||||
|
|
||||||
- - -- define the array operators *=, **=, *~ and **~ for type _char16 |
|
||||||
- - -- |
|
||||||
create function array_char16eq(_char16, char16) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_all_char16eq(_char16, char16) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_char16regexeq(_char16, text) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_all_char16regexeq(_char16, text) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create operator *= ( |
|
||||||
leftarg=_char16, |
|
||||||
rightarg=char16, |
|
||||||
procedure=array_char16eq); |
|
||||||
|
|
||||||
create operator **= ( |
|
||||||
leftarg=_char16, |
|
||||||
rightarg=char16, |
|
||||||
procedure=array_all_char16eq); |
|
||||||
|
|
||||||
create operator *~ ( |
|
||||||
leftarg=_char16, |
|
||||||
rightarg=text, |
|
||||||
procedure=array_char16regexeq); |
|
||||||
|
|
||||||
create operator **~ ( |
|
||||||
leftarg=_char16, |
|
||||||
rightarg=text, |
|
||||||
procedure=array_all_char16regexeq); |
|
||||||
|
|
||||||
- - -- define the array operators *=, **=, *> and **> for type _int4 |
|
||||||
- - -- |
|
||||||
create function array_int4eq(_int4, int4) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_all_int4eq(_int4, int4) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_int4gt(_int4, int4) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function array_all_int4gt(_int4, int4) |
|
||||||
returns bool |
|
||||||
as '/home/dz/lib/postgres/array_iterator.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create operator *= ( |
|
||||||
leftarg=_int4, |
|
||||||
rightarg=int4, |
|
||||||
procedure=array_int4eq); |
|
||||||
|
|
||||||
create operator **= ( |
|
||||||
leftarg=_int4, |
|
||||||
rightarg=int4, |
|
||||||
procedure=array_all_int4eq); |
|
||||||
|
|
||||||
create operator *> ( |
|
||||||
leftarg=_int4, |
|
||||||
rightarg=int4, |
|
||||||
procedure=array_int4gt); |
|
||||||
|
|
||||||
create operator **> ( |
|
||||||
leftarg=_int4, |
|
||||||
rightarg=int4, |
|
||||||
procedure=array_all_int4gt); |
|
||||||
|
|
||||||
*/ |
|
||||||
|
|
||||||
/* end of file */ |
|
||||||
|
|
@ -1,147 +0,0 @@ |
|||||||
/*
|
|
||||||
* datetime_functions.c -- |
|
||||||
* |
|
||||||
* This file defines new functions for the time and date data types. |
|
||||||
* |
|
||||||
* Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it> |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <time.h> |
|
||||||
|
|
||||||
#include "postgres.h" |
|
||||||
#include "pg_type.h" |
|
||||||
#include "utils/palloc.h" |
|
||||||
|
|
||||||
typedef struct DateADT { |
|
||||||
char day; |
|
||||||
char month; |
|
||||||
short year; |
|
||||||
} DateADT; |
|
||||||
|
|
||||||
typedef struct TimeADT { |
|
||||||
short hr; |
|
||||||
short min; |
|
||||||
float sec; |
|
||||||
} TimeADT; |
|
||||||
|
|
||||||
TimeADT * |
|
||||||
time_difference(TimeADT *time1, TimeADT *time2) |
|
||||||
{ |
|
||||||
TimeADT *time = (TimeADT*)palloc(sizeof(TimeADT)); |
|
||||||
|
|
||||||
time->sec = time1->sec - time2->sec; |
|
||||||
time->min = time1->min - time2->min; |
|
||||||
time->hr = time1->hr - time2->hr; |
|
||||||
|
|
||||||
if (time->sec < 0) { |
|
||||||
time->sec += 60.0; |
|
||||||
time->min--; |
|
||||||
} else if (time->sec >= 60.0) { |
|
||||||
time->sec -= 60.0; |
|
||||||
time->min++; |
|
||||||
} |
|
||||||
|
|
||||||
if (time->min < 0) { |
|
||||||
time->min += 60; |
|
||||||
time->hr--; |
|
||||||
} else if (time->min >= 60) { |
|
||||||
time->min -= 60; |
|
||||||
time->hr++; |
|
||||||
} |
|
||||||
|
|
||||||
if (time->hr < 0) { |
|
||||||
time->hr += 24; |
|
||||||
} else if (time->hr >= 24) { |
|
||||||
time->hr -= 24; |
|
||||||
} |
|
||||||
|
|
||||||
return (time); |
|
||||||
} |
|
||||||
|
|
||||||
TimeADT * |
|
||||||
currentTime() |
|
||||||
{ |
|
||||||
time_t current_time; |
|
||||||
struct tm *tm; |
|
||||||
TimeADT *result = (TimeADT*)palloc(sizeof(TimeADT)); |
|
||||||
|
|
||||||
current_time = time(NULL); |
|
||||||
tm = localtime(¤t_time); |
|
||||||
result->sec = tm->tm_sec; |
|
||||||
result->min = tm->tm_min; |
|
||||||
result->hr = tm->tm_hour; |
|
||||||
|
|
||||||
return (result); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
currentDate() |
|
||||||
{ |
|
||||||
time_t current_time; |
|
||||||
struct tm *tm; |
|
||||||
int4 result; |
|
||||||
DateADT *date = (DateADT*)&result; |
|
||||||
|
|
||||||
current_time = time(NULL); |
|
||||||
tm = localtime(¤t_time); |
|
||||||
date->day = tm->tm_mday; |
|
||||||
date->month = tm->tm_mon+1; |
|
||||||
date->year = tm->tm_year+1900; |
|
||||||
|
|
||||||
return (result); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
hours(TimeADT *time) |
|
||||||
{ |
|
||||||
return (time->hr); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
minutes(TimeADT *time) |
|
||||||
{ |
|
||||||
return (time->min); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
seconds(TimeADT *time) |
|
||||||
{ |
|
||||||
int seconds = (int)time->sec; |
|
||||||
return (seconds); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
day(int4 val) |
|
||||||
{ |
|
||||||
DateADT *date = (DateADT*)&val; |
|
||||||
return (date->day); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
month(int4 val) |
|
||||||
{ |
|
||||||
DateADT *date = (DateADT*)&val; |
|
||||||
return (date->month); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
year(int4 val) |
|
||||||
{ |
|
||||||
DateADT *date = (DateADT*)&val; |
|
||||||
return (date->year); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
asMinutes(TimeADT *time) |
|
||||||
{ |
|
||||||
int seconds = (int)time->sec; |
|
||||||
return (time->min + 60*time->hr); |
|
||||||
} |
|
||||||
|
|
||||||
int4 |
|
||||||
asSeconds(TimeADT *time) |
|
||||||
{ |
|
||||||
int seconds = (int)time->sec; |
|
||||||
return (seconds + 60*time->min + 3600*time->hr); |
|
||||||
} |
|
||||||
|
|
@ -1,25 +0,0 @@ |
|||||||
From: Massimo Dal Zotto <dz@cs.unitn.it> |
|
||||||
Date: Tue, 14 May 1996 14:31:18 +0200 (MET DST) |
|
||||||
Subject: [PG95]: new postgres functions |
|
||||||
|
|
||||||
- -----BEGIN PGP SIGNED MESSAGE----- |
|
||||||
|
|
||||||
Some time ago I read in the mailing list requests of people looking |
|
||||||
for more time and date functions. I have now written some of them: |
|
||||||
|
|
||||||
time_difference(time1, time2) ,also defined as operator '-' |
|
||||||
hour(time) |
|
||||||
minutes(time) |
|
||||||
seconds(time) |
|
||||||
asMinutes(time) |
|
||||||
asSeconds(time) |
|
||||||
currentTime() |
|
||||||
currentDate() |
|
||||||
|
|
||||||
The file can be compiled as shared library and loaded as dynamic module |
|
||||||
without need to recompile the backend. This can also be taken as an example |
|
||||||
of the extensibility of postgres (user-defined functions, operators, etc). |
|
||||||
I would be nice to see more of these user contributed modules posted to this |
|
||||||
list and hopefully accessible from the Postgres home page. |
|
||||||
|
|
||||||
|
|
@ -1,69 +0,0 @@ |
|||||||
|
|
||||||
-- SQL code to load and define 'datetime' functions |
|
||||||
|
|
||||||
-- load the new functions |
|
||||||
|
|
||||||
load '/home/dz/lib/postgres/datetime_functions.so'; |
|
||||||
|
|
||||||
-- define the new functions in postgres |
|
||||||
|
|
||||||
create function time_difference(time,time) |
|
||||||
returns time |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function currentDate() |
|
||||||
returns date |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function currentTime() |
|
||||||
returns time |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function hours(time) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function minutes(time) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function seconds(time) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function day(date) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function month(date) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function year(date) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function asMinutes(time) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function asSeconds(time) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/datetime_functions.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create operator - ( |
|
||||||
leftarg=time, |
|
||||||
rightarg=time, |
|
||||||
procedure=time_difference); |
|
||||||
|
|
@ -1,83 +0,0 @@ |
|||||||
/*****************************************************************************/ |
|
||||||
/* soundex.c */ |
|
||||||
/*****************************************************************************/ |
|
||||||
|
|
||||||
#include <string.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include "postgres.h" /* for char16, etc. */ |
|
||||||
#include "utils/palloc.h" /* for palloc */ |
|
||||||
#include "libpq-fe.h" /* for TUPLE */ |
|
||||||
#include <stdio.h> |
|
||||||
#include <ctype.h> |
|
||||||
|
|
||||||
/* prototype for soundex function */ |
|
||||||
char *soundex(char *instr, char *outstr); |
|
||||||
|
|
||||||
text *text_soundex(text *t) |
|
||||||
{ |
|
||||||
/* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ |
|
||||||
char *table = "01230120022455012623010202"; |
|
||||||
int count = 0; |
|
||||||
text *new_t; |
|
||||||
|
|
||||||
char outstr[6+1]; /* max length of soundex is 6 */ |
|
||||||
char *instr; |
|
||||||
|
|
||||||
/* make a null-terminated string */ |
|
||||||
instr=palloc(VARSIZE(t)+1); |
|
||||||
memcpy(instr,VARDATA(t),VARSIZE(t)-VARHDRSZ); |
|
||||||
instr[VARSIZE(t)-VARHDRSZ] = (char)0; |
|
||||||
|
|
||||||
/* load soundex into outstr */ |
|
||||||
soundex(instr, outstr); |
|
||||||
|
|
||||||
/* Now the outstr contains the soundex of instr */ |
|
||||||
/* copy outstr to new_t */ |
|
||||||
new_t = (text *) palloc(strlen(outstr)+VARHDRSZ); |
|
||||||
memset(new_t, 0, strlen(outstr)+1); |
|
||||||
VARSIZE(new_t) = strlen(outstr)+VARHDRSZ; |
|
||||||
memcpy((void *) VARDATA(new_t), |
|
||||||
(void *) outstr, |
|
||||||
strlen(outstr)); |
|
||||||
|
|
||||||
/* free instr */ |
|
||||||
pfree(instr); |
|
||||||
|
|
||||||
return(new_t); |
|
||||||
} |
|
||||||
|
|
||||||
char *soundex(char *instr, char *outstr) |
|
||||||
{ /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ |
|
||||||
char *table = "01230120022455012623010202"; |
|
||||||
int count = 0; |
|
||||||
|
|
||||||
while(!isalpha(instr[0]) && instr[0]) |
|
||||||
++instr; |
|
||||||
|
|
||||||
if(!instr[0]) { /* Hey! Where'd the string go? */ |
|
||||||
outstr[0]=(char)0; |
|
||||||
return outstr; |
|
||||||
} |
|
||||||
|
|
||||||
if(toupper(instr[0]) == 'P' && toupper(instr[1]) == 'H') { |
|
||||||
instr[0] = 'F'; |
|
||||||
instr[1] = 'A'; |
|
||||||
} |
|
||||||
|
|
||||||
*outstr++ = (char)toupper(*instr++); |
|
||||||
|
|
||||||
while(*instr && count < 5) { |
|
||||||
if(isalpha(*instr) && *instr != *(instr-1)) { |
|
||||||
*outstr = table[toupper(instr[0]) - 'A']; |
|
||||||
if(*outstr != '0') { |
|
||||||
++outstr; |
|
||||||
++count; |
|
||||||
} |
|
||||||
} |
|
||||||
++instr; |
|
||||||
} |
|
||||||
|
|
||||||
*outstr = '\0'; |
|
||||||
return(outstr); |
|
||||||
} |
|
||||||
|
|
@ -1,57 +0,0 @@ |
|||||||
--------------- soundex.sql: |
|
||||||
|
|
||||||
CREATE FUNCTION text_soundex(text) RETURNS text |
|
||||||
AS '/usr/local/postgres/postgres95/src/funcs/soundex.so' LANGUAGE 'c'; |
|
||||||
|
|
||||||
SELECT text_soundex('hello world!'); |
|
||||||
|
|
||||||
CREATE TABLE s (nm text)\g |
|
||||||
|
|
||||||
insert into s values ('john')\g |
|
||||||
insert into s values ('joan')\g |
|
||||||
insert into s values ('wobbly')\g |
|
||||||
|
|
||||||
select * from s |
|
||||||
where text_soundex(nm) = text_soundex('john')\g |
|
||||||
|
|
||||||
select nm from s a, s b |
|
||||||
where text_soundex(a.nm) = text_soundex(b.nm) |
|
||||||
and a.oid <> b.oid\g |
|
||||||
|
|
||||||
CREATE FUNCTION text_sx_eq(text, text) RETURNS bool AS |
|
||||||
'select text_soundex($1) = text_soundex($2)' |
|
||||||
LANGUAGE 'sql'\g |
|
||||||
|
|
||||||
CREATE FUNCTION text_sx_lt(text,text) RETURNS bool AS |
|
||||||
'select text_soundex($1) < text_soundex($2)' |
|
||||||
LANGUAGE 'sql'\g |
|
||||||
|
|
||||||
CREATE FUNCTION text_sx_gt(text,text) RETURNS bool AS |
|
||||||
'select text_soundex($1) > text_soundex($2)' |
|
||||||
LANGUAGE 'sql'; |
|
||||||
|
|
||||||
CREATE FUNCTION text_sx_le(text,text) RETURNS bool AS |
|
||||||
'select text_soundex($1) <= text_soundex($2)' |
|
||||||
LANGUAGE 'sql'; |
|
||||||
|
|
||||||
CREATE FUNCTION text_sx_ge(text,text) RETURNS bool AS |
|
||||||
'select text_soundex($1) >= text_soundex($2)' |
|
||||||
LANGUAGE 'sql'; |
|
||||||
|
|
||||||
CREATE FUNCTION text_sx_ne(text,text) RETURNS bool AS |
|
||||||
'select text_soundex($1) <> text_soundex($2)' |
|
||||||
LANGUAGE 'sql'; |
|
||||||
|
|
||||||
DROP OPERATOR #= (text,text)\g |
|
||||||
|
|
||||||
CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_sx_eq, |
|
||||||
commutator=text_sx_eq)\g |
|
||||||
|
|
||||||
SELECT * |
|
||||||
FROM s |
|
||||||
WHERE text_sx_eq(nm,'john')\g |
|
||||||
|
|
||||||
SELECT * |
|
||||||
from s |
|
||||||
where s.nm #= 'john'; |
|
||||||
|
|
@ -1,361 +0,0 @@ |
|||||||
/*
|
|
||||||
* string_io.c -- |
|
||||||
* |
|
||||||
* This file defines new input/output conversion routines for strings. |
|
||||||
* |
|
||||||
* Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it> |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <ctype.h> |
|
||||||
#include <string.h> |
|
||||||
|
|
||||||
#include "postgres.h" |
|
||||||
#include "utils/elog.h" |
|
||||||
#include "utils/palloc.h" |
|
||||||
#include "utils/builtins.h" |
|
||||||
|
|
||||||
/* define this if you want to see iso-8859 characters */ |
|
||||||
#define ISO8859 |
|
||||||
|
|
||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y)) |
|
||||||
#define VALUE(char) ((char) - '0') |
|
||||||
#define DIGIT(val) ((val) + '0') |
|
||||||
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7')) |
|
||||||
#ifndef ISO8859 |
|
||||||
#define NOTPRINTABLE(c) (!isprint(c)) |
|
||||||
#else |
|
||||||
#define NOTPRINTABLE(c) (!isprint(c) && ((c) < 0xa0)) |
|
||||||
#endif |
|
||||||
|
|
||||||
/*
|
|
||||||
* string_output() -- |
|
||||||
* |
|
||||||
* This function takes a pointer to a string data and an optional |
|
||||||
* data size and returns a printable representation of the data |
|
||||||
* translating all escape sequences to C-like \nnn or \c escapes. |
|
||||||
* The function is used by output methods of various string types. |
|
||||||
* |
|
||||||
* Arguments: |
|
||||||
* data - input data (can be NULL) |
|
||||||
* size - optional size of data. A negative value indicates |
|
||||||
* that data is a null terminated string. |
|
||||||
* |
|
||||||
* Returns: |
|
||||||
* a pointer to a new string containing the printable |
|
||||||
* representation of data. |
|
||||||
*/ |
|
||||||
|
|
||||||
char * |
|
||||||
string_output(char *data, int size) |
|
||||||
{ |
|
||||||
register unsigned char c, *p, *r, *result; |
|
||||||
register int l, len; |
|
||||||
|
|
||||||
if (data == NULL) { |
|
||||||
result = (char *) palloc(2); |
|
||||||
result[0] = '-'; |
|
||||||
result[1] = '\0'; |
|
||||||
return (result); |
|
||||||
} |
|
||||||
|
|
||||||
if (size < 0) { |
|
||||||
size = strlen(data); |
|
||||||
} |
|
||||||
|
|
||||||
/* adjust string length for escapes */ |
|
||||||
len = size; |
|
||||||
for (p=data,l=size; l>0; p++,l--) { |
|
||||||
switch (*p) { |
|
||||||
case '\\': |
|
||||||
case '"' : |
|
||||||
case '{': |
|
||||||
case '}': |
|
||||||
case '\b': |
|
||||||
case '\f': |
|
||||||
case '\n': |
|
||||||
case '\r': |
|
||||||
case '\t': |
|
||||||
case '\v': |
|
||||||
len++; |
|
||||||
break; |
|
||||||
default: |
|
||||||
if (NOTPRINTABLE(c)) { |
|
||||||
len += 3; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
len++; |
|
||||||
|
|
||||||
result = (char *) palloc(len); |
|
||||||
|
|
||||||
for (p=data,r=result,l=size; (l > 0) && (c = *p); p++,l--) { |
|
||||||
switch (c) { |
|
||||||
case '\\': |
|
||||||
case '"' : |
|
||||||
case '{': |
|
||||||
case '}': |
|
||||||
*r++ = '\\'; |
|
||||||
*r++ = c; |
|
||||||
break; |
|
||||||
case '\b': |
|
||||||
*r++ = '\\'; |
|
||||||
*r++ = 'b'; |
|
||||||
break; |
|
||||||
case '\f': |
|
||||||
*r++ = '\\'; |
|
||||||
*r++ = 'f'; |
|
||||||
break; |
|
||||||
case '\n': |
|
||||||
*r++ = '\\'; |
|
||||||
*r++ = 'n'; |
|
||||||
break; |
|
||||||
case '\r': |
|
||||||
*r++ = '\\'; |
|
||||||
*r++ = 'r'; |
|
||||||
break; |
|
||||||
case '\t': |
|
||||||
*r++ = '\\'; |
|
||||||
*r++ = 't'; |
|
||||||
break; |
|
||||||
case '\v': |
|
||||||
*r++ = '\\'; |
|
||||||
*r++ = 'v'; |
|
||||||
break; |
|
||||||
default: |
|
||||||
if (NOTPRINTABLE(c)) { |
|
||||||
*r = '\\'; |
|
||||||
r += 3; |
|
||||||
*r-- = DIGIT(c & 07); |
|
||||||
c >>= 3; |
|
||||||
*r-- = DIGIT(c & 07); |
|
||||||
c >>= 3; |
|
||||||
*r = DIGIT(c & 03); |
|
||||||
r += 3; |
|
||||||
} else { |
|
||||||
*r++ = c; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
*r = '\0'; |
|
||||||
|
|
||||||
return((char *) result); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* string_input() -- |
|
||||||
* |
|
||||||
* This function accepts a C string in input and copies it into a new
|
|
||||||
* object allocated with palloc() translating all escape sequences. |
|
||||||
* An optional header can be allocatd before the string, for example |
|
||||||
* to hold the length of a varlena object. |
|
||||||
* This function is not necessary for input from sql commands because |
|
||||||
* the parser already does escape translation, all data input routines |
|
||||||
* receive strings in internal form. |
|
||||||
* |
|
||||||
* Arguments: |
|
||||||
* str - input string possibly with escapes |
|
||||||
* size - the required size of new data. A value of 0 |
|
||||||
* indicates a variable size string, while a |
|
||||||
* negative value indicates a variable size string |
|
||||||
* of size not greater than this absolute value. |
|
||||||
* hdrsize - size of an optional header to be allocated before |
|
||||||
* the data. It must then be filled by the caller. |
|
||||||
* rtn_size - an optional pointer to an int variable where the |
|
||||||
* size of the new string is stored back. |
|
||||||
* |
|
||||||
* Returns: |
|
||||||
* a pointer to the new string or the header. |
|
||||||
*/ |
|
||||||
|
|
||||||
char * |
|
||||||
string_input(char *str, int size, int hdrsize, int *rtn_size) |
|
||||||
{ |
|
||||||
register unsigned char *p, *r; |
|
||||||
unsigned char *result; |
|
||||||
int len; |
|
||||||
|
|
||||||
if ((str == NULL) || (hdrsize < 0)) { |
|
||||||
return (char *) NULL; |
|
||||||
} |
|
||||||
|
|
||||||
/* Compute result size */ |
|
||||||
len = strlen(str); |
|
||||||
for (p=str; *p; ) { |
|
||||||
if (*p++ == '\\') { |
|
||||||
if (ISOCTAL(*p)) { |
|
||||||
if (ISOCTAL(*(p+1))) { |
|
||||||
p++; |
|
||||||
len--; |
|
||||||
} |
|
||||||
if (ISOCTAL(*(p+1))) { |
|
||||||
p++; |
|
||||||
len--; |
|
||||||
} |
|
||||||
} |
|
||||||
if (*p) p++; |
|
||||||
len--; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* result has variable length */ |
|
||||||
if (size == 0) { |
|
||||||
size = len+1; |
|
||||||
} else |
|
||||||
|
|
||||||
/* result has variable length with maximum size */ |
|
||||||
if (size < 0) { |
|
||||||
size = MIN(len, - size)+1; |
|
||||||
} |
|
||||||
|
|
||||||
result = (char *) palloc(hdrsize+size); |
|
||||||
memset(result, 0, hdrsize+size); |
|
||||||
if (rtn_size) { |
|
||||||
*rtn_size = size; |
|
||||||
} |
|
||||||
|
|
||||||
r = result + hdrsize; |
|
||||||
for (p=str; *p; ) { |
|
||||||
register unsigned char c; |
|
||||||
if ((c = *p++) == '\\') { |
|
||||||
switch (c = *p++) { |
|
||||||
case '\0': |
|
||||||
p--; |
|
||||||
break; |
|
||||||
case '0': |
|
||||||
case '1': |
|
||||||
case '2': |
|
||||||
case '3': |
|
||||||
case '4': |
|
||||||
case '5': |
|
||||||
case '6': |
|
||||||
case '7': |
|
||||||
c = VALUE(c); |
|
||||||
if (isdigit(*p)) { |
|
||||||
c = (c<<3) + VALUE(*p++); |
|
||||||
} |
|
||||||
if (isdigit(*p)) { |
|
||||||
c = (c<<3) + VALUE(*p++); |
|
||||||
} |
|
||||||
*r++ = c; |
|
||||||
break; |
|
||||||
case 'b': |
|
||||||
*r++ = '\b'; |
|
||||||
break; |
|
||||||
case 'f': |
|
||||||
*r++ = '\f'; |
|
||||||
break; |
|
||||||
case 'n': |
|
||||||
*r++ = '\n'; |
|
||||||
break; |
|
||||||
case 'r': |
|
||||||
*r++ = '\r'; |
|
||||||
break; |
|
||||||
case 't': |
|
||||||
*r++ = '\t'; |
|
||||||
break; |
|
||||||
case 'v': |
|
||||||
*r++ = '\v'; |
|
||||||
break; |
|
||||||
default: |
|
||||||
*r++ = c; |
|
||||||
} |
|
||||||
} else { |
|
||||||
*r++ = c; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return((char *) result); |
|
||||||
} |
|
||||||
|
|
||||||
char * |
|
||||||
c_charout(int32 c) |
|
||||||
{ |
|
||||||
char str[2]; |
|
||||||
|
|
||||||
str[0] = (char) c; |
|
||||||
str[1] = '\0'; |
|
||||||
|
|
||||||
return (string_output(str, 1)); |
|
||||||
} |
|
||||||
|
|
||||||
char * |
|
||||||
c_char2out(uint16 s) |
|
||||||
{ |
|
||||||
return (string_output((char *) &s, 2)); |
|
||||||
} |
|
||||||
|
|
||||||
char * |
|
||||||
c_char4out(uint32 s) |
|
||||||
{ |
|
||||||
return (string_output((char *) &s, 4)); |
|
||||||
} |
|
||||||
|
|
||||||
char * |
|
||||||
c_char8out(char *s) |
|
||||||
{ |
|
||||||
return (string_output(s, 8)); |
|
||||||
} |
|
||||||
|
|
||||||
char * |
|
||||||
c_char16out(char *s) |
|
||||||
{ |
|
||||||
return (string_output(s, 16)); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* This can be used for text, bytea, SET and unknown data types |
|
||||||
*/ |
|
||||||
|
|
||||||
char * |
|
||||||
c_textout(struct varlena *vlena) |
|
||||||
{ |
|
||||||
int len = 0; |
|
||||||
char *s = NULL; |
|
||||||
|
|
||||||
if (vlena) { |
|
||||||
len = VARSIZE(vlena) - VARHDRSZ; |
|
||||||
s = VARDATA(vlena); |
|
||||||
} |
|
||||||
return (string_output(s, len)); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* This can be used for varchar and bpchar strings |
|
||||||
*/ |
|
||||||
|
|
||||||
char * |
|
||||||
c_varcharout(char *s) |
|
||||||
{ |
|
||||||
int len; |
|
||||||
|
|
||||||
if (s) { |
|
||||||
len = *(int32*)s - 4; |
|
||||||
s += 4; |
|
||||||
} |
|
||||||
return (string_output(s, len)); |
|
||||||
} |
|
||||||
|
|
||||||
#ifdef 0 |
|
||||||
struct varlena * |
|
||||||
c_textin(char *str) |
|
||||||
{ |
|
||||||
struct varlena *result; |
|
||||||
int len; |
|
||||||
|
|
||||||
if (str == NULL) { |
|
||||||
return ((struct varlena *) NULL); |
|
||||||
} |
|
||||||
|
|
||||||
result = (struct varlena *) string_input(str, 0, VARHDRSZ, &len); |
|
||||||
VARSIZE(result) = len; |
|
||||||
|
|
||||||
return (result); |
|
||||||
} |
|
||||||
|
|
||||||
char * |
|
||||||
c_char16in(char *str) |
|
||||||
{ |
|
||||||
return (string_input(str, 16, 0, NULL)); |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
@ -1,111 +0,0 @@ |
|||||||
|
|
||||||
- - -- load the new functions |
|
||||||
- - -- |
|
||||||
load '/home/dz/lib/postgres/string_output.so'; |
|
||||||
|
|
||||||
- - -- create function c_textin(opaque) |
|
||||||
- - -- returns text |
|
||||||
- - -- as '/home/dz/lib/postgres/string_output.so' |
|
||||||
- - -- language 'c'; |
|
||||||
|
|
||||||
create function c_charout(opaque) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/string_output.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function c_char2out(opaque) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/string_output.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function c_char4out(opaque) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/string_output.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function c_char8out(opaque) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/string_output.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function c_char16out(opaque) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/string_output.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function c_textout(opaque) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/string_output.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
create function c_varcharout(opaque) |
|
||||||
returns int4 |
|
||||||
as '/home/dz/lib/postgres/string_output.so' |
|
||||||
language 'c'; |
|
||||||
|
|
||||||
- - -- define a function which sets the new output routines for char types |
|
||||||
- - -- |
|
||||||
- - -- select c_mode(); |
|
||||||
- - -- |
|
||||||
create function c_mode() |
|
||||||
returns text |
|
||||||
as 'update pg_type set typoutput=''c_charout'' where typname=''char''\; |
|
||||||
update pg_type set typoutput=''c_char2out'' where typname=''char2''\; |
|
||||||
update pg_type set typoutput=''c_char4out'' where typname=''char4''\; |
|
||||||
update pg_type set typoutput=''c_char8out'' where typname=''char8''\; |
|
||||||
update pg_type set typoutput=''c_char16out'' where typname=''char16''\; |
|
||||||
update pg_type set typoutput=''c_textout'' where typname=''text''\; |
|
||||||
update pg_type set typoutput=''c_textout'' where typname=''bytea''\; |
|
||||||
update pg_type set typoutput=''c_textout'' where typname=''unknown''\; |
|
||||||
update pg_type set typoutput=''c_textout'' where typname=''SET''\; |
|
||||||
update pg_type set typoutput=''c_varcharout'' where typname=''varchar''\; |
|
||||||
update pg_type set typoutput=''c_varcharout'' where typname=''bpchar''\; |
|
||||||
select ''c_mode''::text' |
|
||||||
language 'sql'; |
|
||||||
|
|
||||||
- - -- define a function which restores the original routines for char types |
|
||||||
- - -- |
|
||||||
- - -- select pg_mode(); |
|
||||||
- - -- |
|
||||||
create function pg_mode() |
|
||||||
returns text |
|
||||||
as 'update pg_type set typoutput=''charout'' where typname=''char''\; |
|
||||||
update pg_type set typoutput=''char2out'' where typname=''char2''\; |
|
||||||
update pg_type set typoutput=''char4out'' where typname=''char4''\; |
|
||||||
update pg_type set typoutput=''char8out'' where typname=''char8''\; |
|
||||||
update pg_type set typoutput=''char16out'' where typname=''char16''\; |
|
||||||
update pg_type set typoutput=''textout'' where typname=''text''\; |
|
||||||
update pg_type set typoutput=''textout'' where typname=''bytea''\; |
|
||||||
update pg_type set typoutput=''textout'' where typname=''unknown''\; |
|
||||||
update pg_type set typoutput=''textout'' where typname=''SET''\; |
|
||||||
update pg_type set typoutput=''varcharout'' where typname=''varchar''\; |
|
||||||
update pg_type set typoutput=''varcharout'' where typname=''bpchar''\; |
|
||||||
select ''pg_mode''::text' |
|
||||||
language 'sql'; |
|
||||||
|
|
||||||
- - -- or do the changes manually |
|
||||||
- - -- |
|
||||||
- - -- update pg_type set typoutput='charout' where typname='char'; |
|
||||||
- - -- update pg_type set typoutput='char2out' where typname='char2'; |
|
||||||
- - -- update pg_type set typoutput='char4out' where typname='char4'; |
|
||||||
- - -- update pg_type set typoutput='char8out' where typname='char8'; |
|
||||||
- - -- update pg_type set typoutput='char16out' where typname='char16'; |
|
||||||
- - -- update pg_type set typoutput='textout' where typname='text'; |
|
||||||
- - -- update pg_type set typoutput='textout' where typname='bytea'; |
|
||||||
- - -- update pg_type set typoutput='textout' where typname='unknown'; |
|
||||||
- - -- update pg_type set typoutput='textout' where typname='SET'; |
|
||||||
- - -- update pg_type set typoutput='varcharout' where typname='varchar'; |
|
||||||
- - -- update pg_type set typoutput='varcharout' where typname='bpchar'; |
|
||||||
- - -- |
|
||||||
- - -- update pg_type set typoutput='c_charout' where typname='char'; |
|
||||||
- - -- update pg_type set typoutput='c_char2out' where typname='char2'; |
|
||||||
- - -- update pg_type set typoutput='c_char4out' where typname='char4'; |
|
||||||
- - -- update pg_type set typoutput='c_char8out' where typname='char8'; |
|
||||||
- - -- update pg_type set typoutput='c_char16out' where typname='char16'; |
|
||||||
- - -- update pg_type set typoutput='c_textout' where typname='text'; |
|
||||||
- - -- update pg_type set typoutput='c_textout' where typname='bytea'; |
|
||||||
- - -- update pg_type set typoutput='c_textout' where typname='unknown'; |
|
||||||
- - -- update pg_type set typoutput='c_textout' where typname='SET'; |
|
||||||
- - -- update pg_type set typoutput='c_varcharout' where typname='varchar'; |
|
||||||
- - -- update pg_type set typoutput='c_varcharout' where typname='bpchar'; |
|
||||||
|
|
Loading…
Reference in new issue