Create aggregate in postgres using C language - postgresql

I want to create user-defined aggregate in postgres by C language. Here are my code.
sql code:
CREATE FUNCTION res_tras_crimes_c(state_c, int64)
RETURNS state_c
AS 'MODULE_PATHNAME', 'res_tras_crimes'
LANGUAGE C
IMMUTABLE
PARALLEL SAFE;
CREATE FUNCTION finalize_trans_crimes_c(state_c)
RETURNS ArrayType
AS 'MODULE_PATHNAME'
LANGUAGE C
IMMUTABLE
PARALLEL SAFE;
CREATE AGGREGATE reservoir_sampling_c(int64)
(
sfunc = res_tras_crimes,
stype = state_c,
FINALFUNC = finalize_trans_crimes,
);
For C code:
typedef struct state_c
{
int64 *reservoir;
int32 poscnt;
int32 reservoir_size;
} state_c;
PG_FUNCTION_INFO_V1(res_tras);
Datum
res_tras(PG_FUNCTION_ARGS)
{
//state_c *d1 = malloc(sizeof(state_c));
//struct state_c st;
// st = (state_c *)PG_GETARG_DATUM(0);
struct state_c *st = (state_c *)PG_GETARG_POINTER(0);
int64 newsample = PG_GETARG_INT64(1);
if(st == NULL) {
int64 r[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int64 *a = r;
st->poscnt = 1;
st->reservoir_size = 100;
st->reservoir = a;
}
if(st->poscnt <= st->reservoir_size){
int32 p = st->poscnt;
*(st->reservoir+p-1) = newsample;
st->poscnt ++;
}else{
int32 pos = rand() % st->poscnt ; //0 - postcnt -1
if(pos < st->reservoir_size){
*(st->reservoir+pos) = newsample;
}
st->poscnt ++;
}
PG_RETURN_POINTER(st);
}
PG_FUNCTION_INFO_V1(finalize_trans);
Datum
finalize_trans_(PG_FUNCTION_ARGS)
{
struct state_c *st = (state_c *) PG_GETARG_POINTER(0);
PG_RETURN_ARRAYTYPE_P(st->reservoir);
}
Can i pass my struct pointer in transition function? and I want to return ARRAYTYPE in final function. I don't konw how to deal with it. Colud you help me? Thanks!
I want to know how to deal the arraytype and struct in c language in postgres

I didn't run your code, but that should work in principle. You would use internal as STYPE in CREATE AGGREGATE and as first argument to the state transition function.
You can look at the PostgreSQL source for an example: array_agg uses internal as STYPE, and you can look at the definition of the state transition function array_agg_array_transfn in src/backend/utils/adt/array_userfuncs.c.

Related

How to make an array with all the enum values in system verilog?

I have an enum :
typedef enum { enum_A = 1, enum_B = -5, enum_C = 10 } enum_t;
I want to make an array that has all the values of the enum:
enum_t enum_array[ enum_t.num() ] = { enum_A, enum_B, enum_C };
The problem is how to initialize the array without litrally writing the enum values?
I tried foreach & simple for - nothing works...
enum_t enum_array[ enum_t.num() ] = enum_array_alues();
function enum_t [enum_t.num() -1:0] enum_array_alues();
automatic enum_t enum_val = enum_t.first();
foreach ( enum_array_alues[val] ) begin
enum_array_alues[val] = enum_val;
enum_val = enum_val.next(); << .next() on a non-contiguous enum type not supported
end
endfunction;
Is there a solution to this problem?
System Verilog could be ugly :-). This is one of these cases. You cannot use enum methods on typedefs, you need an enum variable to do so. Also, function return type cannot be directly defined as an array, you need a typedef for it.
Also, different compilers have their own minds as well. The following works with vcs, mentor and aldera. However, it failed with cadence.
typedef enum { enum_A = 1, enum_B = -5, enum_C = 10, hello } enum_t;
enum_t enum_var;
typedef enum_t enum_a[enum_var.num()];
enum_a enum_array;
initial begin
enum_array = enum_array_values();
end
function automatic enum_a enum_array_values();
enum_t enum_val = enum_val.first;
foreach(enum_array_values[i]) begin
enum_array_values[i] = enum_val;
enum_val = enum_val.next();
end
endfunction
So, my suggestion is to use dynamic arrays. It seems that this method below works with all compilers in eda playground. It is less ugly but requires a bit more code.
module top;
// Code your design here
typedef enum { enum_A = 1, enum_B = -5, enum_C = 10 } enum_t;
typedef enum_t enum_array_t[];
enum_t enum_array[];
initial begin
enum_array = enum_array_values();
foreach (enum_array[i])
$display(enum_array[i].name);
end
function automatic enum_array_t enum_array_values();
int i = 0;
enum_t enum_val;
enum_val = enum_val.first();
forever begin
enum_array_values = new [i+1] (enum_array_values);
enum_array_values[i] = enum_val;
if (enum_val == enum_val.last)
break;
i++;
enum_val = enum_val.next();
end
endfunction
endmodule
A do-while loop works well for iterating over enums
module top;
typedef enum { enum_A = 1, enum_B = -5, enum_C = 10 } enum_t;
typedef enum_t enum_list_t[$];
enum_list_t enum_array = enum_array_values();
function automatic enum_list_t enum_array_values;
enum_t tmp = tmp.first;
do begin
enum_array_values.push_back(tmp);
tmp = tmp.next;
end
while (tmp != tmp.first);
endfunction
initial $display("%p", enum_array);
endmodule

