PostgreSQL: Fetch a sequence nextval from a C function - postgresql

I wrote the following to fetch the next value in a sequence. It works perfectly:
static int64 _get_md_key_next_serial()
{
int ret = SPI_execute("SELECT nextval('md_key_seq')", true, 1);
if (ret <= 0)
return (int64)ret;
if (SPI_processed)
{
SPITupleTable *tuptable = SPI_tuptable;
bool fieldNull;
Datum datum = SPI_getbinval(tuptable->vals[0], tuptable->tupdesc, 1, &fieldNull);
if (!fieldNull)
return DatumGetInt64(datum);
}
return NULL_ZERO;
}
However, surely there is a function call I can make without having to go through SPI?

Unfortunately nextval_internal is not exported, but you could try to call nextval_oid. I did not test this code, so you'll probably have to debug it:
#include "fmgr.h"
#include "commands/sequence.h"
static int64 nextval(Oid sequenceID, FunctionCallInfo fcinfo)
{
FunctionCallInfoData locfcinfo;
InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 1,
InvalidOid, NULL, NULL);
locfcinfo.arg[0] = ObjectIdGetDatum(sequenceID);
locfcinfo.argnull[0] = false;
return DatumGetInt64(nextval_oid(&locfcinfo));
}
Pass the Oid of the sequence and the fcinfo from your own SQL function.

Related

How to change value of module_param parameter in the device driver?

I wrote a simple program for taking a value through command line into my driver. I used module_param() for this and gave permission argument, i.e third arg of module_param(), as S_IWUSR.
This I guess would allow user to modify the value of that parameter once driver is loaded in the kernel. I tried to modify the value of that parameter by:
echo 1 > /sys/module/ghost/parameters/num
But this shows me Permission denied error every time I try to do this, even when I execute the command with sudo. I also tried changing permission in module_param() to 0770 but still was not able to change the parameter value. Is there a way to change the value of parameter passed while inserting the driver ? Why does the above command shows permission denied, even if I run as sudo ?
After the answer of #Ian Abott I am to change the value of the parameter. Now I tried to define a callback function to notify me any changes in the value of that parameter while my driver is loaded. Here is the code
#include"headers.h"
#include"declarations.h"
static int my_set(const char *val, const struct kernel_param *kp)
{
int n = 0, ret;
ret = kstrtoint(val,10,&n); // Kernel function to convert string to integer
if (ret !=0 || n > 10) {
return -EINVAL;
}
printk(KERN_ALERT "my-set function running\n");
return param_set_int(val,kp);
}
static const struct kernel_param_ops param_ops = {
.set = my_set,
.get = param_get_int,
};
module_param(num,int,0600);
static char *name = "hello";
module_param(name,charp,0770);
static int __init init_func(void)
{
int i;
module_param_cb(callBack, &param_ops, &num, 0770);
printk(KERN_INFO "Value of num is %d\n",num);
for( i=0; i<num; i++)
{
printk(KERN_INFO "%s\n", name);
}
return 0;
}
static void __exit exit_func(void)
{
printk(KERN_INFO "Value of num is %d\n",num);
printk(KERN_ALERT "Module removed successfully\n");
}
module_init(init_func);
module_exit(exit_func);
But it doesn't seem to work because my_set function never runs, even if I change the value. My doubt is
1) Is this correct way to implement callback function for the parameter?
2) What is significance of first argument to the function module_param_cb?

How to hash aggregated results in postgresql incrementally without concatenating everything first

