Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ lib*.pc
/dist

# emscripten build excludes
*.js
*.data
*.cjs
pg_config.mjs
*.wasm
pglite.data
pglite.js
Expand Down
26 changes: 20 additions & 6 deletions build-pglite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,25 @@ else
echo "$CONFIG_STATUS exists and is newer than $REF_FILE. ./configure will NOT be run."
fi

# we define here "all" emscripten flags in order to allow native builds (like libpglite)
EXPORTED_RUNTIME_METHODS="addFunction,removeFunction,FS,MEMFS"
PGLITE_EMSCRIPTEN_FLAGS="-sWASM_BIGINT \
-sSUPPORT_LONGJMP=emscripten \
-sFORCE_FILESYSTEM=1 \
-sNO_EXIT_RUNTIME=0 -sENVIRONMENT=node,web,worker \
-sMAIN_MODULE=2 -sMODULARIZE=1 -sEXPORT_ES6=1 \
-sEXPORT_NAME=Module -sALLOW_TABLE_GROWTH -sALLOW_MEMORY_GROWTH \
-sERROR_ON_UNDEFINED_SYMBOLS=0 \
-sEXPORTED_RUNTIME_METHODS=$EXPORTED_RUNTIME_METHODS \
-sTOTAL_MEMORY=32MB \
--embed-file $(pwd)/other/PGPASSFILE@/home/web_user/.pgpass"