What does this function actually do?

i am currently trying to do some self learning in swift just for my own interest. in the course i bought it says that we should create a function similar to this one in order to solve my problem. but I'm blankly staring trying to figure out what this function actually does?
func unknown() -> () -> Int {
var x = 0
let z: () -> Int = {
x += 1
return x
}
return z
}
It is a function that returns another function which will return an integer that will be increased everytime you call it:
let afunc = unknown()
let value1 = afunc() // 1
let value2 = afunc() // 2
let value3 = afunc() // 3
The interesting part of this is the return type. () -> Int is a function that returns an Int, which means that unknown returns a function rather than something simple, like a number.
z is then a variable of that same type and is assigned a function definition to be returned.
If you assign the result of unknown to a variable, you can then invoke the returned function.
This implementation of a high order function is an interesting way of defining generators. An infinite sequence-like class would've achieve the same thing, but with more verbosity:
class MySequence {
private var x = 0
func unknown() -> Int {
x += 1
return x
}
}
var seq = MySequence()
let unknown = seq.unknown
print(unknown()) // 1
print(unknown()) // 2
print(unknown()) // 3
// ... and so on
The main difference between the class and the anonymous closure is the storage for x: the closure captures in due to using the variables within its body, while the class declares explicit storage for the property.
Some fancy stuff can result by using high order functions, like a generator for the Fibonacci numbers:
func fibonnaciSequence() -> () -> Int? {
var a = 0, b = 1
return { let c = a; a += b; b = c; return c }
}
let fibo = fibonnaciSequence()
while let f = fibo() {
// this will print forever
// actually not forever, it will stop at some point due to += overflowing
print(f)
}

Randomization of a parameterized class inside a class not working

