mirror of https://github.com/postgres/postgres
parent
349f40b2c2
commit
a1675649e4
@ -1,229 +0,0 @@ |
|||||||
PostgreSQL on QNX 4 |
|
||||||
-------------------- |
|
||||||
last updated: $Date: 2004/03/23 01:23:47 $ |
|
||||||
|
|
||||||
current maintainer: Bernd Tegge (tegge@repas-aeg.de) |
|
||||||
original author: Andreas Kardos (kardos@repas-aeg.de) |
|
||||||
|
|
||||||
This port is an important step because PostgreSQL is still the only free |
|
||||||
relational database with full SQL and ODBC support available for QNX 4. |
|
||||||
The only commercial databases available are Empress RDBMS and Velocis |
|
||||||
Database Server (not supported for Digital Unix). |
|
||||||
|
|
||||||
The most effort required the emulation of System V semaphore sets, |
|
||||||
shared memory and IPC and of some IEEE floating-point functionality. |
|
||||||
|
|
||||||
It is recommended to use the GNU C compiler instead of the Watcom compiler |
|
||||||
because the Watcom compiler doesn't support a int8 datatype (long or |
|
||||||
long long int) and it does not have a C++ frontend. The only advantage |
|
||||||
using Watcom C would be support of Tk and pgaccess. |
|
||||||
|
|
||||||
QNX 4 does not offer native support of shared libraries. Therefore the related |
|
||||||
functionality cannot be used. Shared library support could probably be |
|
||||||
implemented in future. |
|
||||||
|
|
||||||
QNX 4 does not support UNIX domain sockets. Clients must use TCP/IP |
|
||||||
sockets. Therefore, do not set "listen_addresses" to empty in your |
|
||||||
postgresql.conf file. In fact, it's advisable to explicitly set |
|
||||||
"listen_addresses" in an environment using native QNX networking. |
|
||||||
Otherwise the postmaster might not use the IP-Address you think it does :-) |
|
||||||
|
|
||||||
Prerequisites: |
|
||||||
-------------- |
|
||||||
|
|
||||||
The following prerequisites have been used: |
|
||||||
|
|
||||||
QNX standard: |
|
||||||
QNX 4.25, Watcom C 10.6, GNU make |
|
||||||
|
|
||||||
Available from http://www.teaser.fr/~jcmichot/ |
|
||||||
flex-2.5.4a.tar.gz (flex) |
|
||||||
egcs-112-qnx4-r20.tar[.gz] (GNU C) |
|
||||||
|
|
||||||
Available from ftp://ftp.visi.com/users/hawkeyd/qnx/ |
|
||||||
bison-1.2.5.tar.gz |
|
||||||
|
|
||||||
Available from http://quics.qnx.com/cgi-bin/dir_find.cgi?/usr/free/ |
|
||||||
perl 5.004_04 |
|
||||||
|
|
||||||
from ftp://ftp.freesoftware.com/pub/infozip/zlib/ |
|
||||||
zlib 1.1.3 |
|
||||||
|
|
||||||
tcl8.0.3.tar.Z (Tcl) |
|
||||||
|
|
||||||
In order to achieve meaningful results for the regression tests, you need |
|
||||||
a different shell. The standard QNX shell is quite broken with regard to |
|
||||||
scripting (even QSSL suggested to use pdksh or bash). Both are available |
|
||||||
in source and binaries at |
|
||||||
http://quics.qnx.com/cgi-bin/dir_find.cgi?/usr/free/ |
|
||||||
|
|
||||||
flex can be built without any problems using the Watcom or GNU C compilers. |
|
||||||
|
|
||||||
The current version of bison (1.2.8 at the time of this writing) does not |
|
||||||
build cleanly on QNX4 with gcc installed, but you can download src and |
|
||||||
binary of a previous version from the above mentioned ftp site. |
|
||||||
|
|
||||||
download source |
|
||||||
GNU C can be installed by |
|
||||||
/etc/install -u egcs112-qnx4-r20.tar[.gz] |
|
||||||
|
|
||||||
Although Tcl can be built after some slight code changes using the Watcom |
|
||||||
compiler, the GNU C compiler should be used instead. Otherwise it would be |
|
||||||
impossible to link postgres built with GNU C together with libtcl8.0.a built |
|
||||||
with the Watcom compiler. However, if you are going to build a Watcom version |
|
||||||
you must build the tcl and tk libraries with Watcom too. |
|
||||||
|
|
||||||
To make unix/tclUnixTest.c compilable uncomment |
|
||||||
#include <sys/resource.h> |
|
||||||
in it or |
|
||||||
touch /usr/include/sys/resource.h |
|
||||||
In unix/Makefile.in replace |
|
||||||
( echo cd $(TOP_DIR)/tests\; source all ) | ./tcltest |
|
||||||
by |
|
||||||
( echo cd ../tests\; source all ) | ./tcltest |
|
||||||
After that Tcl can be built and tested as stated in README. |
|
||||||
|
|
||||||
Tk cannot be built with GNU C due to the lack of a stack version of the |
|
||||||
X11 library. With the Watcom compiler Tk could be built but this is not useful |
|
||||||
because of the link problems mentioned above. |
|
||||||
|
|
||||||
Therefore the Tk interface and the pgaccess tool cannot be supported for a GNU C |
|
||||||
version of PostgreSQL on QNX 4. |
|
||||||
|
|
||||||
PostgreSQL: |
|
||||||
----------- |
|
||||||
|
|
||||||
On QNX 4 some headers are not in the directories expected. To avoid |
|
||||||
modifications of the code the following links should be made: |
|
||||||
|
|
||||||
ln -s /usr/local/bin/perl /usr/local/bin/perl5 |
|
||||||
ln -s /usr/include/errno.h /usr/include/sys/errno.h |
|
||||||
ln -s /usr/include/ioctl.h /usr/include/sys/ioctl.h |
|
||||||
ln -s /usr/src/pgsql/src/backend/port/qnx4/ipc.h /usr/include/sys/ipc.h |
|
||||||
ln -s /usr/src/pgsql/src/backend/port/qnx4/sem.h /usr/include/sys/sem.h |
|
||||||
ln -s /usr/src/pgsql/src/backend/port/qnx4/shm.h /usr/include/sys/shm.h |
|
||||||
|
|
||||||
For ecgs-2.91.60 the file |
|
||||||
/usr/local/lib/gcc-lib/i386-pc-qnx4/egcs-2.91.66/include/g++/stl_alloc.h |
|
||||||
had to be patched (extern "C++" { ... } // extern "C++"). |
|
||||||
See attached patch. |
|
||||||
|
|
||||||
If all prerequisites are available postgres can be built and installed by |
|
||||||
cd pgsql/src |
|
||||||
./configure --with-tcl --without-tk --with-perl |
|
||||||
gmake > make.log 2>&1 |
|
||||||
gmake install > make.install.log 2>&1 |
|
||||||
su |
|
||||||
cd interfaces/perl5 |
|
||||||
gmake install |
|
||||||
exit |
|
||||||
|
|
||||||
All other steps can be carried out as stated in the INSTALL file. |
|
||||||
|
|
||||||
Make problems: |
|
||||||
-------------- |
|
||||||
|
|
||||||
Sometimes the Watcom library manager wlib crashes with SIGSEGV on some |
|
||||||
object files. This is a general problem and not PostgreSQL related. |
|
||||||
Currently bootstrap.o causes such a crash. The workaround is not to include |
|
||||||
the object file into the SUBSYS.o but link it directly. For further information |
|
||||||
see backend/Makefile and backend/bootstrap/Makefile. |
|
||||||
libpgsql.a currently cannot be generated because of the same problem. But this |
|
||||||
doesn't matter since shared libraries are not supported. |
|
||||||
(The Makefiles are already changed to ignore this, you don't have to |
|
||||||
do anything) |
|
||||||
|
|
||||||
Regression tests: |
|
||||||
----------------- |
|
||||||
please don't use the QNX shell for the parallel regression tests. Download |
|
||||||
bash from quics.qnx.com and run 'make SHELL=/usr/local/bin/bash check' |
|
||||||
instead. |
|
||||||
|
|
||||||
The majority of regression tests succeeded. The following tests failed: |
|
||||||
|
|
||||||
geometry: |
|
||||||
Some slight deviation in the last digit and "0" instead of "-0". |
|
||||||
Can be ignored. |
|
||||||
|
|
||||||
timestamp, tinterval, abstime, horology: |
|
||||||
Differences for years before the UNIX epoch. The QNX library probably treats |
|
||||||
time_t as unsigned -> dates before 1970 get moved into the far future. |
|
||||||
Can be ignored. |
|
||||||
|
|
||||||
create_function_1, create_function_2, create_type, create_operator, |
|
||||||
create_view, select_views, triggers, misc, plpgsql: |
|
||||||
Error messages due to the lack of shared library support. |
|
||||||
|
|
||||||
rules, select_views: |
|
||||||
looks like it fails because it depends on tables created by previously |
|
||||||
failing tests. |
|
||||||
|
|
||||||
alter_table: |
|
||||||
An expected failure message contains one blank more than expected. |
|
||||||
Possibly a faulty output file. |
|
||||||
|
|
||||||
int8, subselect, union |
|
||||||
fails for Watcom version because of lacking int8 support. |
|
||||||
|
|
||||||
The current state of this port should be sufficient for lot of applications. |
|
||||||
|
|
||||||
|
|
||||||
Have fun! |
|
||||||
|
|
||||||
Andreas Kardos |
|
||||||
2000-04-04 |
|
||||||
|
|
||||||
Bernd Tegge |
|
||||||
tegge@repas-aeg.de |
|
||||||
2001-12-10 |
|
||||||
|
|
||||||
--------------------------------------------------------------------------- |
|
||||||
|
|
||||||
*** ./stl_alloc.h.orig Sat Feb 28 05:17:28 1998 |
|
||||||
--- ./stl_alloc.h Tue Nov 23 04:14:09 1999 |
|
||||||
*************** |
|
||||||
*** 120,125 **** |
|
||||||
--- 120,126 ---- |
|
||||||
#pragma set woff 1174 |
|
||||||
#endif |
|
||||||
|
|
||||||
+ extern "C++" { |
|
||||||
// Malloc-based allocator. Typically slower than default alloc below. |
|
||||||
// Typically thread-safe and more storage efficient. |
|
||||||
#ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG |
|
||||||
*************** |
|
||||||
*** 682,687 **** |
|
||||||
--- 683,689 ---- |
|
||||||
# endif |
|
||||||
|
|
||||||
#endif /* ! __USE_MALLOC */ |
|
||||||
+ } // extern "C++" |
|
||||||
|
|
||||||
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) |
|
||||||
#pragma reset woff 1174 |
|
||||||
|
|
||||||
|
|
||||||
Patch required to build with gcc: |
|
||||||
|
|
||||||
*** /usr/src/postgresql-7.2b3/src/backend/port/qnx4/sem.h Thu Nov 8 21:37:52 2001 |
|
||||||
--- src/backend/port/qnx4/sem.h Mon Dec 10 13:22:18 2001 |
|
||||||
*************** |
|
||||||
*** 55,60 **** |
|
||||||
--- 55,71 ---- |
|
||||||
ushort_t sem_num; /* semaphore # */ |
|
||||||
short sem_op; /* semaphore operation */ |
|
||||||
short sem_flg; /* operation flags */ |
|
||||||
+ }; |
|
||||||
+ |
|
||||||
+ /* |
|
||||||
+ * command union for semctl. |
|
||||||
+ */ |
|
||||||
+ |
|
||||||
+ union semun { |
|
||||||
+ int val; /* value for SETVAL */ |
|
||||||
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ |
|
||||||
+ unsigned short int *array; /* array for GETALL, SETALL */ |
|
||||||
+ struct seminfo *__buf; /* buffer for IPC_INFO */ |
|
||||||
}; |
|
||||||
|
|
||||||
extern int semctl(int semid, int semnum, int cmd, /* ... */ union semun arg); |
|
@ -1,51 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* dynloader.c |
|
||||||
* dynamic loader for QNX4 using the shared library mechanism |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/dynloader/qnx4.c,v 1.6 2004/01/07 18:56:27 neilc Exp $ |
|
||||||
* |
|
||||||
* NOTES |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
/* System includes */ |
|
||||||
|
|
||||||
#include "postgres.h" |
|
||||||
|
|
||||||
/*
|
|
||||||
#include <a.out.h> |
|
||||||
#include <dl.h> |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "utils/dynamic_loader.h" |
|
||||||
#include "dynloader.h" |
|
||||||
|
|
||||||
void * |
|
||||||
pg_dlopen(char *filename) |
|
||||||
{ |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
PGFunction |
|
||||||
pg_dlsym(void *handle, char *funcname) |
|
||||||
{ |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
void |
|
||||||
pg_dlclose(void *handle) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
char * |
|
||||||
pg_dlerror() |
|
||||||
{ |
|
||||||
static char errmsg[] = "Failed to load shared library due to lack of shared library support."; |
|
||||||
|
|
||||||
return errmsg; |
|
||||||
} |
|
@ -1,22 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* dynloader.h |
|
||||||
* dynamic loader for QNX4 using the shared library mechanism |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/dynloader/qnx4.h,v 1.4 2003/11/29 19:51:54 pgsql Exp $ |
|
||||||
* |
|
||||||
* NOTES |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "fmgr.h" |
|
||||||
|
|
||||||
void *pg_dlopen(char *filename); |
|
||||||
PGFunction pg_dlsym(void *handle, char *funcname); |
|
||||||
void pg_dlclose(void *handle); |
|
||||||
char *pg_dlerror(); |
|
@ -1,36 +0,0 @@ |
|||||||
#-------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Makefile--
|
|
||||||
# Makefile for port/qnx4
|
|
||||||
#
|
|
||||||
# IDENTIFICATION
|
|
||||||
# $PostgreSQL: pgsql/src/backend/port/qnx4/Makefile,v 1.6 2003/11/29 19:51:54 pgsql Exp $
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
|
|
||||||
subdir = src/backend/port/qnx4
|
|
||||||
top_builddir = ../../../..
|
|
||||||
include $(top_builddir)/src/Makefile.global |
|
||||||
|
|
||||||
OBJS = isnan.o sem.o shm.o
|
|
||||||
|
|
||||||
all: SUBSYS.o tstsem tstshm |
|
||||||
|
|
||||||
SUBSYS.o: $(OBJS) |
|
||||||
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
|
|
||||||
|
|
||||||
tstsem: tstsem.o sem.o |
|
||||||
$(CC) -o tstsem sem.o tstsem.o
|
|
||||||
|
|
||||||
tstshm: tstshm.o shm.o |
|
||||||
$(CC) -o tstshm shm.o tstshm.o
|
|
||||||
|
|
||||||
depend dep: |
|
||||||
$(CC) -MM $(CFLAGS) *.c >depend
|
|
||||||
|
|
||||||
clean: |
|
||||||
rm -f SUBSYS.o $(OBJS) tstsem tstsem.o tstshm tstshm.o
|
|
||||||
|
|
||||||
ifeq (depend,$(wildcard depend)) |
|
||||||
include depend |
|
||||||
endif |
|
@ -1,31 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* ipc.h |
|
||||||
* System V IPC Emulation |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/qnx4/ipc.h,v 1.7 2003/11/29 19:51:54 pgsql Exp $ |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef _SYS_IPC_H |
|
||||||
#define _SYS_IPC_H |
|
||||||
|
|
||||||
/* Common IPC definitions. */ |
|
||||||
/* Mode bits. */ |
|
||||||
#define IPC_CREAT 0001000 /* create entry if key doesn't exist */ |
|
||||||
#define IPC_EXCL 0002000 /* fail if key exists */ |
|
||||||
#define IPC_NOWAIT 0004000 /* error if request must wait */ |
|
||||||
|
|
||||||
/* Keys. */ |
|
||||||
#define IPC_PRIVATE (key_t)0 /* private key */ |
|
||||||
|
|
||||||
/* Control Commands. */ |
|
||||||
#define IPC_RMID 0 /* remove identifier */ |
|
||||||
#define IPC_STAT 1 /* get shm status */ |
|
||||||
|
|
||||||
#endif /* _SYS_IPC_H */ |
|
@ -1,29 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* isnan.c |
|
||||||
* isnan() implementation |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/qnx4/isnan.c,v 1.5 2004/03/15 03:29:22 tgl Exp $ |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "c.h" |
|
||||||
|
|
||||||
#include <math.h> |
|
||||||
|
|
||||||
#ifndef __nan_bytes |
|
||||||
#define __nan_bytes { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } |
|
||||||
#endif /* __nan_bytes */ |
|
||||||
|
|
||||||
static unsigned char __nan[8] = __nan_bytes; |
|
||||||
|
|
||||||
int |
|
||||||
isnan(double dsrc) |
|
||||||
{ |
|
||||||
return memcmp(&dsrc, __nan, sizeof(double)) == 0; |
|
||||||
} |
|
@ -1,396 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* sem.c |
|
||||||
* System V Semaphore Emulation |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/qnx4/sem.c,v 1.13 2005/10/15 02:49:23 momjian Exp $ |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "postgres.h" |
|
||||||
|
|
||||||
#include <errno.h> |
|
||||||
#include <semaphore.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/sem.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
|
|
||||||
#include "miscadmin.h" |
|
||||||
#include "storage/ipc.h" |
|
||||||
#include "storage/proc.h" |
|
||||||
|
|
||||||
|
|
||||||
#define SEMMAX (PROC_NSEMS_PER_SET+1) |
|
||||||
#define OPMAX 8 |
|
||||||
|
|
||||||
#define MODE 0700 |
|
||||||
#define SHM_INFO_NAME "PgSysV_Sem_Info" |
|
||||||
|
|
||||||
|
|
||||||
struct pending_ops |
|
||||||
{ |
|
||||||
int op[OPMAX]; /* array of pending operations */ |
|
||||||
int idx; /* index of first free array member */ |
|
||||||
}; |
|
||||||
|
|
||||||
struct sem_set_info |
|
||||||
{ |
|
||||||
key_t key; |
|
||||||
int nsems; |
|
||||||
sem_t sem[SEMMAX]; /* array of POSIX semaphores */ |
|
||||||
struct sem semV[SEMMAX]; /* array of System V semaphore structures */ |
|
||||||
struct pending_ops pendingOps[SEMMAX]; /* array of pending operations */ |
|
||||||
}; |
|
||||||
|
|
||||||
struct sem_info |
|
||||||
{ |
|
||||||
sem_t sem; |
|
||||||
int nsets; |
|
||||||
/* there are actually nsets of these: */ |
|
||||||
struct sem_set_info set[1]; /* VARIABLE LENGTH ARRAY */ |
|
||||||
}; |
|
||||||
|
|
||||||
static struct sem_info *SemInfo = (struct sem_info *) - 1; |
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
|
||||||
* semclean - remove the shared memory file on exit |
|
||||||
* only called by the process which created the shm file |
|
||||||
* ---------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
static void |
|
||||||
semclean(void) |
|
||||||
{ |
|
||||||
remove("/dev/shmem/" SHM_INFO_NAME); |
|
||||||
} |
|
||||||
|
|
||||||
int |
|
||||||
semctl(int semid, int semnum, int cmd, /* ... */ union semun arg) |
|
||||||
{ |
|
||||||
int r = 0; |
|
||||||
|
|
||||||
sem_wait(&SemInfo->sem); |
|
||||||
|
|
||||||
if (semid < 0 || semid >= SemInfo->nsets || |
|
||||||
semnum < 0 || semnum >= SemInfo->set[semid].nsems) |
|
||||||
{ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = EINVAL; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
switch (cmd) |
|
||||||
{ |
|
||||||
case GETNCNT: |
|
||||||
r = SemInfo->set[semid].semV[semnum].semncnt; |
|
||||||
break; |
|
||||||
|
|
||||||
case GETPID: |
|
||||||
r = SemInfo->set[semid].semV[semnum].sempid; |
|
||||||
break; |
|
||||||
|
|
||||||
case GETVAL: |
|
||||||
r = SemInfo->set[semid].semV[semnum].semval; |
|
||||||
break; |
|
||||||
|
|
||||||
case GETALL: |
|
||||||
for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++) |
|
||||||
arg.array[semnum] = SemInfo->set[semid].semV[semnum].semval; |
|
||||||
break; |
|
||||||
|
|
||||||
case SETVAL: |
|
||||||
SemInfo->set[semid].semV[semnum].semval = arg.val; |
|
||||||
break; |
|
||||||
|
|
||||||
case SETALL: |
|
||||||
for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++) |
|
||||||
SemInfo->set[semid].semV[semnum].semval = arg.array[semnum]; |
|
||||||
break; |
|
||||||
|
|
||||||
case GETZCNT: |
|
||||||
r = SemInfo->set[semid].semV[semnum].semzcnt; |
|
||||||
break; |
|
||||||
|
|
||||||
case IPC_RMID: |
|
||||||
for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++) |
|
||||||
{ |
|
||||||
if (sem_destroy(&SemInfo->set[semid].sem[semnum]) == -1) |
|
||||||
r = -1; |
|
||||||
} |
|
||||||
SemInfo->set[semid].key = -1; |
|
||||||
SemInfo->set[semid].nsems = 0; |
|
||||||
break; |
|
||||||
|
|
||||||
default: |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = EINVAL; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
|
|
||||||
return r; |
|
||||||
} |
|
||||||
|
|
||||||
int |
|
||||||
semget(key_t key, int nsems, int semflg) |
|
||||||
{ |
|
||||||
int fd, |
|
||||||
semid, |
|
||||||
semnum, |
|
||||||
nsets; |
|
||||||
int exist = 0; |
|
||||||
Size sem_info_size; |
|
||||||
struct stat statbuf; |
|
||||||
|
|
||||||
if (nsems < 0 || nsems > SEMMAX) |
|
||||||
{ |
|
||||||
errno = EINVAL; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
/* open and map shared memory */ |
|
||||||
if (SemInfo == (struct sem_info *) - 1) |
|
||||||
{ |
|
||||||
/* test if the shared memory already exists */ |
|
||||||
fd = shm_open(SHM_INFO_NAME, O_RDWR | O_CREAT | O_EXCL, MODE); |
|
||||||
if (fd == -1 && errno == EEXIST) |
|
||||||
{ |
|
||||||
exist = 1; |
|
||||||
fd = shm_open(SHM_INFO_NAME, O_RDWR | O_CREAT, MODE); |
|
||||||
} |
|
||||||
if (fd == -1) |
|
||||||
return fd; |
|
||||||
/* The size may only be set once. Ignore errors. */ |
|
||||||
nsets = PROC_SEM_MAP_ENTRIES(MaxBackends); |
|
||||||
sem_info_size = sizeof(struct sem_info) + (nsets - 1) * sizeof(struct sem_set_info); |
|
||||||
ltrunc(fd, sem_info_size, SEEK_SET); |
|
||||||
if (fstat(fd, &statbuf)) /* would be strange : the only doc'ed */ |
|
||||||
{ /* error is EBADF */ |
|
||||||
close(fd); |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* size is rounded by proc to the next __PAGESIZE |
|
||||||
*/ |
|
||||||
if (statbuf.st_size != |
|
||||||
(((sem_info_size / __PAGESIZE) + 1) * __PAGESIZE)) |
|
||||||
{ |
|
||||||
fprintf(stderr, |
|
||||||
"Found a pre-existing shared memory block for the semaphore memory\n" |
|
||||||
"of a different size (%ld instead %ld). Make sure that all executables\n" |
|
||||||
"are from the same release or remove the file \"/dev/shmem/%s\"\n" |
|
||||||
"left by a previous version.\n", |
|
||||||
(long) statbuf.st_size, |
|
||||||
(long) sem_info_size, |
|
||||||
SHM_INFO_NAME); |
|
||||||
errno = EACCES; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
SemInfo = mmap(NULL, sem_info_size, |
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
|
||||||
if (SemInfo == MAP_FAILED) |
|
||||||
return -1; |
|
||||||
if (!exist) |
|
||||||
{ |
|
||||||
/* initialize shared memory */ |
|
||||||
memset(SemInfo, 0, sem_info_size); |
|
||||||
SemInfo->nsets = nsets; |
|
||||||
for (semid = 0; semid < nsets; semid++) |
|
||||||
SemInfo->set[semid].key = -1; |
|
||||||
/* create semaphore for locking */ |
|
||||||
sem_init(&SemInfo->sem, 1, 1); |
|
||||||
on_proc_exit(semclean, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
sem_wait(&SemInfo->sem); |
|
||||||
nsets = SemInfo->nsets; |
|
||||||
|
|
||||||
if (key != IPC_PRIVATE) |
|
||||||
{ |
|
||||||
/* search existing element */ |
|
||||||
semid = 0; |
|
||||||
while (semid < nsets && SemInfo->set[semid].key != key) |
|
||||||
semid++; |
|
||||||
if (!(semflg & IPC_CREAT) && semid >= nsets) |
|
||||||
{ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = ENOENT; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
else if (semid < nsets) |
|
||||||
{ |
|
||||||
if (semflg & IPC_CREAT && semflg & IPC_EXCL) |
|
||||||
{ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = EEXIST; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
if (nsems != 0 && SemInfo->set[semid].nsems < nsems) |
|
||||||
{ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = EINVAL; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
return semid; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* search first free element */ |
|
||||||
semid = 0; |
|
||||||
while (semid < nsets && SemInfo->set[semid].key != -1) |
|
||||||
semid++; |
|
||||||
if (semid >= nsets) |
|
||||||
{ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = ENOSPC; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
for (semnum = 0; semnum < nsems; semnum++) |
|
||||||
{ |
|
||||||
sem_init(&SemInfo->set[semid].sem[semnum], 1, 0); |
|
||||||
/* Currently sem_init always returns -1. */ |
|
||||||
#ifdef NOT_USED |
|
||||||
if (sem_init(&SemInfo->set[semid].sem[semnum], 1, 0) == -1) |
|
||||||
{ |
|
||||||
int semnum1; |
|
||||||
|
|
||||||
for (semnum1 = 0; semnum1 < semnum; semnum1++) |
|
||||||
sem_destroy(&SemInfo->set[semid].sem[semnum1]); |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
return -1; |
|
||||||
} |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
SemInfo->set[semid].key = key; |
|
||||||
SemInfo->set[semid].nsems = nsems; |
|
||||||
|
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
|
|
||||||
return semid; |
|
||||||
} |
|
||||||
|
|
||||||
int |
|
||||||
semop(int semid, struct sembuf * sops, size_t nsops) |
|
||||||
{ |
|
||||||
int i, |
|
||||||
r = 0, |
|
||||||
r1, |
|
||||||
errno1 = 0, |
|
||||||
op; |
|
||||||
|
|
||||||
sem_wait(&SemInfo->sem); |
|
||||||
|
|
||||||
if (semid < 0 || semid >= SemInfo->nsets) |
|
||||||
{ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = EINVAL; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
for (i = 0; i < nsops; i++) |
|
||||||
{ |
|
||||||
if ( /* sops[i].sem_num < 0 || */ sops[i].sem_num >= SemInfo->set[semid].nsems) |
|
||||||
{ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = EFBIG; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
for (i = 0; i < nsops; i++) |
|
||||||
{ |
|
||||||
if (sops[i].sem_op < 0) |
|
||||||
{ |
|
||||||
if (SemInfo->set[semid].semV[sops[i].sem_num].semval < -sops[i].sem_op) |
|
||||||
{ |
|
||||||
if (sops[i].sem_flg & IPC_NOWAIT) |
|
||||||
{ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = EAGAIN; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
SemInfo->set[semid].semV[sops[i].sem_num].semncnt++; |
|
||||||
if (SemInfo->set[semid].pendingOps[sops[i].sem_num].idx >= OPMAX) |
|
||||||
{ |
|
||||||
/* pending operations array overflow */ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = ERANGE; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx++] = sops[i].sem_op; |
|
||||||
/* suspend */ |
|
||||||
sem_post(&SemInfo->sem); /* avoid deadlock */ |
|
||||||
r1 = sem_wait(&SemInfo->set[semid].sem[sops[i].sem_num]); |
|
||||||
sem_wait(&SemInfo->sem); |
|
||||||
if (r1) |
|
||||||
{ |
|
||||||
errno1 = errno; |
|
||||||
r = r1; |
|
||||||
/* remove pending operation */ |
|
||||||
SemInfo->set[semid].pendingOps[sops[i].sem_num].op[--SemInfo->set[semid].pendingOps[sops[i].sem_num].idx] = 0; |
|
||||||
} |
|
||||||
else |
|
||||||
SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op; |
|
||||||
SemInfo->set[semid].semV[sops[i].sem_num].semncnt--; |
|
||||||
} |
|
||||||
else |
|
||||||
SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op; |
|
||||||
} |
|
||||||
else if (sops[i].sem_op > 0) |
|
||||||
{ |
|
||||||
SemInfo->set[semid].semV[sops[i].sem_num].semval += sops[i].sem_op; |
|
||||||
op = sops[i].sem_op; |
|
||||||
while (op > 0 && SemInfo->set[semid].pendingOps[sops[i].sem_num].idx > 0) |
|
||||||
{ /* operations pending */ |
|
||||||
if (SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx - 1] + op >= 0) |
|
||||||
{ |
|
||||||
/* unsuspend processes */ |
|
||||||
if (sem_post(&SemInfo->set[semid].sem[sops[i].sem_num])) |
|
||||||
{ |
|
||||||
errno1 = errno; |
|
||||||
r = -1; |
|
||||||
} |
|
||||||
/* adjust pending operations */ |
|
||||||
op += SemInfo->set[semid].pendingOps[sops[i].sem_num].op[--SemInfo->set[semid].pendingOps[sops[i].sem_num].idx]; |
|
||||||
SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx] = 0; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
/* adjust pending operations */ |
|
||||||
SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx - 1] += op; |
|
||||||
op = 0; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
/* sops[i].sem_op == 0 */ |
|
||||||
{ |
|
||||||
/* not supported */ |
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
errno = ENOSYS; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
SemInfo->set[semid].semV[sops[i].sem_num].sempid = getpid(); |
|
||||||
} |
|
||||||
|
|
||||||
sem_post(&SemInfo->sem); |
|
||||||
|
|
||||||
errno = errno1; |
|
||||||
return r; |
|
||||||
} |
|
@ -1,68 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* sem.h |
|
||||||
* System V Semaphore Emulation |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/qnx4/sem.h,v 1.8 2003/11/29 19:51:54 pgsql Exp $ |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef _SYS_SEM_H |
|
||||||
#define _SYS_SEM_H |
|
||||||
|
|
||||||
#include <sys/ipc.h> |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" |
|
||||||
{ |
|
||||||
#endif |
|
||||||
|
|
||||||
/*
|
|
||||||
* Semctl Command Definitions. |
|
||||||
*/ |
|
||||||
|
|
||||||
#define GETNCNT 3 /* get semncnt */ |
|
||||||
#define GETPID 4 /* get sempid */ |
|
||||||
#define GETVAL 5 /* get semval */ |
|
||||||
#define GETALL 6 /* get all semval's */ |
|
||||||
#define GETZCNT 7 /* get semzcnt */ |
|
||||||
#define SETVAL 8 /* set semval */ |
|
||||||
#define SETALL 9 /* set all semval's */ |
|
||||||
|
|
||||||
/*
|
|
||||||
* There is one semaphore structure for each semaphore in the system. |
|
||||||
*/ |
|
||||||
|
|
||||||
struct sem |
|
||||||
{ |
|
||||||
ushort_t semval; /* semaphore text map address */ |
|
||||||
pid_t sempid; /* pid of last operation */ |
|
||||||
ushort_t semncnt; /* # awaiting semval > cval */ |
|
||||||
ushort_t semzcnt; /* # awaiting semval = 0 */ |
|
||||||
}; |
|
||||||
|
|
||||||
/*
|
|
||||||
* User semaphore template for semop system calls. |
|
||||||
*/ |
|
||||||
|
|
||||||
struct sembuf |
|
||||||
{ |
|
||||||
ushort_t sem_num; /* semaphore # */ |
|
||||||
short sem_op; /* semaphore operation */ |
|
||||||
short sem_flg; /* operation flags */ |
|
||||||
}; |
|
||||||
|
|
||||||
extern int semctl(int semid, int semnum, int cmd, /* ... */ union semun arg); |
|
||||||
extern int semget(key_t key, int nsems, int semflg); |
|
||||||
extern int semop(int semid, struct sembuf * sops, size_t nsops); |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif /* _SYS_SEM_H */ |
|
@ -1,274 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* shm.c |
|
||||||
* System V Shared Memory Emulation |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/qnx4/shm.c,v 1.10 2005/10/15 02:49:23 momjian Exp $ |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "postgres.h" |
|
||||||
|
|
||||||
#include <errno.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/shm.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
|
|
||||||
|
|
||||||
#define MODE 0777 |
|
||||||
|
|
||||||
#define SHMMAX 1024 |
|
||||||
|
|
||||||
|
|
||||||
struct shm_info |
|
||||||
{ |
|
||||||
int shmid; |
|
||||||
key_t key; |
|
||||||
size_t size; |
|
||||||
void *addr; |
|
||||||
}; |
|
||||||
|
|
||||||
static struct shm_info *ShmInfo; |
|
||||||
|
|
||||||
|
|
||||||
static int shm_putinfo(struct shm_info * info); |
|
||||||
static int shm_updinfo(int i, struct shm_info * info); |
|
||||||
static int shm_getinfo(int shmid, struct shm_info * info); |
|
||||||
static int shm_getinfobyaddr(const void *addr, struct shm_info * info); |
|
||||||
|
|
||||||
static char * |
|
||||||
keytoname(key_t key, char *name) |
|
||||||
{ |
|
||||||
sprintf(name, "PgShm%x", key); |
|
||||||
return name; |
|
||||||
} |
|
||||||
|
|
||||||
static int |
|
||||||
shm_putinfo(struct shm_info * info) |
|
||||||
{ |
|
||||||
int i; |
|
||||||
|
|
||||||
if (ShmInfo == NULL) |
|
||||||
{ |
|
||||||
ShmInfo = calloc(SHMMAX, sizeof(struct shm_info)); |
|
||||||
if (ShmInfo == NULL) |
|
||||||
return -1; |
|
||||||
/* initialize ShmInfo */ |
|
||||||
for (i = 0; i < SHMMAX; i++) |
|
||||||
ShmInfo[i].shmid = -1; |
|
||||||
} |
|
||||||
|
|
||||||
/* search first free element */ |
|
||||||
i = 0; |
|
||||||
while (i < SHMMAX && ShmInfo[i].shmid != -1) |
|
||||||
i++; |
|
||||||
if (i >= SHMMAX) |
|
||||||
{ |
|
||||||
errno = ENOSPC; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
memcpy(&ShmInfo[i], info, sizeof(struct shm_info)); |
|
||||||
|
|
||||||
return i; |
|
||||||
} |
|
||||||
|
|
||||||
static int |
|
||||||
shm_updinfo(int i, struct shm_info * info) |
|
||||||
{ |
|
||||||
if (i >= SHMMAX) |
|
||||||
return -1; |
|
||||||
if (ShmInfo == NULL) |
|
||||||
return -1; |
|
||||||
|
|
||||||
memcpy(&ShmInfo[i], info, sizeof(struct shm_info)); |
|
||||||
|
|
||||||
return i; |
|
||||||
} |
|
||||||
|
|
||||||
static int |
|
||||||
shm_getinfo(int shmid, struct shm_info * info) |
|
||||||
{ |
|
||||||
int i; |
|
||||||
|
|
||||||
if (ShmInfo == NULL) |
|
||||||
return -1; |
|
||||||
|
|
||||||
/* search element */ |
|
||||||
i = 0; |
|
||||||
while (i < SHMMAX && ShmInfo[i].shmid != shmid) |
|
||||||
i++; |
|
||||||
if (i >= SHMMAX) |
|
||||||
return -1; |
|
||||||
|
|
||||||
memcpy(info, &ShmInfo[i], sizeof(struct shm_info)); |
|
||||||
|
|
||||||
return i; |
|
||||||
} |
|
||||||
|
|
||||||
static int |
|
||||||
shm_getinfobyaddr(const void *addr, struct shm_info * info) |
|
||||||
{ |
|
||||||
int i; |
|
||||||
|
|
||||||
if (ShmInfo == (struct shm_info *) - 1) |
|
||||||
return -1; |
|
||||||
|
|
||||||
/* search element */ |
|
||||||
i = 0; |
|
||||||
while (i < SHMMAX && ShmInfo[i].addr != addr) |
|
||||||
i++; |
|
||||||
if (i >= SHMMAX) |
|
||||||
return -1; |
|
||||||
|
|
||||||
memcpy(info, &ShmInfo[i], sizeof(struct shm_info)); |
|
||||||
|
|
||||||
return i; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void * |
|
||||||
shmat(int shmid, const void *shmaddr, int shmflg) |
|
||||||
{ |
|
||||||
struct shm_info info; |
|
||||||
int i; |
|
||||||
|
|
||||||
i = shm_getinfo(shmid, &info); |
|
||||||
if (i == -1) |
|
||||||
{ |
|
||||||
errno = EACCES; |
|
||||||
return (void *) -1; |
|
||||||
} |
|
||||||
|
|
||||||
info.addr = mmap((void *) shmaddr, info.size, |
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0); |
|
||||||
if (info.addr == MAP_FAILED) |
|
||||||
return info.addr; |
|
||||||
|
|
||||||
if (shm_updinfo(i, &info) == -1) |
|
||||||
{ |
|
||||||
errno = EACCES; |
|
||||||
return (void *) -1; |
|
||||||
} |
|
||||||
|
|
||||||
return info.addr; |
|
||||||
} |
|
||||||
|
|
||||||
int |
|
||||||
shmdt(const void *addr) |
|
||||||
{ |
|
||||||
struct shm_info info; |
|
||||||
|
|
||||||
if (shm_getinfobyaddr(addr, &info) == -1) |
|
||||||
{ |
|
||||||
errno = EACCES; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
return munmap((void *) addr, info.size); |
|
||||||
} |
|
||||||
|
|
||||||
int |
|
||||||
shmctl(int shmid, int cmd, struct shmid_ds * buf) |
|
||||||
{ |
|
||||||
struct shm_info info; |
|
||||||
char name[NAME_MAX + 1]; |
|
||||||
int result; |
|
||||||
int fd; |
|
||||||
struct stat statbuf; |
|
||||||
|
|
||||||
|
|
||||||
switch (cmd) |
|
||||||
{ |
|
||||||
case IPC_RMID: |
|
||||||
if (shm_getinfo(shmid, &info) == -1) |
|
||||||
{ |
|
||||||
errno = EACCES; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
close(info.shmid); |
|
||||||
keytoname(info.key, name); |
|
||||||
return shm_unlink(name); |
|
||||||
|
|
||||||
case IPC_STAT: |
|
||||||
|
|
||||||
/*
|
|
||||||
* we have to open it first. stat() does no prefix tracking -> the |
|
||||||
* call would go to fsys instead of proc |
|
||||||
*/ |
|
||||||
keytoname(shmid, name); |
|
||||||
fd = shm_open(name, 0, MODE); |
|
||||||
if (fd >= 0) |
|
||||||
{ |
|
||||||
result = fstat(fd, &statbuf); |
|
||||||
|
|
||||||
/*
|
|
||||||
* if the file exists, subtract 2 from linkcount : one for our |
|
||||||
* own open and one for the dir entry |
|
||||||
*/ |
|
||||||
if (!result) |
|
||||||
buf->shm_nattch = statbuf.st_nlink - 2; |
|
||||||
close(fd); |
|
||||||
return result; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
/*
|
|
||||||
* if there's no entry for this key it doesn't matter the next |
|
||||||
* shmget() would get a different shm anyway |
|
||||||
*/ |
|
||||||
buf->shm_nattch = 0; |
|
||||||
return 0; |
|
||||||
} |
|
||||||
} |
|
||||||
errno = EINVAL; |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
int |
|
||||||
shmget(key_t key, size_t size, int flags) |
|
||||||
{ |
|
||||||
char name[NAME_MAX + 1]; |
|
||||||
int oflag = 0; |
|
||||||
struct shm_info info; |
|
||||||
|
|
||||||
if (flags & IPC_CREAT) |
|
||||||
oflag |= O_CREAT; |
|
||||||
if (flags & IPC_EXCL) |
|
||||||
oflag |= O_EXCL; |
|
||||||
if (flags & SHM_R) |
|
||||||
{ |
|
||||||
if (flags & SHM_W) |
|
||||||
oflag |= O_RDWR; |
|
||||||
else |
|
||||||
oflag |= O_RDONLY; |
|
||||||
} |
|
||||||
info.shmid = shm_open(keytoname(key, name), oflag, MODE); |
|
||||||
|
|
||||||
/* store shared memory information */ |
|
||||||
if (info.shmid != -1) |
|
||||||
{ |
|
||||||
info.key = key; |
|
||||||
info.size = size; |
|
||||||
info.addr = NULL; |
|
||||||
if (shm_putinfo(&info) == -1) |
|
||||||
{ |
|
||||||
close(info.shmid); |
|
||||||
if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) |
|
||||||
shm_unlink(name); |
|
||||||
return -1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* The size may only be set once. Ignore errors. */ |
|
||||||
ltrunc(info.shmid, size, SEEK_SET); |
|
||||||
|
|
||||||
return info.shmid; |
|
||||||
} |
|
@ -1,43 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* shm.h |
|
||||||
* System V Shared Memory Emulation |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/qnx4/shm.h,v 1.8 2003/11/29 19:51:54 pgsql Exp $ |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef _SYS_SHM_H |
|
||||||
#define _SYS_SHM_H |
|
||||||
|
|
||||||
#include <sys/ipc.h> |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" |
|
||||||
{ |
|
||||||
#endif |
|
||||||
|
|
||||||
#define SHM_R 0400 /* read permission */ |
|
||||||
#define SHM_W 0200 /* write permission */ |
|
||||||
|
|
||||||
struct shmid_ds |
|
||||||
{ |
|
||||||
int dummy; |
|
||||||
int shm_nattch; |
|
||||||
}; |
|
||||||
|
|
||||||
extern void *shmat(int shmid, const void *shmaddr, int shmflg); |
|
||||||
extern int shmdt(const void *addr); |
|
||||||
extern int shmctl(int shmid, int cmd, struct shmid_ds * buf); |
|
||||||
extern int shmget(key_t key, size_t size, int flags); |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif /* _SYS_SHM_H */ |
|
@ -1,206 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* tstsem.c |
|
||||||
* Test of System V Semaphore Emulation |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/qnx4/tstsem.c,v 1.10 2003/11/29 19:51:54 pgsql Exp $ |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "postgres.h" |
|
||||||
|
|
||||||
#include <signal.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include "storage/ipc.h" |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/sem.h> |
|
||||||
|
|
||||||
|
|
||||||
#define SEMMAX 16 |
|
||||||
#define OPSMAX 1 |
|
||||||
|
|
||||||
int MaxBackends = SEMMAX; |
|
||||||
|
|
||||||
static int semid; |
|
||||||
|
|
||||||
static void |
|
||||||
sig_handler(int sig_no) |
|
||||||
{ |
|
||||||
union semun arg; |
|
||||||
int i = semctl(semid, 0, GETNCNT, arg); |
|
||||||
|
|
||||||
if (i == -1) |
|
||||||
perror("semctl"); |
|
||||||
else |
|
||||||
printf("semval = %d\n", i); |
|
||||||
} |
|
||||||
|
|
||||||
void on_proc_exit(void (*function) (), Datum arg) |
|
||||||
{ |
|
||||||
atexit(function); |
|
||||||
} |
|
||||||
int |
|
||||||
main(int argc, char **argv) |
|
||||||
{ |
|
||||||
int c, |
|
||||||
errflg = 0; |
|
||||||
char s[80]; |
|
||||||
key_t key = IPC_PRIVATE; |
|
||||||
int nsems = SEMMAX; |
|
||||||
int semflg = 0; |
|
||||||
int unlink = 0; |
|
||||||
int i; |
|
||||||
struct sembuf sops[OPSMAX]; |
|
||||||
u_short array[SEMMAX]; |
|
||||||
union semun arg; |
|
||||||
|
|
||||||
optarg = NULL; |
|
||||||
while (!errflg && (c = getopt(argc, argv, "k:n:cxu")) != -1) |
|
||||||
{ |
|
||||||
switch (c) |
|
||||||
{ |
|
||||||
case 'k': |
|
||||||
key = atoi(optarg); |
|
||||||
break; |
|
||||||
case 'n': |
|
||||||
nsems = atoi(optarg); |
|
||||||
break; |
|
||||||
case 'c': |
|
||||||
semflg |= IPC_CREAT; |
|
||||||
break; |
|
||||||
case 'x': |
|
||||||
semflg |= IPC_EXCL; |
|
||||||
break; |
|
||||||
case 'u': |
|
||||||
unlink = 1; |
|
||||||
break; |
|
||||||
default: |
|
||||||
errflg++; |
|
||||||
} |
|
||||||
} |
|
||||||
if (errflg) |
|
||||||
{ |
|
||||||
printf("usage: tstsem [-k key] [-n nsems] [-cxu]\n"); |
|
||||||
exit(1); |
|
||||||
} |
|
||||||
|
|
||||||
if (unlink) |
|
||||||
{ |
|
||||||
i = shm_unlink("SysV_Sem_Info"); |
|
||||||
if (i == -1) |
|
||||||
perror("shm_unlink"); |
|
||||||
exit(i); |
|
||||||
} |
|
||||||
|
|
||||||
semid = semget(key, nsems, semflg); |
|
||||||
if (semid == -1) |
|
||||||
{ |
|
||||||
perror("semget"); |
|
||||||
exit(semid); |
|
||||||
} |
|
||||||
|
|
||||||
/* test signal interrupts */ |
|
||||||
signal(SIGTERM, sig_handler); |
|
||||||
|
|
||||||
do |
|
||||||
{ |
|
||||||
printf("(-)sem_op, (+)sem_op, (G)ETVAL, (S)ETVAL, GET(P)ID, GET(A)LL, SETA(L)L, GET(N)CNT, GET(Z)CNT, e(x)it: "); |
|
||||||
scanf("%s", s); |
|
||||||
switch (s[0]) |
|
||||||
{ |
|
||||||
case '-': |
|
||||||
case '+': |
|
||||||
sops[0].sem_num = 0; |
|
||||||
sops[0].sem_op = atoi(s); |
|
||||||
if (sops[0].sem_op == 0) |
|
||||||
sops[0].sem_op = s[0] == '+' ? +1 : -1; |
|
||||||
sops[0].sem_flg = 0; |
|
||||||
if (semop(semid, sops, 1) == -1) |
|
||||||
perror("semop"); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'G': |
|
||||||
case 'g': |
|
||||||
i = semctl(semid, 0, GETVAL, arg); |
|
||||||
if (i == -1) |
|
||||||
perror("semctl"); |
|
||||||
else |
|
||||||
printf("semval = %d\n", i); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'S': |
|
||||||
case 's': |
|
||||||
printf("semval = "); |
|
||||||
scanf("%d", &arg.val); |
|
||||||
if (semctl(semid, 0, SETVAL, arg) == -1) |
|
||||||
perror("semctl"); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'P': |
|
||||||
case 'p': |
|
||||||
i = semctl(semid, 0, GETPID, arg); |
|
||||||
if (i == -1) |
|
||||||
perror("semctl"); |
|
||||||
else |
|
||||||
printf("PID = %d\n", i); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'A': |
|
||||||
case 'a': |
|
||||||
arg.array = array; |
|
||||||
i = semctl(semid, 0, GETALL, arg); |
|
||||||
if (i == -1) |
|
||||||
perror("semctl"); |
|
||||||
else |
|
||||||
{ |
|
||||||
for (i = 0; i < nsems; i++) |
|
||||||
printf("semval[%d] = %hu\n", i, arg.array[i]); |
|
||||||
} |
|
||||||
break; |
|
||||||
|
|
||||||
case 'L': |
|
||||||
case 'l': |
|
||||||
arg.array = array; |
|
||||||
for (i = 0; i < nsems; i++) |
|
||||||
{ |
|
||||||
printf("semval[%d] = ", i); |
|
||||||
scanf("%hu", &arg.array[i]); |
|
||||||
} |
|
||||||
if (semctl(semid, 0, SETALL, arg) == -1) |
|
||||||
perror("semctl"); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'N': |
|
||||||
case 'n': |
|
||||||
i = semctl(semid, 0, GETNCNT, arg); |
|
||||||
if (i == -1) |
|
||||||
perror("semctl"); |
|
||||||
else |
|
||||||
printf("semval = %d\n", i); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'Z': |
|
||||||
case 'z': |
|
||||||
i = semctl(semid, 0, GETZCNT, arg); |
|
||||||
if (i == -1) |
|
||||||
perror("semctl"); |
|
||||||
else |
|
||||||
printf("semval = %d\n", i); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
while (s[0] != 'x'); |
|
||||||
|
|
||||||
if (semctl(semid, 0, IPC_RMID, arg) == -1) |
|
||||||
{ |
|
||||||
perror("semctl"); |
|
||||||
exit(-1); |
|
||||||
} |
|
||||||
|
|
||||||
exit(0); |
|
||||||
} |
|
@ -1,98 +0,0 @@ |
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* tstshm.c |
|
||||||
* Test of System V Shared Memory Emulation |
|
||||||
* |
|
||||||
* Copyright (c) 1999, repas AEG Automation GmbH |
|
||||||
* |
|
||||||
* |
|
||||||
* IDENTIFICATION |
|
||||||
* $PostgreSQL: pgsql/src/backend/port/qnx4/tstshm.c,v 1.5 2003/11/29 19:51:54 pgsql Exp $ |
|
||||||
* |
|
||||||
*------------------------------------------------------------------------- |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "postgres.h" |
|
||||||
|
|
||||||
#include <unistd.h> |
|
||||||
#include <sys/shm.h> |
|
||||||
|
|
||||||
|
|
||||||
int |
|
||||||
main(int argc, char **argv) |
|
||||||
{ |
|
||||||
int c, |
|
||||||
errflg = 0; |
|
||||||
char s[80]; |
|
||||||
key_t key = 0x1000; |
|
||||||
size_t size = 256; |
|
||||||
int shmid = -1; |
|
||||||
caddr_t addr = NULL; |
|
||||||
|
|
||||||
optarg = NULL; |
|
||||||
while (!errflg && (c = getopt(argc, argv, "k:s:")) != -1) |
|
||||||
{ |
|
||||||
switch (c) |
|
||||||
{ |
|
||||||
case 'k': |
|
||||||
key = atoi(optarg); |
|
||||||
break; |
|
||||||
case 's': |
|
||||||
size = atoi(optarg); |
|
||||||
break; |
|
||||||
default: |
|
||||||
errflg++; |
|
||||||
} |
|
||||||
} |
|
||||||
if (errflg) |
|
||||||
{ |
|
||||||
printf("usage: tstshm [-k key] [-s size]\n"); |
|
||||||
exit(1); |
|
||||||
} |
|
||||||
|
|
||||||
do |
|
||||||
{ |
|
||||||
printf("shm(g)et, shm(a)t, shm(d)t, shm(c)tl, (w)rite, (r)ead, e(x)it: "); |
|
||||||
scanf("%s", s); |
|
||||||
switch (s[0]) |
|
||||||
{ |
|
||||||
case 'g': |
|
||||||
shmid = shmget(key, size, IPC_CREAT | SHM_R | SHM_W); |
|
||||||
if (shmid == -1) |
|
||||||
perror("shmget"); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'a': |
|
||||||
addr = shmat(shmid, NULL, 0); |
|
||||||
if (addr == (void *) -1) |
|
||||||
perror("shmat"); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'd': |
|
||||||
if (shmdt(addr) == -1) |
|
||||||
perror("shmdt"); |
|
||||||
else |
|
||||||
addr = NULL; |
|
||||||
break; |
|
||||||
|
|
||||||
case 'c': |
|
||||||
if (shmctl(shmid, IPC_RMID, NULL) == -1) |
|
||||||
perror("shmctl"); |
|
||||||
else |
|
||||||
shmid = -1; |
|
||||||
break; |
|
||||||
|
|
||||||
case 'w': |
|
||||||
printf("String to write: "); |
|
||||||
scanf("%s", addr); |
|
||||||
break; |
|
||||||
|
|
||||||
case 'r': |
|
||||||
puts(addr); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
while (s[0] != 'x'); |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
@ -1,16 +0,0 @@ |
|||||||
MK_NO_LORDER= true
|
|
||||||
AR= ar
|
|
||||||
AROPT = cr
|
|
||||||
LD= $(AR)
|
|
||||||
LDREL= $(AROPT)
|
|
||||||
LDOUT=
|
|
||||||
LDFLAGS=
|
|
||||||
|
|
||||||
enable_shared = no
|
|
||||||
DLSUFFIX = .so
|
|
||||||
CFLAGS_SL =
|
|
||||||
|
|
||||||
%$(DLSUFFIX): %.o |
|
||||||
@echo 'cannot make shared object $@ from $<'
|
|
||||||
|
|
||||||
sqlmansect = 7
|
|
@ -1 +0,0 @@ |
|||||||
LIBS="-lunix" |
|
@ -1,391 +0,0 @@ |
|||||||
-- |
|
||||||
-- FLOAT8 |
|
||||||
-- |
|
||||||
CREATE TABLE FLOAT8_TBL(f1 float8); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); |
|
||||||
-- test for underflow and overflow handling |
|
||||||
SELECT '10e400'::float8; |
|
||||||
ERROR: "10e400" is out of range for type double precision |
|
||||||
SELECT '-10e400'::float8; |
|
||||||
ERROR: "-10e400" is out of range for type double precision |
|
||||||
SELECT '10e-400'::float8; |
|
||||||
ERROR: "10e-400" is out of range for type double precision |
|
||||||
SELECT '-10e-400'::float8; |
|
||||||
ERROR: "-10e-400" is out of range for type double precision |
|
||||||
-- bad input |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES (''); |
|
||||||
ERROR: invalid input syntax for type double precision: "" |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES (' '); |
|
||||||
ERROR: invalid input syntax for type double precision: " " |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); |
|
||||||
ERROR: invalid input syntax for type double precision: "xyz" |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); |
|
||||||
ERROR: invalid input syntax for type double precision: "5.0.0" |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); |
|
||||||
ERROR: invalid input syntax for type double precision: "5 . 0" |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); |
|
||||||
ERROR: invalid input syntax for type double precision: "5. 0" |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); |
|
||||||
ERROR: invalid input syntax for type double precision: " - 3" |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); |
|
||||||
ERROR: invalid input syntax for type double precision: "123 5" |
|
||||||
-- special inputs |
|
||||||
SELECT 'NaN'::float8; |
|
||||||
float8 |
|
||||||
-------- |
|
||||||
NaN |
|
||||||
(1 row) |
|
||||||
SELECT 'nan'::float8; |
|
||||||
float8 |
|
||||||
-------- |
|
||||||
NaN |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT ' NAN '::float8; |
|
||||||
float8 |
|
||||||
-------- |
|
||||||
NaN |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT 'infinity'::float8; |
|
||||||
float8 |
|
||||||
---------- |
|
||||||
Infinity |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT ' -INFINiTY '::float8; |
|
||||||
float8 |
|
||||||
----------- |
|
||||||
-Infinity |
|
||||||
(1 row) |
|
||||||
|
|
||||||
-- bad special inputs |
|
||||||
SELECT 'N A N'::float8; |
|
||||||
ERROR: invalid input syntax for type double precision: "N A N" |
|
||||||
SELECT 'NaN x'::float8; |
|
||||||
ERROR: invalid input syntax for type double precision: "NaN x" |
|
||||||
SELECT ' INFINITY x'::float8; |
|
||||||
ERROR: invalid input syntax for type double precision: " INFINITY x" |
|
||||||
SELECT 'Infinity'::float8 + 100.0; |
|
||||||
ERROR: type "double precision" value out of range: overflow |
|
||||||
SELECT 'Infinity'::float8 / 'Infinity'::float8; |
|
||||||
?column? |
|
||||||
---------- |
|
||||||
NaN |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT 'nan'::float8 / 'nan'::float8; |
|
||||||
?column? |
|
||||||
---------- |
|
||||||
NaN |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT '' AS five, * FROM FLOAT8_TBL; |
|
||||||
five | f1 |
|
||||||
------+---------------------- |
|
||||||
| 0 |
|
||||||
| 1004.3 |
|
||||||
| -34.84 |
|
||||||
| 1.2345678901234e+200 |
|
||||||
| 1.2345678901234e-200 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE f.f1 <> '1004.3'; |
|
||||||
four | f1 |
|
||||||
------+---------------------- |
|
||||||
| 0 |
|
||||||
| -34.84 |
|
||||||
| 1.2345678901234e+200 |
|
||||||
| 1.2345678901234e-200 |
|
||||||
(4 rows) |
|
||||||
|
|
||||||
SELECT '' AS one, f.* FROM FLOAT8_TBL f WHERE f.f1 = '1004.3'; |
|
||||||
one | f1 |
|
||||||
-----+-------- |
|
||||||
| 1004.3 |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT '' AS three, f.* FROM FLOAT8_TBL f WHERE '1004.3' > f.f1; |
|
||||||
three | f1 |
|
||||||
-------+---------------------- |
|
||||||
| 0 |
|
||||||
| -34.84 |
|
||||||
| 1.2345678901234e-200 |
|
||||||
(3 rows) |
|
||||||
|
|
||||||
SELECT '' AS three, f.* FROM FLOAT8_TBL f WHERE f.f1 < '1004.3'; |
|
||||||
three | f1 |
|
||||||
-------+---------------------- |
|
||||||
| 0 |
|
||||||
| -34.84 |
|
||||||
| 1.2345678901234e-200 |
|
||||||
(3 rows) |
|
||||||
|
|
||||||
SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE '1004.3' >= f.f1; |
|
||||||
four | f1 |
|
||||||
------+---------------------- |
|
||||||
| 0 |
|
||||||
| 1004.3 |
|
||||||
| -34.84 |
|
||||||
| 1.2345678901234e-200 |
|
||||||
(4 rows) |
|
||||||
|
|
||||||
SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE f.f1 <= '1004.3'; |
|
||||||
four | f1 |
|
||||||
------+---------------------- |
|
||||||
| 0 |
|
||||||
| 1004.3 |
|
||||||
| -34.84 |
|
||||||
| 1.2345678901234e-200 |
|
||||||
(4 rows) |
|
||||||
|
|
||||||
SELECT '' AS three, f.f1, f.f1 * '-10' AS x |
|
||||||
FROM FLOAT8_TBL f |
|
||||||
WHERE f.f1 > '0.0'; |
|
||||||
three | f1 | x |
|
||||||
-------+----------------------+----------------------- |
|
||||||
| 1004.3 | -10043 |
|
||||||
| 1.2345678901234e+200 | -1.2345678901234e+201 |
|
||||||
| 1.2345678901234e-200 | -1.2345678901234e-199 |
|
||||||
(3 rows) |
|
||||||
|
|
||||||
SELECT '' AS three, f.f1, f.f1 + '-10' AS x |
|
||||||
FROM FLOAT8_TBL f |
|
||||||
WHERE f.f1 > '0.0'; |
|
||||||
three | f1 | x |
|
||||||
-------+----------------------+---------------------- |
|
||||||
| 1004.3 | 994.3 |
|
||||||
| 1.2345678901234e+200 | 1.2345678901234e+200 |
|
||||||
| 1.2345678901234e-200 | -10 |
|
||||||
(3 rows) |
|
||||||
|
|
||||||
SELECT '' AS three, f.f1, f.f1 / '-10' AS x |
|
||||||
FROM FLOAT8_TBL f |
|
||||||
WHERE f.f1 > '0.0'; |
|
||||||
three | f1 | x |
|
||||||
-------+----------------------+----------------------- |
|
||||||
| 1004.3 | -100.43 |
|
||||||
| 1.2345678901234e+200 | -1.2345678901234e+199 |
|
||||||
| 1.2345678901234e-200 | -1.2345678901234e-201 |
|
||||||
(3 rows) |
|
||||||
|
|
||||||
SELECT '' AS three, f.f1, f.f1 - '-10' AS x |
|
||||||
FROM FLOAT8_TBL f |
|
||||||
WHERE f.f1 > '0.0'; |
|
||||||
three | f1 | x |
|
||||||
-------+----------------------+---------------------- |
|
||||||
| 1004.3 | 1014.3 |
|
||||||
| 1.2345678901234e+200 | 1.2345678901234e+200 |
|
||||||
| 1.2345678901234e-200 | 10 |
|
||||||
(3 rows) |
|
||||||
|
|
||||||
SELECT '' AS one, f.f1 ^ '2.0' AS square_f1 |
|
||||||
FROM FLOAT8_TBL f where f.f1 = '1004.3'; |
|
||||||
one | square_f1 |
|
||||||
-----+------------ |
|
||||||
| 1008618.49 |
|
||||||
(1 row) |
|
||||||
|
|
||||||
-- absolute value |
|
||||||
SELECT '' AS five, f.f1, @f.f1 AS abs_f1 |
|
||||||
FROM FLOAT8_TBL f; |
|
||||||
five | f1 | abs_f1 |
|
||||||
------+----------------------+---------------------- |
|
||||||
| 0 | 0 |
|
||||||
| 1004.3 | 1004.3 |
|
||||||
| -34.84 | 34.84 |
|
||||||
| 1.2345678901234e+200 | 1.2345678901234e+200 |
|
||||||
| 1.2345678901234e-200 | 1.2345678901234e-200 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
-- truncate |
|
||||||
SELECT '' AS five, f.f1, trunc(f.f1) AS trunc_f1 |
|
||||||
FROM FLOAT8_TBL f; |
|
||||||
five | f1 | trunc_f1 |
|
||||||
------+----------------------+---------------------- |
|
||||||
| 0 | 0 |
|
||||||
| 1004.3 | 1004 |
|
||||||
| -34.84 | -34 |
|
||||||
| 1.2345678901234e+200 | 1.2345678901234e+200 |
|
||||||
| 1.2345678901234e-200 | 0 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
-- round |
|
||||||
SELECT '' AS five, f.f1, round(f.f1) AS round_f1 |
|
||||||
FROM FLOAT8_TBL f; |
|
||||||
five | f1 | round_f1 |
|
||||||
------+----------------------+---------------------- |
|
||||||
| 0 | 0 |
|
||||||
| 1004.3 | 1004 |
|
||||||
| -34.84 | -35 |
|
||||||
| 1.2345678901234e+200 | 1.2345678901234e+200 |
|
||||||
| 1.2345678901234e-200 | 0 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
-- ceil / ceiling |
|
||||||
select ceil(f1) as ceil_f1 from float8_tbl f; |
|
||||||
ceil_f1 |
|
||||||
---------------------- |
|
||||||
0 |
|
||||||
1005 |
|
||||||
-34 |
|
||||||
1.2345678901234e+200 |
|
||||||
1 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
select ceiling(f1) as ceiling_f1 from float8_tbl f; |
|
||||||
ceiling_f1 |
|
||||||
---------------------- |
|
||||||
0 |
|
||||||
1005 |
|
||||||
-34 |
|
||||||
1.2345678901234e+200 |
|
||||||
1 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
-- floor |
|
||||||
select floor(f1) as floor_f1 from float8_tbl f; |
|
||||||
floor_f1 |
|
||||||
---------------------- |
|
||||||
0 |
|
||||||
1004 |
|
||||||
-35 |
|
||||||
1.2345678901234e+200 |
|
||||||
0 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
-- sign |
|
||||||
select sign(f1) as sign_f1 from float8_tbl f; |
|
||||||
sign_f1 |
|
||||||
--------- |
|
||||||
0 |
|
||||||
1 |
|
||||||
-1 |
|
||||||
1 |
|
||||||
1 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
-- square root |
|
||||||
SELECT sqrt(float8 '64') AS eight; |
|
||||||
eight |
|
||||||
------- |
|
||||||
8 |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT |/ float8 '64' AS eight; |
|
||||||
eight |
|
||||||
------- |
|
||||||
8 |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT '' AS three, f.f1, |/f.f1 AS sqrt_f1 |
|
||||||
FROM FLOAT8_TBL f |
|
||||||
WHERE f.f1 > '0.0'; |
|
||||||
three | f1 | sqrt_f1 |
|
||||||
-------+----------------------+----------------------- |
|
||||||
| 1004.3 | 31.6906926399535 |
|
||||||
| 1.2345678901234e+200 | 1.11111110611109e+100 |
|
||||||
| 1.2345678901234e-200 | 1.11111110611109e-100 |
|
||||||
(3 rows) |
|
||||||
|
|
||||||
-- power |
|
||||||
SELECT power(float8 '144', float8 '0.5'); |
|
||||||
power |
|
||||||
------- |
|
||||||
12 |
|
||||||
(1 row) |
|
||||||
|
|
||||||
-- take exp of ln(f.f1) |
|
||||||
SELECT '' AS three, f.f1, exp(ln(f.f1)) AS exp_ln_f1 |
|
||||||
FROM FLOAT8_TBL f |
|
||||||
WHERE f.f1 > '0.0'; |
|
||||||
three | f1 | exp_ln_f1 |
|
||||||
-------+----------------------+----------------------- |
|
||||||
| 1004.3 | 1004.3 |
|
||||||
| 1.2345678901234e+200 | 1.23456789012337e+200 |
|
||||||
| 1.2345678901234e-200 | 1.23456789012338e-200 |
|
||||||
(3 rows) |
|
||||||
|
|
||||||
-- cube root |
|
||||||
SELECT ||/ float8 '27' AS three; |
|
||||||
three |
|
||||||
------- |
|
||||||
3 |
|
||||||
(1 row) |
|
||||||
|
|
||||||
SELECT '' AS five, f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f; |
|
||||||
five | f1 | cbrt_f1 |
|
||||||
------+----------------------+----------------------- |
|
||||||
| 0 | 0 |
|
||||||
| 1004.3 | 10.014312837827 |
|
||||||
| -34.84 | -3.26607421344208 |
|
||||||
| 1.2345678901234e+200 | 4.97933859234757e+066 |
|
||||||
| 1.2345678901234e-200 | 2.3112042409018e-067 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
SELECT '' AS five, * FROM FLOAT8_TBL; |
|
||||||
five | f1 |
|
||||||
------+---------------------- |
|
||||||
| 0 |
|
||||||
| 1004.3 |
|
||||||
| -34.84 |
|
||||||
| 1.2345678901234e+200 |
|
||||||
| 1.2345678901234e-200 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
UPDATE FLOAT8_TBL |
|
||||||
SET f1 = FLOAT8_TBL.f1 * '-1' |
|
||||||
WHERE FLOAT8_TBL.f1 > '0.0'; |
|
||||||
SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f; |
|
||||||
ERROR: type "double precision" value out of range: overflow |
|
||||||
SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f; |
|
||||||
ERROR: result is out of range |
|
||||||
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; |
|
||||||
ERROR: cannot take logarithm of zero |
|
||||||
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; |
|
||||||
ERROR: cannot take logarithm of a negative number |
|
||||||
SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f; |
|
||||||
ERROR: result is out of range |
|
||||||
SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f; |
|
||||||
ERROR: division by zero |
|
||||||
SELECT '' AS five, * FROM FLOAT8_TBL; |
|
||||||
five | f1 |
|
||||||
------+----------------------- |
|
||||||
| 0 |
|
||||||
| -34.84 |
|
||||||
| -1004.3 |
|
||||||
| -1.2345678901234e+200 |
|
||||||
| -1.2345678901234e-200 |
|
||||||
(5 rows) |
|
||||||
|
|
||||||
-- test for over- and underflow |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); |
|
||||||
ERROR: "10e400" is out of range for type double precision |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); |
|
||||||
ERROR: "-10e400" is out of range for type double precision |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); |
|
||||||
ERROR: "10e-400" is out of range for type double precision |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); |
|
||||||
ERROR: "-10e-400" is out of range for type double precision |
|
||||||
-- maintain external table consistency across platforms |
|
||||||
-- delete all values and reinsert well-behaved ones |
|
||||||
DELETE FROM FLOAT8_TBL; |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('0.0'); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('-34.84'); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('-1004.30'); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e+200'); |
|
||||||
INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e-200'); |
|
||||||
SELECT '' AS five, * FROM FLOAT8_TBL; |
|
||||||
five | f1 |
|
||||||
------+----------------------- |
|
||||||
| 0 |
|
||||||
| -34.84 |
|
||||||
| -1004.3 |
|
||||||
| -1.2345678901234e+200 |
|
||||||
| -1.2345678901234e-200 |
|
||||||
(5 rows) |
|
||||||
|
|
@ -1,11 +1,8 @@ |
|||||||
float4/.*-qnx=float4-exp-three-digits |
|
||||||
float4/i.86-pc-mingw32=float4-exp-three-digits |
float4/i.86-pc-mingw32=float4-exp-three-digits |
||||||
float8/i.86-.*-freebsd[234]=float8-small-is-zero |
float8/i.86-.*-freebsd[234]=float8-small-is-zero |
||||||
float8/i.86-.*-openbsd=float8-small-is-zero |
float8/i.86-.*-openbsd=float8-small-is-zero |
||||||
float8/i.86-.*-netbsd=float8-small-is-zero |
float8/i.86-.*-netbsd=float8-small-is-zero |
||||||
float8/m68k-.*-netbsd=float8-small-is-zero |
float8/m68k-.*-netbsd=float8-small-is-zero |
||||||
float8/.*-qnx=float8-exp-three-digits |
|
||||||
float8/i.86-pc-mingw32=float8-exp-three-digits-win32 |
float8/i.86-pc-mingw32=float8-exp-three-digits-win32 |
||||||
float8/i.86-pc-cygwin=float8-small-is-zero |
float8/i.86-pc-cygwin=float8-small-is-zero |
||||||
int8/.*-qnx=int8-exp-three-digits |
|
||||||
int8/i.86-pc-mingw32=int8-exp-three-digits |
int8/i.86-pc-mingw32=int8-exp-three-digits |
||||||
|
Loading…
Reference in new issue