I want to calculate a hash (sha256) of as set of results, I know how to do to it:
SELECT digest( string_agg(id_,':'), 'sha256') from mytable order by id_;
It works but it first concatenates all records and finally calculate the hash. I want it to be incremental to avoid possible memory problems with large datasets (millions of rows), something like:
SELECT digest_agg(id_, ':', 'sha256') from mytable order by id_;
Ensuring that the hash is calculated incrementally row by row on the way.
Ok, I have finally coded a c extension for this. I post it here in case it would be useful for someone.
/* ------- OS Includes ------------ */
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
/* ----- PostgreSQL Includes -------*/
#include "postgres.h"
#include "fmgr.h"
#include "funcapi.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
PG_MODULE_MAGIC;
typedef struct sha256_state
{
SHA256_CTX* sha256;
bool has_data;
} SHA256_STATE;
/* --------- Prototypes ---------- */
void _PG_init(void);
void _PG_fini(void);
Datum dv_sha256_agg_sfunc(PG_FUNCTION_ARGS);
Datum dv_sha256_agg_final(PG_FUNCTION_ARGS);
SHA256_STATE* sha256_init(void);
void sha256_update(SHA256_STATE* state, char* string, int32 string_size);
void sha256_final(SHA256_STATE* state, char outputBuffer[65]);
/* ------ Version1 convention ---- */
PG_FUNCTION_INFO_V1(dv_sha256_agg_sfunc);
PG_FUNCTION_INFO_V1(dv_sha256_agg_final);
// -----------------------------------------------------------
// Implementations
// -----------------------------------------------------------
void _PG_init(void) {/* Do nothing */}
void _PG_fini(void) {/* Do nothing */}
Datum dv_sha256_agg_sfunc(PG_FUNCTION_ARGS) {
SHA256_STATE* state;
bool is_first = PG_ARGISNULL(0);
text* string;
int32 string_size;
char* data;
char SEP[] = {'\n'}; // Hardcoded separator (can be improved)
if (is_first) {
// First iteration: Create the state
state = sha256_init();
}
else {
// Next iterations: Restore the state
state = (SHA256_STATE*) PG_GETARG_POINTER(0);
}
if (PG_ARGISNULL(1)) {
PG_RETURN_POINTER(state);
}
// Get current chunk
string = PG_GETARG_TEXT_PP(1);
string_size = VARSIZE_ANY_EXHDR(string);
data = VARDATA_ANY(string);
// Add separator
if (state->has_data) {
sha256_update(state, SEP, 1);
}
// Update state
sha256_update(state, data, string_size);
state->has_data = true;
// Updated state
PG_RETURN_POINTER(state);
}
Datum dv_sha256_agg_final(PG_FUNCTION_ARGS) {
SHA256_STATE* state;
char out[65];
text* hash = (text*) palloc(65 + VARHDRSZ);
if (PG_ARGISNULL(0)) {
PG_RETURN_NULL();
}
else {
state = (SHA256_STATE*) PG_GETARG_POINTER(0);
sha256_final(state, out);
SET_VARSIZE(hash, 65 + VARHDRSZ);
memcpy(VARDATA(hash), out, 65);
PG_RETURN_TEXT_P(hash);
}
}
SHA256_STATE* sha256_init() {
SHA256_STATE* state = (SHA256_STATE*) palloc(sizeof(SHA256_STATE));
state->sha256 = (SHA256_CTX*) palloc(sizeof(SHA256_CTX));
SHA256_Init(state->sha256);
state->has_data = false;
return state;
}
void sha256_update(SHA256_STATE* state, char* string, int32 string_size) {
SHA256_Update(state->sha256, string, string_size);
}
void sha256_final(SHA256_STATE* state, char outputBuffer[65]) {
int i;
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_Final(hash, state->sha256);
for(i = 0; i < SHA256_DIGEST_LENGTH; i++) {
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
}
outputBuffer[64] = 0;
}
The aggregate definition:
CREATE FUNCTION dv_sha256_agg_sfunc(state internal, input text)
RETURNS internal AS 'MODULE_PATHNAME',
'dv_sha256_agg_sfunc'
LANGUAGE C VOLATILE;
CREATE FUNCTION dv_sha256_agg_final(state internal)
RETURNS text AS 'MODULE_PATHNAME',
'dv_sha256_agg_final'
LANGUAGE C VOLATILE;
CREATE AGGREGATE dv_sha256_agg(input text) (
SFUNC = dv_sha256_agg_sfunc,
STYPE = internal,
FINALFUNC = dv_sha256_agg_final
);
Test:
select
dv_sha256_agg(id_::text),
encode(digest(string_agg(id_::text,E'\n'),'sha256'),'hex')
from
generate_series(1,100) id_(id_);
Result
dv_sha256_agg | encode
------------------------------------------------------------------+------------------------------------------------------------------
4187fe63fa78d8b4333e6ffc9122e0273ddf90251ced32e1e5b398639c193c87 | 4187fe63fa78d8b4333e6ffc9122e0273ddf90251ced32e1e5b398639c193c87
(1 row)
Notes:
Separator is hardcoded as \n
Null values are ignored
In PostgreSQL you can create your own aggregate function using CREATE AGGREGATE. That way you can write digest_agg yourself.
The challenge is to come up with a good state transition function (SFUNC) that combines the aggregate of the previous values with the next value.
It is possible to implement such a function yourself. Without touching any C code, I wrote one up in plperlu. It is memory efficient, but horrifically slow. If you want it fast, you will probably need to code it up in C. I suspect that the getstate and putstate functions have had no performance consideration whatsoever, as they weren't intended to be used in loops like this.
CREATE LANGUAGE plperlu;
CREATE FUNCTION public.sha256_final(state text) RETURNS bytea
LANGUAGE plperlu
AS $_X$
use Digest::SHA;
my $sha=Digest::SHA->new(256);
if (defined $_[0]) { $sha->putstate($_[0])};
$sha->add($_[1]);
return encode_bytea($sha->digest());
$_X$;
CREATE FUNCTION public.sha256_sfunc(state text, input text) RETURNS text
LANGUAGE plperlu
AS $_X$
use Digest::SHA;
my $sha=Digest::SHA->new(256);
if (defined $_[0]) { $sha->putstate($_[0])};
$sha->add($_[1]);
return $sha->getstate();
$_X$;
CREATE AGGREGATE public.perl_sha256(input text) (
SFUNC = public.sha256_sfunc,
STYPE = text,
FINALFUNC = public.sha256_final
);
--The built in sha256 on pre-aggregate gives the same answer...
select sha256(string_agg::bytea) from (select string_agg(id_::text,'') from generate_series(1,101) id_(id_)) foobar;
--- ...as my own streaming aggregate.
select perl_sha256(id_::text) from generate_series(1,101) id_(id_);
Of course you have to make sure rows are delivered in the correct order. And I didn't implement the ':' delimiter from string_agg, just ''.

