mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Moved src/extend to contrib
This commit is contained in:
		
							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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user