Update value of other column on update of this column - intersystems-cache

i have question, how to do something like a trigger in Intersystems Cache.
Situation:
for example i have table X with properties(columns)
valueA,valueB
i Want to update valueB when valueA changed by UPDATE. I have define global variable ^VALUEBGENER and use to increment it $SEQ function,
My Idea was:
Class User.X Extends %Persistent [ ClassType = persistent, DdlAllowed, Final, Owner = {_SYSTEM}, ProcedureBlock, SqlRowIdPrivate, SqlTableName = X]
{
Property VALUEA As %Library.String(MAXLEN = 8) [ Required,SqlColumnumber = 1];
Property VALUEB As %Library.Integer(MAXVAL = 2147483647, MINVAL = -2147483648) [ Required,SqlColumnNumber = 1,SqlComputed,SqlColumnumber = 2, SqlComputeCode = {SET {valueB}=$SEQ(^VALUEBGENER)}, SqlComputeOnChange = %%UPDATE];
}
but it's doesnt work, when i change valuea but it works when i change valueb so, any idea?
P.S. Sorry for bad english

Can do it by adding a trigger, and SqlCompute
Class User.X Extends %Persistent [ ClassType = persistent, DdlAllowed, Final, Owner = {_SYSTEM}, ProcedureBlock, SqlRowIdPrivate, SqlTableName = X]
{
Property VALUEA As %Library.String(MAXLEN = 8) [ Required, SqlComputed,SqlColumnumber = 1];
Property VALUEB As %Library.Integer(MAXVAL = 2147483647, MINVAL = -2147483648) [ Required,InitialExpression=0,SqlColumnNumber = 2, SqlComputeCode = {SET {*}=$SEQ(^VALUEB)}, SqlComputeOnChange = %%UPDATE ];
Trigger[Event=Update]{
NEW valuebx
new rowid
set rowid={ID}
SET valuebx= 0
// {fieldname*C} evaluates to 1 if the field has been changed and 0
if({VALUEA*C}=1){
// we trigger sql computeCode and inc of global variable by update
//and it doesnt matter what is here in :valuebx
&sql(update x set valueb=:valuebx WHERE ROWID=:rowid)
}
}
}

Related

AssemblyScript - Linear Nested Class Layout

I'm working on a linear data layout where components are alongside each other in memory. Things were going ok until I realized I don't have a way for making offsetof and changetype calls when dealing with nested classes.
For instance, this works as intended:
class Vec2{
x:u8
y:u8
}
const size = offsetof<Vec2>() // 2 -- ok
const ptr = heap.alloc(size)
changeType<Vec2>(ptr).x = 7 // memory = [7,0] -- ok
Naturally this approach fails when nesting classes
class Player{
position:Vec2
health:u8
}
const size = offsetof<Player>() //5 -- want 3, position is a pointer
const ptr = heap.alloc(size)
changeType<Player>(ptr).position.x = 7 //[0,0,0,0,0] -- want [7,0,0], instead accidentally changed pointer 0
The goal is for the memory layout to look like this:
| Player 1 | Player 2 | ...
| x y z h | x y z h |
Ideally I'd love to be able to create 'value-type' fields, or if this isnt a thing, are there alternative approaches?
I'm hoping to avoid extensive boilerplate whenever writing a new component, ie manual size calculation and doing a changetype for each field at its offset etc.
In case anybody is interested I'll post my current solution here. The implementation is a little messy but is certainly automatable using custom scripts or compiler transforms.
Goal: Create a linear proxy for the following class so that the main function behaves as expected:
class Foo {
position: Vec2
health: u8
}
export function main(): Info {
const ptr = heap.alloc(FooProxy.size)
const foo = changetype<FooProxy>(ptr)
foo.health = 3
foo.position.x = 9
foo.position.y = 10
}
Solution: calculate offsets and alignments for each field.
class TypeMetadataBase{
get align():u32{return 0}
get offset():u32{return 0}
}
class TypeMetadata<T> extends TypeMetadataBase{
get align():u32{return alignof<T>()}
get offset():u32{return offsetof<T>()}
constructor(){
super()
if(this.offset == 0)
throw new Error('offset shouldnt be zero, for primitive types use PrimitiveMetadata')
}
};
class PrimitiveMetadata<T> extends TypeMetadataBase{
get align():u32{return sizeof<T>()}
get offset():u32{return sizeof<T>()}
};
class LinearSchema{
metadatas:StaticArray<TypeMetadataBase>
size:u32
offsets:StaticArray<u32>
constructor(metadatas:StaticArray<TypeMetadataBase>){
let align:u32 = 0
const offsets = new StaticArray<u32>(metadatas.length)
for (let i = 0; i < metadatas.length; i++){
if(metadatas[i].align !== 0)
while(align % metadatas[i].align !== 0)
align++
offsets[i] = align
align += metadatas[i].offset
}
this.offsets = offsets
this.metadatas = metadatas
this.size = align
}
}
class Vec2 {
x: u8
y: u8
}
class FooSchema extends LinearSchema{
constructor(){
super([
new PrimitiveMetadata<u8>(),
new TypeMetadata<Vec2>(),
])
}
}
const schema = new FooSchema()
class FooProxy{
static get size():u32{return schema.size}
set health(value:u8){store<u8>(changetype<usize>(this) + schema.offsets[0],value)}
get health():u8{return load<u8>(changetype<usize>(this) + schema.offsets[0])}
get position():Vec2{return changetype<Vec2>(changetype<usize>(this) + schema.offsets[1])}
}

