diff --git a/.gitignore b/.gitignore index 794e35b73cb..118a6c3873a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Global excludes across all subdirectories *.o +*.wasm *.obj *.bc *.so diff --git a/src/Makefile.shlib b/src/Makefile.shlib index 29a7f6d38c8..bd10be44651 100644 --- a/src/Makefile.shlib +++ b/src/Makefile.shlib @@ -122,13 +122,13 @@ ifeq ($(PORTNAME), darwin) ifneq ($(SO_MAJOR_VERSION), 0) version_link = -compatibility_version $(SO_MAJOR_VERSION) -current_version $(SO_MAJOR_VERSION).$(SO_MINOR_VERSION) endif - LINK.shared = $(COMPILER) -dynamiclib -install_name '$(libdir)/lib$(NAME).$(SO_MAJOR_VERSION)$(DLSUFFIX)' $(version_link) $(exported_symbols_list) -multiply_defined suppress + LINK.shared = $(COMPILER) -dynamiclib -install_name '$(libdir)/lib$(NAME).$(SO_MAJOR_VERSION)$(DLSUFFIX)' $(version_link) $(exported_symbols_list) shlib = lib$(NAME).$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)$(DLSUFFIX) shlib_major = lib$(NAME).$(SO_MAJOR_VERSION)$(DLSUFFIX) else # loadable module DLSUFFIX = .so - LINK.shared = $(COMPILER) -bundle -multiply_defined suppress + LINK.shared = $(COMPILER) -bundle endif BUILD.exports = $(AWK) '/^[^\#]/ {printf "_%s\n",$$1}' $< >$@ exports_file = $(SHLIB_EXPORTS:%.txt=%.list) diff --git a/src/backend/Makefile b/src/backend/Makefile index 0da848b1fd3..0f807d4fc02 100644 --- a/src/backend/Makefile +++ b/src/backend/Makefile @@ -62,8 +62,16 @@ ifneq ($(PORTNAME), cygwin) ifneq ($(PORTNAME), win32) ifneq ($(PORTNAME), aix) +OBJS += \ + $(top_builddir)/src/pl/plpgsql/src/pl_comp.o \ + $(top_builddir)/src/pl/plpgsql/src/pl_exec.o \ + $(top_builddir)/src/pl/plpgsql/src/pl_funcs.o \ + $(top_builddir)/src/pl/plpgsql/src/pl_gram.o \ + $(top_builddir)/src/pl/plpgsql/src/pl_handler.o \ + $(top_builddir)/src/pl/plpgsql/src/pl_scanner.o + postgres: $(OBJS) - $(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LDFLAGS_EX) $(export_dynamic) $(LIBS) -o $@ + $(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LDFLAGS_EX) $(export_dynamic) $(LIBS) -sALLOW_MEMORY_GROWTH=1 -sFORCE_FILESYSTEM=1 -lnodefs.js -lproxyfs.js -lidbfs.js -o $@ endif endif diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 986a776bbd5..4c27de9b915 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -1197,6 +1197,8 @@ CheckPointLogicalRewriteHeap(void) struct dirent *mapping_de; char path[MAXPGPATH + 20]; + return; + /* * We start of with a minimum of the last redo pointer. No new decoding * slot will start before that, so that's a safe upper bound for removal. diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 94ab5ca0954..06e0a5f0bc7 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -346,6 +346,9 @@ AuxiliaryProcessMain(int argc, char *argv[]) proc_exit(1); } + checkDataDir(); + ChangeToDataDir(); + /* * Validate we have been given a reasonable-looking DataDir and change * into it (if under postmaster, should be done already). @@ -501,6 +504,25 @@ BootstrapModeMain(void) Assert(!IsUnderPostmaster); Assert(IsBootstrapProcessingMode()); + printf("NAMEDATALEN = %d\n", NAMEDATALEN); + printf("SIZEOF_POINTER = %d\n", (int) sizeof(Pointer)); + printf("ALIGNOF_POINTER = %s\n", (sizeof(Pointer) == 4) ? "i" : "d"); + printf("FLOAT8PASSBYVAL = %s\n", FLOAT8PASSBYVAL ? "true" : "false"); + // Results on wasm: + // NAMEDATALEN = 64 + // SIZEOF_POINTER = 4 + // ALIGNOF_POINTER = i + // FLOAT8PASSBYVAL = false + // Trying to use following for other bki substitutions: + // POSTGRES = 'postgres' + // ENCODING = 6 // PG_UTF8 + // LC_COLLATE = 'C' + // LC_CTYPE = 'en_US.UTF-8' + // + + // manually substituted and embedded during build: + FILE *in = fopen("/usr/local/pgsql/share/postgres_wasm.bki","r"); + /* * To ensure that src/common/link-canary.c is linked into the backend, we * must call it from somewhere. Here is as good as anywhere. @@ -526,6 +548,8 @@ BootstrapModeMain(void) * Process bootstrap input. */ StartTransactionCommand(); + + boot_yyset_in(in); boot_yyparse(); CommitTransactionCommand(); diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb56825..1d3e2602220 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -144,6 +144,9 @@ #include "utils/snapmgr.h" #include "utils/timestamp.h" +#ifdef EMSCRIPTEN +#include +#endif /* * Maximum size of a NOTIFY payload, including terminating NULL. This @@ -1676,6 +1679,12 @@ SignalBackends(void) BackendId *ids; int count; + #ifdef EMSCRIPTEN + // With PGlite we call HandleNotifyInterrupt() directly + HandleNotifyInterrupt(); + return; + #endif + /* * Identify backends that we need to signal. We don't want to send * signals while holding the NotifyQueueLock, so this loop just builds a diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 8cc23ef7fb4..97a98b66b94 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -1864,6 +1864,9 @@ ident_inet(hbaPort *port) static int auth_peer(hbaPort *port) { + + return STATUS_OK; + uid_t uid; gid_t gid; #ifndef WIN32 diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 89a5f901aa0..724bd685987 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -83,6 +83,10 @@ #include "utils/guc.h" #include "utils/memutils.h" +#ifdef EMSCRIPTEN +#include +#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. @@ -149,11 +153,28 @@ static void socket_putmessage_noblock(char msgtype, const char *s, size_t len); static int internal_putbytes(const char *s, size_t len); static int internal_flush(void); +static void emscripten_comm_reset(void); +static int emscripten_flush(void); +static int emscripten_flush_if_writable(void); +static bool emscripten_is_send_pending(void); +static int emscripten_putmessage(char msgtype, const char *s, size_t len); +static void emscripten_putmessage_noblock(char msgtype, const char *s, size_t len); + #ifdef HAVE_UNIX_SOCKETS static int Lock_AF_UNIX(const char *unixSocketDir, const char *unixSocketPath); static int Setup_AF_UNIX(const char *sock_path); #endif /* HAVE_UNIX_SOCKETS */ +#ifdef EMSCRIPTEN +static const PQcommMethods PqCommSocketMethods = { + emscripten_comm_reset, + emscripten_flush, + emscripten_flush_if_writable, + emscripten_is_send_pending, + emscripten_putmessage, + emscripten_putmessage_noblock +}; +#else static const PQcommMethods PqCommSocketMethods = { socket_comm_reset, socket_flush, @@ -162,12 +183,97 @@ static const PQcommMethods PqCommSocketMethods = { socket_putmessage, socket_putmessage_noblock }; +#endif const PQcommMethods *PqCommMethods = &PqCommSocketMethods; WaitEventSet *FeBeWaitSet; +/* -------------------------------- + * Emscripten implementation + * -------------------------------- + */ + +static StringInfoData emscripten_buffer; +static bool emscripten_buffer_is_initialized = false; +static bool emscripten_buffer_busy = false; + +#ifdef EMSCRIPTEN +EM_JS(void, emscripten_dispatch_result, (char *res, int len), { + // Dispatch the result to JS land + if (!Module.eventTarget) return; + var heapBytes = new Uint8Array(Module.HEAPU8.buffer, res, len); + var resultBytes = new Uint8Array(heapBytes); + Module.eventTarget.dispatchEvent(new Module.Event("result", { + detail: resultBytes + })); +}); +#endif + +static void emscripten_init_buffer(void) { + if (!emscripten_buffer_is_initialized) { + initStringInfo(&emscripten_buffer); + emscripten_buffer_is_initialized = true; + } +} + +static void emscripten_comm_reset(void) { + if (emscripten_buffer_is_initialized) { + resetStringInfo(&emscripten_buffer); + } else { + emscripten_init_buffer(); + } +} + +static int emscripten_flush(void) { + if (emscripten_buffer.len > 0) { + emscripten_dispatch_result(emscripten_buffer.data, emscripten_buffer.len); + resetStringInfo(&emscripten_buffer); + } + return 0; +} + +static int emscripten_flush_if_writable(void) { + return emscripten_flush(); + return 0; +} + +static bool emscripten_is_send_pending(void) { + return emscripten_buffer.len > 0; +} + +static int emscripten_putmessage(char msgtype, const char *s, size_t len) { + if (emscripten_buffer_busy) + return 0; + emscripten_buffer_busy = true; + + emscripten_init_buffer(); + + uint32 n32; + Assert(msgtype != 0); + + appendStringInfoChar(&emscripten_buffer, msgtype); + n32 = pg_hton32((uint32) (len + 4)); + appendBinaryStringInfo(&emscripten_buffer, (char *) &n32, 4); + appendBinaryStringInfo(&emscripten_buffer, s, len); + + emscripten_buffer_busy = false; + + // Flush buffer on every message + emscripten_flush(); + + return 0; + +fail: + emscripten_buffer_busy = false; + return EOF; +} + +static void emscripten_putmessage_noblock(char msgtype, const char *s, size_t len) { + emscripten_putmessage(msgtype, s, len); +} + /* -------------------------------- * pq_init - initialize libpq at backend startup * -------------------------------- diff --git a/src/backend/main/main.c b/src/backend/main/main.c index e58e24a6465..8b5580f96f8 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -42,6 +42,9 @@ #include "utils/pg_locale.h" #include "utils/ps_status.h" +#ifdef EMSCRIPTEN +#include +#endif const char *progname; @@ -366,6 +369,8 @@ help(const char *progname) static void check_root(const char *progname) { + return; + #ifndef WIN32 if (geteuid() == 0) { diff --git a/src/backend/port/sysv_sema.c b/src/backend/port/sysv_sema.c index 21c883ba9ac..de471271be7 100644 --- a/src/backend/port/sysv_sema.c +++ b/src/backend/port/sysv_sema.c @@ -98,6 +98,8 @@ InternalIpcSemaphoreCreate(IpcSemaphoreKey semKey, int numSems) { int semId; + return 42; + semId = semget(semKey, numSems, IPC_CREAT | IPC_EXCL | IPCProtection); if (semId < 0) @@ -147,6 +149,8 @@ IpcSemaphoreInitialize(IpcSemaphoreId semId, int semNum, int value) { union semun semun; + return; + semun.val = value; if (semctl(semId, semNum, SETVAL, semun) < 0) { @@ -170,6 +174,8 @@ IpcSemaphoreKill(IpcSemaphoreId semId) { union semun semun; + return; + semun.val = 0; /* unused, but keep compiler quiet */ if (semctl(semId, 0, IPC_RMID, semun) < 0) @@ -182,6 +188,8 @@ IpcSemaphoreGetValue(IpcSemaphoreId semId, int semNum) { union semun dummy; /* for Solaris */ + return 0; + dummy.val = 0; /* unused */ return semctl(semId, semNum, GETVAL, dummy); @@ -193,6 +201,8 @@ IpcSemaphoreGetLastPID(IpcSemaphoreId semId, int semNum) { union semun dummy; /* for Solaris */ + return 42; + dummy.val = 0; /* unused */ return semctl(semId, semNum, GETPID, dummy); @@ -215,6 +225,8 @@ IpcSemaphoreCreate(int numSems) union semun semun; PGSemaphoreData mysema; + return 42; + /* Loop till we find a free IPC key */ for (nextSemaKey++;; nextSemaKey++) { @@ -314,6 +326,7 @@ void PGReserveSemaphores(int maxSemas) { struct stat statbuf; + return; /* * We use the data directory's inode number to seed the search for free @@ -359,6 +372,8 @@ ReleaseSemaphores(int status, Datum arg) { int i; + return; + for (i = 0; i < numSemaSets; i++) IpcSemaphoreKill(mySemaSets[i]); free(mySemaSets); @@ -373,6 +388,7 @@ PGSemaphore PGSemaphoreCreate(void) { PGSemaphore sema; + return sema; /* Can't do this in a backend, because static state is postmaster's */ Assert(!IsUnderPostmaster); @@ -407,6 +423,7 @@ PGSemaphoreCreate(void) void PGSemaphoreReset(PGSemaphore sema) { + return; IpcSemaphoreInitialize(sema->semId, sema->semNum, 0); } @@ -421,6 +438,8 @@ PGSemaphoreLock(PGSemaphore sema) int errStatus; struct sembuf sops; + return; + sops.sem_op = -1; /* decrement */ sops.sem_flg = 0; sops.sem_num = sema->semNum; @@ -454,6 +473,8 @@ PGSemaphoreUnlock(PGSemaphore sema) int errStatus; struct sembuf sops; + return; + sops.sem_op = 1; /* increment */ sops.sem_flg = 0; sops.sem_num = sema->semNum; @@ -484,6 +505,8 @@ PGSemaphoreTryLock(PGSemaphore sema) int errStatus; struct sembuf sops; + return true; + sops.sem_op = -1; /* decrement */ sops.sem_flg = IPC_NOWAIT; /* but don't block */ sops.sem_num = sema->semNum; diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index 0cc83ffc16a..352ad4407dd 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -657,6 +657,40 @@ PGSharedMemoryCreate(Size size, struct stat statbuf; Size sysvsize; + elog(NOTICE, "Init WASM shared memory"); + + /* Initialize new segment. */ + hdr = (PGShmemHeader *) malloc(size); + hdr->creatorPID = getpid(); + hdr->magic = PGShmemMagic; + hdr->dsm_control = 0; + + /* Fill in the data directory ID info, too */ + hdr->device = statbuf.st_dev; + hdr->inode = statbuf.st_ino; + + /* + * Initialize space allocation status for segment. + */ + hdr->totalsize = size; + hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader)); + *shim = hdr; + + /* Save info for possible future use */ + UsedShmemSegAddr = memAddress; + UsedShmemSegID = (unsigned long) NextShmemSegID; + + /* + * If AnonymousShmem is NULL here, then we're not using anonymous shared + * memory, and should return a pointer to the System V shared memory + * block. Otherwise, the System V shared memory block is only a shim, and + * we must return a pointer to the real block. + */ + if (AnonymousShmem == NULL) + return hdr; + memcpy(AnonymousShmem, hdr, sizeof(PGShmemHeader)); + return (PGShmemHeader *) AnonymousShmem; + /* * We use the data directory's ID info (inode and device numbers) to * positively identify shmem segments associated with this data dir, and diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 5a050898fec..9e79e5dff9e 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -1501,6 +1501,7 @@ getInstallationPaths(const char *argv0) */ get_pkglib_path(my_exec_path, pkglib_path); +#ifndef EMSCRIPTEN /* * Verify that there's a readable directory there; otherwise the Postgres * installation is incomplete or corrupt. (A typical cause of this @@ -1517,6 +1518,7 @@ getInstallationPaths(const char *argv0) errhint("This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location.", my_exec_path))); FreeDir(pdir); +#endif /* * XXX is it worth similarly checking the share/ directory? If the lib/ diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 8c18b4ed05b..b62f2d17337 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -1328,6 +1328,8 @@ CheckPointReplicationSlots(void) { int i; + return; + elog(DEBUG1, "performing replication slot checkpoint"); /* diff --git a/src/backend/snowball/Makefile b/src/backend/snowball/Makefile index 50b9199910c..05a5811cb11 100644 --- a/src/backend/snowball/Makefile +++ b/src/backend/snowball/Makefile @@ -16,11 +16,11 @@ include $(top_builddir)/src/Makefile.global override CPPFLAGS := -I$(top_srcdir)/src/include/snowball \ -I$(top_srcdir)/src/include/snowball/libstemmer $(CPPFLAGS) -OBJS = \ - $(WIN32RES) \ - api.o \ - dict_snowball.o \ - utilities.o +# OBJS = \ +# $(WIN32RES) \ +# api.o \ +# dict_snowball.o \ +# utilities.o OBJS += \ stem_ISO_8859_1_basque.o \ @@ -115,7 +115,7 @@ VPATH += $(srcdir)/libstemmer NAME := dict_snowball rpath = -all: all-shared-lib $(SQLSCRIPT) +all: # all-shared-lib $(SQLSCRIPT) include $(top_srcdir)/src/Makefile.shlib diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e96..c109c036224 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -152,6 +152,8 @@ dsm_postmaster_startup(PGShmemHeader *shim) uint32 maxitems; Size segsize; + return; + Assert(!IsUnderPostmaster); /* @@ -294,6 +296,8 @@ dsm_cleanup_for_mmap(void) DIR *dir; struct dirent *dent; + return; + /* Scan the directory for something with a name of the correct format. */ dir = AllocateDir(PG_DYNSHMEM_DIR); diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index 1d893cf863d..effaa73603d 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -60,6 +60,8 @@ #include "storage/shmem.h" #include "utils/memutils.h" +#define WAIT_USE_POLL 1 + /* * Select the fd readiness primitive to use. Normally the "most modern" * primitive supported by the OS will be used, but for testing it can be diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 8cea10c9019..63c7af4c946 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -82,6 +82,10 @@ #include "utils/timeout.h" #include "utils/timestamp.h" +#ifdef EMSCRIPTEN +#include +#endif + /* ---------------- * global variables * ---------------- @@ -207,6 +211,14 @@ static void log_disconnections(int code, Datum arg); static void enable_statement_timeout(void); static void disable_statement_timeout(void); +/* ---------------------------------------------------------------- + * decls for PGlite routines + * ---------------------------------------------------------------- + */ +static void PostgresMain_Part0(void); +static void PostgresMain_Part1(void); +static void PostgresMain_Part2(void); +extern void ExecProtocolMsg(char *query); /* ---------------------------------------------------------------- * routines to obtain user input @@ -3468,6 +3480,8 @@ restore_stack_base(pg_stack_base_t base) void check_stack_depth(void) { + return; + if (stack_is_too_deep()) { ereport(ERROR, @@ -3689,6 +3703,10 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx, { argv++; argc--; +#ifdef EMSCRIPTEN + /* We want to send output to the client using the wire protocol */ + whereToSendOutput = DestRemote; +#endif } } else @@ -3915,6 +3933,58 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx, } +/* ---------------------------------------------------------------- + * ExecProtocolMsg + * PGlite main execute protocol message + * ---------------------------------------------------------------- + */ + +int firstchar; +StringInfoData input_message; +sigjmp_buf local_sigjmp_buf; +volatile bool send_ready_for_query = true; +bool idle_in_transaction_timeout_enabled = false; +bool idle_session_timeout_enabled = false; + +extern void +ExecProtocolMsg(char *query) +{ + char qtype = *query; // First byte is qtype + + int32 msgLen = *((int32 *)(query + 1)); // Next 4 bytes are message length + msgLen = pg_ntoh32(msgLen); + int dataLen = msgLen - 4; // The rest of the message is the data + + resetStringInfo(&input_message); + if (dataLen > 0) + { + // Append the data to the buffer + appendBinaryStringInfo(&input_message, query + 5, dataLen); + } + + firstchar = qtype; + free(query); + + /* Setup error handling */ + if (sigsetjmp(local_sigjmp_buf, 1) != 0) + { + PostgresMain_Part0(); + + /* We can now handle ereport(ERROR) */ + PG_exception_stack = &local_sigjmp_buf; + + if (!ignore_till_sync) + send_ready_for_query = true; /* initially, or after error */ + + return; // Return to the caller + } + + /* Process the query */ + PostgresMain_Part2(); + PostgresMain_Part1(); +} + + /* ---------------------------------------------------------------- * PostgresMain * postgres main loop -- all backends, interactive or otherwise start here @@ -3924,20 +3994,20 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx, * dbname is the name of the database to connect to, or NULL if the database * name should be extracted from the command line arguments or defaulted. * username is the PostgreSQL user name to be used for the session. + * + * Mods: + * + * This has been modified to be called from PGlite and exits early once + * initialisation is complete. + * ExecProtocolMsg above is called to process the query. * ---------------------------------------------------------------- */ + void PostgresMain(int argc, char *argv[], const char *dbname, const char *username) { - int firstchar; - StringInfoData input_message; - sigjmp_buf local_sigjmp_buf; - volatile bool send_ready_for_query = true; - bool idle_in_transaction_timeout_enabled = false; - bool idle_session_timeout_enabled = false; - /* Initialize startup process environment if necessary. */ if (!IsUnderPostmaster) InitStandaloneProcess(argv[0]); @@ -4186,9 +4256,27 @@ PostgresMain(int argc, char *argv[], * unblock in AbortTransaction() because the latter is only called if we * were inside a transaction. */ - if (sigsetjmp(local_sigjmp_buf, 1) != 0) { + PostgresMain_Part0(); + } + + /* We can now handle ereport(ERROR) */ + PG_exception_stack = &local_sigjmp_buf; + + if (!ignore_till_sync) + send_ready_for_query = true; /* initially, or after error */ + + /* + * Non-error queries loop here. + */ + PostgresMain_Part1(); + exit(0); +} + +void +PostgresMain_Part0() +{ /* * NOTE: if you are tempted to add more code in this if-block, * consider the high probability that it should be in @@ -4291,20 +4379,11 @@ PostgresMain(int argc, char *argv[], /* Now we can allow interrupts again */ RESUME_INTERRUPTS(); - } - - /* We can now handle ereport(ERROR) */ - PG_exception_stack = &local_sigjmp_buf; - - if (!ignore_till_sync) - send_ready_for_query = true; /* initially, or after error */ - - /* - * Non-error queries loop here. - */ +} - for (;;) - { +void +PostgresMain_Part1() +{ /* * At top of loop, reset extended-query-message flag, so that any * errors encountered in "idle" state don't provoke skip. @@ -4411,12 +4490,12 @@ PostgresMain(int argc, char *argv[], * STDIN doing the same thing.) */ DoingCommandRead = true; +} - /* - * (3) read a command (loop blocks here) - */ - firstchar = ReadCommand(&input_message); +void +PostgresMain_Part2() +{ /* * (4) turn off the idle-in-transaction and idle-session timeouts, if * active. We do this before step (5) so that any last-moment timeout @@ -4463,7 +4542,7 @@ PostgresMain(int argc, char *argv[], * Sync. */ if (ignore_till_sync && firstchar != EOF) - continue; + return; switch (firstchar) { @@ -4716,7 +4795,6 @@ PostgresMain(int argc, char *argv[], errmsg("invalid frontend message type %d", firstchar))); } - } /* end of input-reading loop */ } /* diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index e8c6cdde972..764793ce212 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -36,6 +36,7 @@ #include "storage/shmem.h" #include "utils/hsearch.h" +#include "extensions/plpgsql.h" /* signatures for PostgreSQL-specific library init/fini functions */ typedef void (*PG_init_t) (void); @@ -90,6 +91,26 @@ static char *find_in_dynamic_libpath(const char *basename); static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA; +/* PGlite static handling of extensions */ + +bool plpgsql_loaded = false; + +typedef struct { + const char *name; + void *function; +} func_map; + +static const func_map function_map[] = { + {"plpgsql_call_handler", plpgsql_call_handler}, + {"plpgsql_inline_handler", plpgsql_inline_handler}, + {"plpgsql_validator", plpgsql_validator}, + {"pg_finfo_plpgsql_call_handler", pg_finfo_plpgsql_call_handler}, + {"pg_finfo_plpgsql_inline_handler", pg_finfo_plpgsql_inline_handler}, + {"pg_finfo_plpgsql_validator", pg_finfo_plpgsql_validator}, + {NULL, NULL} +}; + + /* * Load the specified dynamic-link library file, and look for a function * named funcname in it. @@ -107,6 +128,24 @@ void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle) { + // printf("load_external_function - filename: %s, funcname: %s, signalNotFound: %d, filehandle: %p\n", filename, funcname, signalNotFound, filehandle); + + /* PGlite static handling of extensions */ + if (strcmp(filename, "$libdir/plpgsql") == 0) + { + if (!plpgsql_loaded) + { + plpgsql_PG_init(); + plpgsql_loaded = true; + } + + for (int i = 0; function_map[i].name != NULL; i++) { + if (strcmp(funcname, function_map[i].name) == 0) { + return function_map[i].function; + } + } + } + char *fullname; void *lib_handle; void *retval; @@ -145,6 +184,19 @@ load_external_function(const char *filename, const char *funcname, void load_file(const char *filename, bool restricted) { + // printf("load_file - filename: %s, restricted: %d\n", filename, restricted); + + /* PGlite static handling of extensions */ + if (strcmp(filename, "$libdir/plpgsql") == 0) + { + if (!plpgsql_loaded) + { + plpgsql_PG_init(); + plpgsql_loaded = true; + } + return; + } + char *fullname; /* Apply security restriction if requested */ @@ -170,6 +222,15 @@ load_file(const char *filename, bool restricted) void * lookup_external_function(void *filehandle, const char *funcname) { + // printf("lookup_external_function - filehandle: %p, funcname: %s\n", filehandle, funcname); + + /* PGlite static handling of extensions */ + for (int i = 0; function_map[i].name != NULL; i++) { + if (strcmp(funcname, function_map[i].name) == 0) { + return function_map[i].function; + } + } + return dlsym(filehandle, funcname); } @@ -453,6 +514,7 @@ internal_unload_library(const char *libname) static bool file_exists(const char *name) { + // printf("file_exists - name: %s\n", name); struct stat st; AssertArg(name != NULL); diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 8b73850d0df..e6abafb8b6d 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -337,7 +337,7 @@ checkDataDir(void) * * XXX can we safely enable this check on Windows? */ -#if !defined(WIN32) && !defined(__CYGWIN__) +#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(EMSCRIPTEN) if (stat_buf.st_uid != geteuid()) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), @@ -357,7 +357,7 @@ checkDataDir(void) * be proper support for Unix-y file permissions. Need to think of a * reasonable check to apply on Windows. */ -#if !defined(WIN32) && !defined(__CYGWIN__) +#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(EMSCRIPTEN) if (stat_buf.st_mode & PG_MODE_MASK_GROUP) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), diff --git a/src/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c index 5819faaf2d2..bfa995fcae7 100644 --- a/src/backend/utils/misc/ps_status.c +++ b/src/backend/utils/misc/ps_status.c @@ -22,7 +22,7 @@ #include /* for old BSD */ #include #endif -#if defined(__darwin__) +#if defined(__darwin__) && !defined(EMSCRIPTEN) #include #endif @@ -230,7 +230,7 @@ save_ps_display_args(int argc, char **argv) } new_argv[argc] = NULL; -#if defined(__darwin__) +#if defined(__darwin__) && !defined(EMSCRIPTEN) /* * macOS (and perhaps other NeXT-derived platforms?) has a static copy diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index d704c4220c7..d341a74c8cf 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -553,7 +553,9 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd) dir = opt; else { -#ifndef WIN32 +#if defined(EMSCRIPTEN) + dir = "/"; +#elif !defined(WIN32) struct passwd *pw; uid_t user_id = geteuid(); diff --git a/src/common/exec.c b/src/common/exec.c index 81b810d4cfa..372237d5120 100644 --- a/src/common/exec.c +++ b/src/common/exec.c @@ -130,6 +130,9 @@ find_my_exec(const char *argv0, char *retpath) test_path[MAXPGPATH]; char *path; + retpath = "/dummy/path"; + return 0; + if (!getcwd(cwd, MAXPGPATH)) { log_error(errcode_for_file_access(), diff --git a/src/common/username.c b/src/common/username.c index 669b8ab3b27..b0bb06698f3 100644 --- a/src/common/username.c +++ b/src/common/username.c @@ -30,7 +30,9 @@ const char * get_user_name(char **errstr) { -#ifndef WIN32 +#if defined(EMSCRIPTEN) + return "pglite"; +#elif !defined(WIN32) struct passwd *pw; uid_t user_id = geteuid(); diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index 8290d4c6c49..03c7e8fe82d 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -55,6 +55,7 @@ extern void boot_get_type_io_data(Oid typid, Oid *typoutput); extern int boot_yyparse(void); +void boot_yyset_in (FILE * in_str ); extern int boot_yylex(void); extern void boot_yyerror(const char *str) pg_attribute_noreturn(); diff --git a/src/include/extensions/plpgsql.h b/src/include/extensions/plpgsql.h new file mode 100644 index 00000000000..29963fbba18 --- /dev/null +++ b/src/include/extensions/plpgsql.h @@ -0,0 +1,12 @@ +#include "postgres.h" + +extern void plpgsql_PG_init(void); +extern Datum plpgsql_call_handler(PG_FUNCTION_ARGS); +extern Datum plpgsql_inline_handler(PG_FUNCTION_ARGS); +extern Datum plpgsql_validator(PG_FUNCTION_ARGS); + +#ifndef PLPGSQL_INFO_DEF +extern Pg_finfo_record *pg_finfo_plpgsql_call_handler(void); +extern Pg_finfo_record *pg_finfo_plpgsql_inline_handler(void); +extern Pg_finfo_record *pg_finfo_plpgsql_validator(void); +#endif \ No newline at end of file diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h index 27da86e5e09..eda4e21844d 100644 --- a/src/include/pg_config_manual.h +++ b/src/include/pg_config_manual.h @@ -138,7 +138,7 @@ /* * Define this if your operating system supports link() */ -#if !defined(WIN32) && !defined(__CYGWIN__) +#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(EMSCRIPTEN) #define HAVE_WORKING_LINK 1 #endif diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c index 3421ed4685b..11ca4f1e08d 100644 --- a/src/interfaces/libpq/fe-auth.c +++ b/src/interfaces/libpq/fe-auth.c @@ -1124,7 +1124,9 @@ pg_fe_getauthname(PQExpBuffer errorMessage) */ pglock_thread(); -#ifdef WIN32 +#if defined(EMSCRIPTEN) + name = "pglite"; +#elif defined(WIN32) if (GetUserName(username, &namesize)) name = username; else if (errorMessage) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index e950b41374b..33e8251d993 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -2838,7 +2838,9 @@ PQconnectPoll(PGconn *conn) goto error_return; } -#ifndef WIN32 +#if defined(EMSCRIPTEN) + /* Noop */ +#elif !defined(WIN32) passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass); if (pass == NULL) { diff --git a/src/makefiles/Makefile.darwin b/src/makefiles/Makefile.darwin index b17598f0586..65a08812b82 100644 --- a/src/makefiles/Makefile.darwin +++ b/src/makefiles/Makefile.darwin @@ -5,11 +5,11 @@ DLSUFFIX = .so # env var name to use in place of LD_LIBRARY_PATH ld_library_path_var = DYLD_LIBRARY_PATH -ifdef PGXS - BE_DLLLIBS = -bundle_loader $(bindir)/postgres -else - BE_DLLLIBS = -bundle_loader $(top_builddir)/src/backend/postgres -endif +# ifdef PGXS +# BE_DLLLIBS = -bundle_loader $(bindir)/postgres +# else +# BE_DLLLIBS = -bundle_loader $(top_builddir)/src/backend/postgres +# endif # Rule for building a shared library from a single .o file %.so: %.o diff --git a/src/makefiles/Makefile.linux b/src/makefiles/Makefile.linux index 645f73aa2b7..4f80fd1f87b 100644 --- a/src/makefiles/Makefile.linux +++ b/src/makefiles/Makefile.linux @@ -3,7 +3,7 @@ AROPT = crs export_dynamic = -Wl,-E # Use --enable-new-dtags to generate DT_RUNPATH instead of DT_RPATH. # This allows LD_LIBRARY_PATH to still work when needed. -rpath = -Wl,-rpath,'$(rpathdir)',--enable-new-dtags +#rpath = -Wl,-rpath,'$(rpathdir)',--enable-new-dtags DLSUFFIX = .so diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c index 00aace2f39f..5844f8052e7 100644 --- a/src/pl/plpgsql/src/pl_handler.c +++ b/src/pl/plpgsql/src/pl_handler.c @@ -27,6 +27,10 @@ #include "utils/syscache.h" #include "utils/varlena.h" +#ifdef EMSCRIPTEN +#include +#endif + static bool plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source); static void plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra); static void plpgsql_extra_errors_assign_hook(const char *newvalue, void *extra); @@ -141,8 +145,8 @@ plpgsql_extra_errors_assign_hook(const char *newvalue, void *extra) * * DO NOT make this static nor change its name! */ -void -_PG_init(void) +extern void EMSCRIPTEN_KEEPALIVE +plpgsql_PG_init(void) { /* Be sure we do initialization only once (should be redundant now) */ static bool inited = false; @@ -218,7 +222,7 @@ _PG_init(void) */ PG_FUNCTION_INFO_V1(plpgsql_call_handler); -Datum +extern Datum EMSCRIPTEN_KEEPALIVE plpgsql_call_handler(PG_FUNCTION_ARGS) { bool nonatomic; @@ -311,7 +315,7 @@ plpgsql_call_handler(PG_FUNCTION_ARGS) */ PG_FUNCTION_INFO_V1(plpgsql_inline_handler); -Datum +extern Datum EMSCRIPTEN_KEEPALIVE plpgsql_inline_handler(PG_FUNCTION_ARGS) { LOCAL_FCINFO(fake_fcinfo, 0); @@ -438,7 +442,7 @@ plpgsql_inline_handler(PG_FUNCTION_ARGS) */ PG_FUNCTION_INFO_V1(plpgsql_validator); -Datum +extern Datum EMSCRIPTEN_KEEPALIVE plpgsql_validator(PG_FUNCTION_ARGS) { Oid funcoid = PG_GETARG_OID(0); diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index fcbfcd678b1..bcc41b55faa 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -23,6 +23,8 @@ #include "utils/expandedrecord.h" #include "utils/typcache.h" +#define PLPGSQL_INFO_DEF +#include "extensions/plpgsql.h" /********************************************************************** * Definitions diff --git a/src/port/getpeereid.c b/src/port/getpeereid.c index d6aa755d30a..67cf00478e7 100644 --- a/src/port/getpeereid.c +++ b/src/port/getpeereid.c @@ -34,7 +34,9 @@ int getpeereid(int sock, uid_t *uid, gid_t *gid) { -#if defined(SO_PEERCRED) +#if defined(EMSCRIPTEN) + /* Noop */ +#elif defined(SO_PEERCRED) /* Linux: use getsockopt(SO_PEERCRED) */ struct ucred peercred; ACCEPT_TYPE_ARG3 so_len = sizeof(peercred); diff --git a/src/test/regress/GNUmakefile b/src/test/regress/GNUmakefile index fe6e0c98aa2..87814517f18 100644 --- a/src/test/regress/GNUmakefile +++ b/src/test/regress/GNUmakefile @@ -85,11 +85,11 @@ regress_data_files = \ $(wildcard $(srcdir)/data/*.data) \ $(srcdir)/parallel_schedule $(srcdir)/resultmap -install-tests: all install install-lib installdirs-tests - $(MAKE) -C $(top_builddir)/contrib/spi install - for file in $(subst $(srcdir)/,,$(regress_data_files)); do \ - $(INSTALL_DATA) $(srcdir)/$$file '$(DESTDIR)$(pkglibdir)/regress/'$$file || exit; \ - done +# install-tests: all install install-lib installdirs-tests +# $(MAKE) -C $(top_builddir)/contrib/spi install +# for file in $(subst $(srcdir)/,,$(regress_data_files)); do \ +# $(INSTALL_DATA) $(srcdir)/$$file '$(DESTDIR)$(pkglibdir)/regress/'$$file || exit; \ +# done installdirs-tests: installdirs $(MKDIR_P) $(patsubst $(srcdir)/%/,'$(DESTDIR)$(pkglibdir)/regress/%',$(sort $(dir $(regress_data_files)))) @@ -97,7 +97,7 @@ installdirs-tests: installdirs # Get some extra C modules from contrib/spi -all: refint$(DLSUFFIX) autoinc$(DLSUFFIX) +all: #refint$(DLSUFFIX) autoinc$(DLSUFFIX) refint$(DLSUFFIX): $(top_builddir)/contrib/spi/refint$(DLSUFFIX) cp $< $@