S-function Level 2 C Simulink (R2006b) , Getting string from parameter

I don't find the way to get the string specified in the dialog box of an S-function (C, level 2) block and save it in a variable, inside the .c file corresponding to the block.
Through *mxGetPr(ssGetSFcnParam(S, 0)) I can only get the first position value in the string.
The parameter entered in the dialog block what it is related to the ssGetSFcnParam(S, 0) is '123'.
In the mask editor of the block the type is 'edit'.
#define S_FUNCTION_NAME ver_file_data
#define S_FUNCTION_LEVEL 2
#define NPARAMS 14
#define DVC_TYPE(S) ssGetSFcnParam(S, 0)
static void mdlInitializeSizes(SimStruct *S){
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
ssSetNumSFcnParams(S, NPARAMS); /* Number of expected parameters */
ssSetSFcnParamTunable(S, 0, 0);
ssSetSFcnParamTunable(S, 1, 0);
#if defined(MATLAB_MEX_FILE) if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
mdlCheckParameters(S);
if (ssGetErrorStatus(S) != NULL) {
return;
} } else {
return; }
#endif
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, NUM_INPUTS)) return;
if (!ssSetNumOutputPorts(S, NUM_OUTPUTS)) return;
/* Output Port 0 */
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortDataType(S, 0, SS_UINT8);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
}
static void mdlInitializeSampleTimes(SimStruct *S){
ssSetSampleTime(S, 0, -1);
ssSetOffsetTime(S, 0, 0.0);
}
static void mdlOutputs(SimStruct *S, int_T tid){
ssPrintf("DVC_IND_NO = %x\n",*mxGetPr(DVC_IND_NO(S)));
}
mdlRTW (SimStruct *S){
}
Before getting anything through the outputport, I would like to be able to print with ssPrintf("DVC_IND_NO = %x\n",*mxGetPr(DVC_IND_NO(S))); the 123.
Thank you, best regards.
mxGetPr returns a pointer to double, so makes no sense if the parameter is a char array. And in using *mxGetPr you are saying that you want the value that is pointed to (i.e. the first element, if it is a multi-element double array), which is why you are only getting the first value.
If the input is expected to be a string (i.e. array of char) then you should be using mxArrayToString to access it.
Either way, you should definitely be using helper functions like mxIsChar and mxIsDouble to check the data type before using the appropriate function to access the data.
Add the following at the top
#define DVC_IND_NO(S) = ssGetSFcnParam(S,0)
and the follwoing in your mdlOutputs
char* str;
int i = 0;
str = mxArrayToString(DVC_IND_NO(S));
ssPrintf("DVC_IND_NO = ");
while (str[i]!='\0')
{
ssPrintf("%c",str[i]);
i++;
}

