parent
726ef535ea
commit
d98b4817b3
@ -1,4 +1,4 @@
|
||||
from engine.ast import Context, ast_node
|
||||
from common.ast import Context, ast_node
|
||||
saved_cxt = None
|
||||
|
||||
def initialize(cxt = None, keep = False):
|
@ -1,9 +1,9 @@
|
||||
# code-gen for data decl languages
|
||||
|
||||
from engine.orderby import orderby
|
||||
from engine.ast import ColRef, TableInfo, ast_node, Context, include
|
||||
from engine.scan import scan
|
||||
from engine.utils import base62uuid
|
||||
from common.orderby import orderby
|
||||
from common.ast import ColRef, TableInfo, ast_node, Context, include
|
||||
from common.scan import scan
|
||||
from common.utils import base62uuid
|
||||
|
||||
class create_table(ast_node):
|
||||
name = 'create_table'
|
@ -1,8 +1,8 @@
|
||||
from engine.ast import ColRef, TableInfo, ast_node
|
||||
from engine.orderby import assumption
|
||||
from engine.scan import scan
|
||||
from engine.utils import base62uuid
|
||||
from engine.expr import expr
|
||||
from common.ast import ColRef, TableInfo, ast_node
|
||||
from common.orderby import assumption
|
||||
from common.scan import scan
|
||||
from common.utils import base62uuid
|
||||
from common.expr import expr
|
||||
|
||||
class groupby(ast_node):
|
||||
name = '_groupby'
|
@ -0,0 +1,6 @@
|
||||
from common.ast import ast_node
|
||||
|
||||
|
||||
class join(ast_node):
|
||||
name='join'
|
||||
|
@ -1,6 +1,6 @@
|
||||
from engine.ast import ColRef, TableInfo, View, ast_node, Context
|
||||
from engine.utils import base62uuid, seps
|
||||
from engine.expr import expr
|
||||
from common.ast import ColRef, TableInfo, View, ast_node, Context
|
||||
from common.utils import base62uuid, seps
|
||||
from common.expr import expr
|
||||
|
||||
class order_item:
|
||||
def __init__(self, name, node, order = True):
|
@ -1,11 +1,11 @@
|
||||
from engine.ast import ColRef, TableInfo, ast_node, Context, include
|
||||
from engine.groupby import groupby
|
||||
from engine.join import join
|
||||
from engine.expr import expr
|
||||
from engine.orderby import assumption, orderby
|
||||
from engine.scan import filter
|
||||
from engine.utils import base62uuid, enlist, base62alp, has_other
|
||||
from engine.ddl import create_table, outfile
|
||||
from common.ast import ColRef, TableInfo, ast_node, Context, include
|
||||
from common.groupby import groupby
|
||||
from common.join import join
|
||||
from common.expr import expr
|
||||
from common.orderby import assumption, orderby
|
||||
from common.scan import filter
|
||||
from common.utils import base62uuid, enlist, base62alp, has_other
|
||||
from common.ddl import create_table, outfile
|
||||
import copy
|
||||
|
||||
class projection(ast_node):
|
@ -1,7 +1,7 @@
|
||||
from xmlrpc.client import Boolean
|
||||
from engine.ast import ColRef, TableInfo, View, ast_node, Context
|
||||
from engine.utils import base62uuid
|
||||
from engine.expr import expr
|
||||
from common.ast import ColRef, TableInfo, View, ast_node, Context
|
||||
from common.utils import base62uuid
|
||||
from common.expr import expr
|
||||
|
||||
class scan(ast_node):
|
||||
name = 'scan'
|
@ -0,0 +1,15 @@
|
||||
ifeq ($(PYTHON_EXEC),)
|
||||
PYTHON_EXEC=python3
|
||||
endif
|
||||
PYTHON_CONFIG=$(PYTHON_EXEC)-config
|
||||
PYTHON_LDFLAGS=$(shell echo `$(PYTHON_CONFIG) --ldflags` | sed 's/^-L\([^[:space:]]*\).*$$/\1/')/lib$(PYTHON_EXEC)*.a
|
||||
all:
|
||||
rm ../../libdraw.so; \
|
||||
$(CXX) --shared app2.cpp --std=c++2a -I../.. -I/usr/local/opt/matplotplusplus/include -L../.. -L/usr/local/opt/matplotplusplus/lib/ -lmatplot -laquery -o ../../libdraw.so
|
||||
py:
|
||||
rm ../../libdraw.so; \
|
||||
$(CXX) --shared app.cpp --std=c++2a -I../.. `$(PYTHON_CONFIG) --cflags` -O0 -g3 $(PYTHON_LDFLAGS) ../../libaquery.a -o ../../libdraw.so
|
||||
exe:
|
||||
$(CXX) app.cpp --std=c++2a -I../.. `$(PYTHON_CONFIG) --cflags` -O0 -g3 $(PYTHON_LDFLAGS) ../../libaquery.a -o a.out
|
||||
info:
|
||||
$(info $(PYTHON_LDFLAGS))
|
@ -0,0 +1,47 @@
|
||||
#include <Python.h>
|
||||
#include <random>
|
||||
#include <ctime>
|
||||
#include <cstdio>
|
||||
#include "server/vector_type.hpp"
|
||||
#include "sdk/aquery.h"
|
||||
#include "unistd.h"
|
||||
__AQEXPORT__(bool)
|
||||
draw(vector_type<int> x, vector_type<int> y) {
|
||||
puts("sibal!");
|
||||
auto pid = fork();
|
||||
int status = 0;
|
||||
if (pid == 0) {
|
||||
//PyOS_AfterFork();
|
||||
Py_InitializeEx
|
||||
Py_Initialize();
|
||||
|
||||
PyRun_SimpleString("print(globals())");
|
||||
PyRun_SimpleString("import os");
|
||||
PyRun_SimpleString("sys.path.append(os.getcwd()+'/demo/Python Integration')");
|
||||
//PyErr_Print();
|
||||
PyRun_SimpleString("print('fuck')");
|
||||
auto py_strapp = PyUnicode_DecodeFSDefault("app");
|
||||
auto py_module = PyImport_Import(py_strapp);
|
||||
// Py_DECREF(py_strapp);
|
||||
auto py_entrypt = PyObject_GetAttrString(py_module, "draw");
|
||||
|
||||
auto mvx = PyMemoryView_FromMemory((char*)x.container, x.size * sizeof(int), PyBUF_WRITE),
|
||||
mvy = PyMemoryView_FromMemory((char*)y.container, y.size * sizeof(int), PyBUF_WRITE);
|
||||
PyObject_CallObject(py_entrypt, PyTuple_Pack(2, mvx, mvy));
|
||||
// Py_DECREF(mvx);
|
||||
// Py_DECREF(mvy);
|
||||
// Py_DECREF(py_entrypt);
|
||||
// Py_DECREF(py_module);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
while(wait(&status) > 0);
|
||||
//getchar();
|
||||
}
|
||||
return true;
|
||||
//return Py_FinalizeEx() >= 0;
|
||||
}
|
||||
|
||||
int main(){
|
||||
draw({1,2,3}, {4,5,6});
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def draw(x, y):
|
||||
plt.figure()
|
||||
|
||||
plt.plot(x.cast('i', shape=(len(x)//4, )),
|
||||
y.cast('i', shape=(len(y)//4, )))
|
||||
plt.show()
|
||||
|
@ -0,0 +1,12 @@
|
||||
#include "server/vector_type.hpp"
|
||||
#include "sdk/aquery.h"
|
||||
#include "matplot/matplot.h"
|
||||
|
||||
__AQEXPORT__(bool)
|
||||
draw(vector_type<int> x, vector_type<int> y) {
|
||||
using namespace matplot;
|
||||
auto plt = gca();
|
||||
plt->plot(vector_type_std{x}, vector_type_std{y});
|
||||
show();
|
||||
return true;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
from engine.ast import ast_node
|
||||
|
||||
|
||||
class join(ast_node):
|
||||
name='join'
|
||||
|
Binary file not shown.
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef EXCEPTION_BUFFER_H
|
||||
#define EXCEPTION_BUFFER_H
|
||||
|
||||
#include "monetdb_config.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
typedef struct exception_buffer {
|
||||
jmp_buf state;
|
||||
int code;
|
||||
char *msg;
|
||||
int enabled;
|
||||
} exception_buffer;
|
||||
|
||||
extern exception_buffer *eb_init( exception_buffer *eb );
|
||||
|
||||
/* != 0 on when we return to the savepoint */
|
||||
#define eb_savepoint(eb) ((eb)->enabled=1,setjmp((eb)->state))
|
||||
extern _Noreturn void eb_error( exception_buffer *eb, char *msg, int val );
|
||||
|
||||
#endif /* EXCEPTION_BUFFER_H */
|
@ -0,0 +1,463 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _GDK_ATOMS_H_
|
||||
#define _GDK_ATOMS_H_
|
||||
|
||||
/* atomFromStr returns the number of bytes of the input string that
|
||||
* were processed. atomToStr returns the length of the string
|
||||
* produced. Both functions return -1 on (any kind of) failure. If
|
||||
* *dst is not NULL, *len specifies the available space. If there is
|
||||
* not enough space, or if *dst is NULL, *dst will be freed (if not
|
||||
* NULL) and a new buffer will be allocated and returned in *dst.
|
||||
* *len will be set to reflect the actual size allocated. If
|
||||
* allocation fails, *dst will be NULL on return and *len is
|
||||
* undefined. In any case, if the function returns, *buf is either
|
||||
* NULL or a valid pointer and then *len is the size of the area *buf
|
||||
* points to.
|
||||
*
|
||||
* atomCmp returns a value less than zero/equal to zero/greater than
|
||||
* zer if the first argument points to a values which is deemed
|
||||
* smaller/equal to/larger than the value pointed to by the second
|
||||
* argument.
|
||||
*
|
||||
* atomHash calculates a hash function for the value pointed to by the
|
||||
* argument.
|
||||
*/
|
||||
|
||||
#define IDLENGTH 64 /* maximum BAT id length */
|
||||
|
||||
typedef struct {
|
||||
/* simple attributes */
|
||||
char name[IDLENGTH];
|
||||
uint8_t storage; /* stored as another type? */
|
||||
bool linear; /* atom can be ordered linearly */
|
||||
uint16_t size; /* fixed size of atom */
|
||||
|
||||
/* automatically generated fields */
|
||||
const void *atomNull; /* global nil value */
|
||||
|
||||
/* generic (fixed + varsized atom) ADT functions */
|
||||
ssize_t (*atomFromStr) (const char *src, size_t *len, void **dst, bool external);
|
||||
ssize_t (*atomToStr) (char **dst, size_t *len, const void *src, bool external);
|
||||
void *(*atomRead) (void *dst, size_t *dstlen, stream *s, size_t cnt);
|
||||
gdk_return (*atomWrite) (const void *src, stream *s, size_t cnt);
|
||||
int (*atomCmp) (const void *v1, const void *v2);
|
||||
BUN (*atomHash) (const void *v);
|
||||
/* optional functions */
|
||||
gdk_return (*atomFix) (const void *atom);
|
||||
gdk_return (*atomUnfix) (const void *atom);
|
||||
|
||||
/* varsized atom-only ADT functions */
|
||||
var_t (*atomPut) (BAT *, var_t *off, const void *src);
|
||||
void (*atomDel) (Heap *, var_t *atom);
|
||||
size_t (*atomLen) (const void *atom);
|
||||
gdk_return (*atomHeap) (Heap *, size_t);
|
||||
} atomDesc;
|
||||
|
||||
#define MAXATOMS 128
|
||||
|
||||
gdk_export atomDesc BATatoms[MAXATOMS];
|
||||
gdk_export int GDKatomcnt;
|
||||
|
||||
gdk_export int ATOMallocate(const char *nme);
|
||||
gdk_export int ATOMindex(const char *nme);
|
||||
|
||||
gdk_export str ATOMname(int id);
|
||||
gdk_export size_t ATOMlen(int id, const void *v);
|
||||
gdk_export void *ATOMnil(int id)
|
||||
__attribute__((__malloc__));
|
||||
gdk_export int ATOMprint(int id, const void *val, stream *fd);
|
||||
gdk_export char *ATOMformat(int id, const void *val);
|
||||
|
||||
gdk_export void *ATOMdup(int id, const void *val);
|
||||
|
||||
/*
|
||||
* @- maximum atomic string lengths
|
||||
*/
|
||||
#define bitStrlen 8
|
||||
#define bteStrlen 8
|
||||
#define shtStrlen 12
|
||||
#define intStrlen 24
|
||||
#if SIZEOF_OID == SIZEOF_INT
|
||||
#define oidStrlen 24
|
||||
#else
|
||||
#define oidStrlen 48
|
||||
#endif
|
||||
#if SIZEOF_PTR == SIZEOF_INT
|
||||
#define ptrStrlen 24
|
||||
#else
|
||||
#define ptrStrlen 48
|
||||
#endif
|
||||
#define lngStrlen 48
|
||||
#ifdef HAVE_HGE
|
||||
#define hgeStrlen 96
|
||||
#endif
|
||||
#define fltStrlen 48
|
||||
#define dblStrlen 96
|
||||
|
||||
/*
|
||||
* The system comes with the traditional atomic types: int (4 bytes),
|
||||
* bool(1 byte) and str (variable). In addition, we support the notion
|
||||
* of an OID type, which ensures uniqueness of its members. This
|
||||
* leads to the following type descriptor table.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_HGE
|
||||
gdk_export ssize_t hgeFromStr(const char *src, size_t *len, hge **dst, bool external);
|
||||
gdk_export ssize_t hgeToStr(str *dst, size_t *len, const hge *src, bool external);
|
||||
#endif
|
||||
gdk_export ssize_t lngFromStr(const char *src, size_t *len, lng **dst, bool external);
|
||||
gdk_export ssize_t lngToStr(str *dst, size_t *len, const lng *src, bool external);
|
||||
gdk_export ssize_t intFromStr(const char *src, size_t *len, int **dst, bool external);
|
||||
gdk_export ssize_t intToStr(str *dst, size_t *len, const int *src, bool external);
|
||||
gdk_export ssize_t batFromStr(const char *src, size_t *len, bat **dst, bool external);
|
||||
gdk_export ssize_t batToStr(str *dst, size_t *len, const bat *src, bool external);
|
||||
gdk_export ssize_t ptrFromStr(const char *src, size_t *len, ptr **dst, bool external);
|
||||
gdk_export ssize_t ptrToStr(str *dst, size_t *len, const ptr *src, bool external);
|
||||
gdk_export ssize_t bitFromStr(const char *src, size_t *len, bit **dst, bool external);
|
||||
gdk_export ssize_t bitToStr(str *dst, size_t *len, const bit *src, bool external);
|
||||
gdk_export ssize_t OIDfromStr(const char *src, size_t *len, oid **dst, bool external);
|
||||
gdk_export ssize_t OIDtoStr(str *dst, size_t *len, const oid *src, bool external);
|
||||
gdk_export ssize_t shtFromStr(const char *src, size_t *len, sht **dst, bool external);
|
||||
gdk_export ssize_t shtToStr(str *dst, size_t *len, const sht *src, bool external);
|
||||
gdk_export ssize_t bteFromStr(const char *src, size_t *len, bte **dst, bool external);
|
||||
gdk_export ssize_t bteToStr(str *dst, size_t *len, const bte *src, bool external);
|
||||
gdk_export ssize_t fltFromStr(const char *src, size_t *len, flt **dst, bool external);
|
||||
gdk_export ssize_t fltToStr(str *dst, size_t *len, const flt *src, bool external);
|
||||
gdk_export ssize_t dblFromStr(const char *src, size_t *len, dbl **dst, bool external);
|
||||
gdk_export ssize_t dblToStr(str *dst, size_t *len, const dbl *src, bool external);
|
||||
gdk_export ssize_t GDKstrFromStr(unsigned char *restrict dst, const unsigned char *restrict src, ssize_t len);
|
||||
gdk_export ssize_t strFromStr(const char *restrict src, size_t *restrict len, str *restrict dst, bool external);
|
||||
gdk_export size_t escapedStrlen(const char *restrict src, const char *sep1, const char *sep2, int quote);
|
||||
gdk_export size_t escapedStr(char *restrict dst, const char *restrict src, size_t dstlen, const char *sep1, const char *sep2, int quote);
|
||||
/*
|
||||
* @- nil values
|
||||
* All types have a single value designated as a NIL value. It
|
||||
* designates a missing value and it is ignored (forbidden) in several
|
||||
* primitives. The current policy is to use the smallest value in any
|
||||
* ordered domain. The routine atomnil returns a pointer to the nil
|
||||
* value representation.
|
||||
*/
|
||||
#define GDK_bit_max ((bit) 1)
|
||||
#define GDK_bit_min ((bit) 0)
|
||||
#define GDK_bte_max ((bte) INT8_MAX)
|
||||
#define GDK_bte_min ((bte) INT8_MIN+1)
|
||||
#define GDK_sht_max ((sht) INT16_MAX)
|
||||
#define GDK_sht_min ((sht) INT16_MIN+1)
|
||||
#define GDK_int_max ((int) INT32_MAX)
|
||||
#define GDK_int_min ((int) INT32_MIN+1)
|
||||
#define GDK_lng_max ((lng) INT64_MAX)
|
||||
#define GDK_lng_min ((lng) INT64_MIN+1)
|
||||
#ifdef HAVE_HGE
|
||||
#define GDK_hge_max ((((hge) 1) << 126) - 1 + (((hge) 1) << 126))
|
||||
#define GDK_hge_min (-GDK_hge_max)
|
||||
#endif
|
||||
#define GDK_flt_max ((flt) FLT_MAX)
|
||||
#define GDK_flt_min ((flt) -FLT_MAX)
|
||||
#define GDK_dbl_max ((dbl) DBL_MAX)
|
||||
#define GDK_dbl_min ((dbl) -DBL_MAX)
|
||||
#define GDK_oid_max (((oid) 1 << ((8 * SIZEOF_OID) - 1)) - 1)
|
||||
#define GDK_oid_min ((oid) 0)
|
||||
/* representation of the nil */
|
||||
gdk_export const bte bte_nil;
|
||||
gdk_export const sht sht_nil;
|
||||
gdk_export const int int_nil;
|
||||
#ifdef NAN_CANNOT_BE_USED_AS_INITIALIZER
|
||||
/* Definition of NAN is seriously broken on Intel compiler (at least
|
||||
* in some versions), so we work around it. */
|
||||
union _flt_nil_t {
|
||||
uint32_t l;
|
||||
flt f;
|
||||
};
|
||||
gdk_export const union _flt_nil_t _flt_nil_;
|
||||
#define flt_nil (_flt_nil_.f)
|
||||
union _dbl_nil_t {
|
||||
uint64_t l;
|
||||
dbl d;
|
||||
};
|
||||
gdk_export const union _dbl_nil_t _dbl_nil_;
|
||||
#define dbl_nil (_dbl_nil_.d)
|
||||
#else
|
||||
gdk_export const flt flt_nil;
|
||||
gdk_export const dbl dbl_nil;
|
||||
#endif
|
||||
gdk_export const lng lng_nil;
|
||||
#ifdef HAVE_HGE
|
||||
gdk_export const hge hge_nil;
|
||||
#endif
|
||||
gdk_export const oid oid_nil;
|
||||
gdk_export const char str_nil[2];
|
||||
gdk_export const ptr ptr_nil;
|
||||
gdk_export const uuid uuid_nil;
|
||||
|
||||
/* derived NIL values - OIDDEPEND */
|
||||
#define bit_nil ((bit) bte_nil)
|
||||
#define bat_nil ((bat) int_nil)
|
||||
|
||||
#define void_nil oid_nil
|
||||
|
||||
#define is_bit_nil(v) ((v) == GDK_bte_min-1)
|
||||
#define is_bte_nil(v) ((v) == GDK_bte_min-1)
|
||||
#define is_sht_nil(v) ((v) == GDK_sht_min-1)
|
||||
#define is_int_nil(v) ((v) == GDK_int_min-1)
|
||||
#define is_lng_nil(v) ((v) == GDK_lng_min-1)
|
||||
#ifdef HAVE_HGE
|
||||
#define is_hge_nil(v) ((v) == GDK_hge_min-1)
|
||||
#endif
|
||||
#define is_oid_nil(v) ((v) == ((oid) 1 << ((8 * SIZEOF_OID) - 1)))
|
||||
#define is_flt_nil(v) isnan(v)
|
||||
#define is_dbl_nil(v) isnan(v)
|
||||
#define is_bat_nil(v) (((v) & 0x7FFFFFFF) == 0) /* v == bat_nil || v == 0 */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && _MSC_VER < 1800
|
||||
#include <float.h>
|
||||
#define isnan(x) _isnan(x)
|
||||
#define isinf(x) (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF))
|
||||
#define isfinite(x) _finite(x)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HGE
|
||||
#define is_uuid_nil(x) ((x).h == 0)
|
||||
#else
|
||||
#ifdef HAVE_UUID
|
||||
#define is_uuid_nil(x) uuid_is_null((x).u)
|
||||
#else
|
||||
#define is_uuid_nil(x) (memcmp((x).u, uuid_nil.u, UUID_SIZE) == 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @- Derived types
|
||||
* In all algorithms across GDK, you will find switches on the types
|
||||
* (bte, sht, int, flt, dbl, lng, hge, str). They respectively
|
||||
* represent an octet, a 16-bit int, a 32-bit int, a 32-bit float, a
|
||||
* 64-bit double, a 64-bit int, a 128-bit int, and a pointer-sized location
|
||||
* of a char-buffer (ended by a zero char).
|
||||
*
|
||||
* In contrast, the types (bit, ptr, bat, oid) are derived types. They
|
||||
* do not occur in the switches. The ATOMstorage macro maps them
|
||||
* respectively onto a @code{ bte}, @code{ int} (pointers are 32-bit),
|
||||
* @code{ int}, and @code{ int}. OIDs are 32-bit.
|
||||
*
|
||||
* This approach makes it tractable to switch to 64-bits OIDs, or to a
|
||||
* fully 64-bits OS easily. One only has to map the @code{ oid} and
|
||||
* @code{ ptr} types to @code{ lng} instead of @code{ int}.
|
||||
*
|
||||
* Derived types mimic their fathers in many ways. They inherit the
|
||||
* @code{ size}, @code{ linear}, and @code{ null}
|
||||
* properties of their father. The same goes for the
|
||||
* ADT functions HASH, CMP, PUT, NULL, DEL, LEN, and HEAP. So, a
|
||||
* derived type differs in only two ways from its father:
|
||||
* @table @code
|
||||
* @item [string representation]
|
||||
* the only two ADT operations specific for a derived type are FROMSTR
|
||||
* and TOSTR.
|
||||
* @item [identity]
|
||||
* (a @code{ bit} is really of a different type than @code{ bte}). The
|
||||
* set of operations on derived type values or BATs of such types may
|
||||
* differ from the sets of operations on the father type.
|
||||
* @end table
|
||||
*/
|
||||
/* use "do ... while(0)" so that lhs can safely be used in if statements */
|
||||
#define ATOMstorage(t) BATatoms[t].storage
|
||||
#define ATOMsize(t) BATatoms[t].size
|
||||
#define ATOMfromstr(t,s,l,src,ext) BATatoms[t].atomFromStr(src,l,s,ext)
|
||||
#define ATOMnilptr(t) BATatoms[t].atomNull
|
||||
#define ATOMcompare(t) BATatoms[t].atomCmp
|
||||
#define ATOMcmp(t,l,r) ((*ATOMcompare(t))(l, r))
|
||||
#define ATOMhash(t,src) BATatoms[t].atomHash(src)
|
||||
#define ATOMdel(t,hp,src) do if (BATatoms[t].atomDel) BATatoms[t].atomDel(hp,src); while (0)
|
||||
#define ATOMvarsized(t) (BATatoms[t].atomPut != NULL)
|
||||
#define ATOMlinear(t) BATatoms[t].linear
|
||||
#define ATOMtype(t) ((t) == TYPE_void ? TYPE_oid : (t))
|
||||
#define ATOMfix(t,v) (BATatoms[t].atomFix ? BATatoms[t].atomFix(v) : GDK_SUCCEED)
|
||||
#define ATOMunfix(t,v) (BATatoms[t].atomUnfix ? BATatoms[t].atomUnfix(v) : GDK_SUCCEED)
|
||||
|
||||
/* The base type is the storage type if the comparison function, the
|
||||
* hash function, and the nil value are the same as those of the
|
||||
* storage type; otherwise it is the type itself. */
|
||||
#define ATOMbasetype(t) ((t) != ATOMstorage(t) && \
|
||||
ATOMnilptr(t) == ATOMnilptr(ATOMstorage(t)) && \
|
||||
ATOMcompare(t) == ATOMcompare(ATOMstorage(t)) && \
|
||||
BATatoms[t].atomHash == BATatoms[ATOMstorage(t)].atomHash ? \
|
||||
ATOMstorage(t) : (t))
|
||||
|
||||
/*
|
||||
* In case that atoms are added to a bat, their logical reference
|
||||
* count should be incremented (and decremented if deleted). Notice
|
||||
* that BATs with atomic types that have logical references (e.g. BATs
|
||||
* of BATs but also BATs of ODMG odSet) can never be persistent, as
|
||||
* this would make the commit tremendously complicated.
|
||||
*/
|
||||
|
||||
static inline gdk_return __attribute__((__warn_unused_result__))
|
||||
ATOMputVAR(BAT *b, var_t *dst, const void *src)
|
||||
{
|
||||
assert(BATatoms[b->ttype].atomPut != NULL);
|
||||
if ((*BATatoms[b->ttype].atomPut)(b, dst, src) == (var_t) -1)
|
||||
return GDK_FAIL;
|
||||
return GDK_SUCCEED;
|
||||
}
|
||||
|
||||
|
||||
static inline gdk_return __attribute__((__warn_unused_result__))
|
||||
ATOMputFIX(int type, void *dst, const void *src)
|
||||
{
|
||||
gdk_return rc;
|
||||
|
||||
assert(BATatoms[type].atomPut == NULL);
|
||||
rc = ATOMfix(type, src);
|
||||
if (rc != GDK_SUCCEED)
|
||||
return rc;
|
||||
switch (ATOMsize(type)) {
|
||||
case 0: /* void */
|
||||
break;
|
||||
case 1:
|
||||
* (bte *) dst = * (bte *) src;
|
||||
break;
|
||||
case 2:
|
||||
* (sht *) dst = * (sht *) src;
|
||||
break;
|
||||
case 4:
|
||||
* (int *) dst = * (int *) src;
|
||||
break;
|
||||
case 8:
|
||||
* (lng *) dst = * (lng *) src;
|
||||
break;
|
||||
case 16:
|
||||
#ifdef HAVE_HGE
|
||||
* (hge *) dst = * (hge *) src;
|
||||
#else
|
||||
* (uuid *) dst = * (uuid *) src;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
memcpy(dst, src, ATOMsize(type));
|
||||
break;
|
||||
}
|
||||
return GDK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline gdk_return __attribute__((__warn_unused_result__))
|
||||
ATOMreplaceVAR(BAT *b, var_t *dst, const void *src)
|
||||
{
|
||||
var_t loc = *dst;
|
||||
int type = b->ttype;
|
||||
|
||||
assert(BATatoms[type].atomPut != NULL);
|
||||
if ((*BATatoms[type].atomPut)(b, &loc, src) == (var_t) -1)
|
||||
return GDK_FAIL;
|
||||
if (ATOMunfix(type, dst) != GDK_SUCCEED)
|
||||
return GDK_FAIL;
|
||||
ATOMdel(type, b->tvheap, dst);
|
||||
*dst = loc;
|
||||
return ATOMfix(type, src);
|
||||
}
|
||||
|
||||
/* string heaps:
|
||||
* - strings are 8 byte aligned
|
||||
* - start with a 1024 bucket hash table
|
||||
* - heaps < 64KiB are fully duplicate eliminated with this hash tables
|
||||
* - heaps >= 64KiB are opportunistically (imperfect) duplicate
|
||||
* eliminated as only the last 128KiB chunk is considered and there
|
||||
* is no linked list
|
||||
* - buckets and next pointers are unsigned short "indices"
|
||||
* - indices should be multiplied by 8 and takes from ELIMBASE to get
|
||||
* an offset
|
||||
* Note that a 64KiB chunk of the heap contains at most 8K 8-byte
|
||||
* aligned strings. The 1K bucket list means that in worst load, the
|
||||
* list length is 8 (OK).
|
||||
*/
|
||||
#define GDK_STRHASHTABLE (1<<10) /* 1024 */
|
||||
#define GDK_STRHASHMASK (GDK_STRHASHTABLE-1)
|
||||
#define GDK_STRHASHSIZE (GDK_STRHASHTABLE * sizeof(stridx_t))
|
||||
#define GDK_ELIMPOWER 16 /* 64KiB is the threshold */
|
||||
#define GDK_ELIMDOUBLES(h) ((h)->free < GDK_ELIMLIMIT)
|
||||
#define GDK_ELIMLIMIT (1<<GDK_ELIMPOWER) /* equivalently: ELIMBASE == 0 */
|
||||
#define GDK_ELIMBASE(x) (((x) >> GDK_ELIMPOWER) << GDK_ELIMPOWER)
|
||||
#define GDK_VAROFFSET ((var_t) GDK_STRHASHSIZE)
|
||||
|
||||
/*
|
||||
* @- String Comparison, NILs and UTF-8
|
||||
*
|
||||
* Using the char* type for strings is handy as this is the type of
|
||||
* any constant strings in a C/C++ program. Therefore, MonetDB uses
|
||||
* this definition for str. However, different compilers and
|
||||
* platforms use either signed or unsigned characters for the char
|
||||
* type. It is required that string ordering in MonetDB is consistent
|
||||
* over platforms though.
|
||||
*
|
||||
* As for the choice how strings should be ordered, our support for
|
||||
* UTF-8 actually imposes that it should follow 'unsigned char'
|
||||
* doctrine (like in the AIX native compiler). In this semantics,
|
||||
* though we have to take corrective action to ensure that str(nil) is
|
||||
* the smallest value of the domain.
|
||||
*/
|
||||
static inline bool __attribute__((__pure__))
|
||||
strEQ(const char *l, const char *r)
|
||||
{
|
||||
return strcmp(l, r) == 0;
|
||||
}
|
||||
|
||||
static inline bool __attribute__((__pure__))
|
||||
strNil(const char *s)
|
||||
{
|
||||
return s == NULL || (s[0] == '\200' && s[1] == '\0');
|
||||
}
|
||||
|
||||
static inline size_t __attribute__((__pure__))
|
||||
strLen(const char *s)
|
||||
{
|
||||
return strNil(s) ? 2 : strlen(s) + 1;
|
||||
}
|
||||
|
||||
static inline int __attribute__((__pure__))
|
||||
strCmp(const char *l, const char *r)
|
||||
{
|
||||
return strNil(r)
|
||||
? !strNil(l)
|
||||
: strNil(l) ? -1 : strcmp(l, r);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
VarHeapVal(const void *b, BUN p, int w)
|
||||
{
|
||||
switch (w) {
|
||||
case 1:
|
||||
return (size_t) ((const uint8_t *) b)[p] + GDK_VAROFFSET;
|
||||
case 2:
|
||||
return (size_t) ((const uint16_t *) b)[p] + GDK_VAROFFSET;
|
||||
#if SIZEOF_VAR_T == 8
|
||||
case 4:
|
||||
return (size_t) ((const uint32_t *) b)[p];
|
||||
#endif
|
||||
default:
|
||||
return (size_t) ((const var_t *) b)[p];
|
||||
}
|
||||
}
|
||||
|
||||
static inline BUN __attribute__((__pure__))
|
||||
strHash(const char *key)
|
||||
{
|
||||
BUN y = 0;
|
||||
|
||||
for (BUN i = 0; key[i]; i++) {
|
||||
y += key[i];
|
||||
y += (y << 10);
|
||||
y ^= (y >> 6);
|
||||
}
|
||||
y += (y << 3);
|
||||
y ^= (y >> 11);
|
||||
y += (y << 15);
|
||||
return y;
|
||||
}
|
||||
|
||||
#endif /* _GDK_ATOMS_H_ */
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _GDK_BBP_H_
|
||||
#define _GDK_BBP_H_
|
||||
|
||||
#define BBPLOADED 1 /* set if bat in memory */
|
||||
#define BBPSWAPPED 2 /* set if dirty bat is not in memory */
|
||||
#define BBPTMP 4 /* set if non-persistent bat has image on disk */
|
||||
|
||||
/* These 4 symbols indicate what the persistence state is of a bat.
|
||||
* - If the bat was persistent at the last commit (or at startup
|
||||
* before the first commit), BBPEXISTING or BBPDELETED is set.
|
||||
* - If the bat is to be persistent after the next commit, BBPEXISTING
|
||||
* or BBPNEW is set (i.e. (status&BBPPERSISTENT) != 0).
|
||||
* - If the bat was transient at the last commit (or didn't exist),
|
||||
* BBPNEW is set, or none of these flag values is set.
|
||||
* - If the bat is to be transient at the next commit, BBPDELETED is
|
||||
* set, or none of these flag values is set.
|
||||
* BATmode() switches between BBPDELETED and BBPEXISTING (bat was
|
||||
* persistent at last commit), or between BBPNEW and 0 (bat was
|
||||
* transient or didn't exist at last commit).
|
||||
* Committing a bat switches from BBPNEW to BBPEXISTING, or turns off
|
||||
* BBPDELETED.
|
||||
* In any case, only at most one of BBPDELETED, BBPEXISTING, and
|
||||
* BBPNEW may be set at any one time.
|
||||
*
|
||||
* In short,
|
||||
* BBPEXISTING -- bat was and should remain persistent;
|
||||
* BBPDELETED -- bat was persistent at last commit and should be transient;
|
||||
* BBPNEW -- bat was transient at last commit and should be persistent;
|
||||
* none of the above -- bat was and should remain transient.
|
||||
*/
|
||||
#define BBPDELETED 16 /* set if bat persistent at last commit is now transient */
|
||||
#define BBPEXISTING 32 /* set if bat was already persistent at end of last commit */
|
||||
#define BBPNEW 64 /* set if bat has become persistent since last commit */
|
||||
#define BBPPERSISTENT (BBPEXISTING|BBPNEW) /* mask for currently persistent bats */
|
||||
|
||||
#define BBPSTATUS 127
|
||||
|
||||
#define BBPUNLOADING 128 /* set while we are unloading */
|
||||
#define BBPLOADING 256 /* set while we are loading */
|
||||
#define BBPSAVING 512 /* set while we are saving */
|
||||
#define BBPRENAMED 1024 /* set when bat is renamed in this transaction */
|
||||
#define BBPDELETING 2048 /* set while we are deleting (special case in module unload) */
|
||||
#define BBPHOT 4096 /* bat is "hot", i.e. is still in active use */
|
||||
#define BBPSYNCING 8192 /* bat between creating backup and saving */
|
||||
|
||||
#define BBPUNSTABLE (BBPUNLOADING|BBPDELETING) /* set while we are unloading */
|
||||
#define BBPWAITING (BBPUNLOADING|BBPLOADING|BBPSAVING|BBPDELETING|BBPSYNCING)
|
||||
|
||||
#define BBPTRIM_ALL (((size_t)1) << (sizeof(size_t)*8 - 2)) /* very large positive size_t */
|
||||
|
||||
gdk_export bat getBBPsize(void); /* current occupied size of BBP array */
|
||||
gdk_export lng getBBPlogno(void); /* two lng of extra info in BBP.dir */
|
||||
gdk_export lng getBBPtransid(void);
|
||||
|
||||
/* global calls */
|
||||
gdk_export gdk_return BBPaddfarm(const char *dirname, uint32_t rolemask, bool logerror);
|
||||
|
||||
/* update interface */
|
||||
gdk_export int BBPreclaim(BAT *b);
|
||||
gdk_export gdk_return BBPsave(BAT *b);
|
||||
gdk_export int BBPrename(bat bid, const char *nme);
|
||||
|
||||
/* query interface */
|
||||
gdk_export bat BBPindex(const char *nme);
|
||||
gdk_export BAT *BBPdescriptor(bat b);
|
||||
|
||||
/* swapping interface */
|
||||
gdk_export gdk_return BBPsync(int cnt, bat *restrict subcommit, BUN *restrict sizes, lng logno, lng transid);
|
||||
gdk_export int BBPfix(bat b);
|
||||
gdk_export int BBPunfix(bat b);
|
||||
gdk_export int BBPretain(bat b);
|
||||
gdk_export int BBPrelease(bat b);
|
||||
gdk_export void BBPkeepref(bat i);
|
||||
gdk_export void BBPshare(bat b);
|
||||
gdk_export void BBPcold(bat i);
|
||||
|
||||
#define BBP_status_set(bid, mode) \
|
||||
ATOMIC_SET(&BBP_record(bid).status, mode)
|
||||
|
||||
#define BBP_status_on(bid, flags) \
|
||||
ATOMIC_OR(&BBP_record(bid).status, flags)
|
||||
|
||||
#define BBP_status_off(bid, flags) \
|
||||
ATOMIC_AND(&BBP_record(bid).status, ~(flags))
|
||||
|
||||
#define BBPswappable(b) ((b) && (b)->batCacheid && BBP_refs((b)->batCacheid) == 0)
|
||||
#define BBPtrimmable(b) (BBPswappable(b) && isVIEW(b) == 0 && (BBP_status((b)->batCacheid)&BBPWAITING) == 0)
|
||||
|
||||
#endif /* _GDK_BBP_H_ */
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
/* included from gdk.h */
|
||||
|
||||
gdk_export BAT *BATcalcnegate(BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcabsolute(BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcincr(BAT *b, BAT *s, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcdecr(BAT *b, BAT *s, bool abort_on_error);
|
||||
gdk_export BAT *BATcalciszero(BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcsign(BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcisnil(BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcisnotnil(BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcnot(BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcmin(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcmin_no_nil(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcmincst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalcmincst_no_nil(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstmin(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalccstmin_no_nil(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcmax(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcmax_no_nil(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcmaxcst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalcmaxcst_no_nil(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstmax(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalccstmax_no_nil(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcadd(BAT *b1, BAT *b2, BAT *s1, BAT *s2, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcaddcst(BAT *b, const ValRecord *v, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalccstadd(const ValRecord *v, BAT *b, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcsub(BAT *b1, BAT *b2, BAT *s1, BAT *s2, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcsubcst(BAT *b, const ValRecord *v, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalccstsub(const ValRecord *v, BAT *b, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcmul(BAT *b1, BAT *b2, BAT *s1, BAT *s2, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcmulcst(BAT *b, const ValRecord *v, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalccstmul(const ValRecord *v, BAT *b, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcdiv(BAT *b1, BAT *b2, BAT *s1, BAT *s2, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcdivcst(BAT *b, const ValRecord *v, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalccstdiv(const ValRecord *v, BAT *b, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcmod(BAT *b1, BAT *b2, BAT *s1, BAT *s2, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcmodcst(BAT *b, const ValRecord *v, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalccstmod(const ValRecord *v, BAT *b, BAT *s, int tp, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcxor(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcxorcst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstxor(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcor(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcorcst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstor(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcand(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcandcst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstand(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalclsh(BAT *b1, BAT *b2, BAT *s1, BAT *s2, bool abort_on_error);
|
||||
gdk_export BAT *BATcalclshcst(BAT *b, const ValRecord *v, BAT *s, bool abort_on_error);
|
||||
gdk_export BAT *BATcalccstlsh(const ValRecord *v, BAT *b, BAT *s, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcrsh(BAT *b1, BAT *b2, BAT *s1, BAT *s2, bool abort_on_error);
|
||||
gdk_export BAT *BATcalcrshcst(BAT *b, const ValRecord *v, BAT *s, bool abort_on_error);
|
||||
gdk_export BAT *BATcalccstrsh(const ValRecord *v, BAT *b, BAT *s, bool abort_on_error);
|
||||
gdk_export BAT *BATcalclt(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcltcst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstlt(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcle(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalclecst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstle(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcgt(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcgtcst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstgt(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcge(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalcgecst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstge(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalceq(BAT *b1, BAT *b2, BAT *s1, BAT *s2, bool nil_matches);
|
||||
gdk_export BAT *BATcalceqcst(BAT *b, const ValRecord *v, BAT *s, bool nil_matches);
|
||||
gdk_export BAT *BATcalccsteq(const ValRecord *v, BAT *b, BAT *s, bool nil_matches);
|
||||
gdk_export BAT *BATcalcne(BAT *b1, BAT *b2, BAT *s1, BAT *s2, bool nil_matches);
|
||||
gdk_export BAT *BATcalcnecst(BAT *b, const ValRecord *v, BAT *s, bool nil_matches);
|
||||
gdk_export BAT *BATcalccstne(const ValRecord *v, BAT *b, BAT *s, bool nil_matches);
|
||||
gdk_export BAT *BATcalccmp(BAT *b1, BAT *b2, BAT *s1, BAT *s2);
|
||||
gdk_export BAT *BATcalccmpcst(BAT *b, const ValRecord *v, BAT *s);
|
||||
gdk_export BAT *BATcalccstcmp(const ValRecord *v, BAT *b, BAT *s);
|
||||
gdk_export BAT *BATcalcbetween(BAT *b, BAT *lo, BAT *hi, BAT *s, BAT *slo, BAT *shi, bool symmetric, bool linc, bool hinc, bool nils_false, bool anti);
|
||||
gdk_export BAT *BATcalcbetweencstcst(BAT *b, const ValRecord *lo, const ValRecord *hi, BAT *s, bool symmetric, bool linc, bool hinc, bool nils_false, bool anti);
|
||||
gdk_export BAT *BATcalcbetweenbatcst(BAT *b, BAT *lo, const ValRecord *hi, BAT *s, BAT *slo, bool symmetric, bool linc, bool hinc, bool nils_false, bool anti);
|
||||
gdk_export BAT *BATcalcbetweencstbat(BAT *b, const ValRecord *lo, BAT *hi, BAT *s, BAT *shi, bool symmetric, bool linc, bool hinc, bool nils_false, bool anti);
|
||||
gdk_export gdk_return VARcalcbetween(ValPtr ret, const ValRecord *v, const ValRecord *lo, const ValRecord *hi, bool symmetric, bool linc, bool hinc, bool nils_false, bool anti);
|
||||
gdk_export BAT *BATcalcifthenelse(BAT *b, BAT *b1, BAT *b2);
|
||||
gdk_export BAT *BATcalcifthenelsecst(BAT *b, BAT *b1, const ValRecord *c2);
|
||||
gdk_export BAT *BATcalcifthencstelse(BAT *b, const ValRecord *c1, BAT *b2);
|
||||
gdk_export BAT *BATcalcifthencstelsecst(BAT *b, const ValRecord *c1, const ValRecord *c2);
|
||||
|
||||
gdk_export gdk_return VARcalcnot(ValPtr ret, const ValRecord *v);
|
||||
gdk_export gdk_return VARcalcnegate(ValPtr ret, const ValRecord *v);
|
||||
gdk_export gdk_return VARcalcabsolute(ValPtr ret, const ValRecord *v);
|
||||
gdk_export gdk_return VARcalcincr(ValPtr ret, const ValRecord *v, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalcdecr(ValPtr ret, const ValRecord *v, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalciszero(ValPtr ret, const ValRecord *v);
|
||||
gdk_export gdk_return VARcalcsign(ValPtr ret, const ValRecord *v);
|
||||
gdk_export gdk_return VARcalcisnil(ValPtr ret, const ValRecord *v);
|
||||
gdk_export gdk_return VARcalcisnotnil(ValPtr ret, const ValRecord *v);
|
||||
gdk_export gdk_return VARcalcadd(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalcsub(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalcmul(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalcdiv(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalcmod(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalcxor(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
|
||||
gdk_export gdk_return VARcalcor(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
|
||||
gdk_export gdk_return VARcalcand(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
|
||||
gdk_export gdk_return VARcalclsh(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalcrsh(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool abort_on_error);
|
||||
gdk_export gdk_return VARcalclt(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
|
||||
gdk_export gdk_return VARcalcgt(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
|
||||
gdk_export gdk_return VARcalcle(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
|
||||
gdk_export gdk_return VARcalcge(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
|
||||
gdk_export gdk_return VARcalceq(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool nil_matches);
|
||||
gdk_export gdk_return VARcalcne(ValPtr ret, const ValRecord *lft, const ValRecord *rgt, bool nil_matches);
|
||||
gdk_export gdk_return VARcalccmp(ValPtr ret, const ValRecord *lft, const ValRecord *rgt);
|
||||
gdk_export BAT *BATconvert(BAT *b, BAT *s, int tp, bool abort_on_error, uint8_t scale1, uint8_t scale2, uint8_t precision);
|
||||
gdk_export gdk_return VARconvert(ValPtr ret, const ValRecord *v, bool abort_on_error, uint8_t scale1, uint8_t scale2, uint8_t precision);
|
||||
gdk_export gdk_return BATcalcavg(BAT *b, BAT *s, dbl *avg, BUN *vals, int scale);
|
||||
|
||||
gdk_export BAT *BATgroupsum(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupprod(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export gdk_return BATgroupavg(BAT **bnp, BAT **cntsp, BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error, int scale);
|
||||
gdk_export gdk_return BATgroupavg3(BAT **avgp, BAT **remp, BAT **cntp, BAT *b, BAT *g, BAT *e, BAT *s, bool skip_nils);
|
||||
gdk_export BAT *BATgroupavg3combine(BAT *avg, BAT *rem, BAT *cnt, BAT *g, BAT *e, bool skip_nils);
|
||||
gdk_export BAT *BATgroupcount(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupsize(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupmin(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupmax(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupmedian(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupquantile(BAT *b, BAT *g, BAT *e, BAT *s, int tp, double quantile, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupmedian_avg(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupquantile_avg(BAT *b, BAT *g, BAT *e, BAT *s, int tp, double quantile, bool skip_nils, bool abort_on_error);
|
||||
|
||||
/* helper function for grouped aggregates */
|
||||
gdk_export const char *BATgroupaggrinit(
|
||||
BAT *b, BAT *g, BAT *e, BAT *s,
|
||||
/* outputs: */
|
||||
oid *minp, oid *maxp, BUN *ngrpp,
|
||||
struct canditer *ci, BUN *ncand);
|
||||
|
||||
gdk_export gdk_return BATsum(void *res, int tp, BAT *b, BAT *s, bool skip_nils, bool abort_on_error, bool nil_if_empty);
|
||||
gdk_export gdk_return BATprod(void *res, int tp, BAT *b, BAT *s, bool skip_nils, bool abort_on_error, bool nil_if_empty);
|
||||
gdk_export void *BATmax(BAT *b, void *aggr);
|
||||
gdk_export void *BATmin(BAT *b, void *aggr);
|
||||
gdk_export void *BATmax_skipnil(BAT *b, void *aggr, bit skipnil);
|
||||
gdk_export void *BATmin_skipnil(BAT *b, void *aggr, bit skipnil);
|
||||
|
||||
gdk_export dbl BATcalcstdev_population(dbl *avgp, BAT *b);
|
||||
gdk_export dbl BATcalcstdev_sample(dbl *avgp, BAT *b);
|
||||
gdk_export BAT *BATgroupstdev_sample(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupstdev_population(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export dbl BATcalcvariance_population(dbl *avgp, BAT *b);
|
||||
gdk_export dbl BATcalcvariance_sample(dbl *avgp, BAT *b);
|
||||
gdk_export BAT *BATgroupvariance_sample(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupvariance_population(BAT *b, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export dbl BATcalccovariance_sample(BAT *b1, BAT *b2);
|
||||
gdk_export dbl BATcalccovariance_population(BAT *b1, BAT *b2);
|
||||
gdk_export dbl BATcalccorrelation(BAT *b1, BAT *b2);
|
||||
gdk_export BAT *BATgroupcovariance_sample(BAT *b1, BAT *b2, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupcovariance_population(BAT *b1, BAT *b2, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
gdk_export BAT *BATgroupcorrelation(BAT *b1, BAT *b2, BAT *g, BAT *e, BAT *s, int tp, bool skip_nils, bool abort_on_error);
|
||||
|
||||
gdk_export BAT *BATgroupstr_group_concat(BAT *b, BAT *g, BAT *e, BAT *s, BAT *sep, bool skip_nils, bool abort_on_error, const char *restrict separator);
|
||||
gdk_export gdk_return BATstr_group_concat(ValPtr res, BAT *b, BAT *s, BAT *sep, bool skip_nils, bool abort_on_error, bool nil_if_empty, const char *restrict separator);
|
||||
gdk_export gdk_return GDKanalytical_str_group_concat(BAT *r, BAT *p, BAT *o, BAT *b, BAT *sep, BAT *s, BAT *e, const char *restrict separator, int frame_type);
|
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _GDK_CAND_H_
|
||||
#define _GDK_CAND_H_
|
||||
|
||||
/* candidates by design are ordered oid lists, besides native oid bats
|
||||
* there are
|
||||
* void bats for dense oid lists,
|
||||
* negative oid lists
|
||||
* masked oid lists
|
||||
*/
|
||||
|
||||
#define CAND_NEGOID 0
|
||||
#define CAND_MSK 1
|
||||
|
||||
typedef struct {
|
||||
uint64_t
|
||||
type:1,
|
||||
// mask:1,
|
||||
firstbit:48;
|
||||
} ccand_t;
|
||||
|
||||
#define CCAND(b) ((ccand_t *) (b)->tvheap->base)
|
||||
#define complex_cand(b) ((b)->ttype == TYPE_void && (b)->tvheap != NULL)
|
||||
#define negoid_cand(b) (complex_cand(b) && CCAND(b)->type == CAND_NEGOID)
|
||||
#define mask_cand(b) (complex_cand(b) && CCAND(b)->type == CAND_MSK)
|
||||
#define ccand_first(b) ((b)->tvheap->base + sizeof(ccand_t))
|
||||
#define ccand_free(b) ((b)->tvheap->free - sizeof(ccand_t))
|
||||
|
||||
struct canditer {
|
||||
BAT *s; /* candidate BAT the iterator is based on */
|
||||
union {
|
||||
struct { /* for all except cand_mask */
|
||||
const oid *oids; /* candidate or exceptions for non-dense */
|
||||
BUN offset; /* how much of candidate list BAT we skipped */
|
||||
oid add; /* value to add because of exceptions seen */
|
||||
};
|
||||
struct { /* only for cand_mask */
|
||||
const uint32_t *mask; /* bitmask */
|
||||
BUN nextmsk;
|
||||
oid mskoff;
|
||||
uint8_t nextbit;
|
||||
uint8_t firstbit;
|
||||
uint8_t lastbit;
|
||||
};
|
||||
};
|
||||
oid seq; /* first candidate */
|
||||
oid hseq; /* hseqbase from s/b for first candidate */
|
||||
BUN nvals; /* number of values in .oids/.mask */
|
||||
BUN ncand; /* number of candidates */
|
||||
BUN next; /* next BUN to return value for */
|
||||
enum {
|
||||
cand_dense, /* simple dense BAT, i.e. no look ups */
|
||||
cand_materialized, /* simple materialized OID list */
|
||||
cand_except, /* list of exceptions in vheap */
|
||||
cand_mask, /* bitmask (TYPE_msk) bat as candidate list */
|
||||
} tpe;
|
||||
};
|
||||
|
||||
/* returns the position of the lowest order bit in x, i.e. the
|
||||
* smallest n such that (x & (1<<n)) != 0; must not be called with 0 */
|
||||
static inline int __attribute__((__const__))
|
||||
candmask_lobit(uint32_t x)
|
||||
{
|
||||
assert(x != 0);
|
||||
#if defined(__GNUC__)
|
||||
return __builtin_ctz(x) /* ffs(x) - 1 */;
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned long idx;
|
||||
if (_BitScanForward(&idx, x))
|
||||
return (int) idx;
|
||||
return -1;
|
||||
#else
|
||||
/* use binary search for the lowest set bit */
|
||||
int n = 1;
|
||||
if ((x & 0x0000FFFF) == 0) { n += 16; x >>= 16; }
|
||||
if ((x & 0x000000FF) == 0) { n += 8; x >>= 8; }
|
||||
if ((x & 0x0000000F) == 0) { n += 4; x >>= 4; }
|
||||
if ((x & 0x00000003) == 0) { n += 2; x >>= 2; }
|
||||
return n - (x & 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* population count: count number of 1 bits in a value */
|
||||
static inline uint32_t __attribute__((__const__))
|
||||
candmask_pop(uint32_t x)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return (uint32_t) __builtin_popcount(x);
|
||||
#elif defined(_MSC_VER)
|
||||
return (uint32_t) __popcnt((unsigned int) (x));
|
||||
#else
|
||||
/* divide and conquer implementation (the two versions are
|
||||
* essentially equivalent, but the first version is written a
|
||||
* bit smarter) */
|
||||
#if 1
|
||||
x -= (x >> 1) & ~0U/3 /* 0x55555555 */; /* 3-1=2; 2-1=1; 1-0=1; 0-0=0 */
|
||||
x = (x & ~0U/5) + ((x >> 2) & ~0U/5) /* 0x33333333 */;
|
||||
x = (x + (x >> 4)) & ~0UL/0x11 /* 0x0F0F0F0F */;
|
||||
x = (x + (x >> 8)) & ~0UL/0x101 /* 0x00FF00FF */;
|
||||
x = (x + (x >> 16)) & 0xFFFF /* ~0UL/0x10001 */;
|
||||
#else
|
||||
x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
|
||||
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
|
||||
x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
|
||||
x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
|
||||
x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
|
||||
#endif
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define canditer_next_dense(ci) ((ci)->seq + (ci)->next++)
|
||||
#define canditer_next_mater(ci) ((ci)->oids[(ci)->next++])
|
||||
static inline oid
|
||||
canditer_next_except(struct canditer *ci)
|
||||
{
|
||||
oid o = ci->seq + ci->add + ci->next++;
|
||||
while (ci->add < ci->nvals && o == ci->oids[ci->add]) {
|
||||
ci->add++;
|
||||
o++;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
static inline oid
|
||||
canditer_next_mask(struct canditer *ci)
|
||||
{
|
||||
/* since .next < .ncand, we know there must be another
|
||||
* candidate */
|
||||
while ((ci->mask[ci->nextmsk] >> ci->nextbit) == 0) {
|
||||
ci->nextmsk++;
|
||||
ci->nextbit = 0;
|
||||
}
|
||||
ci->nextbit += candmask_lobit(ci->mask[ci->nextmsk] >> ci->nextbit);
|
||||
oid o = ci->mskoff + ci->nextmsk * 32 + ci->nextbit;
|
||||
if (++ci->nextbit == 32) {
|
||||
ci->nextbit = 0;
|
||||
ci->nextmsk++;
|
||||
}
|
||||
ci->next++;
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline oid
|
||||
canditer_next(struct canditer *ci)
|
||||
{
|
||||
if (ci->next == ci->ncand)
|
||||
return oid_nil;
|
||||
switch (ci->tpe) {
|
||||
case cand_dense:
|
||||
return canditer_next_dense(ci);
|
||||
case cand_materialized:
|
||||
assert(ci->next < ci->nvals);
|
||||
return canditer_next_mater(ci);
|
||||
case cand_except:
|
||||
return canditer_next_except(ci);
|
||||
case cand_mask:
|
||||
/* work around compiler error: control reaches end of
|
||||
* non-void function */
|
||||
break;
|
||||
}
|
||||
assert(ci->tpe == cand_mask);
|
||||
return canditer_next_mask(ci);
|
||||
}
|
||||
|
||||
#define canditer_search_dense(ci, o, next) ((o) < (ci)->seq ? next ? 0 : BUN_NONE : (o) >= (ci)->seq + (ci)->ncand ? next ? (ci)->ncand : BUN_NONE : (o) - (ci)->seq)
|
||||
|
||||
gdk_export BUN canditer_init(struct canditer *ci, BAT *b, BAT *s);
|
||||
gdk_export oid canditer_peek(struct canditer *ci);
|
||||
gdk_export oid canditer_last(const struct canditer *ci);
|
||||
gdk_export oid canditer_prev(struct canditer *ci);
|
||||
gdk_export oid canditer_peekprev(struct canditer *ci);
|
||||
gdk_export oid canditer_idx(const struct canditer *ci, BUN p);
|
||||
#define canditer_idx_dense(ci, p) ((p >= (ci)->ncand)?oid_nil:((ci)->seq + p))
|
||||
gdk_export void canditer_setidx(struct canditer *ci, BUN p);
|
||||
gdk_export void canditer_reset(struct canditer *ci);
|
||||
gdk_export BUN canditer_search(const struct canditer *ci, oid o, bool next);
|
||||
static inline bool
|
||||
canditer_contains(struct canditer *ci, oid o)
|
||||
{
|
||||
if (ci->tpe == cand_mask) {
|
||||
if (o < ci->mskoff)
|
||||
return false;
|
||||
o -= ci->mskoff;
|
||||
BUN p = o / 32;
|
||||
if (p >= ci->nvals)
|
||||
return false;
|
||||
o %= 32;
|
||||
if (p == ci->nvals - 1 && o >= ci->lastbit)
|
||||
return false;
|
||||
return ci->mask[p] & (1U << o);
|
||||
}
|
||||
return canditer_search(ci, o, false) != BUN_NONE;
|
||||
}
|
||||
gdk_export oid canditer_mask_next(const struct canditer *ci, oid o, bool next);
|
||||
gdk_export BAT *canditer_slice(const struct canditer *ci, BUN lo, BUN hi);
|
||||
gdk_export BAT *canditer_sliceval(const struct canditer *ci, oid lo, oid hi);
|
||||
gdk_export BAT *canditer_slice2(const struct canditer *ci, BUN lo1, BUN hi1, BUN lo2, BUN hi2);
|
||||
gdk_export BAT *canditer_slice2val(const struct canditer *ci, oid lo1, oid hi1, oid lo2, oid hi2);
|
||||
gdk_export BAT *BATnegcands(BUN nr, BAT *odels);
|
||||
gdk_export BAT *BATmaskedcands(oid hseq, BUN nr, BAT *masked, bool selected);
|
||||
gdk_export BAT *BATunmask(BAT *b);
|
||||
|
||||
gdk_export BAT *BATmergecand(BAT *a, BAT *b);
|
||||
gdk_export BAT *BATintersectcand(BAT *a, BAT *b);
|
||||
gdk_export BAT *BATdiffcand(BAT *a, BAT *b);
|
||||
|
||||
#endif /* _GDK_CAND_H_ */
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _GDK_DELTA_H_
|
||||
#define _GDK_DELTA_H_
|
||||
|
||||
/*
|
||||
* We make sure here that the BUNs section of a BAT at least starts 4
|
||||
* bytes from the BUN start. This ensures that the first data item of
|
||||
* e.g. a BAT[void,bit] is (at least) integer aligned. This optimizes
|
||||
* processing on such BATs (DDBENCH).
|
||||
*/
|
||||
static inline void
|
||||
DELTAinit(BAT *b)
|
||||
{
|
||||
BATsetcount(b, 0);
|
||||
b->theap->free = 0;
|
||||
b->batInserted = 0;
|
||||
b->tshift = ATOMelmshift(Tsize(b));
|
||||
TRC_DEBUG(DELTA,
|
||||
"%s free %zu ins " BUNFMT " base %p\n",
|
||||
BBP_logical(b->batCacheid),
|
||||
b->theap->free,
|
||||
b->batInserted,
|
||||
b->theap->base);
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon saving a BAT, we should convert the delta marker BUN pointers
|
||||
* into indexes and convert them back into pointers upon reload.
|
||||
*
|
||||
* The BATdirty(b) tells you whether a BAT's main memory
|
||||
* representation differs from its saved image on stable storage. But
|
||||
* *not* whether it has changed since last transaction commit (it can
|
||||
* be storage-clean, but transaction-dirty). For this we have
|
||||
* DELTAdirty(b).
|
||||
*/
|
||||
#define DELTAdirty(b) ((b)->batInserted < BUNlast(b))
|
||||
|
||||
#endif /* _GDK_DELTA_H_ */
|
@ -0,0 +1,299 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _GDK_SEARCH_H_
|
||||
#define _GDK_SEARCH_H_
|
||||
|
||||
struct Hash {
|
||||
int type; /* type of index entity */
|
||||
uint8_t width; /* width of hash entries */
|
||||
BUN mask1; /* .mask1 < .nbucket <= .mask2 */
|
||||
BUN mask2; /* ... both are power-of-two minus one */
|
||||
BUN nbucket; /* number of valid hash buckets */
|
||||
BUN nunique; /* number of unique values */
|
||||
BUN nheads; /* number of chain heads */
|
||||
void *Bckt; /* hash buckets, points into .heapbckt */
|
||||
void *Link; /* collision list, points into .heaplink */
|
||||
Heap heaplink; /* heap where the hash links are stored */
|
||||
Heap heapbckt; /* heap where the hash buckets are stored */
|
||||
};
|
||||
|
||||
static inline BUN
|
||||
HASHbucket(const Hash *h, BUN v)
|
||||
{
|
||||
return (v &= h->mask2) < h->nbucket ? v : v & h->mask1;
|
||||
}
|
||||
|
||||
gdk_export gdk_return BAThash(BAT *b);
|
||||
gdk_export void HASHdestroy(BAT *b);
|
||||
gdk_export BUN HASHprobe(const Hash *h, const void *v);
|
||||
gdk_export BUN HASHlist(Hash *h, BUN i);
|
||||
|
||||
#define BUN2 2
|
||||
#define BUN4 4
|
||||
#if SIZEOF_BUN == 8
|
||||
#define BUN8 8
|
||||
#endif
|
||||
#ifdef BUN2
|
||||
typedef uint16_t BUN2type;
|
||||
#endif
|
||||
typedef uint32_t BUN4type;
|
||||
#if SIZEOF_BUN > 4
|
||||
typedef uint64_t BUN8type;
|
||||
#endif
|
||||
#ifdef BUN2
|
||||
#define BUN2_NONE ((BUN2type) UINT16_C(0xFFFF))
|
||||
#endif
|
||||
#define BUN4_NONE ((BUN4type) UINT32_C(0xFFFFFFFF))
|
||||
#ifdef BUN8
|
||||
#define BUN8_NONE ((BUN8type) UINT64_C(0xFFFFFFFFFFFFFFFF))
|
||||
#endif
|
||||
|
||||
/* play around with h->Bckt[i] and h->Link[j] */
|
||||
|
||||
static inline void
|
||||
HASHput(Hash *h, BUN i, BUN v)
|
||||
{
|
||||
/* if v == BUN_NONE, assigning the value to a BUN2type
|
||||
* etc. automatically converts to BUN2_NONE etc. */
|
||||
switch (h->width) {
|
||||
#ifdef BUN2
|
||||
case BUN2:
|
||||
((BUN2type *) h->Bckt)[i] = (BUN2type) v;
|
||||
break;
|
||||
#endif
|
||||
default: /* BUN4 */
|
||||
((BUN4type *) h->Bckt)[i] = (BUN4type) v;
|
||||
break;
|
||||
#ifdef BUN8
|
||||
case BUN8:
|
||||
((BUN8type *) h->Bckt)[i] = (BUN8type) v;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
HASHputlink(Hash *h, BUN i, BUN v)
|
||||
{
|
||||
/* if v == BUN_NONE, assigning the value to a BUN2type
|
||||
* etc. automatically converts to BUN2_NONE etc. */
|
||||
switch (h->width) {
|
||||
#ifdef BUN2
|
||||
case BUN2:
|
||||
assert(v == BUN_NONE || v == BUN2_NONE || v < i);
|
||||
((BUN2type *) h->Link)[i] = (BUN2type) v;
|
||||
break;
|
||||
#endif
|
||||
default: /* BUN4 */
|
||||
assert(v == BUN_NONE || v == BUN4_NONE || v < i);
|
||||
((BUN4type *) h->Link)[i] = (BUN4type) v;
|
||||
break;
|
||||
#ifdef BUN8
|
||||
case BUN8:
|
||||
assert(v == BUN_NONE || v == BUN8_NONE || v < i);
|
||||
((BUN8type *) h->Link)[i] = (BUN8type) v;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static inline BUN __attribute__((__pure__))
|
||||
HASHget(const Hash *h, BUN i)
|
||||
{
|
||||
switch (h->width) {
|
||||
#ifdef BUN2
|
||||
case BUN2:
|
||||
i = (BUN) ((BUN2type *) h->Bckt)[i];
|
||||
return i == BUN2_NONE ? BUN_NONE : i;
|
||||
#endif
|
||||
default: /* BUN4 */
|
||||
i = (BUN) ((BUN4type *) h->Bckt)[i];
|
||||
return i == BUN4_NONE ? BUN_NONE : i;
|
||||
#ifdef BUN8
|
||||
case BUN8:
|
||||
i = (BUN) ((BUN8type *) h->Bckt)[i];
|
||||
return i == BUN8_NONE ? BUN_NONE : i;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static inline BUN __attribute__((__pure__))
|
||||
HASHgetlink(const Hash *h, BUN i)
|
||||
{
|
||||
switch (h->width) {
|
||||
#ifdef BUN2
|
||||
case BUN2:
|
||||
i = (BUN) ((BUN2type *) h->Link)[i];
|
||||
return i == BUN2_NONE ? BUN_NONE : i;
|
||||
#endif
|
||||
default: /* BUN4 */
|
||||
i = (BUN) ((BUN4type *) h->Link)[i];
|
||||
return i == BUN4_NONE ? BUN_NONE : i;
|
||||
#ifdef BUN8
|
||||
case BUN8:
|
||||
i = (BUN) ((BUN8type *) h->Link)[i];
|
||||
return i == BUN8_NONE ? BUN_NONE : i;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* mix_bte(0x80) == 0x80 */
|
||||
#define mix_bte(X) ((unsigned int) (unsigned char) (X))
|
||||
/* mix_sht(0x8000) == 0x8000 */
|
||||
#define mix_sht(X) ((unsigned int) (unsigned short) (X))
|
||||
/* mix_int(0x81060038) == 0x80000000 */
|
||||
#define mix_int(X) (((unsigned int) (X) >> 7) ^ \
|
||||
((unsigned int) (X) >> 13) ^ \
|
||||
((unsigned int) (X) >> 21) ^ \
|
||||
(unsigned int) (X))
|
||||
/* mix_lng(0x810600394347424F) == 0x8000000000000000 */
|
||||
#define mix_lng(X) (((ulng) (X) >> 7) ^ \
|
||||
((ulng) (X) >> 13) ^ \
|
||||
((ulng) (X) >> 21) ^ \
|
||||
((ulng) (X) >> 31) ^ \
|
||||
((ulng) (X) >> 38) ^ \
|
||||
((ulng) (X) >> 46) ^ \
|
||||
((ulng) (X) >> 56) ^ \
|
||||
(ulng) (X))
|
||||
#ifdef HAVE_HGE
|
||||
/* mix_hge(0x810600394347424F90AC1429D6BFCC57) ==
|
||||
* 0x80000000000000000000000000000000 */
|
||||
#define mix_hge(X) (((uhge) (X) >> 7) ^ \
|
||||
((uhge) (X) >> 13) ^ \
|
||||
((uhge) (X) >> 21) ^ \
|
||||
((uhge) (X) >> 31) ^ \
|
||||
((uhge) (X) >> 38) ^ \
|
||||
((uhge) (X) >> 46) ^ \
|
||||
((uhge) (X) >> 56) ^ \
|
||||
((uhge) (X) >> 65) ^ \
|
||||
((uhge) (X) >> 70) ^ \
|
||||
((uhge) (X) >> 78) ^ \
|
||||
((uhge) (X) >> 85) ^ \
|
||||
((uhge) (X) >> 90) ^ \
|
||||
((uhge) (X) >> 98) ^ \
|
||||
((uhge) (X) >> 107) ^ \
|
||||
((uhge) (X) >> 116) ^ \
|
||||
(uhge) (X))
|
||||
#endif
|
||||
#define hash_loc(H,V) hash_any(H,V)
|
||||
#define hash_var(H,V) hash_any(H,V)
|
||||
#define hash_any(H,V) HASHbucket(H, ATOMhash((H)->type, (V)))
|
||||
#define hash_bte(H,V) (assert((H)->nbucket >= 256), (BUN) mix_bte(*(const unsigned char*) (V)))
|
||||
#define hash_sht(H,V) (assert((H)->nbucket >= 65536), (BUN) mix_sht(*(const unsigned short*) (V)))
|
||||
#define hash_int(H,V) HASHbucket(H, (BUN) mix_int(*(const unsigned int *) (V)))
|
||||
/* XXX return size_t-sized value for 8-byte oid? */
|
||||
#define hash_lng(H,V) HASHbucket(H, (BUN) mix_lng(*(const ulng *) (V)))
|
||||
#ifdef HAVE_HGE
|
||||
#define hash_hge(H,V) HASHbucket(H, (BUN) mix_hge(*(const uhge *) (V)))
|
||||
#endif
|
||||
#if SIZEOF_OID == SIZEOF_INT
|
||||
#define hash_oid(H,V) hash_int(H,V)
|
||||
#else
|
||||
#define hash_oid(H,V) hash_lng(H,V)
|
||||
#endif
|
||||
|
||||
#define hash_flt(H,V) hash_int(H,V)
|
||||
#define hash_dbl(H,V) hash_lng(H,V)
|
||||
|
||||
static inline BUN __attribute__((__const__))
|
||||
mix_uuid(const uuid *u)
|
||||
{
|
||||
ulng u1, u2;
|
||||
|
||||
u1 = (ulng) (uint8_t) u->u[0] << 56 |
|
||||
(ulng) (uint8_t) u->u[1] << 48 |
|
||||
(ulng) (uint8_t) u->u[2] << 40 |
|
||||
(ulng) (uint8_t) u->u[3] << 32 |
|
||||
(ulng) (uint8_t) u->u[4] << 24 |
|
||||
(ulng) (uint8_t) u->u[5] << 16 |
|
||||
(ulng) (uint8_t) u->u[6] << 8 |
|
||||
(ulng) (uint8_t) u->u[7];
|
||||
u2 = (ulng) (uint8_t) u->u[8] << 56 |
|
||||
(ulng) (uint8_t) u->u[9] << 48 |
|
||||
(ulng) (uint8_t) u->u[10] << 40 |
|
||||
(ulng) (uint8_t) u->u[11] << 32 |
|
||||
(ulng) (uint8_t) u->u[12] << 24 |
|
||||
(ulng) (uint8_t) u->u[13] << 16 |
|
||||
(ulng) (uint8_t) u->u[14] << 8 |
|
||||
(ulng) (uint8_t) u->u[15];
|
||||
/* we're not using mix_hge since this way we get the same result
|
||||
* on systems with and without 128 bit integer support */
|
||||
return (BUN) (mix_lng(u1) ^ mix_lng(u2));
|
||||
}
|
||||
#define hash_uuid(H,V) HASHbucket(H, mix_uuid((const uuid *) (V)))
|
||||
|
||||
/*
|
||||
* @- hash-table supported loop over BUNs The first parameter `bi' is
|
||||
* a BAT iterator, the second (`h') should point to the Hash
|
||||
* structure, and `v' a pointer to an atomic value (corresponding to
|
||||
* the head column of `b'). The 'hb' is an BUN index, pointing out the
|
||||
* `hb'-th BUN.
|
||||
*/
|
||||
#define HASHloop(bi, h, hb, v) \
|
||||
for (hb = HASHget(h, HASHprobe(h, v)); \
|
||||
hb != BUN_NONE; \
|
||||
hb = HASHgetlink(h, hb)) \
|
||||
if (ATOMcmp(h->type, v, BUNtail(bi, hb)) == 0)
|
||||
#define HASHloop_str(bi, h, hb, v) \
|
||||
for (hb = HASHget(h, HASHbucket(h, strHash(v))); \
|
||||
hb != BUN_NONE; \
|
||||
hb = HASHgetlink(h, hb)) \
|
||||
if (strEQ(v, BUNtvar(bi, hb)))
|
||||
|
||||
#define HASHlooploc(bi, h, hb, v) \
|
||||
for (hb = HASHget(h, HASHprobe(h, v)); \
|
||||
hb != BUN_NONE; \
|
||||
hb = HASHgetlink(h, hb)) \
|
||||
if (ATOMcmp(h->type, v, BUNtloc(bi, hb)) == 0)
|
||||
#define HASHloopvar(bi, h, hb, v) \
|
||||
for (hb = HASHget(h, HASHprobe(h, v)); \
|
||||
hb != BUN_NONE; \
|
||||
hb = HASHgetlink(h, hb)) \
|
||||
if (ATOMcmp(h->type, v, BUNtvar(bi, hb)) == 0)
|
||||
|
||||
#define HASHloop_TYPE(bi, h, hb, v, TYPE) \
|
||||
for (hb = HASHget(h, hash_##TYPE(h, v)); \
|
||||
hb != BUN_NONE; \
|
||||
hb = HASHgetlink(h,hb)) \
|
||||
if (* (const TYPE *) (v) == * (const TYPE *) BUNtloc(bi, hb))
|
||||
|
||||
/* need to take special care comparing nil floating point values */
|
||||
#define HASHloop_fTYPE(bi, h, hb, v, TYPE) \
|
||||
for (hb = HASHget(h, hash_##TYPE(h, v)); \
|
||||
hb != BUN_NONE; \
|
||||
hb = HASHgetlink(h,hb)) \
|
||||
if (is_##TYPE##_nil(* (const TYPE *) (v)) \
|
||||
? is_##TYPE##_nil(* (const TYPE *) BUNtloc(bi, hb)) \
|
||||
: * (const TYPE *) (v) == * (const TYPE *) BUNtloc(bi, hb))
|
||||
|
||||
#define HASHloop_bte(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, bte)
|
||||
#define HASHloop_sht(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, sht)
|
||||
#define HASHloop_int(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, int)
|
||||
#define HASHloop_lng(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, lng)
|
||||
#ifdef HAVE_HGE
|
||||
#define HASHloop_hge(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, hge)
|
||||
#endif
|
||||
#define HASHloop_flt(bi, h, hb, v) HASHloop_fTYPE(bi, h, hb, v, flt)
|
||||
#define HASHloop_dbl(bi, h, hb, v) HASHloop_fTYPE(bi, h, hb, v, dbl)
|
||||
#ifdef HAVE_HGE
|
||||
#define HASHloop_uuid(bi, hsh, hb, v) \
|
||||
for (hb = HASHget(hsh, hash_uuid(hsh, v)); \
|
||||
hb != BUN_NONE; \
|
||||
hb = HASHgetlink(hsh,hb)) \
|
||||
if (((const uuid *) (v))->h == ((const uuid *) BUNtloc(bi, hb))->h)
|
||||
#else
|
||||
#define HASHloop_uuid(bi, h, hb, v) \
|
||||
for (hb = HASHget(h, hash_uuid(h, v)); \
|
||||
hb != BUN_NONE; \
|
||||
hb = HASHgetlink(h,hb)) \
|
||||
if (memcmp((const uuid *) (v), (const uuid *) BUNtloc(bi, hb), 16) == 0)
|
||||
// if (((const uuid *) (v))->l[0] == ((const uuid *) BUNtloc(bi, hb))->l[0] && ((const uuid *) (v))->l[1] == ((const uuid *) BUNtloc(bi, hb))->l[1])
|
||||
#endif
|
||||
|
||||
#endif /* _GDK_SEARCH_H_ */
|
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef GDK_POSIX_H
|
||||
#define GDK_POSIX_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef HAVE_FTIME
|
||||
#include <sys/timeb.h> /* ftime */
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h> /* gettimeofday */
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYS_SOCKET_H
|
||||
#ifdef HAVE_WINSOCK_H
|
||||
#include <winsock.h> /* for timeval */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "gdk_system.h" /* gdk_export */
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @- virtual memory
|
||||
*/
|
||||
#define MT_VMUNITLOG 16
|
||||
#define MT_VMUNITSIZE (1 << MT_VMUNITLOG)
|
||||
|
||||
/* make sure POSIX_MADV_* and posix_madvise() are defined somehow */
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
# ifndef __USE_BSD
|
||||
# define __USE_BSD
|
||||
# endif
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
/* on Linux, posix_madvise does not seem to work, fall back to classic
|
||||
* madvise */
|
||||
#undef HAVE_POSIX_MADVISE
|
||||
#undef HAVE_POSIX_FADVISE
|
||||
#undef POSIX_MADV_NORMAL
|
||||
#undef POSIX_MADV_RANDOM
|
||||
#undef POSIX_MADV_SEQUENTIAL
|
||||
#undef POSIX_MADV_WILLNEED
|
||||
#undef POSIX_MADV_DONTNEED
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_POSIX_MADVISE
|
||||
# ifdef HAVE_MADVISE
|
||||
# define posix_madvise madvise
|
||||
# define HAVE_POSIX_MADVISE 1
|
||||
# ifndef MADV_RANDOM
|
||||
# define MADV_RANDOM 0
|
||||
# endif
|
||||
# ifndef POSIX_MADV_NORMAL
|
||||
# define POSIX_MADV_NORMAL MADV_NORMAL
|
||||
# define POSIX_MADV_RANDOM MADV_RANDOM
|
||||
# define POSIX_MADV_SEQUENTIAL MADV_SEQUENTIAL
|
||||
# define POSIX_MADV_WILLNEED MADV_WILLNEED
|
||||
# define POSIX_MADV_DONTNEED MADV_DONTNEED
|
||||
# endif
|
||||
# else
|
||||
# define posix_madvise(x,y,z) 0
|
||||
# ifndef POSIX_MADV_NORMAL
|
||||
# define POSIX_MADV_NORMAL 0
|
||||
# define POSIX_MADV_RANDOM 0
|
||||
# define POSIX_MADV_SEQUENTIAL 0
|
||||
# define POSIX_MADV_WILLNEED 0
|
||||
# define POSIX_MADV_DONTNEED 0
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* in case they are still not defined, define these values as
|
||||
* something that doesn't do anything */
|
||||
#ifndef POSIX_MADV_NORMAL
|
||||
#define POSIX_MADV_NORMAL 0
|
||||
#endif
|
||||
#ifndef POSIX_MADV_RANDOM
|
||||
#define POSIX_MADV_RANDOM 0
|
||||
#endif
|
||||
#ifndef POSIX_MADV_SEQUENTIAL
|
||||
#define POSIX_MADV_SEQUENTIAL 0
|
||||
#endif
|
||||
#ifndef POSIX_MADV_WILLNEED
|
||||
#define POSIX_MADV_WILLNEED 0
|
||||
#endif
|
||||
#ifndef POSIX_MADV_DONTNEED
|
||||
#define POSIX_MADV_DONTNEED 0
|
||||
#endif
|
||||
|
||||
/* the new mmap modes, mimic default MADV_* madvise POSIX constants */
|
||||
#define MMAP_NORMAL POSIX_MADV_NORMAL /* no further special treatment */
|
||||
#define MMAP_RANDOM POSIX_MADV_RANDOM /* expect random page references */
|
||||
#define MMAP_SEQUENTIAL POSIX_MADV_SEQUENTIAL /* expect sequential page references */
|
||||
#define MMAP_WILLNEED POSIX_MADV_WILLNEED /* will need these pages */
|
||||
#define MMAP_DONTNEED POSIX_MADV_DONTNEED /* don't need these pages */
|
||||
|
||||
#define MMAP_READ 1024 /* region is readable (default if ommitted) */
|
||||
#define MMAP_WRITE 2048 /* region may be written into */
|
||||
#define MMAP_COPY 4096 /* writable, but changes never reach file */
|
||||
#define MMAP_ASYNC 8192 /* asynchronous writes (default if ommitted) */
|
||||
#define MMAP_SYNC 16384 /* writing is done synchronously */
|
||||
|
||||
/* in order to be sure of madvise and msync modes, pass them to mmap()
|
||||
* call as well */
|
||||
|
||||
gdk_export size_t MT_getrss(void);
|
||||
|
||||
gdk_export bool MT_path_absolute(const char *path);
|
||||
|
||||
|
||||
/*
|
||||
* @+ Posix under WIN32
|
||||
* WIN32 actually supports many Posix functions directly. Some it
|
||||
* does not, though. For some functionality we move in Monet from
|
||||
* Posix calls to MT_*() calls, which translate easier to WIN32.
|
||||
* Examples are MT_mmap() , MT_sleep_ms() and MT_path_absolute(). Why?
|
||||
* In the case of mmap() it is much easier for WIN32 to get a filename
|
||||
* parameter rather than a file-descriptor. That is the reason in the
|
||||
* case of mmap() to go for a MT_mmap() solution.
|
||||
*
|
||||
* For some other functionality, we do not need to abandon the Posix
|
||||
* interface, though. Two cases can be distinguished. Missing
|
||||
* functions in WIN32 are directly implemented
|
||||
* (e.g. dlopen()/dlsym()/dlclose()). Posix functions in WIN32 whose
|
||||
* functionality should be changed a bit. Examples are
|
||||
* stat()/rename()/mkdir()/rmdir() who under WIN32 do not work if the
|
||||
* path ends with a directory separator, but should work according to
|
||||
* Posix. We remap such functions using a define to an equivalent
|
||||
* win_*() function (which in its implementation calls through to the
|
||||
* WIN32 function).
|
||||
*/
|
||||
gdk_export void *mdlopen(const char *library, int mode);
|
||||
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
|
||||
#define RTLD_LAZY 1
|
||||
#define RTLD_NOW 2
|
||||
#define RTLD_GLOBAL 4
|
||||
|
||||
gdk_export void *dlopen(const char *file, int mode);
|
||||
gdk_export int dlclose(void *handle);
|
||||
gdk_export void *dlsym(void *handle, const char *name);
|
||||
gdk_export char *dlerror(void);
|
||||
|
||||
#ifndef HAVE_GETTIMEOFDAY
|
||||
gdk_export int gettimeofday(struct timeval *tv, int *ignore_zone);
|
||||
#endif
|
||||
|
||||
#endif /* NATIVE_WIN32 */
|
||||
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
gdk_export struct tm *localtime_r(const time_t *restrict, struct tm *restrict);
|
||||
#endif
|
||||
#ifndef HAVE_GMTIME_R
|
||||
gdk_export struct tm *gmtime_r(const time_t *restrict, struct tm *restrict);
|
||||
#endif
|
||||
#ifndef HAVE_ASCTIME_R
|
||||
gdk_export char *asctime_r(const struct tm *restrict, char *restrict);
|
||||
#endif
|
||||
#ifndef HAVE_CTIME_R
|
||||
gdk_export char *ctime_r(const time_t *restrict, char *restrict);
|
||||
#endif
|
||||
#ifndef HAVE_STRERROR_R
|
||||
gdk_export int strerror_r(int errnum, char *buf, size_t buflen);
|
||||
#endif
|
||||
|
||||
static inline const char *
|
||||
GDKstrerror(int errnum, char *buf, size_t buflen)
|
||||
{
|
||||
#if !defined(_GNU_SOURCE) || ((_POSIX_C_SOURCE >= 200112L) && !_GNU_SOURCE)
|
||||
if (strerror_r(errnum, buf, buflen) == 0)
|
||||
return buf;
|
||||
snprintf(buf, buflen, "Unknown error %d", errnum);
|
||||
return buf;
|
||||
#else
|
||||
return strerror_r(errnum, buf, buflen);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* GDK_POSIX_H */
|
@ -0,0 +1,722 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _GDK_SYSTEM_H_
|
||||
#define _GDK_SYSTEM_H_
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef LIBGDK
|
||||
#define gdk_export extern __declspec(dllimport)
|
||||
#else
|
||||
#define gdk_export extern __declspec(dllexport)
|
||||
#endif
|
||||
#else
|
||||
#define gdk_export extern
|
||||
#endif
|
||||
|
||||
/* if __has_attribute is not known to the preprocessor, we ignore
|
||||
* attributes completely; if it is known, use it to find out whether
|
||||
* specific attributes that we use are known */
|
||||
#ifndef __has_attribute
|
||||
#ifndef __GNUC__
|
||||
/* we can define __has_attribute as 1 since we define __attribute__ as empty */
|
||||
#define __has_attribute(attr) 1
|
||||
#ifndef __attribute__
|
||||
#define __attribute__(attr) /* empty */
|
||||
#endif
|
||||
#else
|
||||
/* older GCC does have attributes, but not __has_attribute and not all
|
||||
* attributes that we use are known */
|
||||
#define __has_attribute__alloc_size__ 1
|
||||
#define __has_attribute__cold__ 1
|
||||
#define __has_attribute__const__ 1
|
||||
#define __has_attribute__constructor__ 1
|
||||
#define __has_attribute__designated_init__ 0
|
||||
#define __has_attribute__format__ 1
|
||||
#define __has_attribute__malloc__ 1
|
||||
#define __has_attribute__nonnull__ 1
|
||||
#define __has_attribute__nonstring__ 0
|
||||
#define __has_attribute__pure__ 1
|
||||
#define __has_attribute__returns_nonnull__ 0
|
||||
#define __has_attribute__visibility__ 1
|
||||
#define __has_attribute__warn_unused_result__ 1
|
||||
#define __has_attribute(attr) __has_attribute##attr
|
||||
#endif
|
||||
#endif
|
||||
#if !__has_attribute(__alloc_size__)
|
||||
#define __alloc_size__(a)
|
||||
#endif
|
||||
#if !__has_attribute(__cold__)
|
||||
#define __cold__
|
||||
#endif
|
||||
#if !__has_attribute(__const__)
|
||||
#define __const__
|
||||
#endif
|
||||
#if !__has_attribute(__constructor__)
|
||||
#define __constructor__
|
||||
#endif
|
||||
#if !__has_attribute(__designated_init__)
|
||||
#define __designated_init__
|
||||
#endif
|
||||
#if !__has_attribute(__format__)
|
||||
#define __format__(a,b,c)
|
||||
#endif
|
||||
#if !__has_attribute(__malloc__)
|
||||
#define __malloc__
|
||||
#endif
|
||||
#if !__has_attribute(__nonnull__)
|
||||
#define __nonnull__(a)
|
||||
#endif
|
||||
#if !__has_attribute(__nonstring__)
|
||||
#define __nonstring__
|
||||
#endif
|
||||
#if !__has_attribute(__pure__)
|
||||
#define __pure__
|
||||
#endif
|
||||
#if !__has_attribute(__returns_nonnull__)
|
||||
#define __returns_nonnull__
|
||||
#endif
|
||||
#if !__has_attribute(__visibility__)
|
||||
#define __visibility__(a)
|
||||
#elif defined(__CYGWIN__)
|
||||
#define __visibility__(a)
|
||||
#endif
|
||||
#if !__has_attribute(__warn_unused_result__)
|
||||
#define __warn_unused_result__
|
||||
#endif
|
||||
|
||||
/* also see gdk.h for these */
|
||||
#define THRDMASK (1)
|
||||
#define TEMMASK (1<<10)
|
||||
|
||||
/*
|
||||
* @- pthreads Includes and Definitions
|
||||
*/
|
||||
#ifdef HAVE_PTHREAD_H
|
||||
/* don't re-include config.h; on Windows, don't redefine pid_t in an
|
||||
* incompatible way */
|
||||
#undef HAVE_CONFIG_H
|
||||
#ifdef pid_t
|
||||
#undef pid_t
|
||||
#endif
|
||||
#include <sched.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SEMAPHORE_H
|
||||
# include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DISPATCH_DISPATCH_H
|
||||
#include <dispatch/dispatch.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h> /* prerequisite of sys/sysctl on OpenBSD */
|
||||
#endif
|
||||
#ifdef BSD /* BSD macro is defined in sys/param.h */
|
||||
# include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
/* new pthread interface, where the thread id changed to a struct */
|
||||
#ifdef PTW32_VERSION
|
||||
#define PTW32 1
|
||||
#endif
|
||||
|
||||
/* debug and errno integers */
|
||||
gdk_export int GDKdebug;
|
||||
gdk_export void GDKsetdebug(int debug);
|
||||
gdk_export int GDKgetdebug(void);
|
||||
|
||||
gdk_export int GDKnr_threads;
|
||||
|
||||
/* API */
|
||||
|
||||
/*
|
||||
* @- sleep
|
||||
*/
|
||||
|
||||
gdk_export void MT_sleep_ms(unsigned int ms);
|
||||
|
||||
/*
|
||||
* @- MT Thread Api
|
||||
*/
|
||||
typedef size_t MT_Id; /* thread number. will not be zero */
|
||||
|
||||
enum MT_thr_detach { MT_THR_JOINABLE, MT_THR_DETACHED };
|
||||
#define MT_NAME_LEN 32 /* length of thread/semaphore/etc. names */
|
||||
|
||||
#define UNKNOWN_THREAD "unknown thread"
|
||||
typedef int64_t lng;
|
||||
|
||||
typedef struct QryCtx {
|
||||
const lng starttime;
|
||||
lng querytimeout;
|
||||
} QryCtx;
|
||||
|
||||
gdk_export bool MT_thread_init(void);
|
||||
gdk_export int MT_create_thread(MT_Id *t, void (*function) (void *),
|
||||
void *arg, enum MT_thr_detach d,
|
||||
const char *threadname);
|
||||
gdk_export const char *MT_thread_getname(void);
|
||||
gdk_export void *MT_thread_getdata(void);
|
||||
gdk_export void MT_thread_setdata(void *data);
|
||||
gdk_export void MT_exiting_thread(void);
|
||||
gdk_export MT_Id MT_getpid(void);
|
||||
gdk_export int MT_join_thread(MT_Id t);
|
||||
gdk_export QryCtx *MT_thread_get_qry_ctx(void);
|
||||
gdk_export void MT_thread_set_qry_ctx(QryCtx *ctx);
|
||||
|
||||
#if SIZEOF_VOID_P == 4
|
||||
/* "limited" stack size on 32-bit systems */
|
||||
/* to avoid address space fragmentation */
|
||||
#define THREAD_STACK_SIZE ((size_t)1024*1024)
|
||||
#else
|
||||
/* "increased" stack size on 64-bit systems */
|
||||
/* since some compilers seem to require this */
|
||||
/* for burg-generated code in pathfinder */
|
||||
/* and address space fragmentation is no issue */
|
||||
#define THREAD_STACK_SIZE ((size_t)2*1024*1024)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* @- MT Lock API
|
||||
*/
|
||||
#include "matomic.h"
|
||||
|
||||
/* define this to keep lock statistics (can be expensive) */
|
||||
/* #define LOCK_STATS 1 */
|
||||
|
||||
#ifdef LOCK_STATS
|
||||
#include "gdk_tracer.h"
|
||||
|
||||
#define _DBG_LOCK_COUNT_0(l) \
|
||||
do { \
|
||||
(void) ATOMIC_INC(&GDKlockcnt); \
|
||||
TRC_DEBUG(TEM, "Locking %s...\n", (l)->name); \
|
||||
} while (0)
|
||||
|
||||
#define _DBG_LOCK_LOCKER(l) \
|
||||
do { \
|
||||
(l)->locker = __func__; \
|
||||
(l)->thread = MT_thread_getname(); \
|
||||
} while (0)
|
||||
|
||||
#define _DBG_LOCK_UNLOCKER(l) \
|
||||
do { \
|
||||
(l)->locker = __func__; \
|
||||
(l)->thread = NULL; \
|
||||
TRC_DEBUG(TEM, "Unlocking %s\n", (l)->name); \
|
||||
} while (0)
|
||||
|
||||
#define _DBG_LOCK_CONTENTION(l) \
|
||||
do { \
|
||||
TRC_DEBUG(TEM, "Lock %s contention\n", (l)->name); \
|
||||
(void) ATOMIC_INC(&GDKlockcontentioncnt); \
|
||||
(void) ATOMIC_INC(&(l)->contention); \
|
||||
} while (0)
|
||||
|
||||
#define _DBG_LOCK_SLEEP(l) ((void) ATOMIC_INC(&(l)->sleep))
|
||||
|
||||
#define _DBG_LOCK_COUNT_2(l) \
|
||||
do { \
|
||||
(l)->count++; \
|
||||
if ((l)->next == (struct MT_Lock *) -1) { \
|
||||
while (ATOMIC_TAS(&GDKlocklistlock) != 0) \
|
||||
; \
|
||||
(l)->next = GDKlocklist; \
|
||||
(l)->prev = NULL; \
|
||||
if (GDKlocklist) \
|
||||
GDKlocklist->prev = (l); \
|
||||
GDKlocklist = (l); \
|
||||
ATOMIC_CLEAR(&GDKlocklistlock); \
|
||||
} \
|
||||
TRC_DEBUG(TEM, "Locking %s complete\n", (l)->name); \
|
||||
} while (0)
|
||||
|
||||
#define _DBG_LOCK_INIT(l) \
|
||||
do { \
|
||||
(l)->count = 0; \
|
||||
ATOMIC_INIT(&(l)->contention, 0); \
|
||||
ATOMIC_INIT(&(l)->sleep, 0); \
|
||||
(l)->locker = NULL; \
|
||||
(l)->thread = NULL; \
|
||||
/* if name starts with "sa_" don't link in GDKlocklist */ \
|
||||
/* since the lock is in memory that is governed by the */ \
|
||||
/* SQL storage allocator, and hence we have no control */ \
|
||||
/* over when the lock is destroyed and the memory freed */ \
|
||||
if (strncmp((l)->name, "sa_", 3) != 0) { \
|
||||
while (ATOMIC_TAS(&GDKlocklistlock) != 0) \
|
||||
; \
|
||||
if (GDKlocklist) \
|
||||
GDKlocklist->prev = (l); \
|
||||
(l)->next = GDKlocklist; \
|
||||
(l)->prev = NULL; \
|
||||
GDKlocklist = (l); \
|
||||
ATOMIC_CLEAR(&GDKlocklistlock); \
|
||||
} else { \
|
||||
(l)->next = NULL; \
|
||||
(l)->prev = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _DBG_LOCK_DESTROY(l) \
|
||||
do { \
|
||||
/* if name starts with "sa_" don't link in GDKlocklist */ \
|
||||
/* since the lock is in memory that is governed by the */ \
|
||||
/* SQL storage allocator, and hence we have no control */ \
|
||||
/* over when the lock is destroyed and the memory freed */ \
|
||||
if (strncmp((l)->name, "sa_", 3) != 0) { \
|
||||
while (ATOMIC_TAS(&GDKlocklistlock) != 0) \
|
||||
; \
|
||||
if ((l)->next) \
|
||||
(l)->next->prev = (l)->prev; \
|
||||
if ((l)->prev) \
|
||||
(l)->prev->next = (l)->next; \
|
||||
else if (GDKlocklist == (l)) \
|
||||
GDKlocklist = (l)->next; \
|
||||
ATOMIC_CLEAR(&GDKlocklistlock); \
|
||||
ATOMIC_DESTROY(&(l)->contention); \
|
||||
ATOMIC_DESTROY(&(l)->sleep); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define _DBG_LOCK_COUNT_0(l) ((void) 0)
|
||||
#define _DBG_LOCK_CONTENTION(l) ((void) 0)
|
||||
#define _DBG_LOCK_SLEEP(l) ((void) 0)
|
||||
#define _DBG_LOCK_COUNT_2(l) ((void) 0)
|
||||
#define _DBG_LOCK_INIT(l) ((void) 0)
|
||||
#define _DBG_LOCK_DESTROY(l) ((void) 0)
|
||||
#define _DBG_LOCK_LOCKER(l) ((void) 0)
|
||||
#define _DBG_LOCK_UNLOCKER(l) ((void) 0)
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_PTHREAD_H) && defined(WIN32)
|
||||
typedef struct MT_Lock {
|
||||
CRITICAL_SECTION lock;
|
||||
char name[MT_NAME_LEN];
|
||||
#ifdef LOCK_STATS
|
||||
size_t count;
|
||||
ATOMIC_TYPE contention;
|
||||
ATOMIC_TYPE sleep;
|
||||
struct MT_Lock *volatile next;
|
||||
struct MT_Lock *volatile prev;
|
||||
const char *locker;
|
||||
const char *thread;
|
||||
#endif
|
||||
} MT_Lock;
|
||||
|
||||
/* Windows defines read as _read and adds a deprecation warning to read
|
||||
* if you were to still use that. We need the token "read" here. We
|
||||
* cannot simply #undef read, since that messes up the deprecation
|
||||
* stuff. So we define _read as read to change the token back to "read"
|
||||
* where replacement stops (recursive definitions are allowed in C and
|
||||
* are handled well). After our use, we remove the definition of _read
|
||||
* so everything reverts back to the way it was. Bonus: this also works
|
||||
* if "read" was not defined. */
|
||||
#define _read read
|
||||
#pragma section(".CRT$XCU", read)
|
||||
#undef _read
|
||||
#ifdef _WIN64
|
||||
#define _LOCK_PREF_ ""
|
||||
#else
|
||||
#define _LOCK_PREF_ "_"
|
||||
#endif
|
||||
#define MT_LOCK_INITIALIZER(n) { 0 }; \
|
||||
static void wininit_##n(void) \
|
||||
{ \
|
||||
MT_lock_init(&n, #n); \
|
||||
} \
|
||||
__declspec(allocate(".CRT$XCU")) void (*wininit_##n##_)(void) = wininit_##n; \
|
||||
__pragma(comment(linker, "/include:" _LOCK_PREF_ "wininit_" #n "_"))
|
||||
|
||||
#define MT_lock_init(l, n) \
|
||||
do { \
|
||||
InitializeCriticalSection(&(l)->lock); \
|
||||
strcpy_len((l)->name, (n), sizeof((l)->name)); \
|
||||
_DBG_LOCK_INIT(l); \
|
||||
} while (0)
|
||||
|
||||
#define MT_lock_try(l) TryEnterCriticalSection(&(l)->lock)
|
||||
|
||||
#define MT_lock_set(l) \
|
||||
do { \
|
||||
_DBG_LOCK_COUNT_0(l); \
|
||||
if (!MT_lock_try(l)) { \
|
||||
_DBG_LOCK_CONTENTION(l); \
|
||||
MT_thread_setlockwait(l); \
|
||||
EnterCriticalSection(&(l)->lock); \
|
||||
MT_thread_setlockwait(NULL); \
|
||||
} \
|
||||
_DBG_LOCK_LOCKER(l); \
|
||||
_DBG_LOCK_COUNT_2(l); \
|
||||
} while (0)
|
||||
|
||||
#define MT_lock_unset(l) \
|
||||
do { \
|
||||
_DBG_LOCK_UNLOCKER(l); \
|
||||
LeaveCriticalSection(&(l)->lock); \
|
||||
} while (0)
|
||||
|
||||
#define MT_lock_destroy(l) \
|
||||
do { \
|
||||
_DBG_LOCK_DESTROY(l); \
|
||||
DeleteCriticalSection(&(l)->lock); \
|
||||
} while (0)
|
||||
|
||||
typedef struct MT_RWLock {
|
||||
SRWLOCK lock;
|
||||
char name[MT_NAME_LEN];
|
||||
} MT_RWLock;
|
||||
|
||||
#define MT_RWLOCK_INITIALIZER(n) { .lock = SRWLOCK_INIT, .name = #n, }
|
||||
|
||||
#define MT_rwlock_init(l, n) \
|
||||
do { \
|
||||
InitializeSRWLock(&(l)->lock); \
|
||||
strcpy_len((l)->name, (n), sizeof((l)->name)); \
|
||||
} while (0)
|
||||
|
||||
#define MT_rwlock_destroy(l) ((void) 0)
|
||||
|
||||
#define MT_rwlock_rdlock(l) AcquireSRWLockShared(&(l)->lock)
|
||||
#define MT_rwlock_rdtry(l) TryAcquireSRWLockShared(&(l)->lock)
|
||||
|
||||
#define MT_rwlock_rdunlock(l) ReleaseSRWLockShared(&(l)->lock)
|
||||
|
||||
#define MT_rwlock_wrlock(l) AcquireSRWLockExclusive(&(l)->lock)
|
||||
#define MT_rwlock_wrtry(l) TryAcquireSRWLockExclusive(&(l)->lock)
|
||||
|
||||
#define MT_rwlock_wrunlock(l) ReleaseSRWLockExclusive(&(l)->lock)
|
||||
|
||||
#else
|
||||
|
||||
typedef struct MT_Lock {
|
||||
pthread_mutex_t lock;
|
||||
char name[MT_NAME_LEN];
|
||||
#ifdef LOCK_STATS
|
||||
size_t count;
|
||||
ATOMIC_TYPE contention;
|
||||
ATOMIC_TYPE sleep;
|
||||
struct MT_Lock *volatile next;
|
||||
struct MT_Lock *volatile prev;
|
||||
const char *locker;
|
||||
const char *thread;
|
||||
#endif
|
||||
} MT_Lock;
|
||||
|
||||
#ifdef LOCK_STATS
|
||||
#define MT_LOCK_INITIALIZER(n) { .lock = PTHREAD_MUTEX_INITIALIZER, .name = #n, .next = (struct MT_Lock *) -1, }
|
||||
#else
|
||||
#define MT_LOCK_INITIALIZER(n) { .lock = PTHREAD_MUTEX_INITIALIZER, .name = #n, }
|
||||
#endif
|
||||
|
||||
#define MT_lock_init(l, n) \
|
||||
do { \
|
||||
pthread_mutex_init(&(l)->lock, 0); \
|
||||
strcpy_len((l)->name, (n), sizeof((l)->name)); \
|
||||
_DBG_LOCK_INIT(l); \
|
||||
} while (0)
|
||||
|
||||
#define MT_lock_try(l) (pthread_mutex_trylock(&(l)->lock) == 0)
|
||||
|
||||
#ifdef LOCK_STATS
|
||||
#define MT_lock_set(l) \
|
||||
do { \
|
||||
_DBG_LOCK_COUNT_0(l); \
|
||||
if (!MT_lock_try(l)) { \
|
||||
_DBG_LOCK_CONTENTION(l); \
|
||||
MT_thread_setlockwait(l); \
|
||||
pthread_mutex_lock(&(l)->lock); \
|
||||
MT_thread_setlockwait(NULL); \
|
||||
} \
|
||||
_DBG_LOCK_LOCKER(l); \
|
||||
_DBG_LOCK_COUNT_2(l); \
|
||||
} while (0)
|
||||
#else
|
||||
#define MT_lock_set(l) pthread_mutex_lock(&(l)->lock)
|
||||
#endif
|
||||
|
||||
#define MT_lock_unset(l) \
|
||||
do { \
|
||||
_DBG_LOCK_UNLOCKER(l); \
|
||||
pthread_mutex_unlock(&(l)->lock); \
|
||||
} while (0)
|
||||
|
||||
#define MT_lock_destroy(l) \
|
||||
do { \
|
||||
_DBG_LOCK_DESTROY(l); \
|
||||
pthread_mutex_destroy(&(l)->lock); \
|
||||
} while (0)
|
||||
|
||||
#if !defined(__GLIBC__) || __GLIBC__ > 2 || (__GLIBC__ == 2 && defined(__GLIBC_MINOR__) && __GLIBC_MINOR__ >= 30)
|
||||
/* this is the normal implementation of our pthreads-based read-write lock */
|
||||
typedef struct MT_RWLock {
|
||||
pthread_rwlock_t lock;
|
||||
char name[MT_NAME_LEN];
|
||||
} MT_RWLock;
|
||||
|
||||
#define MT_RWLOCK_INITIALIZER(n) \
|
||||
{ .lock = PTHREAD_RWLOCK_INITIALIZER, .name = #n, }
|
||||
|
||||
#define MT_rwlock_init(l, n) \
|
||||
do { \
|
||||
pthread_rwlock_init(&(l)->lock, NULL); \
|
||||
strcpy_len((l)->name, (n), sizeof((l)->name)); \
|
||||
} while (0)
|
||||
|
||||
#define MT_rwlock_destroy(l) pthread_rwlock_destroy(&(l)->lock)
|
||||
|
||||
#define MT_rwlock_rdlock(l) pthread_rwlock_rdlock(&(l)->lock)
|
||||
#define MT_rwlock_rdtry(l) (pthread_rwlock_tryrdlock(&(l)->lock) == 0)
|
||||
|
||||
#define MT_rwlock_rdunlock(l) pthread_rwlock_unlock(&(l)->lock)
|
||||
|
||||
#define MT_rwlock_wrlock(l) pthread_rwlock_wrlock(&(l)->lock)
|
||||
#define MT_rwlock_wrtry(l) (pthread_rwlock_trywrlock(&(l)->lock) == 0)
|
||||
|
||||
#define MT_rwlock_wrunlock(l) pthread_rwlock_unlock(&(l)->lock)
|
||||
|
||||
#else
|
||||
/* in glibc before 2.30, there was a deadlock condition in the tryrdlock
|
||||
* and trywrlock functions, we work around that by not using the
|
||||
* implementation at all
|
||||
* see https://sourceware.org/bugzilla/show_bug.cgi?id=23844 for a
|
||||
* discussion and comment 14 for the analysis */
|
||||
typedef struct MT_RWLock {
|
||||
pthread_mutex_t lock;
|
||||
ATOMIC_TYPE readers;
|
||||
char name[MT_NAME_LEN];
|
||||
} MT_RWLock;
|
||||
|
||||
#define MT_RWLOCK_INITIALIZER(n) \
|
||||
{ .lock = PTHREAD_MUTEX_INITIALIZER, .readers = ATOMIC_VAR_INIT(0), .name = #n, }
|
||||
|
||||
#define MT_rwlock_init(l, n) \
|
||||
do { \
|
||||
pthread_mutex_init(&(l)->lock, 0); \
|
||||
ATOMIC_INIT(&(l)->readers, 0); \
|
||||
strcpy_len((l)->name, (n), sizeof((l)->name)); \
|
||||
} while (0)
|
||||
|
||||
#define MT_rwlock_destroy(l) \
|
||||
do { \
|
||||
pthread_mutex_destroy(&(l)->lock); \
|
||||
ATOMIC_DESTROY(&(l)->readers); \
|
||||
} while (0)
|
||||
|
||||
#define MT_rwlock_rdlock(l) \
|
||||
do { \
|
||||
pthread_mutex_lock(&(l)->lock); \
|
||||
(void) ATOMIC_INC(&(l)->readers); \
|
||||
pthread_mutex_unlock(&(l)->lock); \
|
||||
} while (0)
|
||||
|
||||
static inline bool
|
||||
MT_rwlock_rdtry(MT_RWLock *l)
|
||||
{
|
||||
if (pthread_mutex_trylock(&l->lock) != 0)
|
||||
return false;
|
||||
(void) ATOMIC_INC(&(l)->readers);
|
||||
pthread_mutex_unlock(&l->lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define MT_rwlock_rdunlock(l) \
|
||||
do { \
|
||||
(void) ATOMIC_DEC(&(l)->readers); \
|
||||
} while (0)
|
||||
|
||||
#define MT_rwlock_wrlock(l) \
|
||||
do { \
|
||||
pthread_mutex_lock(&(l)->lock); \
|
||||
while (ATOMIC_GET(&(l)->readers) > 0) \
|
||||
MT_sleep_ms(1); \
|
||||
} while (0)
|
||||
|
||||
static inline bool
|
||||
MT_rwlock_wrtry(MT_RWLock *l)
|
||||
{
|
||||
if (pthread_mutex_trylock(&l->lock) != 0)
|
||||
return false;
|
||||
if (ATOMIC_GET(&l->readers) > 0) {
|
||||
pthread_mutex_unlock(&l->lock);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define MT_rwlock_wrunlock(l) pthread_mutex_unlock(&(l)->lock);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LOCK_STATS
|
||||
gdk_export void GDKlockstatistics(int);
|
||||
gdk_export MT_Lock * volatile GDKlocklist;
|
||||
gdk_export ATOMIC_FLAG GDKlocklistlock;
|
||||
gdk_export ATOMIC_TYPE GDKlockcnt;
|
||||
gdk_export ATOMIC_TYPE GDKlockcontentioncnt;
|
||||
gdk_export ATOMIC_TYPE GDKlocksleepcnt;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @- MT Semaphore API
|
||||
*/
|
||||
#if !defined(HAVE_PTHREAD_H) && defined(WIN32)
|
||||
|
||||
typedef struct {
|
||||
HANDLE sema;
|
||||
char name[MT_NAME_LEN];
|
||||
} MT_Sema;
|
||||
|
||||
#define MT_sema_init(s, nr, n) \
|
||||
do { \
|
||||
assert((s)->sema == NULL); \
|
||||
strcpy_len((s)->name, (n), sizeof((s)->name)); \
|
||||
(s)->sema = CreateSemaphore(NULL, nr, 0x7fffffff, NULL); \
|
||||
} while (0)
|
||||
|
||||
#define MT_sema_destroy(s) \
|
||||
do { \
|
||||
assert((s)->sema != NULL); \
|
||||
CloseHandle((s)->sema); \
|
||||
(s)->sema = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define MT_sema_up(s) ReleaseSemaphore((s)->sema, 1, NULL)
|
||||
|
||||
#define MT_sema_down(s) \
|
||||
do { \
|
||||
TRC_DEBUG(TEM, "Sema %s down...\n", (s)->name); \
|
||||
if (WaitForSingleObject((s)->sema, 0) != WAIT_OBJECT_0) { \
|
||||
MT_thread_setsemawait(s); \
|
||||
while (WaitForSingleObject((s)->sema, INFINITE) != WAIT_OBJECT_0) \
|
||||
; \
|
||||
MT_thread_setsemawait(NULL); \
|
||||
} \
|
||||
TRC_DEBUG(TEM, "Sema %s down complete\n", (s)->name); \
|
||||
} while (0)
|
||||
|
||||
#elif defined(HAVE_DISPATCH_SEMAPHORE_CREATE)
|
||||
|
||||
/* MacOS X */
|
||||
typedef struct {
|
||||
dispatch_semaphore_t sema;
|
||||
char name[MT_NAME_LEN];
|
||||
} MT_Sema;
|
||||
|
||||
#define MT_sema_init(s, nr, n) \
|
||||
do { \
|
||||
strcpy_len((s)->name, (n), sizeof((s)->name)); \
|
||||
(s)->sema = dispatch_semaphore_create((long) (nr)); \
|
||||
} while (0)
|
||||
|
||||
#define MT_sema_destroy(s) dispatch_release((s)->sema)
|
||||
#define MT_sema_up(s) dispatch_semaphore_signal((s)->sema)
|
||||
#define MT_sema_down(s) dispatch_semaphore_wait((s)->sema, DISPATCH_TIME_FOREVER)
|
||||
|
||||
#elif defined(_AIX) || defined(__MACH__)
|
||||
|
||||
/* simulate semaphores using mutex and condition variable */
|
||||
|
||||
typedef struct {
|
||||
int cnt;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
char name[MT_NAME_LEN];
|
||||
} MT_Sema;
|
||||
|
||||
#define MT_sema_init(s, nr, n) \
|
||||
do { \
|
||||
strcpy_len((s)->name, (n), sizeof((s)->name)); \
|
||||
(s)->cnt = (nr); \
|
||||
pthread_mutex_init(&(s)->mutex, 0); \
|
||||
pthread_cond_init(&(s)->cond, 0); \
|
||||
} while (0)
|
||||
|
||||
#define MT_sema_destroy(s) \
|
||||
do { \
|
||||
pthread_mutex_destroy(&(s)->mutex); \
|
||||
pthread_cond_destroy(&(s)->cond); \
|
||||
} while (0)
|
||||
|
||||
#define MT_sema_up(s) \
|
||||
do { \
|
||||
pthread_mutex_lock(&(s)->mutex); \
|
||||
if ((s)->cnt++ < 0) { \
|
||||
pthread_cond_signal(&(s)->cond); \
|
||||
} \
|
||||
pthread_mutex_unlock(&(s)->mutex); \
|
||||
} while (0)
|
||||
|
||||
#define MT_sema_down(s) \
|
||||
do { \
|
||||
TRC_DEBUG(TEM, "Sema %s down...\n", (s)->name); \
|
||||
pthread_mutex_lock(&(s)->mutex); \
|
||||
if (--(s)->cnt < 0) { \
|
||||
MT_thread_setsemawait(s); \
|
||||
do { \
|
||||
pthread_cond_wait(&(s)->cond, \
|
||||
&(s)->mutex); \
|
||||
} while ((s)->cnt < 0); \
|
||||
MT_thread_setsemawait(NULL); \
|
||||
pthread_mutex_unlock(&(s)->mutex); \
|
||||
} \
|
||||
TRC_DEBUG(TEM, "Sema %s down complete\n", (s)->name); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
typedef struct {
|
||||
sem_t sema;
|
||||
char name[MT_NAME_LEN];
|
||||
} MT_Sema;
|
||||
|
||||
#define MT_sema_init(s, nr, n) \
|
||||
do { \
|
||||
strcpy_len((s)->name, (n), sizeof((s)->name)); \
|
||||
sem_init(&(s)->sema, 0, nr); \
|
||||
} while (0)
|
||||
|
||||
#define MT_sema_destroy(s) sem_destroy(&(s)->sema)
|
||||
|
||||
#define MT_sema_up(s) \
|
||||
do { \
|
||||
TRC_DEBUG(TEM, "Sema %s up\n", (s)->name); \
|
||||
sem_post(&(s)->sema); \
|
||||
} while (0)
|
||||
|
||||
#define MT_sema_down(s) \
|
||||
do { \
|
||||
TRC_DEBUG(TEM, "Sema %s down...\n", (s)->name); \
|
||||
if (sem_trywait(&(s)->sema) != 0) { \
|
||||
MT_thread_setsemawait(s); \
|
||||
while (sem_wait(&(s)->sema) != 0) \
|
||||
; \
|
||||
MT_thread_setsemawait(NULL); \
|
||||
} \
|
||||
TRC_DEBUG(TEM, "Sema %s down complete\n", (s)->name); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
gdk_export void MT_thread_setlockwait(MT_Lock *lock);
|
||||
gdk_export void MT_thread_setsemawait(MT_Sema *sema);
|
||||
gdk_export void MT_thread_setworking(const char *work);
|
||||
gdk_export void MT_thread_setalgorithm(const char *algo);
|
||||
gdk_export const char *MT_thread_getalgorithm(void);
|
||||
|
||||
gdk_export int MT_check_nr_cores(void);
|
||||
|
||||
#endif /*_GDK_SYSTEM_H_*/
|
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
/* // TODO: Complete it when documentation is accepted
|
||||
*
|
||||
* Tracer is the general logging system for the MonetDB stack modelled
|
||||
* after the well-known logging schemes (e.g: Python). It provides a
|
||||
* number of logging levels and options to increase or reduce the
|
||||
* verbosity either of individual code parts or of the codebase as a
|
||||
* whole. It allows users to focus on logging messages related to
|
||||
* certain steps of execution, which can be proved handy when it comes
|
||||
* to debugging. The behavior of Tracer can be controlled at runtime
|
||||
* using the SQL API described later on. Certain calls require an "id"
|
||||
* to operate which can be found on the list of each section below.
|
||||
*
|
||||
* Internally, the logger uses a buffer to capture log messages before
|
||||
* they are forwarded to the specific adapter.
|
||||
*
|
||||
* - Sets the minimum flush level that an event will trigger the
|
||||
* logger to flush the buffer
|
||||
* - Produces messages to the output stream. It is also used as a
|
||||
* fallback mechanism in case GDKtracer fails to log for whatever
|
||||
* reason.
|
||||
* - Struct buffer with allocated space etc.
|
||||
* - Flush buffer sends the messages to the selected adapter
|
||||
* - Write about the log structure (e.g: MT_thread_get_name + datetime
|
||||
* + blah blah)
|
||||
*/
|
||||
|
||||
#ifndef _GDK_TRACER_H_
|
||||
#define _GDK_TRACER_H_
|
||||
|
||||
#define GENERATE_ENUM(ENUM) ENUM,
|
||||
|
||||
|
||||
// ADAPTERS
|
||||
#define FOREACH_ADPTR(ADPTR) \
|
||||
ADPTR( BASIC ) \
|
||||
ADPTR( PROFILER ) \
|
||||
ADPTR( MBEDDED ) \
|
||||
\
|
||||
ADPTR( ADAPTERS_COUNT )
|
||||
|
||||
typedef enum {
|
||||
FOREACH_ADPTR(GENERATE_ENUM)
|
||||
} adapter_t;
|
||||
|
||||
|
||||
|
||||
// LOG LEVELS
|
||||
#define FOREACH_LEVEL(LEVEL) \
|
||||
LEVEL( M_CRITICAL ) \
|
||||
LEVEL( M_ERROR ) \
|
||||
LEVEL( M_WARNING ) \
|
||||
LEVEL( M_INFO ) \
|
||||
LEVEL( M_DEBUG ) \
|
||||
\
|
||||
LEVEL( LOG_LEVELS_COUNT )
|
||||
|
||||
typedef enum {
|
||||
FOREACH_LEVEL(GENERATE_ENUM)
|
||||
} log_level_t;
|
||||
|
||||
|
||||
// LAYERS
|
||||
#define FOREACH_LAYER(LAYER) \
|
||||
LAYER( MDB_ALL ) \
|
||||
LAYER( SQL_ALL ) \
|
||||
LAYER( MAL_ALL ) \
|
||||
LAYER( GDK_ALL ) \
|
||||
\
|
||||
LAYER( LAYERS_COUNT )
|
||||
|
||||
typedef enum {
|
||||
FOREACH_LAYER(GENERATE_ENUM)
|
||||
} layer_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* NOTE: Adding/Removing components will affect the test tracer00.mal
|
||||
* See the test file for more details.
|
||||
*
|
||||
*/
|
||||
// COMPONENTS
|
||||
#define FOREACH_COMP(COMP) \
|
||||
COMP( ACCELERATOR ) \
|
||||
COMP( ALGO ) \
|
||||
COMP( ALLOC ) \
|
||||
COMP( BAT_ ) \
|
||||
COMP( CHECK_ ) \
|
||||
COMP( DELTA ) \
|
||||
COMP( HEAP ) \
|
||||
COMP( IO_ ) \
|
||||
COMP( PAR ) \
|
||||
COMP( PERF ) \
|
||||
COMP( TEM ) \
|
||||
COMP( THRD ) \
|
||||
\
|
||||
COMP( GEOM ) \
|
||||
COMP( FITS ) \
|
||||
COMP( SHP ) \
|
||||
\
|
||||
COMP( SQL_PARSER ) \
|
||||
COMP( SQL_TRANS ) \
|
||||
COMP( SQL_REWRITER ) \
|
||||
COMP( SQL_EXECUTION ) \
|
||||
COMP( SQL_STORE ) \
|
||||
\
|
||||
COMP( MAL_WLC ) \
|
||||
COMP( MAL_REMOTE ) \
|
||||
COMP( MAL_MAPI ) \
|
||||
COMP( MAL_SERVER ) \
|
||||
\
|
||||
COMP( MAL_OPTIMIZER ) \
|
||||
\
|
||||
COMP( GDK ) \
|
||||
\
|
||||
COMP( COMPONENTS_COUNT )
|
||||
|
||||
typedef enum {
|
||||
FOREACH_COMP(GENERATE_ENUM)
|
||||
} component_t;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Logging macros
|
||||
*/
|
||||
gdk_export log_level_t lvl_per_component[];
|
||||
|
||||
// If the LOG_LEVEL of the message is one of the following: CRITICAL,
|
||||
// ERROR or WARNING it is logged no matter the component. In any other
|
||||
// case the component is taken into account
|
||||
#define GDK_TRACER_TEST(LOG_LEVEL, COMP) \
|
||||
(LOG_LEVEL <= M_WARNING || \
|
||||
lvl_per_component[COMP] >= LOG_LEVEL)
|
||||
|
||||
|
||||
#define GDK_TRACER_LOG_BODY(LOG_LEVEL, COMP, MSG, ...) \
|
||||
GDKtracer_log(__FILE__, __func__, __LINE__, \
|
||||
LOG_LEVEL, COMP, NULL, MSG, ##__VA_ARGS__)
|
||||
|
||||
#ifdef __COVERITY__
|
||||
/* hide this for static code analysis: too many false positives */
|
||||
#define GDK_TRACER_LOG(LOG_LEVEL, COMP, MSG, ...) ((void) 0)
|
||||
#else
|
||||
#define GDK_TRACER_LOG(LOG_LEVEL, COMP, MSG, ...) \
|
||||
do { \
|
||||
if (GDK_TRACER_TEST(LOG_LEVEL, COMP)) { \
|
||||
GDK_TRACER_LOG_BODY(LOG_LEVEL, COMP, MSG, \
|
||||
## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
#define TRC_CRITICAL(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG_BODY(M_CRITICAL, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
#define TRC_ERROR(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG_BODY(M_ERROR, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
#define TRC_WARNING(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG_BODY(M_WARNING, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
#define TRC_INFO(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG(M_INFO, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
#define TRC_DEBUG(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG(M_DEBUG, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
// Conditional logging - Example usage
|
||||
// NOTE: When using the macro with *_IF always use the macro with
|
||||
// *_ENDIF for logging. Avoiding to do that will result into checking
|
||||
// the LOG_LEVEL of the the COMPONENT 2 times. Also NEVER use the
|
||||
// *_ENDIF macro without before performing a check with *_IF
|
||||
// macro. Such an action will have as a consequence logging everything
|
||||
// without taking into account the LOG_LEVEL of the COMPONENT.
|
||||
/*
|
||||
TRC_CRITICAL_IF(SQL_STORE)
|
||||
{
|
||||
TRC_CRITICAL_ENDIF(SQL_STORE, "Test\n")
|
||||
}
|
||||
*/
|
||||
#define TRC_CRITICAL_IF(COMP) \
|
||||
/* if (GDK_TRACER_TEST(M_CRITICAL, COMP)) */
|
||||
|
||||
#define TRC_ERROR_IF(COMP) \
|
||||
/* if (GDK_TRACER_TEST(M_ERROR, COMP)) */
|
||||
|
||||
#define TRC_WARNING_IF(COMP) \
|
||||
/* if (GDK_TRACER_TEST(M_WARNING, COMP)) */
|
||||
|
||||
#define TRC_INFO_IF(COMP) \
|
||||
if (GDK_TRACER_TEST(M_INFO, COMP))
|
||||
|
||||
#define TRC_DEBUG_IF(COMP) \
|
||||
if (GDK_TRACER_TEST(M_DEBUG, COMP))
|
||||
|
||||
|
||||
#define TRC_CRITICAL_ENDIF(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG_BODY(M_CRITICAL, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
#define TRC_ERROR_ENDIF(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG_BODY(M_ERROR, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
#define TRC_WARNING_ENDIF(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG_BODY(M_WARNING, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
#define TRC_INFO_ENDIF(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG_BODY(M_INFO, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
#define TRC_DEBUG_ENDIF(COMP, MSG, ...) \
|
||||
GDK_TRACER_LOG_BODY(M_DEBUG, COMP, MSG, ## __VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* GDKtracer API
|
||||
* For the allowed log_levels, components and layers see the
|
||||
* LOG_LEVEL, COMPONENT and LAYER enum respectively.
|
||||
*/
|
||||
// Used for logrotate
|
||||
gdk_export void GDKtracer_reinit_basic(int sig);
|
||||
|
||||
gdk_export gdk_return GDKtracer_set_tracefile(const char *tracefile);
|
||||
|
||||
gdk_export gdk_return GDKtracer_stop(void);
|
||||
|
||||
gdk_export gdk_return GDKtracer_set_component_level(const char *comp, const char *lvl);
|
||||
gdk_export const char *GDKtracer_get_component_level(const char *comp);
|
||||
gdk_export gdk_return GDKtracer_reset_component_level(const char *comp);
|
||||
|
||||
gdk_export gdk_return GDKtracer_set_layer_level(const char *layer, const char *lvl);
|
||||
gdk_export gdk_return GDKtracer_reset_layer_level(const char *layer);
|
||||
|
||||
gdk_export gdk_return GDKtracer_set_flush_level(const char *lvl);
|
||||
gdk_export gdk_return GDKtracer_reset_flush_level(void);
|
||||
|
||||
gdk_export gdk_return GDKtracer_set_adapter(const char *adapter);
|
||||
gdk_export gdk_return GDKtracer_reset_adapter(void);
|
||||
|
||||
gdk_export void GDKtracer_log(const char *file, const char *func,
|
||||
int lineno, log_level_t lvl,
|
||||
component_t comp,
|
||||
const char *syserr,
|
||||
_In_z_ _Printf_format_string_ const char *format, ...)
|
||||
__attribute__((__format__(__printf__, 7, 8)));
|
||||
|
||||
gdk_export gdk_return GDKtracer_flush_buffer(void);
|
||||
|
||||
#endif /* _GDK_TRACER_H_ */
|
@ -0,0 +1,357 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _GDK_UTILS_H_
|
||||
#define _GDK_UTILS_H_
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
gdk_export const char *GDKgetenv(const char *name);
|
||||
|
||||
gdk_export bool GDKgetenv_istext(const char *name, const char* text);
|
||||
gdk_export bool GDKgetenv_isyes(const char *name);
|
||||
gdk_export bool GDKgetenv_istrue(const char *name);
|
||||
|
||||
gdk_export int GDKgetenv_int(const char *name, int def);
|
||||
|
||||
gdk_export gdk_return GDKsetenv(const char *name, const char *value);
|
||||
gdk_export gdk_return GDKcopyenv(BAT **key, BAT **val, bool writable);
|
||||
|
||||
/*
|
||||
* @+ Memory management
|
||||
* Memory management in GDK mostly relies on the facilities offered by
|
||||
* the underlying OS. The below routines monitor the available memory
|
||||
* resources which consist of physical swap space and logical vm
|
||||
* space. There are three kinds of memory, that affect these two
|
||||
* resources in different ways:
|
||||
*
|
||||
* - memory mapping
|
||||
* which ask for a logical region of virtual memory space. In
|
||||
* principle, no physical memory is needed to keep the system afloat
|
||||
* here, as the memory mapped file is swapped onto a disk object
|
||||
* that already exists.
|
||||
*
|
||||
* Actually, there are two kings of memory mapping used in GDK,
|
||||
* namely read-only direct mapped and writable copy-on write. For
|
||||
* the dirty pages, the latter actually also consumes physical
|
||||
* memory resources, but that is ignored here for simplicity.
|
||||
*
|
||||
* - anonymous virtual memory
|
||||
* This is virtual memory that is mapped on the swap file. Hence,
|
||||
* this consumes both logical VM space resources and physical memory
|
||||
* space.
|
||||
*
|
||||
* - malloced memory
|
||||
* comes from the heap and directly consumes physical memory
|
||||
* resources.
|
||||
*
|
||||
* The malloc routine checks the memory consumption every 1000 calls,
|
||||
* or for calls larger that 50000 bytes. Consequently, at least every
|
||||
* 50MB increase, alloc memory is checked. The VM calls always check
|
||||
* the memory consumption.
|
||||
*/
|
||||
/* default setting to administer everything */
|
||||
#define GDK_MEM_NULLALLOWED
|
||||
|
||||
#if SIZEOF_VOID_P==8
|
||||
#define GDK_VM_MAXSIZE LL_CONSTANT(4398046511104) /* :-) a 64-bit OS: 4TB */
|
||||
#else
|
||||
#define GDK_VM_MAXSIZE LL_CONSTANT(1610612736) /* :-| a 32-bit OS: 1.5GB */
|
||||
#endif
|
||||
/* virtual memory defines */
|
||||
gdk_export size_t _MT_npages;
|
||||
gdk_export size_t _MT_pagesize;
|
||||
|
||||
#define MT_pagesize() _MT_pagesize
|
||||
#define MT_npages() _MT_npages
|
||||
|
||||
gdk_export size_t GDK_mem_maxsize; /* max allowed size of committed memory */
|
||||
gdk_export size_t GDK_vm_maxsize; /* max allowed size of reserved vm */
|
||||
|
||||
gdk_export void *GDKmmap(const char *path, int mode, size_t len)
|
||||
__attribute__((__warn_unused_result__));
|
||||
gdk_export gdk_return GDKmunmap(void *addr, size_t len);
|
||||
|
||||
gdk_export size_t GDKmem_cursize(void); /* RAM/swapmem that MonetDB has claimed from OS */
|
||||
gdk_export size_t GDKvm_cursize(void); /* current MonetDB VM address space usage */
|
||||
|
||||
gdk_export void *GDKmalloc(size_t size)
|
||||
__attribute__((__malloc__))
|
||||
__attribute__((__alloc_size__(1)))
|
||||
__attribute__((__warn_unused_result__));
|
||||
gdk_export void *GDKzalloc(size_t size)
|
||||
__attribute__((__malloc__))
|
||||
__attribute__((__alloc_size__(1)))
|
||||
__attribute__((__warn_unused_result__));
|
||||
gdk_export void *GDKrealloc(void *pold, size_t size)
|
||||
__attribute__((__alloc_size__(2)))
|
||||
__attribute__((__warn_unused_result__));
|
||||
gdk_export void GDKfree(void *blk);
|
||||
gdk_export str GDKstrdup(const char *s)
|
||||
__attribute__((__malloc__))
|
||||
__attribute__((__warn_unused_result__));
|
||||
gdk_export str GDKstrndup(const char *s, size_t n)
|
||||
__attribute__((__malloc__))
|
||||
__attribute__((__warn_unused_result__));
|
||||
gdk_export size_t GDKmallocated(const void *s);
|
||||
|
||||
gdk_export void MT_init(void); /* init the package. */
|
||||
struct opt;
|
||||
gdk_export gdk_return GDKinit(struct opt *set, int setlen, bool embedded);
|
||||
|
||||
/* used for testing only */
|
||||
gdk_export void GDKsetmallocsuccesscount(lng count);
|
||||
|
||||
/*
|
||||
* Upon closing the session, all persistent BATs should be saved and
|
||||
* the transient BATs should be removed. The buffer pool manager
|
||||
* takes care of this.
|
||||
*/
|
||||
gdk_export void GDKexit(int status);
|
||||
gdk_export bool GDKexiting(void);
|
||||
|
||||
gdk_export void GDKprepareExit(void);
|
||||
gdk_export void GDKreset(int status);
|
||||
/* global version number */
|
||||
gdk_export const char *GDKversion(void)
|
||||
__attribute__((__const__));
|
||||
/* ABI version of GDK library */
|
||||
gdk_export const char *GDKlibversion(void)
|
||||
__attribute__((__const__));
|
||||
|
||||
// these are used in embedded mode to jump out of GDKfatal
|
||||
gdk_export jmp_buf GDKfataljump;
|
||||
gdk_export str GDKfatalmsg;
|
||||
gdk_export bit GDKfataljumpenable;
|
||||
|
||||
/* Timers
|
||||
* The following relative timers are available for inspection.
|
||||
* Note that they may consume recognizable overhead.
|
||||
*
|
||||
*/
|
||||
gdk_export lng GDKusec(void);
|
||||
gdk_export int GDKms(void);
|
||||
|
||||
|
||||
#if !defined(NDEBUG) && !defined(__COVERITY__)
|
||||
/* In debugging mode, replace GDKmalloc and other functions with a
|
||||
* version that optionally prints calling information.
|
||||
*
|
||||
* We have two versions of this code: one using a GNU C extension, and
|
||||
* one using traditional C. The GNU C version also prints the name of
|
||||
* the calling function.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define GDKmalloc(s) \
|
||||
({ \
|
||||
size_t _size = (s); \
|
||||
void *_res = GDKmalloc(_size); \
|
||||
TRC_DEBUG(ALLOC, "GDKmalloc(%zu) -> %p\n", \
|
||||
_size, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define GDKzalloc(s) \
|
||||
({ \
|
||||
size_t _size = (s); \
|
||||
void *_res = GDKzalloc(_size); \
|
||||
TRC_DEBUG(ALLOC, "GDKzalloc(%zu) -> %p\n", \
|
||||
_size, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define GDKrealloc(p, s) \
|
||||
({ \
|
||||
void *_ptr = (p); \
|
||||
size_t _size = (s); \
|
||||
char _buf[12]; \
|
||||
snprintf(_buf, sizeof(_buf), "%p", _ptr); \
|
||||
void *_res = GDKrealloc(_ptr, _size); \
|
||||
TRC_DEBUG(ALLOC, "GDKrealloc(%s,%zu) -> %p\n", \
|
||||
_buf, _size, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define GDKfree(p) \
|
||||
({ \
|
||||
void *_ptr = (p); \
|
||||
if (_ptr) \
|
||||
TRC_DEBUG(ALLOC, "GDKfree(%p)\n", _ptr); \
|
||||
GDKfree(_ptr); \
|
||||
})
|
||||
#define GDKstrdup(s) \
|
||||
({ \
|
||||
const char *_str = (s); \
|
||||
void *_res = GDKstrdup(_str); \
|
||||
TRC_DEBUG(ALLOC, "GDKstrdup(len=%zu) -> %p\n", \
|
||||
_str ? strlen(_str) : 0, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define GDKstrndup(s, n) \
|
||||
({ \
|
||||
const char *_str = (s); \
|
||||
size_t _n = (n); \
|
||||
void *_res = GDKstrndup(_str, _n); \
|
||||
TRC_DEBUG(ALLOC, "GDKstrndup(len=%zu) -> %p\n", \
|
||||
_n, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define GDKmmap(p, m, l) \
|
||||
({ \
|
||||
const char *_path = (p); \
|
||||
int _mode = (m); \
|
||||
size_t _len = (l); \
|
||||
void *_res = GDKmmap(_path, _mode, _len); \
|
||||
TRC_DEBUG(ALLOC, "GDKmmap(%s,0x%x,%zu) -> %p\n", \
|
||||
_path ? _path : "NULL", \
|
||||
(unsigned) _mode, _len, \
|
||||
_res); \
|
||||
_res; \
|
||||
})
|
||||
#define GDKmunmap(p, l) \
|
||||
({ void *_ptr = (p); \
|
||||
size_t _len = (l); \
|
||||
gdk_return _res = GDKmunmap(_ptr, _len); \
|
||||
TRC_DEBUG(ALLOC, \
|
||||
"GDKmunmap(%p,%zu) -> %u\n", \
|
||||
_ptr, _len, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define malloc(s) \
|
||||
({ \
|
||||
size_t _size = (s); \
|
||||
void *_res = malloc(_size); \
|
||||
TRC_DEBUG(ALLOC, "malloc(%zu) -> %p\n", \
|
||||
_size, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define calloc(n, s) \
|
||||
({ \
|
||||
size_t _nmemb = (n); \
|
||||
size_t _size = (s); \
|
||||
void *_res = calloc(_nmemb,_size); \
|
||||
TRC_DEBUG(ALLOC, "calloc(%zu,%zu) -> %p\n", \
|
||||
_nmemb, _size, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define realloc(p, s) \
|
||||
({ \
|
||||
void *_ptr = (p); \
|
||||
size_t _size = (s); \
|
||||
char _buf[12]; \
|
||||
snprintf(_buf, sizeof(_buf), "%p", _ptr); \
|
||||
void *_res = realloc(_ptr, _size); \
|
||||
TRC_DEBUG(ALLOC, "realloc(%s,%zu) -> %p\n", \
|
||||
_buf, _size, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define free(p) \
|
||||
({ \
|
||||
void *_ptr = (p); \
|
||||
TRC_DEBUG(ALLOC, "free(%p)\n", _ptr); \
|
||||
free(_ptr); \
|
||||
})
|
||||
#else
|
||||
static inline void *
|
||||
GDKmalloc_debug(size_t size)
|
||||
{
|
||||
void *res = GDKmalloc(size);
|
||||
TRC_DEBUG(ALLOC, "GDKmalloc(%zu) -> %p\n", size, res);
|
||||
return res;
|
||||
}
|
||||
#define GDKmalloc(s) GDKmalloc_debug((s))
|
||||
static inline void *
|
||||
GDKzalloc_debug(size_t size)
|
||||
{
|
||||
void *res = GDKzalloc(size);
|
||||
TRC_DEBUG(ALLOC, "GDKzalloc(%zu) -> %p\n", size, res);
|
||||
return res;
|
||||
}
|
||||
#define GDKzalloc(s) GDKzalloc_debug((s))
|
||||
static inline void *
|
||||
GDKrealloc_debug(void *ptr, size_t size)
|
||||
{
|
||||
void *res = GDKrealloc(ptr, size);
|
||||
TRC_DEBUG(ALLOC, "GDKrealloc(%p,%zu) -> %p\n", ptr, size, res);
|
||||
return res;
|
||||
}
|
||||
#define GDKrealloc(p, s) GDKrealloc_debug((p), (s))
|
||||
static inline void
|
||||
GDKfree_debug(void *ptr)
|
||||
{
|
||||
TRC_DEBUG(ALLOC, "GDKfree(%p)\n", ptr);
|
||||
GDKfree(ptr);
|
||||
}
|
||||
#define GDKfree(p) GDKfree_debug((p))
|
||||
static inline char *
|
||||
GDKstrdup_debug(const char *str)
|
||||
{
|
||||
void *res = GDKstrdup(str);
|
||||
TRC_DEBUG(ALLOC, "GDKstrdup(len=%zu) -> %p\n",
|
||||
str ? strlen(str) : 0, res);
|
||||
return res;
|
||||
}
|
||||
#define GDKstrdup(s) GDKstrdup_debug((s))
|
||||
static inline char *
|
||||
GDKstrndup_debug(const char *str, size_t n)
|
||||
{
|
||||
void *res = GDKstrndup(str, n);
|
||||
TRC_DEBUG(ALLOC, "GDKstrndup(len=%zu) -> %p\n", n, res);
|
||||
return res;
|
||||
}
|
||||
#define GDKstrndup(s, n) GDKstrndup_debug((s), (n))
|
||||
static inline void *
|
||||
GDKmmap_debug(const char *path, int mode, size_t len)
|
||||
{
|
||||
void *res = GDKmmap(path, mode, len);
|
||||
TRC_DEBUG(ALLOC, "GDKmmap(%s,0x%x,%zu) -> %p\n",
|
||||
path ? path : "NULL", (unsigned) mode, len, res);
|
||||
return res;
|
||||
}
|
||||
#define GDKmmap(p, m, l) GDKmmap_debug((p), (m), (l))
|
||||
static inline gdk_return
|
||||
GDKmunmap_debug(void *ptr, size_t len)
|
||||
{
|
||||
gdk_return res = GDKmunmap(ptr, len);
|
||||
TRC_DEBUG(ALLOC, "GDKmunmap(%p,%zu) -> %d\n",
|
||||
ptr, len, (int) res);
|
||||
return res;
|
||||
}
|
||||
#define GDKmunmap(p, l) GDKmunmap_debug((p), (l))
|
||||
static inline void *
|
||||
malloc_debug(size_t size)
|
||||
{
|
||||
void *res = malloc(size);
|
||||
TRC_DEBUG(ALLOC, "malloc(%zu) -> %p\n", size, res);
|
||||
return res;
|
||||
}
|
||||
#define malloc(s) malloc_debug((s))
|
||||
static inline void *
|
||||
calloc_debug(size_t nmemb, size_t size)
|
||||
{
|
||||
void *res = calloc(nmemb, size);
|
||||
TRC_DEBUG(ALLOC, "calloc(%zu,%zu) -> %p\n", nmemb, size, res);
|
||||
return res;
|
||||
}
|
||||
#define calloc(n, s) calloc_debug((n), (s))
|
||||
static inline void *
|
||||
realloc_debug(void *ptr, size_t size)
|
||||
{
|
||||
void *res = realloc(ptr, size);
|
||||
TRC_DEBUG(ALLOC, "realloc(%p,%zu) -> %p \n", ptr, size, res);
|
||||
return res;
|
||||
}
|
||||
#define realloc(p, s) realloc_debug((p), (s))
|
||||
static inline void
|
||||
free_debug(void *ptr)
|
||||
{
|
||||
TRC_DEBUG(ALLOC, "free(%p)\n", ptr);
|
||||
free(ptr);
|
||||
}
|
||||
#define free(p) free_debug((p))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _GDK_UTILS_H_ */
|
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (c) Martin Kersten
|
||||
* MonetDB Basic Definitions
|
||||
* Definitions that need to included in every file of the Monet system, as well as in user defined module implementations.
|
||||
*/
|
||||
#ifndef _MAL_H
|
||||
#define _MAL_H
|
||||
|
||||
#include "gdk.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef LIBMONETDB5
|
||||
#define mal_export extern __declspec(dllimport)
|
||||
#else
|
||||
#define mal_export extern __declspec(dllexport)
|
||||
#endif
|
||||
#else
|
||||
#define mal_export extern
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TIMES_H
|
||||
# include <sys/times.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MonetDB Calling Options
|
||||
* The number of invocation arguments is kept to a minimum.
|
||||
* See `man mserver5` or tools/mserver/mserver5.1
|
||||
* for additional system variable settings.
|
||||
*/
|
||||
#define MAXSCRIPT 64
|
||||
mal_export lng MALdebug;
|
||||
|
||||
/*
|
||||
* MonetDB assumes it can use most of the machines memory,
|
||||
* leaving a small portion for other programs.
|
||||
*/
|
||||
#define GB (((lng)1024)*1024*1024)
|
||||
#define MEMORY_THRESHOLD (0.2 * GDK_mem_maxsize > 8 * GB? GDK_mem_maxsize - 8 * GB: 0.8 * GDK_mem_maxsize)
|
||||
|
||||
mal_export char monet_cwd[FILENAME_MAX];
|
||||
mal_export char monet_characteristics[4096];
|
||||
mal_export stream *maleventstream;
|
||||
|
||||
/*
|
||||
See gdk/gdk.h for the definition of all debug masks.
|
||||
See `man mserver5` or tools/mserver/mserver5.1
|
||||
for a documentation of all debug options.
|
||||
*/
|
||||
#define GRPthreads (THRDMASK | PARMASK)
|
||||
#define GRPmemory (ALLOCMASK )
|
||||
#define GRPproperties (CHECKMASK | PROPMASK | BATMASK )
|
||||
#define GRPio (IOMASK | PERFMASK )
|
||||
#define GRPheaps (HEAPMASK)
|
||||
#define GRPtransactions (TMMASK | DELTAMASK | TEMMASK)
|
||||
#define GRPmodules (LOADMASK)
|
||||
#define GRPalgorithms (ALGOMASK)
|
||||
#define GRPperformance (DEADBEEFMASK)
|
||||
#define GRPforcemito (FORCEMITOMASK | NOSYNCMASK)
|
||||
|
||||
mal_export MT_Lock mal_contextLock;
|
||||
mal_export MT_Lock mal_remoteLock;
|
||||
mal_export MT_Lock mal_profileLock ;
|
||||
mal_export MT_Lock mal_copyLock ;
|
||||
mal_export MT_Lock mal_delayLock ;
|
||||
|
||||
mal_export int mal_init(char *modules[], int embedded);
|
||||
mal_export _Noreturn void mal_exit(int status);
|
||||
mal_export void mal_reset(void);
|
||||
mal_export const char *mal_version(void);
|
||||
|
||||
/* This should be here, but cannot, as "Client" isn't known, yet ... |-(
|
||||
* For now, we move the prototype declaration to src/mal/mal_client.c,
|
||||
* the only place where it is currently used. Maybe, we should concider
|
||||
* also moving the implementation there...
|
||||
*/
|
||||
|
||||
/* Listing modes are globally known */
|
||||
#define LIST_INPUT 1 /* echo original input */
|
||||
#define LIST_MAL_NAME 2 /* show variable name */
|
||||
#define LIST_MAL_TYPE 4 /* show type resolutoin */
|
||||
#define LIST_MAL_VALUE 8 /* list bat tuple count */
|
||||
#define LIST_MAL_PROPS 16 /* show variable properties */
|
||||
#define LIST_MAL_MAPI 32 /* output Mapi compatible output */
|
||||
#define LIST_MAL_REMOTE 64 /* output MAL for remote execution */
|
||||
#define LIST_MAL_FLOW 128 /* output MAL dataflow dependencies */
|
||||
#define LIST_MAL_ALGO 256 /* output algorithm used */
|
||||
#define LIST_MAL_CALL (LIST_MAL_NAME | LIST_MAL_VALUE )
|
||||
#define LIST_MAL_DEBUG (LIST_MAL_NAME | LIST_MAL_VALUE | LIST_MAL_TYPE | LIST_MAL_PROPS | LIST_MAL_FLOW)
|
||||
#define LIST_MAL_ALL (LIST_MAL_NAME | LIST_MAL_VALUE | LIST_MAL_TYPE | LIST_MAL_MAPI)
|
||||
|
||||
/* type check status is kept around to improve type checking efficiency */
|
||||
#define TYPE_ERROR -1
|
||||
#define TYPE_UNKNOWN 0
|
||||
#define TYPE_RESOLVED 2
|
||||
#define GARBAGECONTROL 3
|
||||
|
||||
#define VARARGS 1 /* deal with variable arguments */
|
||||
#define VARRETS 2
|
||||
|
||||
typedef int malType;
|
||||
typedef str (*MALfcn) ();
|
||||
|
||||
typedef struct SYMDEF {
|
||||
struct SYMDEF *peer; /* where to look next */
|
||||
struct SYMDEF *skip; /* skip to next different symbol */
|
||||
const char *name;
|
||||
int kind; /* what kind of symbol */
|
||||
struct MALBLK *def; /* the details of the MAL fcn */
|
||||
} *Symbol, SymRecord;
|
||||
|
||||
typedef struct VARRECORD {
|
||||
char name[IDLENGTH]; /* use the space for the full name */
|
||||
char kind; /* Could be either _, X or C to stamp the variable type */
|
||||
malType type; /* internal type signature */
|
||||
bool constant:1,
|
||||
typevar:1,
|
||||
fixedtype:1,
|
||||
//FREE SPOT NOW:1,
|
||||
cleanup:1,
|
||||
initialized:1,
|
||||
used:1,
|
||||
disabled:1;
|
||||
short depth; /* scope block depth, set to -1 if not used */
|
||||
ValRecord value;
|
||||
int declared; /* pc index when it was first assigned */
|
||||
int updated; /* pc index when it was first updated */
|
||||
int eolife; /* pc index when it should be garbage collected */
|
||||
int stc; /* pc index for rendering schema.table.column */
|
||||
BUN rowcnt; /* estimated row count*/
|
||||
} *VarPtr, VarRecord;
|
||||
|
||||
/* For performance analysis we keep track of the number of calls and
|
||||
* the total time spent while executing the instruction. (See
|
||||
* mal_profiler.c)
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
bte token; /* instruction type */
|
||||
bit barrier; /* flow of control modifier takes:
|
||||
BARRIER, LEAVE, REDO, EXIT, CATCH, RAISE */
|
||||
bit typechk; /* type check status */
|
||||
bte gc; /* garbage control flags */
|
||||
bte polymorphic; /* complex type analysis */
|
||||
bit varargs; /* variable number of arguments */
|
||||
int jump; /* controlflow program counter */
|
||||
int pc; /* location in MAL plan for profiler*/
|
||||
MALfcn fcn; /* resolved function address */
|
||||
struct MALBLK *blk; /* resolved MAL function address */
|
||||
/* inline statistics */
|
||||
lng clock; /* when the last call was started */
|
||||
lng ticks; /* total micro seconds spent in last call */
|
||||
int calls; /* number of calls made to this instruction */
|
||||
lng totticks; /* total time spent on this instruction. */
|
||||
lng wbytes; /* number of bytes produced in last instruction */
|
||||
/* the core admin */
|
||||
const char *modname; /* module context, reference into namespace */
|
||||
const char *fcnname; /* function name, reference into namespace */
|
||||
int argc, retc, maxarg; /* total and result argument count */
|
||||
int argv[FLEXIBLE_ARRAY_MEMBER]; /* at least a few entries */
|
||||
} *InstrPtr, InstrRecord;
|
||||
|
||||
typedef struct MALBLK {
|
||||
char binding[IDLENGTH]; /* related C-function */
|
||||
str help; /* supportive commentary */
|
||||
str statichelp; /* static help string should not be freed */
|
||||
oid tag; /* unique block tag */
|
||||
struct MALBLK *alternative;
|
||||
int vtop; /* next free slot */
|
||||
int vsize; /* size of variable arena */
|
||||
int vid; /* generate local variable counter */
|
||||
VarRecord *var; /* Variable table */
|
||||
int stop; /* next free slot */
|
||||
int ssize; /* byte size of arena */
|
||||
InstrPtr *stmt; /* Instruction location */
|
||||
|
||||
bool inlineProp:1, /* inline property */
|
||||
unsafeProp:1; /* unsafe property */
|
||||
|
||||
str errors; /* left over errors */
|
||||
struct MALBLK *history; /* of optimizer actions */
|
||||
short keephistory; /* do we need the history at all */
|
||||
int maxarg; /* keep track on the maximal arguments used */
|
||||
ptr replica; /* for the replicator tests */
|
||||
|
||||
/* During the run we keep track on the maximum number of concurrent threads and memory claim */
|
||||
int workers;
|
||||
lng memory;
|
||||
lng starttime; /* track when the query started, for resource management */
|
||||
lng runtime; /* average execution time of block in ticks */
|
||||
int calls; /* number of calls */
|
||||
lng optimize; /* total optimizer time */
|
||||
} *MalBlkPtr, MalBlkRecord;
|
||||
|
||||
#define STACKINCR 128
|
||||
#define MAXGLOBALS (4 * STACKINCR)
|
||||
|
||||
typedef int (*DFhook) (void *, void *, void *, void *);
|
||||
|
||||
typedef struct MALSTK {
|
||||
int stksize;
|
||||
int stktop;
|
||||
int stkbot; /* the first variable to be initialized */
|
||||
int stkdepth; /* to protect against runtime stack overflow */
|
||||
int calldepth; /* to protect against runtime stack overflow */
|
||||
short keepAlive; /* do not garbage collect when set */
|
||||
/*
|
||||
* Parallel processing is mostly driven by dataflow, but within this context
|
||||
* there may be different schemes to take instructions into execution.
|
||||
* The admission scheme (and wrapup) are the necessary scheduler hooks.
|
||||
*/
|
||||
DFhook admit;
|
||||
DFhook wrapup;
|
||||
|
||||
/*
|
||||
* It is handy to administer the timing in the stack frame
|
||||
* for use in profiling instructions.
|
||||
*/
|
||||
struct timeval clock; /* time this stack was created */
|
||||
char cmd; /* debugger and runtime communication */
|
||||
char status; /* srunning 'R' suspended 'S', quiting 'Q' */
|
||||
int pcup; /* saved pc upon a recursive all */
|
||||
oid tag; /* unique invocation call tag */
|
||||
int workers; /* Actual number of concurrent workers */
|
||||
lng memory; /* Actual memory claims for highwater mark */
|
||||
|
||||
struct MALSTK *up; /* stack trace list */
|
||||
struct MALBLK *blk; /* associated definition */
|
||||
ValRecord stk[FLEXIBLE_ARRAY_MEMBER];
|
||||
} MalStack, *MalStkPtr;
|
||||
|
||||
#endif /* _MAL_H*/
|
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _MAL_CLIENT_H_
|
||||
#define _MAL_CLIENT_H_
|
||||
|
||||
#include "mal.h"
|
||||
|
||||
#include "mal_module.h"
|
||||
|
||||
#define SCENARIO_PROPERTIES 8
|
||||
|
||||
enum clientmode {
|
||||
FREECLIENT,
|
||||
FINISHCLIENT,
|
||||
RUNCLIENT,
|
||||
BLOCKCLIENT
|
||||
};
|
||||
|
||||
/*
|
||||
* The prompt structure is designed to simplify recognition of the
|
||||
* language framework for interaction. For access through an API we
|
||||
* assume the prompt is an ASCII string surrounded by a \001 character. This
|
||||
* simplifies recognition. The information between the prompt brackets
|
||||
* can be used to pass the mode to the front-end. Moreover, the prompt
|
||||
* can be dropped if a single stream of information is expected from the
|
||||
* server (see mal_profiler.c).
|
||||
*
|
||||
* The user can request server-side compilation as part of the
|
||||
* initialization string. See the documentation on Scenarios.
|
||||
*/
|
||||
typedef struct CLIENT_INPUT {
|
||||
bstream *fdin;
|
||||
size_t yycur;
|
||||
int listing;
|
||||
char *prompt;
|
||||
struct CLIENT_INPUT *next;
|
||||
} ClientInput;
|
||||
|
||||
typedef struct CLIENT {
|
||||
int idx; /* entry in mal_clients */
|
||||
oid user; /* user id in the auth administration */
|
||||
str username; /* for event processor */
|
||||
/*
|
||||
* The actions for a client is separated into several stages:
|
||||
* parsing, strategic optimization, tactical optimization, and
|
||||
* execution. The routines to handle them are obtained once the
|
||||
* scenario is chosen. Each stage carries a state descriptor, but
|
||||
* they share the IO state description. A backup structure is
|
||||
* provided to temporarily switch to another scenario.
|
||||
*/
|
||||
str scenario; /* scenario management references */
|
||||
str oldscenario;
|
||||
void *state[SCENARIO_PROPERTIES], *oldstate[SCENARIO_PROPERTIES];
|
||||
MALfcn phase[SCENARIO_PROPERTIES], oldphase[SCENARIO_PROPERTIES];
|
||||
char itrace; /* trace execution using interactive mdb */
|
||||
/* if set to 'S' it will put the process to sleep */
|
||||
bit sqlprofiler; /* control off-line sql performance monitoring */
|
||||
/*
|
||||
* Each session comes with resource limitations and predefined settings.
|
||||
*/
|
||||
char optimizer[IDLENGTH];/* The optimizer pipe preferred for this session */
|
||||
int workerlimit; /* maximum number of workthreads processing a query */
|
||||
int memorylimit; /* Memory claim highwater mark, 0 = no limit */
|
||||
lng querytimeout; /* query abort after x usec, 0 = no limit*/
|
||||
lng sessiontimeout; /* session abort after x usec, 0 = no limit */
|
||||
|
||||
time_t login; /* Time when this session started */
|
||||
lng session; /* usec since start of server */
|
||||
time_t idle; /* Time when the session became idle */
|
||||
|
||||
/*
|
||||
* For program debugging and performance trace we keep the actual resource claims.
|
||||
*/
|
||||
time_t lastcmd; /* set when query is received */
|
||||
|
||||
/* The user can request a TRACE SQL statement, calling for collecting the events locally */
|
||||
BAT *profticks;
|
||||
BAT *profstmt;
|
||||
BAT *profevents;
|
||||
|
||||
ATOMIC_TYPE lastprint; /* when we last printed the query, to be depricated */
|
||||
/*
|
||||
* Communication channels for the interconnect are stored here.
|
||||
* It is perfectly legal to have a client without input stream.
|
||||
* It will simply terminate after consuming the input buffer.
|
||||
*/
|
||||
const char *srcFile; /* NULL for stdin, or file name */
|
||||
bstream *fdin;
|
||||
size_t yycur; /* the scanners current position */
|
||||
/*
|
||||
* Keeping track of instructions executed is a valuable tool for
|
||||
* script processing and debugging. It can be changed at runtime
|
||||
* for individual clients using the operation clients.listing(mask).
|
||||
* A listing bit controls the level of detail to be generated during
|
||||
* program execution tracing. The lowest level (1) simply dumps the
|
||||
* input, (2) also demonstrates the MAL internal structure, (4) adds
|
||||
* the type information.
|
||||
*/
|
||||
int listing;
|
||||
str prompt; /* acknowledge prompt */
|
||||
size_t promptlength;
|
||||
ClientInput *bak; /* used for recursive script and string execution */
|
||||
|
||||
stream *fdout; /* streams from and to user. */
|
||||
/*
|
||||
* In interactive mode, reading one line at a time, we should be
|
||||
* aware of parsing compound structures, such as functions and
|
||||
* barrier blocks. The level of nesting is maintained in blkmode,
|
||||
* which is reset to zero upon encountering an end instruction, or
|
||||
* the closing bracket has been detected. Once the complete
|
||||
* structure has been parsed the program can be checked and
|
||||
* executed. Nesting is indicated using a '+' before the prompt.
|
||||
*/
|
||||
int blkmode; /* control block parsing */
|
||||
/*
|
||||
* The MAL debugger uses the client record to keep track of any
|
||||
* pervasive debugger command. For detailed information on the
|
||||
* debugger features.
|
||||
*/
|
||||
int debug;
|
||||
enum clientmode mode; /* FREECLIENT..BLOCKED */
|
||||
/*
|
||||
* Client records are organized into a two-level dependency tree,
|
||||
* where children may be created to deal with parallel processing
|
||||
* activities. Each client runs in its own process thread. Its
|
||||
* identity is retained here for access by others (=father).
|
||||
*/
|
||||
MT_Sema s; /* sema to (de)activate thread */
|
||||
Thread mythread;
|
||||
str errbuf; /* location of GDK exceptions */
|
||||
struct CLIENT *father;
|
||||
/*
|
||||
* Each client has a private entry point into the namespace and
|
||||
* object space (the global variables). Moreover, the parser needs
|
||||
* some administration variables to keep track of critical elements.
|
||||
*/
|
||||
Module usermodule; /* private user scope */
|
||||
Module curmodule; /* where to deliver the symbol, used by parser , only freed globally */
|
||||
Symbol curprg; /* container for the malparser */
|
||||
Symbol backup; /* saving the parser context for functions,commands/patterns */
|
||||
MalStkPtr glb; /* global variable stack */
|
||||
|
||||
/*
|
||||
* Here are pointers to scenario backends contexts. For the time
|
||||
* being just SQL. We need a pointer for each of them, since they
|
||||
* have to be able to interoperate with each other, e.g. both
|
||||
* contexts at the same time are in use.
|
||||
*/
|
||||
void *sqlcontext;
|
||||
|
||||
/*
|
||||
* The workload for replication/replay is saved initially as a MAL block.
|
||||
* It is split into the capturing part (wlc) and the replay part (wlr).
|
||||
* This allows a single server to act as both a master and a replica.
|
||||
*/
|
||||
int wlc_kind; // used by master to characterise the compound transaction
|
||||
MalBlkPtr wlc;
|
||||
|
||||
/*
|
||||
* Errors during copy into are collected in a user specific column set
|
||||
*/
|
||||
BAT *error_row;
|
||||
BAT *error_fld;
|
||||
BAT *error_msg;
|
||||
BAT *error_input;
|
||||
|
||||
size_t blocksize;
|
||||
protocol_version protocol;
|
||||
bool filetrans; /* whether the client can read files for us */
|
||||
char *handshake_options;
|
||||
char *query; /* string, identify whatever we're working on */
|
||||
} *Client, ClientRec;
|
||||
|
||||
mal_export int MAL_MAXCLIENTS;
|
||||
mal_export ClientRec *mal_clients;
|
||||
|
||||
mal_export Client MCgetClient(int id);
|
||||
mal_export Client MCinitClient(oid user, bstream *fin, stream *fout);
|
||||
mal_export Client MCforkClient(Client father);
|
||||
mal_export void MCstopClients(Client c);
|
||||
mal_export int MCactiveClients(void);
|
||||
mal_export size_t MCmemoryClaim(void);
|
||||
mal_export void MCcloseClient(Client c);
|
||||
mal_export str MCsuspendClient(int id);
|
||||
mal_export str MCawakeClient(int id);
|
||||
mal_export int MCpushClientInput(Client c, bstream *new_input, int listing, char *prompt);
|
||||
mal_export int MCvalid(Client c);
|
||||
|
||||
#endif /* _MAL_CLIENT_H_ */
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The error strings are geared at answering the question "what happened".
|
||||
* Optional information about "why it happened" is added
|
||||
* as local strings in the code base with possibly runtime information.
|
||||
* Information on "how to avoid it" is sporadically added using expected values.
|
||||
*
|
||||
* General considerations on error classes are summarized below:
|
||||
* MAL_MALLOC_FAIL
|
||||
* An operation allocates space for an object failed.
|
||||
* Either the pre-requisites are not satisfied, or the system
|
||||
* runs low on resources and can not accomodate the object.
|
||||
* For failures to create BATs it sometimes indicates that an
|
||||
* intermediate BAT size is too large.
|
||||
* OPERATION_FAILED
|
||||
* Mostly the module and function name are indicative enough.
|
||||
* If possible more is said about the error context,
|
||||
* informative references to arguments or variables,
|
||||
* provided it is produced by the underlying implementation.
|
||||
* GDK_EXCEPTION
|
||||
* In general these are generated deep inside the kernel.
|
||||
* They are captured by the MAL interpreter.
|
||||
* SEMANTIC_*
|
||||
* The patterns can be used to defer semantic type errors
|
||||
* to runtime.
|
||||
*
|
||||
* Getting all exception strings in one place improves consistency
|
||||
* and maintenance.
|
||||
*
|
||||
* At a later stage we could introduce internationalization support, i.e.
|
||||
* use a translation table where needed.
|
||||
*/
|
||||
#ifndef MAL_ERRORS
|
||||
#define MAL_ERRORS
|
||||
|
||||
#define SQLSTATE(sqlstate) #sqlstate "!"
|
||||
|
||||
#define MANUAL_HELP "See documentation for details"
|
||||
|
||||
#define PROGRAM_GENERAL "Program contains errors."
|
||||
#define PROGRAM_NYI "Not yet implemented"
|
||||
|
||||
#define SYNTAX_GENERAL "Syntax error detected."
|
||||
#define SYNTAX_SIGNATURE "Function signature missing."
|
||||
|
||||
#define SEMANTIC_GENERAL "Semantic errors detected"
|
||||
#define SEMANTIC_PROGRAM_ERRORS "Program contains semantic errors."
|
||||
#define SEMANTIC_SIGNATURE_MISSING "Function signature missing."
|
||||
#define SEMANTIC_OPERATION_MISSING "Operation not found."
|
||||
#define SEMANTIC_TYPE_ERROR "Explicit type required"
|
||||
#define SEMANTIC_TYPE_MISMATCH "Type mismatch"
|
||||
|
||||
#define INTERNAL_BAT_ACCESS "Internal error, can not access BAT."
|
||||
#define INTERNAL_BAT_HEAD "BAT has wrong head type"
|
||||
#define INTERNAL_OBJ_CREATE "Can not create object"
|
||||
#define INTERNAL_AUTHORIZATION "authorization BATs not empty"
|
||||
|
||||
#define MAL_MALLOC_FAIL "Could not allocate space"
|
||||
#define MAL_STACK_FAIL "Running out of stack space."
|
||||
#define MAL_CALLDEPTH_FAIL "Recursive call limit reached."
|
||||
|
||||
#define INVCRED_ACCESS_DENIED "access denied for user"
|
||||
#define INVCRED_INVALID_USER "invalid credentials for user"
|
||||
#define INVCRED_REMOVE_USER "Can not remove user"
|
||||
#define INVCRED_WRONG_ID "Undefined client id"
|
||||
|
||||
#define RUNTIME_IO_EOF "Attempt to read beyond end-of-file"
|
||||
#define RUNTIME_FILE_NOT_FOUND "File not found"
|
||||
#define RUNTIME_UNLINK "File could not be unlinked"
|
||||
#define RUNTIME_DIR_ERROR "Unable to open directory"
|
||||
#define RUNTIME_CREATE_ERROR "Unable to create file/directory"
|
||||
#define RUNTIME_STREAM_FAILED "Could not create stream"
|
||||
#define RUNTIME_STREAM_WRITE "Could not write to stream"
|
||||
#define RUNTIME_STREAM_INPUT "Could not read from stream"
|
||||
|
||||
#define RUNTIME_LOAD_ERROR "Loading error"
|
||||
#define RUNTIME_OBJECT_MISSING "Object not found"
|
||||
#define RUNTIME_SIGNATURE_MISSING "The <module>.<function> not found"
|
||||
#define RUNTIME_OBJECT_UNDEFINED "Object not found"
|
||||
#define RUNTIME_UNKNOWN_INSTRUCTION "Instruction type not supported"
|
||||
#define RUNTIME_QRY_TIMEOUT "Query aborted due to timeout"
|
||||
#define RUNTIME_SESSION_TIMEOUT "Query aborted due to session timeout"
|
||||
#define OPERATION_FAILED "operation failed"
|
||||
#define _OPERATION_FAILED "Operation failed"
|
||||
|
||||
#define BOX_CLOSED "Box is not open"
|
||||
|
||||
#define SABAOTH_NOT_INITIALIZED "Sabaoth not initialized"
|
||||
#define SABAOTH_USE_RESTRICTION "Sabaoth was not initialized as active database"
|
||||
|
||||
#define SCENARIO_NOT_FOUND "Scenario not initialized"
|
||||
|
||||
#define MACRO_SYNTAX_ERROR "RETURN statement is not the last one"
|
||||
#define MACRO_DUPLICATE "Duplicate macro expansion"
|
||||
#define MACRO_TOO_DEEP "Too many macro expansions"
|
||||
|
||||
#define OPTIMIZER_CYCLE "Too many optimization cycles"
|
||||
|
||||
#define ILLARG_NOTNIL " NIL not allowed"
|
||||
#define ILLARG_CONSTANTS "Constant argument required"
|
||||
|
||||
#define ILLEGAL_ARGUMENT "Illegal argument"
|
||||
#define IDENTIFIER_EXPECTED "Identifier expected"
|
||||
#define POSITIVE_EXPECTED "Argument must be positive"
|
||||
#define ARGUMENT_TOO_LARGE "Argument too large"
|
||||
#define TOO_MANY_BITS "Too many bits"
|
||||
#define DUPLICATE_DEFINITION "Duplicate definition"
|
||||
#define RANGE_ERROR "Range error"
|
||||
|
||||
#define SERVER_STOPPED "Server stopped"
|
||||
|
||||
#define XML_PARSE_ERROR "Document parse error"
|
||||
#define XML_COMMENT_ERROR "Comment may not contain '--'"
|
||||
#define XML_PI_ERROR "No processing instruction target specified"
|
||||
#define XML_VERSION_ERROR "Illegal XML version"
|
||||
#define XML_STANDALONE_ERROR "Illegal XML standalone value"
|
||||
#define XML_NOT_WELL_FORMED "Resulting document not well-formed"
|
||||
#define XML_ATTRIBUTE_ERROR "No attribute name specified"
|
||||
#define XML_ATTRIBUTE_INVALID "Invalid attribute name"
|
||||
#define XML_NO_ELEMENT "No element name specified"
|
||||
#define XML_NO_NAMESPACE "Namespace support not implemented"
|
||||
#define XML_ILLEGAL_NAMESPACE "Illegal namespace"
|
||||
#define XML_ILLEGAL_ATTRIBUTE "Illegal attribute"
|
||||
#define XML_ILLEGAL_CONTENT "Illegal content"
|
||||
|
||||
/* GDK_EXCEPTION should be by itself, i.e. not concatenated with some
|
||||
* other string; to enforce this we have the parentheses */
|
||||
#define GDK_EXCEPTION ("GDK reported error.")
|
||||
#define MAL_DEPRECATED "Deprecated MAL operation."
|
||||
|
||||
#define TYPE_NOT_SUPPORTED "Type is not supported"
|
||||
#endif /* MAL_ERRORS */
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _MAL_EXCEPTION_H
|
||||
#define _MAL_EXCEPTION_H
|
||||
#include "mal_instruction.h"
|
||||
|
||||
/* These are the exceptions known, adding new ones here requires to also
|
||||
* add the "full" name to the exceptionNames array in mal_exception.c */
|
||||
enum malexception {
|
||||
MAL=0,
|
||||
ILLARG,
|
||||
OUTOFBNDS,
|
||||
IO,
|
||||
INVCRED,
|
||||
OPTIMIZER,
|
||||
STKOF,
|
||||
SYNTAX,
|
||||
TYPE,
|
||||
LOADER,
|
||||
PARSE,
|
||||
ARITH,
|
||||
PERMD,
|
||||
SQL,
|
||||
REMOTE
|
||||
};
|
||||
|
||||
#define MAL_SUCCEED ((str) 0) /* no error */
|
||||
|
||||
#define throw \
|
||||
return createException
|
||||
#define rethrow(FCN, TMP, PRV) \
|
||||
do { if ((TMP = (PRV)) != MAL_SUCCEED) return(TMP); } while(0)
|
||||
|
||||
#if !__has_attribute(__returns_nonnull__)
|
||||
#define __returns_nonnull__
|
||||
#endif
|
||||
|
||||
mal_export str createException(enum malexception, const char *,
|
||||
_In_z_ _Printf_format_string_ const char *, ...)
|
||||
__attribute__((__format__(__printf__, 3, 4)))
|
||||
__attribute__((__returns_nonnull__));
|
||||
/*FIXmal_export str createMalException(MalBlkPtr mb, int pc, enum malexception type, const char *prev, const char *format, ...);*/
|
||||
mal_export str createMalException(MalBlkPtr , int , enum malexception ,
|
||||
_In_z_ _Printf_format_string_ const char *, ...)
|
||||
__attribute__((__format__(__printf__, 4, 5)))
|
||||
__attribute__((__returns_nonnull__));
|
||||
mal_export char *concatErrors(char *err1, const char *err2)
|
||||
__attribute__((__nonnull__(1))) __attribute__((__nonnull__(2)))
|
||||
__attribute__((__returns_nonnull__));
|
||||
mal_export bool isExceptionVariable(const char *nme);
|
||||
|
||||
mal_export enum malexception getExceptionType(const char *);
|
||||
mal_export str getExceptionPlace(const char *);
|
||||
mal_export str getExceptionMessageAndState(const char *);
|
||||
mal_export str getExceptionMessage(const char *);
|
||||
mal_export void freeException(str);
|
||||
|
||||
#include "mal_errors.h"
|
||||
#endif /* _MAL_EXCEPTION_H*/
|
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _MAL_INSTR_H
|
||||
#define _MAL_INSTR_H
|
||||
|
||||
#include "mal_type.h"
|
||||
#include "mal_stack.h"
|
||||
#include "mal_namespace.h"
|
||||
|
||||
#define isaSignature(P) ((P)->token >=COMMANDsymbol || (P)->token == PATTERNsymbol)
|
||||
|
||||
#ifdef HAVE_SYS_TIMES_H
|
||||
# include <sys/times.h>
|
||||
#endif
|
||||
|
||||
#define DEBUG_MAL_INSTR
|
||||
#define MAXARG 8 /* was 4 BEWARE the code depends on this knowledge, where? */
|
||||
#define STMT_INCREMENT 4
|
||||
#define MAL_VAR_WINDOW 16 // was 32
|
||||
#define MAXLISTING (64*1024)
|
||||
|
||||
/* Allocation of space assumes a rather exotic number of
|
||||
* arguments. Access to module and function name are cast in macros to
|
||||
* prepare for separate name space management. */
|
||||
#define getModuleId(P) ((P)->modname)
|
||||
#define setModuleId(P,S) (P)->modname= S
|
||||
#define setModuleScope(P,S) do {(P)->modname= (S)==NULL?NULL: (S)->name;} while (0)
|
||||
|
||||
#define getFunctionId(P) (P)->fcnname
|
||||
#define setFunctionId(P,S) (P)->fcnname= S
|
||||
#define garbageControl(P) ((P)->gc & GARBAGECONTROL)
|
||||
|
||||
#define getInstrPtr(M,I) (M)->stmt[I]
|
||||
#define putInstrPtr(M,I,P) (M)->stmt[I] = P
|
||||
#define getSignature(S) getInstrPtr((S)->def,0)
|
||||
#define isMain(M) ((getInstrPtr(M,0))->fcnname== putName("main",4))
|
||||
#define getFcnName(M) getFunctionId(getInstrPtr(M,0))
|
||||
#define getArgCount(M) getInstrPtr(M,0)->argc
|
||||
#define getModName(M) getModuleId(getInstrPtr(M,0))
|
||||
#define getPrgSize(M) (M)->stop
|
||||
|
||||
#define getVar(M,I) (&(M)->var[I])
|
||||
#define getVarType(M,I) ((M)->var[I].type)
|
||||
mal_export char* getVarName(MalBlkPtr mb, int idx);
|
||||
|
||||
#define getVarKind(M,I) ((M)->var[I].kind)
|
||||
#define getVarGDKType(M,I) getGDKType((M)->var[I].type)
|
||||
#define setVarType(M,I,V) ((M)->var[I].type = V)
|
||||
#define setVarKind(M,I,V) ((M)->var[I].kind = V) /* either _, X, or C */
|
||||
|
||||
#define clrVarFixed(M,I) ((M)->var[I].fixedtype = 0)
|
||||
#define setVarFixed(M,I) ((M)->var[I].fixedtype =1)
|
||||
#define isVarFixed(M,I) ((M)->var[I].fixedtype)
|
||||
|
||||
#define clrVarCleanup(M,I) ((M)->var[I].cleanup = 0)
|
||||
#define setVarCleanup(M,I) ((M)->var[I].cleanup = 1)
|
||||
#define isVarCleanup(M,I) ((M)->var[I].cleanup )
|
||||
|
||||
#define isTmpVar(M,I) (getVarKind(M,I) == REFMARKER)
|
||||
|
||||
#define clrVarUsed(M,I) ((M)->var[I].used = 0)
|
||||
#define setVarUsed(M,I) ((M)->var[I].used = 1)
|
||||
#define isVarUsed(M,I) ((M)->var[I].used)
|
||||
|
||||
#define clrVarDisabled(M,I) ((M)->var[I].disabled= 0 )
|
||||
#define setVarDisabled(M,I) ((M)->var[I].disabled = 1)
|
||||
#define isVarDisabled(M,I) ((M)->var[I].disabled)
|
||||
|
||||
#define clrVarInit(M,I) ((M)->var[I].initialized = 0)
|
||||
#define setVarInit(M,I) ((M)->var[I].initialized = 1)
|
||||
#define isVarInit(M,I) ((M)->var[I].initialized)
|
||||
|
||||
#define clrVarTypedef(M,I) ((M)->var[I].typevar = 0)
|
||||
#define setVarTypedef(M,I) ((M)->var[I].typevar = 1)
|
||||
#define isVarTypedef(M,I) ((M)->var[I].typevar)
|
||||
|
||||
#define clrVarConstant(M,I) ((M)->var[I].constant = 0)
|
||||
#define setVarConstant(M,I) ((M)->var[I].constant = 1)
|
||||
#define isVarConstant(M,I) ((M)->var[I].constant)
|
||||
|
||||
#define setVarDeclared(M,I,X) ((M)->var[I].declared = X )
|
||||
#define getVarDeclared(M,I) ((M)->var[I].declared)
|
||||
|
||||
#define setVarUpdated(M,I,X) ((M)->var[I].updated = X )
|
||||
#define getVarUpdated(M,I) ((M)->var[I].updated)
|
||||
|
||||
#define setVarEolife(M,I,X) ((M)->var[I].eolife = X )
|
||||
#define getVarEolife(M,I) ((M)->var[I].eolife)
|
||||
|
||||
#define setVarScope(M,I,S) ((M)->var[I].depth = S)
|
||||
#define getVarScope(M,I) ((M)->var[I].depth)
|
||||
|
||||
#define clrVarCList(M,I) ((M)->var[I].kind = REFMARKER)
|
||||
#define setVarCList(M,I) ((M)->var[I].kind = REFMARKERC)
|
||||
#define isVarCList(M,I) ((M)->var[I].kind == REFMARKERC)
|
||||
|
||||
#define getVarConstant(M,I) ((M)->var[I].value)
|
||||
#define getVarValue(M,I) VALget(&(M)->var[I].value)
|
||||
|
||||
#define setRowCnt(M,I,C) (M)->var[I].rowcnt = C
|
||||
#define getRowCnt(M,I) ((M)->var[I].rowcnt)
|
||||
|
||||
#define getVarSTC(M,I) ((M)->var[I].stc)
|
||||
|
||||
#define getDestVar(P) (P)->argv[0]
|
||||
#define setDestVar(P,X) (P)->argv[0] =X
|
||||
#define setDestType(M,P,V) setVarType((M),getDestVar(P),V)
|
||||
#define getDestType(M,P) destinationType((M),(P))
|
||||
#define getArg(P,I) (P)->argv[I]
|
||||
#define setArg(P,I,R) (P)->argv[I]= R
|
||||
#define getArgName(M,P,I) getVarName((M),(P)->argv[I])
|
||||
#define getArgType(M,P,I) getVarType((M),(P)->argv[I])
|
||||
#define getArgGDKType(M,P,I) getVarGDKType((M),(P)->argv[I])
|
||||
#define getGDKType(T) ( T <= TYPE_str ? T : (T == TYPE_any ? TYPE_void : findGDKtype(T)))
|
||||
|
||||
mal_export void addMalException(MalBlkPtr mb, str msg);
|
||||
mal_export void mal_instruction_reset(void);
|
||||
mal_export InstrPtr newInstruction(MalBlkPtr mb, const char *modnme, const char *fcnnme);
|
||||
mal_export InstrPtr newInstructionArgs(MalBlkPtr mb, const char *modnme, const char *fcnnme, int args);
|
||||
mal_export InstrPtr copyInstruction(InstrPtr p);
|
||||
mal_export InstrPtr copyInstructionArgs(InstrPtr p, int args);
|
||||
mal_export void clrInstruction(InstrPtr p);
|
||||
mal_export void freeInstruction(InstrPtr p);
|
||||
mal_export void clrFunction(InstrPtr p);
|
||||
mal_export Symbol newSymbol(const char *nme, int kind);
|
||||
mal_export void freeSymbol(Symbol s);
|
||||
mal_export void freeSymbolList(Symbol s);
|
||||
mal_export void printSignature(stream *fd, Symbol s, int flg);
|
||||
|
||||
mal_export MalBlkPtr newMalBlk(int elements);
|
||||
mal_export void resetMalBlk(MalBlkPtr mb);
|
||||
mal_export void resetMalTypes(MalBlkPtr mb, int stop);
|
||||
mal_export int newMalBlkStmt(MalBlkPtr mb, int elements);
|
||||
mal_export int resizeMalBlk(MalBlkPtr mb, int elements);
|
||||
mal_export void freeMalBlk(MalBlkPtr mb);
|
||||
mal_export MalBlkPtr copyMalBlk(MalBlkPtr mb);
|
||||
mal_export void addtoMalBlkHistory(MalBlkPtr mb);
|
||||
mal_export void removeMalBlkHistory(MalBlkPtr mb);
|
||||
mal_export MalBlkPtr getMalBlkHistory(MalBlkPtr mb, int idx);
|
||||
mal_export MalBlkPtr getMalBlkOptimized(MalBlkPtr mb, const char *name);
|
||||
mal_export void trimMalVariables(MalBlkPtr mb, MalStkPtr stk);
|
||||
mal_export void trimMalVariables_(MalBlkPtr mb, MalStkPtr glb);
|
||||
mal_export void moveInstruction(MalBlkPtr mb, int pc, int target);
|
||||
mal_export void removeInstruction(MalBlkPtr mb, InstrPtr p);
|
||||
mal_export void removeInstructionBlock(MalBlkPtr mb, int pc, int cnt);
|
||||
mal_export str operatorName(int i);
|
||||
|
||||
mal_export int findVariable(MalBlkPtr mb, const char *name);
|
||||
mal_export int findVariableLength(MalBlkPtr mb, const char *name, int len);
|
||||
mal_export malType getType(MalBlkPtr mb, const char *nme);
|
||||
mal_export str getArgDefault(MalBlkPtr mb, InstrPtr p, int idx);
|
||||
mal_export int newVariable(MalBlkPtr mb, const char *name, size_t len, malType type);
|
||||
mal_export int cloneVariable(MalBlkPtr dst, MalBlkPtr src, int varid);
|
||||
mal_export void setVariableType(MalBlkPtr mb, const int idx, malType type);
|
||||
mal_export int newTmpVariable(MalBlkPtr mb, malType type);
|
||||
mal_export int newTypeVariable(MalBlkPtr mb, malType type);
|
||||
mal_export void freeVariable(MalBlkPtr mb, int varid);
|
||||
mal_export void clearVariable(MalBlkPtr mb, int varid);
|
||||
mal_export int cpyConstant(MalBlkPtr mb, VarPtr vr);
|
||||
mal_export int defConstant(MalBlkPtr mb, int type, ValPtr cst);
|
||||
mal_export int fndConstant(MalBlkPtr mb, const ValRecord *cst, int depth);
|
||||
mal_export str convertConstant(malType type, ValPtr vr);
|
||||
|
||||
mal_export void pushInstruction(MalBlkPtr mb, InstrPtr p);
|
||||
mal_export InstrPtr pushArgument(MalBlkPtr mb, InstrPtr p, int varid);
|
||||
mal_export InstrPtr addArgument(MalBlkPtr mb, InstrPtr p, int varid);
|
||||
mal_export InstrPtr setArgument(MalBlkPtr mb, InstrPtr p, int idx, int varid);
|
||||
mal_export InstrPtr pushReturn(MalBlkPtr mb, InstrPtr p, int varid);
|
||||
mal_export InstrPtr pushArgumentId(MalBlkPtr mb, InstrPtr p, const char *name);
|
||||
mal_export void delArgument(InstrPtr p, int varid);
|
||||
mal_export void setArgType(MalBlkPtr mb, InstrPtr p, int i, int tpe);
|
||||
mal_export void setReturnArgument(InstrPtr p, int varid);
|
||||
mal_export malType destinationType(MalBlkPtr mb, InstrPtr p);
|
||||
mal_export void setPolymorphic(InstrPtr p, int tpe, int force);
|
||||
/* Utility macros to inspect an instruction */
|
||||
#define functionStart(X) ((X)->token == FUNCTIONsymbol || \
|
||||
(X)->token == COMMANDsymbol || \
|
||||
(X)->token == FACTORYsymbol )
|
||||
#define patternStart(X) ((X)->token == PATTERNsymbol)
|
||||
#define functionExit(X) ((X)->token == ENDsymbol)
|
||||
|
||||
#define blockStart(X) ((X)->barrier && (((X)->barrier == BARRIERsymbol || \
|
||||
(X)->barrier == CATCHsymbol )))
|
||||
#define blockExit(X) ((X)->barrier == EXITsymbol)
|
||||
#define blockReturn(X) ((X)->barrier == RETURNsymbol)
|
||||
#define blockCntrl(X) ( (X)->barrier== LEAVEsymbol || \
|
||||
(X)->barrier== REDOsymbol || (X)->barrier== RETURNsymbol )
|
||||
#define isLinearFlow(X) (!(blockStart(X) || blockExit(X) || \
|
||||
(X)->barrier== LEAVEsymbol || (X)->barrier== REDOsymbol ))
|
||||
|
||||
mal_export void strBeforeCall(ValPtr v, ValPtr bak);
|
||||
mal_export void strAfterCall(ValPtr v, ValPtr bak);
|
||||
mal_export void batBeforeCall(ValPtr v, ValPtr bak);
|
||||
mal_export void batAfterCall(ValPtr v, ValPtr bak);
|
||||
#endif /* _MAL_INSTR_H */
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _MAL_SCOPE_H_
|
||||
#define _MAL_SCOPE_H_
|
||||
|
||||
#include "mal.h"
|
||||
/* #define MAL_SCOPE_DEBUG */
|
||||
|
||||
#define MAXSCOPE 256
|
||||
|
||||
typedef struct SCOPEDEF {
|
||||
struct SCOPEDEF *link; /* module with same index value */
|
||||
const char *name; /* index in namespace */
|
||||
Symbol *space; /* type dispatcher table */
|
||||
int isAtomModule; /* atom module definition ? */
|
||||
str help; /* short description of module functionality*/
|
||||
} *Module, ModuleRecord;
|
||||
|
||||
mal_export Module userModule(void);
|
||||
mal_export Module globalModule(const char *nme);
|
||||
mal_export Module fixModule(const char *nme);
|
||||
mal_export Module getModule(const char *nme);
|
||||
mal_export void freeModule(Module cur);
|
||||
mal_export void insertSymbol(Module scope, Symbol prg);
|
||||
mal_export void deleteSymbol(Module scope, Symbol prg);
|
||||
mal_export Module findModule(Module scope, const char *name);
|
||||
mal_export Symbol findSymbol(Module usermodule, const char *mod, const char *fcn);
|
||||
mal_export Symbol findSymbolInModule(Module v, const char *fcn);
|
||||
mal_export void getModuleList(Module** out, int* length);
|
||||
mal_export void freeModuleList(Module* list);
|
||||
mal_export void dumpModules(stream *out);
|
||||
mal_export BAT *getModules(void);
|
||||
|
||||
#define getSymbolIndex(N) (int)(*(unsigned char*)(N))
|
||||
|
||||
#endif /* _MAL_SCOPE_H_ */
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _MAL_NAMESPACE_H
|
||||
#define _MAL_NAMESPACE_H
|
||||
|
||||
mal_export void initNamespace(void);
|
||||
mal_export const char *putName(const char *nme);
|
||||
mal_export const char *putNameLen(const char *nme, size_t len);
|
||||
mal_export const char *getName(const char *nme);
|
||||
mal_export const char *getNameLen(const char *nme, size_t len);
|
||||
mal_export void delName(const char *nme, size_t len);
|
||||
|
||||
#endif /* _MAL_NAMESPACE_H */
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _MAL_STACK_H_
|
||||
#define _MAL_STACK_H_
|
||||
#include "mal.h"
|
||||
|
||||
#define stackSize(CNT) (sizeof(ValRecord)*(CNT) + offsetof(MalStack, stk))
|
||||
|
||||
mal_export MalStkPtr newGlobalStack(int size);
|
||||
mal_export MalStkPtr reallocGlobalStack(MalStkPtr s, int cnt);
|
||||
mal_export void freeStack(MalStkPtr stk);
|
||||
|
||||
#define getStkRecord(S,P,I) &(S)->stk[(P)->argv[I]]
|
||||
#define getStkValue(S,P,I) ( getStkType(S,P,I)== TYPE_str? \
|
||||
getStkRecord(S,P,I)->val.sval :\
|
||||
getStkRecord(S,P,I)->val.pval )
|
||||
#define getStkType(S,P,I) (S)->stk[(P)->argv[I]].vtype
|
||||
#define setStkType(S,P,I,T) (S)->stk[(P)->argv[I]].vtype = T
|
||||
#endif /* _MAL_STACK_H_ */
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef MAL_TYPE_H
|
||||
#define MAL_TYPE_H
|
||||
#include "mal.h"
|
||||
|
||||
/* #define DEBUG_MAL_TYPE 1 */
|
||||
|
||||
#define TMPMARKER '_'
|
||||
#define REFMARKER 'X'
|
||||
#define REFMARKERC 'C'
|
||||
|
||||
#define newBatType(T) (1<<16 | (T & 0377) )
|
||||
#define getBatType(X) ((X) & 0377 )
|
||||
#define isaBatType(X) ((1<<16) & (X) && (X)!= TYPE_any)
|
||||
|
||||
#define isAnyExpression(X) ((X) >> 17)
|
||||
#define isPolymorphic(X) (isAnyExpression(X) || (X)== TYPE_any)
|
||||
|
||||
#define setTypeIndex(X,I) X |= ((I & 017)<<18);
|
||||
#define getTypeIndex(X) (((X)>>18) & 017)
|
||||
|
||||
#define isPolyType(X) (isAnyExpression(X) && getTypeIndex(X)>0)
|
||||
/*
|
||||
* The symbol/instruction kinds are introduced here instead of reusing the defines
|
||||
* derived from the parser to avoid a loop in the define-structure.
|
||||
*/
|
||||
|
||||
#define RAISEsymbol 21 /* flow of control modifiers */
|
||||
#define CATCHsymbol 22
|
||||
#define RETURNsymbol 23
|
||||
#define BARRIERsymbol 24
|
||||
#define REDOsymbol 25
|
||||
#define LEAVEsymbol 26
|
||||
#define YIELDsymbol 27
|
||||
#define EXITsymbol 29
|
||||
|
||||
#define ASSIGNsymbol 40 /* interpreter entry points */
|
||||
#define ENDsymbol 41
|
||||
#define NOOPsymbol 43 /* no operation required */
|
||||
|
||||
#define COMMANDsymbol 61 /* these tokens should be the last group !! */
|
||||
#define FUNCTIONsymbol 62 /* the designate the signature start */
|
||||
#define FACTORYsymbol 63 /* the co-routine infrastructure */
|
||||
#define PATTERNsymbol 64 /* the MAL self-reflection commands */
|
||||
|
||||
#define FCNcall 50 /* internal symbols */
|
||||
#define FACcall 51
|
||||
#define CMDcall 52
|
||||
#define THRDcall 53
|
||||
#define PATcall 54 /* pattern call */
|
||||
|
||||
#define REMsymbol 99 /* commentary to be retained */
|
||||
|
||||
mal_export str getTypeName(malType tpe);
|
||||
mal_export str getTypeIdentifier(malType tpe);
|
||||
mal_export int getAtomIndex(const char *nme, size_t len, int deftpe);
|
||||
#define idcmp(n, m) strcmp(n, m)
|
||||
mal_export int isIdentifier(str s);
|
||||
mal_export int findGDKtype(int type); /* used in src/mal/mal_interpreter.c */
|
||||
|
||||
#endif /* MAL_TYPE_H */
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2023 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _MAPI_QUERYTYPE_H_INCLUDED
|
||||
#define _MAPI_QUERYTYPE_H_INCLUDED 1
|
||||
|
||||
/* this definition is a straight copy from sql/include/sql_query.h */
|
||||
typedef enum {
|
||||
Q_PARSE = 0,
|
||||
Q_TABLE = 1,
|
||||
Q_UPDATE = 2,
|
||||
Q_SCHEMA = 3,
|
||||
Q_TRANS = 4,
|
||||
Q_PREPARE = 5,
|
||||
Q_BLOCK = 6
|
||||
} mapi_query_t;
|
||||
|
||||
#endif /* _MAPI_QUERYTYPE_H_INCLUDED */
|
@ -0,0 +1,495 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
/* This file provides interfaces to perform certain atomic operations
|
||||
* on variables. Atomic in this sense means that an operation
|
||||
* performed in one thread shows up in another thread either
|
||||
* completely or not at all.
|
||||
*
|
||||
* The following operations are defined:
|
||||
* ATOMIC_VAR_INIT -- initializer for the variable (not necessarily atomic!);
|
||||
* ATOMIC_INIT -- initialize the variable (not necessarily atomic!);
|
||||
* ATOMIC_DESTROY -- destroy the variable
|
||||
* ATOMIC_GET -- return the value of a variable;
|
||||
* ATOMIC_SET -- set the value of a variable;
|
||||
* ATOMIC_XCG -- set the value of a variable, return original value;
|
||||
* ATOMIC_CAS -- compare-and-set (see below)
|
||||
* ATOMIC_ADD -- add a value to a variable, return original value;
|
||||
* ATOMIC_SUB -- subtract a value from a variable, return original value;
|
||||
* ATOMIC_INC -- increment a variable's value, return new value;
|
||||
* ATOMIC_DEC -- decrement a variable's value, return new value;
|
||||
* These interfaces work on variables of type ATOMIC_TYPE (uint64_t).
|
||||
*
|
||||
* The compare-and-set operation is based on the C11 standard: if the
|
||||
* atomic variable equals the expected value, the atomic variable is
|
||||
* replaced by the desired value and true is returned. Otherwise, the
|
||||
* expected value is replaced by the current value of the atomic
|
||||
* variable and false is returned.
|
||||
*
|
||||
* Some of these are also available for pointers:
|
||||
* ATOMIC_PTR_INIT
|
||||
* ATOMIC_PTR_DESTROY
|
||||
* ATOMIC_PTR_GET
|
||||
* ATOMIC_PTR_SET
|
||||
* ATOMIC_PTR_XCG
|
||||
* ATOMIC_PTR_CAS
|
||||
* To define an atomic pointer, use ATOMIC_PTR_TYPE. This is a (void *)
|
||||
* pointer that is appropriately adapted for atomic use.
|
||||
*
|
||||
* In addition, the following operations are defined:
|
||||
* ATOMIC_TAS -- test-and-set: set variable to "true" and return old value
|
||||
* ATOMIC_CLEAR -- set variable to "false"
|
||||
* These two operations are only defined on variables of type
|
||||
* ATOMIC_FLAG, and the only values defined for such a variable are
|
||||
* "false" and "true". The variable can be statically initialized
|
||||
* to "false" using the ATOMIC_FLAG_INIT macro.
|
||||
*/
|
||||
|
||||
#ifndef _MATOMIC_H_
|
||||
#define _MATOMIC_H_
|
||||
|
||||
/* define this if you don't want to use atomic instructions */
|
||||
/* #define NO_ATOMIC_INSTRUCTIONS */
|
||||
|
||||
/* the atomic type we export is always a 64 bit unsigned integer */
|
||||
|
||||
/* ignore __STDC_NO_ATOMICS__ if compiling using Intel compiler on
|
||||
* Windows since otherwise we can't compile this at all in C99 mode */
|
||||
#if defined(HAVE_STDATOMIC_H) && (!defined(__STDC_NO_ATOMICS__) || (defined(__INTEL_COMPILER) && defined(_WINDOWS))) && !defined(NO_ATOMIC_INSTRUCTIONS)
|
||||
|
||||
#include <stdatomic.h>
|
||||
|
||||
#if SIZEOF_LONG_LONG == 8
|
||||
typedef volatile atomic_ullong ATOMIC_TYPE;
|
||||
typedef unsigned long long ATOMIC_BASE_TYPE;
|
||||
#elif SIZEOF_LONG == 8
|
||||
typedef volatile atomic_ulong ATOMIC_TYPE;
|
||||
typedef unsigned long ATOMIC_BASE_TYPE;
|
||||
#else
|
||||
#error "we need a 64 bit atomic type"
|
||||
#endif
|
||||
|
||||
#define ATOMIC_INIT(var, val) atomic_init(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_DESTROY(var) ((void) 0)
|
||||
#define ATOMIC_GET(var) ((ATOMIC_BASE_TYPE) atomic_load(var))
|
||||
#define ATOMIC_SET(var, val) atomic_store(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_XCG(var, val) atomic_exchange(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_CAS(var, exp, des) atomic_compare_exchange_strong(var, exp, (ATOMIC_BASE_TYPE) (des))
|
||||
#define ATOMIC_ADD(var, val) atomic_fetch_add(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_SUB(var, val) atomic_fetch_sub(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_INC(var) (atomic_fetch_add(var, 1) + 1)
|
||||
#define ATOMIC_DEC(var) (atomic_fetch_sub(var, 1) - 1)
|
||||
#define ATOMIC_OR(var, val) atomic_fetch_or(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_AND(var, val) atomic_fetch_and(var, (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
typedef volatile atomic_address ATOMIC_PTR_TYPE;
|
||||
#else
|
||||
typedef void *_Atomic volatile ATOMIC_PTR_TYPE;
|
||||
#endif
|
||||
#define ATOMIC_PTR_INIT(var, val) atomic_init(var, val)
|
||||
#define ATOMIC_PTR_DESTROY(var) ((void) 0)
|
||||
#define ATOMIC_PTR_VAR_INIT(val) ATOMIC_VAR_INIT(val)
|
||||
#define ATOMIC_PTR_GET(var) atomic_load(var)
|
||||
#define ATOMIC_PTR_SET(var, val) atomic_store(var, (void *) (val))
|
||||
#define ATOMIC_PTR_XCG(var, val) atomic_exchange(var, (void *) (val))
|
||||
#define ATOMIC_PTR_CAS(var, exp, des) atomic_compare_exchange_strong(var, exp, (void *) (des))
|
||||
|
||||
typedef volatile atomic_flag ATOMIC_FLAG;
|
||||
/* ATOMIC_FLAG_INIT is already defined by the include file */
|
||||
#define ATOMIC_CLEAR(var) atomic_flag_clear(var)
|
||||
#define ATOMIC_TAS(var) atomic_flag_test_and_set(var)
|
||||
|
||||
#elif defined(_MSC_VER) && !defined(NO_ATOMIC_INSTRUCTIONS)
|
||||
|
||||
typedef uint64_t ATOMIC_BASE_TYPE;
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
/* On Windows, with Visual Studio 2005, the compiler uses acquire
|
||||
* semantics for read operations on volatile variables and release
|
||||
* semantics for write operations on volatile variables.
|
||||
*
|
||||
* With Visual Studio 2003, volatile to volatile references are
|
||||
* ordered; the compiler will not re-order volatile variable access.
|
||||
* However, these operations could be re-ordered by the processor.
|
||||
*
|
||||
* See
|
||||
* https://docs.microsoft.com/en-us/windows/desktop/Sync/synchronization-and-multiprocessor-issues
|
||||
*
|
||||
* This does not go for the Intel compiler, so there we use
|
||||
* _InterlockedExchangeAdd to load the value of an atomic variable.
|
||||
* There might be a better way, but it's hard to find in the
|
||||
* documentation.
|
||||
*/
|
||||
|
||||
typedef __declspec(align(8)) volatile ATOMIC_BASE_TYPE ATOMIC_TYPE;
|
||||
|
||||
#define ATOMIC_VAR_INIT(val) (val)
|
||||
#define ATOMIC_INIT(var, val) (*(var) = (val))
|
||||
#define ATOMIC_DESTROY(var) ((void) 0)
|
||||
|
||||
#if SIZEOF_SIZE_T == 8
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
#define ATOMIC_GET(var) ((ATOMIC_BASE_TYPE) _InterlockedExchangeAdd64(var, 0))
|
||||
#else
|
||||
#define ATOMIC_GET(var) (*(var))
|
||||
/* should we use _InterlockedExchangeAdd64(var, 0) instead? */
|
||||
#endif
|
||||
#define ATOMIC_SET(var, val) _InterlockedExchange64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_XCG(var, val) _InterlockedExchange64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
static inline bool
|
||||
ATOMIC_CAS(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE *exp, ATOMIC_BASE_TYPE des)
|
||||
{
|
||||
ATOMIC_BASE_TYPE old;
|
||||
old = _InterlockedCompareExchange64(var, des, *exp);
|
||||
if (old == *exp)
|
||||
return true;
|
||||
*exp = old;
|
||||
return false;
|
||||
}
|
||||
#define ATOMIC_CAS(var, exp, des) ATOMIC_CAS(var, exp, (ATOMIC_BASE_TYPE) (des))
|
||||
#define ATOMIC_ADD(var, val) _InterlockedExchangeAdd64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_SUB(var, val) _InterlockedExchangeAdd64(var, -(val))
|
||||
#define ATOMIC_INC(var) _InterlockedIncrement64(var)
|
||||
#define ATOMIC_DEC(var) _InterlockedDecrement64(var)
|
||||
#define ATOMIC_OR(var, val) _InterlockedOr64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_AND(var, val) _InterlockedAnd64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
#else
|
||||
|
||||
#ifdef DECLSPEC_NOINITALL
|
||||
#define ATOMIC_GET(var) ((ATOMIC_BASE_TYPE) _InlineInterlockedExchangeAdd64(var, 0))
|
||||
#define ATOMIC_SET(var, val) _InlineInterlockedExchange64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_XCG(var, val) _InlineInterlockedExchange64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_ADD(var, val) _InlineInterlockedExchangeAdd64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_SUB(var, val) _InlineInterlockedExchangeAdd64(var, -(val))
|
||||
#define ATOMIC_INC(var) _InlineInterlockedIncrement64(var)
|
||||
#define ATOMIC_DEC(var) _InlineInterlockedDecrement64(var)
|
||||
#define ATOMIC_OR(var, val) _InlineInterlockedOr64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_AND(var, val) _InlineInterlockedAnd64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#else
|
||||
#define ATOMIC_GET(var) ((ATOMIC_BASE_TYPE) _InterlockedExchangeAdd64(var, 0))
|
||||
#define ATOMIC_SET(var, val) _InterlockedExchange64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_XCG(var, val) _InterlockedExchange64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_ADD(var, val) _InterlockedExchangeAdd64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_SUB(var, val) _InterlockedExchangeAdd64(var, -(val))
|
||||
#define ATOMIC_INC(var) _InterlockedIncrement64(var)
|
||||
#define ATOMIC_DEC(var) _InterlockedDecrement64(var)
|
||||
#define ATOMIC_OR(var, val) _InterlockedOr64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#define ATOMIC_AND(var, val) _InterlockedAnd64(var, (ATOMIC_BASE_TYPE) (val))
|
||||
#endif
|
||||
static inline bool
|
||||
ATOMIC_CAS(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE *exp, ATOMIC_BASE_TYPE des)
|
||||
{
|
||||
ATOMIC_BASE_TYPE old;
|
||||
old = _InterlockedCompareExchange64(var, des, *exp);
|
||||
if (old == *exp)
|
||||
return true;
|
||||
*exp = old;
|
||||
return false;
|
||||
}
|
||||
#define ATOMIC_CAS(var, exp, des) ATOMIC_CAS(var, exp, (ATOMIC_BASE_TYPE) (des))
|
||||
|
||||
#endif
|
||||
|
||||
typedef PVOID volatile ATOMIC_PTR_TYPE;
|
||||
#define ATOMIC_PTR_INIT(var, val) (*(var) = (val))
|
||||
#define ATOMIC_PTR_DESTROY(var) ((void) 0)
|
||||
#define ATOMIC_PTR_VAR_INIT(val) (val)
|
||||
#define ATOMIC_PTR_GET(var) (*(var))
|
||||
#define ATOMIC_PTR_SET(var, val) _InterlockedExchangePointer(var, (PVOID) (val))
|
||||
#define ATOMIC_PTR_XCG(var, val) _InterlockedExchangePointer(var, (PVOID) (val))
|
||||
#pragma intrinsic(_InterlockedCompareExchangePointer)
|
||||
static inline bool
|
||||
ATOMIC_PTR_CAS(ATOMIC_PTR_TYPE *var, void **exp, void *des)
|
||||
{
|
||||
void *old;
|
||||
old = _InterlockedCompareExchangePointer(var, des, *exp);
|
||||
if (old == *exp)
|
||||
return true;
|
||||
*exp = old;
|
||||
return false;
|
||||
}
|
||||
#define ATOMIC_PTR_CAS(var, exp, des) ATOMIC_PTR_CAS(var, exp, (void *) (des))
|
||||
|
||||
typedef volatile int ATOMIC_FLAG;
|
||||
#define ATOMIC_FLAG_INIT { 0 }
|
||||
#define ATOMIC_CLEAR(var) _InterlockedExchange(var, 0)
|
||||
#define ATOMIC_TAS(var) _InterlockedCompareExchange(var, 1, 0)
|
||||
#pragma intrinsic(_InterlockedCompareExchange)
|
||||
|
||||
#elif (defined(__GNUC__) || defined(__INTEL_COMPILER)) && defined(__ATOMIC_SEQ_CST) && !(defined(__sun__) && SIZEOF_SIZE_T == 8) && !defined(_MSC_VER) && !defined(NO_ATOMIC_INSTRUCTIONS)
|
||||
|
||||
/* the new way of doing this according to GCC (the old way, using
|
||||
* __sync_* primitives is not supported) */
|
||||
|
||||
typedef uint64_t ATOMIC_BASE_TYPE;
|
||||
typedef volatile ATOMIC_BASE_TYPE ATOMIC_TYPE;
|
||||
|
||||
#define ATOMIC_VAR_INIT(val) (val)
|
||||
#define ATOMIC_INIT(var, val) (*(var) = (val))
|
||||
#define ATOMIC_DESTROY(var) ((void) 0)
|
||||
|
||||
#define ATOMIC_GET(var) ((ATOMIC_BASE_TYPE) __atomic_load_n(var, __ATOMIC_SEQ_CST))
|
||||
#define ATOMIC_SET(var, val) __atomic_store_n(var, (ATOMIC_BASE_TYPE) (val), __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_XCG(var, val) __atomic_exchange_n(var, (ATOMIC_BASE_TYPE) (val), __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_CAS(var, exp, des) __atomic_compare_exchange_n(var, exp, (ATOMIC_BASE_TYPE) (des), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_ADD(var, val) __atomic_fetch_add(var, (ATOMIC_BASE_TYPE) (val), __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_SUB(var, val) __atomic_fetch_sub(var, (ATOMIC_BASE_TYPE) (val), __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_INC(var) __atomic_add_fetch(var, 1, __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_DEC(var) __atomic_sub_fetch(var, 1, __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_OR(var, val) __atomic_fetch_or(var, (ATOMIC_BASE_TYPE) (val), __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_AND(var, val) __atomic_fetch_and(var, (ATOMIC_BASE_TYPE) (val), __ATOMIC_SEQ_CST)
|
||||
|
||||
typedef void *volatile ATOMIC_PTR_TYPE;
|
||||
#define ATOMIC_PTR_INIT(var, val) (*(var) = (val))
|
||||
#define ATOMIC_PTR_VAR_INIT(val) (val)
|
||||
#define ATOMIC_PTR_DESTROY(var) ((void) 0)
|
||||
#define ATOMIC_PTR_GET(var) __atomic_load_n(var, __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_PTR_SET(var, val) __atomic_store_n(var, (val), __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_PTR_XCG(var, val) __atomic_exchange_n(var, (val), __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_PTR_CAS(var, exp, des) __atomic_compare_exchange_n(var, exp, (void *) (des), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
|
||||
typedef volatile char ATOMIC_FLAG;
|
||||
#define ATOMIC_FLAG_INIT { 0 }
|
||||
#define ATOMIC_CLEAR(var) __atomic_clear(var, __ATOMIC_SEQ_CST)
|
||||
#define ATOMIC_TAS(var) __atomic_test_and_set(var, __ATOMIC_SEQ_CST)
|
||||
|
||||
#else
|
||||
|
||||
/* emulate using mutexes */
|
||||
|
||||
typedef uint64_t ATOMIC_BASE_TYPE;
|
||||
|
||||
#include <pthread.h> /* required for pthread_mutex_t */
|
||||
|
||||
typedef struct {
|
||||
ATOMIC_BASE_TYPE val;
|
||||
pthread_mutex_t lck;
|
||||
} ATOMIC_TYPE;
|
||||
#define ATOMIC_VAR_INIT(v) { .val = (v), .lck = PTHREAD_MUTEX_INITIALIZER }
|
||||
|
||||
static inline void
|
||||
ATOMIC_INIT(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE val)
|
||||
{
|
||||
pthread_mutex_init(&var->lck, 0);
|
||||
var->val = val;
|
||||
}
|
||||
#define ATOMIC_INIT(var, val) ATOMIC_INIT((var), (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
#define ATOMIC_DESTROY(var) pthread_mutex_destroy(&(var)->lck)
|
||||
|
||||
static inline ATOMIC_BASE_TYPE
|
||||
ATOMIC_GET(ATOMIC_TYPE *var)
|
||||
{
|
||||
ATOMIC_BASE_TYPE old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ATOMIC_SET(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE val)
|
||||
{
|
||||
pthread_mutex_lock(&var->lck);
|
||||
var->val = val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
}
|
||||
#define ATOMIC_SET(var, val) ATOMIC_SET(var, (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
static inline ATOMIC_BASE_TYPE
|
||||
ATOMIC_XCG(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE val)
|
||||
{
|
||||
ATOMIC_BASE_TYPE old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->val;
|
||||
var->val = val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
#define ATOMIC_XCG(var, val) ATOMIC_XCG(var, (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
static inline bool
|
||||
ATOMIC_CAS(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE *exp, ATOMIC_BASE_TYPE des)
|
||||
{
|
||||
bool ret;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
if (var->val == *exp) {
|
||||
var->val = des;
|
||||
ret = true;
|
||||
} else {
|
||||
*exp = var->val;
|
||||
ret = false;
|
||||
}
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return ret;
|
||||
}
|
||||
#define ATOMIC_CAS(var, exp, des) ATOMIC_CAS(var, exp, (ATOMIC_BASE_TYPE) (des))
|
||||
|
||||
static inline ATOMIC_BASE_TYPE
|
||||
ATOMIC_ADD(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE val)
|
||||
{
|
||||
ATOMIC_BASE_TYPE old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->val;
|
||||
var->val += val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
#define ATOMIC_ADD(var, val) ATOMIC_ADD(var, (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
static inline ATOMIC_BASE_TYPE
|
||||
ATOMIC_SUB(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE val)
|
||||
{
|
||||
ATOMIC_BASE_TYPE old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->val;
|
||||
var->val -= val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
#define ATOMIC_SUB(var, val) ATOMIC_SUB(var, (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
static inline ATOMIC_BASE_TYPE
|
||||
ATOMIC_INC(ATOMIC_TYPE *var)
|
||||
{
|
||||
ATOMIC_BASE_TYPE new;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
new = var->val += 1;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return new;
|
||||
}
|
||||
|
||||
static inline ATOMIC_BASE_TYPE
|
||||
ATOMIC_DEC(ATOMIC_TYPE *var)
|
||||
{
|
||||
ATOMIC_BASE_TYPE new;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
new = var->val -= 1;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return new;
|
||||
}
|
||||
|
||||
static inline ATOMIC_BASE_TYPE
|
||||
ATOMIC_OR(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE val)
|
||||
{
|
||||
ATOMIC_BASE_TYPE old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->val;
|
||||
var->val |= val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
#define ATOMIC_OR(var, val) ATOMIC_OR(var, (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
static inline ATOMIC_BASE_TYPE
|
||||
ATOMIC_AND(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE val)
|
||||
{
|
||||
ATOMIC_BASE_TYPE old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->val;
|
||||
var->val &= val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
#define ATOMIC_AND(var, val) ATOMIC_AND(var, (ATOMIC_BASE_TYPE) (val))
|
||||
|
||||
typedef struct {
|
||||
void *val;
|
||||
pthread_mutex_t lck;
|
||||
} ATOMIC_PTR_TYPE;
|
||||
#define ATOMIC_PTR_VAR_INIT(v) { .val = (v), .lck = PTHREAD_MUTEX_INITIALIZER }
|
||||
|
||||
static inline void
|
||||
ATOMIC_PTR_INIT(ATOMIC_PTR_TYPE *var, void *val)
|
||||
{
|
||||
pthread_mutex_init(&var->lck, 0);
|
||||
var->val = val;
|
||||
}
|
||||
|
||||
#define ATOMIC_PTR_DESTROY(var) pthread_mutex_destroy(&(var)->lck)
|
||||
|
||||
static inline void *
|
||||
ATOMIC_PTR_GET(ATOMIC_PTR_TYPE *var)
|
||||
{
|
||||
void *old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ATOMIC_PTR_SET(ATOMIC_PTR_TYPE *var, void *val)
|
||||
{
|
||||
pthread_mutex_lock(&var->lck);
|
||||
var->val = val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
ATOMIC_PTR_XCG(ATOMIC_PTR_TYPE *var, void *val)
|
||||
{
|
||||
void *old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->val;
|
||||
var->val = val;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ATOMIC_PTR_CAS(ATOMIC_PTR_TYPE *var, void **exp, void *des)
|
||||
{
|
||||
bool ret;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
if (var->val == *exp) {
|
||||
var->val = des;
|
||||
ret = true;
|
||||
} else {
|
||||
*exp = var->val;
|
||||
ret = false;
|
||||
}
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return ret;
|
||||
}
|
||||
#define ATOMIC_PTR_CAS(var, exp, des) ATOMIC_PTR_CAS(var, exp, (void *) (des))
|
||||
|
||||
typedef struct {
|
||||
bool flg;
|
||||
pthread_mutex_t lck;
|
||||
} ATOMIC_FLAG;
|
||||
#define ATOMIC_FLAG_INIT { .flg = false, .lck = PTHREAD_MUTEX_INITIALIZER }
|
||||
|
||||
static inline bool
|
||||
ATOMIC_TAS(ATOMIC_FLAG *var)
|
||||
{
|
||||
bool old;
|
||||
pthread_mutex_lock(&var->lck);
|
||||
old = var->flg;
|
||||
var->flg = true;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ATOMIC_CLEAR(ATOMIC_FLAG *var)
|
||||
{
|
||||
pthread_mutex_lock(&var->lck);
|
||||
var->flg = false;
|
||||
pthread_mutex_unlock(&var->lck);
|
||||
}
|
||||
|
||||
#define USE_NATIVE_LOCKS 1 /* must use pthread locks */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _MATOMIC_H_ */
|
Binary file not shown.
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _MSTRING_H_
|
||||
#define _MSTRING_H_
|
||||
|
||||
#include <stdarg.h> /* va_list etc. */
|
||||
#include <string.h> /* strlen */
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4))
|
||||
/* not on CentOS 6 (GCC 4.4.7) */
|
||||
#define GCC_Pragma(pragma) _Pragma(pragma)
|
||||
#else
|
||||
#define GCC_Pragma(pragma)
|
||||
#endif
|
||||
|
||||
/* copy at most (n-1) bytes from src to dst and add a terminating NULL
|
||||
* byte; return length of src (i.e. can be more than what is copied) */
|
||||
static inline size_t
|
||||
strcpy_len(char *restrict dst, const char *restrict src, size_t n)
|
||||
{
|
||||
if (dst != NULL && n != 0) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if ((dst[i] = src[i]) == 0)
|
||||
return i;
|
||||
}
|
||||
/* for correctness, the decrement isn't needed (just assigning 0
|
||||
* to dst[n-1] would be sufficient), but to work around a too
|
||||
* strict GNU C compiler, we do need it */
|
||||
dst[--n] = 0;
|
||||
/* in some versions of GCC (at least gcc (Ubuntu 7.5.0-3ubuntu1~18.04)
|
||||
* 7.5.0), the error just can't be turned off when using
|
||||
* --enable-strict, so we just use the (more) expensive way of getting the
|
||||
* right answer (rescan the whole string) */
|
||||
#if !defined(__GNUC__) || __GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 5)
|
||||
/* This code is correct, but GCC gives a warning in certain
|
||||
* conditions, so we disable the warning temporarily.
|
||||
* The warning happens e.g. in
|
||||
* strcpy_len(buf, "fixed string", sizeof(buf))
|
||||
* where buf is larger than the string. In that case we never get here
|
||||
* since return is executed in the loop above, but the compiler
|
||||
* complains anyway about reading out-of-bounds.
|
||||
* For GCC we use _Pragma to disable the warning (and hence error).
|
||||
* Since other compilers may warn (and hence error out) on
|
||||
* unrecognized pragmas, we use some preprocessor trickery. */
|
||||
GCC_Pragma("GCC diagnostic push")
|
||||
GCC_Pragma("GCC diagnostic ignored \"-Warray-bounds\"")
|
||||
return n + strlen(src + n);
|
||||
GCC_Pragma("GCC diagnostic pop")
|
||||
#endif
|
||||
}
|
||||
return strlen(src);
|
||||
}
|
||||
|
||||
/* copy the NULL terminated list of src strings with a maximum of n
|
||||
* bytes to dst; return the combined length of the src strings */
|
||||
static inline size_t
|
||||
strconcat_len(char *restrict dst, size_t n, const char *restrict src, ...)
|
||||
{
|
||||
va_list ap;
|
||||
size_t i = 0;
|
||||
|
||||
va_start(ap, src);
|
||||
while (src) {
|
||||
size_t l;
|
||||
if (dst && i < n)
|
||||
l = strcpy_len(dst + i, src, n - i);
|
||||
else
|
||||
l = strlen(src);
|
||||
i += l;
|
||||
src = va_arg(ap, const char *);
|
||||
}
|
||||
va_end(ap);
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
/* __builtin_expect returns its first argument; it is expected to be
|
||||
* equal to the second argument */
|
||||
#define __builtin_expect(expr, expect) (expr)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* UTF-8 encoding is as follows:
|
||||
* U-00000000 - U-0000007F: 0xxxxxxx
|
||||
* U-00000080 - U-000007FF: 110zzzzx 10xxxxxx
|
||||
* U-00000800 - U-0000FFFF: 1110zzzz 10zxxxxx 10xxxxxx
|
||||
* U-00010000 - U-0010FFFF: 11110zzz 10zzxxxx 10xxxxxx 10xxxxxx
|
||||
*
|
||||
* To be correctly coded UTF-8, the sequence should be the shortest
|
||||
* possible encoding of the value being encoded. This means that at
|
||||
* least one of the z bits must be non-zero. Also note that the four
|
||||
* byte sequence can encode more than is allowed and that the values
|
||||
* U+D800..U+DFFF are not allowed to be encoded.
|
||||
*/
|
||||
static inline bool
|
||||
checkUTF8(const char *v)
|
||||
{
|
||||
/* It is unlikely that this functions returns false, because
|
||||
* it is likely that the string presented is a correctly coded
|
||||
* UTF-8 string. So we annotate the tests that are very
|
||||
* unlikely to succeed, i.e. the ones that lead to a return of
|
||||
* false, as being expected to return 0 using the
|
||||
* __builtin_expect function. */
|
||||
if (v != NULL) {
|
||||
if (v[0] != '\200' || v[1] != '\0') {
|
||||
/* check that string is correctly encoded UTF-8 */
|
||||
for (size_t i = 0; v[i]; i++) {
|
||||
/* we do not annotate all tests, only the ones
|
||||
* leading directly to an unlikely return
|
||||
* statement */
|
||||
if ((v[i] & 0x80) == 0) {
|
||||
;
|
||||
} else if ((v[i] & 0xE0) == 0xC0) {
|
||||
if (__builtin_expect(((v[i] & 0x1E) == 0), 0))
|
||||
return false;
|
||||
if (__builtin_expect(((v[++i] & 0xC0) != 0x80), 0))
|
||||
return false;
|
||||
} else if ((v[i] & 0xF0) == 0xE0) {
|
||||
if ((v[i++] & 0x0F) == 0) {
|
||||
if (__builtin_expect(((v[i] & 0xE0) != 0xA0), 0))
|
||||
return false;
|
||||
} else {
|
||||
if (__builtin_expect(((v[i] & 0xC0) != 0x80), 0))
|
||||
return false;
|
||||
}
|
||||
if (__builtin_expect(((v[++i] & 0xC0) != 0x80), 0))
|
||||
return false;
|
||||
} else if (__builtin_expect(((v[i] & 0xF8) == 0xF0), 1)) {
|
||||
if ((v[i++] & 0x07) == 0) {
|
||||
if (__builtin_expect(((v[i] & 0x30) == 0), 0))
|
||||
return false;
|
||||
}
|
||||
if (__builtin_expect(((v[i] & 0xC0) != 0x80), 0))
|
||||
return false;
|
||||
if (__builtin_expect(((v[++i] & 0xC0) != 0x80), 0))
|
||||
return false;
|
||||
if (__builtin_expect(((v[++i] & 0xC0) != 0x80), 0))
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
#undef __builtin_expect
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _SQL_ATOM_H_
|
||||
#define _SQL_ATOM_H_
|
||||
|
||||
#include "sql_mem.h"
|
||||
#include "sql_types.h"
|
||||
|
||||
#define atom_null(a) (((atom*)a)->isnull)
|
||||
|
||||
extern void atom_init( atom *a );
|
||||
extern atom *atom_bool( sql_allocator *sa, sql_subtype *tpe, bit t);
|
||||
#ifdef HAVE_HGE
|
||||
extern atom *atom_int( sql_allocator *sa, sql_subtype *tpe, hge val);
|
||||
#else
|
||||
extern atom *atom_int( sql_allocator *sa, sql_subtype *tpe, lng val);
|
||||
#endif
|
||||
extern atom *atom_float( sql_allocator *sa, sql_subtype *tpe, dbl val);
|
||||
extern atom *atom_string( sql_allocator *sa, sql_subtype *tpe, const char *val);
|
||||
extern atom *atom_general( sql_allocator *sa, sql_subtype *tpe, const char *val);
|
||||
#ifdef HAVE_HGE
|
||||
extern atom *atom_dec( sql_allocator *sa, sql_subtype *tpe, hge val);
|
||||
#else
|
||||
extern atom *atom_dec( sql_allocator *sa, sql_subtype *tpe, lng val);
|
||||
#endif
|
||||
extern atom *atom_ptr( sql_allocator *sa, sql_subtype *tpe, void *v);
|
||||
extern atom *atom_general_ptr( sql_allocator *sa, sql_subtype *tpe, void *v);
|
||||
|
||||
extern unsigned int atom_num_digits( atom *a );
|
||||
|
||||
/* cast atom a to type tp (success returns not NULL, fail returns NULL) */
|
||||
extern atom *atom_cast(sql_allocator *sa, atom *a, sql_subtype *tp);
|
||||
|
||||
extern char *atom2string(sql_allocator *sa, atom *a);
|
||||
extern char *atom2sql(sql_allocator *sa, atom *a, int timezone);
|
||||
extern sql_subtype *atom_type(atom *a);
|
||||
extern atom *atom_set_type(sql_allocator *sa, atom *a, sql_subtype *t);
|
||||
|
||||
#ifdef HAVE_HGE
|
||||
extern hge atom_get_int(atom *a);
|
||||
#else
|
||||
extern lng atom_get_int(atom *a);
|
||||
#endif
|
||||
|
||||
extern int atom_cmp(atom *a1, atom *a2);
|
||||
|
||||
extern atom *atom_neg(sql_allocator *sa, atom *a);
|
||||
extern atom *atom_add(sql_allocator *sa, atom *a1, atom *a2);
|
||||
extern atom *atom_sub(sql_allocator *sa, atom *a1, atom *a2);
|
||||
extern atom *atom_mul(sql_allocator *sa, atom *a1, atom *a2);
|
||||
extern atom *atom_inc(sql_allocator *sa, atom *a);
|
||||
extern int atom_is_true(atom *a);
|
||||
extern int atom_is_false(atom *a);
|
||||
extern int atom_is_zero(atom *a);
|
||||
|
||||
#ifdef HAVE_HGE
|
||||
#define MAX_SCALE 39
|
||||
extern const hge scales[MAX_SCALE];
|
||||
#else
|
||||
#define MAX_SCALE 19
|
||||
extern const lng scales[MAX_SCALE];
|
||||
#endif
|
||||
|
||||
extern atom *atom_zero_value(sql_allocator *sa, sql_subtype* tpe);
|
||||
extern atom *atom_max_value(sql_allocator *sa, sql_subtype *tpe);
|
||||
#endif /* _SQL_ATOM_H_ */
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _SQL_BACKEND_H_
|
||||
#define _SQL_BACKEND_H_
|
||||
|
||||
#include "sql_mem.h"
|
||||
#include "sql_catalog.h"
|
||||
#include "sql_relation.h"
|
||||
|
||||
typedef void (*freecode_fptr) (const char *mod, int clientid, const char *name);
|
||||
|
||||
typedef char *(*create_user_fptr) (ptr mvc, char *user, char *passwd, char enc, char *fullname, sqlid schema_id, char *schema_path, sqlid grantor_id);
|
||||
typedef int (*drop_user_fptr) (ptr mvc, char *user);
|
||||
typedef int (*find_user_fptr) (ptr mvc, char *user);
|
||||
typedef void (*create_privileges_fptr) (ptr mvc, sql_schema *s);
|
||||
typedef int (*schema_has_user_fptr) (ptr mvc, sql_schema *s);
|
||||
typedef int (*alter_user_fptr) (ptr mvc, str user, str passwd, char enc, sqlid schema_id, char *schema_path, str oldpasswd);
|
||||
typedef int (*rename_user_fptr) (ptr mvc, str olduser, str newuser);
|
||||
typedef void* (*schema_user_dependencies) (ptr mvc, int schema_id);
|
||||
typedef void (*create_function) (ptr mvc, str name, sql_rel *rel, sql_table *t);
|
||||
typedef int (*resolve_function) (ptr mvc, sql_func *f, const char *fimp, bit *side_effect);
|
||||
typedef int (*has_module_function) (ptr mvc, char *name);
|
||||
typedef void *(*create_sub_backend) (void *mvc, void *client);
|
||||
|
||||
/* backing struct for this interface */
|
||||
typedef struct _backend_functions {
|
||||
freecode_fptr fcode;
|
||||
create_user_fptr fcuser;
|
||||
drop_user_fptr fduser;
|
||||
find_user_fptr ffuser;
|
||||
create_privileges_fptr fcrpriv;
|
||||
schema_has_user_fptr fshuser;
|
||||
alter_user_fptr fauser;
|
||||
rename_user_fptr fruser;
|
||||
schema_user_dependencies fschuserdep;
|
||||
resolve_function fresolve_function;
|
||||
has_module_function fhas_module_function;
|
||||
create_sub_backend sub_backend;
|
||||
} backend_functions;
|
||||
|
||||
extern void backend_freecode(const char *mod, int clientid, const char *name);
|
||||
|
||||
extern char *backend_create_user(ptr mvc, char *user, char *passwd, char enc, char *fullname, sqlid defschemid, char *schema_path, sqlid grantor);
|
||||
extern int backend_drop_user(ptr mvc, char *user);
|
||||
extern int backend_find_user(ptr mp, char *user);
|
||||
extern void backend_create_privileges(ptr mvc, sql_schema *s);
|
||||
extern int backend_schema_has_user(ptr mvc, sql_schema *s);
|
||||
extern int backend_alter_user(ptr mvc, str user, str passwd, char enc, sqlid schema_id, char *schema_path, str oldpasswd);
|
||||
extern int backend_rename_user(ptr mvc, str olduser, str newuser);
|
||||
extern void* backend_schema_user_dependencies(ptr trans, sqlid schema_id);
|
||||
extern int backend_resolve_function(ptr trans, sql_func *f, const char *fimp, bit *side_effect);
|
||||
extern int backend_has_module(ptr M, char *name);
|
||||
|
||||
extern backend_functions be_funcs;
|
||||
|
||||
#endif /* _SQL_BACKEND_H_ */
|
@ -0,0 +1,877 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef SQL_CATALOG_H
|
||||
#define SQL_CATALOG_H
|
||||
|
||||
#include "sql_mem.h"
|
||||
#include "sql_list.h"
|
||||
#include "sql_hash.h"
|
||||
#include "mapi_querytype.h"
|
||||
#include "stream.h"
|
||||
#include "matomic.h"
|
||||
|
||||
#define sql_shared_module_name "sql"
|
||||
#define sql_private_module_name "user"
|
||||
|
||||
#define tr_none 1
|
||||
#define tr_readonly 2
|
||||
#define tr_writable 4
|
||||
#define tr_append 8
|
||||
#define tr_snapshot 16
|
||||
#define tr_serializable 32
|
||||
|
||||
#define ACT_NO_ACTION 0
|
||||
#define ACT_CASCADE 1
|
||||
#define ACT_RESTRICT 2
|
||||
#define ACT_SET_NULL 3
|
||||
#define ACT_SET_DEFAULT 4
|
||||
|
||||
#define DROP_RESTRICT 0
|
||||
#define DROP_CASCADE 1
|
||||
#define DROP_CASCADE_START 2
|
||||
|
||||
#define PRIV_SELECT 1
|
||||
#define PRIV_UPDATE 2
|
||||
#define PRIV_INSERT 4
|
||||
#define PRIV_DELETE 8
|
||||
#define PRIV_EXECUTE 16
|
||||
#define PRIV_GRANT 32
|
||||
#define PRIV_TRUNCATE 64
|
||||
/* global privs */
|
||||
#define PRIV_COPYFROMFILE 1
|
||||
#define PRIV_COPYINTOFILE 2
|
||||
|
||||
typedef enum sql_dependency {
|
||||
SCHEMA_DEPENDENCY = 1,
|
||||
TABLE_DEPENDENCY = 2,
|
||||
COLUMN_DEPENDENCY = 3,
|
||||
KEY_DEPENDENCY = 4,
|
||||
VIEW_DEPENDENCY = 5,
|
||||
USER_DEPENDENCY = 6,
|
||||
FUNC_DEPENDENCY = 7,
|
||||
TRIGGER_DEPENDENCY = 8,
|
||||
OWNER_DEPENDENCY = 9,
|
||||
INDEX_DEPENDENCY = 10,
|
||||
FKEY_DEPENDENCY = 11,
|
||||
SEQ_DEPENDENCY = 12,
|
||||
PROC_DEPENDENCY = 13,
|
||||
BEDROPPED_DEPENDENCY = 14, /*The object must be dropped when the dependent object is dropped independently of the DROP type.*/
|
||||
TYPE_DEPENDENCY = 15
|
||||
} sql_dependency;
|
||||
|
||||
#define NO_DEPENDENCY 0
|
||||
#define HAS_DEPENDENCY 1
|
||||
#define CICLE_DEPENDENCY 2
|
||||
#define DEPENDENCY_CHECK_ERROR 3
|
||||
#define DEPENDENCY_CHECK_OK 0
|
||||
|
||||
#define ROLE_PUBLIC 1
|
||||
#define ROLE_SYSADMIN 2
|
||||
#define USER_MONETDB 3
|
||||
|
||||
#define SCALE_NONE 0
|
||||
#define SCALE_FIX 1 /* many numerical functions require equal
|
||||
scales/precision for all their inputs */
|
||||
#define SCALE_NOFIX 2
|
||||
#define SCALE_MUL 3 /* multiplication gives the sum of scales */
|
||||
#define SCALE_DIV 4 /* div on the other hand reduces the scales */
|
||||
#define DIGITS_ADD 5 /* some types grow under functions (concat) */
|
||||
#define INOUT 6 /* output type equals input type */
|
||||
#define SCALE_EQ 7 /* user defined functions need equal scales */
|
||||
|
||||
#define RDONLY 0
|
||||
#define RD_INS 1
|
||||
#define RD_UPD_ID 2
|
||||
#define RD_UPD_VAL 3
|
||||
#define QUICK 4
|
||||
#define RD_EXT 5
|
||||
|
||||
/* the following list of macros are used by rel_rankop function */
|
||||
#define UNBOUNDED_PRECEDING_BOUND 0
|
||||
#define UNBOUNDED_FOLLOWING_BOUND 1
|
||||
#define CURRENT_ROW_BOUND 2
|
||||
|
||||
#define FRAME_ROWS 0 /* number of rows (preceding/following) */
|
||||
#define FRAME_RANGE 1 /* logical range (based on the ordering column).
|
||||
Example:
|
||||
RANGE BETWEEN INTERVAL '1' MONTH PRECEDING
|
||||
AND INTERVAL '1' MONTH FOLLOWING */
|
||||
#define FRAME_GROUPS 2
|
||||
#define FRAME_UNBOUNDED_TILL_CURRENT_ROW 3
|
||||
#define FRAME_CURRENT_ROW_TILL_UNBOUNDED 4
|
||||
#define FRAME_ALL 5
|
||||
#define FRAME_CURRENT_ROW 6
|
||||
|
||||
/* the following list of macros are used by SQLwindow_bound function */
|
||||
#define BOUND_FIRST_HALF_PRECEDING 0
|
||||
#define BOUND_FIRST_HALF_FOLLOWING 1
|
||||
#define BOUND_SECOND_HALF_PRECEDING 2
|
||||
#define BOUND_SECOND_HALF_FOLLOWING 3
|
||||
#define CURRENT_ROW_PRECEDING 4
|
||||
#define CURRENT_ROW_FOLLOWING 5
|
||||
|
||||
#define EXCLUDE_NONE 0 /* nothing excluded (also the default) */
|
||||
#define EXCLUDE_CURRENT_ROW 1 /* exclude the current row */
|
||||
#define EXCLUDE_GROUP 2 /* exclude group */
|
||||
#define EXCLUDE_TIES 3 /* exclude group but not the current row */
|
||||
|
||||
/* The following macros are used in properties field of sql_table */
|
||||
#define PARTITION_RANGE 1
|
||||
#define PARTITION_LIST 2
|
||||
#define PARTITION_COLUMN 4
|
||||
#define PARTITION_EXPRESSION 8
|
||||
|
||||
#define STORAGE_MAX_VALUE_LENGTH 2048
|
||||
|
||||
#define cur_user 1
|
||||
#define cur_role 2
|
||||
|
||||
#define sql_max(i1,i2) ((i1)<(i2))?(i2):(i1)
|
||||
|
||||
#define dt_schema "%dt%"
|
||||
#define isDeclaredSchema(s) (strcmp(s->base.name, dt_schema) == 0)
|
||||
|
||||
extern const char *TID;
|
||||
|
||||
typedef enum temp_t {
|
||||
SQL_PERSIST = 0,
|
||||
SQL_LOCAL_TEMP = 1,
|
||||
SQL_GLOBAL_TEMP = 2,
|
||||
SQL_DECLARED_TABLE = 3, /* variable inside a stored procedure */
|
||||
SQL_MERGE_TABLE = 4,
|
||||
/* SQL_STREAM = 5, stream tables are not used anymore */
|
||||
SQL_REMOTE = 6,
|
||||
SQL_REPLICA_TABLE = 7
|
||||
} temp_t;
|
||||
|
||||
typedef enum comp_type {
|
||||
cmp_gt = 0,
|
||||
cmp_gte = 1,
|
||||
cmp_lte = 2,
|
||||
cmp_lt = 3,
|
||||
cmp_equal = 4,
|
||||
cmp_notequal = 5,
|
||||
|
||||
cmp_filter = 6,
|
||||
cmp_or = 7,
|
||||
cmp_in = 8, /* in value list */
|
||||
cmp_notin = 9, /* not in value list */
|
||||
|
||||
mark_in = 10, /* mark joins */
|
||||
mark_notin = 11,
|
||||
|
||||
/* The followin cmp_* are only used within stmt (not sql_exp) */
|
||||
cmp_all = 12, /* special case for crossproducts */
|
||||
cmp_project = 13, /* special case for projection joins */
|
||||
cmp_joined = 14, /* special case already joined */
|
||||
cmp_left_project = 15 /* last step of outer join */
|
||||
} comp_type;
|
||||
|
||||
#define is_theta_exp(e) ((e) == cmp_gt || (e) == cmp_gte || (e) == cmp_lte ||\
|
||||
(e) == cmp_lt || (e) == cmp_equal || (e) == cmp_notequal)
|
||||
|
||||
#define is_complex_exp(et) ((et) == cmp_or || (et) == cmp_in || (et) == cmp_notin || (et) == cmp_filter)
|
||||
|
||||
#define is_equality_or_inequality_exp(et) ((et) == cmp_equal || (et) == cmp_notequal || (et) == cmp_in || \
|
||||
(et) == cmp_notin || (et) == mark_in || (et) == mark_notin)
|
||||
|
||||
typedef enum commit_action_t {
|
||||
CA_COMMIT, /* commit rows, only for persistent tables */
|
||||
CA_DELETE, /* delete rows */
|
||||
CA_PRESERVE, /* preserve rows */
|
||||
CA_DROP /* drop table */
|
||||
} ca_t;
|
||||
|
||||
typedef int sqlid;
|
||||
typedef void *sql_store;
|
||||
|
||||
typedef struct sql_base {
|
||||
unsigned int
|
||||
new:1,
|
||||
deleted:1,
|
||||
refcnt:30;
|
||||
sqlid id;
|
||||
char *name;
|
||||
} sql_base;
|
||||
|
||||
#define isNew(x) ((x)->base.new)
|
||||
|
||||
extern void base_init(sql_allocator *sa, sql_base * b, sqlid id, bool isnew, const char *name);
|
||||
|
||||
typedef struct changeset {
|
||||
sql_allocator *sa;
|
||||
fdestroy destroy;
|
||||
struct list *set;
|
||||
struct list *dset;
|
||||
node *nelm;
|
||||
} changeset;
|
||||
|
||||
typedef struct objlist {
|
||||
list *l;
|
||||
sql_hash *h;
|
||||
sql_store store;
|
||||
} objlist;
|
||||
|
||||
struct sql_trans;
|
||||
struct sql_change;
|
||||
struct objectset;
|
||||
struct versionhead;
|
||||
struct os_iter {
|
||||
struct objectset *os;
|
||||
struct sql_trans *tr;
|
||||
struct versionhead *n;
|
||||
struct sql_hash_e *e;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/* transaction changes */
|
||||
typedef int (*tc_valid_fptr) (struct sql_trans *tr, struct sql_change *c/*, ulng commit_ts, ulng oldest*/);
|
||||
typedef int (*tc_log_fptr) (struct sql_trans *tr, struct sql_change *c); /* write changes to the log */
|
||||
typedef int (*tc_commit_fptr) (struct sql_trans *tr, struct sql_change *c, ulng commit_ts, ulng oldest);/* commit/rollback changes */
|
||||
typedef int (*tc_cleanup_fptr) (sql_store store, struct sql_change *c, ulng oldest); /* garbage collection, ie cleanup structures when possible */
|
||||
typedef void (*destroy_fptr)(sql_store store, sql_base *b);
|
||||
typedef int (*validate_fptr)(struct sql_trans *tr, sql_base *b, int delete);
|
||||
|
||||
extern struct objectset *os_new(sql_allocator *sa, destroy_fptr destroy, bool temporary, bool unique, bool concurrent, sql_store store);
|
||||
extern struct objectset *os_dup(struct objectset *os);
|
||||
extern void os_destroy(struct objectset *os, sql_store store);
|
||||
extern int /*ok, error (name existed) and conflict (added before) */ os_add(struct objectset *os, struct sql_trans *tr, const char *name, sql_base *b);
|
||||
extern int os_del(struct objectset *os, struct sql_trans *tr, const char *name, sql_base *b);
|
||||
extern int os_size(struct objectset *os, struct sql_trans *tr);
|
||||
extern int os_empty(struct objectset *os, struct sql_trans *tr);
|
||||
extern int os_remove(struct objectset *os, struct sql_trans *tr, const char *name);
|
||||
extern sql_base *os_find_name(struct objectset *os, struct sql_trans *tr, const char *name);
|
||||
extern sql_base *os_find_id(struct objectset *os, struct sql_trans *tr, sqlid id);
|
||||
/* iterating (for example for location functinos) */
|
||||
extern void os_iterator(struct os_iter *oi, struct objectset *os, struct sql_trans *tr, const char *name /*optional*/);
|
||||
extern sql_base *oi_next(struct os_iter *oi);
|
||||
extern bool os_obj_intransaction(struct objectset *os, struct sql_trans *tr, sql_base *b);
|
||||
extern bool os_has_changes(struct objectset *os, struct sql_trans *tr);
|
||||
|
||||
extern objlist *ol_new(sql_allocator *sa, destroy_fptr destroy, sql_store store);
|
||||
extern void ol_destroy(objlist *ol, sql_store store);
|
||||
extern int ol_add(objlist *ol, sql_base *data);
|
||||
extern void ol_del(objlist *ol, sql_store store, node *data);
|
||||
extern node *ol_find_name(objlist *ol, const char *name);
|
||||
extern node *ol_find_id(objlist *ol, sqlid id);
|
||||
extern node *ol_rehash(objlist *ol, const char *oldname, node *n);
|
||||
#define ol_length(ol) (list_length(ol->l))
|
||||
#define ol_first_node(ol) (ol->l->h)
|
||||
#define ol_last_node(ol) (ol->l->t)
|
||||
#define ol_fetch(ol,nr) (list_fetch(ol->l, nr))
|
||||
|
||||
extern void cs_new(changeset * cs, sql_allocator *sa, fdestroy destroy);
|
||||
extern void cs_destroy(changeset * cs, void *data);
|
||||
extern void cs_add(changeset * cs, void *elm, bool isnew);
|
||||
extern void cs_del(changeset * cs, void *gdata, node *elm, bool isnew);
|
||||
extern int cs_size(changeset * cs);
|
||||
extern node *cs_find_id(changeset * cs, sqlid id);
|
||||
|
||||
typedef void *backend_code;
|
||||
typedef size_t backend_stack;
|
||||
|
||||
typedef struct sql_schema {
|
||||
sql_base base;
|
||||
sqlid auth_id;
|
||||
sqlid owner;
|
||||
bit system; /* system or user schema */
|
||||
// TODO? int type; /* persistent, session local, transaction local */
|
||||
|
||||
struct objectset *tables;
|
||||
struct objectset *types;
|
||||
struct objectset *funcs;
|
||||
struct objectset *seqs;
|
||||
struct objectset *keys; /* Names for keys, idxs, and triggers and parts are */
|
||||
struct objectset *idxs; /* global, but these objects are only */
|
||||
struct objectset *triggers; /* useful within a table */
|
||||
struct objectset *parts;
|
||||
|
||||
char *internal; /* optional internal module name */
|
||||
sql_store store;
|
||||
} sql_schema;
|
||||
|
||||
typedef struct sql_catalog {
|
||||
struct objectset *schemas;
|
||||
struct objectset *objects;
|
||||
} sql_catalog;
|
||||
|
||||
typedef struct sql_trans {
|
||||
char *name;
|
||||
|
||||
ulng ts; /* transaction start timestamp */
|
||||
ulng tid; /* transaction id */
|
||||
|
||||
sql_store store; /* keep link into the global store */
|
||||
MT_Lock lock; /* lock protecting concurrent writes to the changes list */
|
||||
list *changes; /* list of changes */
|
||||
|
||||
list *dropped; /* protection against recursive cascade action*/
|
||||
list *predicates; /* list of read predicates logged during update transactions */
|
||||
list *dependencies; /* list of dependencies created (list of sqlids from the objects) */
|
||||
list *depchanges; /* list of dependencies changed (it would be tested for conflicts at the end of the transaction) */
|
||||
|
||||
int logchanges; /* count number of changes to be applied to the wal */
|
||||
int active; /* is active transaction */
|
||||
int status; /* status of the last query */
|
||||
|
||||
sql_catalog *cat;
|
||||
sql_schema *tmp; /* each session has its own tmp schema */
|
||||
changeset localtmps;
|
||||
sql_allocator *sa; /* transaction allocator */
|
||||
|
||||
struct sql_trans *parent; /* multilevel transaction support */
|
||||
} sql_trans;
|
||||
|
||||
typedef enum sql_class {
|
||||
EC_ANY,
|
||||
EC_TABLE,
|
||||
EC_BIT,
|
||||
EC_CHAR,
|
||||
EC_STRING,
|
||||
EC_BLOB,
|
||||
EC_POS,
|
||||
EC_NUM,
|
||||
EC_MONTH,
|
||||
EC_SEC,
|
||||
EC_DEC,
|
||||
EC_FLT,
|
||||
EC_TIME,
|
||||
EC_TIME_TZ,
|
||||
EC_DATE,
|
||||
EC_TIMESTAMP,
|
||||
EC_TIMESTAMP_TZ,
|
||||
EC_GEOM,
|
||||
EC_EXTERNAL,
|
||||
EC_MAX /* evaluated to the max value, should be always kept at the bottom */
|
||||
} sql_class;
|
||||
|
||||
#define has_tz(e) (EC_TEMP_TZ(e))
|
||||
#define type_has_tz(t) has_tz((t)->type->eclass)
|
||||
#define EC_VARCHAR(e) ((e)==EC_CHAR||(e)==EC_STRING)
|
||||
#define EC_INTERVAL(e) ((e)==EC_MONTH||(e)==EC_SEC)
|
||||
#define EC_NUMBER(e) ((e)==EC_POS||(e)==EC_NUM||EC_INTERVAL(e)||(e)==EC_DEC||(e)==EC_FLT)
|
||||
#define EC_EXACTNUM(e) ((e)==EC_NUM||(e)==EC_DEC)
|
||||
#define EC_APPNUM(e) ((e)==EC_FLT)
|
||||
#define EC_COMPUTE(e) ((e)==EC_NUM||(e)==EC_FLT)
|
||||
#define EC_BOOLEAN(e) ((e)==EC_BIT||(e)==EC_NUM||(e)==EC_FLT)
|
||||
#define EC_TEMP_TZ(e) ((e)==EC_TIME_TZ||(e)==EC_TIMESTAMP_TZ)
|
||||
#define EC_TEMP(e) ((e)==EC_TIME||(e)==EC_DATE||(e)==EC_TIMESTAMP||EC_TEMP_TZ(e))
|
||||
#define EC_TEMP_FRAC(e) ((e)==EC_TIME||(e)==EC_TIMESTAMP||EC_TEMP_TZ(e))
|
||||
#define EC_TEMP_NOFRAC(e) ((e)==EC_TIME||(e)==EC_TIMESTAMP)
|
||||
#define EC_SCALE(e) ((e)==EC_DEC||EC_TEMP_FRAC(e)||(e)==EC_SEC)
|
||||
#define EC_BACKEND_FIXED(e) (EC_NUMBER(e)||(e)==EC_BIT||EC_TEMP(e))
|
||||
|
||||
typedef struct sql_type {
|
||||
sql_base base;
|
||||
|
||||
char *impl; /* backend correspondent type */
|
||||
unsigned int digits;
|
||||
unsigned int scale; /* indicates how scale is used in functions */
|
||||
int localtype; /* localtype, need for coersions */
|
||||
unsigned char radix;
|
||||
unsigned int bits;
|
||||
sql_class eclass; /* types are grouped into equivalence classes */
|
||||
sql_schema *s;
|
||||
} sql_type;
|
||||
|
||||
typedef struct sql_alias {
|
||||
char *name;
|
||||
char *alias;
|
||||
} sql_alias;
|
||||
|
||||
#define ARG_IN 1
|
||||
#define ARG_OUT 0
|
||||
|
||||
typedef struct sql_subtype {
|
||||
sql_type *type;
|
||||
unsigned int digits;
|
||||
unsigned int scale;
|
||||
} sql_subtype;
|
||||
|
||||
/* sql_func need type transform rules types are equal if underlying
|
||||
* types are equal + scale is equal if types do not mach we try type
|
||||
* conversions which means for simple 1 arg functions
|
||||
*/
|
||||
|
||||
typedef struct sql_arg {
|
||||
char *name;
|
||||
bte inout;
|
||||
sql_subtype type;
|
||||
} sql_arg;
|
||||
|
||||
typedef enum sql_ftype {
|
||||
F_FUNC = 1,
|
||||
F_PROC = 2,
|
||||
F_AGGR = 3,
|
||||
F_FILT = 4,
|
||||
F_UNION = 5,
|
||||
F_ANALYTIC = 6,
|
||||
F_LOADER = 7
|
||||
} sql_ftype;
|
||||
|
||||
#define IS_FUNC(f) ((f)->type == F_FUNC)
|
||||
#define IS_PROC(f) ((f)->type == F_PROC)
|
||||
#define IS_AGGR(f) ((f)->type == F_AGGR)
|
||||
#define IS_FILT(f) ((f)->type == F_FILT)
|
||||
#define IS_UNION(f) ((f)->type == F_UNION)
|
||||
#define IS_ANALYTIC(f) ((f)->type == F_ANALYTIC)
|
||||
#define IS_LOADER(f) ((f)->type == F_LOADER)
|
||||
|
||||
#define FUNC_TYPE_STR(type, F, fn) \
|
||||
switch (type) { \
|
||||
case F_FUNC: \
|
||||
F = "FUNCTION"; \
|
||||
fn = "function"; \
|
||||
break; \
|
||||
case F_PROC: \
|
||||
F = "PROCEDURE"; \
|
||||
fn = "procedure"; \
|
||||
break; \
|
||||
case F_AGGR: \
|
||||
F = "AGGREGATE"; \
|
||||
fn = "aggregate"; \
|
||||
break; \
|
||||
case F_FILT: \
|
||||
F = "FILTER FUNCTION"; \
|
||||
fn = "filter function"; \
|
||||
break; \
|
||||
case F_UNION: \
|
||||
F = "UNION FUNCTION"; \
|
||||
fn = "table returning function"; \
|
||||
break; \
|
||||
case F_ANALYTIC: \
|
||||
F = "WINDOW FUNCTION"; \
|
||||
fn = "window function"; \
|
||||
break; \
|
||||
case F_LOADER: \
|
||||
F = "LOADER FUNCTION"; \
|
||||
fn = "loader function"; \
|
||||
break; \
|
||||
default: \
|
||||
assert(0); \
|
||||
}
|
||||
|
||||
typedef enum sql_flang {
|
||||
FUNC_LANG_INT = 0, /* internal */
|
||||
FUNC_LANG_MAL = 1, /* create sql external mod.func */
|
||||
FUNC_LANG_SQL = 2, /* create ... sql function/procedure */
|
||||
FUNC_LANG_R = 3, /* create .. language R */
|
||||
FUNC_LANG_C = 4, /* create .. language C */
|
||||
FUNC_LANG_J = 5, /* create .. language JAVASCRIPT (not implemented) */
|
||||
/* this should probably be done in a better way */
|
||||
FUNC_LANG_PY = 6, /* create .. language PYTHON */
|
||||
FUNC_LANG_MAP_PY = 7, /* create .. language PYTHON_MAP */
|
||||
/* values 8 and 9 were for Python 2 */
|
||||
FUNC_LANG_PY3 = 10, /* create .. language PYTHON3 */
|
||||
FUNC_LANG_MAP_PY3 = 11, /* create .. language PYTHON3_MAP */
|
||||
FUNC_LANG_CPP = 12 /* create .. language CPP */
|
||||
} sql_flang;
|
||||
|
||||
#define LANG_EXT(l) ((l)>FUNC_LANG_SQL)
|
||||
#define UDF_LANG(l) ((l)>=FUNC_LANG_SQL)
|
||||
|
||||
typedef struct sql_func {
|
||||
sql_base base;
|
||||
|
||||
char *mod;
|
||||
char *imp;
|
||||
/*
|
||||
Backend implementation function after it gets instantiated.
|
||||
During instantiation 'imp' will be set, but look for the 'instantiated' value to check if it's done or not.
|
||||
Note that functions other than SQL and MAL, don't require instantiation and 'imp' is always set.
|
||||
*/
|
||||
sql_ftype type;
|
||||
list *ops; /* param list */
|
||||
list *res; /* list of results */
|
||||
sql_flang lang;
|
||||
char *query; /* sql code */
|
||||
bit semantics; /*When set to true, function incorporates some kind of null semantics.*/
|
||||
bit side_effect;
|
||||
bit varres; /* variable output result */
|
||||
bit vararg; /* variable input arguments */
|
||||
bit system; /* system function */
|
||||
bit instantiated; /* if the function is instantiated */
|
||||
int fix_scale;
|
||||
/*
|
||||
SCALE_NOFIX/SCALE_NONE => nothing
|
||||
SCALE_FIX => input scale fixing,
|
||||
SCALE_ADD => leave inputs as is and do add scales
|
||||
example numerical multiplication
|
||||
SCALE_SUB => first input scale, fix with second scale
|
||||
result scale is equal to first input
|
||||
example numerical division
|
||||
DIGITS_ADD => result digits, sum of args
|
||||
example string concat
|
||||
*/
|
||||
sql_schema *s;
|
||||
sql_allocator *sa;
|
||||
} sql_func;
|
||||
|
||||
typedef struct sql_subfunc {
|
||||
sql_func *func;
|
||||
list *res;
|
||||
list *coltypes; /* we need this for copy into from loader */
|
||||
list *colnames; /* we need this for copy into from loader */
|
||||
char *sname, *tname; /* we need this for create table from loader */
|
||||
} sql_subfunc;
|
||||
|
||||
typedef enum key_type {
|
||||
pkey,
|
||||
ukey,
|
||||
fkey
|
||||
} key_type;
|
||||
|
||||
typedef struct sql_kc {
|
||||
struct sql_column *c;
|
||||
int trunc; /* 0 not truncated, >0 colum is truncated */
|
||||
} sql_kc;
|
||||
|
||||
typedef enum idx_type {
|
||||
hash_idx,
|
||||
join_idx,
|
||||
oph_idx, /* order preserving hash */
|
||||
no_idx, /* no idx, ie no storage */
|
||||
imprints_idx,
|
||||
ordered_idx,
|
||||
new_idx_types
|
||||
} idx_type;
|
||||
|
||||
#define hash_index(t) ((t) == hash_idx || (t) == oph_idx)
|
||||
#define idx_has_column(t) (hash_index(t) || (t) == join_idx)
|
||||
#define oid_index(t) ((t) == join_idx)
|
||||
#define non_updatable_index(t) ((t) == ordered_idx || (t) == no_idx || !idx_has_column(t))
|
||||
|
||||
typedef struct sql_idx {
|
||||
sql_base base;
|
||||
idx_type type; /* unique */
|
||||
struct list *columns; /* list of sql_kc */
|
||||
struct sql_table *t;
|
||||
struct sql_key *key; /* key */
|
||||
ATOMIC_PTR_TYPE data;
|
||||
} sql_idx;
|
||||
|
||||
/* fkey consists of two of these */
|
||||
typedef struct sql_key { /* pkey, ukey, fkey */
|
||||
sql_base base;
|
||||
key_type type; /* pkey, ukey, fkey */
|
||||
sql_idx *idx; /* idx to accelerate key check */
|
||||
|
||||
struct list *columns; /* list of sql_kc */
|
||||
struct sql_table *t;
|
||||
int drop_action; /* only needed for alter drop key */
|
||||
} sql_key;
|
||||
|
||||
typedef struct sql_ukey { /* pkey, ukey */
|
||||
sql_key k;
|
||||
//list *keys;
|
||||
} sql_ukey;
|
||||
|
||||
typedef struct sql_fkey { /* fkey */
|
||||
sql_key k;
|
||||
/* 0=no action, 1=cascade, 2=restrict (default setting), 3=set null, 4=set default */
|
||||
int on_delete;
|
||||
int on_update;
|
||||
sqlid rkey;
|
||||
} sql_fkey;
|
||||
|
||||
typedef struct sql_trigger {
|
||||
sql_base base;
|
||||
sht time; /* before or after */
|
||||
sht orientation; /* row or statement */
|
||||
sht event; /* insert, delete, update, truncate */
|
||||
/* int action_order; TODO, order within the set of triggers */
|
||||
struct list *columns; /* update trigger on list of (sql_kc) columns */
|
||||
|
||||
struct sql_table *t;
|
||||
char *old_name; /* name referencing the old values */
|
||||
char *new_name; /* name referencing the new values */
|
||||
|
||||
char *condition; /* when search condition, ie query */
|
||||
char *statement; /* action, ie list of sql statements */
|
||||
} sql_trigger;
|
||||
|
||||
typedef struct sql_sequence {
|
||||
sql_base base;
|
||||
lng start;
|
||||
lng minvalue;
|
||||
lng maxvalue;
|
||||
lng increment;
|
||||
lng cacheinc;
|
||||
bit cycle;
|
||||
bit bedropped; /*Drop the SEQUENCE if you are dropping the column, e.g., SERIAL COLUMN".*/
|
||||
sql_schema *s;
|
||||
} sql_sequence;
|
||||
|
||||
typedef struct sql_column {
|
||||
sql_base base;
|
||||
sql_subtype type;
|
||||
int colnr;
|
||||
bit null;
|
||||
char *def;
|
||||
char unique; /* 0 NOT UNIQUE, 1 SUB_UNIQUE, 2 UNIQUE */
|
||||
int drop_action; /* only used for alter statements */
|
||||
char *storage_type;
|
||||
size_t dcount;
|
||||
void *min;
|
||||
void *max;
|
||||
|
||||
struct sql_table *t;
|
||||
ATOMIC_PTR_TYPE data;
|
||||
} sql_column;
|
||||
|
||||
typedef enum table_types {
|
||||
tt_table = 0, /* table */
|
||||
tt_view = 1, /* view */
|
||||
tt_merge_table = 3, /* multiple tables form one table */
|
||||
/* tt_stream = 4, stream tables are not used anymore */
|
||||
tt_remote = 5, /* stored on a remote server */
|
||||
tt_replica_table = 6 /* multiple replica of the same table */
|
||||
} table_types;
|
||||
|
||||
#define TABLE_TYPE_DESCRIPTION(tt, properties) \
|
||||
((tt) == tt_table)?"TABLE":((tt) == tt_view)?"VIEW":((tt) == tt_merge_table && !(properties))?"MERGE TABLE": \
|
||||
((tt) == tt_remote)?"REMOTE TABLE": \
|
||||
((tt) == tt_merge_table && ((properties) & PARTITION_LIST) == PARTITION_LIST)?"LIST PARTITION TABLE": \
|
||||
((tt) == tt_merge_table && ((properties) & PARTITION_RANGE) == PARTITION_RANGE)?"RANGE PARTITION TABLE":"REPLICA TABLE"
|
||||
|
||||
#define isTable(x) ((x)->type==tt_table)
|
||||
#define isView(x) ((x)->type==tt_view)
|
||||
#define isNonPartitionedTable(x) ((x)->type==tt_merge_table && !(x)->properties)
|
||||
#define isRangePartitionTable(x) ((x)->type==tt_merge_table && ((x)->properties & PARTITION_RANGE) == PARTITION_RANGE)
|
||||
#define isListPartitionTable(x) ((x)->type==tt_merge_table && ((x)->properties & PARTITION_LIST) == PARTITION_LIST)
|
||||
#define isPartitionedByColumnTable(x) ((x)->type==tt_merge_table && ((x)->properties & PARTITION_COLUMN) == PARTITION_COLUMN)
|
||||
#define isPartitionedByExpressionTable(x) ((x)->type==tt_merge_table && ((x)->properties & PARTITION_EXPRESSION) == PARTITION_EXPRESSION)
|
||||
#define isMergeTable(x) ((x)->type==tt_merge_table)
|
||||
#define isRemote(x) ((x)->type==tt_remote)
|
||||
#define isReplicaTable(x) ((x)->type==tt_replica_table)
|
||||
#define isKindOfTable(x) (isTable(x) || isMergeTable(x) || isRemote(x) || isReplicaTable(x))
|
||||
|
||||
#define TABLE_WRITABLE 0
|
||||
#define TABLE_READONLY 1
|
||||
#define TABLE_APPENDONLY 2
|
||||
|
||||
typedef struct sql_part_value {
|
||||
ptr value;
|
||||
size_t length;
|
||||
} sql_part_value;
|
||||
|
||||
typedef struct sql_part {
|
||||
sql_base base;
|
||||
struct sql_table *t; /* the merge table */
|
||||
sqlid member; /* the member of the merge table */
|
||||
bit with_nills; /* 0 no nills, 1 holds nills, NULL holds all values -> range FROM MINVALUE TO MAXVALUE WITH NULL */
|
||||
union {
|
||||
list *values; /* partition by values/list */
|
||||
struct sql_range { /* partition by range */
|
||||
ptr minvalue;
|
||||
ptr maxvalue;
|
||||
size_t minlength;
|
||||
size_t maxlength;
|
||||
} range;
|
||||
} part;
|
||||
} sql_part;
|
||||
|
||||
typedef struct sql_expression {
|
||||
sql_subtype type; /* the returning sql_subtype of the expression */
|
||||
char *exp; /* the expression itself */
|
||||
list *cols; /* list of colnr of the columns of the table used in the expression */
|
||||
} sql_expression;
|
||||
|
||||
typedef struct sql_table {
|
||||
sql_base base;
|
||||
sht type; /* table, view, etc */
|
||||
sht access; /* writable, readonly, appendonly */
|
||||
bit system; /* system or user table */
|
||||
bit bootstrap; /* system table created during bootstrap */
|
||||
bte properties; /* used for merge_tables */
|
||||
temp_t persistence; /* persistent, global or local temporary */
|
||||
ca_t commit_action; /* on commit action */
|
||||
char *query; /* views may require some query */
|
||||
int sz;
|
||||
|
||||
sql_ukey *pkey;
|
||||
objlist *columns;
|
||||
objlist *idxs;
|
||||
objlist *keys;
|
||||
objlist *triggers;
|
||||
list *members; /* member tables of merge/replica tables */
|
||||
int drop_action; /* only needed for alter drop table */
|
||||
|
||||
ATOMIC_PTR_TYPE data;
|
||||
struct sql_schema *s;
|
||||
|
||||
union {
|
||||
struct sql_column *pcol; /* If it is partitioned on a column */
|
||||
struct sql_expression *pexp; /* If it is partitioned by an expression */
|
||||
} part;
|
||||
} sql_table;
|
||||
|
||||
typedef struct res_col {
|
||||
char *tn;
|
||||
char *name;
|
||||
sql_subtype type;
|
||||
bat b;
|
||||
char mtype;
|
||||
bool cached;
|
||||
ptr *p;
|
||||
} res_col;
|
||||
|
||||
typedef struct res_table {
|
||||
int id;
|
||||
oid query_id;
|
||||
mapi_query_t query_type;
|
||||
int nr_cols;
|
||||
BUN nr_rows;
|
||||
BUN cur_row;
|
||||
int cur_col;
|
||||
const char *tsep;
|
||||
const char *rsep;
|
||||
const char *ssep;
|
||||
const char *ns;
|
||||
res_col *cols;
|
||||
bat order;
|
||||
struct res_table *next;
|
||||
} res_table;
|
||||
|
||||
typedef struct sql_session {
|
||||
sql_allocator *sa;
|
||||
sql_trans *tr; /* active transaction */
|
||||
|
||||
char *schema_name; /* transaction's schema name */
|
||||
sql_schema *schema;
|
||||
|
||||
char ac_on_commit; /* if 1, auto_commit should be enabled on
|
||||
commit, rollback, etc. */
|
||||
char auto_commit;
|
||||
int level; /* TRANSACTION isolation level */
|
||||
int status; /* status, ok/error */
|
||||
backend_stack stk;
|
||||
} sql_session;
|
||||
|
||||
#define sql_base_loop(l, n) for (n=l->h; n; n=n->next)
|
||||
|
||||
extern int base_key(sql_base *b);
|
||||
extern node *list_find_name(list *l, const char *name);
|
||||
extern node *list_find_id(list *l, sqlid id);
|
||||
extern node *list_find_base_id(list *l, sqlid id);
|
||||
|
||||
extern sql_key *find_sql_key(sql_table *t, const char *kname);
|
||||
extern sql_key *sql_trans_find_key(sql_trans *tr, sqlid id);
|
||||
|
||||
extern sql_idx *find_sql_idx(sql_table *t, const char *kname);
|
||||
extern sql_idx *sql_trans_find_idx(sql_trans *tr, sqlid id);
|
||||
|
||||
extern sql_column *find_sql_column(sql_table *t, const char *cname);
|
||||
|
||||
extern sql_table *find_sql_table(sql_trans *tr, sql_schema *s, const char *tname);
|
||||
extern sql_table *find_sql_table_id(sql_trans *tr, sql_schema *s, sqlid id);
|
||||
extern sql_table *sql_trans_find_table(sql_trans *tr, sqlid id);
|
||||
|
||||
extern sql_sequence *find_sql_sequence(sql_trans *tr, sql_schema *s, const char *sname);
|
||||
|
||||
extern sql_schema *find_sql_schema(sql_trans *t, const char *sname);
|
||||
extern sql_schema *find_sql_schema_id(sql_trans *t, sqlid id);
|
||||
|
||||
extern sql_type *find_sql_type(sql_trans *tr, sql_schema * s, const char *tname);
|
||||
extern sql_type *sql_trans_bind_type(sql_trans *tr, sql_schema *s, const char *name);
|
||||
extern sql_type *sql_trans_find_type(sql_trans *tr, sql_schema *s /*optional */, sqlid id);
|
||||
extern sql_func *sql_trans_find_func(sql_trans *tr, sqlid id);
|
||||
extern sql_trigger *sql_trans_find_trigger(sql_trans *tr, sqlid id);
|
||||
|
||||
extern void find_partition_type(sql_subtype *tpe, sql_table *mt);
|
||||
extern void *sql_values_list_element_validate_and_insert(void *v1, void *v2, void *tpe, int* res);
|
||||
extern void *sql_range_part_validate_and_insert(void *v1, void *v2, void *tpe);
|
||||
extern void *sql_values_part_validate_and_insert(void *v1, void *v2, void *tpe);
|
||||
|
||||
typedef struct {
|
||||
BAT *b;
|
||||
char* name;
|
||||
void* def;
|
||||
} sql_emit_col;
|
||||
|
||||
extern int nested_mergetable(sql_trans *tr, sql_table *t, const char *sname, const char *tname);
|
||||
extern bool is_column_unique(sql_column *c);
|
||||
sql_export sql_part *partition_find_part(sql_trans *tr, sql_table *pt, sql_part *pp);
|
||||
extern node *members_find_child_id(list *l, sqlid id);
|
||||
|
||||
#define outside_str 1
|
||||
#define inside_str 2
|
||||
|
||||
#define extracting_schema 1
|
||||
#define extracting_sequence 2
|
||||
|
||||
static inline void
|
||||
extract_schema_and_sequence_name(sql_allocator *sa, char *default_value, char **schema, char **sequence)
|
||||
{
|
||||
int status = outside_str, identifier = extracting_schema;
|
||||
char next_identifier[1024]; /* needs one extra character for null terminator */
|
||||
size_t bp = 0;
|
||||
|
||||
for (size_t i = 0; default_value[i]; i++) {
|
||||
char next = default_value[i];
|
||||
|
||||
if (next == '"') {
|
||||
if (status == inside_str && default_value[i + 1] == '"') {
|
||||
next_identifier[bp++] = '"';
|
||||
i++; /* has to advance two positions */
|
||||
} else if (status == inside_str) {
|
||||
next_identifier[bp++] = '\0';
|
||||
if (identifier == extracting_schema) {
|
||||
*schema = SA_STRDUP(sa, next_identifier);
|
||||
identifier = extracting_sequence;
|
||||
} else if (identifier == extracting_sequence) {
|
||||
*sequence = SA_STRDUP(sa, next_identifier);
|
||||
break; /* done extracting */
|
||||
}
|
||||
bp = 0;
|
||||
status = outside_str;
|
||||
} else {
|
||||
assert(status == outside_str);
|
||||
status = inside_str;
|
||||
}
|
||||
} else if (next == '.') {
|
||||
if (status == outside_str && default_value[i + 1] == '"') {
|
||||
status = inside_str;
|
||||
i++; /* has to advance two positions */
|
||||
} else {
|
||||
assert(status == inside_str);
|
||||
next_identifier[bp++] = '.'; /* used inside an identifier name */
|
||||
}
|
||||
} else if (status == inside_str) {
|
||||
next_identifier[bp++] = next;
|
||||
} else {
|
||||
assert(status == outside_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern void arg_destroy(sql_store store, sql_arg *a);
|
||||
extern void part_value_destroy(sql_store store, sql_part_value *pv);
|
||||
|
||||
typedef struct atom {
|
||||
int isnull;
|
||||
sql_subtype tpe;
|
||||
ValRecord data;
|
||||
} atom;
|
||||
|
||||
/* duplicate atom */
|
||||
extern ValPtr SA_VALcopy(sql_allocator *sa, ValPtr d, const ValRecord *s);
|
||||
extern atom *atom_copy(sql_allocator *sa, atom *a);
|
||||
|
||||
typedef struct pl {
|
||||
sql_column *c;
|
||||
unsigned int cmp;
|
||||
atom *r; /* if r is NULL then a full match is required */
|
||||
atom *f; /* make it match range expressions */
|
||||
uint8_t
|
||||
anti:1,
|
||||
semantics:1;
|
||||
} pl;
|
||||
|
||||
#endif /* SQL_CATALOG_H */
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef SQL_HASH_H
|
||||
#define SQL_HASH_H
|
||||
|
||||
/* sql_hash implementation
|
||||
* used to optimize search in expression and statement lists
|
||||
*/
|
||||
|
||||
#include "sql_mem.h"
|
||||
|
||||
#define HASH_MIN_SIZE 4
|
||||
|
||||
typedef int (*fkeyvalue) (void *data);
|
||||
|
||||
typedef struct sql_hash_e {
|
||||
int key;
|
||||
void *value;
|
||||
struct sql_hash_e *chain;
|
||||
} sql_hash_e;
|
||||
|
||||
typedef struct sql_hash {
|
||||
sql_allocator *sa;
|
||||
int size; /* power of 2 */
|
||||
sql_hash_e **buckets;
|
||||
fkeyvalue key;
|
||||
int entries;
|
||||
} sql_hash;
|
||||
|
||||
extern sql_hash *hash_new(sql_allocator *sa, int size, fkeyvalue key);
|
||||
extern int hash_entries(sql_hash *h);
|
||||
extern int hash_empty(sql_hash *h);
|
||||
extern void hash_del(sql_hash *ht, int key, void *value);
|
||||
extern void hash_clear(sql_hash *h);
|
||||
extern void hash_destroy(sql_hash *h);
|
||||
|
||||
static inline sql_hash_e*
|
||||
hash_add(sql_hash *h, int key, void *value)
|
||||
{
|
||||
sql_hash_e *e = (h->sa)?SA_NEW(h->sa, sql_hash_e):MNEW(sql_hash_e);
|
||||
|
||||
if (e == NULL)
|
||||
return NULL;
|
||||
e->chain = h->buckets[key&(h->size-1)];
|
||||
h->buckets[key&(h->size-1)] = e;
|
||||
e->key = key;
|
||||
e->value = value;
|
||||
h->entries++;
|
||||
return e;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
hash_key(const char *restrict k)
|
||||
{
|
||||
unsigned int h = 37; /* prime number */
|
||||
while (*k) {
|
||||
h = (h * 54059) ^ (k[0] * 76963); /* prime numbers */
|
||||
k++;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
#endif /* SQL_HASH_H */
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef SQL_KEYWORD_H
|
||||
#define SQL_KEYWORD_H
|
||||
|
||||
/* we need to define these here as the parser header file is generated to late.
|
||||
* The numbers get remapped in the scanner.
|
||||
*/
|
||||
#define KW_ALIAS 4000
|
||||
#define KW_TYPE 4001
|
||||
|
||||
typedef struct keyword {
|
||||
char *keyword;
|
||||
int len;
|
||||
int token;
|
||||
struct keyword *next;
|
||||
} keyword;
|
||||
|
||||
extern int keywords_insert(char *k, int token);
|
||||
extern keyword *find_keyword(char *text);
|
||||
extern int keyword_exists(char *text);
|
||||
|
||||
extern void keyword_init(void);
|
||||
extern void keyword_exit(void);
|
||||
|
||||
#endif /* SQL_KEYWORD_H */
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#include "sql_mem.h"
|
||||
#include "sql_hash.h"
|
||||
|
||||
#define SA_LIST(sa, destroy) ((sa)?sa_list(sa):list_create(destroy))
|
||||
|
||||
typedef struct node {
|
||||
struct node *next;
|
||||
void *data;
|
||||
} node;
|
||||
|
||||
typedef void (*fdestroy) (void *gdata, void *ndata); /* gdata is passed to the list_destroy2 function */
|
||||
|
||||
typedef struct list {
|
||||
sql_allocator *sa;
|
||||
sql_hash *ht;
|
||||
MT_Lock ht_lock; /* latch protecting ht */
|
||||
fdestroy destroy;
|
||||
node *h;
|
||||
node *t;
|
||||
int cnt;
|
||||
int expected_cnt;
|
||||
} list;
|
||||
|
||||
typedef int (*traverse_func) (void *clientdata, int seqnr, void *data);
|
||||
typedef int (*prop_check_func) (void *data);
|
||||
|
||||
extern list *list_create(fdestroy destroy);
|
||||
sql_export list *sa_list(sql_allocator *sa);
|
||||
extern list *list_new(sql_allocator *sa, fdestroy destroy);
|
||||
|
||||
extern list *sa_list_append( sql_allocator *sa, list *l, void *data);
|
||||
|
||||
extern void list_destroy(list *l);
|
||||
extern void list_destroy2(list *l, void *data);
|
||||
sql_export int list_length(list *l);
|
||||
extern int list_empty(list *l);
|
||||
|
||||
sql_export list *list_append(list *l, void *data);
|
||||
extern list *list_append_before(list *l, node *n, void *data);
|
||||
extern list *list_prepend(list *l, void *data);
|
||||
|
||||
extern node *list_remove_node(list *l, void *gdata, node *n);
|
||||
extern void list_remove_data(list *l, void *gdata, void *data);
|
||||
extern void list_remove_list(list *l, void *gdata, list *data);
|
||||
extern void list_move_data(list *l, list *d, void *data);
|
||||
|
||||
|
||||
extern int list_traverse(list *l, traverse_func f, void *clientdata);
|
||||
|
||||
extern int list_check_prop_all(list *l, prop_check_func f);
|
||||
|
||||
/* the compare function gets one element from the list and a key from the
|
||||
* as input from the find function
|
||||
* Returns 0 if data and key are equal
|
||||
* */
|
||||
typedef int (*fcmp) (void *data, void *key);
|
||||
typedef void *(*fcmpvalidate) (void *v1, void *v2, void *extra, int *cmp);
|
||||
typedef void *(*fvalidate) (void *v1, void *v2, void *extra);
|
||||
typedef int (*fcmp2) (void *data, void *v1, void *v2);
|
||||
typedef void *(*fdup) (void *data);
|
||||
typedef void *(*freduce) (void *v1, void *v2);
|
||||
typedef void *(*freduce2) (sql_allocator *sa, void *v1, void *v2);
|
||||
typedef void *(*fmap) (void *data, void *clientdata);
|
||||
|
||||
extern void *list_transverse_with_validate(list *l, void *data, void *extra, fvalidate cmp);
|
||||
extern void *list_append_with_validate(list *l, void *data, void *extra, fvalidate cmp);
|
||||
extern void *list_append_sorted(list *l, void *data, void *extra, fcmpvalidate cmp);
|
||||
extern node *list_find(list *l, void *key, fcmp cmp);
|
||||
extern int list_position(list *l, void *val);
|
||||
sql_export void *list_fetch(list *l, int pos);
|
||||
extern list *list_select(list *l, void *key, fcmp cmp, fdup dup);
|
||||
extern list *list_order(list *l, fcmp cmp, fdup dup);
|
||||
extern list *list_distinct(list *l, fcmp cmp, fdup dup);
|
||||
extern void *list_reduce(list *l, freduce red, fdup dup);
|
||||
extern void *list_reduce2(list *l, freduce2 red, sql_allocator *sa);
|
||||
extern list *list_map(list *l, void *data, fmap f);
|
||||
extern int list_cmp(list *l1, list *l2, fcmp cmp);
|
||||
/* cmp the lists in link order */
|
||||
extern int list_match(list *l1, list *l2, fcmp cmp);
|
||||
/* match the lists (in any order) */
|
||||
extern list *list_sort(list *l, fkeyvalue key, fdup dup);
|
||||
/* The sort function sorts the list using the key function, which
|
||||
* translates the list item values into integer keyvalues. */
|
||||
/* sometimes more complex functions are needed to compute a key, then
|
||||
* we can pass the keys via an array, to keysort */
|
||||
extern list *list_keysort(list *l, int *key, fdup dup);
|
||||
|
||||
extern list *list_dup(list *l, fdup dup);
|
||||
extern list *list_merge(list *l, list *data, fdup dup);
|
||||
extern list *list_merge_destroy(list *l, list *data, fdup dup);
|
||||
|
||||
extern list *list_flaten(list *l);
|
||||
|
||||
extern void list_hash_delete(list *l, void *data, fcmp cmp);
|
||||
extern void* list_hash_add(list *l, void *data, fcmp cmp);
|
||||
extern void list_hash_clear(list *l);
|
||||
|
||||
#endif /* LIST_H */
|
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _SQL_MEM_H_
|
||||
#define _SQL_MEM_H_
|
||||
|
||||
#include "gdk.h"
|
||||
#include "exception_buffer.h"
|
||||
|
||||
#define SQL_OK 1
|
||||
#define SQL_ERR 0
|
||||
#define SQL_CONFLICT 2
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef LIBSQL
|
||||
#define sql_export extern __declspec(dllexport)
|
||||
#else
|
||||
#define sql_export extern __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define sql_export extern
|
||||
#endif
|
||||
|
||||
#define MNEW( type ) (type*)GDKmalloc(sizeof(type) )
|
||||
#define ZNEW( type ) (type*)GDKzalloc(sizeof(type) )
|
||||
#define NEW_ARRAY( type, size ) (type*)GDKmalloc((size)*sizeof(type))
|
||||
#define ZNEW_ARRAY( type, size ) (type*)GDKzalloc((size)*sizeof(type))
|
||||
#define RENEW_ARRAY( type,ptr,size) (type*)GDKrealloc((void*)ptr,(size)*sizeof(type))
|
||||
|
||||
#define _DELETE( ptr ) do { GDKfree(ptr); ptr = NULL; } while (0)
|
||||
#define _STRDUP( ptr ) GDKstrdup((char*)ptr)
|
||||
|
||||
extern void c_delete( const void *p );
|
||||
|
||||
typedef struct sql_ref {
|
||||
int refcnt;
|
||||
} sql_ref;
|
||||
|
||||
extern sql_ref *sql_ref_init(sql_ref *r);
|
||||
extern int sql_ref_inc(sql_ref *r);
|
||||
extern int sql_ref_dec(sql_ref *r);
|
||||
|
||||
typedef struct sql_allocator {
|
||||
struct sql_allocator *pa;
|
||||
size_t size;
|
||||
size_t nr;
|
||||
char **blks;
|
||||
size_t used; /* memory used in last block */
|
||||
size_t usedmem; /* used memory */
|
||||
void *freelist; /* list of freed blocks */
|
||||
exception_buffer eb;
|
||||
} sql_allocator;
|
||||
|
||||
sql_export sql_allocator *sa_create( sql_allocator *pa );
|
||||
sql_export sql_allocator *sa_reset( sql_allocator *sa );
|
||||
extern void *sa_alloc( sql_allocator *sa, size_t sz );
|
||||
sql_export void *sa_zalloc( sql_allocator *sa, size_t sz );
|
||||
extern void *sa_realloc( sql_allocator *sa, void *ptr, size_t sz, size_t osz );
|
||||
extern void sa_destroy( sql_allocator *sa );
|
||||
extern char *sa_strndup( sql_allocator *sa, const char *s, size_t l);
|
||||
sql_export char *sa_strdup( sql_allocator *sa, const char *s);
|
||||
extern char *sa_strconcat( sql_allocator *sa, const char *s1, const char *s2);
|
||||
extern size_t sa_size( sql_allocator *sa );
|
||||
|
||||
#define SA_NEW( sa, type ) (sa?((type*)sa_alloc( sa, sizeof(type))):MNEW(type))
|
||||
#define SA_ZNEW( sa, type ) (sa?((type*)sa_zalloc( sa, sizeof(type))):ZNEW(type))
|
||||
#define SA_NEW_ARRAY( sa, type, size ) (sa?(type*)sa_alloc( sa, ((size)*sizeof(type))):NEW_ARRAY(type,size))
|
||||
#define SA_ZNEW_ARRAY( sa, type, size ) (type*)sa_zalloc( sa, ((size)*sizeof(type)))
|
||||
#define SA_RENEW_ARRAY( sa, type, ptr, sz, osz ) (sa?(type*)sa_realloc( sa, ptr, ((sz)*sizeof(type)), ((osz)*sizeof(type))):RENEW_ARRAY(type,ptr,sz))
|
||||
#define SA_STRDUP( sa, s) (sa?sa_strdup(sa, s):_STRDUP(s))
|
||||
|
||||
#define _strlen(s) (int)strlen(s)
|
||||
|
||||
#if !defined(NDEBUG) && !defined(__COVERITY__) && defined(__GNUC__)
|
||||
#define sa_alloc(sa, sz) \
|
||||
({ \
|
||||
sql_allocator *_sa = (sa); \
|
||||
size_t _sz = (sz); \
|
||||
void *_res = sa_alloc(_sa, _sz); \
|
||||
TRC_DEBUG(ALLOC, \
|
||||
"sa_alloc(%p,%zu) -> %p\n", \
|
||||
_sa, _sz, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define sa_zalloc(sa, sz) \
|
||||
({ \
|
||||
sql_allocator *_sa = (sa); \
|
||||
size_t _sz = (sz); \
|
||||
void *_res = sa_zalloc(_sa, _sz); \
|
||||
TRC_DEBUG(ALLOC, \
|
||||
"sa_zalloc(%p,%zu) -> %p\n", \
|
||||
_sa, _sz, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define sa_realloc(sa, ptr, sz, osz) \
|
||||
({ \
|
||||
sql_allocator *_sa = (sa); \
|
||||
void *_ptr = (ptr); \
|
||||
size_t _sz = (sz); \
|
||||
size_t _osz = (osz); \
|
||||
void *_res = sa_realloc(_sa, _ptr, _sz, _osz); \
|
||||
TRC_DEBUG(ALLOC, \
|
||||
"sa_realloc(%p,%p,%zu,%zu) -> %p\n", \
|
||||
_sa, _ptr, _sz, _osz, _res); \
|
||||
_res; \
|
||||
})
|
||||
#define sa_strdup(sa, s) \
|
||||
({ \
|
||||
sql_allocator *_sa = (sa); \
|
||||
const char *_s = (s); \
|
||||
char *_res = sa_strdup(_sa, _s); \
|
||||
TRC_DEBUG(ALLOC, \
|
||||
"sa_strdup(%p,len=%zu) -> %p\n", \
|
||||
_sa, strlen(_s), _res); \
|
||||
_res; \
|
||||
})
|
||||
#define sa_strndup(sa, s, l) \
|
||||
({ \
|
||||
sql_allocator *_sa = (sa); \
|
||||
const char *_s = (s); \
|
||||
size_t _l = (l); \
|
||||
char *_res = sa_strndup(_sa, _s, _l); \
|
||||
TRC_DEBUG(ALLOC, \
|
||||
"sa_strndup(%p,len=%zu) -> %p\n", \
|
||||
_sa, _l, _res); \
|
||||
_res; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#endif /*_SQL_MEM_H_*/
|
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
/* multi version catalog */
|
||||
#ifndef _SQL_MVC_H
|
||||
#define _SQL_MVC_H
|
||||
|
||||
#include "sql_mem.h"
|
||||
#include "gdk.h"
|
||||
#include "sql_scan.h"
|
||||
#include "sql_list.h"
|
||||
#include "sql_types.h"
|
||||
#include "sql_backend.h"
|
||||
#include "sql_catalog.h"
|
||||
#include "sql_relation.h"
|
||||
#include "sql_storage.h"
|
||||
#include "sql_keyword.h"
|
||||
#include "mapi_querytype.h"
|
||||
#include "sql_atom.h"
|
||||
#include "sql_tokens.h"
|
||||
#include "sql_symbol.h"
|
||||
|
||||
#define ERRSIZE 8192
|
||||
#define ERR_AMBIGUOUS 050000
|
||||
#define ERR_GROUPBY 060000
|
||||
#define ERR_NOTFOUND 070000
|
||||
|
||||
/* value vs predicate (boolean) */
|
||||
#define type_value 0
|
||||
#define type_relation 1
|
||||
|
||||
/* cardinality expected by enclosing operator */
|
||||
#define card_none -1 /* psm call doesn't return anything */
|
||||
#define card_value 0
|
||||
#define card_row 1 /* needed for subqueries on single value tables (select (select 1))*/
|
||||
#define card_column 2
|
||||
#define card_set 3 /* some operators require only a set (IN/EXISTS) */
|
||||
#define card_exists 4
|
||||
/* to be removed ie are in type (aka dimention) */
|
||||
#define card_relation 5
|
||||
#define card_loader 6
|
||||
|
||||
#define CARD_VALUE(card) (card == card_value || card == card_row || card == card_column || card == card_set || card == card_exists)
|
||||
|
||||
/* allowed to reduce (in the where and having parts we can reduce) */
|
||||
|
||||
/* different query execution modes (emode) */
|
||||
#define m_normal 0
|
||||
#define m_deallocate 1
|
||||
#define m_prepare 2
|
||||
#define m_plan 3
|
||||
|
||||
/* special modes for function/procedure and view instantiation and
|
||||
dependency generation */
|
||||
#define m_instantiate 5
|
||||
#define m_deps 6
|
||||
|
||||
/* different query execution modifiers (emod) */
|
||||
#define mod_none 0
|
||||
#define mod_debug 1
|
||||
#define mod_trace 2
|
||||
#define mod_explain 4
|
||||
#define mod_exec 8
|
||||
|
||||
typedef struct sql_groupby_expression {
|
||||
symbol *sdef;
|
||||
tokens token;
|
||||
sql_exp *exp;
|
||||
} sql_groupby_expression;
|
||||
|
||||
typedef struct sql_window_definition {
|
||||
char *name;
|
||||
dlist *wdef;
|
||||
bool visited; /* used for window definitions lookup */
|
||||
} sql_window_definition;
|
||||
|
||||
typedef struct sql_local_table { /* declared tables during session */
|
||||
sql_table *table;
|
||||
} sql_local_table;
|
||||
|
||||
typedef struct sql_rel_view { /* CTEs */
|
||||
char *name;
|
||||
sql_rel *rel_view;
|
||||
} sql_rel_view;
|
||||
|
||||
typedef struct sql_var { /* Declared variables and parameters */
|
||||
char *sname; /* Global variables have a schema */
|
||||
char *name;
|
||||
atom var;
|
||||
} sql_var;
|
||||
|
||||
typedef struct sql_frame {
|
||||
char *name; /* frame name */
|
||||
list *group_expressions;
|
||||
list *windows;
|
||||
list *tables;
|
||||
list *rel_views;
|
||||
list *vars;
|
||||
int frame_number;
|
||||
} sql_frame;
|
||||
|
||||
typedef struct mvc {
|
||||
char errstr[ERRSIZE];
|
||||
|
||||
sql_allocator *sa, *ta, *pa;
|
||||
|
||||
struct scanner scanner;
|
||||
|
||||
list *params;
|
||||
sqlid objid; /* when replacing an existing view, it can't be seen */
|
||||
sql_func *forward; /* forward definitions for recursive functions */
|
||||
list *global_vars; /* SQL declared variables on the global scope */
|
||||
sql_frame **frames; /* stack of frames with variables */
|
||||
int topframes;
|
||||
int sizeframes;
|
||||
int frame;
|
||||
struct symbol *sym;
|
||||
|
||||
int8_t use_views:1,
|
||||
schema_path_has_sys:1, /* speed up object search */
|
||||
schema_path_has_tmp:1;
|
||||
struct qc *qc;
|
||||
int clientid; /* id of the owner */
|
||||
|
||||
/* session variables */
|
||||
sqlid user_id;
|
||||
sqlid role_id;
|
||||
int timezone; /* milliseconds west of UTC */
|
||||
int reply_size; /* reply size */
|
||||
int debug;
|
||||
|
||||
char emode; /* execution mode */
|
||||
char emod; /* execution modifier */
|
||||
|
||||
sql_session *session;
|
||||
sql_store store;
|
||||
|
||||
/* per query context */
|
||||
mapi_query_t type; /* query type */
|
||||
|
||||
/* during query needed flags */
|
||||
unsigned int label; /* numbers for relational projection labels */
|
||||
list *cascade_action; /* protection against recursive cascade actions */
|
||||
list *schema_path; /* schema search path for object lookup */
|
||||
uintptr_t sp;
|
||||
} mvc;
|
||||
|
||||
extern sql_table *mvc_init_create_view(mvc *sql, sql_schema *s, const char *name, const char *query);
|
||||
|
||||
/* should return structure */
|
||||
extern sql_store mvc_init(int debug, store_type store, int ro, int su);
|
||||
extern void mvc_exit(sql_store store);
|
||||
|
||||
extern void mvc_logmanager(sql_store store);
|
||||
|
||||
extern mvc *mvc_create(sql_store *store, sql_allocator *pa, int clientid, int debug, bstream *rs, stream *ws);
|
||||
extern int mvc_reset(mvc *m, bstream *rs, stream *ws, int debug);
|
||||
extern void mvc_destroy(mvc *c);
|
||||
|
||||
extern int mvc_status(mvc *c);
|
||||
extern int mvc_error_retry(mvc *c); // error code on errors else 0, errors AMBIGUOUS and GROUPBY will also output 0
|
||||
extern int mvc_type(mvc *c);
|
||||
extern int mvc_debug_on(mvc *m, int flag);
|
||||
extern void mvc_cancel_session(mvc *m);
|
||||
|
||||
/* since Savepoints and transactions are related the
|
||||
* commit function includes the savepoint creation.
|
||||
* Rollbacks can be either full or until a given savepoint.
|
||||
* The special mvc_release can be used to release savepoints.
|
||||
*/
|
||||
#define has_snapshots(tr) ((tr) && (tr)->parent && (tr)->parent->parent)
|
||||
|
||||
extern int mvc_trans(mvc *c);
|
||||
sql_export str mvc_commit(mvc *c, int chain, const char *name, bool enabling_auto_commit);
|
||||
sql_export str mvc_rollback(mvc *c, int chain, const char *name, bool disabling_auto_commit);
|
||||
extern str mvc_release(mvc *c, const char *name);
|
||||
|
||||
extern sql_type *mvc_bind_type(mvc *sql, const char *name);
|
||||
extern sql_type *schema_bind_type(mvc *sql, sql_schema * s, const char *name);
|
||||
|
||||
sql_export sql_schema *mvc_bind_schema(mvc *c, const char *sname);
|
||||
sql_export sql_table *mvc_bind_table(mvc *c, sql_schema *s, const char *tname);
|
||||
extern sql_column *mvc_bind_column(mvc *c, sql_table *t, const char *cname);
|
||||
extern sql_column *mvc_first_column(mvc *c, sql_table *t);
|
||||
extern sql_idx *mvc_bind_idx(mvc *c, sql_schema *s, const char *iname);
|
||||
extern sql_key *mvc_bind_key(mvc *c, sql_schema *s, const char *kname);
|
||||
extern sql_key *mvc_bind_ukey(sql_table *t, list *cols);
|
||||
extern sql_trigger *mvc_bind_trigger(mvc *c, sql_schema *s, const char *tname);
|
||||
|
||||
extern int mvc_create_type(mvc *sql, sql_schema *s, const char *sqlname, unsigned int digits, unsigned int scale, int radix, const char *impl);
|
||||
extern int mvc_drop_type(mvc *sql, sql_schema *s, sql_type *t, int drop_action);
|
||||
|
||||
extern int mvc_create_func(sql_func **f, mvc *m, sql_allocator *sa, sql_schema *s, const char *name, list *args, list *res, sql_ftype type, sql_flang lang,
|
||||
const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect);
|
||||
extern int mvc_drop_func(mvc *c, sql_schema *s, sql_func * func, int drop_action);
|
||||
extern int mvc_drop_all_func(mvc *c, sql_schema *s, list *list_func, int drop_action);
|
||||
|
||||
extern int mvc_drop_schema(mvc *c, sql_schema *s, int drop_action);
|
||||
extern int mvc_create_schema(mvc *m, const char *name, sqlid auth_id, sqlid owner);
|
||||
extern BUN mvc_clear_table(mvc *m, sql_table *t);
|
||||
extern str mvc_drop_table(mvc *c, sql_schema *s, sql_table * t, int drop_action);
|
||||
extern int mvc_create_table(sql_table **t, mvc *m, sql_schema *s, const char *name, int tt, bit system, int persistence, int commit_action, int sz, bit properties);
|
||||
extern int mvc_create_view(sql_table **t, mvc *m, sql_schema *s, const char *name, int persistence, const char *sql, bit system);
|
||||
extern int mvc_create_remote(sql_table **t, mvc *m, sql_schema *s, const char *name, int persistence, const char *loc);
|
||||
|
||||
extern int mvc_drop_column(mvc *c, sql_table *t, sql_column *col, int drop_action);
|
||||
sql_export int mvc_create_column(sql_column **col, mvc *m, sql_table *t, const char *name, sql_subtype *tpe);
|
||||
extern int mvc_create_column_(sql_column **col, mvc *m, sql_table *t, const char *name, const char *type, unsigned int digits);
|
||||
extern int mvc_null(mvc *c, sql_column *col, int flag);
|
||||
extern int mvc_default(mvc *c, sql_column *col, char *val);
|
||||
extern int mvc_drop_default(mvc *c, sql_column *col);
|
||||
extern int mvc_storage(mvc *c, sql_column *col, char *storage);
|
||||
extern int mvc_access(mvc *m, sql_table *t, sht access);
|
||||
extern int mvc_is_sorted(mvc *c, sql_column *col);
|
||||
extern int mvc_is_unique(mvc *m, sql_column *col);
|
||||
extern int mvc_is_duplicate_eliminated(mvc *c, sql_column *col);
|
||||
|
||||
extern int mvc_create_ukey(sql_key **kres, mvc *m, sql_table *t, const char *name, key_type kt);
|
||||
extern int mvc_create_fkey(sql_fkey **kres, mvc *m, sql_table *t, const char *name, key_type kt, sql_key *rkey, int on_delete, int on_update);
|
||||
extern int mvc_create_kc(mvc *m, sql_key *k, sql_column *c);
|
||||
extern int mvc_create_fkc(mvc *m, sql_fkey *fk, sql_column *c);
|
||||
extern int mvc_create_key_done(mvc *m, sql_key *k);
|
||||
|
||||
extern int mvc_drop_key(mvc *c, sql_schema *s, sql_key *key, int drop_action);
|
||||
|
||||
extern int mvc_create_idx(sql_idx **i, mvc *m, sql_table *t, const char *name, idx_type it);
|
||||
extern int mvc_create_ic(mvc *m, sql_idx * i, sql_column *c);
|
||||
extern int mvc_create_idx_done(mvc *m, sql_idx *i);
|
||||
extern int mvc_drop_idx(mvc *c, sql_schema *s, sql_idx * i);
|
||||
|
||||
extern int mvc_create_trigger(sql_trigger **tri, mvc *m, sql_table *t, const char *name, sht time, sht orientation, sht event, const char *old_name, const char *new_name, const char *condition, const char *statement);
|
||||
extern int mvc_drop_trigger(mvc *m, sql_schema *s, sql_trigger * tri);
|
||||
|
||||
/*dependency control*/
|
||||
extern int mvc_create_dependency(mvc *m, sql_base *b, sqlid depend_id, sql_dependency depend_type);
|
||||
extern int mvc_create_dependencies(mvc *m, list *blist, sqlid depend_id, sql_dependency dep_type);
|
||||
extern int mvc_check_dependency(mvc *m, sqlid id, sql_dependency type, list *ignore_ids);
|
||||
|
||||
/* variable management */
|
||||
extern int init_global_variables(mvc *sql);
|
||||
extern sql_var *find_global_var(mvc *sql, sql_schema *s, const char *name);
|
||||
extern sql_var *push_global_var(mvc *sql, const char *sname, const char *name, sql_subtype *type);
|
||||
extern int remove_global_var(mvc *sql, sql_schema *s, const char *name);
|
||||
|
||||
extern sql_var* frame_push_var(mvc *sql, const char *name, sql_subtype *type);
|
||||
extern sql_local_table* frame_push_table(mvc *sql, sql_table *t);
|
||||
extern sql_rel_view* stack_push_rel_view(mvc *sql, const char *name, sql_rel *var);
|
||||
extern sql_window_definition* frame_push_window_def(mvc *sql, const char *name, dlist *wdef);
|
||||
extern dlist* frame_get_window_def(mvc *sql, const char *name, int *pos);
|
||||
extern sql_groupby_expression* frame_push_groupby_expression(mvc *sql, symbol *def, sql_exp *exp);
|
||||
extern sql_exp* frame_get_groupby_expression(mvc *sql, symbol *def);
|
||||
extern void stack_update_rel_view(mvc *sql, const char *name, sql_rel *view);
|
||||
|
||||
extern bool frame_check_var_visited(mvc *sql, int i);
|
||||
extern void frame_set_var_visited(mvc *sql, int i);
|
||||
extern void frame_clear_visited_flag(mvc *sql);
|
||||
|
||||
extern sql_frame *stack_push_frame(mvc *sql, const char *name);
|
||||
extern void stack_pop_frame(mvc *sql);
|
||||
extern void clear_frame(mvc *sql, sql_frame *frame);
|
||||
extern void stack_pop_until(mvc *sql, int frame);
|
||||
|
||||
/* find variable in the stack */
|
||||
extern sql_var *stack_find_var_frame(mvc *sql, const char *name, int *level);
|
||||
extern sql_var *stack_find_var_at_level(mvc *sql, const char *name, int level);
|
||||
extern sql_table *stack_find_table(mvc *sql, const char *name);
|
||||
extern sql_table *frame_find_table(mvc *sq, const char *name);
|
||||
extern sql_rel *stack_find_rel_view(mvc *sql, const char *name);
|
||||
extern int stack_find_rel_view_projection_columns(mvc *sql, const char *name, sql_rel **res);
|
||||
|
||||
/* find variable in the current frame */
|
||||
extern int frame_find_var(mvc *sql, const char *name);
|
||||
extern sql_rel *frame_find_rel_view(mvc *sql, const char *name);
|
||||
|
||||
extern int stack_has_frame(mvc *sql, const char *name);
|
||||
extern int stack_nr_of_declared_tables(mvc *sql);
|
||||
|
||||
extern atom *sqlvar_set(sql_var *var, ValRecord *v);
|
||||
extern str sqlvar_get_string(sql_var *var);
|
||||
extern str sqlvar_set_string(sql_var *var, const char *v);
|
||||
#ifdef HAVE_HGE
|
||||
extern hge val_get_number(ValRecord *val);
|
||||
extern void sqlvar_set_number(sql_var *var, hge v);
|
||||
#else
|
||||
extern lng val_get_number(ValRecord *val);
|
||||
extern void sqlvar_set_number(sql_var *var, lng v);
|
||||
#endif
|
||||
|
||||
#define get_string_global_var(m, val) (sqlvar_get_string(find_global_var(m, mvc_bind_schema(m, "sys"), val)))
|
||||
|
||||
extern int mvc_copy_column(mvc *m, sql_table *t, sql_column *c, sql_column **cres);
|
||||
extern int mvc_copy_key(mvc *m, sql_table *t, sql_key *k, sql_key **kres);
|
||||
extern int mvc_copy_idx(mvc *m, sql_table *t, sql_idx *i, sql_idx **ires);
|
||||
extern int mvc_copy_trigger(mvc *m, sql_table *t, sql_trigger *tr, sql_trigger **tres);
|
||||
|
||||
extern sql_rel *sql_processrelation(mvc *sql, sql_rel *rel, int instantiate, int value_based_opt, int storage_based_opt);
|
||||
|
||||
extern void *sql_error(mvc *sql, int error_code, _In_z_ _Printf_format_string_ char *format, ...)
|
||||
__attribute__((__format__(__printf__, 3, 4)));
|
||||
|
||||
extern int symbol_cmp(mvc* sql, symbol *s1, symbol *s2);
|
||||
|
||||
static inline int mvc_highwater(mvc *sql)
|
||||
{
|
||||
int l = 0, rc = 0;
|
||||
uintptr_t c = (uintptr_t) (&l);
|
||||
|
||||
size_t diff = c < sql->sp ? sql->sp - c : c - sql->sp;
|
||||
if (diff > THREAD_STACK_SIZE - 280 * 1024)
|
||||
rc = 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /*_SQL_MVC_H*/
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _SQL_PARSER_H_
|
||||
#define _SQL_PARSER_H_
|
||||
|
||||
#include "sql_tokens.h"
|
||||
#include "sql_mvc.h"
|
||||
|
||||
/* the next define makes the parser output more specific error messages,
|
||||
* instead of only a dull 'parse error' */
|
||||
#define YYERROR_VERBOSE 1
|
||||
/* enable this to get an idea of what the parser is doing on stdout
|
||||
#define YYDEBUG 1
|
||||
*/
|
||||
|
||||
extern int find_subgeometry_type(mvc *m, char*);
|
||||
extern char *token2string(tokens token);
|
||||
extern int sqlparse(mvc *m);
|
||||
|
||||
#include "mal_errors.h" /* for SQLSTATE() */
|
||||
|
||||
#endif /*_SQL_PARSER_H_*/
|
||||
|
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef SQL_RELATION_H
|
||||
#define SQL_RELATION_H
|
||||
|
||||
#include "sql_catalog.h"
|
||||
|
||||
typedef enum expression_type {
|
||||
e_atom,
|
||||
e_column,
|
||||
e_cmp,
|
||||
e_func,
|
||||
e_aggr,
|
||||
e_convert,
|
||||
e_psm
|
||||
} expression_type;
|
||||
|
||||
#define CARD_ATOM 1
|
||||
#define CARD_AGGR 2
|
||||
#define CARD_MULTI 3
|
||||
|
||||
typedef struct sql_exp_name {
|
||||
unsigned int label;
|
||||
const char *name;
|
||||
const char *rname;
|
||||
} sql_exp_name;
|
||||
|
||||
typedef struct sql_var_name {
|
||||
const char *name;
|
||||
const char *sname;
|
||||
} sql_var_name;
|
||||
|
||||
typedef struct expression {
|
||||
expression_type type; /* atom, cmp, func/aggr */
|
||||
sql_exp_name alias;
|
||||
void *l;
|
||||
void *r;
|
||||
void *f; /* func's and aggr's, also e_cmp may have have 2 arguments */
|
||||
unsigned int flag; /* cmp types, PSM types/level */
|
||||
unsigned int
|
||||
card:2, /* card (0 truth value!) (1 atoms) (2 aggr) (3 multi value) */
|
||||
freevar:4, /* free variable, ie binds to the upper dependent join */
|
||||
intern:1,
|
||||
anti:1,
|
||||
ascending:1, /* order direction */
|
||||
nulls_last:1, /* return null after all other rows */
|
||||
zero_if_empty:1, /* in case of partial aggregator computation, some aggregators need to return 0 instead of NULL */
|
||||
distinct:1,
|
||||
argument_independence:1, /* for a function expression, the arguments are independent of the inner project relation. */
|
||||
|
||||
semantics:1, /* is vs = semantics (nil = nil vs unknown != unknown), ranges with or without nil, aggregation with or without nil */
|
||||
need_no_nil:1,
|
||||
has_no_nil:1,
|
||||
unique:1, /* expression has unique values, but it may have multiple NULL values! */
|
||||
|
||||
base:1,
|
||||
ref:1, /* used to indicate an other expression may reference this one */
|
||||
used:1, /* used for quick dead code removal */
|
||||
symmetric:1; /* compare between symmetric */
|
||||
sql_subtype tpe;
|
||||
void *p; /* properties for the optimizer */
|
||||
} sql_exp;
|
||||
|
||||
#define TABLE_PROD_FUNC 1
|
||||
#define TABLE_FROM_RELATION 2
|
||||
#define TRIGGER_WRAPPER 4
|
||||
|
||||
#define IS_TABLE_PROD_FUNC(X) ((X & TABLE_PROD_FUNC) == TABLE_PROD_FUNC)
|
||||
|
||||
/* or-ed with the above TABLE_PROD_FUNC */
|
||||
#define UPD_COMP 2
|
||||
|
||||
#define LEFT_JOIN 4
|
||||
#define REL_PARTITION 8
|
||||
#define MERGE_LEFT 16 /* used by merge statements */
|
||||
#define OUTER_ZERO 32
|
||||
|
||||
/* We need bit wise exclusive numbers as we merge the level also in the flag */
|
||||
#define PSM_SET 1
|
||||
#define PSM_VAR 2
|
||||
#define PSM_RETURN 4
|
||||
#define PSM_WHILE 8
|
||||
#define PSM_IF 16
|
||||
#define PSM_REL 32
|
||||
#define PSM_EXCEPTION 64
|
||||
|
||||
#define SET_PSM_LEVEL(level) (level<<8)
|
||||
#define GET_PSM_LEVEL(level) (level>>8)
|
||||
|
||||
typedef enum ddl_statement {
|
||||
ddl_output,
|
||||
ddl_list,
|
||||
ddl_psm,
|
||||
ddl_exception,
|
||||
ddl_create_seq,
|
||||
ddl_alter_seq,
|
||||
ddl_drop_seq,
|
||||
ddl_alter_table_add_range_partition,
|
||||
ddl_alter_table_add_list_partition,
|
||||
ddl_release,
|
||||
ddl_commit,
|
||||
ddl_rollback,
|
||||
ddl_trans,
|
||||
ddl_create_schema,
|
||||
ddl_drop_schema,
|
||||
ddl_create_table,
|
||||
ddl_drop_table,
|
||||
ddl_create_view,
|
||||
ddl_drop_view,
|
||||
ddl_drop_constraint,
|
||||
ddl_alter_table,
|
||||
ddl_create_type,
|
||||
ddl_drop_type,
|
||||
ddl_drop_index,
|
||||
ddl_create_function,
|
||||
ddl_drop_function,
|
||||
ddl_create_trigger,
|
||||
ddl_drop_trigger,
|
||||
ddl_grant_roles,
|
||||
ddl_revoke_roles,
|
||||
ddl_grant,
|
||||
ddl_revoke,
|
||||
ddl_grant_func,
|
||||
ddl_revoke_func,
|
||||
ddl_create_user,
|
||||
ddl_drop_user,
|
||||
ddl_alter_user,
|
||||
ddl_rename_user,
|
||||
ddl_create_role,
|
||||
ddl_drop_role,
|
||||
ddl_alter_table_add_table,
|
||||
ddl_alter_table_del_table,
|
||||
ddl_alter_table_set_access,
|
||||
ddl_comment_on,
|
||||
ddl_rename_schema,
|
||||
ddl_rename_table,
|
||||
ddl_rename_column,
|
||||
ddl_maxops /* evaluated to the max value, should be always kept at the bottom */
|
||||
} ddl_statement;
|
||||
|
||||
typedef enum operator_type {
|
||||
op_basetable = 0,
|
||||
op_table,
|
||||
op_ddl,
|
||||
op_project, /* includes order by */
|
||||
op_select,
|
||||
op_join,
|
||||
op_left,
|
||||
op_right,
|
||||
op_full,
|
||||
op_semi,
|
||||
op_anti,
|
||||
op_union,
|
||||
op_inter,
|
||||
op_except,
|
||||
op_groupby,
|
||||
op_topn,
|
||||
op_sample,
|
||||
op_insert, /* insert(l=table, r insert expressions) */
|
||||
op_update, /* update(l=table, r update expressions) */
|
||||
op_delete, /* delete(l=table, r delete expression) */
|
||||
op_truncate, /* truncate(l=table) */
|
||||
op_merge
|
||||
} operator_type;
|
||||
|
||||
#define is_atom(et) (et == e_atom)
|
||||
/* a simple atom is a literal or on the query stack */
|
||||
#define is_simple_atom(e) (is_atom((e)->type) && !(e)->r && !(e)->f)
|
||||
#define is_values(e) ((e)->type == e_atom && (e)->f)
|
||||
#define is_func(et) (et == e_func)
|
||||
#define is_aggr(et) (et == e_aggr)
|
||||
#define is_convert(et) (et == e_convert)
|
||||
#define is_map_op(et) (et == e_func || et == e_convert)
|
||||
#define is_compare(et) (et == e_cmp)
|
||||
#define is_column(et) (et != e_cmp)
|
||||
#define is_alias(et) (et == e_column)
|
||||
#define is_analytic(e) ((e)->type == e_func && ((sql_subfunc*)(e)->f)->func->type == F_ANALYTIC)
|
||||
|
||||
#define is_base(op) (op == op_basetable || op == op_table)
|
||||
#define is_basetable(op) (op == op_basetable)
|
||||
#define is_ddl(op) (op == op_ddl)
|
||||
#define is_outerjoin(op) (op == op_left || op == op_right || op == op_full)
|
||||
#define is_left(op) (op == op_left)
|
||||
#define is_right(op) (op == op_right)
|
||||
#define is_full(op) (op == op_full)
|
||||
#define is_innerjoin(op) (op == op_join)
|
||||
#define is_join(op) (op == op_join || is_outerjoin(op))
|
||||
#define is_semi(op) (op == op_semi || op == op_anti)
|
||||
#define is_joinop(op) (is_join(op) || is_semi(op))
|
||||
#define is_select(op) (op == op_select)
|
||||
#define is_set(op) (op == op_union || op == op_inter || op == op_except)
|
||||
#define is_union(op) (op == op_union)
|
||||
#define is_inter(op) (op == op_inter)
|
||||
#define is_except(op) (op == op_except)
|
||||
#define is_simple_project(op) (op == op_project)
|
||||
#define is_project(op) (op == op_project || op == op_groupby || is_set(op))
|
||||
#define is_groupby(op) (op == op_groupby)
|
||||
#define is_topn(op) (op == op_topn)
|
||||
#define is_modify(op) (op == op_insert || op == op_update || op == op_delete || op == op_truncate || op == op_merge)
|
||||
#define is_sample(op) (op == op_sample)
|
||||
#define is_insert(op) (op == op_insert)
|
||||
#define is_update(op) (op == op_update)
|
||||
#define is_delete(op) (op == op_delete)
|
||||
#define is_truncate(op) (op == op_truncate)
|
||||
#define is_merge(op) (op == op_merge)
|
||||
|
||||
/* ZERO on empty sets, needed for sum (of counts)). */
|
||||
#define zero_if_empty(e) ((e)->zero_if_empty)
|
||||
#define set_zero_if_empty(e) (e)->zero_if_empty = 1
|
||||
|
||||
/* NO NIL semantics of aggr operations */
|
||||
#define need_no_nil(e) ((e)->need_no_nil)
|
||||
#define set_no_nil(e) (e)->need_no_nil = 1
|
||||
|
||||
/* does the expression (possibly) have nils */
|
||||
#define has_nil(e) ((e)->has_no_nil==0)
|
||||
#define set_has_no_nil(e) (e)->has_no_nil = 1
|
||||
#define set_has_nil(e) (e)->has_no_nil = 0
|
||||
|
||||
#define is_ascending(e) ((e)->ascending)
|
||||
#define set_ascending(e) ((e)->ascending = 1)
|
||||
#define set_descending(e) ((e)->ascending = 0)
|
||||
#define nulls_last(e) ((e)->nulls_last)
|
||||
#define set_nulls_last(e) ((e)->nulls_last=1)
|
||||
#define set_nulls_first(e) ((e)->nulls_last=0)
|
||||
#define set_direction(e, dir) ((e)->ascending = (dir&1), (e)->nulls_last = (dir&2)?1:0)
|
||||
|
||||
#define is_unique(e) ((e)->unique)
|
||||
#define set_unique(e) (e)->unique = 1
|
||||
#define set_not_unique(e) (e)->unique = 0
|
||||
#define is_anti(e) ((e)->anti)
|
||||
#define set_anti(e) (e)->anti = 1
|
||||
#define is_semantics(e) ((e)->semantics)
|
||||
#define set_semantics(e) (e)->semantics = 1
|
||||
#define is_symmetric(e) ((e)->symmetric)
|
||||
#define set_symmetric(e) (e)->symmetric = 1
|
||||
#define is_intern(e) ((e)->intern)
|
||||
#define set_intern(e) (e)->intern = 1
|
||||
#define is_basecol(e) ((e)->base)
|
||||
#define set_basecol(e) (e)->base = 1
|
||||
|
||||
#define has_label(e) ((e)->alias.label > 0)
|
||||
|
||||
/* used for expressions and relations */
|
||||
#define need_distinct(er) ((er)->distinct)
|
||||
#define set_distinct(er) (er)->distinct = 1
|
||||
#define set_nodistinct(er) (er)->distinct = 0
|
||||
|
||||
#define is_processed(rel) ((rel)->processed)
|
||||
#define set_processed(rel) (rel)->processed = 1
|
||||
#define reset_processed(rel) (rel)->processed = 0
|
||||
#define is_dependent(rel) ((rel)->dependent)
|
||||
#define set_dependent(rel) (rel)->dependent = 1
|
||||
#define reset_dependent(rel) (rel)->dependent = 0
|
||||
#define is_outer(rel) ((rel)->outer)
|
||||
#define set_outer(rel) (rel)->outer = 1
|
||||
#define reset_outer(rel) (rel)->outer = 0
|
||||
#define is_single(rel) ((rel)->single)
|
||||
#define set_single(rel) (rel)->single = 1
|
||||
#define reset_single(rel) (rel)->single = 0
|
||||
|
||||
#define is_freevar(e) ((e)->freevar)
|
||||
#define set_freevar(e,level) (e)->freevar = level+1
|
||||
#define reset_freevar(e) (e)->freevar = 0
|
||||
|
||||
#define rel_is_ref(rel) (((sql_rel*)(rel))->ref.refcnt > 1)
|
||||
|
||||
typedef struct relation {
|
||||
sql_ref ref;
|
||||
|
||||
operator_type op;
|
||||
void *l;
|
||||
void *r;
|
||||
list *exps;
|
||||
int nrcols; /* nr of cols */
|
||||
unsigned int
|
||||
flag:16,
|
||||
card:4, /* 0, 1 (row), 2 aggr, 3 */
|
||||
dependent:1, /* dependent join */
|
||||
distinct:1,
|
||||
processed:1, /* fully processed or still in the process of building */
|
||||
outer:1, /* used as outer (ungrouped) */
|
||||
grouped:1, /* groupby processed all the group by exps */
|
||||
single:1,
|
||||
/*
|
||||
* Used by rewriters at rel_unnest, rel_optimizer and rel_distribute so a relation is not modified twice
|
||||
* All bits are used by rel_unnest modifiers and always reset after.
|
||||
* The first bit is also used by rel_dce and rel_merge_select_rse optimizers.
|
||||
* The third bit is used by rel_remote_func only and it's not reset.
|
||||
*/
|
||||
used:3;
|
||||
void *p; /* properties for the optimizer, distribution */
|
||||
} sql_rel;
|
||||
|
||||
#endif /* SQL_RELATION_H */
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _SQL_SCAN_H_
|
||||
#define _SQL_SCAN_H_
|
||||
|
||||
#include "sql_mem.h"
|
||||
#include "sql_list.h"
|
||||
#include "stream.h"
|
||||
|
||||
typedef enum { LINE_1, LINE_N } prot;
|
||||
|
||||
struct scanner {
|
||||
bstream *rs;
|
||||
stream *ws;
|
||||
stream *log;
|
||||
|
||||
int yynext; /* next token, lr(1) isn't powerful enough for sql */
|
||||
int yylast; /* previous token, to detect superfluous semi-colons */
|
||||
int yyval; /* current token */
|
||||
size_t yysval; /* start of current token */
|
||||
size_t yycur; /* next char in the queue */
|
||||
size_t as; /* start of query part of view's etc */
|
||||
char yybak; /* sometimes it's needed to write an EOS marker */
|
||||
int started; /* found at least one token */
|
||||
prot mode; /* which mode (line (1,N), blocked) */
|
||||
char *schema; /* Keep schema name of create statement, needed AUTO_INCREMENT, SERIAL */
|
||||
char *errstr; /* error message from the bowels of the scanner */
|
||||
|
||||
|
||||
/* Currently, MonetDB interprets \ specially in strings. This is contrary
|
||||
* to the SQL standard. The default behavior of the reader is controlled by
|
||||
* ``raw_strings`` mserver5 option (``--set raw_strings=<true|false>``) and
|
||||
* the database property of the same name of merovingian (``monetdb set
|
||||
* raw_strings=yes <database>``). If it is ``true`` by default the reader
|
||||
* interprets strings as specified in the SQL standard, i.e. no
|
||||
* interpretation of the \ characters. If it is ``false`` \ characters are
|
||||
* used for escaping.
|
||||
*
|
||||
* The default value of this setting is false as of the Jul2021 release,
|
||||
* i.e. MonetDB by default interprets \ in strings.
|
||||
*
|
||||
* In case that we are interpreting \ in strings, we need state in the
|
||||
* scanner so that we Do The Right Thing (TM) when we get a unicode string
|
||||
* split up in multiple parts (i.e. U&'string1' 'string2') where the second
|
||||
* and subsequent string MUST NOT undergo \ interpretation.
|
||||
*
|
||||
* Because we need to be backward compatible (i.e. we need have ``select
|
||||
* char_length('a\nb')`` return 3) the next 2 members will probably stay for
|
||||
* the forseeable future.
|
||||
*/
|
||||
bool next_string_is_raw;
|
||||
bool raw_string_mode;
|
||||
};
|
||||
|
||||
#define QUERY(scanner) (scanner.rs->buf+scanner.rs->pos)
|
||||
|
||||
extern char *query_cleaned(sql_allocator *sa, const char *query);
|
||||
extern void scanner_init(struct scanner *s, bstream *rs, stream *ws);
|
||||
sql_export void scanner_query_processed(struct scanner *s);
|
||||
|
||||
extern int scanner_init_keywords(void);
|
||||
#endif /* _SQL_SCAN_H_ */
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _SQL_SEMANTIC_H_
|
||||
#define _SQL_SEMANTIC_H_
|
||||
|
||||
#include "sql_list.h"
|
||||
#include "sql_symbol.h"
|
||||
#include "sql_parser.h"
|
||||
|
||||
typedef struct exp_kind_t {
|
||||
bte type;
|
||||
bte card;
|
||||
bit reduce;
|
||||
} exp_kind;
|
||||
|
||||
extern sql_schema *cur_schema(mvc *sql);
|
||||
extern sql_schema *tmp_schema(mvc *sql);
|
||||
|
||||
/* Search function for SQL objects with scoping rules. For tables an optional schema can be provided with search priority */
|
||||
sql_export sql_table *find_table_or_view_on_scope(mvc *sql, sql_schema *s, const char *sname, const char *tname, const char *error, bool isView);
|
||||
extern sql_sequence *find_sequence_on_scope(mvc *sql, const char *sname, const char *name, const char *error);
|
||||
extern sql_idx *find_idx_on_scope(mvc *sql, const char *sname, const char *name, const char *error);
|
||||
extern sql_type *find_type_on_scope(mvc *sql, const char *sname, const char *name, const char *error);
|
||||
extern sql_trigger *find_trigger_on_scope(mvc *sql, const char *sname, const char *name, const char *error);
|
||||
extern bool find_variable_on_scope(mvc *sql, const char *sname, const char *name, sql_var **var, sql_arg **a, sql_subtype **tpe, int *level, const char *error);
|
||||
|
||||
/* These functions find catalog functions according to scoping rules */
|
||||
extern sql_subfunc *sql_find_func(mvc *sql, const char *sname, const char *fname, int nrargs, sql_ftype type, sql_subfunc *prev);
|
||||
extern sql_subfunc *sql_bind_member(mvc *sql, const char *sname, const char *fname, sql_subtype *tp, sql_ftype type, int nrargs, sql_subfunc *prev);
|
||||
extern sql_subfunc *sql_bind_func(mvc *sql, const char *sname, const char *fname, sql_subtype *tp1, sql_subtype *tp2, sql_ftype type);
|
||||
extern sql_subfunc *sql_bind_func3(mvc *sql, const char *sname, const char *fname, sql_subtype *tp1, sql_subtype *tp2, sql_subtype *tp3, sql_ftype type);
|
||||
extern sql_subfunc *sql_bind_func_result(mvc *sql, const char *sname, const char *fname, sql_ftype type, sql_subtype *res, int nargs, ...);
|
||||
extern sql_subfunc *sql_bind_func_(mvc *sql, const char *sname, const char *fname, list *ops, sql_ftype type);
|
||||
extern sql_subfunc *sql_resolve_function_with_undefined_parameters(mvc *sql, const char *sname, const char *fname, list *ops, sql_ftype type);
|
||||
|
||||
extern list *sql_find_funcs(mvc *sql, const char *sname, const char *fname, int nrargs, sql_ftype type);
|
||||
extern list *sql_find_funcs_by_name(mvc *sql, const char *sname, const char *name, sql_ftype type);
|
||||
|
||||
extern char *qname_schema(dlist *qname);
|
||||
extern char *qname_schema_object(dlist *qname);
|
||||
extern char *qname_catalog(dlist *qname);
|
||||
#define qname_module(qname) qname_schema(qname)
|
||||
|
||||
extern sql_subtype *result_datatype(sql_subtype *super, sql_subtype *l, sql_subtype *r);
|
||||
extern sql_subtype *supertype(sql_subtype *super, sql_subtype *r, sql_subtype *i);
|
||||
|
||||
typedef enum {
|
||||
type_set, /* set operations have very limiting coersion rules */
|
||||
type_equal,
|
||||
type_equal_no_any,
|
||||
type_cast /* also truncate */
|
||||
} check_type;
|
||||
|
||||
/* SQL's parameters '?' (in prepare statements) and parameters of sql
|
||||
* functions and procedures are kept in the param list. */
|
||||
|
||||
extern void sql_add_param(mvc *sql, const char *name, sql_subtype *st);
|
||||
extern sql_arg *sql_bind_param(mvc *sql, const char *name);
|
||||
/* once the type of the '?' parameters is known it's set using the set_type
|
||||
* function */
|
||||
extern int set_type_param(mvc *sql, sql_subtype *type, int nr);
|
||||
extern void sql_destroy_params(mvc *sql); /* used in backend */
|
||||
|
||||
extern char *symbol2string(mvc *sql, symbol *s, int expression, char **err);
|
||||
//extern char *dlist2string(mvc *sql, dlist *s, int expression, char **err);
|
||||
|
||||
extern char * toUpperCopy(char *dest, const char *src);
|
||||
|
||||
#endif /*_SQL_SEMANTIC_H_*/
|
||||
|
@ -0,0 +1,544 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef SQL_STORAGE_H
|
||||
#define SQL_STORAGE_H
|
||||
|
||||
#include "sql_catalog.h"
|
||||
#include "store_sequence.h"
|
||||
|
||||
#define COLSIZE 1024
|
||||
|
||||
#define LOG_OK 0
|
||||
#define LOG_ERR (-1)
|
||||
#define LOG_CONFLICT (-2)
|
||||
|
||||
#define isTempTable(x) ((x)->persistence!=SQL_PERSIST)
|
||||
#define isGlobal(x) ((x)->persistence!=SQL_LOCAL_TEMP && (x)->persistence!=SQL_DECLARED_TABLE)
|
||||
#define isGlobalTemp(x) ((x)->persistence==SQL_GLOBAL_TEMP)
|
||||
#define isLocalTemp(x) ((x)->persistence==SQL_LOCAL_TEMP)
|
||||
#define isTempSchema(x) (strcmp((x)->base.name, "tmp") == 0)
|
||||
#define isDeclaredTable(x) ((x)->persistence==SQL_DECLARED_TABLE)
|
||||
|
||||
typedef enum store_type {
|
||||
store_bat, /* delta bats, ie multi user read/write */
|
||||
store_tst,
|
||||
store_mem
|
||||
} store_type;
|
||||
|
||||
|
||||
struct sqlstore;
|
||||
|
||||
/* builtin functions have ids less than this */
|
||||
#define FUNC_OIDS 2000
|
||||
|
||||
/* relational interface */
|
||||
typedef oid (*column_find_row_fptr)(sql_trans *tr, sql_column *c, const void *value, ...);
|
||||
typedef void *(*column_find_value_fptr)(sql_trans *tr, sql_column *c, oid rid);
|
||||
typedef sqlid (*column_find_sqlid_fptr)(sql_trans *tr, sql_column *c, oid rid);
|
||||
typedef bte (*column_find_bte_fptr)(sql_trans *tr, sql_column *c, oid rid);
|
||||
typedef sht (*column_find_sht_fptr)(sql_trans *tr, sql_column *c, oid rid);
|
||||
typedef int (*column_find_int_fptr)(sql_trans *tr, sql_column *c, oid rid);
|
||||
typedef lng (*column_find_lng_fptr)(sql_trans *tr, sql_column *c, oid rid);
|
||||
typedef const char * (*column_find_string_start_fptr)(sql_trans *tr, sql_column *c, oid rid, ptr *cbat);
|
||||
typedef void (*column_find_string_end_fptr)(ptr cbat);
|
||||
typedef int (*column_update_value_fptr)(sql_trans *tr, sql_column *c, oid rid, void *value);
|
||||
typedef int (*table_insert_fptr)(sql_trans *tr, sql_table *t, ...);
|
||||
typedef int (*table_delete_fptr)(sql_trans *tr, sql_table *t, oid rid);
|
||||
|
||||
typedef res_table *(*table_orderby_fptr)(sql_trans *tr, sql_table *t,
|
||||
sql_column *jl, sql_column *jr,
|
||||
sql_column *jl2, sql_column *jr2 /* optional join(jl,jr,(jl2,jr2)) */, sql_column *o, ...);
|
||||
typedef void *(*table_fetch_value_fptr)(res_table *rt, sql_column *c);
|
||||
typedef void (*table_result_destroy_fptr)(res_table *rt);
|
||||
|
||||
typedef struct rids {
|
||||
BUN cur;
|
||||
void *data;
|
||||
} rids;
|
||||
|
||||
typedef struct subrids {
|
||||
BUN pos;
|
||||
sqlid id;
|
||||
void *ids;
|
||||
void *rids;
|
||||
} subrids;
|
||||
|
||||
/* returns table rids, for the given select ranges */
|
||||
typedef rids *(*rids_select_fptr)( sql_trans *tr, sql_column *key, const void *key_value_low, const void *key_value_high, ...);
|
||||
|
||||
/* order rids by orderby_column values */
|
||||
typedef rids *(*rids_orderby_fptr)( sql_trans *tr, rids *r, sql_column *orderby_col);
|
||||
|
||||
typedef rids *(*rids_join_fptr)( sql_trans *tr, rids *l, sql_column *lc, rids *r, sql_column *rc);
|
||||
typedef rids *(*rids_semijoin_fptr)( sql_trans *tr, rids *l, sql_column *lc, rids *r, sql_column *rc);
|
||||
typedef rids *(*rids_diff_fptr)( sql_trans *tr, rids *l, sql_column *lc, subrids *r, sql_column *rc);
|
||||
|
||||
/* return table rids from result of table_select, return (-1) when done */
|
||||
typedef oid (*rids_next_fptr)(rids *r);
|
||||
|
||||
/* clean up the resources taken by the result of table_select */
|
||||
typedef void (*rids_destroy_fptr)(rids *r);
|
||||
typedef int (*rids_empty_fptr)(rids *r);
|
||||
|
||||
typedef subrids *(*subrids_create_fptr)( sql_trans *tr, rids *l, sql_column *jc1, sql_column *jc2, sql_column *obc);
|
||||
|
||||
/* return table rids from result of table_select, return (-1) when done */
|
||||
typedef oid (*subrids_next_fptr)(subrids *r);
|
||||
typedef sqlid (*subrids_nextid_fptr)(subrids *r);
|
||||
|
||||
/* clean up the resources taken by the result of table_select */
|
||||
typedef void (*subrids_destroy_fptr)(subrids *r);
|
||||
|
||||
typedef struct table_functions {
|
||||
column_find_row_fptr column_find_row;
|
||||
column_find_value_fptr column_find_value;
|
||||
column_find_sqlid_fptr column_find_sqlid;
|
||||
column_find_bte_fptr column_find_bte;
|
||||
column_find_int_fptr column_find_int;
|
||||
column_find_lng_fptr column_find_lng;
|
||||
column_find_string_start_fptr column_find_string_start; /* this function returns a pointer to the heap, use it with care! */
|
||||
column_find_string_end_fptr column_find_string_end; /* don't forget to call this function to unfix the bat descriptor! */
|
||||
|
||||
column_update_value_fptr column_update_value;
|
||||
table_insert_fptr table_insert;
|
||||
table_delete_fptr table_delete;
|
||||
table_orderby_fptr table_orderby;
|
||||
table_fetch_value_fptr table_fetch_value;
|
||||
table_result_destroy_fptr table_result_destroy;
|
||||
|
||||
rids_select_fptr rids_select;
|
||||
rids_orderby_fptr rids_orderby;
|
||||
rids_join_fptr rids_join;
|
||||
rids_semijoin_fptr rids_semijoin;
|
||||
rids_next_fptr rids_next;
|
||||
rids_destroy_fptr rids_destroy;
|
||||
rids_empty_fptr rids_empty;
|
||||
|
||||
subrids_create_fptr subrids_create;
|
||||
subrids_next_fptr subrids_next;
|
||||
subrids_nextid_fptr subrids_nextid;
|
||||
subrids_destroy_fptr subrids_destroy;
|
||||
rids_diff_fptr rids_diff;
|
||||
} table_functions;
|
||||
|
||||
/* delta table setup (ie readonly col + ins + upd + del)
|
||||
-- binds for column,idx (rdonly, inserts, updates) and delets
|
||||
*/
|
||||
typedef void *(*bind_col_fptr) (sql_trans *tr, sql_column *c, int access);
|
||||
typedef void *(*bind_idx_fptr) (sql_trans *tr, sql_idx *i, int access);
|
||||
typedef void *(*bind_cands_fptr) (sql_trans *tr, sql_table *t, int nr_of_parts, int part_nr);
|
||||
|
||||
typedef int (*append_col_fptr) (sql_trans *tr, sql_column *c, BUN offset, BAT *offsets, void *d, BUN cnt, int t);
|
||||
typedef int (*append_idx_fptr) (sql_trans *tr, sql_idx *i, BUN offset, BAT *offsets, void *d, BUN cnt, int t);
|
||||
|
||||
typedef int (*update_col_fptr) (sql_trans *tr, sql_column *c, void *tids, void *d, int t);
|
||||
typedef int (*update_idx_fptr) (sql_trans *tr, sql_idx *i, void *tids, void *d, int t);
|
||||
|
||||
typedef int (*delete_tab_fptr) (sql_trans *tr, sql_table *t, void *d, int tpe);
|
||||
typedef int (*claim_tab_fptr) (sql_trans *tr, sql_table *t, size_t cnt, BUN *offset, BAT **offsets);
|
||||
typedef int (*tab_validate_fptr) (sql_trans *tr, sql_table *t, int uncommitted);
|
||||
|
||||
/*
|
||||
-- count number of rows in column (excluding the deletes)
|
||||
-- check for sortedness
|
||||
*/
|
||||
typedef size_t (*count_del_fptr) (sql_trans *tr, sql_table *t, int access);
|
||||
typedef size_t (*count_col_fptr) (sql_trans *tr, sql_column *c, int access);
|
||||
typedef size_t (*count_idx_fptr) (sql_trans *tr, sql_idx *i, int access);
|
||||
typedef size_t (*dcount_col_fptr) (sql_trans *tr, sql_column *c);
|
||||
typedef int (*min_max_col_fptr) (sql_trans *tr, sql_column *c);
|
||||
typedef int (*prop_col_fptr) (sql_trans *tr, sql_column *c);
|
||||
|
||||
/*
|
||||
-- create the necessary storage resources for columns, indices and tables
|
||||
-- returns LOG_OK, LOG_ERR
|
||||
*/
|
||||
typedef int (*create_col_fptr) (sql_trans *tr, sql_column *c);
|
||||
typedef int (*create_idx_fptr) (sql_trans *tr, sql_idx *i);
|
||||
typedef int (*create_del_fptr) (sql_trans *tr, sql_table *t);
|
||||
|
||||
typedef void *(*col_dup_fptr) (sql_column *c);
|
||||
typedef void *(*idx_dup_fptr) (sql_idx *i);
|
||||
typedef void *(*del_dup_fptr) (sql_table *t);
|
||||
|
||||
/*
|
||||
-- upgrade the necessary storage resources for columns, indices and tables
|
||||
-- needed for the upgrade of the logger structure (ie user tables are
|
||||
-- now stored using the object ids, no longer the names). This allows
|
||||
-- renames.
|
||||
-- returns LOG_OK, LOG_ERR
|
||||
*/
|
||||
typedef int (*upgrade_col_fptr) (sql_trans *tr, sql_column *c);
|
||||
typedef int (*upgrade_idx_fptr) (sql_trans *tr, sql_idx *i);
|
||||
typedef int (*upgrade_del_fptr) (sql_trans *tr, sql_table *t);
|
||||
typedef int (*swap_bats_fptr) (sql_trans *tr, sql_column *c, BAT *b);
|
||||
|
||||
/*
|
||||
-- free the storage resources for columns, indices and tables
|
||||
-- returns LOG_OK, LOG_ERR
|
||||
*/
|
||||
typedef int (*destroy_col_fptr) (struct sqlstore *store, sql_column *c);
|
||||
typedef int (*destroy_idx_fptr) (struct sqlstore *store, sql_idx *i);
|
||||
typedef int (*destroy_del_fptr) (struct sqlstore *store, sql_table *t);
|
||||
|
||||
/*
|
||||
-- drop a persistent table, ie add to the list of changes
|
||||
-- returns LOG_OK, LOG_ERR
|
||||
*/
|
||||
typedef int (*drop_col_fptr) (sql_trans *tr, sql_column *c);
|
||||
typedef int (*drop_idx_fptr) (sql_trans *tr, sql_idx *i);
|
||||
typedef int (*drop_del_fptr) (sql_trans *tr, sql_table *t);
|
||||
|
||||
typedef BUN (*clear_table_fptr) (sql_trans *tr, sql_table *t);
|
||||
|
||||
typedef enum storage_type {
|
||||
ST_DEFAULT = 0,
|
||||
ST_DICT,
|
||||
ST_FOR,
|
||||
} storage_type;
|
||||
|
||||
typedef int (*col_compress_fptr) (sql_trans *tr, sql_column *c, storage_type st, BAT *offsets, BAT *vals);
|
||||
|
||||
/*
|
||||
-- update_table rollforward the changes made from table ft to table tt
|
||||
-- returns LOG_OK, LOG_ERR
|
||||
*/
|
||||
typedef int (*update_table_fptr) (sql_trans *tr, sql_table *ft, sql_table *tt);
|
||||
|
||||
/* backing struct for this interface */
|
||||
typedef struct store_functions {
|
||||
|
||||
bind_col_fptr bind_col;
|
||||
bind_idx_fptr bind_idx;
|
||||
bind_cands_fptr bind_cands;
|
||||
|
||||
append_col_fptr append_col;
|
||||
append_idx_fptr append_idx;
|
||||
|
||||
update_col_fptr update_col;
|
||||
update_idx_fptr update_idx;
|
||||
|
||||
delete_tab_fptr delete_tab;
|
||||
claim_tab_fptr claim_tab;
|
||||
claim_tab_fptr key_claim_tab;
|
||||
tab_validate_fptr tab_validate;
|
||||
|
||||
count_del_fptr count_del;
|
||||
count_col_fptr count_col;
|
||||
count_idx_fptr count_idx;
|
||||
dcount_col_fptr dcount_col;
|
||||
min_max_col_fptr min_max_col;
|
||||
prop_col_fptr sorted_col;
|
||||
prop_col_fptr unique_col;
|
||||
prop_col_fptr double_elim_col; /* varsize col with double elimination */
|
||||
|
||||
col_dup_fptr col_dup;
|
||||
idx_dup_fptr idx_dup;
|
||||
del_dup_fptr del_dup;
|
||||
|
||||
create_col_fptr create_col;
|
||||
create_idx_fptr create_idx;
|
||||
create_del_fptr create_del;
|
||||
|
||||
destroy_col_fptr destroy_col;
|
||||
destroy_idx_fptr destroy_idx;
|
||||
destroy_del_fptr destroy_del;
|
||||
|
||||
drop_col_fptr drop_col;
|
||||
drop_idx_fptr drop_idx;
|
||||
drop_del_fptr drop_del;
|
||||
|
||||
clear_table_fptr clear_table;
|
||||
col_compress_fptr col_compress;
|
||||
|
||||
upgrade_col_fptr upgrade_col;
|
||||
upgrade_idx_fptr upgrade_idx;
|
||||
upgrade_del_fptr upgrade_del;
|
||||
swap_bats_fptr swap_bats;
|
||||
} store_functions;
|
||||
|
||||
typedef int (*logger_create_fptr) (struct sqlstore *store, int debug, const char *logdir, int catalog_version);
|
||||
|
||||
typedef void (*logger_destroy_fptr) (struct sqlstore *store);
|
||||
typedef int (*logger_flush_fptr) (struct sqlstore *store, lng save_id);
|
||||
typedef int (*logger_activate_fptr) (struct sqlstore *store);
|
||||
typedef int (*logger_cleanup_fptr) (struct sqlstore *store);
|
||||
|
||||
typedef int (*logger_changes_fptr)(struct sqlstore *store);
|
||||
typedef int (*logger_get_sequence_fptr) (struct sqlstore *store, int seq, lng *id);
|
||||
|
||||
typedef int (*log_isnew_fptr)(struct sqlstore *store);
|
||||
typedef int (*log_tstart_fptr) (struct sqlstore *store, bool flush);
|
||||
typedef int (*log_tend_fptr) (struct sqlstore *store);
|
||||
typedef int (*log_tdone_fptr) (struct sqlstore *store, ulng commit_ts);
|
||||
typedef lng (*log_save_id_fptr) (struct sqlstore *store);
|
||||
typedef int (*log_sequence_fptr) (struct sqlstore *store, int seq, lng id);
|
||||
|
||||
/*
|
||||
-- List which parts of which files must be included in a hot snapshot.
|
||||
-- This is written to the given stream in the following format:
|
||||
-- - The first line is the absolute path of the db dir. All other paths
|
||||
-- are relative to this.
|
||||
-- - Every other line is either "c %ld %s\n" or "w %ld %s\n". The long
|
||||
-- is always the number of bytes to write. The %s is the relative path of the
|
||||
-- destination. For "c" lines (copy), it is also the relative path of the
|
||||
-- source file. For "w" lines (write), the %ld bytes to write follow directly
|
||||
-- after the newline.
|
||||
-- Using a stream (buffer) instead of a list data structure simplifies debugging
|
||||
-- and avoids a lot of tiny allocations and pointer manipulations.
|
||||
*/
|
||||
typedef gdk_return (*logger_get_snapshot_files_fptr)(struct sqlstore *store, stream *plan);
|
||||
|
||||
typedef struct logger_functions {
|
||||
logger_create_fptr create;
|
||||
logger_destroy_fptr destroy;
|
||||
logger_flush_fptr flush;
|
||||
logger_activate_fptr activate;
|
||||
|
||||
logger_changes_fptr changes;
|
||||
logger_get_sequence_fptr get_sequence;
|
||||
|
||||
logger_get_snapshot_files_fptr get_snapshot_files;
|
||||
|
||||
log_isnew_fptr log_isnew;
|
||||
log_tstart_fptr log_tstart;
|
||||
log_tend_fptr log_tend;
|
||||
log_tdone_fptr log_tdone;
|
||||
log_save_id_fptr log_save_id;
|
||||
log_sequence_fptr log_sequence;
|
||||
} logger_functions;
|
||||
|
||||
/* we need to add an interface for result_tables later */
|
||||
|
||||
extern res_table *res_table_create(sql_trans *tr, int res_id, oid query_id, int nr_cols, mapi_query_t querytype, res_table *next, void *order);
|
||||
extern res_col *res_col_create(sql_trans *tr, res_table *t, const char *tn, const char *name, const char *typename, int digits, int scale, char mtype, void *v, bool cache);
|
||||
|
||||
extern void res_table_destroy(res_table *t);
|
||||
|
||||
extern res_table *res_tables_remove(res_table *results, res_table *t);
|
||||
sql_export void res_tables_destroy(res_table *results);
|
||||
extern res_table *res_tables_find(res_table *results, int res_id);
|
||||
|
||||
extern struct sqlstore *store_init(int debug, store_type store, int readonly, int singleuser);
|
||||
extern void store_exit(struct sqlstore *store);
|
||||
|
||||
extern void store_suspend_log(struct sqlstore *store);
|
||||
extern void store_resume_log(struct sqlstore *store);
|
||||
extern lng store_hot_snapshot(struct sqlstore *store, str tarfile);
|
||||
extern lng store_hot_snapshot_to_stream(struct sqlstore *store, stream *s);
|
||||
|
||||
extern ulng store_function_counter(struct sqlstore *store);
|
||||
|
||||
extern ulng store_oldest(struct sqlstore *store);
|
||||
extern ulng store_get_timestamp(struct sqlstore *store);
|
||||
extern void store_manager(struct sqlstore *store);
|
||||
|
||||
extern void store_lock(struct sqlstore *store);
|
||||
extern void store_unlock(struct sqlstore *store);
|
||||
extern sqlid store_next_oid(struct sqlstore *store);
|
||||
|
||||
extern int store_readonly(struct sqlstore *store);
|
||||
|
||||
extern sql_trans *sql_trans_create(struct sqlstore *store, sql_trans *parent, const char *name);
|
||||
extern sql_trans *sql_trans_destroy(sql_trans *tr);
|
||||
//extern bool sql_trans_validate(sql_trans *tr);
|
||||
extern int sql_trans_commit(sql_trans *tr);
|
||||
|
||||
extern int sql_trans_create_type(sql_trans *tr, sql_schema *s, const char *sqlname, unsigned int digits, unsigned int scale, int radix, const char *impl);
|
||||
extern int sql_trans_drop_type(sql_trans *tr, sql_schema * s, sqlid id, int drop_action);
|
||||
|
||||
extern int sql_trans_create_func(sql_func **fres, sql_trans *tr, sql_schema *s, const char *func, list *args, list *res, sql_ftype type, sql_flang lang,
|
||||
const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect);
|
||||
|
||||
extern int sql_trans_drop_func(sql_trans *tr, sql_schema *s, sqlid id, int drop_action);
|
||||
extern int sql_trans_drop_all_func(sql_trans *tr, sql_schema *s, list *list_func, int drop_action);
|
||||
|
||||
extern void sql_trans_update_tables(sql_trans *tr, sql_schema *s);
|
||||
extern void sql_trans_update_schemas(sql_trans *tr);
|
||||
|
||||
extern int sql_trans_create_schema(sql_trans *tr, const char *name, sqlid auth_id, sqlid owner);
|
||||
extern int sql_trans_rename_schema(sql_trans *tr, sqlid id, const char *new_name);
|
||||
extern int sql_trans_drop_schema(sql_trans *tr, sqlid id, int drop_action);
|
||||
|
||||
sql_export int sql_trans_create_table(sql_table **tres, sql_trans *tr, sql_schema *s, const char *name, const char *sql, int tt, bit system, int persistence, int commit_action, int sz, bte properties);
|
||||
|
||||
extern int sql_trans_set_partition_table(sql_trans *tr, sql_table *t);
|
||||
extern int sql_trans_add_table(sql_trans *tr, sql_table *mt, sql_table *pt);
|
||||
extern int sql_trans_add_range_partition(sql_trans *tr, sql_table *mt, sql_table *pt, sql_subtype tpe, ptr min, ptr max, bit with_nills, int update, sql_part** err);
|
||||
extern int sql_trans_add_value_partition(sql_trans *tr, sql_table *mt, sql_table *pt, sql_subtype tpe, list* vals, bit with_nills, int update, sql_part **err);
|
||||
|
||||
extern int sql_trans_rename_table(sql_trans *tr, sql_schema *s, sqlid id, const char *new_name);
|
||||
extern int sql_trans_set_table_schema(sql_trans *tr, sqlid id, sql_schema *os, sql_schema *ns);
|
||||
extern int sql_trans_del_table(sql_trans *tr, sql_table *mt, sql_table *pt, int drop_action);
|
||||
|
||||
extern int sql_trans_drop_table(sql_trans *tr, sql_schema *s, const char *name, int drop_action);
|
||||
extern int sql_trans_drop_table_id(sql_trans *tr, sql_schema *s, sqlid id, int drop_action);
|
||||
extern BUN sql_trans_clear_table(sql_trans *tr, sql_table *t);
|
||||
extern int sql_trans_alter_access(sql_trans *tr, sql_table *t, sht access);
|
||||
|
||||
extern int sql_trans_create_column(sql_column **rcol, sql_trans *tr, sql_table *t, const char *name, sql_subtype *tpe);
|
||||
extern int sql_trans_rename_column(sql_trans *tr, sql_table *t, sqlid id, const char *old_name, const char *new_name);
|
||||
extern int sql_trans_drop_column(sql_trans *tr, sql_table *t, sqlid id, int drop_action);
|
||||
extern int sql_trans_alter_null(sql_trans *tr, sql_column *col, int isnull);
|
||||
extern int sql_trans_alter_default(sql_trans *tr, sql_column *col, char *val);
|
||||
extern int sql_trans_alter_storage(sql_trans *tr, sql_column *col, char *storage);
|
||||
extern int sql_trans_is_sorted(sql_trans *tr, sql_column *col);
|
||||
extern int sql_trans_is_unique(sql_trans *tr, sql_column *col);
|
||||
extern int sql_trans_is_duplicate_eliminated(sql_trans *tr, sql_column *col);
|
||||
extern size_t sql_trans_dist_count(sql_trans *tr, sql_column *col);
|
||||
extern int sql_trans_ranges(sql_trans *tr, sql_column *col, void **min, void **max);
|
||||
|
||||
extern void column_destroy(struct sqlstore *store, sql_column *c);
|
||||
extern void idx_destroy(struct sqlstore *store, sql_idx * i);
|
||||
extern void table_destroy(struct sqlstore *store, sql_table *t);
|
||||
|
||||
extern int sql_trans_create_ukey(sql_key **res, sql_trans *tr, sql_table *t, const char *name, key_type kt);
|
||||
extern int sql_trans_key_done(sql_trans *tr, sql_key *k);
|
||||
|
||||
extern int sql_trans_create_fkey(sql_fkey **res, sql_trans *tr, sql_table *t, const char *name, key_type kt, sql_key *rkey, int on_delete, int on_update);
|
||||
extern int sql_trans_create_kc(sql_trans *tr, sql_key *k, sql_column *c);
|
||||
extern int sql_trans_create_fkc(sql_trans *tr, sql_fkey *fk, sql_column *c);
|
||||
extern int sql_trans_drop_key(sql_trans *tr, sql_schema *s, sqlid id, int drop_action);
|
||||
|
||||
extern int sql_trans_create_idx(sql_idx **i, sql_trans *tr, sql_table *t, const char *name, idx_type it);
|
||||
extern int sql_trans_create_ic(sql_trans *tr, sql_idx *i, sql_column *c);
|
||||
extern int sql_trans_drop_idx(sql_trans *tr, sql_schema *s, sqlid id, int drop_action);
|
||||
|
||||
extern int sql_trans_create_trigger(sql_trigger **tres, sql_trans *tr, sql_table *t, const char *name,sht time, sht orientation, sht event, const char *old_name, const char *new_name,const char *condition, const char *statement);
|
||||
extern int sql_trans_drop_trigger(sql_trans *tr, sql_schema *s, sqlid id, int drop_action);
|
||||
|
||||
extern sql_sequence *create_sql_sequence(struct sqlstore *store, sql_allocator *sa, sql_schema *s, const char *name, lng start, lng min, lng max, lng inc, lng cacheinc, bit cycle);
|
||||
extern int sql_trans_create_sequence(sql_trans *tr, sql_schema *s, const char *name, lng start, lng min, lng max, lng inc, lng cacheinc, bit cycle, bit bedropped);
|
||||
extern int sql_trans_drop_sequence(sql_trans *tr, sql_schema *s, sql_sequence *seq, int drop_action);
|
||||
extern int sql_trans_alter_sequence(sql_trans *tr, sql_sequence *seq, lng min, lng max, lng inc, lng cache, bit cycle);
|
||||
extern int sql_trans_sequence_restart(sql_trans *tr, sql_sequence *seq, lng start);
|
||||
|
||||
extern sql_session * sql_session_create(struct sqlstore *store, sql_allocator *sa, int autocommit);
|
||||
extern void sql_session_destroy(sql_session *s);
|
||||
extern int sql_session_reset(sql_session *s, int autocommit);
|
||||
extern int sql_trans_begin(sql_session *s);
|
||||
extern int sql_trans_end(sql_session *s, int commit /* rollback=0, or commit=1 temporaries */);
|
||||
|
||||
extern list* sql_trans_schema_user_dependencies(sql_trans *tr, sqlid schema_id);
|
||||
extern int sql_trans_create_dependency(sql_trans *tr, sqlid id, sqlid depend_id, sql_dependency depend_type);
|
||||
extern int sql_trans_drop_dependencies(sql_trans *tr, sqlid depend_id);
|
||||
extern int sql_trans_drop_dependency(sql_trans *tr, sqlid id, sqlid depend_id, sql_dependency depend_type);
|
||||
extern list* sql_trans_get_dependencies(sql_trans *tr, sqlid id, sql_dependency depend_type, list *ignore_ids);
|
||||
extern int sql_trans_get_dependency_type(sql_trans *tr, sqlid depend_id, sql_dependency depend_type);
|
||||
extern int sql_trans_check_dependency(sql_trans *tr, sqlid id, sqlid depend_id, sql_dependency depend_type);
|
||||
extern list* sql_trans_owner_schema_dependencies(sql_trans *tr, sqlid id);
|
||||
|
||||
extern sql_table *create_sql_table(struct sqlstore *store, sql_allocator *sa, const char *name, sht type, bit system, int persistence, int commit_action, bit properties);
|
||||
extern sql_column *create_sql_column(struct sqlstore *store, sql_allocator *sa, sql_table *t, const char *name, sql_subtype *tpe);
|
||||
extern sql_key *create_sql_ukey(struct sqlstore *store, sql_allocator *sa, sql_table *t, const char *nme, key_type kt);
|
||||
extern sql_fkey *create_sql_fkey(struct sqlstore *store, sql_allocator *sa, sql_table *t, const char *nme, key_type kt, sql_key *rkey, int on_delete, int on_update );
|
||||
extern sql_key *create_sql_kc(struct sqlstore *store, sql_allocator *sa, sql_key *k, sql_column *c);
|
||||
extern sql_key * key_create_done(sql_trans *tr, sql_allocator *sa, sql_key *k);
|
||||
|
||||
extern sql_idx *create_sql_idx(struct sqlstore *store, sql_allocator *sa, sql_table *t, const char *nme, idx_type it);
|
||||
extern sql_idx *create_sql_ic(struct sqlstore *store, sql_allocator *sa, sql_idx *i, sql_column *c);
|
||||
extern sql_idx *create_sql_idx_done(sql_trans *tr, sql_idx *i);
|
||||
extern sql_func *create_sql_func(struct sqlstore *store, sql_allocator *sa, const char *func, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod,
|
||||
const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect);
|
||||
|
||||
/* for alter we need to duplicate a table */
|
||||
extern sql_table *dup_sql_table(sql_allocator *sa, sql_table *t);
|
||||
extern void drop_sql_column(sql_table *t, sqlid id, int drop_action);
|
||||
extern void drop_sql_idx(sql_table *t, sqlid id);
|
||||
extern void drop_sql_key(sql_table *t, sqlid id, int drop_action);
|
||||
|
||||
extern int sql_trans_copy_column(sql_trans *tr, sql_table *t, sql_column *c, sql_column **cres);
|
||||
extern int sql_trans_copy_key(sql_trans *tr, sql_table *t, sql_key *k, sql_key **kres);
|
||||
extern int sql_trans_copy_idx(sql_trans *tr, sql_table *t, sql_idx *i, sql_idx **ires);
|
||||
extern int sql_trans_copy_trigger(sql_trans *tr, sql_table *t, sql_trigger *tri, sql_trigger **tres);
|
||||
extern sql_table *globaltmp_instantiate(sql_trans *tr, sql_table *t);
|
||||
|
||||
#define NR_TABLE_LOCKS 64
|
||||
#define NR_COLUMN_LOCKS 512
|
||||
#define TRANSACTION_ID_BASE (1ULL<<63)
|
||||
|
||||
typedef struct sqlstore {
|
||||
int catalog_version; /* software version of the catalog */
|
||||
sql_catalog *cat; /* the catalog of persistent tables (what to do with tmp tables ?) */
|
||||
sql_schema *tmp; /* keep pointer to default (empty) tmp schema */
|
||||
MT_Lock lock; /* lock protecting concurrent writes (not reads, ie use rcu) */
|
||||
MT_Lock commit; /* protect transactions, only single commit (one wal writer) */
|
||||
MT_Lock flush; /* flush lock protecting concurrent writes (not reads, ie use rcu) */
|
||||
MT_Lock table_locks[NR_TABLE_LOCKS]; /* protecting concurrent writes to tables (storage) */
|
||||
MT_Lock column_locks[NR_COLUMN_LOCKS]; /* protecting concurrent writes to columns (storage) */
|
||||
list *active; /* list of running transactions */
|
||||
|
||||
ATOMIC_TYPE nr_active; /* count number of transactions */
|
||||
ATOMIC_TYPE lastactive; /* timestamp of last active client */
|
||||
ATOMIC_TYPE timestamp; /* timestamp counter */
|
||||
ATOMIC_TYPE transaction;/* transaction id counter */
|
||||
ATOMIC_TYPE function_counter;/* function counter used during function instantiation */
|
||||
ulng oldest;
|
||||
ulng oldest_pending;
|
||||
int readonly; /* store is readonly */
|
||||
int singleuser; /* store is for a single user only (==1 enable, ==2 single user session running) */
|
||||
int first; /* just created the db */
|
||||
int initialized; /* used during bootstrap only */
|
||||
int debug; /* debug mask */
|
||||
store_type active_type;
|
||||
list *changes; /* pending changes to cleanup */
|
||||
sql_hash *dependencies; /* pending dependencies created to cleanup */
|
||||
sql_hash *depchanges; /* pending dependencies changes to cleanup */
|
||||
list *seqchanges; /* pending sequence number changes to be add to the first commiting transaction */
|
||||
sql_hash *sequences; /* loaded store sequence numbers */
|
||||
|
||||
sql_allocator *sa; /* for now a store allocator, needs a special version with free operations (with reuse) */
|
||||
sqlid obj_id, prev_oid;
|
||||
|
||||
store_functions storage_api;
|
||||
table_functions table_api;
|
||||
logger_functions logger_api;
|
||||
void *logger; /* space to keep logging structure of storage backend */
|
||||
} sqlstore;
|
||||
|
||||
typedef enum sql_dependency_change_type {
|
||||
ddl = 1,
|
||||
dml = 2
|
||||
} sql_dependency_change_type;
|
||||
|
||||
typedef struct sql_dependency_change {
|
||||
sqlid objid; /* id of the object where the dependency was created */
|
||||
sql_dependency_change_type type; /* type of dependency */
|
||||
ulng ts; /* transaction timestamp of the dependency */
|
||||
} sql_dependency_change;
|
||||
|
||||
typedef struct sql_change {
|
||||
sql_base *obj;
|
||||
ulng ts; /* commit/rollback timestamp */
|
||||
void *data; /* data changes */
|
||||
bool committed; /* commit or rollback */
|
||||
bool handled; /* handled in commit */
|
||||
tc_log_fptr log; /* callback to log changes */
|
||||
tc_commit_fptr commit; /* callback to commit or rollback the changes */
|
||||
tc_cleanup_fptr cleanup;/* callback to cleanup changes */
|
||||
} sql_change;
|
||||
|
||||
extern void trans_add(sql_trans *tr, sql_base *b, void *data, tc_cleanup_fptr cleanup, tc_commit_fptr commit, tc_log_fptr log);
|
||||
extern int tr_version_of_parent(sql_trans *tr, ulng ts);
|
||||
|
||||
extern int sql_trans_add_predicate(sql_trans* tr, sql_column *c, unsigned int cmp, atom *r, atom *f, bool anti, bool semantics);
|
||||
extern int sql_trans_add_dependency(sql_trans* tr, sqlid id, sql_dependency_change_type tp);
|
||||
sql_export int sql_trans_add_dependency_change(sql_trans *tr, sqlid id, sql_dependency_change_type tp);
|
||||
|
||||
/* later move intop dict.h on this level */
|
||||
extern BAT *DICTenlarge(BAT *offsets, BUN cnt, BUN sz, role_t role);
|
||||
extern BAT *DICTdecompress_(BAT *o, BAT *u, role_t role);
|
||||
extern int DICTprepare4append(BAT **noffsets, BAT *vals, BAT *dict);
|
||||
extern int DICTprepare4append_vals(void **noffsets, void *vals, BUN cnt, BAT *dict);
|
||||
|
||||
extern BAT *FORdecompress_(BAT *o, lng minval, int tt, role_t role);
|
||||
extern int FORprepare4append(BAT **noffsets, BAT *vals, lng minval, int tt);
|
||||
extern int FORprepare4append_vals(void **noffsets, void *vals, BUN cnt, lng minval, int vtype, int ft);
|
||||
|
||||
#endif /*SQL_STORAGE_H */
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _SQL_STRING_H_
|
||||
#define _SQL_STRING_H_
|
||||
|
||||
#define D__SQL 16
|
||||
|
||||
#define _(String) (String)
|
||||
#define N_(String) (String)
|
||||
|
||||
extern char *mkLower(char *v);
|
||||
extern char *toLower(const char *v);
|
||||
extern char *toUpper(const char *v);
|
||||
extern char *strconcat(const char *s1, const char *s2);
|
||||
extern char *strip_extra_zeros(char *v);
|
||||
extern char *sql_strdup(char *s);
|
||||
extern char *sql_escape_str(sql_allocator *sa, char *s);
|
||||
extern const char *sql_escape_ident(sql_allocator *sa, const char *s);
|
||||
extern char *sql_message(_In_z_ _Printf_format_string_ const char *format, ...)
|
||||
__attribute__((__format__(__printf__, 1, 2)));
|
||||
extern char *sa_message(sql_allocator *sa, _In_z_ _Printf_format_string_ const char *format, ...)
|
||||
__attribute__((__format__(__printf__, 2, 3)));
|
||||
|
||||
#endif /*_SQL_STRING_H_*/
|
||||
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef SQL_SYMBOL_H
|
||||
#define SQL_SYMBOL_H
|
||||
|
||||
#include "sql_types.h"
|
||||
#include "sql_atom.h"
|
||||
#include "sql_tokens.h"
|
||||
|
||||
typedef enum symtype {
|
||||
type_int,
|
||||
type_lng,
|
||||
type_string,
|
||||
type_list,
|
||||
type_symbol,
|
||||
type_type
|
||||
} symtype;
|
||||
|
||||
typedef union symbdata {
|
||||
int i_val;
|
||||
lng l_val;
|
||||
char *sval;
|
||||
struct dlist *lval;
|
||||
struct symbol *sym;
|
||||
struct sql_subtype typeval;
|
||||
} symbdata;
|
||||
|
||||
typedef struct dnode {
|
||||
struct dnode *next;
|
||||
symbdata data;
|
||||
symtype type;
|
||||
} dnode;
|
||||
|
||||
typedef struct dlist {
|
||||
dnode *h;
|
||||
dnode *t;
|
||||
int cnt;
|
||||
} dlist;
|
||||
|
||||
extern dlist *dlist_create(sql_allocator *sa);
|
||||
extern int dlist_length(dlist *l);
|
||||
|
||||
extern dlist *dlist_append_string(sql_allocator *sa, dlist *l, const char *data);
|
||||
extern dlist *dlist_append_list(sql_allocator *sa, dlist *l, dlist *data);
|
||||
extern dlist *dlist_append_int(sql_allocator *sa, dlist *l, int data);
|
||||
extern dlist *dlist_append_lng(sql_allocator *sa, dlist *l, lng data);
|
||||
extern dlist *dlist_append_symbol(sql_allocator *sa, dlist *l, struct symbol *data);
|
||||
extern dlist *dlist_append_type(sql_allocator *sa, dlist *l, struct sql_subtype *data);
|
||||
|
||||
typedef struct symbol {
|
||||
tokens token;
|
||||
symtype type;
|
||||
symbdata data;
|
||||
} symbol;
|
||||
|
||||
typedef struct SelectNode {
|
||||
symbol s;
|
||||
|
||||
symbol *limit;
|
||||
symbol *offset;
|
||||
symbol *sample;
|
||||
symbol *seed;
|
||||
int distinct;
|
||||
int lateral;
|
||||
struct dlist *selection;
|
||||
struct dlist *into; /* ?? */
|
||||
symbol *from;
|
||||
symbol *where;
|
||||
symbol *groupby;
|
||||
symbol *having;
|
||||
symbol *orderby;
|
||||
symbol *name;
|
||||
symbol *window;
|
||||
} SelectNode;
|
||||
|
||||
typedef struct AtomNode {
|
||||
symbol s;
|
||||
struct atom *a;
|
||||
} AtomNode;
|
||||
|
||||
extern symbol *symbol_create(sql_allocator *sa, tokens token, char *data);
|
||||
extern symbol *symbol_create_list(sql_allocator *sa, tokens token, dlist *data);
|
||||
extern symbol *symbol_create_int(sql_allocator *sa, tokens token, int data);
|
||||
extern symbol *symbol_create_lng(sql_allocator *sa, tokens token, lng data);
|
||||
extern symbol *symbol_create_symbol(sql_allocator *sa, tokens token, symbol *data);
|
||||
|
||||
extern symbol *newSelectNode(sql_allocator *sa, int distinct, struct dlist *selection, struct dlist *into, symbol *from, symbol *where, symbol *groupby, symbol *having, symbol *orderby, symbol *name, symbol *limit, symbol *offset, symbol *sample, symbol *seed, symbol *window);
|
||||
|
||||
extern symbol *newAtomNode(sql_allocator *sa, atom *a);
|
||||
|
||||
#endif /* SQL_SYMBOL_H */
|
||||
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef SQL_TOKENS_H
|
||||
#define SQL_TOKENS_H
|
||||
|
||||
typedef enum tokens {
|
||||
// Please keep this list sorted for ease of maintenance
|
||||
SQL_AGGR,
|
||||
SQL_ALTER_SEQ,
|
||||
SQL_ALTER_TABLE,
|
||||
SQL_ALTER_USER,
|
||||
SQL_ANALYZE,
|
||||
SQL_AND,
|
||||
SQL_ASSIGN,
|
||||
SQL_ATOM,
|
||||
SQL_BETWEEN,
|
||||
SQL_BINCOPYFROM,
|
||||
SQL_BINOP,
|
||||
SQL_CACHE,
|
||||
SQL_CALL,
|
||||
SQL_CASE,
|
||||
SQL_CAST,
|
||||
SQL_CHARSET,
|
||||
SQL_CHECK,
|
||||
SQL_COALESCE,
|
||||
SQL_COLUMN,
|
||||
SQL_COLUMN_GROUP,
|
||||
SQL_COLUMN_OPTIONS,
|
||||
SQL_COMMENT,
|
||||
SQL_COMPARE,
|
||||
SQL_CONSTRAINT,
|
||||
SQL_COPYFROM,
|
||||
SQL_COPYLOADER,
|
||||
SQL_COPYTO,
|
||||
SQL_CREATE_FUNC,
|
||||
SQL_CREATE_INDEX,
|
||||
SQL_CREATE_ROLE,
|
||||
SQL_CREATE_SCHEMA,
|
||||
SQL_CREATE_SEQ,
|
||||
SQL_CREATE_TABLE,
|
||||
SQL_CREATE_TABLE_LOADER,
|
||||
SQL_CREATE_TRIGGER,
|
||||
SQL_CREATE_TYPE,
|
||||
SQL_CREATE_USER,
|
||||
SQL_CREATE_VIEW,
|
||||
SQL_CROSS,
|
||||
SQL_CUBE,
|
||||
SQL_CURRENT_ROW,
|
||||
SQL_CYCLE,
|
||||
SQL_DECLARE,
|
||||
SQL_DECLARE_TABLE,
|
||||
SQL_DEFAULT,
|
||||
SQL_DELETE,
|
||||
SQL_DROP_COLUMN,
|
||||
SQL_DROP_CONSTRAINT,
|
||||
SQL_DROP_DEFAULT,
|
||||
SQL_DROP_FUNC,
|
||||
SQL_DROP_INDEX,
|
||||
SQL_DROP_ROLE,
|
||||
SQL_DROP_SCHEMA,
|
||||
SQL_DROP_SEQ,
|
||||
SQL_DROP_TABLE,
|
||||
SQL_DROP_TRIGGER,
|
||||
SQL_DROP_TYPE,
|
||||
SQL_DROP_USER,
|
||||
SQL_DROP_VIEW,
|
||||
SQL_ELSE,
|
||||
SQL_ESCAPE,
|
||||
SQL_EXCEPT,
|
||||
SQL_EXECUTE,
|
||||
SQL_EXISTS,
|
||||
SQL_FILTER,
|
||||
SQL_FOLLOWING,
|
||||
SQL_FOREIGN_KEY,
|
||||
SQL_FRAME,
|
||||
SQL_FROM,
|
||||
SQL_FUNC,
|
||||
SQL_GRANT,
|
||||
SQL_GRANT_ROLES,
|
||||
SQL_GROUPBY,
|
||||
SQL_GROUPING_SETS,
|
||||
SQL_IDENT,
|
||||
SQL_IF,
|
||||
SQL_IN,
|
||||
SQL_INC,
|
||||
SQL_INDEX,
|
||||
SQL_INSERT,
|
||||
SQL_INTERSECT,
|
||||
SQL_IS_NOT_NULL,
|
||||
SQL_IS_NULL,
|
||||
SQL_JOIN,
|
||||
SQL_LIKE,
|
||||
SQL_MAXVALUE,
|
||||
SQL_MERGE,
|
||||
SQL_MERGE_MATCH,
|
||||
SQL_MERGE_NO_MATCH,
|
||||
SQL_MERGE_PARTITION,
|
||||
SQL_MINVALUE,
|
||||
SQL_MULSTMT,
|
||||
SQL_NAME,
|
||||
SQL_NEXT,
|
||||
SQL_NOP,
|
||||
SQL_NOT,
|
||||
SQL_NOT_BETWEEN,
|
||||
SQL_NOT_EXISTS,
|
||||
SQL_NOT_IN,
|
||||
SQL_NOT_LIKE,
|
||||
SQL_NOT_NULL,
|
||||
SQL_NULL,
|
||||
SQL_NULLIF,
|
||||
SQL_OP,
|
||||
SQL_OR,
|
||||
SQL_ORDERBY,
|
||||
SQL_PARAMETER,
|
||||
SQL_PARTITION_COLUMN,
|
||||
SQL_PARTITION_EXPRESSION,
|
||||
SQL_PARTITION_LIST,
|
||||
SQL_PARTITION_RANGE,
|
||||
SQL_PATH,
|
||||
SQL_PRECEDING,
|
||||
SQL_PREP,
|
||||
SQL_PRIMARY_KEY,
|
||||
SQL_PW_ENCRYPTED,
|
||||
SQL_PW_UNENCRYPTED,
|
||||
SQL_RANK,
|
||||
SQL_RENAME_COLUMN,
|
||||
SQL_RENAME_SCHEMA,
|
||||
SQL_RENAME_TABLE,
|
||||
SQL_RENAME_USER,
|
||||
SQL_RETURN,
|
||||
SQL_REVOKE,
|
||||
SQL_REVOKE_ROLES,
|
||||
SQL_ROLLUP,
|
||||
SQL_ROUTINE,
|
||||
SQL_SCHEMA,
|
||||
SQL_SELECT,
|
||||
SQL_SEQUENCE,
|
||||
SQL_SET,
|
||||
SQL_SET_TABLE_SCHEMA,
|
||||
SQL_START,
|
||||
SQL_STORAGE,
|
||||
SQL_TABLE,
|
||||
SQL_TRUNCATE,
|
||||
SQL_TYPE,
|
||||
SQL_UNION,
|
||||
SQL_UNIQUE,
|
||||
SQL_UNOP,
|
||||
SQL_UPDATE,
|
||||
SQL_USING,
|
||||
SQL_VALUES,
|
||||
SQL_VIEW,
|
||||
SQL_WHEN,
|
||||
SQL_WHILE,
|
||||
SQL_WINDOW,
|
||||
SQL_WITH,
|
||||
SQL_XMLATTRIBUTE,
|
||||
SQL_XMLCOMMENT,
|
||||
SQL_XMLCONCAT,
|
||||
SQL_XMLDOCUMENT,
|
||||
SQL_XMLELEMENT,
|
||||
SQL_XMLFOREST,
|
||||
SQL_XMLPARSE,
|
||||
SQL_XMLPI,
|
||||
SQL_XMLTEXT,
|
||||
TR_COMMIT,
|
||||
TR_MODE,
|
||||
TR_RELEASE,
|
||||
TR_ROLLBACK,
|
||||
TR_SAVEPOINT,
|
||||
TR_START
|
||||
// Please keep this list sorted for ease of maintenance
|
||||
} tokens;
|
||||
|
||||
typedef enum jt {
|
||||
jt_inner = 0,
|
||||
jt_left = 1,
|
||||
jt_right = 2,
|
||||
jt_full = 3
|
||||
} jt;
|
||||
|
||||
typedef enum {
|
||||
endian_big = 2,
|
||||
endian_little = 1,
|
||||
endian_native = 3,
|
||||
} endianness;
|
||||
|
||||
#endif
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef SQL_TYPES_H
|
||||
#define SQL_TYPES_H
|
||||
|
||||
#include "sql_mem.h"
|
||||
#include "sql_list.h"
|
||||
#include "sql_string.h"
|
||||
#include "sql_catalog.h"
|
||||
#include "sql_storage.h"
|
||||
#include "sql_backend.h"
|
||||
#include "stream.h"
|
||||
|
||||
extern list *aliases;
|
||||
extern list *types;
|
||||
extern list *funcs;
|
||||
|
||||
extern unsigned int bits2digits(unsigned int b);
|
||||
extern unsigned int digits2bits(unsigned int d);
|
||||
extern unsigned int type_digits_to_char_digits(sql_subtype *t);
|
||||
|
||||
extern int sql_type_convert(int form, int to); /* return 1, convert possible but it's a down cast, 2 convert possible can be done savely */
|
||||
extern bool is_commutative(const char *sname, const char *fnm); /* return true if commutative */
|
||||
|
||||
extern char *sql_bind_alias(const char *alias);
|
||||
|
||||
extern sql_subtype *arg_type( sql_arg *a);
|
||||
|
||||
extern int sql_find_subtype(sql_subtype *res, const char *name, unsigned int digits, unsigned int scale);
|
||||
extern sql_subtype *sql_find_numeric(sql_subtype *r, int localtype, unsigned int digits);
|
||||
|
||||
extern sql_subtype *sql_bind_subtype(sql_allocator *sa, const char *name, unsigned int digits, unsigned int scale);
|
||||
extern sql_subtype *sql_bind_localtype(const char *name);
|
||||
extern sql_subtype *sql_create_subtype(sql_allocator *sa, sql_type *t, unsigned int s, unsigned int d);
|
||||
sql_export void sql_init_subtype(sql_subtype *res, sql_type *t, unsigned int digits, unsigned int scale);
|
||||
|
||||
extern int type_cmp(sql_type *t1, sql_type *t2);
|
||||
extern int subtype_cmp(sql_subtype *t1, sql_subtype *t2);
|
||||
extern int arg_subtype_cmp(sql_arg *a, sql_subtype *t);
|
||||
extern int is_subtype(sql_subtype *t1, sql_subtype *t2);
|
||||
|
||||
extern char *sql_subtype_string(sql_allocator *sa, sql_subtype *t);
|
||||
extern char *subtype2string2(sql_allocator *sa, sql_subtype *tpe);
|
||||
|
||||
extern sql_arg *sql_create_arg(sql_allocator *sa, const char *name, sql_subtype *t, char inout);
|
||||
|
||||
extern int subfunc_cmp(sql_subfunc *f1, sql_subfunc *f2);
|
||||
extern sql_subfunc *sql_dup_subfunc(sql_allocator *sa, sql_func *f, list *ops, sql_subtype *member);
|
||||
|
||||
extern char *sql_func_imp(sql_func *f);
|
||||
extern char *sql_func_mod(sql_func *f);
|
||||
|
||||
extern void types_init(sql_allocator *sa);
|
||||
|
||||
#endif /* SQL_TYPES_H */
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef STORE_SEQ_H
|
||||
#define STORE_SEQ_H
|
||||
|
||||
#include "sql_catalog.h"
|
||||
|
||||
extern void* sequences_init(void);
|
||||
extern void sequences_exit(void);
|
||||
|
||||
extern int seq_hash(void *seq);
|
||||
extern void seq_hash_destroy(sql_hash *h);
|
||||
extern int seq_get_value(sql_store store, sql_sequence *seq, lng *val);
|
||||
extern int seq_next_value(sql_store store, sql_sequence *seq, lng *val);
|
||||
extern int seq_restart(sql_store store, sql_sequence *seq, lng start);
|
||||
|
||||
extern void log_store_sequence(sql_store store, void *seq); /* called locked */
|
||||
extern int seqbulk_next_value(sql_store store, sql_sequence *seq, lng cnt, lng* dest);
|
||||
|
||||
extern void sequences_lock(sql_store store);
|
||||
extern void sequences_unlock(sql_store store);
|
||||
|
||||
#endif /* STORE_SEQ_H */
|
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||||
*/
|
||||
|
||||
#ifndef _STREAM_H_
|
||||
#define _STREAM_H_
|
||||
|
||||
/*
|
||||
* File: stream.h
|
||||
* Auteur: Niels J. Nes
|
||||
* Date: 09-01-2001
|
||||
*
|
||||
* Version 0.1: start
|
||||
*
|
||||
* This is the general interface to input/output. Each stream will
|
||||
* contains some stream info (for now only byteorder). This is
|
||||
* required for proper conversion on different byte order platforms.
|
||||
*/
|
||||
|
||||
//#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* avoid using "#ifdef WIN32" so that this file does not need our config.h */
|
||||
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
|
||||
# ifndef LIBSTREAM
|
||||
# define stream_export extern __declspec(dllimport)
|
||||
# else
|
||||
# define stream_export extern __declspec(dllexport)
|
||||
# endif
|
||||
#else
|
||||
# define stream_export extern
|
||||
#endif
|
||||
#ifndef HAVE_HGE
|
||||
# ifdef HAVE___INT128
|
||||
# define HAVE_HGE 1
|
||||
typedef __int128 hge;
|
||||
# else
|
||||
# ifdef HAVE___INT128_T
|
||||
# define HAVE_HGE 1
|
||||
typedef __int128_t hge;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Defines to help the compiler check printf-style format arguments.
|
||||
* These defines are also in our config.h, but we repeat them here so
|
||||
* that we don't need that for this file.*/
|
||||
#ifndef __GNUC__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# ifndef __attribute__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(_MSC_VER) && !defined(_In_z_)
|
||||
# define _In_z_
|
||||
# define _Printf_format_string_
|
||||
#endif
|
||||
|
||||
#define EOT 4
|
||||
|
||||
/* fwf gets turned into a csv with these parameters */
|
||||
#define STREAM_FWF_FIELD_SEP '|'
|
||||
#define STREAM_FWF_ESCAPE '\\'
|
||||
#define STREAM_FWF_RECORD_SEP '\n'
|
||||
#define STREAM_FWF_FILLER ' '
|
||||
|
||||
typedef struct stream stream;
|
||||
|
||||
/* some os specific initialization */
|
||||
stream_export int mnstr_init(void);
|
||||
|
||||
|
||||
typedef enum mnstr_error_kind {
|
||||
MNSTR_NO__ERROR = 0,
|
||||
MNSTR_OPEN_ERROR,
|
||||
MNSTR_READ_ERROR,
|
||||
MNSTR_WRITE_ERROR,
|
||||
MNSTR_TIMEOUT,
|
||||
MNSTR_UNEXPECTED_EOF,
|
||||
} mnstr_error_kind;
|
||||
|
||||
typedef enum mnstr_flush_level {
|
||||
MNSTR_FLUSH_DATA = 1, // write all data
|
||||
MNSTR_FLUSH_ALL = 2, // write all data and also reset compression state
|
||||
} mnstr_flush_level;
|
||||
|
||||
stream_export const char *mnstr_version(void);
|
||||
|
||||
stream_export char *mnstr_error(const stream *s);
|
||||
stream_export const char* mnstr_peek_error(const stream *s);
|
||||
stream_export mnstr_error_kind mnstr_errnr(const stream *s);
|
||||
stream_export const char *mnstr_error_kind_name(mnstr_error_kind k);
|
||||
stream_export void mnstr_clearerr(stream *s);
|
||||
|
||||
/* all mnstr_readX/mnstr_writeX return
|
||||
* 0 on error
|
||||
* !0 on success
|
||||
*/
|
||||
stream_export int mnstr_readBte(stream *restrict s, int8_t *restrict val); // unused
|
||||
stream_export int mnstr_readChr(stream *restrict s, char *restrict val); // used once in gdk_logger.c
|
||||
stream_export int mnstr_writeChr(stream *s, char val); // used once in gdk_logger and mclient.c
|
||||
stream_export int mnstr_writeBte(stream *s, int8_t val); // used in sql_result.c/mapi10
|
||||
|
||||
stream_export int mnstr_readSht(stream *restrict s, int16_t *restrict val); // unused
|
||||
stream_export int mnstr_writeSht(stream *s, int16_t val); // used in sql_result.c/mapi10
|
||||
stream_export int mnstr_readInt(stream *restrict s, int *restrict val); // used in gdk
|
||||
stream_export int mnstr_writeInt(stream *s, int val); // used in gdk
|
||||
stream_export int mnstr_readLng(stream *restrict s, int64_t *restrict val); // used in gdk_logger.c
|
||||
stream_export int mnstr_writeLng(stream *s, int64_t val); // used in gdk_logger.c, sql_result.c/mapi10
|
||||
|
||||
|
||||
stream_export int mnstr_writeFlt(stream *s, float val); // sql_result.c/mapi10
|
||||
stream_export int mnstr_writeDbl(stream *s, double val); // sql_result.c/mapi10
|
||||
|
||||
#ifdef HAVE_HGE
|
||||
stream_export int mnstr_readHge(stream *restrict s, hge *restrict val); // unused
|
||||
stream_export int mnstr_writeHge(stream *s, hge val); // sql_result.c/mapi10
|
||||
#endif
|
||||
|
||||
stream_export int mnstr_readBteArray(stream *restrict s, int8_t *restrict val, size_t cnt); // unused
|
||||
stream_export int mnstr_writeBteArray(stream *restrict s, const int8_t *restrict val, size_t cnt);
|
||||
stream_export int mnstr_writeStr(stream *restrict s, const char *restrict val); // sql_result.c/mapi10
|
||||
stream_export int mnstr_readStr(stream *restrict s, char *restrict val); // unused
|
||||
|
||||
stream_export int mnstr_readShtArray(stream *restrict s, int16_t *restrict val, size_t cnt); // unused
|
||||
stream_export int mnstr_writeShtArray(stream *restrict s, const int16_t *restrict val, size_t cnt); //unused
|
||||
stream_export int mnstr_readIntArray(stream *restrict s, int *restrict val, size_t cnt); // used once in geom.c
|
||||
stream_export int mnstr_writeIntArray(stream *restrict s, const int *restrict val, size_t cnt); // used once in geom.c
|
||||
stream_export int mnstr_readLngArray(stream *restrict s, int64_t *restrict val, size_t cnt); // unused
|
||||
stream_export int mnstr_writeLngArray(stream *restrict s, const int64_t *restrict val, size_t cnt); // unused
|
||||
#ifdef HAVE_HGE
|
||||
stream_export int mnstr_readHgeArray(stream *restrict s, hge *restrict val, size_t cnt); // unused
|
||||
stream_export int mnstr_writeHgeArray(stream *restrict s, const hge *restrict val, size_t cnt); // unused
|
||||
#endif
|
||||
stream_export int mnstr_printf(stream *restrict s, _In_z_ _Printf_format_string_ const char *restrict format, ...) // USED all over
|
||||
__attribute__((__format__(__printf__, 2, 3)));
|
||||
stream_export ssize_t mnstr_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt); // USED all over
|
||||
stream_export ssize_t mnstr_readline(stream *restrict s, void *restrict buf, size_t maxcnt); // used in mclient, sql.c/mvc_export_table_wrap, bat_logger.c
|
||||
stream_export ssize_t mnstr_write(stream *restrict s, const void *restrict buf, size_t elmsize, size_t cnt); // USED all over
|
||||
stream_export void mnstr_close(stream *s);
|
||||
stream_export void mnstr_destroy(stream *s);
|
||||
stream_export int mnstr_flush(stream *s, mnstr_flush_level flush_level); // used all over
|
||||
stream_export int mnstr_fsync(stream *s); // used in gdk_logger.c, wlc.c and store.c
|
||||
stream_export int mnstr_fgetpos(stream *restrict s, fpos_t *restrict p); // unused
|
||||
stream_export int mnstr_fsetpos(stream *restrict s, fpos_t *restrict p); // unused
|
||||
stream_export char *mnstr_name(const stream *s); // used when wrapping in mclient.c
|
||||
stream_export bool mnstr_isbinary(const stream *s); // unused
|
||||
stream_export bool mnstr_get_swapbytes(const stream *s); // sql_result.c/mapi10
|
||||
stream_export void mnstr_set_bigendian(stream *s, bool bigendian); // used in mapi.c and mal_session.c
|
||||
stream_export void mnstr_settimeout(stream *s, unsigned int ms, bool (*func)(void *), void *data); // used in mapi.c and mal_session.c
|
||||
stream_export int mnstr_isalive(const stream *s); // used once in mal_interpreter.c
|
||||
stream_export bool mnstr_eof(const stream *s); // stream saw end-of-file
|
||||
|
||||
stream_export stream *open_rstream(const char *filename); // used in mclient.c, gdk_logger.c, store.c, snapshot.c
|
||||
stream_export stream *open_wstream(const char *filename); // used in gdk_logger.c and store.c
|
||||
|
||||
/* open in ascii stream in read mode */
|
||||
stream_export stream *open_rastream(const char *filename); // used 13 times
|
||||
|
||||
/* open in ascii stream in write mode*/
|
||||
stream_export stream *open_wastream(const char *filename); // used in mclient.c, mapi.c, mal_io.c, wlc.c, sql.c, wlr.c
|
||||
|
||||
stream_export void close_stream(stream *s);
|
||||
|
||||
stream_export stream *open_urlstream(const char *url); // mclient.c, future copy from remote
|
||||
|
||||
stream_export stream *file_rstream(FILE *restrict fp, bool binary, const char *restrict name); // unused
|
||||
stream_export stream *file_wstream(FILE *restrict fp, bool binary, const char *restrict name); // unused
|
||||
stream_export stream *stdin_rastream(void);
|
||||
stream_export stream *stdout_wastream(void);
|
||||
stream_export stream *stderr_wastream(void);
|
||||
|
||||
stream_export stream *xz_stream(stream *inner, int preset);
|
||||
stream_export stream *gz_stream(stream *inner, int preset);
|
||||
stream_export stream *bz2_stream(stream *inner, int preset);
|
||||
stream_export stream *lz4_stream(stream *inner, int preset);
|
||||
stream_export stream *compressed_stream(stream *inner, int preset);
|
||||
|
||||
stream_export FILE *getFile(stream *s); // gdk_logger.c progress messages
|
||||
stream_export int getFileNo(stream *s); /* fileno(getFile(s)) */ // mclient.c, gdk_logger.c progress messages
|
||||
stream_export size_t getFileSize(stream *s); // mal_import.c, sql_scenario.c, wlr.c, store.c, bat_logger.c
|
||||
|
||||
stream_export stream *iconv_rstream(stream *restrict ss, const char *restrict charset, const char *restrict name); // mclient.c stdin
|
||||
stream_export stream *iconv_wstream(stream *restrict ss, const char *restrict charset, const char *restrict name); // mclient.c stdout
|
||||
|
||||
typedef struct buffer {
|
||||
char *buf;
|
||||
size_t pos;
|
||||
size_t len;
|
||||
} buffer;
|
||||
|
||||
stream_export void buffer_init(buffer *restrict b, char *restrict buf, size_t size); // used in many places
|
||||
stream_export buffer *buffer_create(size_t size); // used in sql_gencode.c and store.c/snapshot
|
||||
stream_export char *buffer_get_buf(buffer *b);
|
||||
stream_export void buffer_destroy(buffer *b);
|
||||
|
||||
stream_export stream *buffer_rastream(buffer *restrict b, const char *restrict name); // used in many places
|
||||
stream_export stream *buffer_wastream(buffer *restrict b, const char *restrict name); // sql_gencode.c
|
||||
stream_export buffer *mnstr_get_buffer(stream *s);
|
||||
|
||||
/* note, the size is fixed to 8K, you cannot simply change it to any
|
||||
* value */
|
||||
#define BLOCK (8 * 1024 - 2)
|
||||
|
||||
/* Block stream is a stream which sends data in blocks of a known size
|
||||
* (BLOCK size or dynamically changed using CHANGE_BLOCK_SIZE msg).
|
||||
*
|
||||
* A block is written once more than BLOCK size data has been written
|
||||
* using the write commands or when the flush command is sent.
|
||||
*
|
||||
* All full blocks together with a single not full block form a major
|
||||
* block. Major blocks can be used to synchronize the communication.
|
||||
* Example server sends some reply, ie a major block consisting of
|
||||
* various minor blocks. The header of the major block can contain
|
||||
* special info which the client can interpret.
|
||||
*
|
||||
* Each read attempt tries to return the number of bytes. Once a lower
|
||||
* number of bytes can be read the end of the major block is
|
||||
* found. The next read will then start with a new major block.
|
||||
*/
|
||||
stream_export stream *block_stream(stream *s); // mapi.c, mal_mapi.c, client.c, merovingian
|
||||
stream_export bool isa_block_stream(const stream *s); // mapi.c, mal_client.c, remote.c, sql_scenario.c/sqlReader, sql_scan.c
|
||||
stream_export stream *bs_stream(stream *s); // unused
|
||||
stream_export void set_prompting(stream *block_stream, const char *prompt, stream *prompt_stream);
|
||||
|
||||
|
||||
typedef enum {
|
||||
PROTOCOL_AUTO = 0, // unused
|
||||
PROTOCOL_9 = 1, // mal_mapi.c, mal_client.c;
|
||||
PROTOCOL_COLUMNAR = 3 // sql_result.c
|
||||
} protocol_version;
|
||||
|
||||
typedef enum {
|
||||
COMPRESSION_NONE = 0, // mal_mapi.c
|
||||
COMPRESSION_SNAPPY = 1, // mcrypt.c, mal_mapi.c
|
||||
COMPRESSION_LZ4 = 2, // same
|
||||
COMPRESSION_AUTO = 255 // never used
|
||||
} compression_method;
|
||||
|
||||
stream_export stream *block_stream2(stream *s, size_t bufsiz, compression_method comp); // mal_mapi.c
|
||||
stream_export int bs2_resizebuf(stream *ss, size_t bufsiz); // sql_result.c
|
||||
stream_export buffer bs2_buffer(stream *s); // sql_result.c
|
||||
stream_export void bs2_setpos(stream *ss, size_t pos); // sql_result.c
|
||||
|
||||
|
||||
/* read block of data including the end of block marker */
|
||||
stream_export ssize_t mnstr_read_block(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt);
|
||||
// used in mapi.c ,mal_mapi,c, merovingian/{client.c,controlrunner.c,control.c}
|
||||
|
||||
typedef struct bstream {
|
||||
stream *s;
|
||||
char *buf;
|
||||
size_t size; /* size of buf */
|
||||
size_t pos; /* the data cursor (ie read until pos) */
|
||||
size_t len; /* len of the data (<= size) */
|
||||
size_t mode; /* 0 line mode else size for block mode */
|
||||
bool eof;
|
||||
} bstream;
|
||||
|
||||
stream_export bstream *bstream_create(stream *rs, size_t chunk_size); // used all over
|
||||
stream_export void bstream_destroy(bstream *s); // all over
|
||||
stream_export ssize_t bstream_read(bstream *s, size_t size); // tablet.c, tokenizer.c
|
||||
stream_export ssize_t bstream_next(bstream *s); // all over
|
||||
|
||||
/* Callback stream is a stream where the read and write functions are
|
||||
* provided by the caller. close and destroy are also provided. The
|
||||
* private pointer is passed on to the callback functions when they
|
||||
* are invoked. */
|
||||
stream_export stream *callback_stream(
|
||||
void *restrict priv,
|
||||
ssize_t (*read)(void *restrict priv, void *restrict buf, size_t elmsize, size_t cnt),
|
||||
ssize_t (*write)(void *restrict priv, const void *restrict buf, size_t elmsize, size_t cnt),
|
||||
void (*close)(void *priv),
|
||||
void (*destroy)(void *priv),
|
||||
const char *restrict name); // used in mclient.c, for readline
|
||||
|
||||
stream_export stream *stream_blackhole_create(void); // never used
|
||||
|
||||
stream_export stream *stream_fwf_create(stream *restrict s, size_t num_fields, size_t *restrict widths, char filler); // sql.c
|
||||
|
||||
|
||||
stream_export stream *create_text_stream(stream *s);
|
||||
|
||||
#endif /*_STREAM_H_*/
|
@ -1 +1 @@
|
||||
Subproject commit 0d0ec214297a3e46947cead37f887eb480043419
|
||||
Subproject commit 6f49544835a35915e1561a2e6581ee9ac0759381
|
@ -1,3 +1,3 @@
|
||||
#ifdef _MSCVER
|
||||
#if defined (_MSCVER) && defined(__cplusplus)
|
||||
#include "pch.hpp"
|
||||
#endif
|
||||
|
@ -0,0 +1,6 @@
|
||||
LOAD MODULE FROM "./libdraw.so" FUNCTIONS (draw(X:vecint, y:vecint) -> bool);
|
||||
create table t(a int, b int);
|
||||
|
||||
insert into t(a, b) values (6,4), (8,8), (9,1), (5,6), (10,8), (1, 9), (4, 11);
|
||||
|
||||
select draw(a, b) from t;
|
@ -0,0 +1,11 @@
|
||||
def validate(y_hat):
|
||||
y = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1]
|
||||
|
||||
import math
|
||||
errs = [yy - int(yyh) for yy, yyh in zip(y, y_hat.split(' '))]
|
||||
err = 0
|
||||
for e in errs:
|
||||
err += abs(e)
|
||||
|
||||
err = err/len(y)
|
||||
return err
|
Loading…
Reference in new issue