How to use timer.performWithDelay with a method call

I'm using a Lua class to create two objects, each of which must check where the other is to determine their movement. I'm attempting to use timer.performWithDelay to have them check every second, but for some reason when I try to do this, the line
o.moveCheckTimer = timer.performWithDelay(1000, o:moveCheck, 0)
in the class constructor throws an error stating that "Function arguments are expected near ','".
I have attempted to use an anonymous function like this:
o.moveCheckTimer = timer.performWithDelay(1000, function() o:moveCheck() end, 0)
but that causes the timer of both objects to only call the function for the most recent object that was created and not for itself (also very confusing behavior, and if anyone knows why this happens I would love to learn why).
I have dug through the API and info on method calls thoroughly, but I can't seem to find anything that uses them both together, and I feel like I'm missing something.
How can I use the method call as the listener for this timer?
Here is the full constructor:
Melee = {}
Melee.__index = Melee
function Melee:new(id, name, lane, side)
local o = {}
setmetatable(o, Melee)
o.id = id
o.name = name
o.lane = lane
o.side = side
if name == "spearman" then
o.maxhp = 100
o.range = 1
o.damage = {10, 20}
o.imageName = "images/rebels/spearman.png"
else
error("Attempted to create melee unit with undefined name")
end
o.hp = o.maxhp
--Display self
o.image = display.newImageRect(mainGroup, "images/rebels/spearman.png", 80, 80)
o.image.x = 0
o.image.y = lanes[lane]
o.image.anchorY = 1
if side == 2 then
o.image.xScale = -1
o.image:setFillColor(0.8)
o.image.x = display.contentWidth - 100
end
--Move and attack
local destination = display.contentWidth
if side == 2 then
destination = 0
end
o.moving = 1
o.movement = transition.to(o.image, {x = destination, time = 30000+math.random(-200,200)})
o.moveCheckTimer = timer.performWithDelay(1000, o:moveCheck, 0)
--o.attackTimer = timer.performWithDelay(1000, self:attack, 0)
return o
end

Should this method be static?