order of execution of forked processes

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/sem.h>
#include<sys/ipc.h>
int sem_id;
void update_file(int number)
{
struct sembuf sem_op;
FILE* file;
printf("Inside Update Process\n");
/* wait on the semaphore, unless it's value is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = -1; /* <-- Amount by which the value of the semaphore is to be decreased */
sem_op.sem_flg = 0;
semop(sem_id, &sem_op, 1);
/* we "locked" the semaphore, and are assured exclusive access to file. */
/* manipulate the file in some way. for example, write a number into it. */
file = fopen("file.txt", "a+");
if (file) {
fprintf(file, " \n%d\n", number);
fclose(file);
}
/* finally, signal the semaphore - increase its value by one. */
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop( sem_id, &sem_op, 1);
}
void write_file(char* contents)
{
printf("Inside Write Process\n");
struct sembuf sem_op;
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop( sem_id, &sem_op, 1);
FILE *file = fopen("file.txt","w");
if(file)
{
fprintf(file,contents);
fclose(file);
}
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop( sem_id, &sem_op, 1);
}
int main()
{
//key_t key = ftok("file.txt",'E');
sem_id = semget( IPC_PRIVATE, 1, 0600 | IPC_CREAT);
/*here 100 is any arbit number to be assigned as the key of the
semaphore,1 is the number of semaphores in the semaphore set, */
if(sem_id == -1)
{
perror("main : semget");
exit(1);
}
int rc = semctl( sem_id, 0, SETVAL, 1);
pid_t u = fork();
if(u == 0)
{
update_file(100);
exit(0);
}
else
{
wait();
}
pid_t w = fork();
if(w == 0)
{
write_file("Hello!!");
exit(0);
}
else
{
wait();
}
}
If I run the above code as a c code, the write_file() function is called after the update_file () function
Whereas if I run the same code as a c++ code, the order of execution is reverse... why is it so??
Just some suggestions, but it looks to me like it could be caused by a combination of things:
The wait() call is supposed to take a pointer argument (that can
be NULL). Compiler should have caught this, but you must be picking
up another definition somewhere that permits your syntax. You are
also missing an include for sys/wait.h. This might be why the
compiler isn't complaining as I'd expect it to.
Depending on your machine/OS configuration the fork'd process may
not get to run until after the parent yields. Assuming the "wait()"
you are calling isn't working the way we would be expecting, it is
possible for the parent to execute completely before the children
get to run.
Unfortunately, I wasn't able to duplicate the same temporal behavior. However, when I generated assembly files for each of the two cases (C & C++), I noticed that the C++ version is missing the "wait" system call, but the C version is as I would expect. To me, this suggests that somewhere in the C++ headers this special version without an argument is being #defined out of the code. This difference could be the reason behind the behavior you are seeing.
In a nutshell... add the #include, and change your wait calls to "wait(0)"

Is it possible to implement the Haversine formula in Objective-C and call it from SQLite?

As I understand, SQLite doesn't have the math functions to properly implement the Haversine formula in straight SQL. I'm thinking this should be possible using an external function, with the implementation being in C.
The goal is to have a SQLite database in an iPhone, and to be able to sort by the distance to the user's current location. I've searched, but I can't find an example of any examples of this being done. I think the difficult parts would be getting the function declarations correct. The end result I'm hoping for, is to be able to execute a SQL statement like:
SELECT * FROM LOCATION loc ORDER BY distance(loc.lat, loc.long, ?, ?)
I have a C Haversine formula. The function definition is as follows:
float distance( float nLat1, float nLon1, float nLat2, float nLon2 );
Does anyone know if this is possible and/or have some example code to start from?
I just had good luck with this post: http://www.thismuchiknow.co.uk/?p=71
This demonstrates a sqlite function that takes in one string parameter and returns a string result.
In your case you would need a function that reads four floats and returns a float but the principle is the same (you would replace sqlite3_value_text with sqlite3_value_double and sqlite3_result_text with sqlite3_result_double):
#include <stdlib.h>
#include <sqlite3.h>
#include <stdio.h>
void haver(sqlite3_context* ctx,int cnt,sqlite3_value** val)
{
printf("In SQLite haver implementation, called for value: %s\n", sqlite3_value_text(*val));
char * resultOfCall = "Result of function call"; //this would call the distance function
sqlite3_result_text(ctx, resultOfCall, strlen(resultOfCall), NULL);
}
int cback (void* udata,int ncol,char** value,char** colname)
{
int i=0;
for(;i<ncol;i++)
printf("Result column: %s value: %s \n", colname[i], value[i]);
return 0;
}
int main()
{
sqlite3 * handle;
int res = sqlite3_open("./test.sql", &handle);
res = sqlite3_create_function(handle, "haver", 1, SQLITE_UTF8, NULL, &haver, NULL, NULL);
char * errmsg = NULL;
res = sqlite3_exec(handle, "select haver(w) from t", &cback, NULL, &errmsg);
printf("sqlite3_exec result: %d %s\n", res, errmsg != NULL ? errmsg : "No error");
sqlite3_close(handle);
}