I am trying to use a parameterized class inside another class which I have to randomize.
typedef enum logic [1:0] {
TWO_LEGS,
FOUR_LEGS,
SIX_LEGS,
EIGHT_LEGS
} leg_e;
typedef enum logic [2:0] {
HUMAN,
DOGS,
CAT,
ELEPHANT,
FLY,
COCKROACH,
SPIDER
} animal_e;
class parameterized_class #( type enum_type);
static int initial_allocation;
static enum_type list[$];
rand int unsigned ptr;
constraint ptr_c {
ptr < list.size();
}
function new();
enum_type my_enum;
if(initial_allocation == 0) begin
initial_allocation = 1;
for(int unsigned i = 0; i < my_enum.num(); i++)
repeat($urandom_range(1,10)) list.push_back(my_enum);
end
endfunction
endclass
class random_class;
rand parameterized_class#(leg_e) leg_select;
rand parameterized_class#(animal_e) animal_select;
rand leg_e leg_q[$];
rand animal_e animal_q[$];
constraint leg_animal_c {
leg_select.list[leg_select.ptr] == TWO_LEGS -> animal_select.list[animal_select.ptr] inside {HUMAN};
leg_select.list[leg_select.ptr] == FOUR_LEGS -> animal_select.list[animal_select.ptr] inside {DOGS, CAT, ELEPHANT};
leg_select.list[leg_select.ptr] == SIX_LEGS -> animal_select.list[animal_select.ptr] inside {FLY, COCKROACH};
leg_select.list[leg_select.ptr] == EIGHT_LEGS -> animal_select.list[animal_select.ptr] inside {SPIDER};
}
constraint q_c {
leg_q.size() dist {[0:5] := 50, [6:10] := 50};
animal_q.size() == leg_q.size();
foreach(leg_q[i]) {
leg_q[i] == leg_select.list[leg_select.ptr];
animal_q[i] == animal_select.list[animal_select.ptr];
}
}
function new();
leg_select = new;
animal_select = new;
endfunction
endclass
module tb;
initial begin
random_class rnd = new;
repeat (10) begin
rnd.randomize();
$display("Animals in queue = %p", rnd.animal_q);
$display("Legs in queue = %p", rnd.leg_q);
end
end
endmodule
I am getting an error:
The solver will not solve for array 'animal_select.list' indexed by random
variable 'animal_select.ptr'.
Please try to use a state variable, constant, or loop variable for array
index.
What modification I havee to make to get a result like:
{DOGS, CAT, HUMAN, ELEPHANT}
{FOUR_LEGS, FOUR_LEGS, TWO_LEGS, FOUR_LEGS, }
I think you might be over-thinking your problem. I think this code produces the result you are hoping for:
typedef enum logic [1:0] {
TWO_LEGS,
FOUR_LEGS,
SIX_LEGS,
EIGHT_LEGS
} leg_e;
typedef enum logic [2:0] {
HUMAN,
DOGS,
CAT,
ELEPHANT,
FLY,
COCKROACH,
SPIDER
} animal_e;
class random_class;
rand leg_e leg_q[$];
rand animal_e animal_q[$];
constraint leg_animal_c {
foreach (leg_q[i]) leg_q[i] == TWO_LEGS -> animal_q[i] inside {HUMAN};
foreach (leg_q[i]) leg_q[i] == FOUR_LEGS -> animal_q[i] inside {DOGS, CAT, ELEPHANT};
foreach (leg_q[i]) leg_q[i] == SIX_LEGS -> animal_q[i] inside {FLY, COCKROACH};
foreach (leg_q[i]) leg_q[i] == EIGHT_LEGS -> animal_q[i] inside {SPIDER};
}
constraint q_c {
leg_q.size() dist {[0:5] := 50, [6:10] := 50};
animal_q.size() == leg_q.size();
}
endclass
module tb;
initial begin
random_class rnd = new;
repeat (10) begin
rnd.randomize();
$display("Animals in queue = %p", rnd.animal_q);
$display("Legs in queue = %p", rnd.leg_q);
end
end
endmodule
https://www.edaplayground.com/x/3rh8
I put a $diplay() debug in your code
foreach (list[i]) $display(list[i].name());
and see that your initialization is wrong. You always push the first enum into the list.
I changed your code to
for(int unsigned i = 0; i < my_enum.num(); i++) begin
/*repeat($urandom_range(1,10))*/ list.push_back(my_enum);
my_enum = my_enum.next();
end
and it does work. EDA code here.
And why do all the queues have identical elements, it is because of your constraints
foreach(leg_q[i]) {
leg_q[i] == leg_select.list[leg_select.ptr];
animal_q[i] == animal_select.list[animal_select.ptr];
}