# Step 1: configure the project
if [ "$RUN_CONFIGURE" = true ]; then
LDFLAGS="-sWASM_BIGINT -sUSE_PTHREADS=0" CFLAGS="${PGLITE_CFLAGS} -sWASM_BIGINT -fpic -sENVIRONMENT=node,web,worker -sSUPPORT_LONGJMP=emscripten -Wno-declaration-after-statement -Wno-macro-redefined -Wno-unused-function -Wno-missing-prototypes -Wno-incompatible-pointer-types" emconfigure ./configure ac_cv_exeext=.cjs --disable-spinlocks --disable-largefile --without-llvm --without-pam --disable-largefile --with-openssl=no --without-readline --without-icu --with-includes=$INSTALL_PREFIX/include:$INSTALL_PREFIX/include/libxml2 --with-libraries=$INSTALL_PREFIX/lib --with-uuid=ossp --with-zlib --with-libxml --with-libxslt --with-template=emscripten --prefix=$INSTALL_FOLDER || { echo 'error: emconfigure failed' ; exit 11; }
LDFLAGS="-sWASM_BIGINT -sUSE_PTHREADS=0" \
LDFLAGS_SL="-sSIDE_MODULE=1" \
LDFLAGS_EX=$PGLITE_EMSCRIPTEN_FLAGS \
CFLAGS="${PGLITE_CFLAGS} -sWASM_BIGINT -fpic -sENVIRONMENT=node,web,worker -sSUPPORT_LONGJMP=emscripten -Wno-declaration-after-statement -Wno-macro-redefined -Wno-unused-function -Wno-missing-prototypes -Wno-incompatible-pointer-types" emconfigure ./configure ac_cv_exeext=.js --host aarch64-unknown-linux-gnu --disable-spinlocks --disable-largefile --without-llvm --without-pam --disable-largefile --with-openssl=no --without-readline --without-icu --with-includes=$INSTALL_PREFIX/include:$INSTALL_PREFIX/include/libxml2:$(pwd)/pglite/includes --with-libraries=$INSTALL_PREFIX/lib --with-uuid=ossp --with-zlib --with-libxml --with-libxslt --with-template=emscripten --prefix=$INSTALL_FOLDER || { echo 'error: emconfigure failed' ; exit 11; }
else
echo "Warning: configure has not been run because RUN_CONFIGURE=${RUN_CONFIGURE}"
fi
Expand All @@ -49,7 +65,7 @@ emmake make PORTNAME=emscripten -j || { echo 'error: emmake make PORTNAME=emscri
emmake make PORTNAME=emscripten install || { echo 'error: emmake make PORTNAME=emscripten install' ; exit 22; }

# Step 3.1: make all contrib extensions - do not install
emmake make PORTNAME=emscripten LDFLAGS_SL="-sSIDE_MODULE=1" -C contrib/ -j || { echo 'error: emmake make PORTNAME=emscripten -C contrib/ -j' ; exit 31; }
emmake make PORTNAME=emscripten -C contrib/ -j || { echo 'error: emmake make PORTNAME=emscripten -C contrib/ -j' ; exit 31; }
# Step 3.2: make dist contrib extensions - this will create an archive for each extension
emmake make PORTNAME=emscripten -C contrib/ dist || { echo 'error: emmake make PORTNAME=emscripten -C contrib/ dist' ; exit 32; }
# the above will also create a file with the imports that each extension needs - we pass these as input in the next step for emscripten to keep alive
Expand All @@ -58,20 +74,18 @@ emmake make PORTNAME=emscripten -C contrib/ dist || { echo 'error: emmake make P
SAVE_PATH=$PATH
PATH=$PATH:$INSTALL_FOLDER/bin
emmake make OPTFLAGS="" PORTNAME=emscripten -j -C pglite || { echo 'error: emmake make OPTFLAGS="" PORTNAME=emscripten -j -C pglite' ; exit 41; }
emmake make OPTFLAGS="" PORTNAME=emscripten LDFLAGS_SL="-sSIDE_MODULE=1" -C pglite/ dist || { echo 'error: make OPTFLAGS="" PORTNAME=emscripten LDFLAGS_SL="-sSIDE_MODULE=1" -C pglite/ dist ' ; exit 42; }
emmake make OPTFLAGS="" PORTNAME=emscripten -C pglite/ dist || { echo 'error: make OPTFLAGS="" PORTNAME=emscripten -C pglite/ dist ' ; exit 42; }
PATH=$SAVE_PATH

# Step 5: make and install pglite
# we define here "all" emscripten flags in order to allow native builds (like libpglite)
EXPORTED_RUNTIME_METHODS="MEMFS,IDBFS,FS,setValue,getValue,UTF8ToString,stringToNewUTF8,stringToUTF8OnStack,addFunction,removeFunction"
PGLITE_EMSCRIPTEN_FLAGS="-sWASM_BIGINT \
-sSUPPORT_LONGJMP=emscripten \
-sFORCE_FILESYSTEM=1 \
-sNO_EXIT_RUNTIME=1 -sENVIRONMENT=node,web,worker \
-sMAIN_MODULE=2 -sMODULARIZE=1 -sEXPORT_ES6=1 \
-sEXPORT_NAME=Module -sALLOW_TABLE_GROWTH -sALLOW_MEMORY_GROWTH \
-sERROR_ON_UNDEFINED_SYMBOLS=1 \
-sERROR_ON_UNDEFINED_SYMBOLS=0 \
-sEXPORTED_RUNTIME_METHODS=$EXPORTED_RUNTIME_METHODS"

# Building pglite itself needs to be the last step because of the PRELOAD_FILES parameter (a list of files and folders) need to be available.
PGLITE_CFLAGS="$PGLITE_CFLAGS $PGLITE_EMSCRIPTEN_FLAGS" emmake make PORTNAME=emscripten -j -C src/backend/ install-pglite || { echo 'emmake make OPTFLAGS="" PORTNAME=emscripten -j -C pglite' ; exit 51; }
21 changes: 0 additions & 21 deletions pglite-wasm/interactive_one.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,6 @@ volatile sigjmp_buf local_sigjmp_buf;
// track back how many ex raised in steps of the loop until sucessfull clear_error
volatile int canary_ex = 0;

// read FROM JS
// (i guess return number of bytes written)
// ssize_t pglite_read(/* ignored */ int socket, void *buffer, size_t length,/* ignored */ int flags,/* ignored */ void *address,/* ignored */ socklen_t *address_len);
//typedef ssize_t (*pglite_read_t)(/* ignored */ int socket, void *buffer, size_t length,/* ignored */ int flags,/* ignored */ void *address,/* ignored */ unsigned int *address_len);
typedef ssize_t (*pglite_read_t)(void *buffer, size_t max_length);
extern pglite_read_t pglite_read;

// write TO JS
// (i guess return number of bytes read)
// ssize_t pglite_write(/* ignored */ int sockfd, const void *buf, size_t len, /* ignored */ int flags);
// typedef ssize_t (*pglite_write_t)(/* ignored */ int sockfd, const void *buf, size_t len, /* ignored */ int flags);
typedef ssize_t (*pglite_write_t)(void *buffer, size_t length);
extern pglite_write_t pglite_write;

__attribute__((export_name("set_read_write_cbs")))
void
set_read_write_cbs(pglite_read_t read_cb, pglite_write_t write_cb) {
pglite_read = read_cb;
pglite_write = write_cb;
}

extern void AbortTransaction(void);
extern void CleanupTransaction(void);
extern void ClientAuthentication(Port *port);
Expand Down
88 changes: 88 additions & 0 deletions pglite/includes/pglite-comm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#if defined(__EMSCRIPTEN__)

#ifndef PGLITE_COMM_H
#define PGLITE_COMM_H

#include <emscripten/emscripten.h>

volatile int querylen = 0;
volatile FILE* queryfp = NULL;

// read FROM JS
// (i guess return number of bytes written)
// ssize_t pglite_read(/* ignored */ int socket, void *buffer, size_t length,/* ignored */ int flags,/* ignored */ void *address,/* ignored */ socklen_t *address_len);
//typedef ssize_t (*pglite_read_t)(/* ignored */ int socket, void *buffer, size_t length,/* ignored */ int flags,/* ignored */ void *address,/* ignored */ unsigned int *address_len);
typedef ssize_t (*pglite_read_t)(void *buffer, size_t max_length);
pglite_read_t pglite_read;

// write TO JS
// (i guess return number of bytes read)
// ssize_t pglite_write(/* ignored */ int sockfd, const void *buf, size_t len, /* ignored */ int flags);
// typedef ssize_t (*pglite_write_t)(/* ignored */ int sockfd, const void *buf, size_t len, /* ignored */ int flags);
typedef ssize_t (*pglite_write_t)(void *buffer, size_t length);
pglite_write_t pglite_write;

__attribute__((export_name("set_read_write_cbs")))
void
set_read_write_cbs(pglite_read_t read_cb, pglite_write_t write_cb) {
pglite_read = read_cb;
pglite_write = write_cb;
}

int EMSCRIPTEN_KEEPALIVE fcntl(int __fd, int __cmd, ...) {
// dummy
return 0;
}

int EMSCRIPTEN_KEEPALIVE setsockopt(int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen) {
// dummy
return 0;
}

int EMSCRIPTEN_KEEPALIVE getsockopt(int __fd, int __level, int __optname,
void *__restrict __optval,
socklen_t *__restrict __optlen) {
// dummy
return 0;
}

int EMSCRIPTEN_KEEPALIVE getsockname(int __fd, struct sockaddr * __addr,
socklen_t *__restrict __len) {
// dummy
return 0;
}

ssize_t EMSCRIPTEN_KEEPALIVE
recv(int __fd, void *__buf, size_t __n, int __flags) {
ssize_t got = pglite_read(__buf, __n);
return got;
}

ssize_t EMSCRIPTEN_KEEPALIVE
send(int __fd, const void *__buf, size_t __n, int __flags) {
ssize_t wrote = pglite_write(__buf, __n);
return wrote;
}

int EMSCRIPTEN_KEEPALIVE
connect(int socket, const struct sockaddr *address, socklen_t address_len) {
// dummy
return 0;
}

struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};

int EMSCRIPTEN_KEEPALIVE
poll(struct pollfd fds[], ssize_t nfds, int timeout) {
// dummy
return nfds;
}

#endif

#endif // ifndef PGLITE_COMM_H
4 changes: 4 additions & 0 deletions src/backend/libpq/be-secure.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include "tcop/tcopprot.h"
#include "utils/wait_event.h"

#if defined(__EMSCRIPTEN__)
#include "pglite-comm.h"
#endif

char *ssl_library;
char *ssl_cert_file;
char *ssl_key_file;
Expand Down
51 changes: 0 additions & 51 deletions src/backend/libpq/pqcomm.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@
#include "utils/guc_hooks.h"
#include "utils/memutils.h"

#if defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
#endif

/*
* Cope with the various platform-specific ways to spell TCP keepalive socket
* options. This doesn't cover Windows, which as usual does its own thing.
Expand Down Expand Up @@ -129,53 +125,6 @@ static size_t PqSendStart; /* Next index to send a byte in PqSendBuffer */
static char PqRecvBuffer[PQ_RECV_BUFFER_SIZE];
static int PqRecvPointer; /* Next index to read a byte from PqRecvBuffer */
static int PqRecvLength; /* End of data available in PqRecvBuffer */
#if defined(__EMSCRIPTEN__) || defined(__wasi__)
volatile int querylen = 0;
volatile FILE* queryfp = NULL;

typedef ssize_t (*pglite_read_t)(void *buffer, size_t max_length);
extern pglite_read_t pglite_read;

typedef ssize_t(*pglite_write_t)(void *buffer, size_t length);
extern pglite_write_t pglite_write;

int EMSCRIPTEN_KEEPALIVE fcntl(int __fd, int __cmd, ...) {
// dummy
return 0;
}

int EMSCRIPTEN_KEEPALIVE setsockopt(int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen) {
// dummy
return 0;
}

int EMSCRIPTEN_KEEPALIVE getsockopt(int __fd, int __level, int __optname,
void *__restrict __optval,
socklen_t *__restrict __optlen) {
// dummy
return 0;
}

int EMSCRIPTEN_KEEPALIVE getsockname(int __fd, struct sockaddr * __addr,
socklen_t *__restrict __len) {
// dummy
return 0;
}

ssize_t EMSCRIPTEN_KEEPALIVE
recv(int __fd, void *__buf, size_t __n, int __flags) {
ssize_t got = pglite_read(__buf, __n);
return got;
}

ssize_t EMSCRIPTEN_KEEPALIVE
send(int __fd, const void *__buf, size_t __n, int __flags) {
ssize_t wrote = pglite_write(__buf, __n);
return wrote;
}

#endif

/*
* Message status
Expand Down
6 changes: 0 additions & 6 deletions src/backend/tcop/postgres.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,6 @@ int restrict_nonsystem_relation_kind;

#if (defined(__EMSCRIPTEN__) || defined(__wasi__))
bool quote_all_identifiers = false;

typedef ssize_t (*pglite_read_t)(void *buffer, size_t max_length);
pglite_read_t pglite_read = NULL;

typedef ssize_t(*pglite_write_t)(void *buffer, size_t length);
pglite_write_t pglite_write = NULL;
#endif // WASM


Expand Down
12 changes: 5 additions & 7 deletions src/bin/pg_config/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ OBJS = \

all:
ifeq ($(PORTNAME), emscripten)
all: pg_config pg_config_sh
all: pg_config
else
all: pg_config
endif
Expand All @@ -31,18 +31,16 @@ pg_config: $(OBJS) | submake-libpgport

# the emscripten build generates multiple "runnable" files (.cjs/.mjs + .wasm)
# but other postgres tools expect exacly 'pg_config' as an executable
# the following rule creates a node script that calls the pg_config.cjs/.mjs
# we create a pg_config link to run_pg_config.mjs, which in turn calls pg_config.cjs/.mjs
# pg_config.wasm is implicitly expected to be in the same folder
pg_config_sh: pg_config
echo "#!/usr/bin/env node" > pg_config
echo 'require("./pg_config$(X)")' >> pg_config
chmod +x pg_config

install: all installdirs
$(INSTALL_SCRIPT) pg_config$(X) '$(DESTDIR)$(bindir)/pg_config$(X)'
ifeq ($(PORTNAME), emscripten)
$(INSTALL_PROGRAM) pg_config.wasm '$(DESTDIR)$(bindir)/pg_config.wasm'
$(INSTALL_PROGRAM) pg_config '$(DESTDIR)$(bindir)/pg_config'
$(INSTALL_PROGRAM) pg_config$(X) '$(DESTDIR)$(bindir)/pg_config.mjs'
$(INSTALL_PROGRAM) run_pg_config.mjs '$(DESTDIR)$(bindir)/run_pg_config.mjs'
ln -sf '$(DESTDIR)$(bindir)/run_pg_config.mjs' '$(DESTDIR)$(bindir)/pg_config'
endif

installdirs:
Expand Down
12 changes: 12 additions & 0 deletions src/bin/pg_config/run_pg_config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env node
import Module from "./pg_config.mjs";

// If the module has a `main()` (or similar) method, call it:
if (typeof Module.main === "function") {
await Module.main();
} else if (typeof Module === "function") {
// If it's a callable function/class, instantiate or run it
await Module();
} else {
console.error("⚠️ Module has no callable entry point");
}
2 changes: 1 addition & 1 deletion src/bin/pg_dump/pg_backup_db.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ ExecuteSqlQuery(Archive *AHX, const char *query, ExecStatusType status)
ArchiveHandle *AH = (ArchiveHandle *) AHX;
PGresult *res;

res = PQexec(AH->connection, query); printf("# 295:" __FILE__ ": PQexec fail == %d q=%s\r\n", PQresultStatus(res) != status, query );
res = PQexec(AH->connection, query);
if (PQresultStatus(res) != status)
die_on_query_failure(AH, query);
return res;
Expand Down
10 changes: 8 additions & 2 deletions src/bin/pg_dump/pg_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ int sdk_fd_seek(int fd, int offset,int whence, unsigned long long *retptr) {
#endif
#endif

#if defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
#endif

typedef struct
{
Oid roleoid; /* role's OID */
Expand Down Expand Up @@ -366,8 +370,10 @@ static TableInfo *getRootTableInfo(const TableInfo *tbinfo);
static bool forcePartitionRootLoad(const TableInfo *tbinfo);
static void read_dump_filters(const char *filename, DumpOptions *dopt);


int
int
#if defined(__EMSCRIPTEN__)
EMSCRIPTEN_KEEPALIVE
#endif
main(int argc, char **argv)
{
int c;
Expand Down
4 changes: 4 additions & 0 deletions src/interfaces/libpq/fe-secure.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
#include "libpq-fe.h"
#include "libpq-int.h"

#if defined(__EMSCRIPTEN__)
#include "pglite-comm.h"
#endif

/*
* Macros to handle disabling and then restoring the state of SIGPIPE handling.
* On Windows, these are all no-ops since there's no SIGPIPEs.
Expand Down