Allow optional () after current_user, session_user, user, current_time,

current_timestamp, current_date for ODBC compatibility.

Add more functions to odbc.sql catalog extension, use new CREATE OR
REPLACE FUNCTION.

Document iODBC/unixODBC build options.
This commit is contained in:
Peter Eisentraut 2001-10-09 22:32:33 +00:00
parent 839b9bc011
commit ec5c62874d
5 changed files with 292 additions and 166 deletions

View File

@ -1,4 +1,4 @@
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.60 2001/10/09 18:46:00 petere Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.61 2001/10/09 22:32:32 petere Exp $ -->
<chapter id="installation">
<title><![%standalone-include[<productname>PostgreSQL</>]]>
@ -696,7 +696,25 @@ su - postgres
<term><option>--enable-odbc</option></term>
<listitem>
<para>
Build the ODBC driver package.
Build the ODBC driver.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--with-iodbc</option></term>
<listitem>
<para>
Build the ODBC driver for use with <productname>iODBC</>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--with-unixodbc</option></term>
<listitem>
<para>
Build the ODBC driver for use with <productname>unixODBC</>.
</para>
</listitem>
</varlistentry>
@ -708,10 +726,16 @@ su - postgres
Specifies the directory where the ODBC driver will expect its
<filename>odbcinst.ini</> configuration file. The default is
<filename>/usr/local/pgsql/etc</filename> or whatever you
specified as <option>--sysconfdir</option>. A default file
will be installed there. If you intend to share the
<filename>odbcinst.ini</> file between several ODBC drivers
then you may want to use this option.
specified as <option>--sysconfdir</option>. It should be
arranged that the driver reads the same file as the driver
manager.
</para>
<para>
If either the option <option>--with-iodbc</option> or the
option <option>--with-unixodbc</option> is used, this option
will be ignored because in that case the driver manager
handles the location of the configuration file.
</para>
</listitem>
</varlistentry>

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.24 2001/09/13 15:55:23 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.25 2001/10/09 22:32:32 petere Exp $
-->
<chapter id="odbc">
@ -80,39 +80,69 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.24 2001/09/13 15:55:23
<title>Installation</title>
<para>
The first thing to note about the <productname>psqlODBC</> driver
(or any <acronym>ODBC</> driver) is that there must exist a
<firstterm>driver manager</> on the system where the
<acronym>ODBC</> driver is to be used. There exists a free
<acronym>ODBC</> driver for Unix called
<indexterm><primary>iODBC</primary></indexterm>
<productname>iODBC</> which can be obtained via <ulink
url="http://www.iodbc.org">http://www.iodbc.org</ulink>.
Instructions for installing <productname>iODBC</> are contained in
the <productname>iODBC</> distribution. Having said that, any
driver manager that you can find for your platform should support
the <productname>psqlODBC</> driver, or any other <acronym>ODBC</>
driver for that matter.
In order to make use of an <acronym>ODBC</> driver there must
exist a <firstterm>driver manager</> on the system where the
<acronym>ODBC</> driver is to be used. There are two free
<acronym>ODBC</> driver managers for Unix-like operating systems
known to us: <indexterm><primary>iODBC</primary></indexterm>
<ulink url="http://www.iodbc.org"><productname>iODBC</></ulink>
and <indexterm><primary>unixODBC</primary></indexterm> <ulink
url="http://www.unixodbc.org"><productname>unixODBC</></ulink>.
Instructions for installing these driver managers are to be found
in the respective distribution. Software that provides database
access through <acronym>ODBC</acronym> should provide its own
driver manager (which may well be one of these two). Having said
that, any driver manager that you can find for your platform
should support the <productname>PostgreSQL</> <acronym>ODBC</>
driver, or any other <acronym>ODBC</> driver for that matter.
</para>
<note>
<para>
The <productname>unixODBC</> distribution ships with a
<productname>PostgreSQL</> <acronym>ODBC</> driver of its own,
which is similar to the one contained in the
<productname>PostgreSQL</> distribution. It is up to you which
one you want to use. We plan to coordinate the development of
both drivers better in the future.
</para>
</note>
<para>
To install the <acronym>ODBC</> you simply need to supply the
<option>--enable-odbc</> option to the <filename>configure</>
script when you are building the entire <productname>PostgreSQL</>
distribution. The library will then automatically be built and
installed with the rest of the programs. If you forget that option
or want to build the ODBC driver later you can change into the
directory <filename>src/interfaces/odbc</> and do <literal>make</>
and <literal>make install</> there.
</para>
<para>
To install <productname>psqlODBC</> you simply need to supply the
<option>--enable-odbc</> option to the <filename>configure</> script when you are
building the entire <productname>PostgreSQL</> distribution. The library
and header files will then automatically be built and installed with the
rest of the programs. If you forget that option or want to build the ODBC
driver later you can change into the directory <filename>src/interfaces/odbc</>
and do <literal>make</> and <literal>make install</> there.
It is also possible to build the driver to be specifically tuned
for use with <productname>iODBC</> or <productname>unixODBC</>.
This means in particular that the driver will use the driver
manager's routines to process the configuration files, which is
probably desirable since it creates a more consistent
<acronym>ODBC</> environment on your system. If you want to do
that, then supply the <filename>configure</> options
<option>--with-iodbc</> or <option>--with-unixodbc</> (but not
both).
</para>
<para>
The installation-wide configuration file <filename>odbcinst.ini</> will be
installed into the directory <filename>/usr/local/pgsql/etc/</>, or equivalent,
depending on what <option>--prefix</> and/or <option>--sysconfdir</> options
you supplied to <filename>configure</>. Since this file can also be shared
between different <acronym>ODBC</> drivers you can also install it in a shared
location. To do that, override the location of this file with the
<option>--with-odbcinst</> option.
If you build a <quote>stand-alone</quote> driver (not tied to
<productname>iODBC</> or <productname>unixODBC</>), then you can
specify where the driver should look for the configuration file
<filename>odbcinst.ini</>. By default it will be the directory
<filename>/usr/local/pgsql/etc/</>, or equivalent, depending on
what <option>--prefix</> and/or <option>--sysconfdir</> options
you supplied to <filename>configure</>. To select a specific
location outside the <productname>PostgreSQL</> installation
layout, use the <option>--with-odbcinst</> option. To be most
useful, it should be arranged that the driver and the driver
manager read the same configuration file.
</para>
<para>
@ -125,20 +155,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.24 2001/09/13 15:55:23
psql -d template1 -f <replaceable>LOCATION</>/odbc.sql
</programlisting>
where specifying <literal>template1</literal> as the target
database will ensure that all subsequent new databases will
have these same definitions.
database will ensure that all subsequent new databases will have
these same definitions. If for any reason you want to remove
these functions again, run the file
<filename>odbc-drop.sql</filename> through
<command>psql</command>.
</para>
<sect2>
<title>Supported Platforms</title>
<para>
<productname>psqlODBC</productname> has been built and tested
on <systemitem class="osname">Linux</>. There have been reports of success
with <systemitem class="osname">FreeBSD</> and with <systemitem class="osname">Solaris</>. There are no known restrictions
on the basic code for other platforms which already support
<productname>Postgres</productname>.
</para>
</sect2>
</sect1>
<sect1 id="odbc-config">

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.260 2001/10/08 18:16:59 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.261 2001/10/09 22:32:32 petere Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -237,6 +237,7 @@ static void doNegateFloat(Value *v);
%type <list> row_descriptor, row_list, in_expr_nodes
%type <node> row_expr
%type <node> case_expr, case_arg, when_clause, case_default
%type <boolean> opt_empty_parentheses
%type <list> when_clause_list
%type <ival> sub_type
%type <list> OptCreateAs, CreateAsList
@ -4894,7 +4895,7 @@ c_expr: attr
n->agg_distinct = FALSE;
$$ = (Node *)n;
}
| CURRENT_DATE
| CURRENT_DATE opt_empty_parentheses
{
/*
* Translate as "date('now'::text)".
@ -4927,7 +4928,7 @@ c_expr: attr
$$ = (Node *)makeTypeCast((Node *)s, d);
}
| CURRENT_TIME
| CURRENT_TIME opt_empty_parentheses
{
/*
* Translate as "timetz('now'::text)".
@ -4978,7 +4979,7 @@ c_expr: attr
$$ = (Node *)makeTypeCast((Node *)s, d);
}
| CURRENT_TIMESTAMP
| CURRENT_TIMESTAMP opt_empty_parentheses
{
/*
* Translate as "timestamptz('now'::text)".
@ -5032,7 +5033,7 @@ c_expr: attr
$$ = (Node *)makeTypeCast((Node *)s, d);
}
| CURRENT_USER
| CURRENT_USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "current_user";
@ -5041,7 +5042,7 @@ c_expr: attr
n->agg_distinct = FALSE;
$$ = (Node *)n;
}
| SESSION_USER
| SESSION_USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "session_user";
@ -5050,7 +5051,7 @@ c_expr: attr
n->agg_distinct = FALSE;
$$ = (Node *)n;
}
| USER
| USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "current_user";
@ -5386,6 +5387,8 @@ attrs: attr_name
{ $$ = lappend($1, makeString("*")); }
;
opt_empty_parentheses: '(' ')' { $$ = TRUE; }
| /*EMPTY*/ { $$ = TRUE; }
/*****************************************************************************
*

View File

@ -2,7 +2,7 @@
#
# GNUMakefile for psqlodbc (Postgres ODBC driver)
#
# $Header: /cvsroot/pgsql/src/interfaces/odbc/Attic/GNUmakefile,v 1.21 2001/09/23 13:32:24 petere Exp $
# $Header: /cvsroot/pgsql/src/interfaces/odbc/Attic/GNUmakefile,v 1.22 2001/10/09 22:32:33 petere Exp $
#
#-------------------------------------------------------------------------
@ -43,7 +43,7 @@ OBJS += gpps.o
override CPPFLAGS += -DODBCINSTDIR='"$(odbcinst_ini_dir)"'
endif
all: all-lib
all: all-lib odbc-drop.sql
# Shared library stuff
include $(top_srcdir)/src/Makefile.shlib
@ -53,16 +53,20 @@ include $(top_srcdir)/src/Makefile.shlib
# names and we don't want those. (This issue is probably ELF specific.)
LINK.shared += $(shlib_symbolic)
odbc-drop.sql: odbc.sql
sed -n '/^CREATE OR REPLACE FUNCTION/s/CREATE OR REPLACE FUNCTION \([^ (][^ (]*([^)]*)\).*/DROP FUNCTION \1;/p' $< >$@
install: all installdirs
$(INSTALL_DATA) $(srcdir)/odbc.sql $(DESTDIR)$(datadir)/odbc.sql
$(INSTALL_DATA) odbc-drop.sql $(DESTDIR)$(datadir)/odbc-drop.sql
$(MAKE) install-lib
installdirs:
$(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(datadir)
uninstall: uninstall-lib
rm -f $(DESTDIR)$(datadir)/odbc.sql
rm -f $(DESTDIR)$(datadir)/odbc.sql $(DESTDIR)$(datadir)/odbc-drop.sql
clean distclean maintainer-clean: clean-lib
rm -f $(OBJS)
rm -f odbc-drop.sql

View File

@ -1,139 +1,212 @@
-- PostgreSQL catalog extensions for ODBC compliance
-- $Header: /cvsroot/pgsql/src/interfaces/odbc/Attic/odbc.sql,v 1.1 2000/09/18 20:11:37 petere Exp $
-- PostgreSQL catalog extensions for ODBC compatibility
-- $Header: /cvsroot/pgsql/src/interfaces/odbc/Attic/odbc.sql,v 1.2 2001/10/09 22:32:33 petere Exp $
-- ODBC functions are described here:
-- <http://msdn.microsoft.com/library/en-us/odbc/htm/odbcscalar_functions.asp>
-- Note: If we format this file consistently we can automatically
-- generate a corresponding "drop script". Start "CREATE" in the first
-- column, and keep everything up to and including the argument list on
-- the same line. See also the makefile rule.
-- In the current driver, ODBC functions must map directly into a
-- Postgres function. So in some cases we must create a compatible
-- function.
-- truncate on the left
CREATE FUNCTION ltrunc(text, integer)
RETURNS text
AS 'SELECT substring($1 FROM 1 FOR $2)'
LANGUAGE 'SQL';
-- truncate on the right
CREATE FUNCTION rtrunc(text, integer)
RETURNS text
AS 'SELECT substring($1 FROM (char_length($1)-($2)+1) FOR $2)'
LANGUAGE 'SQL';
CREATE FUNCTION space(integer)
RETURNS text
AS 'SELECT lpad('''', $1, '' '')'
LANGUAGE 'SQL';
-- String Functions
-- ++++++++++++++++
--
-- Mathematical functions
-- Built-in: ASCII, BIT_LENGTH, CHAR_LENGTH, CHARACTER_LENGTH, LTRIM,
-- OCTET_LENGTH, POSITION, REPEAT, RTRIM, SUBSTRING
-- Missing: DIFFERENCE, REPLACE, SOUNDEX, LENGTH (ODBC sense)
-- Keyword problems: CHAR, LEFT, RIGHT
-- CHAR(code)
CREATE OR REPLACE FUNCTION "char"(integer) RETURNS text AS '
SELECT chr($1);
' LANGUAGE SQL;
-- CONCAT(string1, string2)
CREATE OR REPLACE FUNCTION concat(text, text) RETURNS text AS '
SELECT $1 || $2;
' LANGUAGE SQL;
-- INSERT(string1, start, len, string2)
CREATE OR REPLACE FUNCTION insert(text, integer, integer, text) RETURNS text AS '
SELECT substring($1 from 1 for $2) || $4 || substring($1 from $2 + $3 + 1);
' LANGUAGE SQL;
-- LCASE(string)
CREATE OR REPLACE FUNCTION lcase(text) RETURNS text AS '
SELECT lower($1);
' LANGUAGE SQL;
-- LEFT(string, count)
CREATE OR REPLACE FUNCTION "left"(text, integer) RETURNS text AS '
SELECT substring($1 for $2);
' LANGUAGE SQL;
-- LOCATE(substring, string[, start])
CREATE OR REPLACE FUNCTION locate(text, text) RETURNS integer AS '
SELECT position($1 in $2);
' LANGUAGE SQL;
CREATE OR REPLACE FUNCTION locate(text, text, integer) RETURNS integer AS '
SELECT position($1 in substring($2 from $3)) + $3 - 1;
' LANGUAGE SQL;
-- RIGHT(string, count)
CREATE OR REPLACE FUNCTION "right"(text, integer) RETURNS text AS '
SELECT substring($1 from char_length($1) - $2 + 1);
' LANGUAGE SQL;
-- SPACE(count)
CREATE OR REPLACE FUNCTION space(integer) RETURNS text AS '
SELECT repeat('' '', $1);
' LANGUAGE SQL;
-- UCASE(string)
CREATE OR REPLACE FUNCTION ucase(text) RETURNS text AS '
SELECT upper($1);
' LANGUAGE SQL;
-- Numeric Functions
-- +++++++++++++++++
--
-- Built-in: ABS, ACOS, ASIN, ATAN, ATAN2, COS, COT, DEGRESS, EXP,
-- FLOOR, MOD, PI, RADIANS, ROUND, SIGN, SIN, SQRT, TAN
-- Missing: LOG (ODBC sense)
CREATE FUNCTION truncate(numeric,integer)
RETURNS numeric
AS 'SELECT trunc($1, $2)'
LANGUAGE 'SQL';
-- CEILING(num)
CREATE OR REPLACE FUNCTION ceiling(numeric) RETURNS numeric AS '
SELECT ceil($1);
' LANGUAGE SQL;
-- LOG10(num)
CREATE OR REPLACE FUNCTION log10(double precision) RETURNS double precision AS '
SELECT log($1);
' LANGUAGE SQL;
CREATE OR REPLACE FUNCTION log10(numeric) RETURNS numeric AS '
SELECT log($1);
' LANGUAGE SQL;
-- POWER(num, num)
CREATE OR REPLACE FUNCTION power(double precision, double precision)
RETURNS double precision AS '
SELECT pow($1, $2);
' LANGUAGE SQL;
CREATE OR REPLACE FUNCTION power(numeric, numeric)
RETURNS numeric AS '
SELECT pow($1, $2);
' LANGUAGE SQL;
-- RAND([seed])
CREATE OR REPLACE FUNCTION rand() RETURNS double precision AS '
SELECT random();
' LANGUAGE SQL;
CREATE OR REPLACE FUNCTION rand(double precision) RETURNS double precision AS '
SELECT setseed($1);
SELECT random();
' LANGUAGE SQL;
-- TRUNCATE(num, places)
CREATE OR REPLACE FUNCTION truncate(numeric, integer) RETURNS numeric AS '
SELECT trunc($1, $2);
' LANGUAGE SQL;
-- Time, Date, and Interval Functions
-- ++++++++++++++++++++++++++++++++++
--
-- Date/time functions for v7.0
--
-- Built-in: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, EXTRACT, NOW
-- Missing: none
CREATE FUNCTION curdate()
RETURNS date
AS 'SELECT CAST(''now'' AS date)'
LANGUAGE 'SQL';
CREATE FUNCTION curtime()
RETURNS time
AS 'SELECT CAST(''now'' AS time)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION curdate() RETURNS date AS '
SELECT current_date;
' LANGUAGE SQL;
CREATE FUNCTION dayname(timestamp)
RETURNS text
AS 'SELECT to_char($1,''Day'')'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION curtime() RETURNS time with time zone AS '
SELECT current_time;
' LANGUAGE SQL;
CREATE FUNCTION dayofmonth(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''day'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION dayname(timestamp) RETURNS text AS '
SELECT to_char($1,''Day'');
' LANGUAGE SQL;
CREATE FUNCTION dayofweek(timestamp)
RETURNS integer
AS 'SELECT ( CAST(date_part(''dow'', $1) AS integer) + 1)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION dayofmonth(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(day FROM $1) AS integer);
' LANGUAGE SQL;
CREATE FUNCTION dayofyear(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''doy'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION dayofweek(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(dow FROM $1) AS integer) + 1;
' LANGUAGE SQL;
CREATE FUNCTION hour(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''hour'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION dayofyear(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(doy FROM $1) AS integer);
' LANGUAGE SQL;
CREATE FUNCTION minute(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''minute'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION hour(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(hour FROM $1) AS integer);
' LANGUAGE SQL;
CREATE FUNCTION odbc_month(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''month'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION minute(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(minute FROM $1) AS integer);
' LANGUAGE SQL;
CREATE FUNCTION monthname(timestamp)
RETURNS text
AS 'SELECT to_char($1, ''Month'')'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION month(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(month FROM $1) AS integer);
' LANGUAGE SQL;
CREATE FUNCTION quarter(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''quarter'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION monthname(timestamp) RETURNS text AS '
SELECT to_char($1, ''Month'');
' LANGUAGE SQL;
CREATE FUNCTION second(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''second'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION quarter(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(quarter FROM $1) AS integer);
' LANGUAGE SQL;
CREATE OR REPLACE FUNCTION second(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(second FROM $1) AS integer);
' LANGUAGE SQL;
/*
-- The first argument is an integer constant denoting the units
-- of the second argument. Until we know the actual values, we
-- cannot implement these. - thomas 2000-04-11
CREATE FUNCTION timestampadd(integer,integer,timestamp)
RETURNS timestamp
AS 'SELECT CAST(($3 + ($2 * $1)) AS timestamp)'
LANGUAGE 'SQL';
xCREATE OR REPLACE FUNCTION timestampadd(integer, integer, timestamp)
RETURNS timestamp AS '
SELECT CAST(($3 + ($2 * $1)) AS timestamp);
' LANGUAGE SQL;
CREATE FUNCTION timestampdiff(integer,integer,timestamp)
RETURNS timestamp
AS 'SELECT CAST(($3 + ($2 * $1)) AS timestamp)'
LANGUAGE 'SQL';
xCREATE OR REPLACE FUNCTION timestampdiff(integer, integer, timestamp)
RETURNS timestamp AS '
SELECT CAST(($3 + ($2 * $1)) AS timestamp);
' LANGUAGE SQL;
*/
CREATE FUNCTION week(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''week'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION week(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(week FROM $1) AS integer);
' LANGUAGE SQL;
CREATE FUNCTION year(timestamp)
RETURNS integer
AS 'SELECT CAST(date_part(''year'', $1) AS integer)'
LANGUAGE 'SQL';
CREATE OR REPLACE FUNCTION year(timestamp) RETURNS integer AS '
SELECT CAST(EXTRACT(year FROM $1) AS integer);
' LANGUAGE SQL;
-- System Functions
-- ++++++++++++++++
--
-- System functions.
--
/*
CREATE FUNCTION database()
RETURNS text
AS 'SELECT ...'
LANGUAGE 'SQL';
*/
CREATE FUNCTION odbc_user()
RETURNS text
AS 'SELECT CAST(USER AS text)'
LANGUAGE 'SQL';
-- Built-in: USER
-- Missing: DATABASE, IFNULL