I am fairly new to java and am currently debugging a program. So I have a class that has a simple method with a few calculations. Basically when I call this method from another class to use a variable (that happens to be part of an array where some of it is being calculated) I get the calculation I need. Then I call it once more in another class, it calculates again and my numbers become compromised. Is there a way to have this method take in some value, calculate and then stay put?
This is the array class. I need to instantiate this once and then have the values for the arrays be static when I call it again. Is there a way to make the method stay put while I just call the arrays?
In another class I use PlanMat pm = new PlanMat()
then something like pm.materials(fSi, fS, fO); and to call an array pm.rho0[48];
public class PlanMat {
Constants con = new Constants();
double GPa = con.GPascals;
Main m = new Main();
public int i ;
public int eos [ ];
public double rho0 [ ];
public double c [ ];
public double nn [ ];
public double Ks0 [ ];
public double Ksp [ ];
public void materials(double fSi, double fS, double fO)
{
i = 0;
eos = new int [ 51 ];
rho0 = new double [ 51 ];
c = new double [ 51 ];
nn = new double [ 51 ];
Ks0 = new double [ 51 ];
Ksp =new double [ 51 ];
double fFeS = ( ((con.M_Fe / con.M_S) + 1) * fS );
double fFeSi = ( ((con.M_Fe / con.M_Si) + 1) * fSi);
double fFeO = ( ((0.950 * con.M_Fe) + con.M_O) / (1.95 * con.M_O) * fO);
double fFe = 1.0 - fFeS - fFeSi - fFeO;
i = 48;
eos [ i ] = 1;
rho0 [ i ] = 1.0 / ( (fFe / rho0[3]) + (fFeSi / rho0[21])
+ (fFeO / rho0[22]) + (fFeS / rho0[13]) );
Ks0 [ i ] = fFe * Ks0[3] + fFeSi * Ks0[21] + fFeO * Ks0[22]
+ fFeS * Ks0[13];
Ksp [ i ] = fFe * Ks0[3] + fFeSi * Ks0[21] + fFeO * Ks0[22]
+ fFeS * Ks0[13];
c [ i ] = 0.0;
nn [ i ]= 0.0;
}
}
There are two wasys to acheive this:
First:
You should write set and get methods, call to set method to set the values and get method to get the values. You would be setting the values say in class1 you set the values and now if you want the same values in class2 to you would be calling your get method to get the values as an array and pass this array as an argument to the constructor of class2.
Second:
You can pass the whole object to the class2 constructor and use that object in that class your values will be same and data will not be compromised but for this you will have to implement the Serializable on your data class(That you are using in both.)
class a{
......
function()
{
a,b
}
}
class b{
...function(){
here u need your variable value.
call the function and store the variable value in new variable.
}
}
if u need to do same u can do
class c{
...function(){
here u need your variable value.
call the function and store the variable value in new variable.
}
}

How to search multi keywork in linq query

i have this code in homepage
CheckBox[] ch= new CheckBox[12];
ch[0] = ChkContextA;
ch[1]= ChkContextB;
ch[2]= ChkContextC;
ch[3]= ChkContextD;
ch[4]= ChkContextE;
ch[5]= ChkContextF;
ch[6]= ChkContextG;
ch[7]= ChkContextH;
ch[8]= ChkContextI;
ch[9]= ChkContextJ;
ch[10]= ChkContextK;
ch[11]= ChiContextL;
for (int i = 0; i < 11; i++)
if (ch[i].Checked) search += ch[i].Text + " ";
Response.Redirect("SearchEstate.aspx?content="+search);
and this code in SearchEstate
var content = Request.QueryString["content"];
RealEstateEntities db = new RealEstateEntities();
var query = from O in db.Owners
join E in db.Estates on O.OwnerID equals E.OwnerID
join P in db.Properties on E.PropertyID equals P.PropertyID
where P.Facilities.Contains(content)
select new
{
regdate = E.RegisterDate,
region = E.Region,
Estype = E.EstateType,
Fac = P.Facilities,
deal = P.DealType,
price = P.TotalCost,
img = E.Picture,
addrss = O.Address,
area = P.Area,
tel = P.TellNum,
bed = P.RoomNum,
park = P.ParikingNum
};
Repeater2.DataSource = query.OrderByDescending(x => x.regdate);
Repeater2.DataBind();
when user checked some checkbox "content" for example have this value:
SearchEstate.aspx?content=ContextB ContextE ContextJ
I Want search this values in Facility field in db
How can I do this? (Sorry for my bad English)
I have the feeling your are looking for something along the lines of this query:
var content = Request.QueryString["content"];
string[] contentArray = content.Split(' ');
//...
var query = //...
where P.Facilities.Any(f => contentArray.Contains(f.FacilityName))
//...
(or instead of FacilityName some other property of Facility)
But I am not sure.

Oracle 00306 error on calling procedure with parameter - array of numbers

I have a type defined in Types like this "create or replace type numbers_table is table of numbers". I have a procedure that has a parameter of this type (ids_list IN numbers_table).
On calling the procedure with Oracle Client I keep receiving the "..Wrong number or types of arguments ..." error.
I am passing this parameter like this:
OracleParameter param1 = new OracleParameter("ids_list", OracleDbType.Decimal, ParamDirection.Input);
param1.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
param1.ArrayBindSize = new int[collectioncount];
param1.ArrayBindStatus = new OracleParameterStatus[collectioncount];
param1.Size = collectioncount;
for(int i = 0; i < collectioncount; i++)
{
param1[i].ArrayBindSize = 8000;
param1[i].ArrayBindStatus = new OracleParameterStatus.Success;
}
param1.Value = collection;
Still no luck ... I have tried to change OracleDbType.Decimal to Double, Long, Int64 etc but nothing works for me.