/*
* Copyright (c) 2004-2019 Tada AB and other contributors, as listed below.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the The BSD 3-Clause License
* which accompanies this distribution, and is available at
* http://opensource.org/licenses/BSD-3-Clause
*
* Contributors:
* Tada AB
* Chapman Flack
*/
#ifndef __pljava_pljava_h
#define __pljava_pljava_h
#include
#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************************
* Misc stuff to tie Java to PostgreSQL. TRY/CATCH macros, thread
* blocking, etc. resides here.
*
* @author Thomas Hallgren
*****************************************************************/
#ifdef __STRICT_ANSI__
extern int vsnprintf(char* buf, size_t count, const char* format, va_list arg);
#endif
#include
#include
#include
#include
#include
#include
#include
/*
* AssertVariableIsOfType appeared in PG9.3. Can test for the macro directly.
* Likewise for StaticAssertStmt.
*/
#ifndef AssertVariableIsOfType
#define AssertVariableIsOfType(varname, typename)
#endif
#ifndef StaticAssertStmt
#define StaticAssertStmt(condition, errmessage)
#endif
/*
* AllocSetContextCreate sprouted these macros for common combinations of
* size parameters in PG 9.6. It becomes /necessary/ to use them in PG 11
* when using AllocSetContextCreate (which becomes a macro in that version)
* and not the (new in that version) AllocSetContextCreateExtended.
*/
#if PG_VERSION_NUM < 90600
#define ALLOCSET_DEFAULT_SIZES \
ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
#define ALLOCSET_SMALL_SIZES \
ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE
#define ALLOCSET_START_SMALL_SIZES \
ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
#endif
/*
* GETSTRUCT require "access/htup_details.h" to be included in PG9.3
*/
#if PG_VERSION_NUM >= 90300
#include "access/htup_details.h"
#endif
/*
* PG_*_{MIN,MAX} macros (which happen, conveniently, to match Java's datatypes
* (the signed ones, anyway), appear in PG 9.5. Could test for them directly,
* but explicit version conditionals may be easier to find and prune when the
* back-compatibility horizon passes them. Here are only the ones being used.
*/
#if PG_VERSION_NUM < 90500
#define PG_INT32_MAX (0x7FFFFFFF)
#endif
extern void* mainThreadId;
extern JNIEnv* currentJNIEnv;
extern MemoryContext JavaMemoryContext;
/* The STACK_BASE_PUSH / STACK_BASE_POP macros are used to surround code where
* a thread will be entering the backend that isn't necessarily the same one
* that has called into PL/Java from the backend. (This can only occur when the
* threadlock has been released by a call into PL/Java from whatever thread had
* been executing in the backend, and the thread that is about to enter the
* backend now holds the lock.) The backend does proactive checking of stack
* depth as a precaution, and that check would be incorrect if comparing the
* current stack pointer to some other thread's stack base. Therefore, these
* macros will check whether the thread is indeed different from the last one
* in the backend and, if so, substitute this thread's stack base for the old
* value, which is then restored by STACK_BASE_POP.
*
* Large caution, though: what this WANTS to do is change PG's notion of the
* BASE of this thread's stack, and that's not at all what it really does;
* set_stack_base() uses the CURRENT stack position, which could be who knows
* how deep already, and there is really no way to do better because the JVM
* doesn't expose the base of a thread's stack anyway (or even drop any hints
* about how it implements stacks). So, all this fussing around may indeed
* prevent nuisance stack-overflow aborts caused by comparing pointers to
* different stacks ... but it may only serve to conceal, or prevent recovery
* from, actual excessive stack use.
*
* stack_base_ptr was static before PG 8.1. By executive decision, PL/Java now
* has 8.1 as a back compatibility limit; no empty #defines here for earlier.
*/
#if 90104<=PG_VERSION_NUM || \
90008<=PG_VERSION_NUM && PG_VERSION_NUM<90100 || \
80412<=PG_VERSION_NUM && PG_VERSION_NUM<90000 || \
80319<=PG_VERSION_NUM && PG_VERSION_NUM<80400
#define NEED_MISCADMIN_FOR_STACK_BASE
#define _STACK_BASE_TYPE pg_stack_base_t
#define _STACK_BASE_SET saveStackBasePtr = set_stack_base()
#define _STACK_BASE_RESTORE restore_stack_base(saveStackBasePtr)
#else
extern
#if PG_VERSION_NUM < 80300
DLLIMPORT
#else
PGDLLIMPORT
#endif
char* stack_base_ptr;
#define _STACK_BASE_TYPE char*
#define _STACK_BASE_SET \
saveStackBasePtr = stack_base_ptr; \
stack_base_ptr = (char*)&saveMainThreadId
#define _STACK_BASE_RESTORE stack_base_ptr = saveStackBasePtr
#endif
#define STACK_BASE_VARS \
void* saveMainThreadId = 0; \
_STACK_BASE_TYPE saveStackBasePtr;
#define STACK_BASE_PUSH(threadId) \
if(threadId != mainThreadId) \
{ \
_STACK_BASE_SET; \
saveMainThreadId = mainThreadId; \
mainThreadId = threadId; \
elog(DEBUG2, "Set stack base for thread " UINT64_FORMAT, \
(uint64)mainThreadId); \
}
#define STACK_BASE_POP() \
if(saveMainThreadId != 0) \
{ \
_STACK_BASE_RESTORE; \
mainThreadId = saveMainThreadId; \
elog(DEBUG2, "Restored stack base for thread " UINT64_FORMAT, \
(uint64)mainThreadId); \
}
/* NOTE!
* When using the PG_TRY, PG_CATCH, PG_TRY_END family of macros,
* it is an ABSOLUTE NECESSITY to use the PG_TRY_RETURN or
* PG_TRY_RETURN_VOID in place of any return.
*/
#define PG_TRY_POP \
PG_exception_stack = save_exception_stack; \
error_context_stack = save_context_stack
#define PG_TRY_RETURN(retVal) { PG_TRY_POP; return retVal; }
#define PG_TRY_RETURN_VOID { PG_TRY_POP; return; }
/* Some error codes missing from errcodes.h
*
* Class 07 - Dynamic SQL Exception
*/
#define ERRCODE_INVALID_DESCRIPTOR_INDEX MAKE_SQLSTATE('0','7', '0','0','9')
/*
* Union used when coercing void* to jlong and vice versa
*/
typedef union
{
void* ptrVal;
jlong longVal; /* 64 bit quantity */
} Ptr2Long;
struct Invocation_;
typedef struct Invocation_ Invocation;
struct Function_;
typedef struct Function_* Function;
#ifdef __cplusplus
}
#endif
#endif