Skip to content
Snippets Groups Projects
Commit 951986c5 authored by Bruce Momjian's avatar Bruce Momjian
Browse files

Update of contrib stuff from massimo.

parent 5aaf00f3
No related branches found
No related tags found
No related merge requests found
#-------------------------------------------------------------------------
#
# Makefile--
# Makefile for new sequence functions.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
include $(SRCDIR)/Makefile.global
INCLUDE_OPT = -I ./ \
-I $(SRCDIR)/ \
-I $(SRCDIR)/include \
-I $(SRCDIR)/port/$(PORTNAME)
CFLAGS += $(INCLUDE_OPT)
ifeq ($(PORTNAME), linux)
ifdef LINUX_ELF
ifeq ($(CC), gcc)
CFLAGS += -fPIC
endif
endif
endif
ifeq ($(PORTNAME), i386_solaris)
CFLAGS+= -fPIC
endif
MODNAME = set_sequence
MODULE = $(MODNAME)$(DLSUFFIX)
all: module sql
module: $(MODULE)
sql: $(MODNAME).sql
install: $(MODULE)
cp -p $(MODULE) $(LIBDIR)
cd $(LIBDIR); strip $(MODULE)
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(LIBDIR)/$(MODULE)|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
%$(DLSUFFIX): %.c
cc $(CFLAGS) -shared -o $@ $<
depend dep:
$(CC) -MM $(INCLUDE_OPT) *.c >depend
clean:
rm -f $(MODULE) $(MODNAME).sql
ifeq (depend,$(wildcard depend))
include depend
endif
/*
* set_sequence.c --
*
* Set a new sequence value.
*
* Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it>
*/
#include "postgres.h"
#include "nodes/parsenodes.h"
#include "commands/sequence.h"
#include "set_sequence.h"
extern int setval(struct varlena *seqin, int4 val);
int
set_currval(struct varlena *sequence, int4 nextval)
{
return setval(sequence, nextval);
}
int
next_id(struct varlena *sequence)
{
return nextval(sequence);
}
int
last_id(struct varlena *sequence)
{
return currval(sequence);
}
int
set_last_id(struct varlena *sequence, int4 nextval)
{
return setval(sequence, nextval);
}
/* end of file */
#ifndef SET_SEQUENCE_H
#define SET_SEQUENCE_H
int set_currval(struct varlena *sequence, int4 nextval);
int next_id(struct varlena *sequence);
int last_id(struct varlena *sequence);
int set_last_id(struct varlena *sequence, int4 nextval);
#endif
-- SQL code to define new sequence utilities
-- Set a new sequence value
--
create function set_currval(text, int4) returns int4
as 'MODULE_PATHNAME'
language 'C';
-- Increment the value of sequence
--
-- select next_id('sequence_name');
--
create function next_id(text) returns int4
as 'MODULE_PATHNAME'
language 'C';
-- Return the last value set for a sequence
--
-- select last_id('sequence_name');
--
create function last_id(text) returns int4
as 'MODULE_PATHNAME'
language 'C';
-- Set the current value of a sequence
--
-- select set_last_id('sequence_name', 1);
--
create function set_last_id(text,int4) returns int4
as 'MODULE_PATHNAME'
language 'C';
-- end of file
#-------------------------------------------------------------------------
#
# Makefile--
# Makefile for new string I/O functions.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
include $(SRCDIR)/Makefile.global
INCLUDE_OPT = -I ./ \
-I $(SRCDIR)/ \
-I $(SRCDIR)/include \
-I $(SRCDIR)/port/$(PORTNAME)
CFLAGS += $(INCLUDE_OPT)
ifeq ($(PORTNAME), linux)
ifdef LINUX_ELF
ifeq ($(CC), gcc)
CFLAGS += -fPIC
endif
endif
endif
ifeq ($(PORTNAME), i386_solaris)
CFLAGS+= -fPIC
endif
MODNAME = string_io
MODULE = $(MODNAME)$(DLSUFFIX)
all: module sql
module: $(MODULE)
sql: $(MODNAME).sql
install: $(MODULE)
cp -p $(MODULE) $(LIBDIR)
cd $(LIBDIR); strip $(MODULE)
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(LIBDIR)/$(MODULE)|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
%$(DLSUFFIX): %.c
cc $(CFLAGS) -shared -o $@ $<
depend dep:
$(CC) -MM $(INCLUDE_OPT) *.c >depend
clean:
rm -f $(MODULE) $(MODNAME).sql
ifeq (depend,$(wildcard depend))
include depend
endif
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include "utils/palloc.h" #include "utils/palloc.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "string_io.h"
/* define this if you want to see iso-8859 characters */ /* define this if you want to see iso-8859 characters */
#define ISO8859 #define ISO8859
...@@ -48,32 +50,24 @@ ...@@ -48,32 +50,24 @@
char * char *
string_output(char *data, int size) string_output(char *data, int size)
{ {
register unsigned char c, register unsigned char c, *p, *r, *result;
*p, register int l, len;
*r,
*result; if (data == NULL) {
register int l,
len;
if (data == NULL)
{
result = (char *) palloc(2); result = (char *) palloc(2);
result[0] = '-'; result[0] = '-';
result[1] = '\0'; result[1] = '\0';
return (result); return (result);
} }
if (size < 0) if (size < 0) {
{
size = strlen(data); size = strlen(data);
} }
/* adjust string length for escapes */ /* adjust string length for escapes */
len = size; len = size;
for (p = data, l = size; l > 0; p++, l--) for (p=data,l=size; l>0; p++,l--) {
{ switch (*p) {
switch (*p)
{
case '\\': case '\\':
case '"' : case '"' :
case '{': case '{':
...@@ -87,8 +81,7 @@ string_output(char *data, int size) ...@@ -87,8 +81,7 @@ string_output(char *data, int size)
len++; len++;
break; break;
default: default:
if (NOTPRINTABLE(*p)) if (NOTPRINTABLE(*p)) {
{
len += 3; len += 3;
} }
} }
...@@ -97,10 +90,8 @@ string_output(char *data, int size) ...@@ -97,10 +90,8 @@ string_output(char *data, int size)
result = (char *) palloc(len); result = (char *) palloc(len);
for (p = data, r = result, l = size; (l > 0) && (c = *p); p++, l--) for (p=data,r=result,l=size; (l > 0) && (c = *p); p++,l--) {
{ switch (c) {
switch (c)
{
case '\\': case '\\':
case '"' : case '"' :
case '{': case '{':
...@@ -133,8 +124,7 @@ string_output(char *data, int size) ...@@ -133,8 +124,7 @@ string_output(char *data, int size)
*r++ = 'v'; *r++ = 'v';
break; break;
default: default:
if (NOTPRINTABLE(c)) if (NOTPRINTABLE(c)) {
{
*r = '\\'; *r = '\\';
r += 3; r += 3;
*r-- = DIGIT(c & 07); *r-- = DIGIT(c & 07);
...@@ -143,9 +133,7 @@ string_output(char *data, int size) ...@@ -143,9 +133,7 @@ string_output(char *data, int size)
c >>= 3; c >>= 3;
*r = DIGIT(c & 03); *r = DIGIT(c & 03);
r += 3; r += 3;
} } else {
else
{
*r++ = c; *r++ = c;
} }
} }
...@@ -184,69 +172,54 @@ string_output(char *data, int size) ...@@ -184,69 +172,54 @@ string_output(char *data, int size)
char * char *
string_input(char *str, int size, int hdrsize, int *rtn_size) string_input(char *str, int size, int hdrsize, int *rtn_size)
{ {
register unsigned char *p, register unsigned char *p, *r;
*r;
unsigned char *result; unsigned char *result;
int len; int len;
if ((str == NULL) || (hdrsize < 0)) if ((str == NULL) || (hdrsize < 0)) {
{
return (char *) NULL; return (char *) NULL;
} }
/* Compute result size */ /* Compute result size */
len = strlen(str); len = strlen(str);
for (p = str; *p;) for (p=str; *p; ) {
{ if (*p++ == '\\') {
if (*p++ == '\\') if (ISOCTAL(*p)) {
{ if (ISOCTAL(*(p+1))) {
if (ISOCTAL(*p))
{
if (ISOCTAL(*(p + 1)))
{
p++; p++;
len--; len--;
} }
if (ISOCTAL(*(p + 1))) if (ISOCTAL(*(p+1))) {
{
p++; p++;
len--; len--;
} }
} }
if (*p) if (*p) p++;
p++;
len--; len--;
} }
} }
/* result has variable length */ /* result has variable length */
if (size == 0) if (size == 0) {
{
size = len+1; size = len+1;
} } else
else
/* result has variable length with maximum size */ /* result has variable length with maximum size */
if (size < 0) if (size < 0) {
{
size = MIN(len, - size)+1; size = MIN(len, - size)+1;
} }
result = (char *) palloc(hdrsize+size); result = (char *) palloc(hdrsize+size);
memset(result, 0, hdrsize+size); memset(result, 0, hdrsize+size);
if (rtn_size) if (rtn_size) {
{
*rtn_size = size; *rtn_size = size;
} }
r = result + hdrsize; r = result + hdrsize;
for (p = str; *p;) for (p=str; *p; ) {
{
register unsigned char c; register unsigned char c;
if ((c = *p++) == '\\') {
if ((c = *p++) == '\\') switch (c = *p++) {
{
switch (c = *p++)
{
case '\0': case '\0':
p--; p--;
break; break;
...@@ -259,12 +232,10 @@ string_input(char *str, int size, int hdrsize, int *rtn_size) ...@@ -259,12 +232,10 @@ string_input(char *str, int size, int hdrsize, int *rtn_size)
case '6': case '6':
case '7': case '7':
c = VALUE(c); c = VALUE(c);
if (isdigit(*p)) if (isdigit(*p)) {
{
c = (c<<3) + VALUE(*p++); c = (c<<3) + VALUE(*p++);
} }
if (isdigit(*p)) if (isdigit(*p)) {
{
c = (c<<3) + VALUE(*p++); c = (c<<3) + VALUE(*p++);
} }
*r++ = c; *r++ = c;
...@@ -290,9 +261,7 @@ string_input(char *str, int size, int hdrsize, int *rtn_size) ...@@ -290,9 +261,7 @@ string_input(char *str, int size, int hdrsize, int *rtn_size)
default: default:
*r++ = c; *r++ = c;
} }
} } else {
else
{
*r++ = c; *r++ = c;
} }
} }
...@@ -345,8 +314,7 @@ c_textout(struct varlena * vlena) ...@@ -345,8 +314,7 @@ c_textout(struct varlena * vlena)
int len = 0; int len = 0;
char *s = NULL; char *s = NULL;
if (vlena) if (vlena) {
{
len = VARSIZE(vlena) - VARHDRSZ; len = VARSIZE(vlena) - VARHDRSZ;
s = VARDATA(vlena); s = VARDATA(vlena);
} }
...@@ -360,25 +328,23 @@ c_textout(struct varlena * vlena) ...@@ -360,25 +328,23 @@ c_textout(struct varlena * vlena)
char * char *
c_varcharout(char *s) c_varcharout(char *s)
{ {
int len; int len = 0;
if (s) if (s) {
{
len = *(int32*)s - 4; len = *(int32*)s - 4;
s += 4; s += 4;
} }
return (string_output(s, len)); return (string_output(s, len));
} }
#ifdef 0 #if 0
struct varlena * struct varlena *
c_textin(char *str) c_textin(char *str)
{ {
struct varlena *result; struct varlena *result;
int len; int len;
if (str == NULL) if (str == NULL) {
{
return ((struct varlena *) NULL); return ((struct varlena *) NULL);
} }
...@@ -393,5 +359,7 @@ c_char16in(char *str) ...@@ -393,5 +359,7 @@ c_char16in(char *str)
{ {
return (string_input(str, 16, 0, NULL)); return (string_input(str, 16, 0, NULL));
} }
#endif #endif
/* end of file */
#ifndef STRING_IO_H
#define STRING_IO_H
char *string_output(char *data, int size);
char *string_input(char *str, int size, int hdrsize, int *rtn_size);
char *c_charout(int32 c);
char *c_char2out(uint16 s);
char *c_char4out(uint32 s);
char *c_char8out(char *s);
char *c_char16out(char *s);
char *c_textout(struct varlena *vlena);
char *c_varcharout(char *s);
#if 0
struct varlena *c_textin(char *str);
char *c_char16in(char *str);
#endif
#endif
-- SQL code to define the new string I/O functions
-- This is not needed because escapes are handled by the parser
--
-- create function c_textin(opaque)
-- returns text
-- as 'MODULE_PATHNAME'
-- language 'c';
create function c_charout(opaque) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function c_char2out(opaque) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function c_char4out(opaque) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function c_char8out(opaque) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function c_char16out(opaque) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function c_textout(opaque) returns int4
as 'MODULE_PATHNAME'
language 'c';
create function c_varcharout(opaque) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- Define a function which sets the new output routines for char types
--
-- select c_mode();
--
create function c_mode() returns text
as 'update pg_type set typoutput=''c_charout'' where typname=''char'';
update pg_type set typoutput=''c_char2out'' where typname=''char2'';
update pg_type set typoutput=''c_char4out'' where typname=''char4'';
update pg_type set typoutput=''c_char8out'' where typname=''char8'';
update pg_type set typoutput=''c_char16out'' where typname=''char16'';
update pg_type set typoutput=''c_textout'' where typname=''text'';
update pg_type set typoutput=''c_textout'' where typname=''bytea'';
update pg_type set typoutput=''c_textout'' where typname=''unknown'';
update pg_type set typoutput=''c_textout'' where typname=''SET'';
update pg_type set typoutput=''c_varcharout'' where typname=''varchar'';
update pg_type set typoutput=''c_varcharout'' where typname=''bpchar'';
select ''c_mode''::text'
language 'sql';
-- Define a function which restores the original routines for char types
--
-- select pg_mode();
--
create function pg_mode() returns text
as 'update pg_type set typoutput=''charout'' where typname=''char'';
update pg_type set typoutput=''char2out'' where typname=''char2'';
update pg_type set typoutput=''char4out'' where typname=''char4'';
update pg_type set typoutput=''char8out'' where typname=''char8'';
update pg_type set typoutput=''char16out'' where typname=''char16'';
update pg_type set typoutput=''textout'' where typname=''text'';
update pg_type set typoutput=''textout'' where typname=''bytea'';
update pg_type set typoutput=''textout'' where typname=''unknown'';
update pg_type set typoutput=''textout'' where typname=''SET'';
update pg_type set typoutput=''varcharout'' where typname=''varchar'';
update pg_type set typoutput=''varcharout'' where typname=''bpchar'';
select ''pg_mode''::text'
language 'sql';
-- Use these if you want do the updates manually
--
-- update pg_type set typoutput='charout' where typname='char';
-- update pg_type set typoutput='char2out' where typname='char2';
-- update pg_type set typoutput='char4out' where typname='char4';
-- update pg_type set typoutput='char8out' where typname='char8';
-- update pg_type set typoutput='char16out' where typname='char16';
-- update pg_type set typoutput='textout' where typname='text';
-- update pg_type set typoutput='textout' where typname='bytea';
-- update pg_type set typoutput='textout' where typname='unknown';
-- update pg_type set typoutput='textout' where typname='SET';
-- update pg_type set typoutput='varcharout' where typname='varchar';
-- update pg_type set typoutput='varcharout' where typname='bpchar';
--
-- update pg_type set typoutput='c_charout' where typname='char';
-- update pg_type set typoutput='c_char2out' where typname='char2';
-- update pg_type set typoutput='c_char4out' where typname='char4';
-- update pg_type set typoutput='c_char8out' where typname='char8';
-- update pg_type set typoutput='c_char16out' where typname='char16';
-- update pg_type set typoutput='c_textout' where typname='text';
-- update pg_type set typoutput='c_textout' where typname='bytea';
-- update pg_type set typoutput='c_textout' where typname='unknown';
-- update pg_type set typoutput='c_textout' where typname='SET';
-- update pg_type set typoutput='c_varcharout' where typname='varchar';
-- update pg_type set typoutput='c_varcharout' where typname='bpchar';
-- end of file
#-------------------------------------------------------------------------
#
# Makefile--
# Makefile for new string I/O functions.
#
#-------------------------------------------------------------------------
PGDIR = ../..
SRCDIR = $(PGDIR)/src
include $(SRCDIR)/Makefile.global
INCLUDE_OPT = -I ./ \
-I $(SRCDIR)/ \
-I $(SRCDIR)/include \
-I $(SRCDIR)/port/$(PORTNAME)
CFLAGS += $(INCLUDE_OPT)
ifeq ($(PORTNAME), linux)
ifdef LINUX_ELF
ifeq ($(CC), gcc)
CFLAGS += -fPIC
endif
endif
endif
ifeq ($(PORTNAME), i386_solaris)
CFLAGS+= -fPIC
endif
MODNAME = user_locks
MODULE = $(MODNAME)$(DLSUFFIX)
all: module sql
module: $(MODULE)
sql: $(MODNAME).sql
install: $(MODULE)
cp -p $(MODULE) $(LIBDIR)
cd $(LIBDIR); strip $(MODULE)
%.sql: %.sql.in
sed "s|MODULE_PATHNAME|$(LIBDIR)/$(MODULE)|" < $< > $@
.SUFFIXES: $(DLSUFFIX)
%$(DLSUFFIX): %.c
cc $(CFLAGS) -shared -o $@ $<
depend dep:
$(CC) -MM $(INCLUDE_OPT) *.c >depend
clean:
rm -f $(MODULE) $(MODNAME).sql
ifeq (depend,$(wildcard depend))
include depend
endif
/*
* user_locks.c --
*
* This loadable module, together with my user-lock.patch applied to the
* backend, provides support for user-level long-term cooperative locks.
*
* Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it>
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "postgres.h"
#include "miscadmin.h"
#include "storage/lock.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/block.h"
#include "storage/multilev.h"
#include "utils/elog.h"
#include "user_locks.h"
#define USER_LOCKS_TABLE_ID 0
extern Oid MyDatabaseId;
int
user_lock(unsigned int id1, unsigned int id2, LOCKT lockt)
{
LOCKTAG tag;
memset(&tag,0,sizeof(LOCKTAG));
tag.relId = 0;
tag.dbId = MyDatabaseId;
tag.tupleId.ip_blkid.bi_hi = id2 >> 16;
tag.tupleId.ip_blkid.bi_lo = id2 & 0xffff;
tag.tupleId.ip_posid = (unsigned short) (id1 & 0xffff);
return LockAcquire(USER_LOCKS_TABLE_ID, &tag, lockt);
}
int
user_unlock(unsigned int id1, unsigned int id2, LOCKT lockt)
{
LOCKTAG tag;
memset(&tag, 0,sizeof(LOCKTAG));
tag.relId = 0;
tag.dbId = MyDatabaseId;
tag.tupleId.ip_blkid.bi_hi = id2 >> 16;
tag.tupleId.ip_blkid.bi_lo = id2 & 0xffff;
tag.tupleId.ip_posid = (unsigned short) (id1 & 0xffff);
return LockRelease(USER_LOCKS_TABLE_ID, &tag, lockt);
}
int
user_write_lock(unsigned int id1, unsigned int id2)
{
return user_lock(id1, id2, WRITE_LOCK);
}
int
user_write_unlock(unsigned int id1, unsigned int id2)
{
return user_unlock(id1, id2, WRITE_LOCK);
}
int
user_write_lock_oid(Oid oid)
{
return user_lock(0, oid, WRITE_LOCK);
}
int
user_write_unlock_oid(Oid oid)
{
return user_unlock(0, oid, WRITE_LOCK);
}
int
user_unlock_all()
{
PROC *proc;
SHMEM_OFFSET location;
ShmemPIDLookup(getpid(),&location);
if (location == INVALID_OFFSET) {
elog(NOTICE, "UserUnlockAll: unable to get proc ptr");
return -1;
}
proc = (PROC *) MAKE_PTR(location);
return LockReleaseAll(USER_LOCKS_TABLE_ID, &proc->lockQueue);
}
/* end of file */
User locks, by Massimo Dal Zotto <dz@cs.unitn.it>
This loadable module, together with my user-lock.patch applied to the
backend, provides support for user-level long-term cooperative locks.
For example one can write (this example is written in TclX):
set rec [sql "select ...,user_write_lock_oid(oid) from table where id=$id"]
if {[keylget rec user_write_lock_oid] == 1} {
# the write lock has been acquired with the record, start
# a long editing session, then update the database and
# release the lock.
sql "update table set ... where id=$id"
sql "select user_write_unlock_oid([keylget rec oid])"
} else {
# the record has been read but the write lock couldn't be acquired,
# so it should not be modified by the application.
messageBox "This record is in use by another user, retry later"
}
This could also be done by setting a flag in the record itself but in
this case you have the overhead of the updates to the record and there
may be some locks not released if the backend or the application crashes
before resetting the flag.
It could also be done with a begin/end block but in this case the entire
table would be locked by postgres and it is not acceptable to do this for
a long period because other transactions would block completely.
Note that this type of locks are handled cooperatively by the application
and do not interfere with the normal locks used by postgres. So an user
could still modify an user-locked record if he wanted to ignore the lock.
#ifndef USER_LOCKS_H
#define USER_LOCKS_H
int user_lock(unsigned int id1, unsigned int id2, LOCKT lockt);
int user_unlock(unsigned int id1, unsigned int id2, LOCKT lockt);
int user_write_lock(unsigned int id1, unsigned int id2);
int user_write_unlock(unsigned int id1, unsigned int id2);
int user_write_lock_oid(Oid oid);
int user_write_unlock_oid(Oid oid);
int user_unlock_all(void);
#endif
-- SQL code to define the user locks functions
-- select user_lock(group,id,type);
--
create function user_lock(int4,int4,int4) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_unlock(group,id,type);
--
create function user_unlock(int4,int4,int4) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_write_lock(group,id);
--
create function user_write_lock(int4,int4) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_write_unlock(group,id);
--
create function user_write_unlock(int4,int4) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_write_lock(group,oid);
--
create function user_write_lock(int4,oid) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_write_unlock(group,oid);
--
create function user_write_unlock(int4,oid) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_write_lock_oid(oid);
--
create function user_write_lock_oid(oid) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_write_unlock_oid(oid);
--
create function user_write_unlock_oid(oid) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_write_lock_oid(int4);
--
create function user_write_lock_oid(int4) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_write_unlock_oid(int4);
--
create function user_write_unlock_oid(int4) returns int4
as 'MODULE_PATHNAME'
language 'c';
-- select user_unlock_all();
--
create function user_unlock_all() returns int4
as 'MODULE_PATHNAME'
language 'c';
-- end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment