I have data in global in this format:
^kza("mltab","TAB","Dta",1,1) = 3341
^kza("mltab","TAB","Dta",1,2) = "First Name"
^kza("mltab","TAB","Dta",1,3) = "type1"
^kza("mltab","TAB","Dta",1,4) = 7400.11
^kza("mltab","TAB","Dta",2,1) = 3614
^kza("mltab","TAB","Dta",2,2) = "Second Name"
^kza("mltab","TAB","Dta",2,3) = "type2"
^kza("mltab","TAB","Dta",2,4) = 7600.11
My object class looks like this:
Class Kza.Employees Extends %Persistent [ StorageStrategy = EmpStorage ]
{
Property num As %Integer; //unique identifier
Property id As %Integer;
Property num As %Integer;
Property name As %String;
Property type As %String;
Property pay As %Double;
Index NewIndex1 On id [ IdKey, PrimaryKey, Unique ];
<Storage name="EmpStorage">
<ExtentSize>100000</ExtentSize>
<SequenceNumber>8</SequenceNumber>
<SQLMap name="MasterMap">
<ConditionalWithHostVars></ConditionalWithHostVars>
<Data name="num">
<Node>1</Node>
</Data>
<Data name="name">
<Node>2</Node>
</Data>
<Data name="pay">
<Node>4</Node>
</Data>
<Data name="type">
<Node>3</Node>
</Data>
<Global>^kza</Global>
<RowIdSpec name="1">
<Expression>{L1}</Expression>
<Field>id</Field>
</RowIdSpec>
<Subscript name="1">
<Expression>"mltab"</Expression>
</Subscript>
<Subscript name="2">
<Expression>"TAB"</Expression>
</Subscript>
<Subscript name="3">
<Expression>"Dta"</Expression>
</Subscript>
<Subscript name="4">
<Expression>{id}</Expression>
</Subscript>
<Type>data</Type>
</SQLMap>
<StreamLocation>^Kza.EmployeesS</StreamLocation>
<Type>%CacheSQLStorage</Type>
</Storage>
}
The problem is that if I do
insert into Kza.Employees(id, num, name, pay, type) VALUES(132, 3214, 'Name Second', 89000, 'type5')
the result is:
^kza("mltab","TAB","Dta",1) = ""
^kza("mltab","TAB","Dta",1,1) = 3214
^kza("mltab","TAB","Dta",1,2) = "Name Second"
^kza("mltab","TAB","Dta",1,3) = 'type 5'
^kza("mltab","TAB","Dta",1,4) = 89000
But i need to don't have saved the first line, so HOW TO ELIMINATE SAVE THIS NODE:
^kza("mltab","TAB","Dta",1) = ""
Try making the num, name, type, or pay property required (if there are any that cannot be null).
Caché defines the ^kza("mltab","TAB","Dta",1) node because if the other 4 field are all null, the existence of the ^kza("mltab","TAB","Dta",1) node defines the existence of the row.
In other words, if num, name, type, or pay are all null and ^kza("mltab","TAB","Dta",1) is not defined, the row would not be defined.
Related
I am using the Terraform provider mrparkers/keycloak to attempt to assign Keycloak groups a list of users.
The snippet below creates realms, groups, and users correctly, but I am stumped on the final line for calling a list of users which should belong to the group being looped through.
Anything to point me in the right direction would be hugely appreciated. :)
vars
variable "realms" {
description = "realms"
type = set(string)
default = ["mrpc"]
}
variable "mrpc-groups" {
type = map(object({
name = string
realm = string
members = set(string)
}))
default = {
"0" = {
realm = "mrpc"
name = "mrpc-admins"
members = ["hellfire", "hellfire2"]
},
"1" = {
realm = "mrpc"
name = "mrpc-mods"
members = ["hellfire2"]
}
}
}
variable "mrpc-users" {
type = map(object({
username = string
email = string
first_name = string
last_name = string
realm = string
}))
default = {
"0" = {
realm = "mrpc"
username = "hellfire"
email = "bla#bla.bla"
first_name = "hell"
last_name = "fire"
}
"1" = {
realm = "mrpc"
username = "hellfire2"
email = "bla2#bla.bla"
first_name = "hell2"
last_name = "fire2"
}
}
}
resources
resource "keycloak_realm" "realm" {
for_each = var.realms
realm = each.value
}
resource "keycloak_group" "group" {
for_each = var.mrpc-groups
realm_id = each.value["realm"]
name = each.value["name"]
depends_on = [keycloak_realm.realm]
}
resource "keycloak_user" "user" {
for_each = var.mrpc-users
realm_id = each.value["realm"]
username = each.value["username"]
email = each.value["email"]
first_name = each.value["first_name"]
last_name = each.value["last_name"]
}
resource "keycloak_group_memberships" "group_members" {
for_each = keycloak_group.group
realm_id = each.value["realm_id"]
group_id = each.value["name"]
members = [ "hellfire2" ]
# i want this to be var.mrpc-groups.*.members (* used incorrectly here i think)
# if
# var.mrpc-groups.*.name == each.value["name"]
#
# so that the correct member list in the vars is used when the matching group is being looped over
# any method to get the final outcome is good :)
}
We can use the distinct and flatten functions in conjunction with a for expression within a list constructor to solve this:
distinct(flatten([for key, attrs in var.mrpc_groups : attrs.members]))
As tested locally, this will return the following for your values exactly as requested in the question indicated by var.mrpc-groups.*.members:
members = [
"hellfire",
"hellfire2",
]
The for expression iterates through the variable mrpc_groups map and returns the list(string) value assigned to the members key within each group's key value pairs. The lambda/closure scope variables are simply key and attrs because the context is unclear to me, so I was unsure what a more descriptive name would be.
The returned structure would be a list where each element would be the list assigned to the members key (i.e. [["hellfire", "hellfire2"], ["hellfire2"]]). We use flatten to flatten the list of lists into a single list comprised of the elements of each nested list.
There would still be duplicates in this flattened list, and therefore we use the distinct function to return a list comprised of only unique elements.
For the additional question about assigning the members associated with the group at the current iteration, we can simply implement the following:
members = flatten([for key, attrs in var.mrpc_groups : attrs.members if attrs.name == each.value["name"]])
This will similarly iterate through the map variable of var.mrpc_groups, and construct a list of the members list filtered to only the group matching the name of the current group iterated through keycloak_group.group. We then flatten again because it is also a nested list similar to the first question and answer.
Note that for this additional question it would be easier for you in general and for this answer if you restructured the variable keys to be the name of the group instead of as a nested key value pair.
DXL, ibm DOORS
Looping through module, then through every object history, I am trying to assign to "_Owner" attribute the author from obj history who modified last time "_ReqStatus" attribute, if "_Owner" is empty.
This is what I tried:
Module m = current
History h
HistoryType ht
Object o
string attributName
string authorName
string newOwner
noError()
for o in entire m do {
for h in o do
{
string owner = ""
attributName=""
attributName = h.attrName
authorName=""
owner = o."_Owner"
if isDeleted(o) then continue
if((attributName=="_ReqStatus"))
{
authorName=h.author
//print authorName
//print "\n"
if(null owner)
{
print identifier(o)
print "\n"
newOwner = authorName
print newOwner"\n"
owner = newOwner
print owner
break
}
}
}
}
ErrMess = lastError()
The output for print owner is as expected. My problem is that in-DOORS attribute is not filling at all with any value.
_Owner attribute type is Ennumeration and attribute properties look like this, but I don't know if it matters:
"_Owner" attr properties
When you assign string owner = o."_Owner", the variable owner is not a handle to the object attribute itself, but the content of o's "_Owner" attribute is copied to owner. So, in your later recalculation owner = newOwner, you only change that variable and not the attribute. Try o."_Owner" = newOwner instead.
I have a following space schema in Tarantool
box.schema.space.create('customer')
format = {
{name = 'id', type = 'string'},
{name = 'last_name', type = 'string'},
}
box.space.customer:format(format)
box.space.customer:create_index('id', {parts = {{field = 'id', is_nullable = false}}})
box.space.customer:replace({'1', 'Ivanov'})
I want to add the new field first_name to this space. What's the way I can do that?
Before answering a question we should discuss a format method.
format - it’s a space option that allows you to get value from a tuple by name. Actually tuple is a “list” of values and any field could be accessed by field number.
What’s next? E.g. you have a simple schema.
box.schema.space.create('customer')
box.space.customer:format(format)
box.space.customer:create_index('id', {parts = {{field = 'id', is_nullable = false}}})
box.space.customer:replace({'1', 'Ivanov'})
Let’s define new format that has the third field - first_name.
new_format = {
{name = 'id', type = 'string'},
{name = 'last_name', type = 'string'},
{name = 'first_name', type = 'string'},
}
box.space.customer:format(new_format) -- error: our tuple have only two fields
tarantool> box.space.customer:format(new_format)
- --
- error: Tuple field 3 required by space format is missing
...
There are two ways to fix it.
Add new field to the end of tuple with default value.
box.space.customer:update({'1'}, {{'=', 3, 'Ivan'}})
box.space.customer:format(new_format) -- OK
Define new field as nullable
new_format = {
{name = 'id', type = 'string'},
{name = 'last_name', type = 'string'},
{name = 'first_name', type = 'string', is_nullable = true},
}
box.space.customer:format(new_format) -- OK: absence of the third value is acceptable
You can choose one described above variant.
I’ve just add some notes:
You can’t add some value through the absence field (e.g. you have first and second values you should add the third before adding the fourth)
tarantool> box.tuple.new({'1', 'Ivanov'}):update({{'=', 4, 'value'}})
- --
- error: Field 4 was not found in the tuple
...
tarantool> box.tuple.new({'1', 'Ivanov'}):update({{'=', 3, box.NULL}, {'=', 4, 'value'}})
- --
- ['1', 'Ivanov', null, 'value']
...
Filling in the field with the default value can be quite a long operation if you have a lot of data. Please be careful when apply any migratons.
Read more about format method in the documentation.
I am wondering if I can pass variable to be evaluated as String inside gstring evaluation.
simplest example will be some thing like
def var ='person.lName'
def value = "${var}"
println(value)
I am looking to get output the value of lastName in the person instance. As a last resort I can use reflection, but wondering there should be some thing simpler in groovy, that I am not aware of.
Can you try:
def var = Eval.me( 'new Date()' )
In place of the first line in your example.
The Eval class is documented here
edit
I am guessing (from your updated question) that you have a person variable, and then people are passing in a String like person.lName , and you want to return the lName property of that class?
Can you try something like this using GroovyShell?
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
GroovyShell shell = new GroovyShell( binding )
def result = shell.evaluate( commandString )
Or this, using direct string parsing and property access
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
// Split the command string into a list based on '.', and inject starting with null
def result = commandString.split( /\./ ).inject( null ) { curr, prop ->
// if curr is null, then return the property from the binding
// Otherwise try to get the given property from the curr object
curr?."$prop" ?: binding[ prop ]
}
Say that you want to create a Lua table, and all its keys are valid lua identifiers. Then you can use the key=value syntax:
local niceTable = { I=1, like=1, this=1, syntax=1 }
If however your strings are not "identifiable", then you have to use the ['key']=value syntax:
local operators = { ['*']="Why", ['+']="the", ['/']="brackets", ['?']='?' }
I'm a bit baffled about this. What are those brackets doing there? What do they mean?
They identify the contained string as a key in the resulting table. The first form, you could consider as equal to
local niceTable = {}
niceTable.I = 1;
niceTable.like = 1;
The second form is equal to
local operators = {}
operators['*'] = "Why";
operators['+'] = "The";
The difference is purely syntactic sugar, except where the first one uses identifiers, so it has to follow the identifier rules, such as doesn't start with a number and interpret-time constant, and the second form uses any old string, so it can be determined at runtime, for example, and a string that's not a legal identifier. However, the result is fundamentally the same. The need for the brackets is easily explained.
local var = 5;
local table = {
var = 5;
};
-- table.var = 5;
Here, var is the identifier, not the variable.
local table = {
[var] = 5;
};
-- table[5] = 5;
Here, var is the variable, not the identifier.
The normal syntax for indexing a table is t[val]. For string keys only, Lua provides an alternate syntax, where t.foo is exactly equivalent to t["foo"]. This is purely a syntactical convenience, so-called 'syntax sugar'. It doesn't add functionality, it just gives you a less cluttered syntax for using strings as named fields.
There are a lot of strings keys this won't work for:
t["hello_world"] => t.hello_world -- works
t["hello world"] => t.hello world -- oops, space in the string
t["5 * 3"] => t.5 * 3 -- oops
t['[10]'] => t.[10] -- oops
Basically it only works if the string key would be a valid identifier.
Again, tables are indexed via [], and in most cases you need to use them:
t = {
-- [key] = value
[10] = "ten", -- number key, string value
["print function"] = print, -- string key, function value
["sub table"] = {}, -- string key, table value
[print] = 111, -- function key, number value
["foo"] = 123, -- string key, number value
}
Only if you're using a string key which would work as a valid identifier (no spaces, contains only word characters, numbers, or underlines, and doesn't begin with a number) can you use the shortcut syntax. For the table above, that would be only 'foo':
t = {
-- [key] = value
[10] = "ten", -- number key, string value
["print function"] = print, -- string key, function value
["sub table"] = {}, -- string key, table value
[print] = 111, -- function key, number value
foo = 123, -- string key, number value
}