Sort array of dictionary

I need to sort an array of dictionaries in the following ways. The array contains dictionaries with the following format:
[{
fecha = "09:54:51";
"nombre_vendedor" = Rafaela;
numero = 501;
precio = 52;
"punto_venta" = Base;
tipo = Gold;
}
{
fecha = "09:54:51";
"nombre_vendedor" = Miguel;
numero = 400;
precio = 40;
"punto_venta" = Base;
tipo = Gold;
}]
All I have to sort by the "numero" key.
Anyone have any idea how to do this. I've been trying to sortedArrayUsingComparator method but I get no result.
Thank You.
You can use the sort method the following way:
myArray.sort { $0["numero"]! < $1["numero"]! }
Try this:
var descriptor: NSSortDescriptor = NSSortDescriptor(key: "numero", ascending: true)
var sortedResults: NSArray = results.sortedArrayUsingDescriptors([descriptor])
You can use the sort method, passing a closure which, given 2 array elements, determines which one comes first.
A safe way to achieve that is:
array.sort { (lhs, rhs) in
if let n2 = rhs["numero"] as? Int {
if let n1 = lhs["numero"] as? Int {
return n1 < n2
}
return false
}
return true
}
As you may notice, I usually prefer to use safe code vs. unsafe - that's the reason why the code checks for existance of the numero key on both dictionaries.
The above implementation sorts the array in place, placing items not having the numero key at the end - if you want the opposite case, just switch the last 2 return statements

Unable to type cast <AnonymousType#1> to <WindowsFormsApplication1.Attributes> [ C#3.0 ]

I have
List<Attributes> la = new List<Attributes>();
la = (from t in result
let t1 = t.AttributeCollection
from t2 in t1
where t2.AttributeCode.Equals(attributeType)
let t3 = t2.TimeSeriesData
from k in t3.ToList()
where k.Key.Equals(startDate) && k.Key.Equals(endDate)
select new
{
AttributeCode = attributeType,
TimeSeriesData = fn(k.Key, k.Value.ToString())
}).ToList<Attributes>();
I am getting the error:
'System.Collections.Generic.IEnumerable<AnonymousType#1>' does not contain a definition for 'ToList' and the best extension method overload 'System.Linq.Enumerable.ToList<TSource>(System.Collections.Generic.IEnumerable<TSource>)' has some invalid arguments
I understood tye error meaning but how to type cast it. I have used var and then iterating over it got the result. But without that any other way by which I can do it?
Using C# 3.0
Thanks
may be:
List<Attributes> la = new List<Attributes>();
la = (from t in result
let t1 = t.AttributeCollection
from t2 in t1
where t2.AttributeCode.Equals(attributeType)
let t3 = t2.TimeSeriesData
from k in t3.ToList()
where k.Key.Equals(startDate) && k.Key.Equals(endDate)
select new Attributes()
{
AttributeCode = attributeType,
TimeSeriesData = fn(k.Key, k.Value.ToString())
}).ToList<Attributes>();
you are constructing anonymous type with same fields as Attributes. But they are different types and can't be cast to each other.
Basically save it to an anonymous list type, and then call a conversion function.
public void TestMethod(){
List<Attributes> la = new List<Attributes>();
var annonyType = (from t in result
let t1 = t.AttributeCollection
from t2 in t1
where t2.AttributeCode.Equals(attributeType)
let t3 = t2.TimeSeriesData
from k in t3.ToList()
where k.Key.Equals(startDate) && k.Key.Equals(endDate)
select new
{
AttributeCode = attributeType,
TimeSeriesData = fn(k.Key, k.Value.ToString())
});
la = annonyType.ConvertAll(x=>ConvertToAttribute(x.AttributeCode , x.TimeSeriesData ));
....
//End test method
}
//... (where TimeSeriesDataType = type returned by fn(
public Attributes ConvertToAttribute(string AttributeType, TimeSeriesDataType d){
return new Attribute()....;
}