OSDN Git Service

Initial 64-bit integer package.
authorThomas G. Lockhart <lockhart@fourpalms.org>
Sat, 17 May 1997 14:24:09 +0000 (14:24 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Sat, 17 May 1997 14:24:09 +0000 (14:24 +0000)
contrib/int8/Makefile [new file with mode: 0644]
contrib/int8/README [new file with mode: 0644]
contrib/int8/int8.c [new file with mode: 0644]
contrib/int8/int8.source [new file with mode: 0644]
contrib/int8/itest.sql [new file with mode: 0644]

diff --git a/contrib/int8/Makefile b/contrib/int8/Makefile
new file mode 100644 (file)
index 0000000..13528fc
--- /dev/null
@@ -0,0 +1,64 @@
+#-------------------------------------------------------------------------
+#
+# Makefile--
+#    Makefile for Postgres 64-bit integer extensions
+#
+# Thomas G. Lockhart <Thomas.Lockhart@jpl.nasa.gov>
+#
+# This is a first attempt at 64-bit arithmetic for Postgres.
+# It takes advantage of "long long int" support in GNU C on 32-bit machines.
+# The modules are built and installed as user-defined types,
+#  so destination directories are pointing away from the standard
+#  Postgres areas. You will need to modify the paths to fit your machine.
+#
+# On my Linux box, I had to find an extra library for the division function (?).
+# For Alpha boxes, both the DEC and GNU compilers should need "long int" only.
+#
+#-------------------------------------------------------------------------
+
+ifndef PGDIR
+PGDIR= /opt/postgres/current
+endif
+
+SRCDIR= $(PGDIR)/src
+
+include $(SRCDIR)/Makefile.global
+
+# Comment out this re-declaration of LIBDIR
+#  if you are installing as the postgres superuser
+#   into a specific database or into template1.
+LIBDIR= /home/tgl/lib
+
+CFLAGS+= -I$(PGDIR)/include -I$(PGDIR)/src/include -I$(LIBPQDIR)
+
+# This extra library is for the 64-bit division routine on my Linux box
+# and probably will need to be commented-out for most other platforms.
+CLIBS+= /usr/lib/gcc-lib/i486-linux/2.7.2/libgcc.a
+
+TARGETS= int8.sql int8$(DLSUFFIX)
+
+all:   $(TARGETS)
+
+int8$(DLSUFFIX):       int8.o
+       $(CC) -shared -o int8$(DLSUFFIX) int8.o $(CLIBS)
+
+install:
+       $(MAKE) all
+       cp -p int8$(DLSUFFIX) $(LIBDIR)
+
+%.sql: %.source
+       if [ -z "$$USER" ]; then USER=$$LOGNAME; fi; \
+       if [ -z "$$USER" ]; then USER=`whoami`; fi; \
+       if [ -z "$$USER" ]; then echo 'Cannot deduce $$USER.'; exit 1; fi; \
+       rm -f $@; \
+       C=`pwd`; \
+       O=$C; \
+       if [ -d ${LIBDIR} ]; then O=${LIBDIR}; fi; \
+       sed -e "s:_CWD_:$$C:g" \
+           -e "s:_OBJWD_:$$O:g" \
+           -e "s:_DLSUFFIX_:$(DLSUFFIX):g" \
+           -e "s/_USER_/$$USER/g" < $< > $@
+
+clean: 
+       rm -f $(TARGETS) int8.o
+
diff --git a/contrib/int8/README b/contrib/int8/README
new file mode 100644 (file)
index 0000000..7d52370
--- /dev/null
@@ -0,0 +1,101 @@
+                       Postgres int8
+
+Thomas G. Lockhart <Thomas.Lockhart@jpl.nasa.gov>
+
+This is a first attempt at 64-bit integer arithmetic for Postgres. The code
+should support any 64-bit architecture and any 32-bit machine using a recent
+GNU C compiler. At the moment, DEC-Alpha and Linux/gcc are explicitly
+supported. The code uses "long long int" support in GNU C on 32-bit machines.
+This type is an extension to ANSI-C, and may not appear on any other compiler.
+
+The modules are built and installed as user-defined types, so destination
+ directories are pointing away from the standard Postgres areas.
+
+Other compilers and architectures should be supportable, so please let me know 
+what changes were required to run on your machine, and I will fold those into 
+this standard distribution.
+
+Good luck!
+
+                       - Tom
+
+
+                       Installation
+
+You will need to modify the Makefile paths to fit your machine. Since this
+is packaged as a "user-installable" type, the libraries and source code
+can reside outside of the standard Postgres areas.
+
+If you are compiling on a DEC-Alpha, then the code might compile
+and run without change. (I do a lot of code development on Alphas,
+but do not have a Postgres installation to test).
+
+  make
+  make install
+  psql dbname < int8.sql
+
+If you are running gcc on a 32-bit machine, you will probably need to:
+ - remove the extra library reference in the Makefile.
+ - if there are unresolved symbols when you try running, then find
+    the right library. The one I had chosen might be a clue.
+
+If you are not running gcc on a 32-bit machine, you will need to:
+ - redeclare the 64 bit data type.
+ - modify the scanf and printf() arguments to use the appropriate
+    64-bit int arguments.
+
+On my Linux box, I had to find an extra library for the division function.
+For Alpha boxes, both the DEC and GNU compilers should need "long int" only.
+I have a reference to "__alpha" in the C source code, but have not tested it
+ and am not certain that this is the correct pre-defined symbol for that machine.
+
+itest.sql is a small test file which exercises some of the I/O, functions,
+ and boolean operators.
+
+int8:
+       =
+       <>
+       <
+       >
+       <=
+       >=
+
+       -       unary minus
+       +       addition
+       -       subtraction
+       *       multiplication
+       /       division
+
+       int4()  convert to 4-byte integer
+       float8()        convert to double float
+
+Routines defined are:
+
+int64 *int8in(char *str);
+char *int8out(int64 *val);
+
+bool int8eq(int64 *val1, int64 *val2);
+bool int8ne(int64 *val1, int64 *val2);
+bool int8lt(int64 *val1, int64 *val2);
+bool int8gt(int64 *val1, int64 *val2);
+bool int8le(int64 *val1, int64 *val2);
+bool int8ge(int64 *val1, int64 *val2);
+
+bool int84eq(int64 *val1, int32 val2);
+bool int84ne(int64 *val1, int32 val2);
+bool int84lt(int64 *val1, int32 val2);
+bool int84gt(int64 *val1, int32 val2);
+bool int84le(int64 *val1, int32 val2);
+bool int84ge(int64 *val1, int32 val2);
+
+int64 *int8um(int64 *val);
+int64 *int8pl(int64 *val1, int64 *val2);
+int64 *int8mi(int64 *val1, int64 *val2);
+int64 *int8mul(int64 *val1, int64 *val2);
+int64 *int8div(int64 *val1, int64 *val2);
+
+int64 *int48(int32 val);
+int32 int84(int64 *val);
+
+int64 *dtoi8(float8 *val);
+float8 *i8tod(int64 *val);
diff --git a/contrib/int8/int8.c b/contrib/int8/int8.c
new file mode 100644 (file)
index 0000000..93822cb
--- /dev/null
@@ -0,0 +1,361 @@
+/*-------------------------------------------------------------------------
+ *
+ * int8.c--
+ *    Internal 64-bit integer operations
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>     /* for sprintf proto, etc. */
+#include <stdlib.h>    /* for strtod, etc. */
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <math.h>
+#include <float.h>
+#include <limits.h>
+
+#include "postgres.h"
+#include "utils/palloc.h"
+
+#define MAXINT8LEN     25
+
+#define USE_LOCAL_CODE 1
+
+#if defined(__alpha) || defined(__GNUC__)
+#define HAVE_64BIT_INTS 1
+#endif
+
+#ifndef HAVE_64BIT_INTS
+typedef char[8] int64;
+
+#elif defined(__alpha)
+typedef long int int64;
+#define INT64_FORMAT "%ld"
+
+#elif defined(__GNUC__)
+typedef long long int int64;
+#define INT64_FORMAT "%Ld"
+
+#else
+typedef long int int64;
+#define INT64_FORMAT "%ld"
+#endif
+
+int64 *int8in(char *str);
+char *int8out(int64 *val);
+
+bool int8eq(int64 *val1, int64 *val2);
+bool int8ne(int64 *val1, int64 *val2);
+bool int8lt(int64 *val1, int64 *val2);
+bool int8gt(int64 *val1, int64 *val2);
+bool int8le(int64 *val1, int64 *val2);
+bool int8ge(int64 *val1, int64 *val2);
+
+bool int84eq(int64 *val1, int32 val2);
+bool int84ne(int64 *val1, int32 val2);
+bool int84lt(int64 *val1, int32 val2);
+bool int84gt(int64 *val1, int32 val2);
+bool int84le(int64 *val1, int32 val2);
+bool int84ge(int64 *val1, int32 val2);
+
+int64 *int8um(int64 *val);
+int64 *int8pl(int64 *val1, int64 *val2);
+int64 *int8mi(int64 *val1, int64 *val2);
+int64 *int8mul(int64 *val1, int64 *val2);
+int64 *int8div(int64 *val1, int64 *val2);
+
+int64 *int48(int32 val);
+int32 int84(int64 *val);
+#if FALSE
+int64 *int28(int16 val);
+int16 int82(int64 *val);
+#endif
+
+float64 i8tod(int64 *val);
+int64 *dtoi8(float64 val);
+
+#if USE_LOCAL_CODE
+
+#ifndef PALLOC
+#define PALLOC(p) palloc(p)
+#endif
+
+#ifndef PALLOCTYPE
+#define PALLOCTYPE(p) palloc(sizeof(p))
+#endif
+
+#endif
+
+/***********************************************************************
+ **
+ **    Routines for 64-bit integers.
+ **
+ ***********************************************************************/
+
+/*----------------------------------------------------------
+ * Formatting and conversion routines.
+ *---------------------------------------------------------*/
+
+/* int8in()
+ */
+int64 *int8in(char *str)
+{
+    int64 *result = PALLOCTYPE(int64);
+
+#if HAVE_64BIT_INTS
+    if (!PointerIsValid(str))
+       elog (WARN,"Bad (null) int8 external representation",NULL);
+
+    if (sscanf(str, INT64_FORMAT, result) != 1)
+       elog(WARN,"Bad int8 external representation '%s'",str);
+
+#else
+    elog(WARN,"64-bit integers are not supported",NULL);
+    result = NULL;
+#endif
+
+    return(result);
+} /* int8in() */
+
+
+/* int8out()
+ */
+char *int8out(int64 *val)
+{
+    char *result;
+
+    int len;
+    char buf[MAXINT8LEN+1];
+
+#if HAVE_64BIT_INTS
+    if (!PointerIsValid(val))
+       return(NULL);
+
+    if ((len = snprintf( buf, MAXINT8LEN, INT64_FORMAT, *val)) < 0)
+         elog (WARN,"Unable to format int8",NULL);
+
+    result = PALLOC(len+1);
+
+    strcpy(result, buf);
+
+#else
+    elog(WARN,"64-bit integers are not supported",NULL);
+    result = NULL;
+#endif
+
+    return( result);
+} /* int8out() */
+
+
+/*----------------------------------------------------------
+ *  Relational operators for int8s.
+ *---------------------------------------------------------*/
+
+/* int8relop()
+ * Is val1 relop val2?
+ */
+bool int8eq(int64 *val1, int64 *val2)
+{
+    return(*val1 == *val2);
+} /* int8eq() */
+
+bool int8ne(int64 *val1, int64 *val2)
+{
+    return(*val1 != *val2);
+} /* int8ne() */
+
+bool int8lt(int64 *val1, int64 *val2)
+{
+    return(*val1 < *val2);
+} /* int8lt() */
+
+bool int8gt(int64 *val1, int64 *val2)
+{
+    return(*val1 > *val2);
+} /* int8gt() */
+
+bool int8le(int64 *val1, int64 *val2)
+{
+    return(*val1 <= *val2);
+} /* int8le() */
+
+bool int8ge(int64 *val1, int64 *val2)
+{
+    return(*val1 >= *val2);
+} /* int8ge() */
+
+
+/* int84relop()
+ * Is 64-bit val1 relop 32-bit val2?
+ */
+bool int84eq(int64 *val1, int32 val2)
+{
+    return(*val1 == val2);
+} /* int84eq() */
+
+bool int84ne(int64 *val1, int32 val2)
+{
+    return(*val1 != val2);
+} /* int84ne() */
+
+bool int84lt(int64 *val1, int32 val2)
+{
+    return(*val1 < val2);
+} /* int84lt() */
+
+bool int84gt(int64 *val1, int32 val2)
+{
+    return(*val1 > val2);
+} /* int84gt() */
+
+bool int84le(int64 *val1, int32 val2)
+{
+    return(*val1 <= val2);
+} /* int84le() */
+
+bool int84ge(int64 *val1, int32 val2)
+{
+    return(*val1 >= val2);
+} /* int84ge() */
+
+
+/*----------------------------------------------------------
+ *  Arithmetic operators on 64-bit integers.
+ *---------------------------------------------------------*/
+
+int64 *int8um(int64 *val)
+{
+    int64 *result = PALLOCTYPE(int64);
+
+    if (!PointerIsValid(val))
+       return NULL;
+
+    *result = (- *val);
+
+    return(result);
+} /* int8um() */
+
+int64 *int8pl(int64 *val1, int64 *val2)
+{
+    int64 *result = PALLOCTYPE(int64);
+
+    if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
+       return NULL;
+
+    *result = *val1 + *val2;
+
+    return(result);
+} /* int8pl() */
+
+int64 *int8mi(int64 *val1, int64 *val2)
+{
+    int64 *result = PALLOCTYPE(int64);
+
+    if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
+       return NULL;
+
+    *result = *val1 - *val2;
+
+    return(result);
+} /* int8mi() */
+
+int64 *int8mul(int64 *val1, int64 *val2)
+{
+    int64 *result = PALLOCTYPE(int64);
+
+    if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
+       return NULL;
+
+    *result = *val1 * *val2;
+
+    return(result);
+} /* int8mul() */
+
+int64 *int8div(int64 *val1, int64 *val2)
+{
+    int64 *result = PALLOCTYPE(int64);
+
+    if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
+       return NULL;
+
+    *result = *val1 / *val2;
+
+    return(result);
+} /* int8div() */
+
+
+/*----------------------------------------------------------
+ *  Conversion operators.
+ *---------------------------------------------------------*/
+
+int64 *int48(int32 val)
+{
+    int64 *result = PALLOCTYPE(int64);
+
+    *result = val;
+
+    return(result);
+} /* int48() */
+
+int32 int84(int64 *val)
+{
+    int32 result;
+
+    if (!PointerIsValid(val))
+       elog(WARN,"Invalid (null) int64, can't convert int8 to int4",NULL);
+
+    if ((*val < INT_MIN) || (*val > INT_MAX))
+       elog(WARN,"int8 conversion to int4 is out of range",NULL);
+
+    result = *val;
+
+    return(result);
+} /* int84() */
+
+#if FALSE
+int64 *int28(int16 val)
+{
+    int64 *result;
+
+    if (!PointerIsValid(result = PALLOCTYPE(int64)))
+       elog(WARN,"Memory allocation failed, can't convert int8 to int2",NULL);
+
+    *result = val;
+
+    return(result);
+} /* int28() */
+
+int16 int82(int64 *val)
+{
+    int16 result;
+
+    if (!PointerIsValid(val))
+       elog(WARN,"Invalid (null) int8, can't convert to int2",NULL);
+
+    result = *val;
+
+    return(result);
+} /* int82() */
+#endif
+
+float64 i8tod(int64 *val)
+{
+    float64 result = PALLOCTYPE(float64data);
+
+    *result = *val;
+
+    return(result);
+} /* i8tod() */
+
+int64 *dtoi8(float64 val)
+{
+    int64 *result = PALLOCTYPE(int64);
+
+    if ((*val < (-pow(2,64)+1)) || (*val > (pow(2,64)-1)))
+       elog(WARN,"Floating point conversion to int64 is out of range",NULL);
+
+    *result = *val;
+
+    return(result);
+} /* dtoi8() */
+
diff --git a/contrib/int8/int8.source b/contrib/int8/int8.source
new file mode 100644 (file)
index 0000000..3f0e175
--- /dev/null
@@ -0,0 +1,288 @@
+---------------------------------------------------------------------------
+--
+-- int8.sql-
+--    This file defines operators for 64-bit integers.
+--
+---------------------------------------------------------------------------
+
+LOAD '_OBJWD_/int8.so';
+
+CREATE FUNCTION int8in(opaque)
+    RETURNS int8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE FUNCTION int8out(opaque)
+    RETURNS opaque
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE TYPE int8 (
+   internallength = 8,
+   input = int8in,
+   output = int8out
+);
+
+
+-----------------------------
+-- Create operators
+-----------------------------
+
+CREATE FUNCTION int8um(int8)
+    RETURNS int8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR - (
+   rightarg = int8,
+   procedure = int8um
+);
+
+CREATE FUNCTION int8pl(int8,int8)
+    RETURNS int8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR + (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8pl,
+   commutator = +
+);
+
+CREATE FUNCTION int8mi(int8,int8)
+    RETURNS int8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR - (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8mi
+);
+
+CREATE FUNCTION int8mul(int8,int8)
+    RETURNS int8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR * (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8mul,
+   commutator = *
+);
+
+CREATE FUNCTION int8div(int8,int8)
+    RETURNS int8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR / (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8div
+);
+
+--
+-- 64-bit comparison operators
+--
+
+CREATE FUNCTION int8eq(int8,int8)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR = (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8eq,
+   commutator = =
+);
+
+CREATE FUNCTION int8ne(int8,int8)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR <> (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8ne,
+   commutator = <>
+);
+
+CREATE FUNCTION int8lt(int8,int8)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR < (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8lt
+);
+
+CREATE FUNCTION int8gt(int8,int8)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR > (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8gt
+);
+
+CREATE FUNCTION int8le(int8,int8)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR <= (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8le
+);
+
+CREATE FUNCTION int8ge(int8,int8)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR >= (
+   leftarg = int8,
+   rightarg = int8,
+   procedure = int8ge
+);
+
+--
+-- 64-bit/32-bit comparison operators
+--
+
+CREATE FUNCTION int84eq(int8,int4)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR = (
+   leftarg = int8,
+   rightarg = int4,
+   procedure = int84eq,
+   commutator = =
+);
+
+CREATE FUNCTION int84ne(int8,int4)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR <> (
+   leftarg = int8,
+   rightarg = int4,
+   procedure = int84ne,
+   commutator = <>
+);
+
+CREATE FUNCTION int84lt(int8,int4)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR < (
+   leftarg = int8,
+   rightarg = int4,
+   procedure = int84lt
+);
+
+CREATE FUNCTION int84gt(int8,int4)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR > (
+   leftarg = int8,
+   rightarg = int4,
+   procedure = int84gt
+);
+
+CREATE FUNCTION int84le(int8,int4)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR <= (
+   leftarg = int8,
+   rightarg = int4,
+   procedure = int84le
+);
+
+CREATE FUNCTION int84ge(int8,int4)
+    RETURNS bool
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE OPERATOR >= (
+   leftarg = int8,
+   rightarg = int4,
+   procedure = int84ge
+);
+
+--
+-- Conversion functions
+--
+
+CREATE FUNCTION int48(int4)
+    RETURNS int8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE FUNCTION int84(int8)
+    RETURNS int4
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+--CREATE FUNCTION int28(int2)
+--    RETURNS int8
+--    AS '_OBJWD_/int8.so'
+--    LANGUAGE 'c';
+--
+--CREATE FUNCTION int82(int8)
+--    RETURNS int2
+--    AS '_OBJWD_/int8.so'
+--    LANGUAGE 'c';
+
+CREATE FUNCTION i8tod(int8)
+    RETURNS float8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+CREATE FUNCTION dtoi8(float8)
+    RETURNS int8
+    AS '_OBJWD_/int8.so'
+    LANGUAGE 'c';
+
+--
+-- Generic conversion routines
+--
+
+CREATE FUNCTION int8(int4)
+    RETURNS int8
+    AS 'select int48($1)'
+    LANGUAGE 'sql';
+
+CREATE FUNCTION int8(float8)
+    RETURNS int8
+    AS 'select dtoi8($1)'
+    LANGUAGE 'sql';
+
+CREATE FUNCTION float8(int8)
+    RETURNS float8
+    AS 'select i8tod($1)'
+    LANGUAGE 'sql';
+
+CREATE FUNCTION int4(int8)
+    RETURNS int4
+    AS 'select int84($1)'
+    LANGUAGE 'sql';
+
diff --git a/contrib/int8/itest.sql b/contrib/int8/itest.sql
new file mode 100644 (file)
index 0000000..4a6f298
--- /dev/null
@@ -0,0 +1,27 @@
+--
+-- Test int8 64-bit integers.
+--
+drop table qtest;
+create table qtest(q1 int8, q2 int8);
+
+insert into qtest values('123','456');
+insert into qtest values('123','4567890123456789');
+insert into qtest values('4567890123456789','123');
+insert into qtest values('4567890123456789','4567890123456789');
+insert into qtest values('4567890123456789','-4567890123456789');
+
+select * from qtest;
+
+select q1, -q1 as minus from qtest;
+
+select q1, q2, q1 + q2 as plus from qtest;
+select q1, q2, q1 - q2 as minus from qtest;
+select q1, q2, q1 * q2 as multiply from qtest
+ where q1 < 1000 or (q2 > 0 and q2 < 1000);
+--select q1, q2, q1 * q2 as multiply qtest
+-- where q1 < '1000'::int8 or (q2 > '0'::int8 and q2 < '1000'::int8);
+select q1, q2, q1 / q2 as divide from qtest;
+
+select q1, float8(q1) from qtest;
+select q2, float8(q2) from qtest;
+select q1, int8(float8(q1)) from qtest;