8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 16:43:03 +01:00

Fixed CORE-5657: Various UDF-related security vulnerabilities

This commit is contained in:
AlexPeshkoff 2017-11-09 13:15:00 +03:00
parent 820a64eba8
commit b9c17656e9
26 changed files with 454 additions and 3326 deletions

View File

@ -113,7 +113,7 @@ copyFiles() {
mkdir $DestDir/UDF
mkdir $DestDir/misc
mkdir $DestDir/misc/upgrade
for i in ib_udf metadata security; do
for i in metadata security; do
mkdir $DestDir/misc/upgrade/$i
done
@ -184,16 +184,8 @@ copyFiles() {
cp $BuiltFBDir/intl/libfbintl.so $DestDir/intl/fbintl
cp $BuiltFBDir/UDF/ib_udf.so $DestDir/UDF/
cp $BuiltFBDir/UDF/fbudf.so $DestDir/UDF/
# Note that the following items copy files from outside the build tree
# Copy the sql-declarations into the UDF-directory
cp $BuildRootDir/src/extlib/ib_udf.sql $DestDir/UDF/
cp $BuildRootDir/src/extlib/ib_udf2.sql $DestDir/UDF/
cp $BuildRootDir/src/extlib/fbudf/fbudf.sql $DestDir/UDF/
# Copy various documentation
ls $BuildRootDir/doc/*.pdf >/dev/null 2>&1 && cp $BuildRootDir/doc/*.pdf $DestDir/doc
cp $BuildRootDir/doc/sql.extensions/README* $DestDir/doc/sql.extensions

View File

@ -139,7 +139,7 @@ copyFiles() {
makeDirs "@FB_BINDIR@ @FB_SBINDIR@ @FB_CONFDIR@ @FB_LIBDIR@ @FB_INCDIR@ @FB_DOCDIR@/sql.extensions @FB_UDFDIR@ @FB_SAMPLEDIR@ \
@FB_SAMPLEDBDIR@ @FB_HELPDIR@ @FB_INTLDIR@ @FB_MISCDIR@ @FB_SECDBDIR@ @FB_MSGDIR@ @FB_LOGDIR@ @FB_GUARDDIR@ @FB_PLUGDIR@"
for i in ib_udf metadata security; do
for i in metadata security; do
makeDirs @FB_MISCDIR@/upgrade/$i
done
@ -263,18 +263,7 @@ copyFiles() {
chmod 0755 ${TargetDir}@FB_INTLDIR@/fbintl
chmod 0644 ${TargetDir}@FB_INTLDIR@/fbintl.conf
#UDF
cp $BuiltFBDir/UDF/ib_udf.so ${TargetDir}@FB_UDFDIR@
cp $BuiltFBDir/UDF/fbudf.so ${TargetDir}@FB_UDFDIR@
# Note that the following items copy files from outside the build tree.
# Copy the sql-declarations into the UDF-directory
cp $BuildRootDir/src/extlib/ib_udf.sql ${TargetDir}@FB_UDFDIR@
cp $BuildRootDir/src/extlib/ib_udf2.sql ${TargetDir}@FB_UDFDIR@
cp $BuildRootDir/src/extlib/fbudf/fbudf.sql ${TargetDir}@FB_UDFDIR@
chown root:wheel ${TargetDir}@FB_UDFDIR@/*.so ${TargetDir}@FB_UDFDIR@/*.sql
chmod 0755 ${TargetDir}@FB_UDFDIR@/*.so
chmod 0644 ${TargetDir}@FB_UDFDIR@/*.sql
#doc
cp $BuildRootDir/doc/README.* ${TargetDir}@FB_DOCDIR@

View File

@ -262,17 +262,8 @@ copyFiles() {
chmod 0755 ${TargetDir}@FB_INTLDIR@/fbintl
chmod 0644 ${TargetDir}@FB_INTLDIR@/fbintl.conf
#UDF
cp $BuiltFBDir/UDF/ib_udf.so ${TargetDir}@FB_UDFDIR@
cp $BuiltFBDir/UDF/fbudf.so ${TargetDir}@FB_UDFDIR@
# Note that the following items copy files from outside the build tree.
# Copy the sql-declarations into the UDF-directory
cp $BuildRootDir/src/extlib/ib_udf.sql ${TargetDir}@FB_UDFDIR@
cp $BuildRootDir/src/extlib/ib_udf2.sql ${TargetDir}@FB_UDFDIR@
cp $BuildRootDir/src/extlib/fbudf/fbudf.sql ${TargetDir}@FB_UDFDIR@
chmod 0755 ${TargetDir}@FB_UDFDIR@/*.so
chmod 0644 ${TargetDir}@FB_UDFDIR@/*.sql
#doc
cp $BuildRootDir/doc/*.pdf ${TargetDir}@FB_DOCDIR@

View File

@ -179,12 +179,6 @@ cp -Rf $BuiltFBDir/lib/libfbclient.so* $DestDir/lib || exit
cp -f $BuiltFBDir/lib/libib_util.so $DestDir/lib/libib_util.so || exit
cp $BuiltFBDir/intl/libfbintl.so $DestDir/intl/fbintl || exit
cp $BuiltFBDir/UDF/ib_udf.so $DestDir/UDF/ || exit
cp $BuiltFBDir/UDF/fbudf.so $DestDir/UDF/ || exit
# Copy the sql-declarations into the UDF-directory
cp $BuildRootDir/src/extlib/ib_udf.sql $DestDir/UDF/ || exit
cp $BuildRootDir/src/extlib/fbudf/fbudf.sql $DestDir/UDF/ || exit
# Note that this copies files from outside the build tree.
echo Installing documentation

View File

@ -287,23 +287,6 @@ if "%PROCESSOR_ARCHITECTURE%"=="x86" (
goto :EOF
)
@echo Copying udf library scripts...
for %%v in ( ib_udf.sql ib_udf2.sql ) do (
@copy /Y %FB_ROOT_PATH%\src\extlib\%%v %FB_OUTPUT_DIR%\udf\%%v > nul
@if %ERRORLEVEL% GEQ 1 (
call :ERROR copy /Y %FB_ROOT_PATH%\src\extlib\%%v %FB_OUTPUT_DIR%\udf\%%v failed with error %ERRORLEVEL%.
goto :EOF
)
)
for %%v in ( fbudf.sql fbudf.txt ) do (
@copy /Y %FB_ROOT_PATH%\src\extlib\fbudf\%%v %FB_OUTPUT_DIR%\UDF\%%v > nul
@if %ERRORLEVEL% GEQ 1 (
call :ERROR copy /Y %FB_ROOT_PATH%\src\extlib\fbudf\%%v %FB_OUTPUT_DIR%\UDF\%%v failed with error %ERRORLEVEL%.
goto :EOF
)
)
:: Various upgrade scripts and docs
mkdir %FB_OUTPUT_DIR%\misc\upgrade\security 2>nul
@copy %FB_ROOT_PATH%\src\misc\upgrade\v3.0\security_* %FB_OUTPUT_DIR%\misc\upgrade\security > nul

View File

@ -180,12 +180,11 @@
# NOTE: THE EXTERNAL FUNCTION ENGINE FEATURE COULD BE USED TO COMPROMISE
# THE SERVER/HOST AS WELL AS DATABASE SECURITY!!
#
# IT IS STRONGLY RECOMMENDED THAT THIS SETTING BE USED TO LIMIT
# EXTERNAL FUNCTION LOCATIONS!
# IT IS STRONGLY RECOMMENDED THAT THIS SETTING BE SET TO NONE!
#
# Type: string (special format)
#
#UdfAccess = Restrict UDF
#UdfAccess = None
# ----------------------------

View File

@ -396,27 +396,10 @@ msg.timestamp: $(MSG_FILES)
$(TOUCH) $@
.PHONY: udfs ibutil ibudf fbudf udfsupport
.PHONY: ibutil udfsupport
udfsupport:
$(MAKE) ibutil
$(MAKE) udfs
udfs: ibudf fbudf
UDF = $(FB_BUILD)/UDF
IBUDF_SO = $(UDF)/ib_udf.$(SHRLIB_EXT)
FBUDF_SO = $(UDF)/fbudf.$(SHRLIB_EXT)
ibudf: $(IBUDF_SO)
$(IBUDF_SO): $(IBUDF_Objects)
$(call LINK_UDF,ib_udf) -o $@ $^ $(LINK_UDF_LIBS)
fbudf: $(FBUDF_SO)
$(FBUDF_SO): $(FBUDF_Objects) $(COMMON_LIB)
$(call LINK_UDF,fbudf) -o $@ $^ $(LINK_UDF_LIBS) $(FIREBIRD_LIBRARY_LINK)
ibutil: $(LIBIBUTIL_SO)
@ -425,7 +408,7 @@ $(LIBIBUTIL_SO): $(UTIL_Objects)
#___________________________________________________________________________
# most of utilities, including network server and UDFs
# most of utilities, including network server and UDF support
# qli is not here cause it needs special database (help.fdb), therefore needs gbak
#
@ -498,20 +481,22 @@ $(NBACKUP): $(NBACKUP_Objects) $(COMMON_LIB)
# plugins - some of them are required to build examples, use separate entry for them
#
.PHONY: udr legacy_user_management legacy_auth_server trace auth_debug
.PHONY: udr legacy_user_management legacy_auth_server trace auth_debug udf_compat
UDR_PLUGIN = $(call makePluginName,udr_engine)
LEGACY_USER_MANAGER = $(call makePluginName,Legacy_UserManager)
LEGACY_AUTH_SERVER = $(call makePluginName,Legacy_Auth)
SRP_USER_MANAGER = $(call makePluginName,Srp)
FBTRACE = $(call makePluginName,fbtrace)
AUTH_DEBUGGER = $(call makePluginName,Auth_Debug)
UDF_BACKWARD_COMPATIBILITY_BASENAME = $(LIB_PREFIX)udf_compat.$(SHRLIB_EXT)
UDF_BACKWARD_COMPATIBILITY = $(PLUGINS)/udr/$(UDF_BACKWARD_COMPATIBILITY_BASENAME)
BUILD_DEBUG:=
ifeq ($(TARGET),Debug)
BUILD_DEBUG:=auth_debug
endif
plugins: udr legacy_user_management legacy_auth_server srp_user_management trace $(BUILD_DEBUG)
plugins: udr legacy_user_management legacy_auth_server srp_user_management trace $(BUILD_DEBUG) udf_compat
udr: $(UDR_PLUGIN) $(PLUGINS)/udr_engine.conf
@ -546,6 +531,15 @@ srp_user_management: $(SRP_USER_MANAGER)
$(SRP_USER_MANAGER): $(SRP_USERS_MANAGE_Objects) $(COMMON_LIB)
$(LINK_PLUGIN) $(call LIB_LINK_SONAME,$(notdir $@).0) -o $@ $^ $(LINK_PLUG_LIBS) $(FIREBIRD_LIBRARY_LINK)
udf_compat: $(UDF_BACKWARD_COMPATIBILITY) $(COMPAT_SQL)
$(UDF_BACKWARD_COMPATIBILITY): $(COMPAT_Objects)
$(LIB_LINK) $(LIB_LINK_OPTIONS) $(call LIB_LINK_SONAME,$(UDF_BACKWARD_COMPATIBILITY_BASENAME)) \
$(LINK_UDR_PLUGIN_SYMBOLS) $(LIB_PATH_OPTS) $(UNDEF_FLAGS) -o $@ $^ $(THR_LIBS)
$(COMPAT_SQL): $(SRC_COMPAT_SQL)
cp $^ $@
#___________________________________________________________________________
# codes - developers change them sometimes
#

View File

@ -196,11 +196,14 @@ AllObjects += $(UDRENG_Objects)
# UDF support
IBUDF_Objects:= $(call makeObjects,extlib,ib_udf.cpp)
FBUDF_Objects:= $(call makeObjects,extlib/fbudf,fbudf.cpp)
UTIL_Objects:= $(call makeObjects,extlib,ib_util.cpp)
AllObjects += $(IBUDF_Objects) $(FBUDF_Objects) $(UTIL_Objects)
# UDR backward compatible with distributed UDFs
COMPAT_Objects:= $(call makeObjects,extlib,UdfBackwardCompatibility.cpp)
SRC_COMPAT_SQL:= $(SRC_ROOT)/extlib/UdfBackwardCompatibility.sql
COMPAT_SQL:= $(PLUGINS)/udr/udf_compat.sql
AllObjects += $(UTIL_Objects) $(COMPAT_Objects)
# Regenerate error codes

View File

@ -96,8 +96,6 @@ darwin_finish_cs_framework:
chmod +x ../builds/install/arch-specific/darwin/changeMultiConnectMode
cp ../builds/install/arch-specific/darwin/changeMultiConnectMode \
$(FB_FW)/Resources/bin/changeMultiConnectMode.sh
cp ../src/extlib/ib_udf.sql $(FB_FW)/Resources/English.lproj/var/UDF
cp ../src/extlib/fbudf/fbudf.sql $(FB_FW)/Resources/English.lproj/var/UDF
cp ../builds/install/arch-specific/darwin/FrameworkInfo.plist \
$(FB_FW)/Resources/Info.plist
cp ../builds/install/arch-specific/darwin/launchd.org.firebird.gds.plist \
@ -165,8 +163,6 @@ darwin_finish_ss_framework:
cp ../gen/firebird/bin/gdef $(FB_FW)/Resources/bin
cp ../gen/firebird/bin/fbsvcmgr $(FB_FW)/Resources/bin
cp ../gen/firebird/bin/fbtracemgr $(FB_FW)/Resources/bin
cp ../src/extlib/ib_udf.sql $(FB_FW)/Resources/English.lproj/var/UDF
cp ../src/extlib/fbudf/fbudf.sql $(FB_FW)/Resources/English.lproj/var/UDF
cp ../builds/install/arch-specific/darwin/FrameworkInfo.plist \
$(FB_FW)/Resources/Info.plist
cp ../builds/install/arch-specific/darwin/launchdss.org.firebird.gds.plist \

View File

@ -0,0 +1,32 @@
********************************************************************************
LIST OF KNOWN INCOMPATIBILITIES
between versions 3.0 and 4.0
********************************************************************************
This document describes all the changes that make v4.0 incompatible in any way
as compared with the previous releases and hence could affect your databases and
applications.
Please read the below descriptions carefully before upgrading your software to
the new Firebird version.
Deprecating UDF
--------------------------
* Initial design of UDF always used to be security problem. The most dangerous
security holes when UDFs and external tables are used simultaneousky were
fixed in FB 1.5. But even after it incorrectly declared (using SQL statement
DECLARE EXTERNAL FUNCTION) UDF can easily cause various security issues like
server crash or execution of arbitrary code. Therefore UDFs are deprecated
in v.4. That means that UDFs can't be used with default configuration
(parameter "UdfAccess" set to "None") and all sample UDF libraries (ib_udf,
fbudf) are not distributed any more. Most of functions in that libraries
were replaced with builtin analogs in previous versions and therefore
already deprecated. A few remaining functions got safe replacement in UDR
library "udf_compat", namely div, frac, dow, sdow, getExactTimestampUTC and
isLeapYear. Users who still wish to use UDFs should set "UdfAccess" to
"Restrict <path-list>". If you never used to modify this parameter before
path-list is just UDF and resulting line in firebird.conf should be:
UdfAccess = Restrict UDF
Recommended long-term solution is replacing of UDF with UDR.

View File

@ -162,8 +162,8 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
{TYPE_STRING, "RemoteBindAddress", (ConfigValue) 0},
{TYPE_STRING, "ExternalFileAccess", (ConfigValue) "None"}, // location(s) of external files for tables
{TYPE_STRING, "DatabaseAccess", (ConfigValue) "Full"}, // location(s) of databases
#define UDF_DEFAULT_CONFIG_VALUE "Restrict UDF"
{TYPE_STRING, "UdfAccess", (ConfigValue) UDF_DEFAULT_CONFIG_VALUE}, // location(s) of UDFs
#define UDF_DEFAULT_RESTRICT_VALUE "Restrict UDF" // use it to substitute FB_UDFDIR value
{TYPE_STRING, "UdfAccess", (ConfigValue) "None"}, // location(s) of UDFs
{TYPE_STRING, "TempDirectories", (ConfigValue) 0},
#ifdef DEV_BUILD
{TYPE_BOOLEAN, "BugcheckAbort", (ConfigValue) true}, // whether to abort() engine when internal error is found
@ -595,8 +595,8 @@ const char *Config::getUdfAccess()
}
const char* v = (const char*) getDefaultConfig()->values[KEY_UDF_ACCESS];
if (CASE_SENSITIVITY ? (! strcmp(v, UDF_DEFAULT_CONFIG_VALUE) && FB_UDFDIR[0]) :
(! fb_utils::stricmp(v, UDF_DEFAULT_CONFIG_VALUE) && FB_UDFDIR[0]))
if (CASE_SENSITIVITY ? (! strcmp(v, UDF_DEFAULT_RESTRICT_VALUE) && FB_UDFDIR[0]) :
(! fb_utils::stricmp(v, UDF_DEFAULT_RESTRICT_VALUE) && FB_UDFDIR[0]))
{
udfValue->printf("Restrict %s", FB_UDFDIR);
value = udfValue->c_str();

View File

@ -0,0 +1,348 @@
/*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2008 Adriano dos Santos Fernandes <adrianosf@gmail.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Alex Peshkoff, 2017
* Claudio Valderrama, 2001
*/
#define FB_UDR_STATUS_TYPE ::Firebird::ThrowStatusWrapper
#include "firebird.h"
#include <ibase.h>
#include <firebird/UdrCppEngine.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_MATH_H
#include <math.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#ifdef HAVE_SYS_TIMEB_H
# include <sys/timeb.h>
#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#include <limits>
using namespace Firebird;
//------------------------------------------------------------------------------
/***
create function div (
n1 integer,
n2 integer
) returns double precision
external name 'udf_compat!UC_div'
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(UC_div)
FB_UDR_MESSAGE(InMessage,
(FB_INTEGER, n1)
(FB_INTEGER, n2)
);
FB_UDR_MESSAGE(OutMessage,
(FB_DOUBLE, result)
);
FB_UDR_EXECUTE_FUNCTION
{
if (in->n1Null || in->n2Null)
{
out->resultNull = FB_TRUE;
out->result = 0;
}
else
{
out->resultNull = FB_FALSE;
if (in->n2)
out->result = div(in->n1, in->n2).quot;
else
out->result = std::numeric_limits<double>::infinity();
}
}
FB_UDR_END_FUNCTION
/***
create function frac (
val double precision
) returns double precision
external name 'udf_compat!UC_frac'
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(UC_frac)
FB_UDR_MESSAGE(InMessage,
(FB_DOUBLE, val)
);
FB_UDR_MESSAGE(OutMessage,
(FB_DOUBLE, result)
);
FB_UDR_EXECUTE_FUNCTION
{
if (in->valNull)
{
out->resultNull = FB_TRUE;
out->result = 0;
}
else
{
out->resultNull = FB_FALSE;
out->result = in->val > 0 ? in->val - floor(in->val) :
in->val < 0 ? in->val - ceil(in->val) : 0;
}
}
FB_UDR_END_FUNCTION
namespace
{
enum day_format {day_short, day_long};
const FB_SIZE_T day_len[] = {4, 14};
const char* day_fmtstr[] = {"%a", "%A"};
void decode_timestamp(IUtil* u, const FbTimestamp* from, tm* to, unsigned* fractions)
{
// decode firebird timestamp format
memset(to, 0, sizeof(tm));
from->date.decode(u, (unsigned*)&to->tm_year, (unsigned*)&to->tm_mon, (unsigned*)&to->tm_mday);
to->tm_year -= 1900;
to->tm_mon--;
from->time.decode(u, (unsigned*)&to->tm_hour, (unsigned*)&to->tm_min, (unsigned*)&to->tm_sec, fractions);
// set wday/yday
time_t tt = mktime(to);
localtime_r(&tt, to);
}
template <typename VC>
void get_DOW(IUtil* u, const FbTimestamp* v, VC* rc, const day_format df)
{
// decode firebird timestamp format
tm times;
decode_timestamp(u, v, &times, NULL);
const int dow = times.tm_wday;
if (dow >= 0 && dow <= 6)
{
FB_SIZE_T name_len = day_len[df];
const char* name_fmt = day_fmtstr[df];
// There should be a better way to do this than to alter the thread's locale.
if (!strcmp(setlocale(LC_TIME, NULL), "C"))
setlocale(LC_ALL, "");
name_len = static_cast<FB_SIZE_T>(strftime(rc->str, name_len, name_fmt, &times));
if (name_len)
{
// There's no clarity in the docs whether '\0' is counted or not; be safe.
if (!rc->str[name_len - 1])
--name_len;
rc->length = name_len;
return;
}
}
rc->length = df == day_long ? 5 : 3;
memcpy(rc->str, "ERROR", rc->length);
}
void encode_timestamp(IUtil* u, const tm* from, const unsigned fractions, FbTimestamp* to)
{
tm times = *from;
// decode firebird timestamp format
times.tm_year += 1900;
times.tm_mon++;
to->date.encode(u, times.tm_year, times.tm_mon, times.tm_mday);
to->time.encode(u, times.tm_hour, times.tm_min, times.tm_sec, fractions);
}
} // anonymous namespace
/***
create function dow (
val timestamp
) returns varchar(14) collate none
external name 'udf_compat!UC_dow'
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(UC_dow)
FB_UDR_MESSAGE(InMessage,
(FB_TIMESTAMP, val)
);
FB_UDR_MESSAGE(OutMessage,
(FB_VARCHAR(14), result)
);
FB_UDR_EXECUTE_FUNCTION
{
out->resultNull = in->valNull;
if (!out->resultNull)
get_DOW(master->getUtilInterface(), &in->val, &out->result, day_long);
}
FB_UDR_END_FUNCTION
/***
create function sdow (
val timestamp
) returns varchar(4) collate none
external name 'udf_compat!UC_sdow'
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(UC_sdow)
FB_UDR_MESSAGE(InMessage,
(FB_TIMESTAMP, val)
);
FB_UDR_MESSAGE(OutMessage,
(FB_VARCHAR(4), result)
);
FB_UDR_EXECUTE_FUNCTION
{
out->resultNull = in->valNull;
if (!out->resultNull)
get_DOW(master->getUtilInterface(), &in->val, &out->result, day_short);
}
FB_UDR_END_FUNCTION
/***
create function getExactTimestampUTC
returns timestamp
external name 'udf_compat!UC_getExactTimestampUTC'
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(UC_getExactTimestampUTC)
FB_UDR_MESSAGE(OutMessage,
(FB_TIMESTAMP, result)
);
FB_UDR_EXECUTE_FUNCTION
{
#if defined(HAVE_GETTIMEOFDAY)
timeval tv;
GETTIMEOFDAY(&tv);
const time_t seconds = tv.tv_sec;
tm timex;
#if defined(HAVE_GMTIME_R)
tm* times = gmtime_r(&seconds, &timex);
#else
timeMutex.enter();
tm* times = gmtime(&seconds);
if (times)
{
// Copy to local variable before we exit the mutex.
timex = *times;
times = &timex;
}
timeMutex.leave();
#endif // gmtime_r
if (times)
{
encode_timestamp(master->getUtilInterface(), times, tv.tv_usec / 100, &out->result);
out->resultNull = false;
}
#else // gettimeofday
_timeb timebuffer;
_ftime(&timebuffer);
// gmtime uses thread local storage in NT, no need to lock threads.
// Of course, this facility is only available in multithreaded builds.
tm* times = gmtime(&timebuffer.time);
if (times)
{
encode_timestamp(master->getUtilInterface(), times, timebuffer.millitm * 10, &out->result);
out->resultNull = false;
}
#endif
else
{
out->resultNull = true;
out->result.date.value = 0;
out->result.time.value = 0;
}
}
FB_UDR_END_FUNCTION
/***
create function isLeapYear (
val timestamp
) returns boolean
external name 'udf_compat!UC_isLeapYear'
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(UC_isLeapYear)
FB_UDR_MESSAGE(InMessage,
(FB_TIMESTAMP, val)
);
FB_UDR_MESSAGE(OutMessage,
(FB_BOOLEAN, result)
);
FB_UDR_EXECUTE_FUNCTION
{
if (in->valNull)
{
out->result = FB_FALSE;
out->resultNull = true;
return;
}
const int ly = in->val.date.getYear(master->getUtilInterface());
out->result = ((ly % 4 == 0 && ly % 100 != 0) || ly % 400 == 0) ? FB_TRUE : FB_FALSE;
out->resultNull = false;
}
FB_UDR_END_FUNCTION
//------------------------------------------------------------------------------
// This should be used in only one of the UDR library files.
// Build must export firebird_udr_plugin function.
FB_UDR_IMPLEMENT_ENTRY_POINT

View File

@ -0,0 +1,43 @@
-- Create functions in current DB
create function div (
n1 integer,
n2 integer
) returns double precision
external name 'udf_compat!UC_div'
engine udr;
create function frac (
val double precision
) returns double precision
external name 'udf_compat!UC_frac'
engine udr;
create function dow (
val timestamp
) returns varchar(14) collate none
external name 'udf_compat!UC_dow'
engine udr;
create function sdow (
val timestamp
) returns varchar(4) collate none
external name 'udf_compat!UC_sdow'
engine udr;
create function getExactTimestampUTC
returns timestamp
external name 'udf_compat!UC_getExactTimestampUTC'
engine udr;
create function isLeapYear (
val timestamp
) returns boolean
external name 'udf_compat!UC_isLeapYear'
engine udr;
-- Run minimum test
select 25, 3, div(25, 3) from rdb$database;
select pi(), frac(pi()) from rdb$database;
select current_date, dow(current_date), sdow(current_date) from rdb$database;
select current_timestamp, getExactTimestampUTC() from rdb$database;
select current_date, isLeapYear(current_date) from rdb$database;

View File

@ -1,37 +0,0 @@
========================================================================
DYNAMIC LINK LIBRARY : fbudf
========================================================================
AppWizard has created this fbudf DLL for you.
This file contains a summary of what you will find in each of the files that
make up your fbudf application.
fbudf.dsp
This file (the project file) contains information at the project level and
is used to build a single project or subproject. Other users can share the
project (.dsp) file, but they should export the makefiles locally.
fbudf.cpp
This is the main DLL source file.
fbudf.h
This file contains your DLL exports.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named fbudf.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

View File

@ -1,835 +0,0 @@
/*
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/idpl.html.
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* The Original Code was created by Claudio Valderrama C. for IBPhoenix.
* The development of the Original Code was sponsored by Craig Leonardi.
*
* Copyright (c) 2001 IBPhoenix
* All Rights Reserved.
*
* 2002.01.07 Claudio Valderrama: change the impolite way truncate and round work,
* make null handling more consistent and add dpower(x,y).
* Beware the SQL declaration for those functions has changed.
* 2002.01.20 Claudio Valderrama: addMonth should work with negative values, too.
* 2003.10.26: Made some values const and other minor changes.
* 2004.09.29 Claudio Valderrama: fix numeric overflow in addHour reported by
* "jssahdra" <joga.singh at inventum.cc>. Since all add<time> functions are
* wrappers around addTenthMSec, only two lines needed to be fixed.
*/
// fbudf.cpp : Defines the entry point for the DLL application.
//
/*
CVC: The MS way of doing things puts the includes in stdafx. I expect
that you can continue this trend without problems on other compilers
or platforms. Since I conditioned the Windows-related includes, it should
be easy to add needed headers to stdafx.h after a makefile is built.
*/
#include "stdafx.h"
#ifndef FBUDF_EXPORTS
#define FBUDF_EXPORTS
#endif
#include "fbudf.h"
#include "../common/classes/NoThrowTimeStamp.h"
#if defined(HAVE_GETTIMEOFDAY) && (!(defined (HAVE_LOCALTIME_R) && defined (HAVE_GMTIME_R)))
#define NEED_TIME_MUTEX
#include "../common/classes/locks.h"
#endif
//Original code for this library was written by Claudio Valderrama
// on July 2001 for IBPhoenix.
// Define this symbol if you want truncate and round to be symmetric wr to zero.
//#define SYMMETRIC_MATH
#if defined (_WIN32)
/*
BOOL APIENTRY DllMain( HANDLE ,//hModule,
DWORD ul_reason_for_call,
LPVOID //lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
*/
#endif
// To do: go from C++ native types to abstract FB types.
#ifdef DEV_BUILD
// This function shouldn't be defined in production.
FBUDF_API paramdsc* testreflect(paramdsc* rc)
{
rc->dsc_address = 0;
rc->dsc_flags = 1 | 4; //DSC_null | DSC_nullable;
return rc;
}
#endif
namespace internal
{
typedef ISC_USHORT fb_len;
const long seconds_in_day = 86400;
const long tenthmsec_in_day = seconds_in_day * ISC_TIME_SECONDS_PRECISION;
const int varchar_indicator_size = sizeof(ISC_USHORT);
const int max_varchar_size = 65535 - varchar_indicator_size; // in theory
// This definition comes from jrd\val.h and is used in helper
// functions {get/set}_varchar_len defined below.
struct vvary
{
fb_len vary_length;
ISC_UCHAR vary_string[max_varchar_size];
};
/*
inline fb_len get_varchar_len(const char* vchar)
{
return reinterpret_cast<const vvary*>(vchar)->vary_length;
}
*/
inline fb_len get_varchar_len(const ISC_UCHAR* vchar)
{
return reinterpret_cast<const vvary*>(vchar)->vary_length;
}
inline void set_varchar_len(char* vchar, const fb_len len)
{
reinterpret_cast<vvary*>(vchar)->vary_length = len;
}
inline void set_varchar_len(ISC_UCHAR* vchar, const fb_len len)
{
reinterpret_cast<vvary*>(vchar)->vary_length = len;
}
bool isnull(const paramdsc* v)
{
return !v || !v->dsc_address || (v->dsc_flags & DSC_null);
}
paramdsc* setnull(paramdsc* v)
{
if (v)
v->dsc_flags |= DSC_null;
return v;
}
int get_int_type(const paramdsc* v, ISC_INT64& rc)
{
int s = -1;
switch (v->dsc_dtype)
{
case dtype_short:
rc = *reinterpret_cast<ISC_SHORT*>(v->dsc_address);
s = sizeof(ISC_SHORT);
break;
case dtype_long:
rc = *reinterpret_cast<ISC_LONG*>(v->dsc_address);
s = sizeof(ISC_LONG);
break;
case dtype_int64:
rc = *reinterpret_cast<ISC_INT64*>(v->dsc_address);
s = sizeof(ISC_INT64);
break;
default:
break;
}
return s;
}
void set_int_type(paramdsc* v, const ISC_INT64 iv)
{
switch (v->dsc_dtype)
{
case dtype_short:
*reinterpret_cast<ISC_SHORT*>(v->dsc_address) = static_cast<ISC_SHORT>(iv);
break;
case dtype_long:
*reinterpret_cast<ISC_LONG*>(v->dsc_address) = static_cast<ISC_LONG>(iv);
break;
case dtype_int64:
*reinterpret_cast<ISC_INT64*>(v->dsc_address) = iv;
break;
}
}
int get_double_type(const paramdsc* v, double& rc)
{
int s = -1;
switch (v->dsc_dtype)
{
case dtype_real:
rc = static_cast<double>(*reinterpret_cast<float*>(v->dsc_address));
s = sizeof(float);
break;
case dtype_double:
rc = *reinterpret_cast<double*>(v->dsc_address);
s = sizeof(double);
break;
default:
break;
}
return s;
}
void set_double_type(paramdsc* v, const double iv)
{
switch (v->dsc_dtype)
{
case dtype_real:
*reinterpret_cast<float*>(v->dsc_address) = static_cast<float>(iv);
break;
case dtype_double:
*reinterpret_cast<double*>(v->dsc_address) = iv;
break;
}
}
int get_any_string_type(const paramdsc* v, ISC_UCHAR*& text)
{
int len = v->dsc_length;
switch (v->dsc_dtype)
{
case dtype_text:
text = v->dsc_address;
break;
case dtype_cstring:
text = v->dsc_address;
if (len && text)
{
const ISC_UCHAR* p = text; //strlen(v->dsc_address);
while (*p)
++p; // couldn't use strlen!
if (p - text < len)
len = p - text;
}
break;
case dtype_varying:
len -= varchar_indicator_size;
text = reinterpret_cast<vvary*>(v->dsc_address)->vary_string;
{
const int x = get_varchar_len(v->dsc_address);
if (x < len)
len = x;
}
break;
default:
len = -1;
break;
}
return len;
}
void set_any_string_type(paramdsc* v, const int len0, ISC_UCHAR* text = 0)
{
fb_len len = static_cast<fb_len>(len0);
switch (v->dsc_dtype)
{
case dtype_text:
v->dsc_length = len;
if (text)
memcpy(v->dsc_address, text, len);
else
memset(v->dsc_address, ' ', len);
break;
case dtype_cstring:
v->dsc_length = len;
if (text)
memcpy(v->dsc_address, text, len);
else
v->dsc_length = len = 0;
v->dsc_address[len] = 0;
break;
case dtype_varying:
if (!text)
len = 0;
else if (len > max_varchar_size)
len = max_varchar_size;
v->dsc_length = len + static_cast<fb_len>(varchar_indicator_size);
set_varchar_len(v->dsc_address, len);
if (text)
memcpy(v->dsc_address + varchar_indicator_size, text, len);
break;
}
}
int get_scaled_double(const paramdsc* v, double& rc)
{
ISC_INT64 iv;
int rct = get_int_type(v, iv);
if (rct < 0)
rct = get_double_type(v, rc);
else
{
rc = static_cast<double>(iv);
int scale = v->dsc_scale;
for (; scale < 0; ++scale)
rc /= 10;
for (; scale > 0; --scale)
rc *= 10;
}
return rct;
}
} // namespace internal
// BEGIN DEPRECATED FUNCTIONS.
FBUDF_API paramdsc* idNvl(paramdsc* v, paramdsc* v2)
{
if (!internal::isnull(v))
return v;
return v2;
}
FBUDF_API void sNvl(const paramdsc* v, const paramdsc* v2, paramdsc* rc)
{
if (!internal::isnull(v))
{
ISC_UCHAR* sv = 0;
const int len = internal::get_any_string_type(v, sv);
if (len < 0)
internal::setnull(rc);
else
internal::set_any_string_type(rc, len, sv);
return;
}
if (!internal::isnull(v2))
{
ISC_UCHAR* sv2 = 0;
const int len = internal::get_any_string_type(v2, sv2);
if (len < 0)
internal::setnull(rc);
else
internal::set_any_string_type(rc, len, sv2);
return;
}
internal::setnull(rc);
}
FBUDF_API paramdsc* iNullIf(paramdsc* v, paramdsc* v2)
{
if (internal::isnull(v) || internal::isnull(v2))
return 0;
ISC_INT64 iv, iv2;
const int rc = internal::get_int_type(v, iv);
const int rc2 = internal::get_int_type(v2, iv2);
if (rc < 0 || rc2 < 0)
return v;
if (iv == iv2 && v->dsc_scale == v2->dsc_scale)
return 0;
return v;
}
FBUDF_API paramdsc* dNullIf(paramdsc* v, paramdsc* v2)
{
if (internal::isnull(v) || internal::isnull(v2))
return 0;
double iv, iv2;
const int rc = internal::get_double_type(v, iv);
const int rc2 = internal::get_double_type(v2, iv2);
if (rc < 0 || rc2 < 0)
return v;
if (iv == iv2) // && v->dsc_scale == v2->dsc_scale) double w/o scale
return 0;
return v;
}
FBUDF_API void sNullIf(const paramdsc* v, const paramdsc* v2, paramdsc* rc)
{
if (internal::isnull(v) || internal::isnull(v2))
{
internal::setnull(rc);
return;
}
ISC_UCHAR* sv;
const int len = internal::get_any_string_type(v, sv);
ISC_UCHAR* sv2;
const int len2 = internal::get_any_string_type(v2, sv2);
if (len < 0 || len2 < 0) // good luck with the result, we can't do more.
return;
if (len == len2 && (!len || !memcmp(sv, sv2, len)) &&
(v->dsc_sub_type == v2->dsc_sub_type || // ttype
!v->dsc_sub_type || !v2->dsc_sub_type)) // tyype
{
internal::setnull(rc);
return;
}
internal::set_any_string_type(rc, len, sv);
return;
}
// END DEPRECATED FUNCTIONS.
namespace internal
{
void decode_timestamp(const GDS_TIMESTAMP* date, tm* times_arg) throw()
{
Firebird::NoThrowTimeStamp::decode_timestamp(*date, times_arg);
}
void encode_timestamp(const tm* times_arg, GDS_TIMESTAMP* date) throw()
{
*date = Firebird::NoThrowTimeStamp::encode_timestamp(times_arg);
}
enum day_format {day_short, day_long};
const fb_len day_len[] = {4, 14};
const char* day_fmtstr[] = {"%a", "%A"};
void get_DOW(const ISC_TIMESTAMP* v, paramvary* rc, const day_format df)
{
tm times;
decode_timestamp(v, &times);
const int dow = times.tm_wday;
if (dow >= 0 && dow <= 6)
{
fb_len name_len = day_len[df];
const char* name_fmt = day_fmtstr[df];
// There should be a better way to do this than to alter the thread's locale.
if (!strcmp(setlocale(LC_TIME, NULL), "C"))
setlocale(LC_ALL, "");
char* const target = reinterpret_cast<char*>(rc->vary_string);
name_len = static_cast<fb_len>(strftime(target, name_len, name_fmt, &times));
if (name_len)
{
// There's no clarity in the docs whether '\0' is counted or not; be safe.
if (!target[name_len - 1])
--name_len;
rc->vary_length = name_len;
return;
}
}
rc->vary_length = 5;
memcpy(rc->vary_string, "ERROR", 5);
}
} // namespace internal
FBUDF_API void DOW(const ISC_TIMESTAMP* v, paramvary* rc)
{
internal::get_DOW(v, rc, internal::day_long);
}
FBUDF_API void SDOW(const ISC_TIMESTAMP* v, paramvary* rc)
{
internal::get_DOW(v, rc, internal::day_short);
}
FBUDF_API void right(const paramdsc* v, const ISC_SHORT& rl, paramdsc* rc)
{
if (internal::isnull(v))
{
internal::setnull(rc);
return;
}
ISC_UCHAR* text = 0;
int len = internal::get_any_string_type(v, text);
const int diff = len - rl;
if (rl < len)
len = rl;
if (len < 0)
{
internal::setnull(rc);
return;
}
if (diff > 0)
text += diff;
internal::set_any_string_type(rc, len, text);
return;
}
FBUDF_API ISC_TIMESTAMP* addDay(ISC_TIMESTAMP* v, const ISC_LONG& ndays)
{
v->timestamp_date += ndays;
return v;
}
FBUDF_API void addDay2(const ISC_TIMESTAMP* v0, const ISC_LONG& ndays, ISC_TIMESTAMP* v)
{
*v = *v0;
v->timestamp_date += ndays;
}
FBUDF_API ISC_TIMESTAMP* addWeek(ISC_TIMESTAMP* v, const ISC_LONG& nweeks)
{
v->timestamp_date += nweeks * 7;
return v;
}
FBUDF_API ISC_TIMESTAMP* addMonth(ISC_TIMESTAMP* v, const ISC_LONG& nmonths)
{
tm times;
internal::decode_timestamp(v, &times);
const int y = nmonths / 12, m = nmonths % 12;
times.tm_year += y;
if ((times.tm_mon += m) > 11)
{
++times.tm_year;
times.tm_mon -= 12;
}
else if (times.tm_mon < 0)
{
--times.tm_year;
times.tm_mon += 12;
}
const int ly = times.tm_year + 1900;
const bool leap = (ly % 4 == 0 && ly % 100 != 0) || ly % 400 == 0;
const int md[] = {31, (leap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (times.tm_mday > md[times.tm_mon])
times.tm_mday = md[times.tm_mon];
internal::encode_timestamp(&times, v);
return v;
}
FBUDF_API ISC_TIMESTAMP* addYear(ISC_TIMESTAMP* v, const ISC_LONG& nyears)
{
tm times;
internal::decode_timestamp(v, &times);
times.tm_year += nyears;
internal::encode_timestamp(&times, v);
return v;
}
namespace internal
{
ISC_TIMESTAMP* addTenthMSec(ISC_TIMESTAMP* v, SINT64 tenthmilliseconds, int multiplier)
{
const SINT64 full = tenthmilliseconds * multiplier;
const long days = full / tenthmsec_in_day, secs = full % tenthmsec_in_day;
v->timestamp_date += days;
// Time portion is unsigned, so we avoid unsigned rolling over negative values
// that only produce a new unsigned number with the wrong result.
if (secs < 0 && static_cast<ISC_ULONG>(-secs) > v->timestamp_time)
{
--v->timestamp_date;
v->timestamp_time += tenthmsec_in_day + secs;
}
else if ((v->timestamp_time += secs) >= static_cast<ISC_ULONG>(tenthmsec_in_day))
{
++v->timestamp_date;
v->timestamp_time -= tenthmsec_in_day;
}
return v;
}
} // namespace internal
FBUDF_API ISC_TIMESTAMP* addMilliSecond(ISC_TIMESTAMP* v, const ISC_LONG& nmseconds)
{
return internal::addTenthMSec(v, nmseconds, ISC_TIME_SECONDS_PRECISION / 1000);
}
FBUDF_API ISC_TIMESTAMP* addSecond(ISC_TIMESTAMP* v, const ISC_LONG& nseconds)
{
return internal::addTenthMSec(v, nseconds, ISC_TIME_SECONDS_PRECISION);
}
FBUDF_API ISC_TIMESTAMP* addMinute(ISC_TIMESTAMP* v, const ISC_LONG& nminutes)
{
return internal::addTenthMSec(v, nminutes, 60 * ISC_TIME_SECONDS_PRECISION);
}
FBUDF_API ISC_TIMESTAMP* addHour(ISC_TIMESTAMP* v, const ISC_LONG& nhours)
{
return internal::addTenthMSec(v, nhours, 3600 * ISC_TIME_SECONDS_PRECISION);
}
#ifdef NEED_TIME_MUTEX
Firebird::Mutex timeMutex;
#endif
FBUDF_API void getExactTimestamp(ISC_TIMESTAMP* rc)
{
#if defined(HAVE_GETTIMEOFDAY)
timeval tv;
GETTIMEOFDAY(&tv);
const time_t seconds = tv.tv_sec;
tm timex;
#if defined(HAVE_LOCALTIME_R)
tm* times = localtime_r(&seconds, &timex);
#else
timeMutex.enter();
tm* times = localtime(&seconds);
if (times)
{
// Copy to local variable before we exit the mutex.
timex = *times;
times = &timex;
}
timeMutex.leave();
#endif // localtime_r
if (times)
{
internal::encode_timestamp(times, rc);
rc->timestamp_time += tv.tv_usec / 100;
}
else
rc->timestamp_date = rc->timestamp_time = 0;
#else // gettimeofday
_timeb timebuffer;
_ftime(&timebuffer);
// localtime uses thread local storage in NT, no need to lock threads.
// Of course, this facility is only available in multithreaded builds.
tm* times = localtime(&timebuffer.time);
if (times)
{
internal::encode_timestamp(times, rc);
rc->timestamp_time += timebuffer.millitm * 10;
}
else
rc->timestamp_date = rc->timestamp_time = 0;
#endif
return;
}
FBUDF_API void getExactTimestampUTC(ISC_TIMESTAMP* rc)
{
#if defined(HAVE_GETTIMEOFDAY)
timeval tv;
GETTIMEOFDAY(&tv);
const time_t seconds = tv.tv_sec;
tm timex;
#if defined(HAVE_GMTIME_R)
tm* times = gmtime_r(&seconds, &timex);
#else
timeMutex.enter();
tm* times = gmtime(&seconds);
if (times)
{
// Copy to local variable before we exit the mutex.
timex = *times;
times = &timex;
}
timeMutex.leave();
#endif // gmtime_r
if (times)
{
internal::encode_timestamp(times, rc);
rc->timestamp_time += tv.tv_usec / 100;
}
else
rc->timestamp_date = rc->timestamp_time = 0;
#else // gettimeofday
_timeb timebuffer;
_ftime(&timebuffer);
// gmtime uses thread local storage in NT, no need to lock threads.
// Of course, this facility is only available in multithreaded builds.
tm* times = gmtime(&timebuffer.time);
if (times)
{
internal::encode_timestamp(times, rc);
rc->timestamp_time += timebuffer.millitm * 10;
}
else
rc->timestamp_date = rc->timestamp_time = 0;
#endif
return;
}
FBUDF_API ISC_LONG isLeapYear(const ISC_TIMESTAMP* v)
{
tm times;
internal::decode_timestamp(v, &times);
const int ly = times.tm_year + 1900;
return (ly % 4 == 0 && ly % 100 != 0) || ly % 400 == 0;
}
FBUDF_API void fbtruncate(const paramdsc* v, paramdsc* rc)
{
if (internal::isnull(v))
{
internal::setnull(rc);
return;
}
ISC_INT64 iv;
const int rct = internal::get_int_type(v, iv);
if (rct < 0 || v->dsc_scale > 0)
{
internal::setnull(rc);
return;
}
if (!v->dsc_scale /*|| !v->dsc_sub_type*/) //second test won't work with ODS9
{
internal::set_int_type(rc, iv);
rc->dsc_scale = 0;
return;
}
// truncate(0.9) => 0
// truncate(-0.9) => -1
// truncate(-0.9) => 0 ### SYMMETRIC_MATH defined.
int scale = v->dsc_scale;
#if defined(SYMMETRIC_MATH)
while (scale++ < 0)
iv /= 10;
#else
const bool isNeg = iv < 0;
bool gt = false;
while (scale++ < 0)
{
if (iv % 10)
gt = true;
iv /= 10;
}
if (gt)
{
if (isNeg)
--iv;
}
#endif
internal::set_int_type(rc, iv);
rc->dsc_scale = 0;
return;
}
FBUDF_API void fbround(const paramdsc* v, paramdsc* rc)
{
if (internal::isnull(v))
{
internal::setnull(rc);
return;
}
ISC_INT64 iv;
const int rct = internal::get_int_type(v, iv);
if (rct < 0 || v->dsc_scale > 0)
{
internal::setnull(rc);
return;
}
if (!v->dsc_scale /*|| !v->dsc_sub_type*/) //second test won't work with ODS9
{
internal::set_int_type(rc, iv);
rc->dsc_scale = 0;
return;
}
// round(0.3) => 0 ### round(0.5) => 1
// round(-0.3) => 0 ### round(-0.5) => 0
// round(-0.3) => 0 ### round(-0.5) => -1 ### SYMMETRIC_MATH defined.
const bool isNeg = iv < 0;
int scale = v->dsc_scale;
bool gt = false, check_more = false;
while (scale++ < 0)
{
if (!scale)
{
int dig;
if (iv == MIN_SINT64)
dig = -(iv + 10) % 10;
else
dig = static_cast<int>(iv >= 0 ? iv % 10 : -iv % 10);
#if defined(SYMMETRIC_MATH)
if (dig >= 5)
gt = true;
#else
if (!isNeg)
{
if (dig >= 5)
gt = true;
}
else
{
if (dig > 5 || (dig == 5 && check_more))
gt = true;
}
#endif
}
else if (isNeg && !check_more)
{
if (iv % 10 != 0)
check_more = true;
}
iv /= 10;
}
if (gt)
{
if (isNeg)
--iv;
else
++iv;
}
internal::set_int_type(rc, iv);
rc->dsc_scale = 0;
return;
}
FBUDF_API void power(const paramdsc* v, const paramdsc* v2, paramdsc* rc)
{
if (internal::isnull(v) || internal::isnull(v2))
{
internal::setnull(rc);
return;
}
double d, d2;
const int rct = internal::get_scaled_double(v, d);
const int rct2 = internal::get_scaled_double(v2, d2);
// If we cause a div by zero, SS shuts down in response.
// The doc I read says 0^0 will produce 1, so it's not tested below.
if (rct < 0 || rct2 < 0 || (!d && d2 < 0))
{
internal::setnull(rc);
return;
}
internal::set_double_type(rc, pow(d, d2));
rc->dsc_scale = 0;
return;
}
FBUDF_API void string2blob(const paramdsc* v, blobcallback* outblob)
{
if (internal::isnull(v))
{
outblob->blob_handle = 0; // hint for the engine, null blob.
return;
}
ISC_UCHAR* text = 0;
const int len = internal::get_any_string_type(v, text);
if (len < 0 && outblob)
outblob->blob_handle = 0; // hint for the engine, null blob.
if (!outblob || !outblob->blob_handle)
return;
outblob->blob_put_segment(outblob->blob_handle, text, len);
return;
}

View File

@ -1,94 +0,0 @@
/*
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/idpl.html.
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* The Original Code was created by Claudio Valderrama C. for IBPhoenix.
* The development of the Original Code was sponsored by Craig Leonardi.
*
* Copyright (c) 2001 IBPhoenix
* All Rights Reserved.
*/
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the FBUDF_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// FBUDF_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#ifdef FBUDF_EXPORTS
#define FBUDF_API __declspec(dllexport)
#else
#define FBUDF_API __declspec(dllimport)
#endif
#elif defined(DARWIN)
#define FBUDF_API API_ROUTINE
#else
#define FBUDF_API
#endif
//Original code for this library was written by Claudio Valderrama
// on July 2001 for IBPhoenix.
#ifdef __cplusplus
extern "C" {
#endif
#ifdef DEV_BUILD
//This function shouldn't be defined in production.
FBUDF_API paramdsc* testreflect(paramdsc* rc);
#endif
// BEGIN DEPRECATED FUNCTIONS.
FBUDF_API paramdsc* idNvl(paramdsc* v, paramdsc* v2);
FBUDF_API void sNvl(const paramdsc* v, const paramdsc* v2, paramdsc* rc);
FBUDF_API paramdsc* iNullIf(paramdsc* v, paramdsc* v2);
FBUDF_API paramdsc* dNullIf(paramdsc* v, paramdsc* v2);
FBUDF_API void sNullIf(const paramdsc* v, const paramdsc* v2, paramdsc* rc);
// END DEPRECATED FUNCTIONS.
FBUDF_API void DOW(const ISC_TIMESTAMP* v, paramvary* rc);
FBUDF_API void SDOW(const ISC_TIMESTAMP* v, paramvary* rc);
FBUDF_API void right(const paramdsc* v, const ISC_SHORT& rl, paramdsc* rc);
FBUDF_API ISC_TIMESTAMP* addDay(ISC_TIMESTAMP* v, const ISC_LONG& ndays);
FBUDF_API void addDay2(const ISC_TIMESTAMP* v0, const ISC_LONG& ndays, ISC_TIMESTAMP* v);
FBUDF_API ISC_TIMESTAMP* addWeek(ISC_TIMESTAMP* v, const ISC_LONG& nweeks);
FBUDF_API ISC_TIMESTAMP* addMonth(ISC_TIMESTAMP* v, const ISC_LONG& nmonths);
FBUDF_API ISC_TIMESTAMP* addYear(ISC_TIMESTAMP* v, const ISC_LONG& nyears);
FBUDF_API ISC_TIMESTAMP* addMilliSecond(ISC_TIMESTAMP* v, const ISC_LONG& nmseconds);
FBUDF_API ISC_TIMESTAMP* addSecond(ISC_TIMESTAMP* v, const ISC_LONG& nseconds);
FBUDF_API ISC_TIMESTAMP* addMinute(ISC_TIMESTAMP* v, const ISC_LONG& nminutes);
FBUDF_API ISC_TIMESTAMP* addHour(ISC_TIMESTAMP* v, const ISC_LONG& nhours);
FBUDF_API void getExactTimestamp(ISC_TIMESTAMP* rc);
FBUDF_API void getExactTimestampUTC(ISC_TIMESTAMP* rc);
FBUDF_API ISC_LONG isLeapYear(const ISC_TIMESTAMP* v);
FBUDF_API void fbtruncate(const paramdsc* v, paramdsc* rc);
FBUDF_API void fbround(const paramdsc* v, paramdsc* rc);
FBUDF_API void power(const paramdsc* v, const paramdsc* v2, paramdsc* rc);
FBUDF_API void string2blob(const paramdsc* v, blobcallback* outblob);
#ifdef __cplusplus
}
#endif

View File

@ -1,206 +0,0 @@
/*
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/idpl.html.
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* The Original Code was created by Claudio Valderrama C. for IBPhoenix.
* The development of the Original Code was sponsored by Craig Leonardi.
*
* Copyright (c) 2001 IBPhoenix
* All Rights Reserved.
*/
/* This file defines the new udfs for Firebird. */
set sql dialect 3;
-- The Nvl family is deprecated. Use native COALESCE instead.
--FBUDF_API paramdsc* idNvl(paramdsc* v, paramdsc* v2)
declare external function invl
int by descriptor, int by descriptor
returns int by descriptor
entry_point 'idNvl' module_name 'fbudf';
--FBUDF_API paramdsc* idNvl(paramdsc* v, paramdsc* v2)
declare external function i64nvl
numeric(18,0) by descriptor, numeric(18,0) by descriptor
returns numeric(18,0) by descriptor
entry_point 'idNvl' module_name 'fbudf';
--FBUDF_API paramdsc* idNvl(paramdsc* v, paramdsc* v2)
declare external function dnvl
double precision by descriptor, double precision by descriptor
returns double precision by descriptor
entry_point 'idNvl' module_name 'fbudf';
--FBUDF_API paramdsc* sNvl(paramdsc* v, paramdsc* v2, paramdsc* rc)
declare external function snvl
varchar(100) by descriptor, varchar(100) by descriptor,
varchar(100) by descriptor returns parameter 3
entry_point 'sNvl' module_name 'fbudf';
-- The NullIf family is deprecated. Use native NULLIF instead.
--FBUDF_API paramdsc* iNullIf(paramdsc* v, paramdsc* v2)
declare external function inullif
int by descriptor, int by descriptor
returns int by descriptor
entry_point 'iNullIf' module_name 'fbudf';
--FBUDF_API paramdsc* dNullIf(paramdsc* v, paramdsc* v2)
declare external function dnullif
double precision by descriptor, double precision by descriptor
returns double precision by descriptor
entry_point 'dNullIf' module_name 'fbudf';
--FBUDF_API paramdsc* iNullIf(paramdsc* v, paramdsc* v2)
declare external function i64nullif
numeric(18,4) by descriptor, numeric(18,4) by descriptor
returns numeric(18,4) by descriptor
entry_point 'iNullIf' module_name 'fbudf';
--FBUDF_API paramdsc* sNullIf(paramdsc* v, paramdsc* v2, paramdsc* rc)
declare external function snullif
varchar(100) by descriptor, varchar(100) by descriptor,
varchar(100) by descriptor returns parameter 3
entry_point 'sNullIf' module_name 'fbudf';
--FBUDF_API char* DOW(ISC_DATE* v, char* rc)
declare external function dow
timestamp,
varchar(15) returns parameter 2
entry_point 'DOW' module_name 'fbudf';
--FBUDF_API char* SDOW(ISC_DATE* v, char* rc)
declare external function sdow
timestamp,
varchar(5) returns parameter 2
entry_point 'SDOW' module_name 'fbudf';
--FBUDF_API paramdsc* right(const paramdsc*, const ISC_SHORT& rl, paramdsc* rc)
declare external function sright
varchar(100) by descriptor, smallint,
varchar(100) by descriptor returns parameter 3
entry_point 'right' module_name 'fbudf';
--FBUDF_API ISC_TIMESTAMP* addDay(ISC_TIMESTAMP* v, const ISC_SLONG& ndays)
declare external function addDay
timestamp, int
returns timestamp
entry_point 'addDay' module_name 'fbudf';
--FBUDF_API void addDay2(const ISC_TIMESTAMP* v0, const ISC_SLONG& ndays, ISC_TIMESTAMP* v)
declare external function addDay2
timestamp, int, timestamp
returns parameter 3
entry_point 'addDay2' module_name 'fbudf';
--FBUDF_API ISC_TIMESTAMP* addWeek(ISC_TIMESTAMP* v, const ISC_SLONG& nweeks)
declare external function addWeek
timestamp, int
returns timestamp
entry_point 'addWeek' module_name 'fbudf';
--FBUDF_API ISC_TIMESTAMP* addMonth(ISC_TIMESTAMP* v, const ISC_SLONG& nmonths)
declare external function addMonth
timestamp, int
returns timestamp
entry_point 'addMonth' module_name 'fbudf';
--FBUDF_API ISC_TIMESTAMP* addYear(ISC_TIMESTAMP* v, const ISC_SLONG& nyears)
declare external function addYear
timestamp, int
returns timestamp
entry_point 'addYear' module_name 'fbudf';
--FBUDF_API ISC_TIMESTAMP* addMilliSecond(ISC_TIMESTAMP* v, const ISC_SLONG& nseconds)
declare external function addMilliSecond
timestamp, int
returns timestamp
entry_point 'addMilliSecond' module_name 'fbudf';
--FBUDF_API ISC_TIMESTAMP* addSecond(ISC_TIMESTAMP* v, const ISC_SLONG& nseconds)
declare external function addSecond
timestamp, int
returns timestamp
entry_point 'addSecond' module_name 'fbudf';
--FBUDF_API ISC_TIMESTAMP* addMinute(ISC_TIMESTAMP* v, const ISC_SLONG& nminutes)
declare external function addMinute
timestamp, int
returns timestamp
entry_point 'addMinute' module_name 'fbudf';
--FBUDF_API ISC_TIMESTAMP* addHour(ISC_TIMESTAMP* v, const ISC_SLONG& nhours)
declare external function addHour
timestamp, int
returns timestamp
entry_point 'addHour' module_name 'fbudf';
--It will work only with Win32 until it's ported to another OS.
--FBUDF_API ISC_TIMESTAMP* getExactTimestamp(ISC_TIMESTAMP* rc)
declare external function getExactTimestamp
timestamp
returns parameter 1
entry_point 'getExactTimestamp' module_name 'fbudf';
--It will work only with Win32 until it's ported to another OS.
--FBUDF_API void getExactTimestampUTC(ISC_TIMESTAMP* rc);
declare external function getExactTimestampUTC
timestamp
returns parameter 1
entry_point 'getExactTimestampUTC' module_name 'fbudf';
--FBUDF_API int isLeapYear(const ISC_TIMESTAMP* v);
declare external function isLeapYear
timestamp
returns int by value
entry_point 'isLeapYear' module_name 'fbudf';
--FBUDF_API paramdsc* fbtruncate(const paramdsc* v, paramdsc* rc)
declare external function Truncate
int by descriptor, int by descriptor
returns parameter 2
entry_point 'fbtruncate' module_name 'fbudf';
--FBUDF_API paramdsc* fbtruncate(const paramdsc* v, paramdsc* rc)
declare external function i64Truncate
numeric(18) by descriptor, numeric(18) by descriptor
returns parameter 2
entry_point 'fbtruncate' module_name 'fbudf';
--FBUDF_API paramdsc* fbround(const paramdsc* v, paramdsc* rc)
declare external function Round
int by descriptor, int by descriptor
returns parameter 2
entry_point 'fbround' module_name 'fbudf';
--FBUDF_API paramdsc* fbround(const paramdsc* v, paramdsc* rc)
declare external function i64Round
numeric(18, 4) by descriptor, numeric(18, 4) by descriptor
returns parameter 2
entry_point 'fbround' module_name 'fbudf';
--FBUDF_API paramdsc* power(const paramdsc* v, const paramdsc* v2, paramdsc* rc)
declare external function dPower
double precision by descriptor, double precision by descriptor,
double precision by descriptor
returns parameter 3
entry_point 'power' module_name 'fbudf';
--FBUDF_API blobcallback* string2blob(const paramdsc* v, blobcallback* outblob)
declare external function string2blob
varchar(300) by descriptor,
blob returns parameter 2
entry_point 'string2blob' module_name 'fbudf';

View File

@ -1,47 +0,0 @@
FBUDF, a small project to enhance ibudf.
The library ibudf that comes with IB5, IB6 and FB has some generic routines.
However, it lacks others and it seems a good idea to enhance it with more
functionality. The first test is to build a separate small library. When those
functions have been tested, they may be included in ibudf. This way, it's possible
to experiment with fbudf without mangling the established library.
This is initially a MSVC project for Windows. It will be generalized later.
It doesn't use ib_util because it relies on the engine providing return
arguments when they are of type string.
Originally, this library intends to offer:
NVL => one for integers and the other for strings. This way, the overhead
for strings can be avoided for integers.
NULLIF => same idea than before.
DOW (Day of Week) Monday, Tuesday, Wednesday ...
SDOW(Short Day of Week) Mon, Tue, Wed, Thu ....
(
The following two aren't necessary:
SUBSTR: It has been superseded by internal SUBSTRING in Firebird.
LEFT: You can use SUBSTRING(s from 1 for N) in Firebird
)
RIGHT: This will work only for 1-byte charsets.
TRUNCATE / ROUND
(
The following two are already in udflib:
CEILING / FLOOR
)
Date manipulation stuff ...
Add a day, week, month, year to a date.
String <-> BLOB
STRING2BLOB
(Firebird already is capable of accepting a string to populate a blob on INSERT only.)
---
Claudio Valderrama - July 2001.

View File

@ -1,30 +0,0 @@
/*
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/idpl.html.
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* The Original Code was created by Claudio Valderrama C. for IBPhoenix.
* The development of the Original Code was sponsored by Craig Leonardi.
*
* Copyright (c) 2001 IBPhoenix
* All Rights Reserved.
*/
// stdafx.cpp : source file that includes just the standard includes
// fbudf.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@ -1,79 +0,0 @@
/*
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/idpl.html.
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* The Original Code was created by Claudio Valderrama C. for IBPhoenix.
* The development of the Original Code was sponsored by Craig Leonardi.
*
* Copyright (c) 2001 IBPhoenix
* All Rights Reserved.
*/
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__F60BDFDF_7A2D_11D5_8EEB_4854E8274D24__INCLUDED_)
#define AFX_STDAFX_H__F60BDFDF_7A2D_11D5_8EEB_4854E8274D24__INCLUDED_
// TODO: reference additional headers your program requires here
#include "firebird.h"
#ifdef HAVE_MATH_H
#include <math.h>
#endif
//#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#ifdef HAVE_SYS_TIMEB_H
# include <sys/timeb.h>
#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
//#include "ib_util.h"
//#include "ib_udf.h"
#ifdef HAVE_PTHREAD_H
#include "fb_pthread.h"
#endif
#include "../../jrd/ibase.h"
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__F60BDFDF_7A2D_11D5_8EEB_4854E8274D24__INCLUDED_)

View File

@ -1,462 +0,0 @@
/*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Changes made by Claudio Valderrama for the Firebird project
* changes to substr and added substrlen
* 2004.9.1 Claudio Valderrama, change some UDF's to be able to detect NULL.
* 2004.12.5 Slavomir Skopalik contributed IB_UDF_frac.
*
*/
#include "firebird.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include "fb_types.h"
#include "ib_util.h"
#include "ib_udf.h"
extern "C"
{
#ifndef __ICC
#ifndef SOLARIS
#ifdef WIN_NT
#define exception_type _exception
#else
#define exception_type __exception
#endif
int MATHERR(struct exception_type*)
{
return 1;
}
#undef exception_type
#endif // SOLARIS
#endif //__ICC
typedef char* pChar;
double EXPORT IB_UDF_abs( double *a)
{
return (*a < 0.0) ? -*a : *a;
}
double EXPORT IB_UDF_acos( double *a)
{
return (acos(*a));
}
pChar EXPORT IB_UDF_ascii_char( ISC_LONG *a)
{
if (!a)
return 0;
char* b = (char *) ib_util_malloc(2);
*b = (char) (*a);
// let us not forget to NULL terminate
b[1] = '\0';
return (b);
}
ISC_LONG EXPORT IB_UDF_ascii_val( const char *a)
{
// NULL is treated as ASCII(0).
return ((ISC_LONG) (*a));
}
double EXPORT IB_UDF_asin( double *a)
{
return (asin(*a));
}
double EXPORT IB_UDF_atan( double *a)
{
return (atan(*a));
}
double EXPORT IB_UDF_atan2( double *a, double *b)
{
return (atan2(*a, *b));
}
ISC_LONG EXPORT IB_UDF_bin_and( ISC_LONG *a, ISC_LONG *b)
{
return (*a & *b);
}
ISC_LONG EXPORT IB_UDF_bin_or( ISC_LONG *a, ISC_LONG *b)
{
return (*a | *b);
}
ISC_LONG EXPORT IB_UDF_bin_xor( ISC_LONG *a, ISC_LONG *b)
{
return (*a ^ *b);
}
double EXPORT IB_UDF_ceiling( double *a)
{
return (ceil(*a));
}
double EXPORT IB_UDF_cos( double *a)
{
return (cos(*a));
}
double EXPORT IB_UDF_cosh( double *a)
{
return (cosh(*a));
}
double EXPORT IB_UDF_cot( double *a)
{
return (1.0 / tan(*a));
}
double EXPORT IB_UDF_div( ISC_LONG *a, ISC_LONG *b)
{
if (*b != 0)
{
// VS8.0 has two implementations of div().
// Let's explicitly use the int-aware one.
div_t div_result = div((int) *a, (int) *b);
return (div_result.quot);
}
// This is a Kludge! We need to return INF,
// but this seems to be the only way to do
// it since there seens to be no constant for it.
#ifdef HAVE_INFINITY
return INFINITY;
#else
return 1 / tan(0.0);
#endif
}
double EXPORT IB_UDF_floor( double *a)
{
return (floor(*a));
}
double EXPORT IB_UDF_frac(const double* x)
{
if (*x > 0)
return *x - floor(*x);
if (*x < 0)
return *x - ceil(*x);
return 0;
}
double EXPORT IB_UDF_ln( double *a)
{
return (log(*a));
}
double EXPORT IB_UDF_log( double *a, double *b)
{
return (log(*b) / log(*a));
}
double EXPORT IB_UDF_log10( double *a)
{
return (log10(*a));
}
pChar EXPORT IB_UDF_lower(const char *s)
{
if (!s)
return 0;
char* buf = (char *) ib_util_malloc(static_cast<long>(strlen(s) + 1));
char* p = buf;
while (*s)
{
if (*s >= 'A' && *s <= 'Z') {
*p++ = *s++ - 'A' + 'a';
}
else
*p++ = *s++;
}
*p = '\0';
return buf;
}
pChar EXPORT IB_UDF_lpad( const char *s, ISC_LONG *a, const char *c)
{
if (!s || !c)
return 0;
const long avalue = *a;
if (avalue >= 0)
{
long current = 0;
const long length = static_cast<long>(strlen(s));
const long padlength = static_cast<long>(strlen(c));
const long stop = avalue < length ? avalue : length;
char* buf = (char*) ib_util_malloc(avalue + 1);
if (padlength)
{
while (current + length < avalue)
{
memcpy(&buf[current], c, padlength);
current += padlength;
}
memcpy(&buf[(avalue - length < 0) ? 0 : avalue - length], s, stop);
buf[avalue] = '\0';
}
else
{
memcpy(buf, s, stop);
buf[stop] = '\0';
}
return buf;
}
return NULL;
}
pChar EXPORT IB_UDF_ltrim( const char *s)
{
if (!s)
return 0;
while (*s == ' ') // skip leading blanks
s++;
const long length = static_cast<long>(strlen(s));
char* buf = (char *) ib_util_malloc(length + 1);
memcpy(buf, s, length);
buf[length] = '\0';
return buf;
}
double EXPORT IB_UDF_mod( ISC_LONG *a, ISC_LONG *b)
{
if (*b != 0)
{
// VS8.0 has two implementations of div().
// Let's explicitly use the int-aware one.
div_t div_result = div((int) *a, (int) *b);
return (div_result.rem);
}
// This is a Kludge! We need to return INF,
// but this seems to be the only way to do
// it since there seens to be no constant for it.
#ifdef HAVE_INFINITY
return INFINITY;
#else
return 1 / tan(0.0);
#endif
}
double EXPORT IB_UDF_pi()
{
return (IB_PI);
}
double EXPORT IB_UDF_srand()
{
srand((unsigned) time(NULL));
return ((float) rand() / (float) RAND_MAX);
}
double EXPORT IB_UDF_rand()
{
return ((float) rand() / (float) RAND_MAX);
}
pChar EXPORT IB_UDF_rpad( const char *s, ISC_LONG *a, const char *c)
{
if (!s || !c)
return 0;
const long avalue = *a;
if (avalue >= 0)
{
const long length = static_cast<long>(strlen(s));
long current = (avalue - length) < 0 ? avalue : length;
const long padlength = static_cast<long>(strlen(c));
char* buf = (char*) ib_util_malloc (avalue + 1);
memcpy(buf, s, current);
if (padlength)
{
while (current + padlength < avalue)
{
memcpy(&buf[current], c, padlength);
current += padlength;
}
memcpy(&buf[current], c, avalue - current);
buf[avalue] = '\0';
}
else
buf[current] = 0;
return buf;
}
return NULL;
}
pChar EXPORT IB_UDF_rtrim( const char *s)
{
if (!s)
return 0;
const char* p = s + strlen(s);
while (--p >= s && *p == ' ')
; // empty loop body
const long length = p - s + 1;
char* buf = (char *) ib_util_malloc(length + 1);
memcpy(buf, s, length);
buf[length] = '\0';
return buf;
}
ISC_LONG EXPORT IB_UDF_sign( double *a)
{
if (*a > 0)
return 1;
if (*a < 0)
return -1;
// If neither is true then it equals 0
return 0;
}
double EXPORT IB_UDF_sin( double *a)
{
return (sin(*a));
}
double EXPORT IB_UDF_sinh( double *a)
{
return (sinh(*a));
}
double EXPORT IB_UDF_sqrt( double *a)
{
return (sqrt(*a));
}
pChar EXPORT IB_UDF_substr(const char* s, ISC_SHORT* m, ISC_SHORT* n)
{
if (!s) {
return 0;
}
char* buf;
long length = static_cast<long>(strlen(s));
if (!length ||
*m > *n ||
*m < 1 ||
*n < 1 ||
*m > length)
{
buf = (char*)ib_util_malloc(1);
buf[0] = '\0';
}
else
{
// we want from the mth char to the nth char inclusive, so add one to the length.
// CVC: We need to compensate for n if it's longer than s's length
if (*n > length) {
length -= *m - 1;
}
else {
length = *n - *m + 1;
}
buf = (char*)ib_util_malloc (length + 1);
memcpy(buf, s + *m - 1, length);
buf[length] = '\0';
}
return buf;
}
pChar EXPORT IB_UDF_substrlen(const char* s, ISC_SHORT* m, ISC_SHORT* n)
{
/* Created by Claudio Valderrama for the Firebird project,
2001.04.17 We don't want to return NULL when params are wrong
and we'll return the remaining characters if the final position
is greater than the string's length, unless NULL is provided.
*/
if (!s) {
return NULL;
}
char* buf;
long length = static_cast<long>(strlen(s));
if (!length ||
*m < 1 ||
*n < 1 ||
*m > length)
{
buf = (char*)ib_util_malloc(1);
buf[0] = '\0';
}
else
{
// we want from the mth char to the (m+n)th char inclusive, so add one to the length.
// CVC: We need to compensate for n if it's longer than s's length
if (*m + *n - 1 > length) {
length -= *m - 1;
}
else {
length = *n;
}
buf = (char*) ib_util_malloc (length + 1);
memcpy(buf, s + *m - 1, length);
buf[length] = '\0';
}
return buf;
}
ISC_LONG EXPORT IB_UDF_strlen( const char *a)
{
return static_cast<ISC_LONG>(strlen(a));
}
double EXPORT IB_UDF_tan( double *a)
{
return (tan(*a));
}
double EXPORT IB_UDF_tanh( double *a)
{
return (tanh(*a));
}
} // extern "C"

View File

@ -1,38 +0,0 @@
/*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#if defined(__cplusplus) && defined(DARWIN)
#include "firebird.h"
#define EXPORT API_ROUTINE
#else
#define EXPORT
#endif
#define MATHERR matherr
#include <stdarg.h>
#define IB_E 2.7182818284590452354
#define IB_PI 3.14159265358979323846
#define IB_PI_2 1.57079632679489661923
#define IB_PI_4 0.78539816339744830962
#define IB_1_PI 0.31830988618379067154
#define IB_2_PI 0.63661977236758134308
#define IB_2_SQRTPI 1.12837916709551257390
#define IB_SQRT2 1.41421356237309504880
#define IB_SQRT1_2 0.70710678118654752440

View File

@ -1,692 +0,0 @@
/*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Revision 1.2 2000/11/28 06:47:52 fsg
* Changed declaration of ascii_char in ib_udf.sql
* to get correct result as proposed by Claudio Valderrama
* 2001.5.19 Claudio Valderrama, add the declaration of alternative
* substrlen function to handle string,start,length instead.
*
*/
/*****************************************
*
* a b s
*
*****************************************
*
* Functional description:
* Returns the absolute value of a
* number.
*
*****************************************
DECLARE EXTERNAL FUNCTION abs
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_abs' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a c o s
*
*****************************************
*
* Functional description:
* Returns the arccosine of a number
* between -1 and 1, if the number is
* out of bounds it returns NaN, as handled
* by the _matherr routine.
*
*****************************************
DECLARE EXTERNAL FUNCTION acos
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_acos' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a s c i i _ c h a r
*
*****************************************
*
* Functional description:
* Returns the ASCII character corresponding
* with the value passed in.
*
*****************************************
DECLARE EXTERNAL FUNCTION ascii_char
INTEGER
RETURNS CSTRING(1) FREE_IT
ENTRY_POINT 'IB_UDF_ascii_char' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a s c i i _ v a l
*
*****************************************
*
* Functional description:
* Returns the ascii value of the character
* passed in.
*
*****************************************
DECLARE EXTERNAL FUNCTION ascii_val
CHAR(1)
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_ascii_val' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a s i n
*
*****************************************
*
* Functional description:
* Returns the arcsin of a number between
* -1 and 1, if the number is out of
* range NaN is returned.
*
*****************************************
DECLARE EXTERNAL FUNCTION asin
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_asin' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a t a n
*
*****************************************
*
* Functional description:
* Returns the arctangent of a number.
*
*
*****************************************
DECLARE EXTERNAL FUNCTION atan
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_atan' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a t a n 2
*
*****************************************
*
* Functional description:
* Returns the arctangent of the
* first param / the second param.
*
*****************************************
DECLARE EXTERNAL FUNCTION atan2
DOUBLE PRECISION, DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_atan2' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* b i n _ a n d
*
*****************************************
*
* Functional description:
* Returns the result of a binary AND
* operation performed on the two numbers.
*
*****************************************
DECLARE EXTERNAL FUNCTION bin_and
INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_bin_and' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* b i n _ o r
*
*****************************************
*
* Functional description:
* Returns the result of a binary OR
* operation performed on the two numbers.
*
*****************************************
DECLARE EXTERNAL FUNCTION bin_or
INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_bin_or' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* b i n _ x o r
*
*****************************************
*
* Functional description:
* Returns the result of a binary XOR
* operation performed on the two numbers.
*
*****************************************
DECLARE EXTERNAL FUNCTION bin_xor
INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_bin_xor' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* c e i l i n g
*
*****************************************
*
* Functional description:
* Returns a double value representing
* the smallest integer that is greater
* than or equal to the input value.
*
*****************************************
DECLARE EXTERNAL FUNCTION ceiling
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_ceiling' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* c o s
*
*****************************************
*
* Functional description:
* The cos function returns the cosine
* of x. If x is greater than or equal
* to 263, or less than or equal to -263,
* a loss of significance in the result
* of a call to cos occurs, in which case
* the function generates a _TLOSS error
* and returns an indefinite (same as a
* quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION cos
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_cos' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* c o s h
*
*****************************************
*
* Functional description:
* The cosh function returns the hyperbolic cosine
* of x. If x is greater than or equal
* to 263, or less than or equal to -263,
* a loss of significance in the result
* of a call to cos occurs, in which case
* the function generates a _TLOSS error
* and returns an indefinite (same as a
* quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION cosh
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_cosh' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* c o t
*
*****************************************
*
* Functional description:
* Returns 1 over the tangent of the
* input parameter.
*
*****************************************
DECLARE EXTERNAL FUNCTION cot
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_cot' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* d i v
*
*****************************************
*
* Functional description:
* Returns the quotient part of the division
* of the two input parameters.
*
*****************************************/
DECLARE EXTERNAL FUNCTION div
INTEGER, INTEGER
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_div' MODULE_NAME 'ib_udf';
/*****************************************
*
* f l o o r
*
*****************************************
*
* Functional description:
* Returns a floating-point value
* representing the largest integer that
* is less than or equal to x.
*
*****************************************
DECLARE EXTERNAL FUNCTION floor
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_floor' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* u d f _ f r a c
*
*****************************************
*
* Functional description:
* Returns a floating-point value
* representing the fractional part of x.
*
*****************************************/
DECLARE EXTERNAL FUNCTION udf_frac
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_frac' MODULE_NAME 'ib_udf';
/*****************************************
*
* l n
*
*****************************************
*
* Functional description:
* Returns the natural log of a number.
*
*****************************************
DECLARE EXTERNAL FUNCTION ln
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_ln' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l o g
*
*****************************************
*
* Functional description:
* log (x,y) returns the logarithm
* base x of y.
*
*****************************************
DECLARE EXTERNAL FUNCTION log
DOUBLE PRECISION, DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_log' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l o g 1 0
*
*****************************************
*
* Functional description:
* Returns the logarithm base 10 of the
* input parameter.
*
*****************************************
DECLARE EXTERNAL FUNCTION log10
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_log10' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l o w e r
*
*****************************************
*
* Functional description:
* Returns the input string into lower
* case characters. Note: This function
* will not work with international and
* non-ascii characters.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************
DECLARE EXTERNAL FUNCTION lower
CSTRING(255)
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_lower' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l p a d
*
*****************************************
*
* Functional description:
* Appends the given character to beginning
* of the input string until length of the result
* string becomes equal to the given number.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************
DECLARE EXTERNAL FUNCTION lpad
CSTRING(255), INTEGER, CSTRING(1)
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_lpad' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l t r i m
*
*****************************************
*
* Functional description:
* Removes leading spaces from the input
* string.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************/
DECLARE EXTERNAL FUNCTION ltrim
CSTRING(255)
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_ltrim' MODULE_NAME 'ib_udf';
/*****************************************
*
* m o d
*
*****************************************
*
* Functional description:
* Returns the remainder part of the
* division of the two input parameters.
*
*****************************************
DECLARE EXTERNAL FUNCTION mod
INTEGER, INTEGER
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_mod' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* p i
*
*****************************************
*
* Functional description:
* Returns the value of pi = 3.14159...
*
*****************************************
DECLARE EXTERNAL FUNCTION pi
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_pi' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* r a n d
*
*****************************************
*
* Functional description:
* Returns a random number between 0
* and 1. Note the random number
* generator is seeded using the current
* time.
*
*****************************************
DECLARE EXTERNAL FUNCTION rand
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_rand' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* r p a d
*
*****************************************
*
* Functional description:
* Appends the given character to end
* of the input string until length of the result
* string becomes equal to the given number.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************
DECLARE EXTERNAL FUNCTION rpad
CSTRING(255), INTEGER, CSTRING(1)
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_rpad' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* r t r i m
*
*****************************************
*
* Functional description:
* Removes trailing spaces from the input
* string.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************/
DECLARE EXTERNAL FUNCTION rtrim
CSTRING(255)
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_rtrim' MODULE_NAME 'ib_udf';
/*****************************************
*
* s i g n
*
*****************************************
*
* Functional description:
* Returns 1, 0, or -1 depending on whether
* the input value is positive, zero or
* negative, respectively.
*
*****************************************
DECLARE EXTERNAL FUNCTION sign
DOUBLE PRECISION
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_sign' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* s i n
*
*****************************************
*
* Functional description:
* Returns the sine of x. If x is greater
* than or equal to 263, or less than or
* equal to -263, a loss of significance
* in the result occurs, in which case the
* function generates a _TLOSS error and
* returns an indefinite (same as a quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION sin
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_sin' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* s i n h
*
*****************************************
*
* Functional description:
* Returns the hyperbolic sine of x. If x is greater
* than or equal to 263, or less than or
* equal to -263, a loss of significance
* in the result occurs, in which case the
* function generates a _TLOSS error and
* returns an indefinite (same as a quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION sinh
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_sinh' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* s q r t
*
*****************************************
*
* Functional description:
* Returns the square root of a number.
*
*****************************************
DECLARE EXTERNAL FUNCTION sqrt
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_sqrt' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* s u b s t r
*
*****************************************
*
* Functional description:
* substr(s,m,n) returns the substring
* of s which starts at position m and
* ending at position n.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
* Change by Claudio Valderrama: when n>length(s),
* the result will be the original string instead
* of NULL as it was originally designed.
*
*****************************************/
DECLARE EXTERNAL FUNCTION substr
CSTRING(255), SMALLINT, SMALLINT
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_substr' MODULE_NAME 'ib_udf';
/*****************************************
*
* s u b s t r l e n
*
*****************************************
*
* Functional description:
* substrlen(s,i,l) returns the substring
* of s which starts at position i and
* ends at position i+l-1, being l the length.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************/
DECLARE EXTERNAL FUNCTION substrlen
CSTRING(255), SMALLINT, SMALLINT
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_substrlen' MODULE_NAME 'ib_udf';
/*****************************************
*
* s t r l e n
*
*****************************************
*
* Functional description:
* Returns the length of a given string.
*
*****************************************/
DECLARE EXTERNAL FUNCTION strlen
CSTRING(32767)
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_strlen' MODULE_NAME 'ib_udf';
/*****************************************
*
* t a n
*
*****************************************
*
* Functional description:
* Returns the tangent of x. If x is
* greater than or equal to 263, or less
* than or equal to -263, a loss of
* significance in the result occurs, in
* which case the function generates a
* _TLOSS error and returns an indefinite
* (same as a quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION tan
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_tan' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* t a n h
*
*****************************************
*
* Functional description:
* Returns the tangent of x. If x is
* greater than or equal to 263, or less
* than or equal to -263, a loss of
* significance in the result occurs, in
* which case the function generates a
* _TLOSS error and returns an indefinite
* (same as a quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION tanh
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_tanh' MODULE_NAME 'ib_udf'; */

View File

@ -1,716 +0,0 @@
/*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Revision 1.2 2000/11/28 06:47:52 fsg
* Changed declaration of ascii_char in ib_udf.sql
* to get correct result as proposed by Claudio Valderrama
* 2001.5.19 Claudio Valderrama, add the declaration of alternative
* substrlen function to handle string,start,length instead.
* 2004.9.1 Claudio Valderrama, changed some UDF's to be able to detect NULL
* and renamed the resulting file as ib_udf2.sql.
*
*/
/*****************************************
*
* a b s
*
*****************************************
*
* Functional description:
* Returns the absolute value of a
* number.
*
*****************************************
DECLARE EXTERNAL FUNCTION abs
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_abs' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a c o s
*
*****************************************
*
* Functional description:
* Returns the arccosine of a number
* between -1 and 1, if the number is
* out of bounds it returns NaN, as handled
* by the _matherr routine.
*
*****************************************
DECLARE EXTERNAL FUNCTION acos
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_acos' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a s c i i _ c h a r
*
*****************************************
*
* Functional description:
* Returns the ASCII character corresponding
* with the value passed in.
*
*****************************************
DECLARE EXTERNAL FUNCTION ascii_char
INTEGER NULL
RETURNS CSTRING(1) FREE_IT
ENTRY_POINT 'IB_UDF_ascii_char' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a s c i i _ v a l
*
*****************************************
*
* Functional description:
* Returns the ascii value of the character
* passed in.
*
*****************************************
DECLARE EXTERNAL FUNCTION ascii_val
CHAR(1)
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_ascii_val' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a s i n
*
*****************************************
*
* Functional description:
* Returns the arcsin of a number between
* -1 and 1, if the number is out of
* range NaN is returned.
*
*****************************************
DECLARE EXTERNAL FUNCTION asin
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_asin' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a t a n
*
*****************************************
*
* Functional description:
* Returns the arctangent of a number.
*
*
*****************************************
DECLARE EXTERNAL FUNCTION atan
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_atan' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* a t a n 2
*
*****************************************
*
* Functional description:
* Returns the arctangent of the
* first param / the second param.
*
*****************************************
DECLARE EXTERNAL FUNCTION atan2
DOUBLE PRECISION, DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_atan2' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* b i n _ a n d
*
*****************************************
*
* Functional description:
* Returns the result of a binary AND
* operation performed on the two numbers.
*
*****************************************
DECLARE EXTERNAL FUNCTION bin_and
INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_bin_and' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* b i n _ o r
*
*****************************************
*
* Functional description:
* Returns the result of a binary OR
* operation performed on the two numbers.
*
*****************************************
DECLARE EXTERNAL FUNCTION bin_or
INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_bin_or' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* b i n _ x o r
*
*****************************************
*
* Functional description:
* Returns the result of a binary XOR
* operation performed on the two numbers.
*
*****************************************
DECLARE EXTERNAL FUNCTION bin_xor
INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_bin_xor' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* c e i l i n g
*
*****************************************
*
* Functional description:
* Returns a double value representing
* the smallest integer that is greater
* than or equal to the input value.
*
*****************************************
DECLARE EXTERNAL FUNCTION ceiling
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_ceiling' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* c o s
*
*****************************************
*
* Functional description:
* The cos function returns the cosine
* of x. If x is greater than or equal
* to 263, or less than or equal to -263,
* a loss of significance in the result
* of a call to cos occurs, in which case
* the function generates a _TLOSS error
* and returns an indefinite (same as a
* quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION cos
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_cos' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* c o s h
*
*****************************************
*
* Functional description:
* The cosh function returns the hyperbolic cosine
* of x. If x is greater than or equal
* to 263, or less than or equal to -263,
* a loss of significance in the result
* of a call to cos occurs, in which case
* the function generates a _TLOSS error
* and returns an indefinite (same as a
* quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION cosh
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_cosh' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* c o t
*
*****************************************
*
* Functional description:
* Returns 1 over the tangent of the
* input parameter.
*
*****************************************
DECLARE EXTERNAL FUNCTION cot
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_cot' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* d i v
*
*****************************************
*
* Functional description:
* Returns the quotient part of the division
* of the two input parameters.
*
*****************************************/
DECLARE EXTERNAL FUNCTION div
INTEGER, INTEGER
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_div' MODULE_NAME 'ib_udf';
/*****************************************
*
* f l o o r
*
*****************************************
*
* Functional description:
* Returns a floating-point value
* representing the largest integer that
* is less than or equal to x.
*
*****************************************
DECLARE EXTERNAL FUNCTION floor
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_floor' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* u d f _ f r a c
*
*****************************************
*
* Functional description:
* Returns a floating-point value
* representing the fractional part of x.
*
*****************************************/
DECLARE EXTERNAL FUNCTION udf_frac
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_frac' MODULE_NAME 'ib_udf';
/*****************************************
*
* l n
*
*****************************************
*
* Functional description:
* Returns the natural log of a number.
*
*****************************************
DECLARE EXTERNAL FUNCTION ln
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_ln' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l o g
*
*****************************************
*
* Functional description:
* log (x,y) returns the logarithm
* base x of y.
*
*****************************************
DECLARE EXTERNAL FUNCTION log
DOUBLE PRECISION, DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_log' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l o g 1 0
*
*****************************************
*
* Functional description:
* Returns the logarithm base 10 of the
* input parameter.
*
*****************************************
DECLARE EXTERNAL FUNCTION log10
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_log10' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l o w e r
*
*****************************************
*
* Functional description:
* Returns the input string into lower
* case characters. Note: This function
* will not work with international and
* non-ascii characters.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************
DECLARE EXTERNAL FUNCTION "LOWER"
CSTRING(255) NULL
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_lower' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l p a d
*
*****************************************
*
* Functional description:
* Appends the given character to beginning
* of the input string until length of the result
* string becomes equal to the given number.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************
DECLARE EXTERNAL FUNCTION lpad
CSTRING(255) NULL, INTEGER, CSTRING(1) NULL
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_lpad' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* l t r i m
*
*****************************************
*
* Functional description:
* Removes leading spaces from the input
* string.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************/
DECLARE EXTERNAL FUNCTION ltrim
CSTRING(255) NULL
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_ltrim' MODULE_NAME 'ib_udf';
/*****************************************
*
* m o d
*
*****************************************
*
* Functional description:
* Returns the remainder part of the
* division of the two input parameters.
*
*****************************************
DECLARE EXTERNAL FUNCTION mod
INTEGER, INTEGER
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_mod' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* p i
*
*****************************************
*
* Functional description:
* Returns the value of pi = 3.14159...
*
*****************************************
DECLARE EXTERNAL FUNCTION pi
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_pi' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* r a n d
*
*****************************************
*
* Functional description:
* Returns a random number between 0
* and 1.
*
*
* Note: Use srand to seed the
* random number generator.
* This behavior has been changed.
*****************************************
DECLARE EXTERNAL FUNCTION rand
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_rand' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* r p a d
*
*****************************************
*
* Functional description:
* Appends the given character to end
* of the input string until length of the result
* string becomes equal to the given number.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************
DECLARE EXTERNAL FUNCTION rpad
CSTRING(255) NULL, INTEGER, CSTRING(1) NULL
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_rpad' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* r t r i m
*
*****************************************
*
* Functional description:
* Removes trailing spaces from the input
* string.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************/
DECLARE EXTERNAL FUNCTION rtrim
CSTRING(255) NULL
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_rtrim' MODULE_NAME 'ib_udf';
/*****************************************
*
* s i g n
*
*****************************************
*
* Functional description:
* Returns 1, 0, or -1 depending on whether
* the input value is positive, zero or
* negative, respectively.
*
*****************************************
DECLARE EXTERNAL FUNCTION sign
DOUBLE PRECISION
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_sign' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* s i n
*
*****************************************
*
* Functional description:
* Returns the sine of x. If x is greater
* than or equal to 263, or less than or
* equal to -263, a loss of significance
* in the result occurs, in which case the
* function generates a _TLOSS error and
* returns an indefinite (same as a quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION sin
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_sin' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* s i n h
*
*****************************************
*
* Functional description:
* Returns the hyperbolic sine of x. If x is greater
* than or equal to 263, or less than or
* equal to -263, a loss of significance
* in the result occurs, in which case the
* function generates a _TLOSS error and
* returns an indefinite (same as a quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION sinh
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_sinh' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* s q r t
*
*****************************************
*
* Functional description:
* Returns the square root of a number.
*
*****************************************
DECLARE EXTERNAL FUNCTION sqrt
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_sqrt' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* s r a n d
*
*****************************************
*
* Functional description:
* Returns a random number between 0
* and 1. Note the random number
* generator is seeded using the current
* time.
*
*****************************************/
DECLARE EXTERNAL FUNCTION srand
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_srand' MODULE_NAME 'ib_udf';
/*****************************************
*
* s u b s t r
*
*****************************************
*
* Functional description:
* substr(s,m,n) returns the substring
* of s which starts at position m and
* ending at position n.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
* Change by Claudio Valderrama: when n>length(s),
* the result will be the original string instead
* of NULL as it was originally designed.
*
*****************************************/
DECLARE EXTERNAL FUNCTION substr
CSTRING(255) NULL, SMALLINT, SMALLINT
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_substr' MODULE_NAME 'ib_udf';
/*****************************************
*
* s u b s t r l e n
*
*****************************************
*
* Functional description:
* substrlen(s,i,l) returns the substring
* of s which starts at position i and
* ends at position i+l-1, being l the length.
* Note: This function is NOT limited to
* receiving and returning only 255 characters,
* rather, it can use as long as 32767
* characters which is the limit on an
* INTERBASE character string.
*
*****************************************/
DECLARE EXTERNAL FUNCTION substrlen
CSTRING(255) NULL, SMALLINT, SMALLINT
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_substrlen' MODULE_NAME 'ib_udf';
/*****************************************
*
* s t r l e n
*
*****************************************
*
* Functional description:
* Returns the length of a given string.
*
*****************************************/
DECLARE EXTERNAL FUNCTION strlen
CSTRING(32767) CHARACTER SET NONE
RETURNS INTEGER BY VALUE
ENTRY_POINT 'IB_UDF_strlen' MODULE_NAME 'ib_udf';
/*****************************************
*
* t a n
*
*****************************************
*
* Functional description:
* Returns the tangent of x. If x is
* greater than or equal to 263, or less
* than or equal to -263, a loss of
* significance in the result occurs, in
* which case the function generates a
* _TLOSS error and returns an indefinite
* (same as a quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION tan
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_tan' MODULE_NAME 'ib_udf'; */
/*****************************************
*
* t a n h
*
*****************************************
*
* Functional description:
* Returns the tangent of x. If x is
* greater than or equal to 263, or less
* than or equal to -263, a loss of
* significance in the result occurs, in
* which case the function generates a
* _TLOSS error and returns an indefinite
* (same as a quiet NaN).
*
*****************************************
DECLARE EXTERNAL FUNCTION tanh
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_tanh' MODULE_NAME 'ib_udf'; */

View File

@ -19,7 +19,7 @@
*/
#include <stdlib.h>
#include "ib_udf.h"
#include "ib_util.h"
#include "firebird.h"
typedef void* VoidPtr;

View File

@ -152,7 +152,7 @@
#define FB__META_FB_BOOLEAN \
builder->setType(status, index, SQL_BOOLEAN); \
builder->setLength(status, index, sizeof(ISC_BOOLEAN));
builder->setLength(status, index, sizeof(FB_BOOLEAN));
#define FB__META_FB_DATE \
builder->setType(status, index, SQL_DATE); \